mirror of
https://github.com/burrowers/garble.git
synced 2025-12-24 12:58:05 +08:00
cleanup
This commit is contained in:
@@ -140,6 +140,63 @@ func IndexExprByExpr(xExpr, indexExpr ast.Expr) *ast.IndexExpr {
|
|||||||
return &ast.IndexExpr{X: xExpr, Index: indexExpr}
|
return &ast.IndexExpr{X: xExpr, Index: indexExpr}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnaryExpr creates a unary expression with the given operator and operand
|
||||||
|
func UnaryExpr(op token.Token, x ast.Expr) *ast.UnaryExpr {
|
||||||
|
return &ast.UnaryExpr{
|
||||||
|
Op: op,
|
||||||
|
X: x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StarExpr creates a pointer type expression "*x"
|
||||||
|
func StarExpr(x ast.Expr) *ast.StarExpr {
|
||||||
|
return &ast.StarExpr{X: x}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayType creates an array type expression "[len]eltType"
|
||||||
|
func ArrayType(len ast.Expr, eltType ast.Expr) *ast.ArrayType {
|
||||||
|
return &ast.ArrayType{
|
||||||
|
Len: len,
|
||||||
|
Elt: eltType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteArrayType creates a byte array type "[len]byte"
|
||||||
|
func ByteArrayType(len int64) *ast.ArrayType {
|
||||||
|
lenLit := IntLit(int(len))
|
||||||
|
return ArrayType(lenLit, ast.NewIdent("byte"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteSliceType creates a byte slice type "[]byte"
|
||||||
|
func ByteSliceType() *ast.ArrayType {
|
||||||
|
return &ast.ArrayType{Elt: ast.NewIdent("byte")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BinaryExpr creates a binary expression "x op y"
|
||||||
|
func BinaryExpr(x ast.Expr, op token.Token, y ast.Expr) *ast.BinaryExpr {
|
||||||
|
return &ast.BinaryExpr{
|
||||||
|
X: x,
|
||||||
|
Op: op,
|
||||||
|
Y: y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintLit returns an ast.BasicLit of kind INT for uint64 values
|
||||||
|
func UintLit(value uint64) *ast.BasicLit {
|
||||||
|
return &ast.BasicLit{
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: fmt.Sprint(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field creates a field with names and type for function parameters or struct fields
|
||||||
|
func Field(typ ast.Expr, names ...*ast.Ident) *ast.Field {
|
||||||
|
return &ast.Field{
|
||||||
|
Names: names,
|
||||||
|
Type: typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ConstToAst(val constant.Value) ast.Expr {
|
func ConstToAst(val constant.Value) ast.Expr {
|
||||||
switch val.Kind() {
|
switch val.Kind() {
|
||||||
case constant.Bool:
|
case constant.Bool:
|
||||||
|
|||||||
@@ -226,9 +226,10 @@ func withPos(node ast.Node, pos token.Pos) ast.Node {
|
|||||||
func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
|
func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
|
||||||
obf := getNextObfuscator(obfRand, len(data))
|
obf := getNextObfuscator(obfRand, 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)
|
junkBytes := make([]byte, obfRand.Intn(maxStringJunkBytes-minStringJunkBytes)+minStringJunkBytes)
|
||||||
obfRand.Read(junkBytes)
|
obfRand.Read(junkBytes)
|
||||||
|
|
||||||
splitIdx := obfRand.Intn(len(junkBytes))
|
splitIdx := obfRand.Intn(len(junkBytes))
|
||||||
|
|
||||||
extKeys := randExtKeys(obfRand.Rand)
|
extKeys := randExtKeys(obfRand.Rand)
|
||||||
@@ -246,7 +247,7 @@ func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
|
|||||||
// }
|
// }
|
||||||
funcTyp := &ast.FuncType{
|
funcTyp := &ast.FuncType{
|
||||||
Params: &ast.FieldList{List: []*ast.Field{{
|
Params: &ast.FieldList{List: []*ast.Field{{
|
||||||
Type: &ast.ArrayType{Elt: ast.NewIdent("byte")},
|
Type: ah.ByteSliceType(),
|
||||||
}}},
|
}}},
|
||||||
Results: &ast.FieldList{List: []*ast.Field{{
|
Results: &ast.FieldList{List: []*ast.Field{{
|
||||||
Type: ast.NewIdent("string"),
|
Type: ast.NewIdent("string"),
|
||||||
@@ -256,26 +257,23 @@ func obfuscateString(obfRand *obfRand, data string) *ast.CallExpr {
|
|||||||
Type: &ast.FuncType{
|
Type: &ast.FuncType{
|
||||||
Params: &ast.FieldList{List: []*ast.Field{{
|
Params: &ast.FieldList{List: []*ast.Field{{
|
||||||
Names: []*ast.Ident{ast.NewIdent("x")},
|
Names: []*ast.Ident{ast.NewIdent("x")},
|
||||||
Type: &ast.ArrayType{Elt: ast.NewIdent("byte")},
|
Type: ah.ByteSliceType(),
|
||||||
}}},
|
}}},
|
||||||
Results: &ast.FieldList{List: []*ast.Field{{
|
Results: &ast.FieldList{List: []*ast.Field{{
|
||||||
Type: ast.NewIdent("string"),
|
Type: ast.NewIdent("string"),
|
||||||
}}},
|
}}},
|
||||||
},
|
},
|
||||||
Body: &ast.BlockStmt{List: []ast.Stmt{
|
Body: ah.BlockStmt(
|
||||||
&ast.ReturnStmt{Results: []ast.Expr{
|
ah.ReturnStmt(
|
||||||
&ast.CallExpr{
|
ah.CallExprByName("string",
|
||||||
Fun: ast.NewIdent("string"),
|
&ast.SliceExpr{
|
||||||
Args: []ast.Expr{
|
X: ast.NewIdent("x"),
|
||||||
&ast.SliceExpr{
|
Low: ah.IntLit(splitIdx),
|
||||||
X: ast.NewIdent("x"),
|
High: ah.IntLit(splitIdx + len(plainData)),
|
||||||
Low: ah.IntLit(splitIdx),
|
|
||||||
High: ah.IntLit(splitIdx + len(plainData)),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
}},
|
),
|
||||||
}},
|
),
|
||||||
}
|
}
|
||||||
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(obfRand.proxyDispatcher.HideValue(funcVal, funcTyp), ast.NewIdent("data"))))
|
||||||
return ah.LambdaCall(params, ast.NewIdent("string"), block, args)
|
return ah.LambdaCall(params, ast.NewIdent("string"), block, args)
|
||||||
@@ -289,17 +287,14 @@ func obfuscateByteSlice(obfRand *obfRand, isPointer bool, data []byte) *ast.Call
|
|||||||
params, args := extKeysToParams(obfRand, extKeys)
|
params, args := extKeysToParams(obfRand, extKeys)
|
||||||
|
|
||||||
if isPointer {
|
if isPointer {
|
||||||
block.List = append(block.List, ah.ReturnStmt(&ast.UnaryExpr{
|
block.List = append(block.List, ah.ReturnStmt(
|
||||||
Op: token.AND,
|
ah.UnaryExpr(token.AND, ast.NewIdent("data")),
|
||||||
X: ast.NewIdent("data"),
|
))
|
||||||
}))
|
return ah.LambdaCall(params, ah.StarExpr(ah.ByteSliceType()), block, args)
|
||||||
return ah.LambdaCall(params, &ast.StarExpr{
|
|
||||||
X: &ast.ArrayType{Elt: ast.NewIdent("byte")},
|
|
||||||
}, block, args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
block.List = append(block.List, ah.ReturnStmt(ast.NewIdent("data")))
|
block.List = append(block.List, ah.ReturnStmt(ast.NewIdent("data")))
|
||||||
return ah.LambdaCall(params, &ast.ArrayType{Elt: ast.NewIdent("byte")}, block, args)
|
return ah.LambdaCall(params, ah.ByteSliceType(), block, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length int64) *ast.CallExpr {
|
func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length int64) *ast.CallExpr {
|
||||||
@@ -309,10 +304,7 @@ func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length in
|
|||||||
block := obf.obfuscate(obfRand.Rand, data, extKeys)
|
block := obf.obfuscate(obfRand.Rand, data, extKeys)
|
||||||
params, args := extKeysToParams(obfRand, extKeys)
|
params, args := extKeysToParams(obfRand, extKeys)
|
||||||
|
|
||||||
arrayType := &ast.ArrayType{
|
arrayType := ah.ByteArrayType(length)
|
||||||
Len: ah.IntLit(int(length)),
|
|
||||||
Elt: ast.NewIdent("byte"),
|
|
||||||
}
|
|
||||||
|
|
||||||
sliceToArray := []ast.Stmt{
|
sliceToArray := []ast.Stmt{
|
||||||
&ast.DeclStmt{
|
&ast.DeclStmt{
|
||||||
@@ -328,26 +320,25 @@ func obfuscateByteArray(obfRand *obfRand, isPointer bool, data []byte, length in
|
|||||||
Key: ast.NewIdent("i"),
|
Key: ast.NewIdent("i"),
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
X: ast.NewIdent("data"),
|
X: ast.NewIdent("data"),
|
||||||
Body: &ast.BlockStmt{List: []ast.Stmt{
|
Body: ah.BlockStmt(
|
||||||
&ast.AssignStmt{
|
ah.AssignStmt(
|
||||||
Lhs: []ast.Expr{ah.IndexExpr("newdata", ast.NewIdent("i"))},
|
ah.IndexExprByExpr(ast.NewIdent("newdata"), ast.NewIdent("i")),
|
||||||
Tok: token.ASSIGN,
|
ah.IndexExprByExpr(ast.NewIdent("data"), ast.NewIdent("i")),
|
||||||
Rhs: []ast.Expr{ah.IndexExpr("data", ast.NewIdent("i"))},
|
),
|
||||||
},
|
),
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var retexpr ast.Expr = ast.NewIdent("newdata")
|
var retexpr ast.Expr = ast.NewIdent("newdata")
|
||||||
if isPointer {
|
if isPointer {
|
||||||
retexpr = &ast.UnaryExpr{X: retexpr, Op: token.AND}
|
retexpr = ah.UnaryExpr(token.AND, retexpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
sliceToArray = append(sliceToArray, ah.ReturnStmt(retexpr))
|
sliceToArray = append(sliceToArray, ah.ReturnStmt(retexpr))
|
||||||
block.List = append(block.List, sliceToArray...)
|
block.List = append(block.List, sliceToArray...)
|
||||||
|
|
||||||
if isPointer {
|
if isPointer {
|
||||||
return ah.LambdaCall(params, &ast.StarExpr{X: arrayType}, block, args)
|
return ah.LambdaCall(params, ah.StarExpr(arrayType), block, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ah.LambdaCall(params, arrayType, block, args)
|
return ah.LambdaCall(params, arrayType, block, args)
|
||||||
|
|||||||
@@ -15,48 +15,48 @@ import (
|
|||||||
ah "mvdan.cc/garble/internal/asthelper"
|
ah "mvdan.cc/garble/internal/asthelper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// extKeyRarity probability of using an external key.
|
// externalKeyProbability probability of using an external key.
|
||||||
// Larger value, greater probability of using an external key.
|
// Larger value, greater probability of using an external key.
|
||||||
// Must be between 0 and 1
|
// Must be between 0 and 1
|
||||||
type extKeyRarity float32
|
type externalKeyProbability float32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rareRarity extKeyRarity = 0.4
|
lowProb externalKeyProbability = 0.4
|
||||||
normalRarity extKeyRarity = 0.6
|
normalProb externalKeyProbability = 0.6
|
||||||
commonRarity extKeyRarity = 0.8
|
highProb externalKeyProbability = 0.8
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r extKeyRarity) Try(rand *mathrand.Rand) bool {
|
func (r externalKeyProbability) Try(rand *mathrand.Rand) bool {
|
||||||
return rand.Float32() < float32(r)
|
return rand.Float32() < float32(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// extKey contains all information about the external key
|
// externalKey contains all information about the external key
|
||||||
type extKey struct {
|
type externalKey struct {
|
||||||
name, typ string
|
name, typ string
|
||||||
value uint64
|
value uint64
|
||||||
bits int
|
bits int
|
||||||
refs int
|
refs int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *extKey) Type() *ast.Ident {
|
func (k *externalKey) Type() *ast.Ident {
|
||||||
return ast.NewIdent(k.typ)
|
return ast.NewIdent(k.typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *extKey) Name() *ast.Ident {
|
func (k *externalKey) Name() *ast.Ident {
|
||||||
return ast.NewIdent(k.name)
|
return ast.NewIdent(k.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *extKey) AddRef() {
|
func (k *externalKey) AddRef() {
|
||||||
k.refs++
|
k.refs++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *extKey) IsUsed() bool {
|
func (k *externalKey) IsUsed() bool {
|
||||||
return k.refs > 0
|
return k.refs > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// obfuscator takes a byte slice and converts it to a ast.BlockStmt
|
// obfuscator takes a byte slice and converts it to a ast.BlockStmt
|
||||||
type obfuscator interface {
|
type obfuscator interface {
|
||||||
obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt
|
obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -107,20 +107,18 @@ func evalOperator(t token.Token, x, y byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func operatorToReversedBinaryExpr(t token.Token, x, y ast.Expr) *ast.BinaryExpr {
|
func operatorToReversedBinaryExpr(t token.Token, x, y ast.Expr) *ast.BinaryExpr {
|
||||||
expr := &ast.BinaryExpr{X: x, Y: y}
|
var op token.Token
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case token.XOR:
|
case token.XOR:
|
||||||
expr.Op = token.XOR
|
op = token.XOR
|
||||||
case token.ADD:
|
case token.ADD:
|
||||||
expr.Op = token.SUB
|
op = token.SUB
|
||||||
case token.SUB:
|
case token.SUB:
|
||||||
expr.Op = token.ADD
|
op = token.ADD
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unknown operator: %s", t))
|
panic(fmt.Sprintf("unknown operator: %s", t))
|
||||||
}
|
}
|
||||||
|
return ah.BinaryExpr(x, op, y)
|
||||||
return expr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -149,44 +147,38 @@ var extKeyRanges = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// randExtKey generates a random external key with a unique name, type, value, and bitnesses
|
// randExtKey generates a random external key with a unique name, type, value, and bitnesses
|
||||||
func randExtKey(obfRand *mathrand.Rand, idx int) *extKey {
|
func randExtKey(rand *mathrand.Rand, idx int) *externalKey {
|
||||||
r := extKeyRanges[obfRand.Intn(len(extKeyRanges))]
|
r := extKeyRanges[rand.Intn(len(extKeyRanges))]
|
||||||
return &extKey{
|
return &externalKey{
|
||||||
name: "garbleExternalKey" + strconv.Itoa(idx),
|
name: "garbleExternalKey" + strconv.Itoa(idx),
|
||||||
typ: r.typ,
|
typ: r.typ,
|
||||||
value: obfRand.Uint64() & r.max,
|
value: rand.Uint64() & r.max,
|
||||||
bits: r.bits,
|
bits: r.bits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randExtKeys(obfRand *mathrand.Rand) []*extKey {
|
func randExtKeys(rand *mathrand.Rand) []*externalKey {
|
||||||
count := minExtKeyCount + obfRand.Intn(maxExtKeyCount-minExtKeyCount)
|
count := minExtKeyCount + rand.Intn(maxExtKeyCount-minExtKeyCount)
|
||||||
keys := make([]*extKey, count)
|
keys := make([]*externalKey, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
keys[i] = randExtKey(obfRand, i)
|
keys[i] = randExtKey(rand, i)
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// extKeysToParams converts a list of extKeys into a parameter list and argument expressions for function calls.
|
// extKeysToParams converts a list of extKeys into a parameter list and argument expressions for function calls.
|
||||||
// It ensures unused keys have placeholder names and sometimes use proxyDispatcher.HideValue for key values
|
// It ensures unused keys have placeholder names and sometimes use proxyDispatcher.HideValue for key values
|
||||||
func extKeysToParams(objRand *obfRand, keys []*extKey) (params *ast.FieldList, args []ast.Expr) {
|
func extKeysToParams(objRand *obfRand, keys []*externalKey) (params *ast.FieldList, args []ast.Expr) {
|
||||||
params = &ast.FieldList{}
|
params = &ast.FieldList{}
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
name := key.Name()
|
name := key.Name()
|
||||||
if !key.IsUsed() {
|
if !key.IsUsed() {
|
||||||
name.Name = "_"
|
name.Name = "_"
|
||||||
}
|
}
|
||||||
params.List = append(params.List, &ast.Field{
|
params.List = append(params.List, ah.Field(key.Type(), name))
|
||||||
Names: []*ast.Ident{name},
|
|
||||||
Type: key.Type(),
|
|
||||||
})
|
|
||||||
|
|
||||||
var extKeyExpr ast.Expr = &ast.BasicLit{
|
var extKeyExpr ast.Expr = ah.UintLit(key.value)
|
||||||
Kind: token.INT,
|
if lowProb.Try(objRand.Rand) {
|
||||||
Value: fmt.Sprint(key.value),
|
|
||||||
}
|
|
||||||
if rareRarity.Try(objRand.Rand) {
|
|
||||||
extKeyExpr = objRand.proxyDispatcher.HideValue(extKeyExpr, ast.NewIdent(key.typ))
|
extKeyExpr = objRand.proxyDispatcher.HideValue(extKeyExpr, ast.NewIdent(key.typ))
|
||||||
}
|
}
|
||||||
args = append(args, extKeyExpr)
|
args = append(args, extKeyExpr)
|
||||||
@@ -196,15 +188,11 @@ func extKeysToParams(objRand *obfRand, keys []*extKey) (params *ast.FieldList, a
|
|||||||
|
|
||||||
// extKeyToExpr converts an external key into an AST expression like:
|
// extKeyToExpr converts an external key into an AST expression like:
|
||||||
//
|
//
|
||||||
// uint8(key >> b)
|
// uint8(key >> b)
|
||||||
func extKeyToExpr(key *extKey, b int) ast.Expr {
|
func (key *externalKey) ToExpr(b int) ast.Expr {
|
||||||
var x ast.Expr = key.Name()
|
var x ast.Expr = key.Name()
|
||||||
if b > 0 {
|
if b > 0 {
|
||||||
x = &ast.BinaryExpr{
|
x = ah.BinaryExpr(x, token.SHR, ah.IntLit(b*8))
|
||||||
X: x,
|
|
||||||
Op: token.SHR,
|
|
||||||
Y: ah.IntLit(b * 8),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if key.typ != "uint8" {
|
if key.typ != "uint8" {
|
||||||
x = ah.CallExprByName("byte", x)
|
x = ah.CallExprByName("byte", x)
|
||||||
@@ -219,26 +207,23 @@ func extKeyToExpr(key *extKey, b int) ast.Expr {
|
|||||||
// data[<index>] = data[<index>] <random operator> byte(<external key> >> <random shift>) // repeated random times
|
// data[<index>] = data[<index>] <random operator> byte(<external key> >> <random shift>) // repeated random times
|
||||||
// return data
|
// return data
|
||||||
// }()
|
// }()
|
||||||
func dataToByteSliceWithExtKeys(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) ast.Expr {
|
func dataToByteSliceWithExtKeys(rand *mathrand.Rand, data []byte, extKeys []*externalKey) ast.Expr {
|
||||||
extKeyOpCount := minByteSliceExtKeyOps + obfRand.Intn(maxByteSliceExtKeyOps-minByteSliceExtKeyOps)
|
extKeyOpCount := minByteSliceExtKeyOps + rand.Intn(maxByteSliceExtKeyOps-minByteSliceExtKeyOps)
|
||||||
|
|
||||||
var stmts []ast.Stmt
|
var stmts []ast.Stmt
|
||||||
for i := 0; i < extKeyOpCount; i++ {
|
for i := 0; i < extKeyOpCount; i++ {
|
||||||
key := extKeys[obfRand.Intn(len(extKeys))]
|
key := extKeys[rand.Intn(len(extKeys))]
|
||||||
key.AddRef()
|
key.AddRef()
|
||||||
|
|
||||||
idx, op, b := obfRand.Intn(len(data)), randOperator(obfRand), obfRand.Intn(key.bits/8)
|
idx, op, b := rand.Intn(len(data)), randOperator(rand), rand.Intn(key.bits/8)
|
||||||
data[idx] = evalOperator(op, data[idx], byte(key.value>>(b*8)))
|
data[idx] = evalOperator(op, data[idx], byte(key.value>>(b*8)))
|
||||||
stmts = append(stmts, &ast.AssignStmt{
|
stmts = append(stmts, ah.AssignStmt(
|
||||||
Lhs: []ast.Expr{ah.IndexExpr("data", ah.IntLit(idx))},
|
ah.IndexExpr("data", ah.IntLit(idx)),
|
||||||
Tok: token.ASSIGN,
|
operatorToReversedBinaryExpr(op,
|
||||||
Rhs: []ast.Expr{
|
ah.IndexExpr("data", ah.IntLit(idx)),
|
||||||
operatorToReversedBinaryExpr(op,
|
key.ToExpr(b),
|
||||||
ah.IndexExpr("data", ah.IntLit(idx)),
|
),
|
||||||
extKeyToExpr(key, b),
|
))
|
||||||
),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// External keys can be applied several times to the same array element,
|
// External keys can be applied several times to the same array element,
|
||||||
@@ -246,26 +231,26 @@ func dataToByteSliceWithExtKeys(obfRand *mathrand.Rand, data []byte, extKeys []*
|
|||||||
slices.Reverse(stmts)
|
slices.Reverse(stmts)
|
||||||
|
|
||||||
stmts = append([]ast.Stmt{ah.AssignDefineStmt(ast.NewIdent("data"), ah.DataToByteSlice(data))}, append(stmts, ah.ReturnStmt(ast.NewIdent("data")))...)
|
stmts = append([]ast.Stmt{ah.AssignDefineStmt(ast.NewIdent("data"), ah.DataToByteSlice(data))}, append(stmts, ah.ReturnStmt(ast.NewIdent("data")))...)
|
||||||
return ah.LambdaCall(nil, &ast.ArrayType{Elt: ast.NewIdent("byte")}, ah.BlockStmt(stmts...), nil)
|
return ah.LambdaCall(nil, ah.ByteSliceType(), ah.BlockStmt(stmts...), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dataToByteSliceWithExtKeys scramble and turns a byte into an AST expression like:
|
// dataToByteSliceWithExtKeys scramble and turns a byte into an AST expression like:
|
||||||
//
|
//
|
||||||
// byte(<obfuscated value>) <random operator> byte(<external key> >> <random shift>)
|
// byte(<obfuscated value>) <random operator> byte(<external key> >> <random shift>)
|
||||||
func byteLitWithExtKey(obfRand *mathrand.Rand, val byte, extKeys []*extKey, rarity extKeyRarity) ast.Expr {
|
func byteLitWithExtKey(rand *mathrand.Rand, val byte, extKeys []*externalKey, extKeyProb externalKeyProbability) ast.Expr {
|
||||||
if !rarity.Try(obfRand) {
|
if !extKeyProb.Try(rand) {
|
||||||
return ah.IntLit(int(val))
|
return ah.IntLit(int(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
key := extKeys[obfRand.Intn(len(extKeys))]
|
key := extKeys[rand.Intn(len(extKeys))]
|
||||||
key.AddRef()
|
key.AddRef()
|
||||||
|
|
||||||
op, b := randOperator(obfRand), obfRand.Intn(key.bits/8)
|
op, b := randOperator(rand), rand.Intn(key.bits/8)
|
||||||
newVal := evalOperator(op, val, byte(key.value>>(b*8)))
|
newVal := evalOperator(op, val, byte(key.value>>(b*8)))
|
||||||
|
|
||||||
return operatorToReversedBinaryExpr(op,
|
return operatorToReversedBinaryExpr(op,
|
||||||
ah.CallExprByName("byte", ah.IntLit(int(newVal))),
|
ah.CallExprByName("byte", ah.IntLit(int(newVal))),
|
||||||
extKeyToExpr(key, b),
|
key.ToExpr(b),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type seed struct{}
|
|||||||
// check that the obfuscator interface is implemented
|
// check that the obfuscator interface is implemented
|
||||||
var _ obfuscator = seed{}
|
var _ obfuscator = seed{}
|
||||||
|
|
||||||
func (seed) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt {
|
func (seed) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt {
|
||||||
seed := byte(obfRand.Uint32())
|
seed := byte(obfRand.Uint32())
|
||||||
originalSeed := seed
|
originalSeed := seed
|
||||||
|
|
||||||
@@ -27,18 +27,18 @@ func (seed) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *a
|
|||||||
seed += encB
|
seed += encB
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
callExpr = ah.CallExpr(ast.NewIdent("fnc"), byteLitWithExtKey(obfRand, encB, extKeys, commonRarity))
|
callExpr = ah.CallExpr(ast.NewIdent("fnc"), byteLitWithExtKey(obfRand, encB, extKeys, highProb))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
callExpr = ah.CallExpr(callExpr, byteLitWithExtKey(obfRand, encB, extKeys, rareRarity))
|
callExpr = ah.CallExpr(callExpr, byteLitWithExtKey(obfRand, encB, extKeys, lowProb))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ah.BlockStmt(
|
return ah.BlockStmt(
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("seed")},
|
Lhs: []ast.Expr{ast.NewIdent("seed")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{ah.CallExprByName("byte", byteLitWithExtKey(obfRand, originalSeed, extKeys, commonRarity))},
|
Rhs: []ast.Expr{ah.CallExprByName("byte", byteLitWithExtKey(obfRand, originalSeed, extKeys, highProb))},
|
||||||
},
|
},
|
||||||
&ast.DeclStmt{
|
&ast.DeclStmt{
|
||||||
Decl: &ast.GenDecl{
|
Decl: &ast.GenDecl{
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ type shuffle struct{}
|
|||||||
// check that the obfuscator interface is implemented
|
// check that the obfuscator interface is implemented
|
||||||
var _ obfuscator = shuffle{}
|
var _ obfuscator = shuffle{}
|
||||||
|
|
||||||
func (shuffle) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt {
|
func (shuffle) obfuscate(rand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt {
|
||||||
key := make([]byte, len(data))
|
key := make([]byte, len(data))
|
||||||
obfRand.Read(key)
|
rand.Read(key)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
minIdxKeySize = 2
|
minIdxKeySize = 2
|
||||||
@@ -26,7 +26,7 @@ func (shuffle) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey)
|
|||||||
)
|
)
|
||||||
|
|
||||||
idxKeySize := minIdxKeySize
|
idxKeySize := minIdxKeySize
|
||||||
if tmp := obfRand.Intn(len(data)); tmp > idxKeySize {
|
if tmp := rand.Intn(len(data)); tmp > idxKeySize {
|
||||||
idxKeySize = tmp
|
idxKeySize = tmp
|
||||||
}
|
}
|
||||||
if idxKeySize > maxIdxKeySize {
|
if idxKeySize > maxIdxKeySize {
|
||||||
@@ -34,19 +34,19 @@ func (shuffle) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
idxKey := make([]byte, idxKeySize)
|
idxKey := make([]byte, idxKeySize)
|
||||||
obfRand.Read(idxKey)
|
rand.Read(idxKey)
|
||||||
|
|
||||||
fullData := make([]byte, len(data)+len(key))
|
fullData := make([]byte, len(data)+len(key))
|
||||||
operators := make([]token.Token, len(fullData))
|
operators := make([]token.Token, len(fullData))
|
||||||
for i := range operators {
|
for i := range operators {
|
||||||
operators[i] = randOperator(obfRand)
|
operators[i] = randOperator(rand)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, b := range key {
|
for i, b := range key {
|
||||||
fullData[i], fullData[i+len(data)] = evalOperator(operators[i], data[i], b), b
|
fullData[i], fullData[i+len(data)] = evalOperator(operators[i], data[i], b), b
|
||||||
}
|
}
|
||||||
|
|
||||||
shuffledIdxs := obfRand.Perm(len(fullData))
|
shuffledIdxs := rand.Perm(len(fullData))
|
||||||
|
|
||||||
shuffledFullData := make([]byte, len(fullData))
|
shuffledFullData := make([]byte, len(fullData))
|
||||||
for i, b := range fullData {
|
for i, b := range fullData {
|
||||||
@@ -55,7 +55,7 @@ func (shuffle) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey)
|
|||||||
|
|
||||||
args := []ast.Expr{ast.NewIdent("data")}
|
args := []ast.Expr{ast.NewIdent("data")}
|
||||||
for i := range data {
|
for i := range data {
|
||||||
keyIdx := obfRand.Intn(idxKeySize)
|
keyIdx := rand.Intn(idxKeySize)
|
||||||
k := int(idxKey[keyIdx])
|
k := int(idxKey[keyIdx])
|
||||||
|
|
||||||
args = append(args, operatorToReversedBinaryExpr(
|
args = append(args, operatorToReversedBinaryExpr(
|
||||||
@@ -69,12 +69,12 @@ func (shuffle) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey)
|
|||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("fullData")},
|
Lhs: []ast.Expr{ast.NewIdent("fullData")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(obfRand, shuffledFullData, extKeys)},
|
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(rand, shuffledFullData, extKeys)},
|
||||||
},
|
},
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("idxKey")},
|
Lhs: []ast.Expr{ast.NewIdent("idxKey")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(obfRand, idxKey, extKeys)},
|
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(rand, idxKey, extKeys)},
|
||||||
},
|
},
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("data")},
|
Lhs: []ast.Expr{ast.NewIdent("data")},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand"
|
||||||
|
|
||||||
ah "mvdan.cc/garble/internal/asthelper"
|
ah "mvdan.cc/garble/internal/asthelper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,11 +16,11 @@ type simple struct{}
|
|||||||
// check that the obfuscator interface is implemented
|
// check that the obfuscator interface is implemented
|
||||||
var _ obfuscator = simple{}
|
var _ obfuscator = simple{}
|
||||||
|
|
||||||
func (simple) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt {
|
func (simple) obfuscate(rand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt {
|
||||||
key := make([]byte, len(data))
|
key := make([]byte, len(data))
|
||||||
obfRand.Read(key)
|
rand.Read(key)
|
||||||
|
|
||||||
op := randOperator(obfRand)
|
op := randOperator(rand)
|
||||||
for i, b := range key {
|
for i, b := range key {
|
||||||
data[i] = evalOperator(op, data[i], b)
|
data[i] = evalOperator(op, data[i], b)
|
||||||
}
|
}
|
||||||
@@ -28,12 +29,12 @@ func (simple) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey)
|
|||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("key")},
|
Lhs: []ast.Expr{ast.NewIdent("key")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(obfRand, key, extKeys)},
|
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(rand, key, extKeys)},
|
||||||
},
|
},
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("data")},
|
Lhs: []ast.Expr{ast.NewIdent("data")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(obfRand, data, extKeys)},
|
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(rand, data, extKeys)},
|
||||||
},
|
},
|
||||||
&ast.RangeStmt{
|
&ast.RangeStmt{
|
||||||
Key: ast.NewIdent("i"),
|
Key: ast.NewIdent("i"),
|
||||||
|
|||||||
@@ -66,33 +66,33 @@ func encryptChunks(chunks [][]byte, op token.Token, key byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (split) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt {
|
func (split) obfuscate(rand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt {
|
||||||
var chunks [][]byte
|
var chunks [][]byte
|
||||||
// Short arrays should be divided into single-byte fragments
|
// Short arrays should be divided into single-byte fragments
|
||||||
if len(data)/maxChunkSize < minCaseCount {
|
if len(data)/maxChunkSize < minCaseCount {
|
||||||
chunks = splitIntoOneByteChunks(data)
|
chunks = splitIntoOneByteChunks(data)
|
||||||
} else {
|
} else {
|
||||||
chunks = splitIntoRandomChunks(obfRand, data)
|
chunks = splitIntoRandomChunks(rand, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate indexes for cases chunk count + 1 decrypt case + 1 exit case
|
// Generate indexes for cases chunk count + 1 decrypt case + 1 exit case
|
||||||
indexes := obfRand.Perm(len(chunks) + 2)
|
indexes := rand.Perm(len(chunks) + 2)
|
||||||
|
|
||||||
decryptKeyInitial := byte(obfRand.Uint32())
|
decryptKeyInitial := byte(rand.Uint32())
|
||||||
decryptKey := decryptKeyInitial
|
decryptKey := decryptKeyInitial
|
||||||
// Calculate decrypt key based on indexes and position. Ignore exit index
|
// Calculate decrypt key based on indexes and position. Ignore exit index
|
||||||
for i, index := range indexes[:len(indexes)-1] {
|
for i, index := range indexes[:len(indexes)-1] {
|
||||||
decryptKey ^= byte(index * i)
|
decryptKey ^= byte(index * i)
|
||||||
}
|
}
|
||||||
|
|
||||||
op := randOperator(obfRand)
|
op := randOperator(rand)
|
||||||
encryptChunks(chunks, op, decryptKey)
|
encryptChunks(chunks, op, decryptKey)
|
||||||
|
|
||||||
decryptIndex := indexes[len(indexes)-2]
|
decryptIndex := indexes[len(indexes)-2]
|
||||||
exitIndex := indexes[len(indexes)-1]
|
exitIndex := indexes[len(indexes)-1]
|
||||||
switchCases := []ast.Stmt{&ast.CaseClause{
|
switchCases := []ast.Stmt{&ast.CaseClause{
|
||||||
List: []ast.Expr{ah.IntLit(decryptIndex)},
|
List: []ast.Expr{ah.IntLit(decryptIndex)},
|
||||||
Body: shuffleStmts(obfRand,
|
Body: shuffleStmts(rand,
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("i")},
|
Lhs: []ast.Expr{ast.NewIdent("i")},
|
||||||
Tok: token.ASSIGN,
|
Tok: token.ASSIGN,
|
||||||
@@ -131,15 +131,15 @@ func (split) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(chunk) != 1 {
|
if len(chunk) != 1 {
|
||||||
appendCallExpr.Args = append(appendCallExpr.Args, dataToByteSliceWithExtKeys(obfRand, chunk, extKeys))
|
appendCallExpr.Args = append(appendCallExpr.Args, dataToByteSliceWithExtKeys(rand, chunk, extKeys))
|
||||||
appendCallExpr.Ellipsis = 1
|
appendCallExpr.Ellipsis = 1
|
||||||
} else {
|
} else {
|
||||||
appendCallExpr.Args = append(appendCallExpr.Args, byteLitWithExtKey(obfRand, chunk[0], extKeys, rareRarity))
|
appendCallExpr.Args = append(appendCallExpr.Args, byteLitWithExtKey(rand, chunk[0], extKeys, lowProb))
|
||||||
}
|
}
|
||||||
|
|
||||||
switchCases = append(switchCases, &ast.CaseClause{
|
switchCases = append(switchCases, &ast.CaseClause{
|
||||||
List: []ast.Expr{ah.IntLit(index)},
|
List: []ast.Expr{ah.IntLit(index)},
|
||||||
Body: shuffleStmts(obfRand,
|
Body: shuffleStmts(rand,
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("i")},
|
Lhs: []ast.Expr{ast.NewIdent("i")},
|
||||||
Tok: token.ASSIGN,
|
Tok: token.ASSIGN,
|
||||||
@@ -168,7 +168,7 @@ func (split) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *
|
|||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("decryptKey")},
|
Lhs: []ast.Expr{ast.NewIdent("decryptKey")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{ah.CallExprByName("int", byteLitWithExtKey(obfRand, decryptKeyInitial, extKeys, normalRarity))},
|
Rhs: []ast.Expr{ah.CallExprByName("int", byteLitWithExtKey(rand, decryptKeyInitial, extKeys, normalProb))},
|
||||||
},
|
},
|
||||||
&ast.ForStmt{
|
&ast.ForStmt{
|
||||||
Init: &ast.AssignStmt{
|
Init: &ast.AssignStmt{
|
||||||
@@ -199,7 +199,7 @@ func (split) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *
|
|||||||
},
|
},
|
||||||
&ast.SwitchStmt{
|
&ast.SwitchStmt{
|
||||||
Tag: ast.NewIdent("i"),
|
Tag: ast.NewIdent("i"),
|
||||||
Body: ah.BlockStmt(shuffleStmts(obfRand, switchCases...)...),
|
Body: ah.BlockStmt(shuffleStmts(rand, switchCases...)...),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -58,13 +58,13 @@ func generateSwapCount(obfRand *mathrand.Rand, dataLen int) int {
|
|||||||
return swapCount
|
return swapCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (swap) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *ast.BlockStmt {
|
func (swap) obfuscate(rand *mathrand.Rand, data []byte, extKeys []*externalKey) *ast.BlockStmt {
|
||||||
swapCount := generateSwapCount(obfRand, len(data))
|
swapCount := generateSwapCount(rand, len(data))
|
||||||
shiftKey := byte(obfRand.Uint32())
|
shiftKey := byte(rand.Uint32())
|
||||||
|
|
||||||
op := randOperator(obfRand)
|
op := randOperator(rand)
|
||||||
|
|
||||||
positions := genRandIntSlice(obfRand, len(data), swapCount)
|
positions := genRandIntSlice(rand, len(data), swapCount)
|
||||||
for i := len(positions) - 2; i >= 0; i -= 2 {
|
for i := len(positions) - 2; i >= 0; i -= 2 {
|
||||||
// Generate local key for xor based on random key and byte position
|
// Generate local key for xor based on random key and byte position
|
||||||
localKey := byte(i) + byte(positions[i]^positions[i+1]) + shiftKey
|
localKey := byte(i) + byte(positions[i]^positions[i+1]) + shiftKey
|
||||||
@@ -76,7 +76,7 @@ func (swap) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *a
|
|||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("data")},
|
Lhs: []ast.Expr{ast.NewIdent("data")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(obfRand, data, extKeys)},
|
Rhs: []ast.Expr{dataToByteSliceWithExtKeys(rand, data, extKeys)},
|
||||||
},
|
},
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
Lhs: []ast.Expr{ast.NewIdent("positions")},
|
Lhs: []ast.Expr{ast.NewIdent("positions")},
|
||||||
@@ -118,7 +118,7 @@ func (swap) obfuscate(obfRand *mathrand.Rand, data []byte, extKeys []*extKey) *a
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Op: token.ADD,
|
Op: token.ADD,
|
||||||
Y: byteLitWithExtKey(obfRand, shiftKey, extKeys, commonRarity),
|
Y: byteLitWithExtKey(rand, shiftKey, extKeys, highProb),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
&ast.AssignStmt{
|
&ast.AssignStmt{
|
||||||
|
|||||||
Reference in New Issue
Block a user