exec garble build exec ./main cmp stderr main.stderr # TODO: why is 'obfuscatedMethod' present? ! binsubstr main$exe 'obfuscatedFunc' 'ObfuscatedFunc' binsubstr main$exe 'UnobfuscatedMethod' [short] stop # no need to verify this with -short go build exec ./main cmp stderr main.stderr -- go.mod -- module test/main go 1.22 replace big.chungus/meme => ./big.chungus/meme require big.chungus/meme v0.0.0 -- a.go -- package main // Call a function which is linknamed to another symbol. // What's special here is that we obfuscate this call before the function declaration. // If we decide not to obfuscate the name in the function declaration, // we shouldn't obfuscate the name here either. func linknameCalledInPkg() { println(obfuscatedFunc()) } -- main.go -- package main import ( _ "os/exec" "reflect" _ "strings" "unsafe" _ "big.chungus/meme" "test/main/imported" ) // A linkname to an external non-obfuscated func. //go:linkname byteIndex strings.IndexByte func byteIndex(s string, c byte) int // A linkname to an external non-obfuscated non-exported func. //go:linkname interfaceEqual os/exec.interfaceEqual func interfaceEqual(a, b any) bool // A linkname to an external obfuscated func. //go:linkname obfuscatedFunc test/main/imported.ObfuscatedFuncImpl func obfuscatedFunc() string // A linkname to an external obfuscated method. //go:linkname obfuscatedMethod test/main/imported.Receiver.obfuscatedMethod func obfuscatedMethod(imported.Receiver) string // A linkname to an external unobfuscated method. //go:linkname unobfuscatedMethod test/main/imported.Receiver.UnobfuscatedMethod func unobfuscatedMethod(imported.Receiver) string // A linkname to an external obfuscated pointer method, with an extra parameter. //go:linkname obfuscatedPointerMethod test/main/imported.(*Receiver).obfuscatedPointerMethod func obfuscatedPointerMethod(*imported.Receiver, string) string // Similar to the above, but for std, plus having to define a type. // Some libraries do abuse reflect in this way, unfortunately. type rtype struct{} //go:linkname rtype_ptrTo reflect.(*rtype).ptrTo func rtype_ptrTo(*rtype) *rtype //go:linkname rtype_NumMethod reflect.(*rtype).NumMethod func rtype_NumMethod(*rtype) int // A linkname to an entirely made up name, implemented elsewhere. //go:linkname renamedFunc madeup.newName func renamedFunc() string // A linkname to an external non-obfuscated func in another // module whose package path has a dot in it. //go:linkname tagline big.chungus/meme.chungify func tagline() string func main() { println(byteIndex("01234", '3')) println(interfaceEqual("Sephiroth", 7)) println(obfuscatedFunc()) r := imported.Receiver{Field: "field value"} println(obfuscatedMethod(r)) println(unobfuscatedMethod(r)) println(obfuscatedPointerMethod(&r, "another value")) typ := reflect.TypeOf(new(error)).Elem() type emptyInterface struct { _ *rtype ptr unsafe.Pointer } rtyp := (*rtype)(((*emptyInterface)(unsafe.Pointer(&typ))).ptr) println("rtype_ptrTo non-nil", rtype_ptrTo(rtyp) != nil) println("rtype_NumMethod", rtype_NumMethod(rtyp)) println(renamedFunc()) println(tagline()) println(imported.ByteIndex("01234", '3')) linknameCalledInPkg() } -- imported/imported.go -- package imported import ( _ "strings" _ "unsafe" ) func ObfuscatedFuncImpl() string { return "obfuscated func" } type Receiver struct{ Field string } func (r Receiver) obfuscatedMethod() string { return "obfuscated method: " + r.Field } func (r *Receiver) obfuscatedPointerMethod(extra string) string { return "obfuscated pointer method: " + r.Field + " plus " + extra } func (r Receiver) UnobfuscatedMethod() string { return "unobfuscated method: " + r.Field } //go:linkname renamedFunc madeup.newName func renamedFunc() string { return "renamed func" } // A linkname to an external non-obfuscated func. // Different from byteIndex, as we call this from an importer package. //go:linkname ByteIndex strings.IndexByte func ByteIndex(s string, c byte) int -- big.chungus/meme/go.mod -- module test/main go 1.22 -- big.chungus/meme/dante.go -- package meme func chungify() string { return "featuring Dante from the Devil May Cry series" } -- main.stderr -- 3 false obfuscated func obfuscated method: field value unobfuscated method: field value obfuscated pointer method: field value plus another value rtype_ptrTo non-nil true rtype_NumMethod 1 renamed func featuring Dante from the Devil May Cry series 3 obfuscated func