Contents

Go binary obfuscation protection

Go is awesome. Compile in one place, run everywhere, no dependencies, no hassle!

But here comes the trouble. We write a program that we want to run on someone else’s computer. However, golang’s default mechanism will leak some of our information, although not much, but also a bit embarrassing. This article combines some common methods on the Internet to summarize a set of general and simple protection measures.

Remove debug symbols

By default, the program compiled by go will output the error in which thread, file, function, and line it made when it runs in error, like this,

/2017/go-binary-obfuscate/00.png

Image credit < gt r = “7”/>

DWARF information is a treasure for small hackers, and these key information cannot be left behind. And removing these things is also very simple:

go build -ldflags "-s -w” [<your/package]

(Requires Go version greater than 1.7)

The -ldflags parameter here will eventually be passed to it at go tool link, go tool link -h is explained as follows

...
  -s    disable symbol table
  -w    disable DWARF generation

Another benefit of removing debug symbols is a significant reduction in file size (20% on average)

-rwxr-xr-x 1 tim staff 1636736 May 5 11:59 bin/hello  <- 标准编译
-rwxr-xr-x 1 tim staff 1190272 May 5 11:59 hello      <- stripped

Plus a UPX shell, you can also compress to one-fifth of the original file size! I don’t know why, the binary of the go language is particularly good!

Delete trace file information

When panic is triggered in go, the file directory in the picture above is also part of the leaked information. For example, the picture above includes the operating system (Linux) used by the little hacker, the name of the little hacker (nikos), and if you use the homebrew version of Go, it will also leak your compiler version. So of course these should be deleted!

The source of this information is the environment variables of the environment in which the compiler runs.

When the function in the image above is compiled, the environment variables are like this.

GOROOT=/opt/go
GOPATH=/home/nikos/projects/go
GOROOT_FINAL=$GOROOT

These can be changed. According to the reference materials, when compiling GO will look for our own code from $GOPATH, extract the standard library from $GOROOT, rewrite GOROOT to GOROOT_FINAL when packaging and write it to the target file as part of the trace information. The way to rewrite $GOPATH is also very simple. Create a soft link (shortcut) to the real GOPATH in an inconspicuous directory. When the compiler looks for it, it will write the directory name of the shortcut to the final file, so as to achieve our purpose of hiding ourselves.

Without further ado, add the code. Put it in your own bash_profile or .zshrc

 ACTUAL_GOPATH="~/Programming/go"
 export GOPATH='/tmp/go'
 export GOROOT_FINAL=$GOPATH
 [ ! -d $GOPATH ] && ln -s "$ACTUAL_GOPATH" "$GOPATH"
 [[ ! $PATH =~ $GOPATH ]] && export PATH=$PATH:$GOPATH/bin

Personally, I also wrote the GOROOT_FINAL as GOPATH. In fact, this string can be any value, but if it is written in the same way, the reverse personnel cannot distinguish whether the library called is written by ourselves or the standard library of the go language. Very obscene~

In this way, the generated binary file is equivalent to the Release version when compiled in other languages. Diverge it again, write a library by yourself, make the key string into an external resource and decrypt it when called. The code does not retain the plain text, and then crack it, you can only trace the human flesh function. full score!

References