Decoder Chains
Obfuscated data in a log or an alert is rarely one encoding. It is base64 inside URL-encoding inside hex, or UTF-16LE inside base64, or gzip inside base64. This unwraps the whole chain one layer at a time, shows every intermediate value, states the evidence for each step, and stops — saying so — when the output has stopped being a plausible decode. Everything happens in this browser tab.
Why the intermediate layers are the answer
A single-encoding decoder gives you one string and no context. When a payload is nested, the useful observation is usually not the innermost text — it is the layer at which the result stops making sense. If three layers come off cleanly and the fourth produces noise, the chain was three deep and the fourth candidate was a coincidence. If the second layer is already readable PowerShell, you can stop reading and start responding. That is why each layer is printed with its byte count and the reason it was taken, rather than collapsing the whole thing into one output box.
A candidate that decodes is not an encoding
Every hexadecimal string of even length “decodes” as hex. Most strings of letters and digits “decode” as base64. Producing output proves nothing, which is how an analyst ends up reading random bytes as if they were a finding. So each layer carries a confidence and the basis for it: the padding, the alphabet, a magic number, the printable ratio of the result. A 64-character hex string is reported as far more likely to be a SHA-256 digest than hex-encoded data and is not unwrapped automatically — you can force it, and it is then labelled as your choice rather than a detection. ROT13 is never detected at all, and that is deliberate: its output is ordinary text, so there is no evidence that could exist.
UTF-16LE, and why PowerShell matters here
powershell -EncodedCommand takes base64 of the command as UTF-16LE, not UTF-8. Decode it with an ordinary base64 tool and you get the command with a null byte between every character — readable enough to recognise, mangled enough that searching it, hashing it or pasting it into a ticket goes wrong. That two-layer chain is detected here from the zero in every other byte, and the UTF-16LE step is shown as its own layer. The same applies to gzip and zlib arriving base64-wrapped, which is normal in web logs and in SIEM fields: the inflate uses the browser's ownDecompressionStream, so there is no library to ship and nothing to upload. An engine that lacks it says so instead of quietly skipping the layer.
What this does not prove
- Decoding is not analysis. A decoded payload is still potentially malicious. This tool does not execute it, does not fetch any URL it contains, does not look anything up and does not judge whether what came out is hostile. It turns bytes into other bytes.
- A clean unwrap does not mean you found the whole chain. Encryption, a custom XOR, a non-standard alphabet or a proprietary packer all look like “binary that matches no container” here. The tool stops and says that, which is not the same as saying there is nothing underneath.
- The confidence is about the encoding, never about the content. “High confidence” means there was strong evidence the data was base64 — it says nothing about whether the result is benign, complete, or even the whole field.
- A truncated paste decodes truncated. Log pipelines cut long fields. Base64 recovers from a truncated tail quietly and the last characters of the plaintext simply disappear, with no error anywhere. If the result ends mid-word, suspect the source before the tool.
When to use the plain Base64 tool instead
If you already know what you have and it is one layer — an Authorization: Basic header, a config value, something you encoded yourself five minutes ago — use base64. It decodes as you type, with no layers, no confidence and no stop reason to read. This page is for the case where you do not know what the wrapping is or how deep it goes. For a JWT specifically, go to jwt-decoder — it splits the three parts and reads the claims, which this tool will not do for you.
What to do with the result
Pulling indicators out of the decoded text is a different job and it is scripted: ioc-extractor takes the plaintext and extracts addresses, domains, URLs and hashes, refanging defanged notation on the way in and defanging on the way out so what you paste into a ticket cannot be clicked. It works on files and whole directory trees, which this page deliberately does not. If the payload arrived in an email, phishing-email-analyzer handles the message as a whole rather than the encoded fragment. If the surrounding lines still need normalising into a timeline, that is log-parser.
For judgement rather than mechanics: malware-analysis-basics covers what a decoded script actually tells you and what it does not, soc-analyst-workflow puts the decode in the order an analyst works an alert, and the log-triage-analyst prompt insists on the benign explanation first — worth reaching for before you conclude anything from a string that merely looks alarming. Writing detection for the obfuscation pattern itself belongs in detection-engineering.
Nothing you paste is transmitted. There is no API call, no upload and no server round trip — the decoders, the heuristics and the inflate all run as JavaScript in this tab. That matters more here than on any other tool on this site, because what you paste into a decoder is frequently a real sample from a real incident, and a sample sent to a third party is a disclosure you did not intend to make. Line endings are normalised before anything is inspected, so a payload copied out of a Windows console with CRLF behaves the same as one copied from a Linux host.