Skip to content

Decoding PowerShell -EncodedCommand and Obfuscation

How -EncodedCommand and common PowerShell obfuscation work — base64/UTF-16LE, gzip/deflate, char codes, concatenation, the format operator and backticks — and how to decode them safely.

Published on 3 min read

TL;DR. -EncodedCommand is Base64 of UTF-16LE text. Beyond that, attackers layer gzip/deflate, [char] codes, string concatenation, the -f format operator and backtick escaping. All of these are reversible with pure text transformations that never run the code. The PowerShell Parser unwraps them layer by layer and shows the result as inert text; paste anything into its de-obfuscation view.

-EncodedCommand

powershell -EncodedCommand <base64> (also -enc, -e) takes the command as Base64 of the UTF-16LE bytes of the text (Microsoft: about_PowerShell.exe). To decode: Base64-decode the argument, then interpret the bytes as UTF-16LE. A tell-tale sign is the alternating A padding you see in the Base64 (VwByAGkAdABlA...), which is the high byte of each ASCII character being zero.

Layered obfuscation

Real samples nest encodings. The common ones, all reversible as text:

  • Compression: [Convert]::FromBase64String(...) fed to a GzipStream or DeflateStream, then IEX. Decode the Base64, then inflate the gzip/deflate stream.
  • Char codes: [char]73+[char]69+[char]88 or [char[]](73,69,88)-join'' — convert each number to its character.
  • Concatenation: 'IE'+'X' — join adjacent string literals.
  • Format operator: ("{1}{0}" -f 'X','IE') — reorder by the numeric placeholders.
  • Backticks: IEX — a backtick inside a word is an escape with no effect; drop it.

The parser applies each of these and shows every intermediate layer, so you can see exactly how a one-liner was built. See encoded command, download cradle and Invoke-Expression.

Decode safely, never run

Decoding is the opposite of execution: it is Base64, UTF-16LE, inflation and string edits — none of which invoke PowerShell. That is why an in-browser tool can safely reveal a payload that you would never run. The parser marks findings such as AMSI bypasses, download cradles and logging tampering in the decoded text, and extracts any URLs and IPs as inert strings.

Where you meet each form

Script block logging (4104) usually stores the decoded block, but the command line in 400/800 events, PSReadLine history and transcripts keeps the encoded form — so decode it there. Analyze a whole collection in your browser.

FAQ

What encoding does -EncodedCommand use?

The argument is Base64 of the command text encoded as UTF-16LE (little-endian Unicode). Decode the Base64, then read the bytes as UTF-16LE to recover the script.

Is it safe to decode a malicious command?

Decoding is a pure text transformation — Base64, UTF-16LE, gzip/deflate inflation, string manipulation. It never runs the command. Reading the decoded text is safe; running it is not.

Does script block logging already show the decoded script?

Often yes: 4104 records the block after de-obfuscation. But the command line in 400/800 events, PSReadLine history and transcripts shows the encoded form, so you still need to decode it there.

Related articles

Step-by-step: open PowerShell .evtx logs, PSReadLine history and transcripts in a free in-browser viewer, reassemble script blocks, decode encoded commands and export CSV or JSON.
How PowerShell transcripts are structured, what the header records, how command timestamps work with -IncludeInvocationHeader, and how to investigate them.
What the PSReadLine history file records, where it lives, why it has no timestamps, and how to use it — and its limits — in an investigation.