|
|
|
env GOPRIVATE=test/main
|
|
|
|
|
|
|
|
garble -literals build
|
|
|
|
exec ./main$exe
|
|
|
|
cmp stderr main.stderr
|
|
|
|
|
|
|
|
binsubstr main$exe 'Skip this block' 'also skip this' 'skip typed const' 'skip typed var' 'skip typed var assign' 'stringTypeField strType' 'stringType lambda func return' 'testMap1 key' 'testMap2 key' 'testMap3 key' 'testMap1 value' 'testMap3 value' 'testMap1 new value' 'testMap3 new value' 'stringType func param' 'stringType return' 'skip untyped const'
|
|
|
|
! binsubstr main$exe 'garbleDecrypt' 'Lorem' 'dolor' 'first assign' 'second assign' 'First Line' 'Second Line' 'map value' 'to obfuscate' 'also obfuscate' 'stringTypeField String'
|
|
|
|
|
|
|
|
[short] stop # checking that the build is reproducible is slow
|
|
|
|
|
|
|
|
# Also check that the binary is reproducible.
|
|
|
|
cp main$exe main_old$exe
|
|
|
|
rm main$exe
|
|
|
|
garble -literals build
|
|
|
|
bincmp main$exe main_old$exe
|
|
|
|
|
|
|
|
# Check that the program works as expected without garble.
|
|
|
|
go build
|
|
|
|
exec ./main$exe
|
|
|
|
cmp stderr main.stderr
|
|
|
|
binsubstr main$exe 'Lorem' 'dolor' 'second assign' 'First Line' 'Second Line' 'map value' 'to obfuscate' 'also obfuscate' 'stringTypeField String'
|
|
|
|
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
# Generate and write random literals into a separate file.
|
|
|
|
# Some of them will be huge; assuming that we don't try to obfuscate them, the
|
|
|
|
# test should generally run in under a second. If this test hangs for over ten
|
|
|
|
# seconds, it means we're trying to obfuscate them.
|
|
|
|
generate-literals extra_literals.go
|
|
|
|
|
|
|
|
# Also check that the binary is different from previous builds.
|
|
|
|
rm main$exe
|
|
|
|
garble -literals -debugdir=.obf-src -seed=8J+Ri/Cfh6fwn4e+ build
|
|
|
|
! bincmp main$exe main_old$exe
|
|
|
|
|
|
|
|
exec ./main$exe
|
|
|
|
cmp stderr main.stderr
|
|
|
|
|
|
|
|
# Check obfuscators
|
|
|
|
|
|
|
|
# Xor obfuscator. Detect a[i] = a[i] (^|-|+) b[i]
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
grep '^\s+\w+\[\w+\] = \w+\[\w+\] [\^\-+] \w+$' .obf-src/main/extra_literals.go
|
|
|
|
|
|
|
|
# Swap obfuscator. Detect [...]byte|uint16|uint32|uint64{...}
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
grep '^\s+\w+ := \[\.{3}\](byte|uint16|uint32|uint64)\{[0-9\s,]+\}$' .obf-src/main/extra_literals.go
|
|
|
|
|
|
|
|
# Split obfuscator. Detect decryptKey ^= i * counter
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
grep '^\s+\w+ \^= \w+ \* \w+$' .obf-src/main/extra_literals.go
|
|
|
|
|
|
|
|
# XorShuffle obfuscator. Detect data = append(data, x (^|-|+) y...)
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
grep '^\s+\w+ = append\(\w+,(\s+\w+\[\d+\][\^\-+]\w+\[\d+\],?)+\)$' .obf-src/main/extra_literals.go
|
|
|
|
|
|
|
|
# XorSeed obfuscator. Detect type decFunc func(byte) decFunc
|
do not try to obfuscate huge literals (#204)
It's common for asset bundling code generators to produce huge literals,
for example in strings. Our literal obfuscators are meant for relatively
small string-like literals that a human would write, such as URLs, file
paths, and English text.
I ran some quick experiments, and it seems like "garble build -literals"
appears to hang trying to obfuscate literals starting at 5-20KiB. It's
not really hung; it's just doing a lot of busy work obfuscating those
literals. The code it produces is also far from ideal, so it also takes
some time to finally compile.
The generated code also led to crashes. For example, using "garble build
-literals -tiny" on a package containing literals of over a megabyte,
our use of asthelper to remove comments and shuffle line numbers could
run out of stack memory.
This all points in one direction: we never designed "-literals" to deal
with large sizes. Set a source-code-size limit of 2KiB.
We alter the literals.txt test as well, to include a few 128KiB string
literals. Before this fix, "go test" would seemingly hang on that test
for over a minute (I did not wait any longer). With the fix, those large
literals are not obfuscated, so the test ends in its usual 1-3s.
As said in the const comment, I don't believe any of this is a big
problem. Come Go 1.16, most developers should stop using asset-bundling
code generators and use go:embed instead. If we wanted to somehow
obfuscate those, it would be an entirely separate feature.
And, if someone wants to work on obfuscating truly large literals for
any reason, we need good tests and benchmarks to ensure garble does not
consume CPU for minutes or run out of memory.
I also simplified the generate-literals test command. The only argument
that matters to the script is the filename, since it's used later on.
Fixes #178.
4 years ago
|
|
|
grep '^\s+type \w+ func\(byte\) \w+$' .obf-src/main/extra_literals.go
|
|
|
|
|
|
|
|
-- go.mod --
|
|
|
|
module test/main
|
|
|
|
|
|
|
|
go 1.15
|
|
|
|
-- main.go --
|
|
|
|
package main
|
|
|
|
|
|
|
|
type strucTest struct {
|
|
|
|
field string
|
|
|
|
anotherfield string
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
cnst string = "Lorem"
|
|
|
|
multiline string = `First Line
|
|
|
|
Second Line`
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
i = 1
|
|
|
|
boolean = true
|
|
|
|
|
|
|
|
skip1 = "Skip this block"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
foo = iota
|
|
|
|
bar
|
|
|
|
|
|
|
|
skip2 = "also skip this"
|
|
|
|
)
|
|
|
|
|
|
|
|
const arrayLen = 4
|
|
|
|
|
|
|
|
var array [arrayLen]byte
|
|
|
|
|
|
|
|
type typeAlias [arrayLen]byte
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
empty := ""
|
|
|
|
|
|
|
|
localVar := "dolor"
|
|
|
|
|
|
|
|
reassign := "first assign"
|
|
|
|
reassign = "second assign"
|
|
|
|
|
|
|
|
add := "total" + " string"
|
|
|
|
|
|
|
|
println(cnst, boolean)
|
|
|
|
println(multiline, add)
|
|
|
|
println(localVar)
|
|
|
|
println(reassign)
|
|
|
|
println(empty)
|
|
|
|
|
|
|
|
x := strucTest{
|
|
|
|
field: "to obfuscate",
|
|
|
|
anotherfield: "also obfuscate",
|
|
|
|
}
|
|
|
|
|
|
|
|
lambda := func() string {
|
|
|
|
return "😅 😅"
|
|
|
|
}()
|
|
|
|
println(lambda)
|
|
|
|
|
|
|
|
println(x.field, x.anotherfield)
|
|
|
|
|
|
|
|
testMap := map[string]string{"map key": "map value"}
|
|
|
|
testMap["map key"] = "new value"
|
|
|
|
println(testMap["map key"])
|
|
|
|
println("another literal")
|
|
|
|
println(skip1, skip2)
|
|
|
|
println(i, foo, bar)
|
|
|
|
typedTest()
|
|
|
|
constantTest()
|
|
|
|
byteTest()
|
|
|
|
}
|
|
|
|
|
|
|
|
type stringType string
|
|
|
|
|
|
|
|
type stringTypeStruct struct {
|
|
|
|
str string
|
|
|
|
strType stringType
|
|
|
|
}
|
|
|
|
|
|
|
|
// typedTest types defined from string broke previously
|
|
|
|
func typedTest() {
|
|
|
|
const skipUntypedConst = "skip untyped const"
|
|
|
|
stringTypeFunc(skipUntypedConst)
|
|
|
|
|
|
|
|
const skipTypedConst stringType = "skip typed const" // skip
|
|
|
|
var skipTypedVar stringType = "skip typed var" // skip
|
|
|
|
|
|
|
|
var skipTypedVarAssign stringType
|
|
|
|
skipTypedVarAssign = "skip typed var assign" // skip
|
|
|
|
|
|
|
|
println(skipTypedConst, skipTypedVar, skipTypedVarAssign)
|
|
|
|
|
|
|
|
y := stringTypeStruct{
|
|
|
|
str: "stringTypeField String", // obfuscate
|
|
|
|
strType: "stringTypeField strType", // skip
|
|
|
|
}
|
|
|
|
println(y.str, y.strType)
|
|
|
|
|
|
|
|
z := func(s stringType) stringType {
|
|
|
|
return "stringType lambda func return" // skip
|
|
|
|
}("lambda call") // skip
|
|
|
|
println(z)
|
|
|
|
|
|
|
|
testMap1 := map[string]stringType{"testMap1 key": "testMap1 value"} // skip
|
|
|
|
testMap1["testMap1 key"] = "testMap1 new value" // skip
|
|
|
|
|
|
|
|
testMap2 := map[stringType]string{"testMap2 key": "testMap2 value"} // skip key
|
|
|
|
testMap2["testMap2 key"] = "testMap2 new value" // skip key
|
|
|
|
|
|
|
|
testMap3 := map[stringType]stringType{"testMap3 key": "testMap3 value"} // skip
|
|
|
|
testMap3["testMap3 key"] = "testMap3 new value" // skip
|
|
|
|
|
|
|
|
println(stringTypeFunc("stringType func param")) // skip
|
|
|
|
}
|
|
|
|
|
|
|
|
// constantTest tests that string constants which need to be constant are skipped
|
|
|
|
func constantTest() {
|
|
|
|
const a = "foo" // skip
|
|
|
|
const length = len(a)
|
|
|
|
|
|
|
|
const b = "bar" // skip
|
|
|
|
type T [len(b)]byte
|
|
|
|
|
|
|
|
const c = "foo" // skip
|
|
|
|
var _ [len(c)]byte
|
|
|
|
|
|
|
|
const d = "foo" // skip
|
|
|
|
var arr = [5]string{len(d): "foo"}
|
|
|
|
for _, elm := range arr {
|
|
|
|
if elm != "" {
|
|
|
|
println(elm)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const e = "foo" // skip
|
|
|
|
var slice = []string{len(e): "foo"}
|
|
|
|
for _, elm := range slice {
|
|
|
|
if elm != "" {
|
|
|
|
println(elm)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const f = "foo" // skip
|
|
|
|
const i = length + len(f)
|
|
|
|
println(length, i)
|
|
|
|
}
|
|
|
|
|
|
|
|
func byteTest() {
|
|
|
|
a := []byte{12, 13}
|
|
|
|
for _, elm := range a {
|
|
|
|
print(elm, ",")
|
|
|
|
}
|
|
|
|
println()
|
|
|
|
var b = []byte{12, 13}
|
|
|
|
for _, elm := range b {
|
|
|
|
print(elm, ",")
|
|
|
|
}
|
|
|
|
println()
|
|
|
|
|
|
|
|
var c = [2]byte{12, 13}
|
|
|
|
for _, elm := range c {
|
|
|
|
print(elm, ",")
|
|
|
|
}
|
|
|
|
println()
|
|
|
|
|
|
|
|
d := func() [4]byte {
|
|
|
|
return [4]byte{12, 13}
|
|
|
|
}()
|
|
|
|
for _, elm := range d {
|
|
|
|
print(elm, ",")
|
|
|
|
}
|
|
|
|
println()
|
|
|
|
}
|
|
|
|
|
|
|
|
func stringTypeFunc(s stringType) stringType {
|
|
|
|
println(s)
|
|
|
|
return "stringType return" // skip
|
|
|
|
}
|
|
|
|
-- main.stderr --
|
|
|
|
Lorem true
|
|
|
|
First Line
|
|
|
|
Second Line total string
|
|
|
|
dolor
|
|
|
|
second assign
|
|
|
|
|
|
|
|
😅 😅
|
|
|
|
to obfuscate also obfuscate
|
|
|
|
new value
|
|
|
|
another literal
|
|
|
|
Skip this block also skip this
|
|
|
|
1 0 1
|
|
|
|
skip untyped const
|
|
|
|
skip typed const skip typed var skip typed var assign
|
|
|
|
stringTypeField String stringTypeField strType
|
|
|
|
stringType lambda func return
|
|
|
|
stringType func param
|
|
|
|
stringType return
|
|
|
|
foo
|
|
|
|
foo
|
|
|
|
3 6
|
|
|
|
12,13,
|
|
|
|
12,13,
|
|
|
|
12,13,
|
|
|
|
12,13,0,0,
|