Correctly encode PowerShell payloads for exploits

2 min read

PowerShell has this feature where it allows you to execute base64 encoded scripts or commands. Whether this is a good idea or not, I’ll leave that up to for you to decide. But it is a neat little party trick in CTF’s when you need to pass a payload crafted on Linux over to your Windows target. Being able to encode payloads as a base64 encoded string makes it easy to deliver over the network like for example HTTP. Let’s craft a base64 encoded payload to execute

$ echo -n "echo Hacked" | base64 -w 0
ZWNobyBIYWNrZWQ=

Executing this payload in Powershell will fail and yield the following error:

C:\>pwsh -EncodedCommand ZWNobyBIYWNrZWQ=
捥潨䠠捡敫�: The term '捥潨䠠捡敫�' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

PowerShell is built with dotnet, which means that strings should be Unicode encoded. Unicode in Windows-lingo means little-endian UTF-16. But when encoding the output of echo in Linux we basically have a UTF-8 encoded string. To fix this we can use iconv to convert to UTF-16LE:

$ echo -n "echo Hacked." | iconv -t UTF-16LE | base64 -w 0
ZQBjAGgAbwAgAEgAYQBjAGsAZQBkAC4A

It’s also possible to use python, if that’s what you prefer:

from base64 import b64encode
b64encode('echo Hacked.'.encode('UTF-16LE'))

You should now be able to correctly get your payload executed in PowerShell

C:\>pwsh -EncodedCommand ZQBjAGgAbwAgAEgAYQBjAGsAZQBkAC4A
Hacked.