EventPeeker

PowerShell Encoded Command & Obfuscation Detection — AMSI Bypass, Downgrade Attacks

Attackers obfuscate PowerShell to evade signature-based detection — encoding commands in Base64, splitting strings to break keyword matching, patching AMSI to silence antivirus, and downgrading to PowerShell v2 to bypass Script Block Logging entirely. Detecting obfuscation requires layered visibility: process creation (4688) for suspicious flags, Script Block Logging (4104) for de-obfuscated content, and the PowerShell engine lifecycle event (400) for version downgrade attacks.

Severity

High

ATT&CK Tactic

Execution

Common attacker usage

Cobalt Strike and Metasploit — both use -EncodedCommand cradles by default · Empire and PowerShell Empire — heavy reliance on Base64 and AMSI bypass · Ransomware operators (LockBit, BlackCat) — use encoded PowerShell for lateral movement and payload staging · APT groups (Lazarus, Scattered Spider, TA505) — multi-layer obfuscation with downgrade attacks · Invoke-Obfuscation — open-source tool that generates dozens of obfuscation variants from any script

Investigate immediately if

  • !Event 400 in PowerShell/Operational shows EngineVersion 2.0 — almost always a downgrade attack bypassing Script Block Logging
  • !-EncodedCommand (or -enc / -e / -ec) appears in a 4688 command line from a non-admin user or unusual parent process
  • !Event 4104 script block content contains AmsiUtils, amsiContext, AmsiScanBuffer, or amsiInitFailed
  • !Nested Base64 strings are present — double or triple encoding indicates deliberate evasion, not legitimate automation

MITRE ATT&CK

Technique

T1059.001 · PowerShell

Tactic

Execution

View on attack.mitre.org →

Security Relevance

Obfuscation is not a technique — it is a meta-technique layered on top of every other PowerShell attack. Encoded commands, AMSI bypass, and downgrade attacks are pre-execution steps that strip defenders of their primary visibility before the payload runs. When AMSI is successfully patched, Windows Defender cannot inspect the script. When PowerShell downgrades to version 2, Script Block Logging is silenced. The attacker can then run Mimikatz, download a beacon, or dump credentials with no alert generated. Detection at the obfuscation layer — before the payload executes — is therefore higher-value than detecting the payload itself.

Indicators of Malicious Use

  • -EncodedCommand / -enc / -e / -ec in Event 4688 command line — Base64-encoded UTF-16LE payload. Decode with CyberChef: From Base64 → Decode text (UTF-16LE). Any encoded command from a non-automation context is suspect.
  • PowerShell -Version 2 flag in 4688 — explicit downgrade to PSv2, which lacks Script Block Logging. Confirm via Event 400 in Microsoft-Windows-PowerShell/Operational with EngineVersion: 2.0.
  • AMSI bypass keywords in 4104 script block content: AmsiUtils, amsiContext, AmsiScanBuffer, amsiInitFailed, Bypass, UnsafeNativeMethods, GetDelegateForFunctionPointer — these are the Reflection-based AMSI patch methods.
  • String concatenation obfuscation in 4104: `'IE'+'X'`, `('IEX'[2,0,1]-join'')`, `$env:ComSpec[4,15,25]-join''` — splits offensive keywords to break signature matching.
  • Char-code assembly: `[char]73+[char]69+[char]88` builds 'IEX' from ASCII codes; `[string[]]@(...) -join ''` joins char arrays — both evade keyword-based detection.
  • Multiple nested FromBase64String calls — double or triple Base64 encoding is never seen in legitimate automation and is a strong obfuscation indicator.
  • Add-Type -TypeDefinition with P/Invoke signatures in 4104 — injects native Win32 API calls from PowerShell, used for AMSI memory patching and shellcode injection.
  • Invoke-Obfuscation output patterns — token-level obfuscation produces fragmented string joins, backtick insertion (`po`wer`shell`), and whitespace-padded operators. These all appear de-obfuscated in 4104.

Example Log Entry

# Event 400 in Microsoft-Windows-PowerShell/Operational — PowerShell v2 Downgrade
Log Name:   Microsoft-Windows-PowerShell/Operational
Source:     Microsoft-Windows-PowerShell
Event ID:   400
Level:      Information

EngineState is changed from None to Available.
Details:
  NewEngineState=Available
  PreviousEngineState=None
  SequenceNumber=15
  HostName=ConsoleHost
  EngineVersion=2.0          ← v2 has no Script Block Logging
  RunspaceId={...}
  PipelineId=
  CommandName=
  CommandType=
  ScriptName=
  CommandPath=
  CommandLine=

# Event 4104 — AMSI Bypass Attempt (de-obfuscated by PowerShell before logging)
Log Name: Microsoft-Windows-PowerShell/Operational
Event ID:  4104
Level:     Warning

Creating Scriptblock text (1 of 1):

$a=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$b=$a.GetField('amsiInitFailed','NonPublic,Static')
$b.SetValue($null,$true)

ScriptBlock ID: {d7e4a9b2-1c8f-4d3a-be56-9f012a34c567}
Path:

# Event 4688 — Encoded PowerShell from Office Process
Log Name: Security
Event ID:  4688

New Process Information:
  New Process Name:   C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  Process Command Line: powershell.exe -NoP -NonI -W Hidden -Enc JABjAGwAaQBlAG4AdA...
  Creator Process Name: C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE

Investigation Steps

  1. 1.Decode the -EncodedCommand payload first — use CyberChef with From Base64 → Decode text as UTF-16LE. If nested encoding is present, apply From Base64 multiple times. The decoded content is the actual command.
  2. 2.Check Event 4104 for the same session — even if -EncodedCommand was used, PowerShell de-obfuscates before logging in Script Block 4104. Search the same computer and time window for 4104 events to see what actually executed.
  3. 3.Look for Event 400 in Microsoft-Windows-PowerShell/Operational with EngineVersion: 2.0 — if present, the attacker deliberately downgraded to PSv2 to avoid Script Block Logging. Any 4104 events from this session are from PSv5+ — the PSv2 portion may be invisible.
  4. 4.Search 4104 content for AMSI bypass keywords: AmsiUtils, amsiContext, AmsiScanBuffer, amsiInitFailed, UnsafeNativeMethods — if found, assume the subsequent payload ran without AV inspection.
  5. 5.Check the parent process in 4688 — PowerShell from Word/Excel/Outlook (WINWORD.EXE, EXCEL.EXE) or wscript.exe/mshta.exe is a phishing macro. From SYSTEM without a known automation parent is a persistence mechanism.
  6. 6.If AMSI bypass succeeded, look for Defender 1116/1117 events in the window after — AV may still have caught the payload on disk or via behavioral detection even after AMSI was patched.
  7. 7.Check network connections made by powershell.exe at the same time — firewall logs or 5156 (network connection allowed) events reveal C2 infrastructure used after obfuscation cleared the way.

Check your own logs for this technique — upload an EVTX file for instant detection, no account required.

Common False Positives

  • Software deployment tools (SCCM, Intune) occasionally use -EncodedCommand to safely transport complex argument strings — verify the parent process is a known management agent (CCMExec.exe, IntuneManagementExtension.exe).
  • Some enterprise monitoring agents (SolarWinds, Datto) Base64-encode machine-generated scripts for safe transport — correlate with your RMM vendor's known process names.
  • CI/CD pipelines and build systems may use encoded PowerShell for cross-platform compatibility — these should be predictable, scheduled, and run from known service accounts.
  • Developers may test -EncodedCommand interactively — parent process will be an IDE or terminal, and the decoded content will be benign.

Remediation

  • Enable PowerShell Script Block Logging (Event 4104) via GPO: Computer Configuration → Administrative Templates → Windows Components → Windows PowerShell → Turn on Script Block Logging. This de-obfuscates encoded commands automatically.
  • Remove PowerShell v2 entirely: `Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root`. Without PSv2, the downgrade attack has no target — Event 400 with EngineVersion 2.0 becomes impossible.
  • Alert on Event 400 with EngineVersion 2.0 in your SIEM — this combination is nearly always malicious. Legitimate software targeting PSv2 is extremely rare and should be approved by exception.
  • Deploy Windows Defender Application Control (WDAC) with PowerShell Constrained Language Mode — CLM blocks the Reflection-based `Add-Type` calls that most AMSI bypass methods require.
  • Enable AMSI for all PowerShell sessions via Defender policy — even when attackers attempt AMSI bypass, failed bypass attempts generate detectable Defender events (1116/1117) for the bypass code itself.
  • Consider alerting on -EncodedCommand from non-admin, non-system accounts — legitimate users almost never need to run encoded PowerShell directly.

Related Event IDs

4104PowerShell Script Block Logging — de-obfuscates encoded commands automatically before logging
4688Process creation — reveals -EncodedCommand flag, -Version 2 downgrade, and parent process chain
4103PowerShell module logging — captures pipeline execution and module imports
1116Windows Defender malware detected — may fire on bypass code even after AMSI is patched
1117Windows Defender action taken — quarantine or block events for payload caught post-execution

Related Detection Guides

Frequently Asked Questions

Why does AMSI bypass matter if I have Script Block Logging enabled?
AMSI and Script Block Logging are separate controls. AMSI inspects scripts before execution and can block them — bypassing it means Windows Defender cannot stop the script. Script Block Logging (4104) still captures the de-obfuscated content regardless of AMSI state, so you retain visibility for forensics. But AMSI bypass means the payload executed without AV intervention, while Script Block Logging is a detection-after-the-fact control. Both matter — losing AMSI degrades prevention; losing 4104 degrades detection.
Can attackers bypass Script Block Logging itself?
Yes, via three main methods: (1) PowerShell -Version 2 downgrade — PSv2 predates Script Block Logging and silences 4104 entirely; fix by removing PSv2 with Remove-WindowsFeature MicrosoftWindowsPowerShellV2Root. (2) ETW patching — attackers can patch the Event Tracing for Windows provider that feeds 4104; this is rarer and detectable via Sysmon Event 1 or 4103 gaps. (3) Direct .NET API calls — bypasses the PowerShell engine entirely, so no 4104 is generated; detect via 4688 process creation of powershell.exe or via Sysmon Event 7 (DLL load) watching for clrjit.dll.
What is the PowerShell downgrade attack and why is it so reliable?
PowerShell -Version 2 launches a PSv2 engine that lacks Script Block Logging (introduced in PSv5), AMSI integration (PSv5+), and constrained language mode enforcement. Attackers run `powershell -Version 2 -Command <payload>` and gain a logging-free execution environment. It is reliable because PSv2 components ship installed by default on Windows 10/11 and Server editions — unless explicitly removed. Event 400 in Microsoft-Windows-PowerShell/Operational with EngineVersion: 2.0 is the primary detection signal. Remove PSv2 to eliminate the attack surface entirely.
Does Constrained Language Mode (CLM) stop AMSI bypass and obfuscation?
CLM blocks the Reflection-based Add-Type and GetType methods that most AMSI bypass tools require, making the majority of public AMSI bypass scripts fail in CLM environments. However, CLM alone is insufficient — it must be enforced by WDAC or AppLocker, as PowerShell's own Execution Policy and -Version flags do not trigger CLM. Attackers running as local admin can create new runspaces or use the .NET CLR directly to escape CLM. The combination of WDAC-enforced CLM + PSv2 removal + Script Block Logging makes PowerShell obfuscation attacks significantly harder.

Analyze your Windows Event Logs

Upload an .evtx file from servers, domain controllers, or endpoints — get instant detections, MITRE mappings, and an AI-generated triage report.

Detect this technique in your logs →