diff --git a/Editor/ObfusPasses/ControlFlowObfus.meta b/Editor/ObfusPasses/ControlFlowObfus.meta new file mode 100644 index 0000000..9013ba5 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 02fb097cf61874c41923b3ef23fee199 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs b/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs new file mode 100644 index 0000000..6914fcf --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs @@ -0,0 +1,137 @@ +using dnlib.DotNet; +using Obfuz.Conf; +using Obfuz.Settings; +using System; +using System.Collections.Generic; +using System.Xml; + +namespace Obfuz.ObfusPasses.ControlFlowObfus +{ + struct ObfuscationRuleData + { + public readonly ObfuscationLevel obfuscationLevel; + public ObfuscationRuleData(ObfuscationLevel level) + { + obfuscationLevel = level; + } + } + + interface IObfuscationPolicy + { + bool NeedObfuscate(MethodDef method); + + ObfuscationRuleData GetObfuscationRuleData(MethodDef method); + } + + abstract class ObfuscationPolicyBase : IObfuscationPolicy + { + public abstract bool NeedObfuscate(MethodDef method); + + public abstract ObfuscationRuleData GetObfuscationRuleData(MethodDef method); + } + + class ConfigurableObfuscationPolicy : ObfuscationPolicyBase + { + class ObfuscationRule : IRule + { + public ObfuscationLevel? obfuscationLevel; + + public void InheritParent(ObfuscationRule parentRule) + { + if (obfuscationLevel == null) + obfuscationLevel = parentRule.obfuscationLevel; + } + } + + class MethodSpec : MethodRuleBase + { + } + + class TypeSpec : TypeRuleBase + { + } + + class AssemblySpec : AssemblyRuleBase + { + } + + private static readonly ObfuscationRule s_default = new ObfuscationRule() + { + obfuscationLevel = ObfuscationLevel.Basic, + }; + + private ObfuscationRule _global; + + private readonly XmlAssemblyTypeMethodRuleParser _xmlParser; + + private readonly Dictionary _methodRuleCache = new Dictionary(); + + public ConfigurableObfuscationPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) + { + _xmlParser = new XmlAssemblyTypeMethodRuleParser( + toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobal); + LoadConfigs(xmlConfigFiles); + } + + private void LoadConfigs(List configFiles) + { + _xmlParser.LoadConfigs(configFiles); + + 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) + { + return (ObfuscationLevel)Enum.Parse(typeof(ObfuscationLevel), str); + } + + private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele) + { + var rule = new ObfuscationRule(); + if (ele.HasAttribute("obfuscationLevel")) + { + rule.obfuscationLevel = ParseObfuscationLevel(ele.GetAttribute("obfuscationLevel")); + } + return rule; + } + + private ObfuscationRule GetMethodObfuscationRule(MethodDef method) + { + if (!_methodRuleCache.TryGetValue(method, out var rule)) + { + rule = _xmlParser.GetMethodRule(method, s_default); + _methodRuleCache[method] = rule; + } + return rule; + } + + public override bool NeedObfuscate(MethodDef method) + { + 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); + } + } +} diff --git a/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs.meta b/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs.meta new file mode 100644 index 0000000..1203f4b --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/ConfigurableObfuscationPolicy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6983877d8859df4882c30f75be7a70e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs b/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs new file mode 100644 index 0000000..b32ed37 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs @@ -0,0 +1,73 @@ +using dnlib.DotNet; +using Obfuz.Data; +using Obfuz.Emit; +using Obfuz.Settings; +using Obfuz.Utils; + +namespace Obfuz.ObfusPasses.ControlFlowObfus +{ + class ObfusMethodContext + { + public MethodDef method; + public LocalVariableAllocator localVariableAllocator; + public IRandom localRandom; + public EncryptionScopeInfo encryptionScope; + public DefaultMetadataImporter importer; + public ModuleConstFieldAllocator constFieldAllocator; + } + + internal class ControlFlowObfusPass : ObfuscationMethodPassBase + { + private readonly ControlFlowObfuscationSettingsFacade _settings; + + private IObfuscationPolicy _obfuscationPolicy; + private IObfuscator _obfuscator; + + public ControlFlowObfusPass(ControlFlowObfuscationSettingsFacade settings) + { + _settings = settings; + _obfuscator = new DefaultObfuscator(); + } + + public override ObfuscationPassType Type => ObfuscationPassType.ControlFlowObfus; + + public override void Start() + { + ObfuscationPassContext ctx = ObfuscationPassContext.Current; + _obfuscationPolicy = new ConfigurableObfuscationPolicy( + ctx.coreSettings.assembliesToObfuscate, + _settings.ruleFiles); + } + + public override void Stop() + { + + } + + protected override bool NeedObfuscateMethod(MethodDef method) + { + return _obfuscationPolicy.NeedObfuscate(method); + } + + protected override void ObfuscateData(MethodDef method) + { + //Debug.Log($"Obfuscating method: {method.FullName} with EvalStackObfusPass"); + + ObfuscationPassContext ctx = ObfuscationPassContext.Current; + var calc = new BasicBlockCollection(method, false); + var encryptionScope = ctx.encryptionScopeProvider.GetScope(method.Module); + var ruleData = _obfuscationPolicy.GetObfuscationRuleData(method); + var localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method)); + var obfusMethodCtx = new ObfusMethodContext + { + method = method, + localVariableAllocator = new LocalVariableAllocator(method), + encryptionScope = encryptionScope, + constFieldAllocator = ctx.constFieldAllocator.GetModuleAllocator(method.Module), + localRandom = localRandom, + importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, ctx.encryptionScopeProvider), + }; + _obfuscator.Obfuscate(calc, obfusMethodCtx); + } + } +} diff --git a/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs.meta b/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs.meta new file mode 100644 index 0000000..ad62fd6 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/ControlFlowObfusPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf62db4d3137e6447bd5cb2a65f101d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs b/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs new file mode 100644 index 0000000..53fe525 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs @@ -0,0 +1,12 @@ +using Obfuz.Emit; + +namespace Obfuz.ObfusPasses.ControlFlowObfus +{ + class DefaultObfuscator : ObfuscatorBase + { + public override bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs.meta b/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs.meta new file mode 100644 index 0000000..2592609 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/DefaultObfuscator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8aa2a2e43fa066541b982dbb63452458 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs b/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs new file mode 100644 index 0000000..b8dfc07 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs @@ -0,0 +1,14 @@ +using Obfuz.Emit; + +namespace Obfuz.ObfusPasses.ControlFlowObfus +{ + interface IObfuscator + { + bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx); + } + + abstract class ObfuscatorBase : IObfuscator + { + public abstract bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx); + } +} diff --git a/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs.meta b/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs.meta new file mode 100644 index 0000000..e909f23 --- /dev/null +++ b/Editor/ObfusPasses/ControlFlowObfus/IObfuscator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ada5f6005768f745a18dc8b968e1684 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Settings/ControlFlowObfuscationSettings.cs b/Editor/Settings/ControlFlowObfuscationSettings.cs new file mode 100644 index 0000000..9417e01 --- /dev/null +++ b/Editor/Settings/ControlFlowObfuscationSettings.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Obfuz.Settings +{ + + public class ControlFlowObfuscationSettingsFacade + { + public List ruleFiles; + } + + [Serializable] + public class ControlFlowObfuscationSettings + { + [Tooltip("rule config xml files")] + public string[] ruleFiles; + + public ControlFlowObfuscationSettingsFacade ToFacade() + { + return new ControlFlowObfuscationSettingsFacade + { + ruleFiles = new List(ruleFiles ?? Array.Empty()), + }; + } + } +} diff --git a/Editor/Settings/ControlFlowObfuscationSettings.cs.meta b/Editor/Settings/ControlFlowObfuscationSettings.cs.meta new file mode 100644 index 0000000..8d8b0f2 --- /dev/null +++ b/Editor/Settings/ControlFlowObfuscationSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d40d2fb33f081b2458505c7566b1bc8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: