burrowers / garble

Obfuscate Go builds
BSD 3-Clause "New" or "Revised" License
4k stars 254 forks source link

Add support for obfuscating files embedded via //go:embed #194

Open lu4p opened 3 years ago

lu4p commented 3 years ago

Draft: https://go.googlesource.com/proposal/+/master/design/draft-embed.md Proposal: https://github.com/golang/go/issues/41191 User facing api: https://github.com/golang/go/blob/master/src/embed/embed.go Compiler support commit: https://github.com/golang/go/commit/8bde9b320e25b2d6edf96fa5e694046fea0c04c8

The compiler puts the embedded files directly into the objectfile, so we need to rewrite the generated objectfiles, to replace the embedded files with an obfuscated version.

embed.FS

Supporting embed.FS (var x embed.FS) should be relatively straightforward.

We would need to rewrite the following functions from src/embed/embed.go: func (f *file) Name() string func (f FS) lookup(name string) *file func (f *file) Info() (fs.FileInfo, error) func (f FS) readDir(dir string) []file func (f *openFile) Read(b []byte) (int, error)

We already do sth. similar in https://github.com/burrowers/garble/blob/master/runtime_strip.go.

Alternatively we could add a wrapper func WrapFS(fs embed.FS) garble.FS, which would allow us to not rewrite src/embed/embed.go and instead move the responsibility to the user.

//go:embed *.txt
var obfFS embed.FS

var fs = garble.WrapFS(obfFS)

variables

Variables are more tricky:

//go:embed version.txt
var Version string
//go:embed version.txt
var Version []byte

We would probably need to inject lambda functions into the Objectfile. On a source code level those would look similiar to this one:

//go:embed version.txt
var Version = func() string{ 
    deobfs := // do steps to deobfuscate
    return  deobfs
}

Alternatively we could export a func DecodeEmbededString(*string) function, which could then be called by the user to decode the embedded variable.

This is blocked by #124.

mvdan commented 3 years ago

I think this should be low priority, because it's fairly easy to have a pre-build step that obfuscates the files to embed before calling garble build. This is vastly different to literal obfuscation, which is hard to do unless you write a somewhat complex tool that understands and modifies Go code.

ShamariYoti commented 7 months ago

I think this should be low priority, because it's fairly easy to have a pre-build step that obfuscates the files to embed before calling garble build. This is vastly different to literal obfuscation, which is hard to do unless you write a somewhat complex tool that understands and modifies Go code.

Hi @mvdan I've just came across this to where I'd need to obfuscate files embeded via go:embed, as per your comment, do you have any examples of how this could work? I guess i'd need to de obfuscate the contents of these files when running the application to.

it's fairly easy to have a pre-build step that obfuscates the files to embed before calling garble build

lu4p commented 7 months ago

I wrote https://github.com/lu4p/embed-encrypt a while ago, if you want to use it it would need to be updated to work with a current go version. (There is a PR of someone working on it)

I still think this should be part of garble as using another pre build step is pretty cumbersome.

ShamariYoti commented 7 months ago

Thanks @lu4p, any idea when that PR will be merged?

mvdan commented 7 months ago

I'm not opposed to merging this into garble if someone else implements it. Hopefully it wouldn't add much maintainer complexity in the long term. Perhaps we could reuse some of the code used for literal obfuscation, with the caveat that source literals tend to be small, and embedded files can easily get large, e.g. images weighing megabytes.