From 9c445213b5a6391de89c4336256385958b109c09 Mon Sep 17 00:00:00 2001 From: walon Date: Fri, 20 Jun 2025 17:34:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=85=8D=E7=BD=AE=20obfuscat?= =?UTF-8?q?ionLevel=E5=92=8C=20obfuscationPercentage,=E6=94=AF=E6=8C=81adv?= =?UTF-8?q?ancedObfuscation::neg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/Data/ConstFieldAllocator.cs | 2 +- .../ConfigurableObfuscationPolicy.cs | 51 +++++++++++++++++-- Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs | 43 ++++++++++------ .../Obfuscators/AdvancedObfuscator.cs | 3 ++ .../ExprObfus/Obfuscators/NoneObfuscator.cs | 35 ------------- Editor/Settings/ExprObfuscationSettings.cs | 18 ------- Editor/Settings/ObfuscationLevel.cs | 10 ++++ .../ObfuscationLevel.cs.meta} | 2 +- Editor/Utils/RandomWithKey.cs | 2 +- 9 files changed, 89 insertions(+), 77 deletions(-) delete mode 100644 Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs create mode 100644 Editor/Settings/ObfuscationLevel.cs rename Editor/{ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs.meta => Settings/ObfuscationLevel.cs.meta} (83%) diff --git a/Editor/Data/ConstFieldAllocator.cs b/Editor/Data/ConstFieldAllocator.cs index 7e9ccbc..9902751 100644 --- a/Editor/Data/ConstFieldAllocator.cs +++ b/Editor/Data/ConstFieldAllocator.cs @@ -294,7 +294,7 @@ namespace Obfuz.Data _moduleEntityManager = moduleEntityManager; } - private ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod) + public ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod) { return _moduleEntityManager.GetEntity(mod, () => new ModuleConstFieldAllocator(_encryptionScopeProvider, _rvaDataAllocator, _moduleEntityManager)); } diff --git a/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs b/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs index d53ecc7..563d947 100644 --- a/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs +++ b/Editor/ObfusPasses/ExprObfus/ConfigurableObfuscationPolicy.cs @@ -6,21 +6,36 @@ using System; using System.Collections.Generic; using System.Linq; using System.Xml; +using UnityEditor.VersionControl; namespace Obfuz.ObfusPasses.ExprObfus { + struct ObfuscationRuleData + { + public readonly ObfuscationLevel obfuscationLevel; + public readonly float obfuscationPercentage; + public ObfuscationRuleData(ObfuscationLevel level, float percentage) + { + obfuscationLevel = level; + obfuscationPercentage = percentage; + } + } - public interface IObfuscationPolicy + interface IObfuscationPolicy { bool NeedObfuscate(MethodDef method); + + ObfuscationRuleData GetObfuscationRuleData(MethodDef method); } - public abstract class ObfuscationPolicyBase : IObfuscationPolicy + abstract class ObfuscationPolicyBase : IObfuscationPolicy { public abstract bool NeedObfuscate(MethodDef method); + + public abstract ObfuscationRuleData GetObfuscationRuleData(MethodDef method); } - public class ConfigurableObfuscationPolicy : ObfuscationPolicyBase + class ConfigurableObfuscationPolicy : ObfuscationPolicyBase { class ObfuscationRule : IRule { @@ -54,6 +69,8 @@ namespace Obfuz.ObfusPasses.ExprObfus obfuscationPercentage = 0.5f, }; + private ObfuscationRule _global; + private readonly XmlAssemblyTypeMethodRuleParser _xmlParser; private readonly Dictionary _methodRuleCache = new Dictionary(); @@ -61,14 +78,32 @@ namespace Obfuz.ObfusPasses.ExprObfus public ConfigurableObfuscationPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) { _xmlParser = new XmlAssemblyTypeMethodRuleParser( - toObfuscatedAssemblyNames, ParseObfuscationRule, null); + toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobal); LoadConfigs(xmlConfigFiles); } private void LoadConfigs(List configFiles) { _xmlParser.LoadConfigs(configFiles); - _xmlParser.InheritParentRules(s_default); + + if (_global == null) + { + _global = s_default; + } + else + { + _global.InheritParent(s_default); + } + _xmlParser.InheritParentRules(_global); + } + + private void ParseGlobal(string configFile, XmlElement ele) + { + switch (ele.Name) + { + case "global": _global = ParseObfuscationRule(configFile, ele); break; + default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); + } } private ObfuscationLevel ParseObfuscationLevel(string str) @@ -105,5 +140,11 @@ namespace Obfuz.ObfusPasses.ExprObfus ObfuscationRule rule = GetMethodObfuscationRule(method); return rule.obfuscationLevel.Value > ObfuscationLevel.None; } + + public override ObfuscationRuleData GetObfuscationRuleData(MethodDef method) + { + var rule = GetMethodObfuscationRule(method); + return new ObfuscationRuleData(rule.obfuscationLevel.Value, rule.obfuscationPercentage.Value); + } } } diff --git a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs index b539673..f638468 100644 --- a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs +++ b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs @@ -20,18 +20,24 @@ namespace Obfuz.ObfusPasses.ExprObfus public EncryptionScopeInfo encryptionScope; public DefaultMetadataImporter importer; public ModuleConstFieldAllocator constFieldAllocator; + public float obfuscationPercentage; } class ExprObfusPass : ObfuscationMethodPassBase { private readonly ExprObfuscationSettingsFacade _settings; - private readonly IObfuscator _obfuscator; + private readonly IObfuscator _basicObfuscator; + private readonly IObfuscator _advancedObfuscator; + private readonly IObfuscator _mostAdvancedObfuscator; + private IObfuscationPolicy _obfuscationPolicy; public ExprObfusPass(ExprObfuscationSettingsFacade settings) { _settings = settings; - _obfuscator = CreateObfuscator(_settings.obfuscationLevel); + _basicObfuscator = new BasicObfuscator(); + _advancedObfuscator = new AdvancedObfuscator(); + _mostAdvancedObfuscator = new MostAdvancedObfuscator(); } public override ObfuscationPassType Type => ObfuscationPassType.ExprObfus; @@ -44,14 +50,14 @@ namespace Obfuz.ObfusPasses.ExprObfus _settings.ruleFiles); } - private IObfuscator CreateObfuscator(ObfuscationLevel level) + private IObfuscator GetObfuscator(ObfuscationLevel level) { switch (level) { - case ObfuscationLevel.None: return new NoneObfuscator(); - case ObfuscationLevel.Basic:return new BasicObfuscator(); - case ObfuscationLevel.Advanced: return new AdvancedObfuscator(); - case ObfuscationLevel.MostAdvanced: return new MostAdvancedObfuscator(); + case ObfuscationLevel.None: return null; + case ObfuscationLevel.Basic: return _basicObfuscator; + case ObfuscationLevel.Advanced: return _advancedObfuscator; + case ObfuscationLevel.MostAdvanced: return _mostAdvancedObfuscator; default: throw new System.ArgumentOutOfRangeException(nameof(level), level, "Unknown obfuscation level"); } } @@ -63,18 +69,19 @@ namespace Obfuz.ObfusPasses.ExprObfus protected override bool NeedObfuscateMethod(MethodDef method) { - return _settings.obfuscationLevel != ObfuscationLevel.None && _obfuscationPolicy.NeedObfuscate(method); + return _obfuscationPolicy.NeedObfuscate(method); } - protected bool TryObfuscateInstruction(InstructionParameterInfo pi, Instruction inst, List outputInstructions, ObfusMethodContext ctx) + protected bool TryObfuscateInstruction(IObfuscator obfuscator, InstructionParameterInfo pi, Instruction inst, List outputInstructions, ObfusMethodContext ctx) { //Debug.Log($"Obfuscating instruction: {inst} in method: {ctx.method.FullName}"); - var localRandom = ctx.localRandom; + IRandom localRandom = ctx.localRandom; + float obfuscationPercentage = ctx.obfuscationPercentage; switch (inst.OpCode.Code) { case Code.Neg: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicUnaryOp(inst, pi.op1, pi.retType, outputInstructions, ctx); + return localRandom.NextInPercentage(obfuscationPercentage) && obfuscator.ObfuscateBasicUnaryOp(inst, pi.op1, pi.retType, outputInstructions, ctx); } case Code.Add: case Code.Sub: @@ -84,23 +91,23 @@ namespace Obfuz.ObfusPasses.ExprObfus case Code.Rem: case Code.Rem_Un: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateBasicBinOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); + return localRandom.NextInPercentage(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(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); + return localRandom.NextInPercentage(obfuscationPercentage) && obfuscator.ObfuscateBinBitwiseOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); } case Code.Not: { - return localRandom.NextInPercentage(_settings.obfuscationPercentage) && _obfuscator.ObfuscateUnaryBitwiseOp(inst, pi.op1, pi.retType, outputInstructions, ctx); + return localRandom.NextInPercentage(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(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); + return localRandom.NextInPercentage(obfuscationPercentage) && obfuscator.ObfuscateBitShiftOp(inst, pi.op1, pi.op2, pi.retType, outputInstructions, ctx); } } return false; @@ -116,14 +123,18 @@ namespace Obfuz.ObfusPasses.ExprObfus ObfuscationPassContext ctx = ObfuscationPassContext.Current; var calc = new EvalStackCalculator(method); var encryptionScope = ctx.encryptionScopeProvider.GetScope(method.Module); + var ruleData = _obfuscationPolicy.GetObfuscationRuleData(method); + var obfuscator = GetObfuscator(ruleData.obfuscationLevel); var obfusMethodCtx = new ObfusMethodContext { method = method, evalStackCalculator = calc, localVariableAllocator = new LocalVariableAllocator(method), encryptionScope = encryptionScope, + constFieldAllocator = ctx.constFieldAllocator.GetModuleAllocator(method.Module), localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method)), importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, ctx.encryptionScopeProvider), + obfuscationPercentage = ruleData.obfuscationPercentage, }; for (int i = 0; i < instructions.Count; i++) { @@ -132,7 +143,7 @@ namespace Obfuz.ObfusPasses.ExprObfus if (calc.TryGetParameterInfo(inst, out InstructionParameterInfo pi)) { outputInstructions.Clear(); - if (TryObfuscateInstruction(pi, inst, outputInstructions, obfusMethodCtx)) + if (TryObfuscateInstruction(obfuscator, 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/Obfuscators/AdvancedObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs index 187b2f9..1499132 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs +++ b/Editor/ObfusPasses/ExprObfus/Obfuscators/AdvancedObfuscator.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Obfuz.Utils; using Obfuz.Data; using UnityEngine; +using UnityEngine.Assertions; namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators { @@ -89,6 +90,7 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators // 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; @@ -107,6 +109,7 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators // 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; diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs b/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs deleted file mode 100644 index 82ce128..0000000 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs +++ /dev/null @@ -1,35 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Emit; -using System.Collections.Generic; - -namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators -{ - class NoneObfuscator : ObfuscatorBase - { - public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) - { - return false; - } - - public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) - { - return false; - } - - public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) - { - return false; - } - - public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) - { - return false; - } - - public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List outputInsts, ObfusMethodContext ctx) - { - return false; - } - } -} diff --git a/Editor/Settings/ExprObfuscationSettings.cs b/Editor/Settings/ExprObfuscationSettings.cs index ec827d5..3b854a1 100644 --- a/Editor/Settings/ExprObfuscationSettings.cs +++ b/Editor/Settings/ExprObfuscationSettings.cs @@ -4,31 +4,15 @@ using UnityEngine; namespace Obfuz.Settings { - public enum ObfuscationLevel - { - None = 0, - Basic = 1, - Advanced = 2, - MostAdvanced = 3 - } public class ExprObfuscationSettingsFacade { - public ObfuscationLevel obfuscationLevel; - public float obfuscationPercentage; public List ruleFiles; } [Serializable] public class ExprObfuscationSettings { - [Tooltip("Obfuscation level")] - public ObfuscationLevel obfuscationLevel = ObfuscationLevel.Basic; - - [Tooltip("percentage of obfuscation, 0.0 - 1.0, 0.5 means 50% of expressions will be obfuscated")] - [Range(0.1f, 1.0f)] - public float obfuscationPercentage = 0.5f; - [Tooltip("rule config xml files")] public string[] ruleFiles; @@ -36,8 +20,6 @@ namespace Obfuz.Settings { return new ExprObfuscationSettingsFacade { - obfuscationLevel = obfuscationLevel, - obfuscationPercentage = obfuscationPercentage, ruleFiles = new List(ruleFiles), }; } diff --git a/Editor/Settings/ObfuscationLevel.cs b/Editor/Settings/ObfuscationLevel.cs new file mode 100644 index 0000000..b3f5702 --- /dev/null +++ b/Editor/Settings/ObfuscationLevel.cs @@ -0,0 +1,10 @@ +namespace Obfuz.Settings +{ + public enum ObfuscationLevel + { + None = 0, + Basic = 1, + Advanced = 2, + MostAdvanced = 3 + } +} diff --git a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs.meta b/Editor/Settings/ObfuscationLevel.cs.meta similarity index 83% rename from Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs.meta rename to Editor/Settings/ObfuscationLevel.cs.meta index bf7a5d7..c6567f4 100644 --- a/Editor/ObfusPasses/ExprObfus/Obfuscators/NoneObfuscator.cs.meta +++ b/Editor/Settings/ObfuscationLevel.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ca85b81393732984a9019bdbe5d9e9a7 +guid: dd8e1281c6c9bcd419fecc67980cb673 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Utils/RandomWithKey.cs b/Editor/Utils/RandomWithKey.cs index c3f9679..e7ae157 100644 --- a/Editor/Utils/RandomWithKey.cs +++ b/Editor/Utils/RandomWithKey.cs @@ -50,7 +50,7 @@ public float NextFloat() { - return (float)((double)NextInt() / int.MaxValue); + return (float)((double)(uint)NextInt() / uint.MaxValue); } public bool NextInPercentage(float percentage)