diff --git a/Editor/EncryptionVM/Instructions/MultipleInstruction.cs b/Editor/EncryptionVM/Instructions/MultipleInstruction.cs index 2635f5e..af9b2eb 100644 --- a/Editor/EncryptionVM/Instructions/MultipleInstruction.cs +++ b/Editor/EncryptionVM/Instructions/MultipleInstruction.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using Obfuz.Utils; using System; using System.Collections.Generic; @@ -14,7 +15,7 @@ namespace Obfuz.EncryptionVM.Instructions { _multiValue = addValue; _opKeyIndex = opKeyIndex; - _revertMultiValue = (int)ModInverseOdd((uint)addValue); + _revertMultiValue = MathUtil.ModInverse32(addValue); Verify(); } @@ -24,23 +25,6 @@ namespace Obfuz.EncryptionVM.Instructions Assert.AreEqual(a, a * _multiValue * _revertMultiValue); } - public static uint ModInverseOdd(uint a) - { - if (a % 2 == 0) - throw new ArgumentException("Input must be an odd number.", nameof(a)); - - uint x = 1; // 初始解:x₀ = 1 (mod 2) - for (int i = 0; i < 5; i++) // 迭代5次(2^1 → 2^32) - { - int shift = 2 << i; // 当前模数为 2^(2^(i+1)) - ulong mod = 1UL << shift; // 使用 ulong 避免溢出 - ulong ax = (ulong)a * x; // 计算 a*x(64位避免截断) - ulong term = (2 - ax) % mod; - x = (uint)((x * term) % mod); // 更新 x,结果截断为 uint - } - return x; // 最终解为 x₅ mod 2^32 - } - public override int Encrypt(int value, int[] secretKey, int salt) { return value * _multiValue + secretKey[_opKeyIndex] + salt; diff --git a/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs b/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs index b6fd973..62fc609 100644 --- a/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs +++ b/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Obfuz.Utils; +using System.Collections.Generic; namespace Obfuz.EncryptionVM.Instructions { @@ -17,7 +18,7 @@ namespace Obfuz.EncryptionVM.Instructions public MultipleRotateXorInstruction(int multipleValue, int index1, int rotateBitNum, int xorValue) { _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); + _revertMultipleValue = MathUtil.ModInverse32(multipleValue); _index1 = index1; _rotateBitNum = rotateBitNum; _xorValue = xorValue; diff --git a/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs b/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs index 512a408..a8a6932 100644 --- a/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs +++ b/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Obfuz.Utils; +using System.Collections.Generic; namespace Obfuz.EncryptionVM.Instructions { @@ -17,7 +18,7 @@ namespace Obfuz.EncryptionVM.Instructions public MultipleXorRotateInstruction(int multipleValue, int index1, int xorValue, int rotateBitNum) { _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); + _revertMultipleValue = MathUtil.ModInverse32(multipleValue); _index1 = index1; _rotateBitNum = rotateBitNum; _xorValue = xorValue; diff --git a/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs b/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs index 8652278..ab82331 100644 --- a/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs +++ b/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Obfuz.Utils; +using System.Collections.Generic; namespace Obfuz.EncryptionVM.Instructions { @@ -17,7 +18,7 @@ namespace Obfuz.EncryptionVM.Instructions public XorMultipleRotateInstruction(int xorValue, int multipleValue, int index1, int rotateBitNum) { _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); + _revertMultipleValue = MathUtil.ModInverse32(multipleValue); _index1 = index1; _rotateBitNum = rotateBitNum; _xorValue = xorValue; diff --git a/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs b/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs index 917c035..d53ecc7 100644 --- a/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs +++ b/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs @@ -1,5 +1,6 @@ using dnlib.DotNet; using Obfuz.Conf; +using Obfuz.Settings; using Obfuz.Utils; using System; using System.Collections.Generic; @@ -23,12 +24,15 @@ namespace Obfuz.ObfusPasses.ExprObfus { class ObfuscationRule : IRule { - public bool? obfuscate; + public ObfuscationLevel? obfuscationLevel; + public float? obfuscationPercentage; public void InheritParent(ObfuscationRule parentRule) { - if (obfuscate == null) - obfuscate = parentRule.obfuscate; + if (obfuscationLevel == null) + obfuscationLevel = parentRule.obfuscationLevel; + if (obfuscationPercentage == null) + obfuscationPercentage = parentRule.obfuscationPercentage; } } @@ -46,7 +50,8 @@ namespace Obfuz.ObfusPasses.ExprObfus private static readonly ObfuscationRule s_default = new ObfuscationRule() { - obfuscate = false, + obfuscationLevel = ObfuscationLevel.None, + obfuscationPercentage = 0.5f, }; private readonly XmlAssemblyTypeMethodRuleParser _xmlParser; @@ -66,12 +71,21 @@ namespace Obfuz.ObfusPasses.ExprObfus _xmlParser.InheritParentRules(s_default); } + private ObfuscationLevel ParseObfuscationLevel(string str) + { + return (ObfuscationLevel)Enum.Parse(typeof(ObfuscationLevel), str); + } + private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele) { var rule = new ObfuscationRule(); - if (ele.HasAttribute("obfuscate")) + if (ele.HasAttribute("obfuscationLevel")) { - rule.obfuscate = ConfigUtil.ParseBool(ele.GetAttribute("obfuscate")); + rule.obfuscationLevel = ParseObfuscationLevel(ele.GetAttribute("obfuscationLevel")); + } + if (ele.HasAttribute("obfuscationPercentage")) + { + rule.obfuscationPercentage = float.Parse(ele.GetAttribute("obfuscationPercentage")); } return rule; } @@ -89,7 +103,7 @@ namespace Obfuz.ObfusPasses.ExprObfus public override bool NeedObfuscate(MethodDef method) { ObfuscationRule rule = GetMethodObfuscationRule(method); - return rule.obfuscate == true; + return rule.obfuscationLevel.Value > ObfuscationLevel.None; } } } diff --git a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs index 4e83e7f..b539673 100644 --- a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs +++ b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs @@ -1,5 +1,6 @@ using dnlib.DotNet; using dnlib.DotNet.Emit; +using Obfuz.Data; using Obfuz.Emit; using Obfuz.ObfusPasses.ExprObfus.Obfuscators; using Obfuz.Settings; @@ -10,15 +11,27 @@ using UnityEngine; namespace Obfuz.ObfusPasses.ExprObfus { + class ObfusMethodContext + { + public MethodDef method; + public EvalStackCalculator evalStackCalculator; + public LocalVariableAllocator localVariableAllocator; + public IRandom localRandom; + public EncryptionScopeInfo encryptionScope; + public DefaultMetadataImporter importer; + public ModuleConstFieldAllocator constFieldAllocator; + } + class ExprObfusPass : ObfuscationMethodPassBase { private readonly ExprObfuscationSettingsFacade _settings; + private readonly IObfuscator _obfuscator; private IObfuscationPolicy _obfuscationPolicy; - private IObfuscator _obfuscator; public ExprObfusPass(ExprObfuscationSettingsFacade settings) { _settings = settings; + _obfuscator = CreateObfuscator(_settings.obfuscationLevel); } public override ObfuscationPassType Type => ObfuscationPassType.ExprObfus; @@ -29,17 +42,16 @@ namespace Obfuz.ObfusPasses.ExprObfus _obfuscationPolicy = new ConfigurableObfuscationPolicy( ctx.coreSettings.assembliesToObfuscate, _settings.ruleFiles); - _obfuscator = CreateObfuscator(ctx.encryptionScopeProvider, ctx.moduleEntityManager, _settings.obfuscationLevel); } - private IObfuscator CreateObfuscator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager, ObfuscationLevel level) + private IObfuscator CreateObfuscator(ObfuscationLevel level) { switch (level) { case ObfuscationLevel.None: return new NoneObfuscator(); - case ObfuscationLevel.Basic:return new BasicObfuscator(encryptionScopeProvider, moduleEntityManager); - case ObfuscationLevel.Advanced: return new AdvancedObfuscator(encryptionScopeProvider, moduleEntityManager); - case ObfuscationLevel.MostAdvanced: return new MostAdvancedObfuscator(encryptionScopeProvider, moduleEntityManager); + case ObfuscationLevel.Basic:return new BasicObfuscator(); + case ObfuscationLevel.Advanced: return new AdvancedObfuscator(); + case ObfuscationLevel.MostAdvanced: return new MostAdvancedObfuscator(); default: throw new System.ArgumentOutOfRangeException(nameof(level), level, "Unknown obfuscation level"); } } @@ -54,14 +66,15 @@ namespace Obfuz.ObfusPasses.ExprObfus return _settings.obfuscationLevel != ObfuscationLevel.None && _obfuscationPolicy.NeedObfuscate(method); } - protected bool TryObfuscateInstruction(MethodDef callingMethod, InstructionParameterInfo pi, LocalVariableAllocator localVariableAllocator, IRandom localRandom, Instruction inst, List outputInstructions) + protected bool TryObfuscateInstruction(InstructionParameterInfo pi, Instruction inst, List outputInstructions, ObfusMethodContext ctx) { - Debug.Log($"Obfuscating instruction: {inst} in method: {callingMethod.FullName}"); + //Debug.Log($"Obfuscating instruction: {inst} in method: {ctx.method.FullName}"); + var localRandom = ctx.localRandom; switch (inst.OpCode.Code) { case Code.Neg: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicUnaryOp(callingMethod, inst, pi.op1, pi.retType, localVariableAllocator, outputInstructions); + return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicUnaryOp(inst, pi.op1, pi.retType, outputInstructions, ctx); } case Code.Add: case Code.Sub: @@ -71,23 +84,23 @@ namespace Obfuz.ObfusPasses.ExprObfus case Code.Rem: case Code.Rem_Un: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicBinOp(callingMethod, inst, pi.op1, pi.op2, pi.retType, localVariableAllocator, outputInstructions); + return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicBinOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); } case Code.And: case Code.Or: case Code.Xor: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBinBitwiseOp(callingMethod, inst, pi.op1, pi.op2, pi.retType, localVariableAllocator, outputInstructions); + return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBinBitwiseOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); } case Code.Not: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateUnaryBitwiseOp(callingMethod, inst, pi.op1, pi.retType, localVariableAllocator, outputInstructions); + return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateUnaryBitwiseOp(inst, pi.op1, pi.retType, outputInstructions, ctx); } case Code.Shl: case Code.Shr: case Code.Shr_Un: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBitShiftOp(callingMethod, inst, pi.op1, pi.op2, pi.retType, localVariableAllocator, outputInstructions); + return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBitShiftOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); } } return false; @@ -96,13 +109,22 @@ namespace Obfuz.ObfusPasses.ExprObfus protected override void ObfuscateData(MethodDef method) { Debug.Log($"Obfuscating method: {method.FullName} with ExprObfusPass"); - var calc = new EvalStackCalculator(method); - var localVarAllocator = new LocalVariableAllocator(method); IList instructions = method.Body.Instructions; var outputInstructions = new List(); var totalFinalInstructions = new List(); - var encryptionScope = ObfuscationPassContext.Current.encryptionScopeProvider.GetScope(method.Module); - var localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method)); + + ObfuscationPassContext ctx = ObfuscationPassContext.Current; + var calc = new EvalStackCalculator(method); + var encryptionScope = ctx.encryptionScopeProvider.GetScope(method.Module); + var obfusMethodCtx = new ObfusMethodContext + { + method = method, + evalStackCalculator = calc, + localVariableAllocator = new LocalVariableAllocator(method), + encryptionScope = encryptionScope, + localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method)), + importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, ctx.encryptionScopeProvider), + }; for (int i = 0; i < instructions.Count; i++) { Instruction inst = instructions[i]; @@ -110,7 +132,7 @@ namespace Obfuz.ObfusPasses.ExprObfus if (calc.TryGetParameterInfo(inst, out InstructionParameterInfo pi)) { outputInstructions.Clear(); - if (TryObfuscateInstruction(method, pi, localVarAllocator, localRandom, inst, outputInstructions)) + if (TryObfuscateInstruction(pi, inst, outputInstructions, obfusMethodCtx)) { // current instruction may be the target of control flow instruction, so we can't remove it directly. // we replace it with nop now, then remove it in CleanUpInstructionPass diff --git a/Editor/ObfusPasses/ExprObfus/IObfuscator.cs b/Editor/ObfusPasses/ExprObfus/IObfuscator.cs index 0a377b2..f43485b 100644 --- a/Editor/ObfusPasses/ExprObfus/IObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/IObfuscator.cs @@ -7,23 +7,23 @@ namespace Obfuz.ObfusPasses.ExprObfus { interface IObfuscator { - bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); - bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); - bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); - bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); - bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); } abstract class ObfuscatorBase : IObfuscator { - public abstract bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); - public abstract bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); - public abstract bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); - public abstract bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); - public abstract bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts); + public abstract bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); + public abstract bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); + public abstract bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); + public abstract bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); + public abstract bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx); } } diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs index 968da37..187b2f9 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs @@ -1,12 +1,190 @@ -using Obfuz.Emit; +using dnlib.DotNet.Emit; +using dnlib.DotNet; +using Obfuz.Emit; +using System.Collections.Generic; +using Obfuz.Utils; +using Obfuz.Data; +using UnityEngine; namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators { class AdvancedObfuscator : BasicObfuscator { - public AdvancedObfuscator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager) - : base(encryptionScopeProvider, moduleEntityManager) + + private void LoadConstInt(int a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List outputInsts) { + Instruction inst; + if (random.NextInPercentage(constProbability)) + { + inst = Instruction.Create(OpCodes.Ldc_I4, a); + } + else + { + FieldDef field = constFieldAllocator.Allocate(a); + inst = Instruction.Create(OpCodes.Ldsfld, field); + } + outputInsts.Add(inst); + } + + private void LoadConstLong(long a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List outputInsts) + { + Instruction inst; + if (random.NextInPercentage(constProbability)) + { + inst = Instruction.Create(OpCodes.Ldc_I8, a); + } + else + { + FieldDef field = constFieldAllocator.Allocate(a); + inst = Instruction.Create(OpCodes.Ldsfld, field); + } + outputInsts.Add(inst); + } + + private void LoadConstFloat(float a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List outputInsts) + { + Instruction inst; + if (random.NextInPercentage(constProbability)) + { + inst = Instruction.Create(OpCodes.Ldc_R4, a); + } + else + { + FieldDef field = constFieldAllocator.Allocate(a); + inst = Instruction.Create(OpCodes.Ldsfld, field); + } + outputInsts.Add(inst); + } + + private void LoadConstDouble(double a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List outputInsts) + { + Instruction inst; + if (random.NextInPercentage(constProbability)) + { + inst = Instruction.Create(OpCodes.Ldc_R8, a); + } + else + { + FieldDef field = constFieldAllocator.Allocate(a); + inst = Instruction.Create(OpCodes.Ldsfld, field); + } + outputInsts.Add(inst); + } + + public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) + { + DefaultMetadataImporter importer = ctx.importer; + EncryptionScopeInfo encryptionScope = ctx.encryptionScope; + 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); + 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); + 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; + } + } + return true; + } + default: return false; + } + } + + public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) + { + if (op1 != op2) + { + 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 ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) + { + return base.ObfuscateUnaryBitwiseOp(inst, op, ret, outputInsts, ctx); + } + + public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) + { + if (op1 != op2) + { + 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 outputInsts, ObfusMethodContext ctx) + { + if (op2 != EvalDataType.Int32) + { + 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); } } } diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/BasicObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/BasicObfuscator.cs index 19ed618..8332a41 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/BasicObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/Obfuscators/BasicObfuscator.cs @@ -14,20 +14,6 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators class BasicObfuscator : ObfuscatorBase { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly GroupByModuleEntityManager _moduleEntityManager; - - public BasicObfuscator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager) - { - _encryptionScopeProvider = encryptionScopeProvider; - _moduleEntityManager = moduleEntityManager; - } - - private DefaultMetadataImporter GetModuleMetadataImporter(ModuleDef module) - { - return _moduleEntityManager.GetDefaultModuleMetadataImporter(module, _encryptionScopeProvider); - } - private IMethod GetMethod(DefaultMetadataImporter importer, Code code, EvalDataType op1) { switch (code) @@ -183,10 +169,9 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators } } - public override bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { - DefaultMetadataImporter importer = GetModuleMetadataImporter(method.Module); - IMethod opMethod = GetMethod(importer, inst.OpCode.Code, op); + IMethod opMethod = GetMethod(ctx.importer, inst.OpCode.Code, op); if (opMethod == null) { return false; @@ -195,15 +180,14 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators return true; } - public override bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { if (op1 != op2) { 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; } - DefaultMetadataImporter importer = GetModuleMetadataImporter(method.Module); - IMethod opMethod = GetMethod(importer, inst.OpCode.Code, op1); + IMethod opMethod = GetMethod(ctx.importer, inst.OpCode.Code, op1); if (opMethod == null) { return false; @@ -212,10 +196,9 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators return true; } - public override bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { - DefaultMetadataImporter importer = GetModuleMetadataImporter(method.Module); - IMethod opMethod = GetMethod(importer, inst.OpCode.Code, op); + IMethod opMethod = GetMethod(ctx.importer, inst.OpCode.Code, op); if (opMethod == null) { return false; @@ -224,15 +207,14 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators return true; } - public override bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { if (op1 != op2) { 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; } - DefaultMetadataImporter importer = GetModuleMetadataImporter(method.Module); - IMethod opMethod = GetMethod(importer, inst.OpCode.Code, op1); + IMethod opMethod = GetMethod(ctx.importer, inst.OpCode.Code, op1); if (opMethod == null) { return false; @@ -241,15 +223,14 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators return true; } - public override bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { if (op2 != EvalDataType.Int32) { Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with operand type {op2}. This is a limitation of the BasicObfuscator."); return false; } - DefaultMetadataImporter importer = GetModuleMetadataImporter(method.Module); - IMethod opMethod = GetMethod(importer, inst.OpCode.Code, op1); + IMethod opMethod = GetMethod(ctx.importer, inst.OpCode.Code, op1); if (opMethod == null) { return false; diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/MostAdvancedObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/MostAdvancedObfuscator.cs index 0b0febf..a3d0c72 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/MostAdvancedObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/Obfuscators/MostAdvancedObfuscator.cs @@ -4,9 +4,5 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators { class MostAdvancedObfuscator : AdvancedObfuscator { - public MostAdvancedObfuscator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager) - : base(encryptionScopeProvider, moduleEntityManager) - { - } } } diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs index abd0167..82ce128 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs @@ -7,27 +7,27 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators { class NoneObfuscator : ObfuscatorBase { - public override bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { return false; } - public override bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { return false; } - public override bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { return false; } - public override bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { return false; } - public override bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List outputInsts) + public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) { return false; } diff --git a/Editor/Utils/MathUtil.cs b/Editor/Utils/MathUtil.cs new file mode 100644 index 0000000..a08ff70 --- /dev/null +++ b/Editor/Utils/MathUtil.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz.Utils +{ + internal static class MathUtil + { + //public static int ModInverseOdd32(int sa) + //{ + // uint a = (uint)sa; + // if (a % 2 == 0) + // throw new ArgumentException("Input must be an odd number.", nameof(a)); + + // uint x = 1; // 初始解:x₀ = 1 (mod 2) + // for (int i = 0; i < 5; i++) // 迭代5次(2^1 → 2^32) + // { + // int shift = 2 << i; // 当前模数为 2^(2^(i+1)) + // ulong mod = 1UL << shift; // 使用 ulong 避免溢出 + // ulong ax = (ulong)a * x; // 计算 a*x(64位避免截断) + // ulong term = (2 - ax) % mod; + // x = (uint)((x * term) % mod); // 更新 x,结果截断为 uint + // } + // return (int)x; // 最终解为 x₅ mod 2^32 + //} + + public static int ModInverse32(int sa) + { + uint x = (uint)sa; + if ((x & 1) == 0) + throw new ArgumentException("x must be odd (coprime with 2^32)"); + + uint inv = x; + inv = inv * (2 - x * inv); // 1 + inv = inv * (2 - x * inv); // 2 + inv = inv * (2 - x * inv); // 3 + inv = inv * (2 - x * inv); // 4 + inv = inv * (2 - x * inv); // 5 + return (int)inv; + } + + public static long ModInverse64(long sx) + { + ulong x = (ulong)sx; + if ((x & 1) == 0) + throw new ArgumentException("x must be odd (coprime with 2^64)"); + + ulong inv = x; + inv *= 2 - x * inv; // 1 + inv *= 2 - x * inv; // 2 + inv *= 2 - x * inv; // 3 + inv *= 2 - x * inv; // 4 + inv *= 2 - x * inv; // 5 + inv *= 2 - x * inv; // 6 + + return (long)inv; + } + } +} diff --git a/Editor/Utils/MathUtil.cs.meta b/Editor/Utils/MathUtil.cs.meta new file mode 100644 index 0000000..4dc5598 --- /dev/null +++ b/Editor/Utils/MathUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d5962b5e88adac40a2b1c65a8d304bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: