burrowers / garble

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

json.unmarshel does not work #848

Closed 0sm1les closed 1 month ago

0sm1les commented 2 months ago

What version of Garble and Go are you using?

$ garble version
mvdan.cc/garble v0.12.1

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

What environment are you running Garble on?

xubuntu

go env Output
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/user/.cache/go-build'
GOENV='/home/user/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/user/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/user/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.3'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
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 -ffile-prefix-map=/tmp/go-build497023866=/tmp/go-build -gno-record-gcc-switches'

What did you do?

json unmarshal does not work, when I unmarshal into a struct and check the struct it is empty even though unmarshel returned no errors. the code works as intended when just using go build.

What did you expect to see?

a struct filled with my info.

What did you see instead?

an empty struct.

0sm1les commented 2 months ago

this issue was marked as to little info so i made a small example.

main.go

package main

import (
    "encoding/json"
    "fmt"
    "garbe-test/models"
    "os"
)

func main() {
    var test models.Garble_test
    test_string := `{
        "Field1":"test1",
        "Field2":"test2",
        "Field3":3
    }`
    err := json.Unmarshal([]byte(test_string), &test)
    if err != nil {
        fmt.Println(err)
        os.Exit(0)
    }
    fmt.Println(test)
}

models.go

package models

type Garble_test struct {
    Field1 string
    Field2 string
    Field3 int
}

running with go build

$ go build main.go && ./main
{test1 test2 3}

running with garble build -seed="random"

$ /home/user/go/bin/garble -seed="random" build
$ ./main
{  0}
0sm1les commented 2 months ago

i also tried reading from a file because maybe this string was being messed up but it was not the case. Still did not work with garble and worked with go build.

0sm1les commented 2 months ago

When i move the struct out of my models package and into the main package it works, although this is unoptimal and should be fixed

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Garble_test struct {
    Field1 string
    Field2 string
    Field3 int
}

func main() {
    var test Garble_test

    test_string := `{
            "Field1":"test1",
            "Field2":"test2",
            "Field3":3
        }`

    err := json.Unmarshal([]byte(test_string), &test)
    if err != nil {
        fmt.Println(err)
        os.Exit(0)
    }
    fmt.Println(test)
}
$ garble -seed="random" build
-seed chosen at random: wXOTnV9OlJLgRx1jWBDQEA
$ ./main 
{test1 test2 3}
0sm1les commented 2 months ago

tried "solution" in bigger program and does not work

0sm1les commented 2 months ago

because json.unmarshal is not throwing any errors, I think this problem is to do with obfuscating the struct. if you change the names of the fields and your raw json still uses the original field names it wont be able to match the values.

0sm1les commented 2 months ago

case in point, I tried to use json.marshal to serialize some directory info and this is the result, its technically working but this is not workable:

​​Gr1jjyGHsVeT: 7
​​​SlLV5YxVF: false
​​​U5vyWJ: "Lrwxrwxrwx"
​​VG4aj5: "bin"

as you can see the original field names have been replaced.

I think the solution to this is to have an option where you can choose to not obfuscate structs for this reason.

0sm1les commented 2 months ago

my temporary solution is to use maps, but i imagine this will be a common issue for a lot of software.

mvdan commented 1 month ago

@0sm1les see https://github.com/burrowers/garble?tab=readme-ov-file#caveats, in particular the second point there. This is a known limitation and not one that can be fixed without making builds extremely slow.