PowerShell EncodedCommand Decoder

Decode powershell -enc / -EncodedCommand payloads (Base64 of UTF-16LE) into the script they run — without running anything.

Free · no sign-up · updated

Runs entirely in your browser. Nothing you enter leaves this page.

requests since opened: 0
Verify it yourself

This page is served with a security policy your browser enforces: it cannot open connections or load anything from other sites — not even to us.

  1. Open your browser’s developer tools (F12, or ⌥⌘I on Mac) → Network tab, then use the tool. No new requests appear.
  2. Or disconnect from the internet after the page loads — the tool keeps working, because it never needed the network.
  3. See the rule itself: in the Network tab, select this page’s document → Response Headers → content-security-policy contains connect-src 'none' and no 'unsafe-inline' for scripts.
  4. Press Test the lock: the page tries a harmless request and the browser blocks it (the Console shows the refusal).

tools v0.9.1 · build 0efa119

How to use
  1. Paste the whole command line from the alert or log, or just the Base64 part.
  2. Read the decoded script; suspicious calls are listed under it.
  3. If the script holds another Base64 blob, copy it in and add steps (Base64 → Inflate raw) to peel the next layer.

Steps

  1. 1.

Output

working…

What -EncodedCommand actually contains

powershell.exe accepts a whole script as a single Base64 argument. The script is first encoded as UTF-16LE — two bytes per character, with a zero byte after every ASCII letter — and only then as Base64. That is why decoding it as plain Base64 gives text with a dot or blank between every character.

PowerShell also accepts shortened parameter names, so the same thing appears as -EncodedCommand, -enc, -ec or even -e, with a leading - or /. Paste the full command line: the decoder finds the argument whichever form is used.

Peeling nested layers

Attackers rarely stop at one layer. A common second stage looks like [IO.Compression.DeflateStream] around [Convert]::FromBase64String('…'): a compressed blob inside the script. Copy the inner Base64 string into the input, then add the steps Base64 decode and Inflate (raw deflate) — .NET’s DeflateStream writes raw deflate without a zlib header. GzipStream needs Gunzip instead.

Use “Use as input” to move the output back to the input and keep going. Auto-decode tries the common layers for you and stops when nothing more decodes.

What to look for in the decoded script

Download cradles (Net.WebClient with DownloadString or DownloadFile, Invoke-WebRequest, Start-BitsTransfer), in-memory execution (IEX / Invoke-Expression, reflection Assembly.Load), hidden windows and policy bypasses (-WindowStyle Hidden, -ExecutionPolicy Bypass, -NoProfile), and attempts to disable defences such as AMSI tampering or Set-MpPreference. URLs and IP addresses in the script are your next indicators: the IOC Extractor lists and defangs them for a ticket.

Common questions

Why does a normal Base64 decoder show dots between the letters?

PowerShell encodes the script as UTF-16LE before Base64, so every ASCII character is followed by a zero byte. This decoder reads it as UTF-16LE, the way powershell.exe does.

Is it safe to decode a malicious command here?

Yes. Decoding only turns bytes into text; nothing is run. The page is also locked by your browser, so it cannot fetch anything the script points to.

Where do I find the decoded script in Windows logs?

With script block logging on, event 4104 in Microsoft-Windows-PowerShell/Operational already records the decoded script. Process creation events (4688 with command lines, or Sysmon event 1) show the encoded form.

Known limitations
  • Decodes and lists suspicious calls; it does not deobfuscate string concatenation, -f format tricks or tick marks.
  • Nothing is executed. The decoded script is shown as text only.
  • The page has no network access, so it cannot look up URLs or hashes found in the script.
  • Browser extensions can read any page — use a private window for sensitive data. How the lock works