Why AMSI and Script Block Logging Matter
The Antimalware Scan Interface (AMSI) is a Windows API surface that allows security products to inspect content at runtime — before scripts execute, not just at file-write time. PowerShell, VBA macros, JScript, and Windows Script Host all feed through AMSI when security products hook it. Script Block Logging (SBL) is a separate mechanism that logs the actual content of PowerShell code blocks to Event ID 4104 before they run, regardless of obfuscation applied to the source.
Together, AMSI and SBL close the obfuscation gap that allowed attackers to evade signature-based AV by encoding payloads. That is exactly why MITRE tracks their defeat as a dedicated defence evasion technique (T1562.010: Impair Defenses — Disable or Modify Tools).
Red teams, initial access brokers, and post-exploitation frameworks including Cobalt Strike, Sliver, and Havoc all include AMSI bypass modules. In many intrusions, disabling AMSI is the first action taken after obtaining a PowerShell foothold.
How AMSI Works (and Where It Can Be Broken)
AMSI operates by having security products register as AMSI providers. When a script engine (powershell.exe, wscript.exe) initialises, it loads amsi.dll into its process and calls AmsiInitialize(). Before executing any content, it calls AmsiScanBuffer() with the content. The registered provider evaluates the content and returns a result. If the result indicates malicious content, the engine raises an error and does not execute.
The critical detail: AMSI runs in-process with the script engine. This means a process with sufficient privilege can modify the AMSI machinery from within. The primary bypass categories exploit this:
1. Memory Patching (AmsiScanBuffer Patch)
The most common and historically most reliable bypass. An attacker uses reflection or P/Invoke to locate the AmsiScanBuffer function in memory and overwrites its first bytes to return a clean result unconditionally:
# Simplified illustration of the technique (not an operational payload)
$amsi = [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$field = $amsi.GetField('amsiInitFailed','NonPublic,Static')
$field.SetValue($null,$true)
Some variants patch AmsiInitialize instead, causing AMSI to fail to initialise and fall back to a permissive state.
Detection angle: The write to a non-writable memory region in amsi.dll will frequently trigger process memory modification events in EDR telemetry. The reflection call pattern (GetType('System.Management.Automation.AmsiUtils')) is the canonical string that detection rules target.
2. Forcing AmsiInitFailed
A lightweight variant sets the amsiInitFailed private field to true via reflection. PowerShell’s AMSI integration checks this field before calling into the provider; if it is true, scans are skipped. This does not require writing to executable memory but does require reflection access to internal PowerShell fields.
3. COM-Based AMSI Bypass
Some bypasses operate at the COM object level by manipulating AMSI provider registration or replacing the AMSI result interface. These are less common but more difficult to detect at the script-content level because they do not use the characteristic reflection strings.
4. Downgrading PowerShell
PowerShell version 2 does not support AMSI or Script Block Logging. Invoking powershell.exe -version 2 drops into a legacy engine where neither control applies. This is detectable and most modern environments disable PSv2, but it remains functional where the .NET 2.0 runtime is present.
Detection: powershell.exe with -version 2 or -v 2 command-line argument.
5. Obfuscation to Evade AMSI Signatures
AMSI providers ultimately rely on signatures for content they scan. Heavily obfuscated or encrypted payloads that are decrypted in memory at execution time can avoid string-based signatures. Script Block Logging captures the deobfuscated content, which is why attackers often bypass SBL alongside AMSI.
6. Script Block Logging Suppression
SBL writes to the Microsoft-Windows-PowerShell/Operational log under Event ID 4104. Attackers suppress this by:
- Setting the
EnableScriptBlockLoggingregistry value to0atHKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging - Calling
[System.Management.Automation.Logging]internals via reflection to disable the logging pipeline - Clearing the PowerShell event log directly (
Clear-EventLog -LogName "Microsoft-Windows-PowerShell/Operational")
Registry modification is detectable; reflection-based suppression is more evasive and requires behavioural detection.
Detection Strategy
Event Sources
| Source | Event ID | Content |
|---|---|---|
| Microsoft-Windows-PowerShell/Operational | 4104 | Script block content (post-deobfuscation) |
| Microsoft-Windows-PowerShell/Operational | 4105/4106 | Script block start/stop |
| Security | 4688 | Process creation (powershell.exe args) |
| Sysmon | 1 | Process creation with full command line |
| Sysmon | 10 | Process access (for memory injection detection) |
| Sysmon | 13 | Registry value modification |
Sigma Rules
Detecting the AmsiUtils reflection pattern (covers patches 1 and 2):
title: PowerShell AMSI Bypass via AmsiUtils Reflection
id: 7d8f6e3a-2b4c-4a1d-9f0e-5c7b3a2d1e8f
status: stable
description: Detects PowerShell commands accessing AmsiUtils internals via reflection, a common pattern used to disable AMSI scanning
author: SOC Analyst Hub
date: 2026-07-11
references:
- https://attack.mitre.org/techniques/T1562/010/
logsource:
product: windows
service: powershell
definition: Script block logging must be enabled (Event ID 4104)
detection:
selection:
EventID: 4104
Payload|contains:
- 'AmsiUtils'
- 'amsiInitFailed'
- 'AmsiScanBuffer'
- 'AmsiInitialize'
condition: selection
falsepositives:
- Security research and red team tooling in authorised test environments
level: high
tags:
- attack.defense_evasion
- attack.t1562.010
Detecting PowerShell version 2 downgrade:
title: PowerShell Version 2 Downgrade for AMSI Bypass
id: 3a5c9b2d-7e1f-4b8a-2c6d-9f3e5a1b4c7d
status: stable
description: Detects invocation of PowerShell with the -version 2 flag, used to bypass AMSI and Script Block Logging
author: SOC Analyst Hub
date: 2026-07-11
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\powershell.exe'
CommandLine|contains:
- '-version 2'
- '-v 2'
- '-vers 2'
- '-ve 2'
condition: selection
falsepositives:
- Legacy automation scripts requiring PowerShell 2 compatibility (should be rare in modern environments)
level: medium
tags:
- attack.defense_evasion
- attack.t1562.010
Detecting Script Block Logging registry suppression:
title: PowerShell Script Block Logging Disabled via Registry
id: 9c1e4f7a-5b3d-4c2e-8a6f-1d9b2c5e7f3a
status: stable
description: Detects modification to the PowerShell Script Block Logging registry key that could disable logging of PowerShell execution
author: SOC Analyst Hub
date: 2026-07-11
logsource:
product: windows
service: sysmon
definition: Sysmon EventID 13 (Registry value set) required
detection:
selection:
EventID: 13
TargetObject|contains: '\PowerShell\ScriptBlockLogging'
Details: 'DWORD (0x00000000)'
condition: selection
falsepositives:
- Group Policy applying a deliberate policy to disable logging (investigate and confirm intentionality)
level: high
tags:
- attack.defense_evasion
- attack.t1562.010
Detecting PowerShell event log clearing:
title: PowerShell Operational Log Cleared
id: 2f8a3c5e-9b1d-4e7f-6a2c-8d4b1e9f5c3a
status: stable
description: Detects clearing of the PowerShell operational event log, used to destroy Script Block Logging evidence
author: SOC Analyst Hub
date: 2026-07-11
logsource:
product: windows
service: system
detection:
selection:
EventID: 104
Channel: System
Provider_Name: 'Microsoft-Windows-Eventlog'
Message|contains: 'Microsoft-Windows-PowerShell/Operational'
condition: selection
falsepositives:
- Authorised log rotation or housekeeping (should be centralised and documented)
level: high
tags:
- attack.defense_evasion
- attack.t1070.001
- attack.t1562.010
KQL Queries (Microsoft Sentinel / Defender XDR)
AMSI bypass reflection attempts (DeviceEvents or SecurityEvent):
DeviceEvents
| where ActionType == "PowerShellCommandExecution"
or ActionType == "ScriptBlockLogged"
| where AdditionalFields has_any (
"AmsiUtils",
"amsiInitFailed",
"AmsiScanBuffer",
"AmsiInitialize",
"amsiContext",
"amsiSession"
)
| project Timestamp, DeviceName, InitiatingProcessAccountName,
InitiatingProcessCommandLine, AdditionalFields
| order by Timestamp desc
PowerShell v2 downgrade:
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine matches regex @"(?i)-ve?r?s?i?o?n?\s+2"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessCommandLine
| order by Timestamp desc
Script Block Logging gaps (machines where PowerShell ran but SBL was absent):
// Find machines with PowerShell process creation but no corresponding 4104 events
let ps_machines = DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where Timestamp > ago(1d)
| summarize by DeviceName, bin(Timestamp, 1h);
let sbl_machines = DeviceEvents
| where ActionType == "ScriptBlockLogged"
| where Timestamp > ago(1d)
| summarize by DeviceName, bin(Timestamp, 1h);
ps_machines
| join kind=leftanti sbl_machines on DeviceName, Timestamp
| summarize PowerShellWithoutSBL = count() by DeviceName
| where PowerShellWithoutSBL > 0
| order by PowerShellWithoutSBL desc
Registry modifications to disable security controls:
DeviceRegistryEvents
| where RegistryKey has_any (
"ScriptBlockLogging",
"ModuleLogging",
"Transcription",
"AMSI"
)
| where ActionType in ("RegistryValueSet", "RegistryValueDeleted")
| project Timestamp, DeviceName, InitiatingProcessAccountName,
RegistryKey, RegistryValueName, RegistryValueData,
InitiatingProcessCommandLine
| order by Timestamp desc
Common False Positives and Tuning
Security testing: Authorised red team engagements and penetration tests generate identical signatures. Coordinate with test schedules and consider allowlisting known test systems or accounts during engagement windows.
Security software itself: Some endpoint security products access AMSI internals during their own initialisation. Build an allowlist of known security product process paths.
PowerShell v2 for legacy automation: Some organisations have older automation that explicitly requires -version 2. Identify these, document them, and create allowlist conditions in detection rules.
Script Block Logging gaps on unmanaged endpoints: If endpoint detection is incomplete, you will see PowerShell execution with no corresponding SBL events — not because AMSI was bypassed but because the agent was not present. Treat unexplained SBL gaps as medium-priority investigation items separate from bypass detections.
Hardening Measures
Enable and enforce Script Block Logging and Module Logging via Group Policy (Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell). Set both EnableScriptBlockLogging and EnableModuleLogging to Enabled.
Disable PowerShell version 2: Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root. Confirm no legitimate applications require it before disabling.
Enforce Constrained Language Mode via AppLocker or WDAC policies. CLM restricts the PowerShell APIs available to untrusted scripts, limiting the reflection techniques AMSI bypass requires.
Forward PowerShell event logs (4103, 4104, 4105, 4106) to your SIEM. Without centralised collection, log clearing on the local endpoint destroys evidence.
Monitor AMSI provider registration via the HKLM\SOFTWARE\Microsoft\AMSI\Providers registry key. Unexpected additions or removals warrant immediate investigation.
Relation to Post-Exploitation Frameworks
Most major C2 frameworks ship with AMSI bypass capabilities:
- Cobalt Strike aggressor scripts include multiple bypass variants; the
amsi.dllpatch is the most commonly deployed - Sliver includes an
--amsiflag for its shellcode loader - Havoc has a built-in AMSI bypass in its Agent Loader
- Metasploit post modules include PowerShell-based bypasses
Detecting the bypass is often more reliable than detecting the framework payload itself, because bypass strings change less frequently than payload signatures.