PowerShell Encoding with Go

2 minute read

Intro

The default character encoding used by Windows PowerShell is UTF-16LE, which is a less commonly used UTF encoding scheme which means you might come across encoding issues when trying to execute encoded commands in PowerShell. I wanted to create a quick utility Go script that encodes strings from the common UTF-8 format to UTF-16LE. I wrote this blog for those who are thinking of writing Windows exploits in Go or are commonly generating base64 PowerShell commands. With that said, let’s jump straight into some Go code!

UTF16 Encoding Strings with Go

In a new directory called “utf16”, create a Go file called main.go and then run the following command to initalize a new Go module:

go mod init utf16

We need to “go get” the unicode package from golang.org since this package isn’t part of the standard library:

go get -v golang.org/x/text/encoding/unicode

Lastly, paste the following code in main.go and run it with go run main.go (I’ll assume you have Go installed):

package main

import (
        "encoding/base64"
        "fmt"

        "golang.org/x/text/encoding/unicode"
)

func main() {
        pwshCmd := `iex "ping -n 5 localhost"`
        utf16Encoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewEncoder()
        utf16EncodedCmd, err := utf16Encoder.Bytes([]byte(pwshCmd))
        if err != nil {
                panic(err.Error())
        }

        b64Cmd := base64.StdEncoding.EncodeToString(utf16EncodedCmd)
        fmt.Println(b64Cmd)
}

The output from the program above should be:

aQBlAHgAIAAiAHAAaQBuAGcAIAAtAG4AIAA1ACAAbABvAGMAYQBsAGgAbwBzAHQAIgA=

Code Walkthrough

Here is a break down of what each significant line is doing:

  1. Creating a UTF-16LE encoder - the argument IgnoreBOM means to not incude byte order mark which is used to determine if a files content is UTF encoded
utf16Encoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewEncoder()
  1. Encoding a UTF-8 byte slice to a UTF-16LE byte slice
utf16EncodedCmd, err := utf16Encoder.Bytes([]byte(pwshCmd))
  1. Base64 encoding a UTF-16LE byte slice into a string
b64Cmd := base64.StdEncoding.EncodeToString(utf16EncodedCmd)

With our corrently encoded PowerShell command, we can now execute our command with PowerShell:

execute-powershell-base64


EOF

At this point, it would be pretty simple to turn this program into a useful CLI tool using cobra or go-arg, but I’ll leave that up to you. Happy Hacking!

If you enjoyed reading this blog and learned something, keep an eye out for more of my posts and maybe consider following me on GitHub, where I work on cybersecurity projects. And if you are feeling really generous, consider buying me a coffee!

References

comments powered by Disqus