burrowers / garble

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

Literal not obfuscated when injecting via -ldflags="-X ..." #717

Open leighhopcroft opened 1 year ago

leighhopcroft commented 1 year ago

What version of Garble and Go are you using?

$ garble version
mvdan.cc/garble v0.9.3

Build settings:
      -buildmode exe
       -compiler gc
     CGO_ENABLED 1
          GOARCH amd64
            GOOS linux
         GOAMD64 v1
$ go version
go version go1.20.3 linux/amd64

What environment are you running Garble on?

docker container linux/amd64 golang:1.20

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.3"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/app/go.mod"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build336972811=/tmp/go-build -gno-record-gcc-switches"

What did you do?

garble -literals build -ldflags="-X 'main.literal=THIS SHOULD BE OBFUSCATED'" -o main

I expected the resulting binary to contain an obfuscated variable due to the -literals flag, but inspecting the binary with strings includes the value "THIS SHOULD BE OBFUSCATED".

To reproduce:

// contents of main.go
package main

import "fmt"

var literal string

func main() {
    fmt.Println(literal)
}
# contents of Dockerfile
FROM golang:1.20
RUN go version

RUN go install mvdan.cc/garble@v0.9.3
RUN garble version

WORKDIR /app
COPY main.go ./
RUN go mod init garble-obfus-issue && go mod tidy

RUN go env
RUN garble -literals build -ldflags="-X 'main.literal=THIS SHOULD BE OBFUSCATED'" -o main
RUN /bin/bash -c 'if [[ $(strings main | grep "THIS SHOULD BE OBFUSCATED" | wc -l) -eq 0 ]]; then echo "OK"; else echo "main.literal NOT OBFUSCATED"; exit 1; fi'

Then run:

docker build --rm -f "Dockerfile" -t garbleobfusissue:test .

The Docker build fails, showing that the plain string was found in the binary rather than an obfuscated version.

What did you expect to see?

The Docker build should succeed, showing that the plain string was not found in the binary.

What did you see instead?

The Docker build failed, showing that the plain string was found in the binary.

mvdan commented 1 year ago

This is a TODO; see https://github.com/burrowers/garble/blob/9044b1d31cac35ebdd82e6781605807d38be781f/testdata/script/ldflags.txtar#L21.

It's not trivial because such literals are currently inserted at link time, well after garble's obfuscation at the source level has happened. To support this, we would have to stop passing the -X flags to the linker, inserting the string values ourselves - and obfuscating the literals in the process. Certainly doable, just not a few lines of code either. cc @lu4p