PowerShell Deobfuscator

Paste an obfuscated PowerShell command or script. It is decoded layer by layer in your browser — nothing is uploaded, nothing is executed — and the result is shown as inert text, with suspicious patterns listed as leads to verify.

PowerShell obfuscation hides what a script does behind layers: a Base64 -EncodedCommand, gzip compression, character codes, string concatenation, the -f format operator and backtick escapes — each layer peeled off in turn until readable text, or the point where static unwinding stops, is left. This tool peels those layers one at a time and shows each step, so you can see what the script says without running it. If the script came from a Windows event log, the EVTX viewer reads the .evtx file and flags 4104 events; for other text logs, the log parser finds the lines that matter. The companion article how to deobfuscate PowerShell scripts explains the layers and the safe workflow in prose.

Last updated:

Up to 200 KB (.txt or .ps1). The file is read in your browser and never leaves your device. Nothing is executed.

🔒 Your script is unwound in your browser and never leaves your device. No account, no upload, no server call — and nothing here ever runs.

What happens to the script you paste

Nothing leaves your browser. The script is unwound locally by JavaScript on this page: no upload, no server call, no storage, no account. That matters because a suspicious script should never be pasted into a chat — a chat may run it, quote it, or store it — and it should never be run to see what it does. Closing the page discards it.

What a clean result does NOT prove

A clean result is not proof of safety. It means no known layer applied and no indicator matched — a dynamically built string, an encrypted payload or a runtime-only value cannot be unwound statically, and a script with no indicators can still be malicious.

An indicator is not proof of malice. Download cradles, IEX and encoded commands all have legitimate uses in administration and deployment; each match is a lead to verify in context, not a verdict.

Never run an unknown script to find out what it does. Decode it inertly, hand the result to your EDR or a sandbox, and treat the decoded text with the same suspicion as the encoded form — it is evidence, not a clean bill of health.

How the unwinding works

The tool tries eight layers in order, one per step, and repeats until no layer applies or ten layers have been peeled: -EncodedCommand extraction (Base64 to UTF-16LE, falling back to UTF-8); a bare Base64 blob; gzip or deflate decompression (the input may be Base64-wrapped first); [char] and [char[]] code sequences; string concatenation across mixed quotes and lines; the -f format operator; backtick escape removal; and a listing of ${...} and $variable placeholders, which are never resolved because their values exist only at runtime. Each step shows the text before and after, with character counts.

What the tool does NOT do: it never executes anything — the result is inert text, and the page cannot run it even by accident. It cannot unwind dynamically built strings, encrypted payloads or values that only exist at runtime, and it does not judge whether a script is safe: the indicators are pattern matches, and a script that defeats every layer is reported as "could not unwind further", never as clean.

Script Block Logging (event 4104) records the script text PowerShell actually ran, but long scripts are split into fragments of about 4 KB, each carrying a ScriptBlockId, a MessageNumber and a MessageTotal. The reassembly tab groups fragments by ScriptBlockId, orders them by MessageNumber, joins them, and flags any missing part — a group that is 2 of 3 with part 2 missing is incomplete, and the missing text cannot be guessed. The reassembled text feeds the same deobfuscator.

Frequently asked questions

Why is the result shown as inert text instead of a runnable script?

Because the point of deobfuscation is to read a suspicious script, not to run it. The decoded text may still download and execute a payload — showing it as inert text with a copy button lets you inspect it, share it with your EDR or a sandbox, and never risk a double-click.

The tool stopped with "could not unwind further". What now?

The remaining text uses a layer this tool does not know, builds its strings at runtime, or is encrypted — static unwinding has reached its limit. Do not run it to find out: hand the encoded form and the partial decode to your EDR or a sandbox, and treat the unknown layer as a reason for suspicion, not a clean result.

What do I do with the indicators?

Treat each one as a question, not an answer. A download cradle asks where the URL points and whether that host is expected; an AMSI-bypass pattern asks why the script tries to blind the scanner; an encoded command asks what the encoding was hiding. Verify each in context — in your EDR, your logs, and the machine the script came from — before deciding anything.