实现 AdvancedObfuscator

dev
walon 2025-06-20 18:23:38 +08:00
parent 9c445213b5
commit f247719bc1
1 changed files with 155 additions and 91 deletions

View File

@ -6,6 +6,8 @@ using Obfuz.Utils;
using Obfuz.Data; using Obfuz.Data;
using UnityEngine; using UnityEngine;
using UnityEngine.Assertions; using UnityEngine.Assertions;
using JetBrains.Annotations;
using System;
namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
{ {
@ -72,122 +74,184 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
outputInsts.Add(inst); outputInsts.Add(inst);
} }
public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx) //public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
//{
// IRandom random = ctx.localRandom;
// ModuleConstFieldAllocator constFieldAllocator = ctx.constFieldAllocator;
// switch (inst.OpCode.Code)
// {
// case Code.Neg:
// {
// switch (op)
// {
// case EvalDataType.Int32:
// {
// // y = -x = (x * a + b) * (-ra) + b * ra;
// int a = random.NextInt() | 0x1;
// int ra = MathUtil.ModInverse32(a);
// Assert.AreEqual(1, a * ra);
// int b = random.NextInt();
// int b_ra = b * ra;
// float constProbability = 0.5f;
// LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstInt(-ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// return true;
// }
// case EvalDataType.Int64:
// {
// // y = -x = (x * a + b) * (-ra) + b * ra;
// long a = random.NextLong() | 0x1L;
// long ra = MathUtil.ModInverse64(a);
// Assert.AreEqual(1L, a * ra);
// long b = random.NextLong();
// long b_ra = b * ra;
// float constProbability = 0.5f;
// LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstLong(-ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// return true;
// }
// case EvalDataType.Float:
// {
// // y = -x = (x + a) * b; a = 0.0f, b = 1.0f,
// float a = 0.0f;
// float b = -1.0f;
// float constProbability = 0f;
// LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// return true;
// }
// case EvalDataType.Double:
// {
// // y = -x = (x + a) * b; a = 0.0, b = -1.0,
// double a = 0.0;
// double b = -1.0;
// float constProbability = 0f;
// LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// return true;
// }
// }
// break;
// }
// }
// return base.ObfuscateBasicUnaryOp(inst, op, ret, outputInsts, ctx);
//}
private bool GenerateIdentityTransformForArgument(Instruction inst, EvalDataType op, List<Instruction> outputInsts, ObfusMethodContext ctx)
{ {
DefaultMetadataImporter importer = ctx.importer;
EncryptionScopeInfo encryptionScope = ctx.encryptionScope;
IRandom random = ctx.localRandom; IRandom random = ctx.localRandom;
ModuleConstFieldAllocator constFieldAllocator = ctx.constFieldAllocator; ModuleConstFieldAllocator constFieldAllocator = ctx.constFieldAllocator;
switch (inst.OpCode.Code)
{
case Code.Neg:
{
switch (op) switch (op)
{ {
case EvalDataType.Int32: case EvalDataType.Int32:
{ {
// y = -x = (x * a + b) * (-ra) + b * ra; // = x + y = x + (y * a + b) * ra + (-b * ra)
int a = random.NextInt() | 0x1; int a = random.NextInt() | 0x1;
int ra = MathUtil.ModInverse32(a); int ra = MathUtil.ModInverse32(a);
Assert.AreEqual(1, a * ra);
int b = random.NextInt(); int b = random.NextInt();
int b_ra = b * ra; int b_ra = -b * ra;
float constProbability = 0.5f; float constProbability = 0.5f;
LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts); LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts); LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstInt(-ra, random, constProbability, constFieldAllocator, outputInsts); LoadConstInt(ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts); LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
outputInsts.Add(inst.Clone());
return true; return true;
} }
case EvalDataType.Int64: case EvalDataType.Int64:
{ {
// y = -x = (x * a + b) * (-ra) + b * ra; // = x + y = x + (y * a + b) * ra + (-b * ra)
long a = random.NextLong() | 0x1L; long a = random.NextLong() | 0x1L;
long ra = MathUtil.ModInverse64(a); long ra = MathUtil.ModInverse64(a);
Assert.AreEqual(1L, a * ra);
long b = random.NextLong(); long b = random.NextLong();
long b_ra = b * ra; long b_ra = -b * ra;
float constProbability = 0.5f; float constProbability = 0.5f;
LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts); LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts); LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstLong(-ra, random, constProbability, constFieldAllocator, outputInsts); LoadConstLong(ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts); LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
outputInsts.Add(inst.Clone());
return true; return true;
} }
case EvalDataType.Float: case EvalDataType.Float:
{ {
// y = -x = (x + a) * b; a = 0.0f, b = 1.0f, // = x + y = x + (y + a) * b; a = 0.0f, b = 1.0f
float a = 0.0f; float a = 0.0f;
float b = -1.0f; float b = 1.0f;
float constProbability = 0f; float constProbability = 0f;
LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts); LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts); LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
outputInsts.Add(inst.Clone());
return true; return true;
} }
case EvalDataType.Double: case EvalDataType.Double:
{ {
// y = -x = (x + a) * b; a = 0.0, b = -1.0, // = x + y = x + (y + a) * b; a = 0.0, b = 1.0
double a = 0.0; double a = 0.0;
double b = -1.0; double b = 1.0;
float constProbability = 0f; float constProbability = 0f;
LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts); LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add)); outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts); LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul)); outputInsts.Add(Instruction.Create(OpCodes.Mul));
return true; outputInsts.Add(inst.Clone());
}
}
return true; return true;
} }
default: return false; default: return false;
} }
} }
public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx) public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{ {
if (op1 != op2) return GenerateIdentityTransformForArgument(inst, op, outputInsts, ctx) || base.ObfuscateBasicUnaryOp(inst, op, ret, outputInsts, ctx);
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with different operand types: op1={op1}, op2={op2}, ret={ret}. This is a limitation of the BasicObfuscator.");
return false;
} }
return base.ObfuscateBasicBinOp(inst, op1, op2, ret, outputInsts, ctx); public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
return GenerateIdentityTransformForArgument(inst, op2, outputInsts, ctx) || base.ObfuscateBasicBinOp(inst, op1, op2, ret, outputInsts, ctx);
} }
public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx) public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{ {
return base.ObfuscateUnaryBitwiseOp(inst, op, ret, outputInsts, ctx); return GenerateIdentityTransformForArgument(inst, op, outputInsts, ctx) || base.ObfuscateUnaryBitwiseOp(inst, op, ret, outputInsts, ctx);
} }
public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx) public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{ {
if (op1 != op2) return GenerateIdentityTransformForArgument(inst, op2, outputInsts, ctx) || base.ObfuscateBinBitwiseOp(inst, op1 , op2, ret, outputInsts, ctx);
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with different operand types: op1={op1}, op2={op2}, ret={ret}. This is a limitation of the BasicObfuscator.");
return false;
}
return base.ObfuscateBinBitwiseOp(inst, op1 , op2, ret, outputInsts, ctx);
} }
public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx) public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{ {
if (op2 != EvalDataType.Int32) return GenerateIdentityTransformForArgument(inst, op2, outputInsts, ctx) || base.ObfuscateBitShiftOp(inst, op1, op2 , ret, outputInsts, ctx);
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with operand type {op2}. This is a limitation of the BasicObfuscator.");
return false;
}
return base.ObfuscateBitShiftOp(inst, op1, op2 , ret, outputInsts, ctx);
} }
} }
} }