Encoding 101

Encoding 101

in

Transfering a payload to a host isn’t always as simple as using ftp, spinning up an smbserver/webserver, or using ssh. Sometimes we have to be a bit creative because the vector of transimission might be something like a stacked query in a sqli. Whatever the case is we the ability transmit binaries as strings while protecting them from getting corrupted en route is powerful.
There are four general steps:

  1. Minifying the payload
  2. Convert Binary To a Hex String
  3. Convert Hex String To Base64
  4. Url Encode The Base64 Encoded Hex String

Minifying Payloads

Compressing the payload

It’s worthwile to try compressing the binary with upx.

upx -9 nc.exe 

Single Line Payloads For Hex Dumps

When we are converting payloads to strings its good practice to make the payload be a one line string.This means removing non printable characters such as carriage returns(0x0D), line feeds(0xA), vertical(0xB)/horizontal tabs(0x09), and anything other non essential characters. My preferred way to do this is with awk.

awk 'BEGIN{RS="\1";ORS="";getline;gsub("\t,"");gsub("\n"," ");print}'

We can remove as many characters as we need with gsubs.
Another handy thing is that we can specify characters with in hexadecimal notation.

awk 'BEGIN{RS="\1";ORS="";getline;gsub("\x09","");gsub("\n"," ");print}'

Hex Strings <==> Binary

Binary ==> Hex String

Here is an example with nc.exe.
We create a hex string of the binary on kali with:

# we want to trim the newlines otherwise we'll get cucked.
xxd -p /usr/share/windows-resources/binaries/nc.exe | tr -d \\n > nc-hex.txt

Binary <== Hex String

Next on windows we can turn in back into a binary with:

# read the textfile as single ASCII string
$hex = [System.IO.File]::ReadAllText('C:\Windows\temp\donkey.hex', [System.Text.Encoding]::ASCII)

# convert to bytes and write these as new binary file
[System.IO.File]::WriteAllBytes('C:\Windows\temp\donkey.exe', ($hex -split '(.{2})' -ne '' -replace '^', '0X'))

We can combine the two statements into the one liner below:

[System.IO.File]::WriteAllBytes('C:\Windows\temp\donkey.exe', ("$(gc 'C:\Windows\temp\donkey.hex')" -split '(.{2})' -ne '' -replace '^', '0X'))

If necessary we can specific an encoding to get-content via then -encoding parameter.

[System.IO.File]::WriteAllBytes('C:\Windows\temp\donkey.exe', ("$(gc 'C:\Windows\temp\donkey.hex' -encoding UTF8)" -split '(.{2})' -ne '' -replace '^', '0X'))

Hex Dumps On Windows

On the other hand, if we are on a windows host we can use powershell to create a hex dump of a binary in place of xxd (for exfiltrating a binary for example).

# read the binary data as byte array
[byte[]]$data = [System.IO.File]::ReadAllBytes('C:\Windows\temp\donkey.hex')

# write to new file as string of hex encoded characters
[System.IO.File]::WriteAllText('C:\Windows\temp\donkey.exe',[System.BitConverter]::ToString($data).Replace('-',''), [System.Text.Encoding]::ASCII)

Base64 Encoding Hex Strings

Windows

Powershell

Encoding

$to_encode = get-content file
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($to_encode))

Decoding

$encoded = get-content file
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encoded)) | write-output

DOS

With some limitiations we can b64 encode/decode in dos using certutil.

Encoding

certutil.exe -encode file-to-encode output-file

Decoding

certutil.exe -decode file-to-decode output-file

Linux

Encoding

base64 file | tr -d '\n'

Decoding

base64 -d file | tr -d '\n'

URL Encoding (Percent Encoding Strings)

Linux

This reads as match two characters and insert a percent character after each.

sed 's/../%&/g'

Windows

The is a bit more clear in powershell, note that the ^ in replace is regex the beginning of a match.

"$(gc 'C:\Windows\temp\donkey.hex')" -split '(.{2})' -ne '' -replace '^', '%'