Decoding a PowerShell -EncodedCommand During Incident Response (the UTF-16 gotcha)
You're triaging an alert. Scheduled task, weird parent process, and a command line that looks like this: powershell.exe -nop -w hidden -enc JABjACAAPQAg... You know the drill: grab the Base64 blob, decode it, read the script. So you paste it into a decoder and get back this: $ c = " h t t p : / / ... Garbage. A space (or a null) between every single character. First instinct is that the payload is doubly-encoded or encrypted. It isn't. This is the single most common gotcha with -EncodedCommand , and once you know it, it takes ten seconds to fix. Why it looks garbled powershell.exe -enc (short for -EncodedCommand ) expects Base64 of UTF-16LE (little-endian Unicode) bytes - not UTF-8. That's mandated by PowerShell itself, not a choice the attacker made. In UTF-16LE, every ASCII character is stored as two bytes: the character followed by a 0x00 null byte. So the letter c isn't 0x63 , it's 0x63 0x00 . When you Base64-decode the blob and then read it as UTF-8, every one of those null bytes renders as a space or an invisible control character. Hence the h t t p spacing. Text: c = " UTF-16LE: 63 00 3D 00 22 00 UTF-8 view: c โ = โ " โ is Base64 of UTF-16LE, not UTF-8 - that's why naive decoding shows a space/null between every character. - Decode it right with [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($enc)) , or in Python withbase64.b64decode(enc).decode("utf-16-le") . - If the result is still binary and starts with H4sI , it's gzip inside Base64 - inflate it to reach the real script. - Decoding never executes the command, so it's safe to analyze suspicious samples locally. Seen a -enc payload with an interesting nesting trick? Share the pattern in the comments. Top comments (0)
Comments
No comments yet. Start the discussion.