From 9c25f4c2b2c63c4c56a4c9f44bcc4c3e73d4b2bc Mon Sep 17 00:00:00 2001 From: pagran <67878280+pagran@users.noreply.github.com> Date: Sun, 9 Aug 2020 13:05:47 +0300 Subject: [PATCH] Add xorShuffle obfuscator (#85) * Refactoring * Rename Xor2 to XorShuffle --- internal/literals/obfuscators.go | 1 + internal/literals/xor_shuffle.go | 62 ++++++++++++++++++++++++++++++++ testdata/scripts/literals.txt | 3 ++ 3 files changed, 66 insertions(+) create mode 100644 internal/literals/xor_shuffle.go diff --git a/internal/literals/obfuscators.go b/internal/literals/obfuscators.go index 2a179da..84ac68a 100644 --- a/internal/literals/obfuscators.go +++ b/internal/literals/obfuscators.go @@ -20,6 +20,7 @@ var ( xor{}, swap{}, split{}, + xorShuffle{}, } envGarbleSeed = os.Getenv("GARBLE_SEED") ) diff --git a/internal/literals/xor_shuffle.go b/internal/literals/xor_shuffle.go new file mode 100644 index 0000000..1a8741a --- /dev/null +++ b/internal/literals/xor_shuffle.go @@ -0,0 +1,62 @@ +package literals + +import ( + "go/ast" + "go/token" + mathrand "math/rand" + + ah "mvdan.cc/garble/internal/asthelper" +) + +type xorShuffle struct{} + +// check that the obfuscator interface is implemented +var _ obfuscator = xorShuffle{} + +func (x xorShuffle) obfuscate(data []byte) *ast.BlockStmt { + key := make([]byte, len(data)) + genRandBytes(key) + + fullData := make([]byte, len(data)+len(key)) + for i, b := range key { + fullData[i], fullData[i+len(data)] = data[i]^b, b + } + + shuffledIdxs := mathrand.Perm(len(fullData)) + + shuffledFullData := make([]byte, len(fullData)) + for i, b := range fullData { + shuffledFullData[shuffledIdxs[i]] = b + } + + args := []ast.Expr{ah.Ident("data")} + for i := range data { + args = append(args, &ast.BinaryExpr{ + X: ah.IndexExpr("fullData", ah.IntLit(shuffledIdxs[i])), + Op: token.XOR, + Y: ah.IndexExpr("fullData", ah.IntLit(shuffledIdxs[len(data)+i])), + }) + } + + return ah.BlockStmt( + &ast.AssignStmt{ + Lhs: []ast.Expr{ah.Ident("fullData")}, + Tok: token.DEFINE, + Rhs: []ast.Expr{ah.DataToByteSlice(shuffledFullData)}, + }, + &ast.DeclStmt{ + Decl: &ast.GenDecl{ + Tok: token.VAR, + Specs: []ast.Spec{&ast.ValueSpec{ + Names: []*ast.Ident{ah.Ident("data")}, + Type: &ast.ArrayType{Elt: ah.Ident("byte")}, + }}, + }, + }, + &ast.AssignStmt{ + Lhs: []ast.Expr{ah.Ident("data")}, + Tok: token.ASSIGN, + Rhs: []ast.Expr{ah.CallExpr(ah.Ident("append"), args...)}, + }, + ) +} diff --git a/testdata/scripts/literals.txt b/testdata/scripts/literals.txt index 9dd1194..c8533c1 100644 --- a/testdata/scripts/literals.txt +++ b/testdata/scripts/literals.txt @@ -45,6 +45,9 @@ grep '^\s+\w+ := \[\.{3}\](byte|uint16|uint32|uint64)\{[0-9\s,]+\}$' .obf-src/ma # Split obfuscator. Detect decryptKey ^= i * counter grep '^\s+\w+ \^= \w+ \* \w+$' .obf-src/main/z0.go +# XorShuffle obfuscator. Detect data = append(data, x ^ y...) +grep '^\s+\w+ = append\(\w+,(\s+\w+\[\d+\]\^\w+\[\d+\],?)+\)$' .obf-src/main/z0.go + -- go.mod -- module test/main