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.
		
		
		
		
		
			
		
			
				
	
	
		
			150 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Markdown
		
	
			
		
		
	
	
			150 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Markdown
		
	
# garble
 | 
						|
 | 
						|
	go install mvdan.cc/garble@latest
 | 
						|
 | 
						|
Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.18 or later.
 | 
						|
 | 
						|
	garble build [build flags] [packages]
 | 
						|
 | 
						|
The tool also supports `garble test` to run tests with obfuscated code,
 | 
						|
and `garble reverse` to de-obfuscate text such as stack traces.
 | 
						|
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 de-obfuscate 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](https://go.dev/pkg/runtime/#Version) and [module](https://go.dev/pkg/runtime/debug/#ReadBuildInfo) information
 | 
						|
* Strip filenames and shuffle position information
 | 
						|
* Strip debugging information and symbol tables via `-ldflags="-w -s"`
 | 
						|
* [Obfuscate literals](#literal-obfuscation), if the `-literals` flag is given
 | 
						|
* Remove [extra information](#tiny-mode), if the `-tiny` flag is given
 | 
						|
 | 
						|
The tool obfuscates the packages matching `GOGARBLE`, a comma-separated list of
 | 
						|
glob patterns of module path prefixes, as documented in `go help private`.
 | 
						|
When `GOGARBLE` is empty, it assumes the value of `GOPRIVATE`.
 | 
						|
When `GOPRIVATE` is also empty, then `GOGARBLE` assumes the value of the current
 | 
						|
module path, to obfuscate all packages under the current module.
 | 
						|
 | 
						|
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](https://go.dev/doc/manage-install#installing-multiple)
 | 
						|
and set up `$PATH` with them. For example, for Go 1.17.1:
 | 
						|
 | 
						|
```sh
 | 
						|
$ go install golang.org/dl/go1.17.1@latest
 | 
						|
$ go1.17.1 download
 | 
						|
$ PATH=$(go1.17.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, as well as prevent extracting some more information.
 | 
						|
 | 
						|
With this flag, no panics or fatal runtime 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.
 | 
						|
 | 
						|
Note that this flag can make debugging crashes harder, as a panic will simply
 | 
						|
exit the entire program without printing a stack trace, and all source code
 | 
						|
positions are set to line 1. Similarly, `garble reverse` is generally not useful
 | 
						|
in this mode.
 | 
						|
 | 
						|
### 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 then the obfuscated build.
 | 
						|
 | 
						|
Garble obfuscates one package at a time, mirroring how Go compiles one package
 | 
						|
at a time. This allows Garble to fully support Go's build cache; incremental
 | 
						|
`garble build` calls should only re-build and re-obfuscate modified code.
 | 
						|
 | 
						|
Note that the first call to `garble build` may be comparatively slow,
 | 
						|
as it has to obfuscate each package for the first time. This is akin to clearing
 | 
						|
`GOCACHE` with `go clean -cache` and running a `go build` from scratch.
 | 
						|
 | 
						|
### Determinism and seeds
 | 
						|
 | 
						|
Just like Go, garble builds are deterministic and reproducible in nature.
 | 
						|
This has significant benefits, such as caching builds and being able to use
 | 
						|
`garble reverse` to de-obfuscate stack traces.
 | 
						|
 | 
						|
By default, garble will obfuscate each package in a unique way,
 | 
						|
which will change if its build input changes: the version of garble, the version
 | 
						|
of Go, the package's source code, or any build parameter such as GOOS or -tags.
 | 
						|
This is a reasonable default since guessing those inputs is very hard.
 | 
						|
 | 
						|
However, providing your own obfuscation seed via `-seed` brings some advantages.
 | 
						|
For example, builds sharing the same seed will produce the same obfuscation,
 | 
						|
even if any of the build parameters or versions vary.
 | 
						|
It can also make reverse-engineering harder, as an end user could guess what
 | 
						|
version of Go or garble you're using.
 | 
						|
 | 
						|
Note that extra care should be taken when using custom seeds.
 | 
						|
If a seed used to build a binary gets lost, `garble reverse` will not work.
 | 
						|
Rotating the seeds can also help against reverse-engineering in the long run,
 | 
						|
as otherwise some bits of code may be obfuscated the same way over time.
 | 
						|
 | 
						|
An alternative approach is `-seed=random`, where each build is entirely different.
 | 
						|
 | 
						|
### 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. This area is a work in progress; see
 | 
						|
  [#3](https://github.com/burrowers/garble/issues/3).
 | 
						|
 | 
						|
* Garble aims to automatically detect which Go types are used with reflection,
 | 
						|
  as obfuscating those types might break your program.
 | 
						|
  Note that Garble obfuscates [one package at a time](#speed),
 | 
						|
  so if your reflection code inspects a type from an imported package,
 | 
						|
  and your program broke, you may need to add a "hint" in the imported package:
 | 
						|
   ```go
 | 
						|
   type Message struct {
 | 
						|
       Command string
 | 
						|
       Args    string
 | 
						|
   }
 | 
						|
 | 
						|
   // Never obfuscate the Message type.
 | 
						|
   var _ = reflect.TypeOf(Message{})
 | 
						|
   ```
 | 
						|
 | 
						|
* Go declarations exported for cgo via `//export` are not obfuscated.
 | 
						|
 | 
						|
* Go plugins are not currently supported; see [#87](https://github.com/burrowers/garble/issues/87).
 | 
						|
 | 
						|
### Contributing
 | 
						|
 | 
						|
We welcome new contributors. If you would like to contribute, see
 | 
						|
[CONTRIBUTING.md](CONTRIBUTING.md) as a starting point.
 |