Base64-Encoded PowerShell Commands

powershell.exe -EncodedCommand (short form -enc; pwsh -e on PowerShell 7+) accepts a Base64 string in place of a command line. The encoding requirement is specific: Base64 of a UTF-16LE byte string — not UTF-8. Getting the charset wrong produces garbled commands, which is why the canonical recipe uses [System.Text.Encoding]::Unicode (Unicode = UTF-16LE on Windows).

Encoding and execution

$Text = '<one-line PowerShell command>'
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($Text)
$EncodedText = [Convert]::ToBase64String($Bytes)
 
powershell.exe -enc $EncodedText

Microsoft’s own documentation demonstrates exactly this pattern for dir "C:\Program Files". Decoding on Linux for analysis: echo '<b64>' | base64 -d | iconv -f UTF-16LE -t UTF-8.

Why attackers love it

  • Quoting hell disappears: nested quotes and curly braces that are painful through cmd.exe, scheduled tasks, or service binPath strings ride through cleanly inside an opaque blob.
  • Naive signature evasion: static command-line detections keyed on keywords (Invoke-Expression, DownloadString) see only Base64. This made -enc a hallmark of cradles and stagers (see invoke-webrequest-download-cradles).
  • Pairing with other flags: -enc is routinely combined with -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass — see powershell-execution-policy-bypass.

Base64 is encoding, not encryption — any analyst (or EDR) can decode it instantly, and modern defenders do: AMSI scans the decoded content at runtime, so -enc alone defeats only static string matching, not behavioral inspection. It is also the same encoding trick seen in unattend.xml password values, where <PlainText>false</PlainText> merely means “Base64’d UTF-16LE”.

Detection

  • Command lines containing -enc/-encodedcommand with long blobs (Sysmon EID 1) — high-signal analytic.
  • Decode-and-rescan pipelines in EDR/SIEM; AMSI covers in-memory execution.
  • -enc combined with -w hidden or download cradle content after decoding.

Sources