Randomize operator (xor, add, subtract) on all obfuscators (#90)

Co-authored-by: lu4p <lu4p@pm.me>
pull/91/head
pagran 4 years ago committed by GitHub
parent 2eba744530
commit 28adbaa73b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,6 +4,7 @@ import (
cryptrand "crypto/rand"
"fmt"
"go/ast"
"go/token"
mathrand "math/rand"
"os"
"strings"
@ -44,6 +45,12 @@ func genRandBytes(buffer []byte) {
}
}
func genRandByte() byte {
bytes := make([]byte, 1)
genRandBytes(bytes)
return bytes[0]
}
func genRandIntSlice(max, count int) []int {
indexes := make([]int, count)
for i := 0; i < count; i++ {
@ -51,3 +58,38 @@ func genRandIntSlice(max, count int) []int {
}
return indexes
}
func randOperator() token.Token {
operatorTokens := [...]token.Token{token.XOR, token.ADD, token.SUB}
return operatorTokens[mathrand.Intn(len(operatorTokens))]
}
func evalOperator(t token.Token, x, y byte) byte {
switch t {
case token.XOR:
return x ^ y
case token.ADD:
return x + y
case token.SUB:
return x - y
default:
panic(fmt.Sprintf("unknown operator: %s", t))
}
}
func operatorToReversedBinaryExpr(t token.Token, x, y ast.Expr) *ast.BinaryExpr {
expr := &ast.BinaryExpr{X: x, Y: y}
switch t {
case token.XOR:
expr.Op = token.XOR
case token.ADD:
expr.Op = token.SUB
case token.SUB:
expr.Op = token.ADD
default:
panic(fmt.Sprintf("unknown operator: %s", t))
}
return expr
}

@ -55,14 +55,13 @@ func shuffleStmts(stmts ...ast.Stmt) []ast.Stmt {
return stmts
}
// Xor encrypt chunks based on key and position
func encryptChunks(chunks [][]byte, key int) {
idx := 0
for chunkIdx := range chunks {
chunk := chunks[chunkIdx]
for i := range chunk {
chunk[i] ^= byte(key ^ idx)
idx++
// Encrypt chunks based on key and position
func encryptChunks(chunks [][]byte, op token.Token, key byte) {
byteOffset := 0
for _, chunk := range chunks {
for i, b := range chunk {
chunk[i] = evalOperator(op, b, key^byte(byteOffset))
byteOffset++
}
}
}
@ -79,13 +78,15 @@ func (x split) obfuscate(data []byte) *ast.BlockStmt {
// Generate indexes for cases chunk count + 1 decrypt case + 1 exit case
indexes := mathrand.Perm(len(chunks) + 2)
decryptKeyInitial := mathrand.Int()
decryptKeyInitial := genRandByte()
decryptKey := decryptKeyInitial
// Calculate decrypt key based on indexes and position. Ignore exit index
for i, index := range indexes[:len(indexes)-1] {
decryptKey ^= index * i
decryptKey ^= byte(index * i)
}
encryptChunks(chunks, decryptKey)
op := randOperator()
encryptChunks(chunks, op, decryptKey)
decryptIndex := indexes[len(indexes)-2]
exitIndex := indexes[len(indexes)-1]
@ -103,12 +104,18 @@ func (x split) obfuscate(data []byte) *ast.BlockStmt {
X: ah.Ident("data"),
Body: ah.BlockStmt(&ast.AssignStmt{
Lhs: []ast.Expr{ah.IndexExpr("data", ah.Ident("y"))},
Tok: token.XOR_ASSIGN,
Rhs: []ast.Expr{ah.CallExpr(ah.Ident("byte"), &ast.BinaryExpr{
X: ah.Ident("decryptKey"),
Op: token.XOR,
Y: ah.Ident("y"),
})},
Tok: token.ASSIGN,
Rhs: []ast.Expr{
operatorToReversedBinaryExpr(
op,
ah.IndexExpr("data", ah.Ident("y")),
ah.CallExpr(ah.Ident("byte"), &ast.BinaryExpr{
X: ah.Ident("decryptKey"),
Op: token.XOR,
Y: ah.Ident("y"),
}),
),
},
}),
},
),
@ -165,7 +172,7 @@ func (x split) obfuscate(data []byte) *ast.BlockStmt {
&ast.AssignStmt{
Lhs: []ast.Expr{ah.Ident("decryptKey")},
Tok: token.DEFINE,
Rhs: []ast.Expr{ah.IntLit(decryptKeyInitial)},
Rhs: []ast.Expr{ah.IntLit(int(decryptKeyInitial))},
},
&ast.ForStmt{
Init: &ast.AssignStmt{

@ -57,14 +57,16 @@ func generateSwapCount(dataLen int) int {
func (x swap) obfuscate(data []byte) *ast.BlockStmt {
swapCount := generateSwapCount(len(data))
shiftKey := byte(mathrand.Intn(math.MaxUint8))
shiftKey := genRandByte()
op := randOperator()
positions := genRandIntSlice(len(data), swapCount)
for i := len(positions) - 2; i >= 0; i -= 2 {
// Generate local key for xor based on random key and byte position
localKey := byte(i) + byte(positions[i]^positions[i+1]) + shiftKey
// Swap bytes from i+1 to i and xor using local key
data[positions[i]], data[positions[i+1]] = data[positions[i+1]]^localKey, data[positions[i]]^localKey
// Swap bytes from i+1 to i and encrypt using operator and local key
data[positions[i]], data[positions[i+1]] = evalOperator(op, data[positions[i+1]], localKey), evalOperator(op, data[positions[i]], localKey)
}
return ah.BlockStmt(
@ -127,20 +129,22 @@ func (x swap) obfuscate(data []byte) *ast.BlockStmt {
},
Tok: token.ASSIGN,
Rhs: []ast.Expr{
&ast.BinaryExpr{
X: ah.IndexExpr("data", ah.IndexExpr("positions", &ast.BinaryExpr{
X: ah.Ident("i"),
Op: token.ADD,
Y: ah.IntLit(1),
})),
Op: token.XOR,
Y: ah.Ident("localKey"),
},
&ast.BinaryExpr{
X: ah.IndexExpr("data", ah.IndexExpr("positions", ah.Ident("i"))),
Op: token.XOR,
Y: ah.Ident("localKey"),
},
operatorToReversedBinaryExpr(
op,
ah.IndexExpr("data",
ah.IndexExpr("positions", &ast.BinaryExpr{
X: ah.Ident("i"),
Op: token.ADD,
Y: ah.IntLit(1),
}),
),
ah.Ident("localKey"),
),
operatorToReversedBinaryExpr(
op,
ah.IndexExpr("data", ah.IndexExpr("positions", ah.Ident("i"))),
ah.Ident("localKey"),
),
},
},
),

@ -16,8 +16,9 @@ func (x xor) obfuscate(data []byte) *ast.BlockStmt {
key := make([]byte, len(data))
genRandBytes(key)
op := randOperator()
for i, b := range key {
data[i] = data[i] ^ b
data[i] = evalOperator(op, data[i], b)
}
return &ast.BlockStmt{List: []ast.Stmt{
@ -40,11 +41,7 @@ func (x xor) obfuscate(data []byte) *ast.BlockStmt {
&ast.AssignStmt{
Lhs: []ast.Expr{ah.IndexExpr("data", ah.Ident("i"))},
Tok: token.ASSIGN,
Rhs: []ast.Expr{&ast.BinaryExpr{
X: ah.IndexExpr("data", ah.Ident("i")),
Op: token.XOR,
Y: ah.Ident("b"),
}},
Rhs: []ast.Expr{operatorToReversedBinaryExpr(op, ah.IndexExpr("data", ah.Ident("i")), ah.Ident("b"))},
},
}},
},

@ -13,15 +13,14 @@ type xorSeed struct{}
var _ obfuscator = xorSeed{}
func (x xorSeed) obfuscate(data []byte) *ast.BlockStmt {
preSeed := make([]byte, 1)
genRandBytes(preSeed)
seed := preSeed[0]
seed := genRandByte()
originalSeed := seed
op := randOperator()
var callExpr *ast.CallExpr
for i, b := range data {
encB := b ^ seed
encB := evalOperator(op, b, seed)
seed += encB
if i == 0 {
@ -95,11 +94,7 @@ func (x xorSeed) obfuscate(data []byte) *ast.BlockStmt {
Lhs: []ast.Expr{ah.Ident("data")},
Tok: token.ASSIGN,
Rhs: []ast.Expr{
ah.CallExpr(ah.Ident("append"), ah.Ident("data"), &ast.BinaryExpr{
X: ah.Ident("x"),
Op: token.XOR,
Y: ah.Ident("seed"),
}),
ah.CallExpr(ah.Ident("append"), ah.Ident("data"), operatorToReversedBinaryExpr(op, ah.Ident("x"), ah.Ident("seed"))),
},
},
&ast.AssignStmt{

@ -18,8 +18,13 @@ func (x xorShuffle) obfuscate(data []byte) *ast.BlockStmt {
genRandBytes(key)
fullData := make([]byte, len(data)+len(key))
operators := make([]token.Token, len(fullData))
for i := range operators {
operators[i] = randOperator()
}
for i, b := range key {
fullData[i], fullData[i+len(data)] = data[i]^b, b
fullData[i], fullData[i+len(data)] = evalOperator(operators[i], data[i], b), b
}
shuffledIdxs := mathrand.Perm(len(fullData))
@ -31,11 +36,11 @@ func (x xorShuffle) obfuscate(data []byte) *ast.BlockStmt {
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])),
})
args = append(args, operatorToReversedBinaryExpr(
operators[i],
ah.IndexExpr("fullData", ah.IntLit(shuffledIdxs[i])),
ah.IndexExpr("fullData", ah.IntLit(shuffledIdxs[len(data)+i])),
))
}
return ah.BlockStmt(

@ -36,8 +36,8 @@ cmp stderr normal.stderr
# Check obfuscators
# Xor obfuscator. Detect a[i] = a[i] ^ b[i]
grep '^\s+\w+\[\w+\] = \w+\[\w+\] \^ \w+$' .obf-src/main/z0.go
# Xor obfuscator. Detect a[i] = a[i] (^|-|+) b[i]
grep '^\s+\w+\[\w+\] = \w+\[\w+\] [\^\-+] \w+$' .obf-src/main/z0.go
# Swap obfuscator. Detect [...]byte|uint16|uint32|uint64{...}
grep '^\s+\w+ := \[\.{3}\](byte|uint16|uint32|uint64)\{[0-9\s,]+\}$' .obf-src/main/z0.go
@ -45,8 +45,8 @@ 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
# XorShuffle obfuscator. Detect data = append(data, x (^|-|+) y...)
grep '^\s+\w+ = append\(\w+,(\s+\w+\[\d+\][\^\-+]\w+\[\d+\],?)+\)$' .obf-src/main/z0.go
# XorSeed obfuscator. Detect type decFunc func(byte) decFunc
grep '^\s+type \w+ func\(byte\) \w+$' .obf-src/main/z0.go

Loading…
Cancel
Save