支持部分 AdvancedObfuscator
parent
4bc6cf923f
commit
111d3a7dc1
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<ObfuscationRule>
|
||||
{
|
||||
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<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule> _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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Instruction> outputInstructions)
|
||||
protected bool TryObfuscateInstruction(InstructionParameterInfo pi, Instruction inst, List<Instruction> 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<Instruction> instructions = method.Body.Instructions;
|
||||
var outputInstructions = new List<Instruction>();
|
||||
var totalFinalInstructions = new List<Instruction>();
|
||||
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
|
||||
|
|
|
@ -7,23 +7,23 @@ namespace Obfuz.ObfusPasses.ExprObfus
|
|||
{
|
||||
interface IObfuscator
|
||||
{
|
||||
bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
|
||||
bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
|
||||
bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
|
||||
bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
|
||||
bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
}
|
||||
|
||||
abstract class ObfuscatorBase : IObfuscator
|
||||
{
|
||||
public abstract bool ObfuscateBasicUnaryOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
public abstract bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
public abstract bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
public abstract bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
public abstract bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts);
|
||||
public abstract bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
public abstract bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
public abstract bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
public abstract bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
public abstract bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Instruction> 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<Instruction> 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<Instruction> 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<Instruction> 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<Instruction> 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<Instruction> 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<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return base.ObfuscateUnaryBitwiseOp(inst, op, ret, outputInsts, ctx);
|
||||
}
|
||||
|
||||
public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> 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<Instruction> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Instruction> outputInsts)
|
||||
public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> 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<Instruction> outputInsts)
|
||||
public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> 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<Instruction> outputInsts)
|
||||
public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> 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<Instruction> outputInsts)
|
||||
public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> 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<Instruction> outputInsts)
|
||||
public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> 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;
|
||||
|
|
|
@ -4,9 +4,5 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
|
|||
{
|
||||
class MostAdvancedObfuscator : AdvancedObfuscator
|
||||
{
|
||||
public MostAdvancedObfuscator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager)
|
||||
: base(encryptionScopeProvider, moduleEntityManager)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Instruction> outputInsts)
|
||||
public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ObfuscateBasicBinOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts)
|
||||
public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ObfuscateUnaryBitwiseOp(MethodDef method, Instruction inst, EvalDataType op, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts)
|
||||
public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ObfuscateBinBitwiseOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts)
|
||||
public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ObfuscateBitShiftOp(MethodDef method, Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, LocalVariableAllocator localVariableAllocator, List<Instruction> outputInsts)
|
||||
public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d5962b5e88adac40a2b1c65a8d304bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue