Forked from: github.com/burrowers/garble
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
Go to file
Daniel Martí 6b1a062c6f make -literals succeed on all of std
Two bugs were remaining which made the build with -literals of std fail.

First, we were ignoring too many objects in constant expressions,
including type names. This resulted in type names declared in
dependencies which were incorrectly not obfuscated in the current
package:

	# go/constant
	O1ku7TCe.go:1: undefined: alzLJ5Fd.Word
	b0ieEGVQ.go:1: undefined: alzLJ5Fd.Word
	LEpgYKdb.go:4: undefined: alzLJ5Fd.Word
	FkhHJCfm.go:1: undefined: alzLJ5Fd.Word

This edge case is easy to reproduce, so a test case is added to
literals.txt.

The second issue is trickier; in some packages like os/user, we would
get syntax errors because of comments printed out of place:

	../tip/os/user/getgrouplist_unix.go:35:130: syntax error: unexpected newline, expecting comma or )

This is a similar kind of error that we tried to fix with e2f06cce94. In
particular, it's fixed by also setting CallExpr.Rparen in withPos. We
also add many other missing Pos fields for good measure, even though
we're not sure they help just yet.

Unfortunately, all my attempts to minimize this into a reproducible
failure have failed. We can't just copy the failing file from os/user,
as it only builds on some OSs. It seems like it was the perfect mix of
cgo (which adds line directive comments) plus unlucky positioning of
literals.

For that last reason, as well as for ensuring that -literals works well
with a wide variety of software, we add a build of all of std with
-literals when not testing with -short. This is akin to what we do in
goprivate.txt, but with the -literals flag. This does make "go test"
more expensive, but also more thorough.

Fixes #285, hopefully for good this time.
3 years ago
.github all: drop support for Go 1.15.x (#265) 3 years ago
internal make -literals succeed on all of std 3 years ago
scripts update the list of runtime-related packages for 1.16 (#246) 3 years ago
testdata make -literals succeed on all of std 3 years ago
.gitattributes start testing on GitHub Actions 5 years ago
.gitignore skip literals used in constant expressions 4 years ago
AUTHORS set up an AUTHORS file to attribute copyright 4 years ago
CHANGELOG.md CHANGELOG: start drafting for v0.2.0 3 years ago
CONTRIBUTING.md CONTRIBUTING: include some basic terminology (#188) 4 years ago
LICENSE set up an AUTHORS file to attribute copyright 4 years ago
README.md README: refactor and include more useful information 3 years ago
bench_test.go rework the build benchmarks 3 years ago
go.mod all: drop support for Go 1.15.x (#265) 3 years ago
go.sum all: drop support for Go 1.15.x (#265) 3 years ago
hash.go make flags like -literals and GOPRIVATE affect hashing (#288) 3 years ago
main.go obfuscate literals as part of transformGo (#299) 3 years ago
main_test.go handle unknown flags in reverse (#290) 3 years ago
position.go set positions when using cursor.Replace 3 years ago
reverse.go make reverse error if no changes were made 3 years ago
runtime_strip.go all: drop support for Go 1.15.x (#265) 3 years ago
shared.go make flags like -literals and GOPRIVATE affect hashing (#288) 3 years ago

README.md

garble

GO111MODULE=on go get mvdan.cc/garble

Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.16 or later.

garble build [build flags] [packages]

See garble -h for up to date usage information.

Purpose

Produce a binary that works as well as a regular build, but that has as little information about the original source code as possible.

The tool is designed to be:

  • Coupled with cmd/go, to support modules and build caching
  • Deterministic and reproducible, given the same initial source code
  • Reversible given the original source, to deobfuscate panic stack traces

Mechanism

The tool wraps calls to the Go compiler and linker to transform the Go build, in order to:

  • Replace as many useful identifiers as possible with short base64 hashes
  • Replace package paths with short base64 hashes
  • Remove all build and module information
  • Strip filenames and shuffle position information
  • Strip debugging information and symbol tables via -ldflags="-w -s"
  • Obfuscate literals, if the -literals flag is given
  • Remove extra information, if the -tiny flag is given

By default, the tool obfuscates the packages under the current module. If not running in module mode, then only the main package is obfuscated. To specify what packages to obfuscate, set GOPRIVATE, documented at go help private.

Note that commands like garble build will use the go version found in your $PATH. To use different versions of Go, you can install them and set up $PATH with them. For example, for Go 1.16.1:

$ go get golang.org/dl/go1.16.1
$ go1.16.1 download
$ PATH=$(go1.16.1 env GOROOT)/bin:${PATH} garble build

Literal obfuscation

Using the -literals flag causes literal expressions such as strings to be replaced with more complex variants, resolving to the same value at run-time. This feature is opt-in, as it can cause slow-downs depending on the input code.

Literal expressions used as constants cannot be obfuscated, since they are resolved at compile time. This includes any expressions part of a const declaration.

Tiny mode

When the -tiny flag is passed, extra information is stripped from the resulting Go binary. This includes line numbers, filenames, and code in the runtime that prints panics, fatal errors, and trace/debug info. All in all this can make binaries 2-5% smaller in our testing.

Note: if -tiny is passed, no panics, fatal errors will ever be printed, but they can still be handled internally with recover as normal. In addition, the GODEBUG environmental variable will be ignored.

Speed

garble build should take about twice as long as go build, as it needs to complete two builds. The original build, to be able to load and type-check the input code, and finally the obfuscated build.

Go's build cache is fully supported; if a first garble build run is slow, a second run should be significantly faster. This should offset the cost of the double builds, as incremental builds in Go are fast.

Determinism and seeds

Just like Go, garble builds are deterministic and reproducible if the inputs remain the same: the version of Go, the version of Garble, and the input code. This has significant benefits, such as caching builds or being able to use garble reverse to de-obfuscate stack traces.

However, it also means that an input package will be obfuscated in exactly the same way if none of those inputs change. If you want two builds of your program to be entirely different, you can use -seed to provide a new seed for the entire build, which will cause a full rebuild.

If any open source packages are being obfuscated, providing a custom seed can also provide extra protection. It could be possible to guess the versions of Go and garble given how a public package was obfuscated without a seed.

Caveats

Most of these can improve with time and effort. The purpose of this section is to document the current shortcomings of this tool.

  • Exported methods are never obfuscated at the moment, since they could be required by interfaces and reflection. This area is a work in progress.

  • It can be hard for garble to know what types will be used with reflection, including JSON encoding or decoding. If your program breaks because a type's names are obfuscated when they should not be, you can add an explicit hint:

    type Message struct {
    	Command string
    	Args    string
    }
    
    // Never obfuscate the Message type.
    var _ = reflect.TypeOf(Message{})
    
  • Go plugins are not currently supported; see #87.

Contributing

We welcome new contributors. If you would like to contribute, see CONTRIBUTING.md as a starting point.