Fix byte array and untyped constant obfuscation.

Byte arrays were previously,
obfuscated as byte slices.

Untyped constants are now skipped,
because they cannot be replaced with typed variables.
pull/71/head
lu4p 4 years ago committed by Daniel Martí
parent d48bdbadae
commit 705f9d3a28

@ -54,15 +54,20 @@ func Obfuscate(files []*ast.File, info *types.Info, fset *token.FileSet, blackli
for _, name := range spec.Names {
obj := info.ObjectOf(name)
// The object itself is blacklisted, e.g. a value that needs to be constant
if _, ok := blacklist[obj]; ok {
basic, ok := obj.Type().(*types.Basic)
if !ok {
// skip the block if it contains non basic types
return false
}
if basic.Info()&types.IsUntyped != 0 {
// skip the block if it contains untyped constants
return false
}
}
for _, val := range spec.Values {
if _, ok := val.(*ast.BasicLit); !ok {
return false // skip the block if it contains non basic literals
// The object itself is blacklisted, e.g. a value that needs to be constant
if _, ok := blacklist[obj]; ok {
return false
}
}
}
@ -79,35 +84,53 @@ func Obfuscate(files []*ast.File, info *types.Info, fset *token.FileSet, blackli
case *ast.CompositeLit:
byteType := types.Universe.Lookup("byte").Type()
switch x := info.TypeOf(x.Type).(type) {
switch y := info.TypeOf(x.Type).(type) {
case *types.Array:
if x.Elem() != byteType {
if y.Elem() != byteType {
return true
}
case *types.Slice:
if x.Elem() != byteType {
return true
data := make([]byte, y.Len())
for i, el := range x.Elts {
lit, ok := el.(*ast.BasicLit)
if !ok {
return true
}
value, err := strconv.Atoi(lit.Value)
if err != nil {
return true
}
data[i] = byte(value)
}
default:
return true
}
cursor.Replace(obfuscateByteArray(data, y.Len()))
var data []byte
for _, el := range x.Elts {
lit, ok := el.(*ast.BasicLit)
if !ok {
case *types.Slice:
if y.Elem() != byteType {
return true
}
value, err := strconv.Atoi(lit.Value)
if err != nil {
return true
var data []byte
for _, el := range x.Elts {
lit, ok := el.(*ast.BasicLit)
if !ok {
return true
}
value, err := strconv.Atoi(lit.Value)
if err != nil {
return true
}
data = append(data, byte(value))
}
cursor.Replace(obfuscateByteSlice(data))
data = append(data, byte(value))
}
cursor.Replace(obfuscateBytes(data))
case *ast.BasicLit:
switch cursor.Name() {
case "Values", "Rhs", "Value", "Args", "X", "Y", "Results":
@ -152,7 +175,7 @@ func obfuscateString(data string) *ast.CallExpr {
return callExpr(&ast.Ident{Name: "string"}, block)
}
func obfuscateBytes(data []byte) *ast.CallExpr {
func obfuscateByteSlice(data []byte) *ast.CallExpr {
obfuscator := randObfuscator()
block := obfuscator.obfuscate(data)
block.List = append(block.List, &ast.ReturnStmt{
@ -161,6 +184,56 @@ func obfuscateBytes(data []byte) *ast.CallExpr {
return callExpr(&ast.ArrayType{Elt: &ast.Ident{Name: "byte"}}, block)
}
func obfuscateByteArray(data []byte, length int64) *ast.CallExpr {
obfuscator := randObfuscator()
block := obfuscator.obfuscate(data)
arrayType := &ast.ArrayType{
Len: &ast.BasicLit{
Kind: token.INT,
Value: strconv.Itoa(int(length)),
},
Elt: &ast.Ident{Name: "byte"},
}
sliceToArray := []ast.Stmt{
&ast.DeclStmt{
Decl: &ast.GenDecl{
Tok: token.VAR,
Specs: []ast.Spec{&ast.ValueSpec{
Names: []*ast.Ident{{Name: "newdata"}},
Type: arrayType,
}},
},
},
&ast.RangeStmt{
Key: &ast.Ident{Name: "i"},
Tok: token.DEFINE,
X: &ast.Ident{Name: "newdata"},
Body: &ast.BlockStmt{List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{&ast.IndexExpr{
X: &ast.Ident{Name: "newdata"},
Index: &ast.Ident{Name: "i"},
}},
Tok: token.ASSIGN,
Rhs: []ast.Expr{&ast.IndexExpr{
X: &ast.Ident{Name: "data"},
Index: &ast.Ident{Name: "i"},
}},
},
}},
},
&ast.ReturnStmt{Results: []ast.Expr{
&ast.Ident{Name: "newdata"},
}},
}
block.List = append(block.List, sliceToArray...)
return callExpr(arrayType, block)
}
// ConstBlacklist blacklist identifieres used in constant expressions
func ConstBlacklist(node ast.Node, info *types.Info, blacklist map[types.Object]struct{}) {
blacklistObjects := func(node ast.Node) bool {

@ -7,7 +7,7 @@ cmp stderr main.stderr
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' 'testMap3 value' 'testMap1 new value' 'testMap3 new value' 'stringType func param' 'stringType return'
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' 'testMap3 value' 'testMap1 new value' 'testMap3 new value' 'stringType func param' 'stringType return' 'skip untyped const'
[short] stop # checking that the build is reproducible is slow
# Also check that the binary is reproducible.
@ -28,7 +28,7 @@ type strucTest struct {
const (
cnst string = "Lorem"
multiline = `First Line
multiline string = `First Line
Second Line`
)
@ -70,7 +70,7 @@ func main() {
field: "to obfuscate",
anotherfield: "also obfuscate",
}
lambda := func() string {
return "😅 😅"
}()
@ -98,6 +98,9 @@ type stringTypeStruct struct {
// 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
@ -158,6 +161,7 @@ func constantTest() {
const f = "foo" // skip
const i = length + len(f)
println(length, i)
}
func byteTest() {
@ -177,6 +181,14 @@ func byteTest() {
print(elm, ", ")
}
println()
d := func() [4]byte {
return [4]byte{12, 13}
}()
for _, elm := range d {
print(elm, ", ")
}
println()
}
func stringTypeFunc(s stringType) stringType {
@ -197,6 +209,7 @@ new value
another literal
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
@ -204,6 +217,8 @@ stringType func param
stringType return
foo
foo
3 6
12, 13,
12, 13,
12, 13,
12, 13, 0, 0,

Loading…
Cancel
Save