mirror of
https://github.com/burrowers/garble
synced 2026-06-06 15:24:28 +00:00
30357af923
This lets us start taking advantage of featurs from Go 1.23, particularly tracking aliases in go/types and iterators. Note that we need to add code to properly handle or skip over the new *types.Alias type which go/types produces for Go type aliases. Also note that we actually turn this mode off entirely for now, due to the bug reported at https://go.dev/issue/70394. We don't yet remove our own alias tracking code yet due to the above. We hope to be able to remove it very soon.
119 lines
3.0 KiB
Plaintext
119 lines
3.0 KiB
Plaintext
env GARBLE_EXPERIMENTAL_CONTROLFLOW=1
|
|
exec garble -literals -debugdir=debug -seed=0002deadbeef build -o=main$exe
|
|
|
|
stderr '"test/main.func1" function has no effect on the resulting binary'
|
|
|
|
exec ./main
|
|
cmp stderr main.stderr
|
|
|
|
# simple check to ensure that control flow will work. Must be a minimum of 10 goto's
|
|
grep 'goto _s2a_l10' $WORK/debug/test/main/GARBLE_controlflow.go
|
|
|
|
# obfuscated function must be removed from original file
|
|
! grep 'main\(\)' $WORK/debug/test/main/garble_main.go
|
|
# original file must contains empty function
|
|
grep '\_\(\)' $WORK/debug/test/main/garble_main.go
|
|
|
|
# obfuscated file must contains interface for unexported interface emulation
|
|
grep 'GoString\(\) string' $WORK/debug/test/main/GARBLE_controlflow.go
|
|
grep 'String\(\) string' $WORK/debug/test/main/GARBLE_controlflow.go
|
|
|
|
# control flow obfuscation should work correctly with literals obfuscation
|
|
! binsubstr main$exe 'correct name'
|
|
|
|
|
|
# check xor hardening
|
|
grep '\(\w+ \^ \d+\)' $WORK/debug/test/main/GARBLE_controlflow.go
|
|
# check delegate table hardening
|
|
grep 'func\(int\) int' $WORK/debug/test/main/GARBLE_controlflow.go
|
|
|
|
-- go.mod --
|
|
module test/main
|
|
|
|
go 1.23
|
|
-- garble_main.go --
|
|
package main
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"hash/crc32"
|
|
)
|
|
|
|
//garble:controlflow flatten_passes=0 junk_jumps=max block_splits=max
|
|
func func1() {}
|
|
|
|
//garble:controlflow flatten_passes=1 junk_jumps=max block_splits=max flatten_hardening=xor
|
|
func xorHardeningTest(i int) int {
|
|
if i == 0 {
|
|
return 1
|
|
}
|
|
return i * 2;
|
|
}
|
|
|
|
//garble:controlflow flatten_passes=1 junk_jumps=max block_splits=max flatten_hardening=delegate_table
|
|
func delegateHardeningTest(i int) int {
|
|
if i == 0 {
|
|
return 1
|
|
}
|
|
return i * 3;
|
|
}
|
|
|
|
//garble:controlflow flatten_passes=1 junk_jumps=max block_splits=max flatten_hardening=xor,delegate_table
|
|
// Trigger multiple hardening using multiple anonymous functions
|
|
func multiHardeningTest(i int) int {
|
|
notZero := func(i int) bool {
|
|
return i != 0
|
|
}
|
|
isZero := func(i int) bool {
|
|
return i == 0
|
|
}
|
|
multiply := func(i int) int {
|
|
return i * 4
|
|
}
|
|
|
|
if !notZero(i) && isZero(i) {
|
|
return 1
|
|
}
|
|
return multiply(i);
|
|
}
|
|
|
|
//garble:controlflow flatten_passes=1 junk_jumps=10 block_splits=10 trash_blocks=32
|
|
func main() {
|
|
// Reference to the unexported interface triggers creation of a new interface
|
|
// with a list of all functions of the private interface
|
|
endian := binary.LittleEndian
|
|
println(endian.String())
|
|
println(endian.GoString())
|
|
println(endian.Uint16([]byte{0, 1}))
|
|
|
|
// Switch statement should be simplified to if statements
|
|
switch endian.String() {
|
|
case "LittleEndian":
|
|
println("correct name")
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
|
|
// Indirect import "hash" package
|
|
hash := crc32.New(crc32.IEEETable)
|
|
hash.Write([]byte("1"))
|
|
hash.Write([]byte("2"))
|
|
hash.Write([]byte("3"))
|
|
|
|
println(hex.EncodeToString(hash.Sum(nil)))
|
|
|
|
println(xorHardeningTest(0))
|
|
println(delegateHardeningTest(0))
|
|
println(multiHardeningTest(0))
|
|
}
|
|
|
|
-- main.stderr --
|
|
LittleEndian
|
|
binary.LittleEndian
|
|
256
|
|
correct name
|
|
884863d2
|
|
1
|
|
1
|
|
1 |