internal/literals: simplify the obfuscator selection code

The "next obfuscator" logic was split into three funcs for no reason;
it all fits into a single function in less than a dozen lines.

While here, avoid calling the obfRand variables the same as the
type itself, as that leads to significant confusion.
This commit is contained in:
Daniel Martí
2026-04-15 14:41:31 +01:00
committed by Paul
parent cecc5d0017
commit 28c2fd54c0
2 changed files with 37 additions and 48 deletions
+34 -31
View File
@@ -40,7 +40,7 @@ type NameProviderFunc func(rand *mathrand.Rand, baseName string) string
// Obfuscate replaces literals with obfuscated anonymous functions.
func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkStrings map[*types.Var]string, nameFunc NameProviderFunc) *ast.File {
obfRand := newObfRand(rand, file, nameFunc)
or := newObfRand(rand, file, nameFunc)
pre := func(cursor *astutil.Cursor) bool {
switch node := cursor.Node().(type) {
case *ast.FuncDecl:
@@ -89,7 +89,7 @@ func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkString
return true
}
cursor.Replace(withPos(obfuscateString(obfRand, value), node.Pos()))
cursor.Replace(withPos(obfuscateString(or, value), node.Pos()))
return true
}
@@ -106,7 +106,7 @@ func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkString
}
if child, ok := node.X.(*ast.CompositeLit); ok {
newnode := handleCompositeLiteral(obfRand, true, child, info)
newnode := handleCompositeLiteral(or, true, child, info)
if newnode != nil {
cursor.Replace(newnode)
}
@@ -125,7 +125,7 @@ func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkString
return true
}
newnode := handleCompositeLiteral(obfRand, false, node, info)
newnode := handleCompositeLiteral(or, false, node, info)
if newnode != nil {
cursor.Replace(newnode)
}
@@ -135,7 +135,7 @@ func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkString
}
newFile := astutil.Apply(file, pre, post).(*ast.File)
obfRand.proxyDispatcher.AddToFile(newFile)
or.proxyDispatcher.AddToFile(newFile)
return newFile
}
@@ -144,7 +144,7 @@ func Obfuscate(rand *mathrand.Rand, file *ast.File, info *types.Info, linkString
// be used to replace it.
//
// If the input node cannot be obfuscated nil is returned.
func handleCompositeLiteral(obfRand *obfRand, isPointer bool, node *ast.CompositeLit, info *types.Info) ast.Node {
func handleCompositeLiteral(or *obfRand, isPointer bool, node *ast.CompositeLit, info *types.Info) ast.Node {
if len(node.Elts) < MinSize || len(node.Elts) > MaxSize {
return nil
}
@@ -187,10 +187,10 @@ func handleCompositeLiteral(obfRand *obfRand, isPointer bool, node *ast.Composit
}
if arrayLen > 0 {
return withPos(obfuscateByteArray(obfRand, isPointer, data, arrayLen), node.Pos())
return withPos(obfuscateByteArray(or, isPointer, data, arrayLen), node.Pos())
}
return withPos(obfuscateByteSlice(obfRand, isPointer, data), node.Pos())
return withPos(obfuscateByteSlice(or, isPointer, data), node.Pos())
}
// withPos sets any token.Pos fields under node which affect printing to pos.
@@ -237,22 +237,22 @@ func withPos(node ast.Node, pos token.Pos) ast.Node {
return node
}
func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
obf := getNextObfuscator(obfRand, len(data))
func obfuscateString(or *obfRand, data string) *ast.CallExpr {
obf := or.pickObfuscator(len(data))
// Generate junk bytes to to prepend and append to the data.
// This is to prevent the obfuscated string from being easily fingerprintable.
junkBytes := make([]byte, obfRand.Intn(maxStringJunkBytes-minStringJunkBytes)+minStringJunkBytes)
obfRand.Read(junkBytes)
splitIdx := obfRand.Intn(len(junkBytes))
junkBytes := make([]byte, or.rnd.Intn(maxStringJunkBytes-minStringJunkBytes)+minStringJunkBytes)
or.rnd.Read(junkBytes)
splitIdx := or.rnd.Intn(len(junkBytes))
extKeys := randExtKeys(obfRand.Rand)
extKeys := randExtKeys(or.rnd)
plainData := []byte(data)
plainDataWithJunkBytes := append(append(junkBytes[:splitIdx], plainData...), junkBytes[splitIdx:]...)
block := obf.obfuscate(obfRand.Rand, plainDataWithJunkBytes, extKeys)
params, args := extKeysToParams(obfRand, extKeys)
block := obf.obfuscate(or.rnd, plainDataWithJunkBytes, extKeys)
params, args := extKeysToParams(or, extKeys)
// Generate unique cast bytes to string function and hide it using proxyDispatcher:
//
@@ -289,16 +289,16 @@ func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
),
),
}
block.List = append(block.List, ah.ReturnStmt(ah.CallExpr(obfRand.proxyDispatcher.HideValue(funcVal, funcTyp), ast.NewIdent("data"))))
block.List = append(block.List, ah.ReturnStmt(ah.CallExpr(or.proxyDispatcher.HideValue(funcVal, funcTyp), ast.NewIdent("data"))))
return ah.LambdaCall(params, ast.NewIdent("string"), block, args)
}
func obfuscateByteSlice(obfRand *obfRand, isPointer bool, data []byte) *ast.CallExpr {
obf := getNextObfuscator(obfRand, len(data))
func obfuscateByteSlice(or *obfRand, isPointer bool, data []byte) *ast.CallExpr {
obf := or.pickObfuscator(len(data))
extKeys := randExtKeys(obfRand.Rand)
block := obf.obfuscate(obfRand.Rand, data, extKeys)
params, args := extKeysToParams(obfRand, extKeys)
extKeys := randExtKeys(or.rnd)
block := obf.obfuscate(or.rnd, data, extKeys)
params, args := extKeysToParams(or, extKeys)
if isPointer {
block.List = append(block.List, ah.ReturnStmt(
@@ -311,12 +311,12 @@ func obfuscateByteSlice(obfRand *obfRand, isPointer bool, data []byte) *ast.Call
return ah.LambdaCall(params, ah.ByteSliceType(), block, args)
}
func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length int64) *ast.CallExpr {
obf := getNextObfuscator(obfRand, len(data))
func obfuscateByteArray(or *obfRand, isPointer bool, data []byte, length int64) *ast.CallExpr {
obf := or.pickObfuscator(len(data))
extKeys := randExtKeys(obfRand.Rand)
block := obf.obfuscate(obfRand.Rand, data, extKeys)
params, args := extKeysToParams(obfRand, extKeys)
extKeys := randExtKeys(or.rnd)
block := obf.obfuscate(or.rnd, data, extKeys)
params, args := extKeysToParams(or, extKeys)
arrayType := ah.ByteArrayType(length)
@@ -358,12 +358,15 @@ func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length in
return ah.LambdaCall(params, arrayType, block, args)
}
func getNextObfuscator(obfRand *obfRand, size int) obfuscator {
func (or *obfRand) pickObfuscator(size int) obfuscator {
if size < MinSize || size > MaxSize {
panic(fmt.Sprintf("getNextObfuscator called with size %d outside [%d, %d]", size, MinSize, MaxSize))
panic(fmt.Sprintf("nextObfuscator called with size %d outside [%d, %d]", size, MinSize, MaxSize))
}
if or.testObfuscator != nil {
return or.testObfuscator
}
if size <= MaxSizeExpensive {
return obfRand.nextObfuscator()
return Obfuscators[or.rnd.Intn(len(Obfuscators))]
}
return obfRand.nextCheapObfuscator()
return CheapObfuscators[or.rnd.Intn(len(CheapObfuscators))]
}
+3 -17
View File
@@ -178,7 +178,7 @@ func extKeysToParams(objRand *obfRand, keys []*externalKey) (params *ast.FieldLi
params.List = append(params.List, ah.Field(key.Type(), name))
var extKeyExpr ast.Expr = ah.UintLit(key.value)
if lowProb.Try(objRand.Rand) {
if lowProb.Try(objRand.rnd) {
extKeyExpr = objRand.proxyDispatcher.HideValue(extKeyExpr, ast.NewIdent(key.typ))
}
args = append(args, extKeyExpr)
@@ -255,26 +255,12 @@ func byteLitWithExtKey(rand *mathrand.Rand, val byte, extKeys []*externalKey, ex
}
type obfRand struct {
*mathrand.Rand
rnd *mathrand.Rand
testObfuscator obfuscator
proxyDispatcher *proxyDispatcher
}
func (r *obfRand) nextObfuscator() obfuscator {
if r.testObfuscator != nil {
return r.testObfuscator
}
return Obfuscators[r.Intn(len(Obfuscators))]
}
func (r *obfRand) nextCheapObfuscator() obfuscator {
if r.testObfuscator != nil {
return r.testObfuscator
}
return CheapObfuscators[r.Intn(len(CheapObfuscators))]
}
func newObfRand(rand *mathrand.Rand, file *ast.File, nameFunc NameProviderFunc) *obfRand {
testObf := testPkgToObfuscatorMap[file.Name.Name]
return &obfRand{rand, testObf, newProxyDispatcher(rand, nameFunc)}