Fix floats.

Ignore hexadecimal and octal notated numbers.

Replace underscores in float/  int literals.

Literals test compare output of normal "go run ." ,
to test that no numbers get broken.
pull/64/head
lu4p 5 years ago
parent ce9efab562
commit 818ec7749c

@ -14,7 +14,7 @@ import (
"mvdan.cc/garble/literals/obfuscators"
)
func getCallexpr(resultType ast.Expr, block *ast.BlockStmt) *ast.CallExpr {
func callExpr(resultType ast.Expr, block *ast.BlockStmt) *ast.CallExpr {
return &ast.CallExpr{
Fun: &ast.FuncLit{
Type: &ast.FuncType{
@ -30,12 +30,12 @@ func getCallexpr(resultType ast.Expr, block *ast.BlockStmt) *ast.CallExpr {
}
}
func getObfuscator() obfuscators.Obfuscator {
func randObfuscator() obfuscators.Obfuscator {
randPos := mathrand.Intn(len(obfuscators.Obfuscators))
return obfuscators.Obfuscators[randPos]
}
func getReturnStmt(result ast.Expr) *ast.ReturnStmt {
func returnStmt(result ast.Expr) *ast.ReturnStmt {
return &ast.ReturnStmt{
Results: []ast.Expr{result},
}
@ -53,8 +53,6 @@ func isTypeDefStr(typ types.Type) bool {
func containsTypeDefStr(expr ast.Expr, info *types.Info) bool {
typ := info.TypeOf(expr)
// log.Println(expr, typ, reflect.TypeOf(expr), reflect.TypeOf(typ))
if sig, ok := typ.(*types.Signature); ok {
for i := 0; i < sig.Params().Len(); i++ {
if isTypeDefStr(sig.Params().At(i).Type()) {
@ -75,7 +73,7 @@ func containsTypeDefStr(expr ast.Expr, info *types.Info) bool {
}
// Obfuscate replace literals with obfuscated lambda functions
func Obfuscate(files []*ast.File, info *types.Info, blacklist map[types.Object]struct{}) []*ast.File {
func Obfuscate(files []*ast.File, info *types.Info, fset *token.FileSet, blacklist map[types.Object]struct{}) []*ast.File {
pre := func(cursor *astutil.Cursor) bool {
switch x := cursor.Node().(type) {
case *ast.ValueSpec:
@ -180,7 +178,7 @@ func Obfuscate(files []*ast.File, info *types.Info, blacklist map[types.Object]s
data = append(data, byte(value))
}
cursor.Replace(obfuscateByte(data))
cursor.Replace(obfuscateBytes(data))
}
case *ast.UnaryExpr:
switch cursor.Name() {
@ -220,12 +218,17 @@ func Obfuscate(files []*ast.File, info *types.Info, blacklist map[types.Object]s
}
for i := range files {
astutil.AddImport(fset, files[i], "unsafe")
files[i] = astutil.Apply(files[i], pre, post).(*ast.File)
if !astutil.UsesImport(files[i], "unsafe") {
astutil.DeleteImport(fset, files[i], "unsafe")
}
}
return files
}
func obfuscateNumberLiteral(cursor *astutil.Cursor, info *types.Info) error {
// TODO: Add support for obfuscation of hexadecimal and octal notation
var (
call *ast.CallExpr
basic *ast.BasicLit
@ -266,18 +269,20 @@ func obfuscateNumberLiteral(cursor *astutil.Cursor, info *types.Info) error {
}
strValue := sign + basic.Value
// Literals can have underscores for better readabilty
strValue = strings.ReplaceAll(strValue, "_", "")
switch typeInfo {
case types.Typ[types.Float32]:
fV, err := strconv.ParseFloat(strValue, 32)
if err != nil {
panic(err)
return err
}
call = obfuscateFloat32(float32(fV))
case types.Typ[types.Float64], types.Typ[types.UntypedFloat]:
fV, err := strconv.ParseFloat(strValue, 64)
if err != nil {
panic(err)
return err
}
call = obfuscateFloat64(fV)
}
@ -291,7 +296,7 @@ func obfuscateNumberLiteral(cursor *astutil.Cursor, info *types.Info) error {
splitStrValue := strings.Split(strValue, ".")
intValue, err := strconv.Atoi(splitStrValue[0])
if err != nil {
panic(err)
return err
}
switch typeInfo {

@ -4,6 +4,7 @@ import (
"encoding/binary"
"go/ast"
"go/token"
"math"
)
func getBoundsCheck(pos string) *ast.AssignStmt {
@ -23,7 +24,7 @@ func getBoundsCheck(pos string) *ast.AssignStmt {
}
func obfuscateUint8(data uint8) *ast.CallExpr {
obfuscator := getObfuscator()
obfuscator := randObfuscator()
block := obfuscator.Obfuscate([]byte{byte(data)})
block.List = append(block.List,
&ast.ReturnStmt{
@ -43,11 +44,11 @@ func obfuscateUint8(data uint8) *ast.CallExpr {
},
})
return getCallexpr(&ast.Ident{Name: "uint8"}, block)
return callExpr(&ast.Ident{Name: "uint8"}, block)
}
func obfuscateUint16(data uint16) *ast.CallExpr {
obfuscator := getObfuscator()
obfuscator := randObfuscator()
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, data)
block := obfuscator.Obfuscate(b)
@ -87,13 +88,13 @@ func obfuscateUint16(data uint16) *ast.CallExpr {
},
}
block.List = append(block.List, getBoundsCheck("1"), getReturnStmt(convertExpr))
block.List = append(block.List, getBoundsCheck("1"), returnStmt(convertExpr))
return getCallexpr(&ast.Ident{Name: "uint16"}, block)
return callExpr(&ast.Ident{Name: "uint16"}, block)
}
func obfuscateUint32(data uint32) *ast.CallExpr {
obfuscator := getObfuscator()
obfuscator := randObfuscator()
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, data)
block := obfuscator.Obfuscate(b)
@ -177,13 +178,13 @@ func obfuscateUint32(data uint32) *ast.CallExpr {
},
}
block.List = append(block.List, getBoundsCheck("3"), getReturnStmt(convertExpr))
block.List = append(block.List, getBoundsCheck("3"), returnStmt(convertExpr))
return getCallexpr(&ast.Ident{Name: "uint32"}, block)
return callExpr(&ast.Ident{Name: "uint32"}, block)
}
func obfuscateUint64(data uint64) *ast.CallExpr {
obfuscator := getObfuscator()
obfuscator := randObfuscator()
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, data)
block := obfuscator.Obfuscate(b)
@ -354,9 +355,9 @@ func obfuscateUint64(data uint64) *ast.CallExpr {
},
}
block.List = append(block.List, getBoundsCheck("7"), getReturnStmt(convertExpr))
block.List = append(block.List, getBoundsCheck("7"), returnStmt(convertExpr))
return getCallexpr(&ast.Ident{Name: "uint64"}, block)
return callExpr(&ast.Ident{Name: "uint64"}, block)
}
func obfuscateUint(data uint) *ast.CallExpr {
@ -436,24 +437,61 @@ func obfuscateInt(data int) *ast.CallExpr {
}
}
func obfuscateFloat32(data float32) *ast.CallExpr {
func uintToFloat(uintExpr *ast.CallExpr, bits string) *ast.CallExpr {
return &ast.CallExpr{
Fun: &ast.Ident{
Name: "float32",
},
Args: []ast.Expr{
obfuscateUint32(uint32(data)),
Fun: &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{},
Results: &ast.FieldList{
List: []*ast.Field{
{Type: &ast.Ident{Name: "float" + bits}},
},
},
},
Body: &ast.BlockStmt{
List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{&ast.Ident{Name: "result"}},
Tok: token.DEFINE,
Rhs: []ast.Expr{uintExpr},
},
&ast.ReturnStmt{
Results: []ast.Expr{
&ast.StarExpr{
X: &ast.CallExpr{
Fun: &ast.ParenExpr{
X: &ast.StarExpr{X: &ast.Ident{Name: "float" + bits}},
},
Args: []ast.Expr{
&ast.CallExpr{
Fun: &ast.SelectorExpr{
X: &ast.Ident{Name: "unsafe"},
Sel: &ast.Ident{Name: "Pointer"},
},
Args: []ast.Expr{
&ast.UnaryExpr{
Op: token.AND,
X: &ast.Ident{Name: "result"},
},
},
},
},
},
},
},
},
},
},
},
}
}
func obfuscateFloat32(data float32) *ast.CallExpr {
b := math.Float32bits(data)
return uintToFloat(obfuscateUint32(b), "32")
}
func obfuscateFloat64(data float64) *ast.CallExpr {
return &ast.CallExpr{
Fun: &ast.Ident{
Name: "float64",
},
Args: []ast.Expr{
obfuscateUint64(uint64(data)),
},
}
b := math.Float64bits(data)
return uintToFloat(obfuscateUint64(b), "64")
}

@ -18,52 +18,39 @@ func (x xor) Obfuscate(data []byte) *ast.BlockStmt {
data[i] = data[i] ^ b
}
return &ast.BlockStmt{
List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{
&ast.Ident{Name: "key"},
},
Tok: token.DEFINE,
Rhs: []ast.Expr{dataToByteSlice(key)},
},
&ast.AssignStmt{
Lhs: []ast.Expr{
&ast.Ident{Name: "data"},
},
Tok: token.DEFINE,
Rhs: []ast.Expr{dataToByteSlice(data)},
},
&ast.RangeStmt{
Key: &ast.Ident{Name: "i"},
Value: &ast.Ident{Name: "b"},
Tok: token.DEFINE,
X: &ast.Ident{Name: "key"},
Body: &ast.BlockStmt{
List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{
&ast.IndexExpr{
X: &ast.Ident{Name: "data"},
Index: &ast.Ident{Name: "i"},
},
},
Tok: token.ASSIGN,
Rhs: []ast.Expr{
&ast.BinaryExpr{
X: &ast.IndexExpr{
X: &ast.Ident{Name: "data"},
Index: &ast.Ident{Name: "i"},
},
Op: token.XOR,
Y: &ast.Ident{Name: "b"},
},
},
return &ast.BlockStmt{List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{&ast.Ident{Name: "key"}},
Tok: token.DEFINE,
Rhs: []ast.Expr{dataToByteSlice(key)},
},
&ast.AssignStmt{
Lhs: []ast.Expr{&ast.Ident{Name: "data"}},
Tok: token.DEFINE,
Rhs: []ast.Expr{dataToByteSlice(data)},
},
&ast.RangeStmt{
Key: &ast.Ident{Name: "i"},
Value: &ast.Ident{Name: "b"},
Tok: token.DEFINE,
X: &ast.Ident{Name: "key"},
Body: &ast.BlockStmt{List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{&ast.IndexExpr{
X: &ast.Ident{Name: "data"},
Index: &ast.Ident{Name: "i"},
}},
Tok: token.ASSIGN,
Rhs: []ast.Expr{&ast.BinaryExpr{
X: &ast.IndexExpr{
X: &ast.Ident{Name: "data"},
Index: &ast.Ident{Name: "i"},
},
},
Op: token.XOR,
Y: &ast.Ident{Name: "b"},
}},
},
},
}},
},
}
}}
}

@ -6,31 +6,25 @@ import (
)
func obfuscateString(data string) *ast.CallExpr {
obfuscator := getObfuscator()
obfuscator := randObfuscator()
block := obfuscator.Obfuscate([]byte(data))
block.List = append(block.List, &ast.ReturnStmt{
Results: []ast.Expr{
&ast.CallExpr{
Fun: &ast.Ident{Name: "string"},
Args: []ast.Expr{
&ast.Ident{Name: "data"},
},
},
},
Results: []ast.Expr{&ast.CallExpr{
Fun: &ast.Ident{Name: "string"},
Args: []ast.Expr{&ast.Ident{Name: "data"}},
}},
})
return getCallexpr(&ast.Ident{Name: "string"}, block)
return callExpr(&ast.Ident{Name: "string"}, block)
}
func obfuscateByte(data []byte) *ast.CallExpr {
obfuscator := getObfuscator()
func obfuscateBytes(data []byte) *ast.CallExpr {
obfuscator := randObfuscator()
block := obfuscator.Obfuscate(data)
block.List = append(block.List, &ast.ReturnStmt{
Results: []ast.Expr{
&ast.Ident{Name: "data"},
},
Results: []ast.Expr{&ast.Ident{Name: "data"}},
})
return getCallexpr(&ast.ArrayType{Elt: &ast.Ident{Name: "byte"}}, block)
return callExpr(&ast.ArrayType{Elt: &ast.Ident{Name: "byte"}}, block)
}
func obfuscateBool(data bool) *ast.BinaryExpr {

@ -396,7 +396,7 @@ func transformCompile(args []string) ([]string, error) {
blacklist := buildBlacklist(files, info, pkg)
if envGarbleLiterals {
files = literals.Obfuscate(files, info, blacklist)
files = literals.Obfuscate(files, info, fset, blacklist)
// ast changed so we need to typecheck again
pkg, err = origTypesConfig.Check(pkgPath, fset, files, info)
if err != nil {

@ -1,8 +1,11 @@
go run .
cmp stderr main.stderr
cp stderr normal.stderr
garble -literals build
exec ./main$exe
cmp stderr main.stderr
! binsubstr main$exe 'garbleDecrypt' 'Lorem' 'ipsum' 'dolor' 'first assign' 'second assign' 'First Line' 'Second Line' 'map value' 'to obfuscate' 'also obfuscate' 'stringTypeField String' 'stringTypeStruct' '2824583991413579605' '3735714531481032066'
cmp stderr normal.stderr
! binsubstr main$exe 'garbleDecrypt' 'Lorem' 'ipsum' 'dolor' 'first assign' 'second assign' 'First Line' 'Second Line' 'map value' 'to obfuscate' 'also obfuscate' 'stringTypeField String' 'stringTypeStruct'
binsubstr main$exe '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' 'testMap2 value' 'testMap3 value' 'testMap1 new value' 'testMap2 new value' 'testMap3 new value' 'stringType func param' 'stringType return'
[short] stop # checking that the build is reproducible is slow
@ -189,6 +192,15 @@ func numTest() {
complexVar64 complex64 = -435453453534 // skip
complexVar128 complex128 = 1 + 4i // skip
underscoreInt = 1_3_3_7
underscoreFloat = 1_3_3_7.0
hexInt = 0x1337 // skip
hexFloat = 0x1337p0 // skip
octalInt = 0o1337 // skip
octalFloat = 0o1337 // skip
)
floatShort := -435453453534.0
@ -196,6 +208,7 @@ func numTest() {
println(uintVar, uint8Var, uint16Var, uint32Var, uint64Var, uintptrVar)
println(untypedFloat, floatVar, floatShort, floatVar32)
println(complexVar64, complexVar128)
println(underscoreInt, underscoreFloat, hexInt, hexFloat, octalInt, octalFloat)
}
@ -257,8 +270,9 @@ foo
1 3 2824583991413579605 4 5 3735714531481032066
-3453453534411 -3453453534423 -122 3534 333453534 3453453534423
3453453534423 34 3534 333453534 3453453534423 3453453534423
+3.000000e+000 +7.545345e+010 +1.844674e+019 +2.633204e+009
+3.000000e+000 +7.545345e+010 -4.354535e+011 -4.354535e+011
(-4.354535e+011+0.000000e+000i) (+1.000000e+000+4.000000e+000i)
1337 +1.337000e+003 4919 +4.919000e+003 735 735
12, 13,
12, 13,
true false false true true false

Loading…
Cancel
Save