From d3e6e134193e3bdd85eb150513f03ceb2e8753be Mon Sep 17 00:00:00 2001 From: walon Date: Mon, 12 May 2025 22:01:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81pass=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/ConfigurablePassPolicy.cs | 547 ++++++++++++++++++ Editor/IObfuscationPass.cs | 5 +- .../BasicBlockObfuscationPassBase.cs | 7 +- Editor/ObfusPasses/CallObfus/CallObfusPass.cs | 2 + .../CleanUp/CleanUpInstructionPass.cs | 2 + .../ConstEncrypt/ConstEncryptPass.cs | 1 + Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs | 2 +- .../FieldEncrypt/FieldEncryptPass.cs | 2 + .../InstructionObfuscationPassBase.cs | 7 +- Editor/ObfusPasses/ObfuscationPassBase.cs | 7 + Editor/ObfusPasses/ObfuscationPassType.cs | 5 + .../SymbolObfus/Policies/SupportPassPolicy.cs | 50 ++ .../SymbolObfus/SymbolObfusPass.cs | 2 + .../ObfusPasses/SymbolObfus/SymbolRename.cs | 2 +- Editor/ObfuscationPassContext.cs | 1 + Editor/Obfuscator.cs | 5 + Editor/ObfuscatorBuilder.cs | 23 +- 17 files changed, 660 insertions(+), 10 deletions(-) create mode 100644 Editor/ConfigurablePassPolicy.cs create mode 100644 Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs diff --git a/Editor/ConfigurablePassPolicy.cs b/Editor/ConfigurablePassPolicy.cs new file mode 100644 index 0000000..6f8bbcc --- /dev/null +++ b/Editor/ConfigurablePassPolicy.cs @@ -0,0 +1,547 @@ +using dnlib.DotNet; +using Obfuz.ObfusPasses; +using Obfuz.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using UnityEngine; + +namespace Obfuz +{ + public class ConfigurablePassPolicy + { + class PassRule + { + public ObfuscationPassType? enablePasses; + public ObfuscationPassType? disablePasses; + public ObfuscationPassType? addPasses; + public ObfuscationPassType? removePasses; + public ObfuscationPassType finalPasses; + + public void InheritParent(PassRule parentRule, ObfuscationPassType globalEnabledPasses) + { + finalPasses = parentRule.finalPasses; + if (enablePasses != null) + { + finalPasses = enablePasses.Value; + } + if (disablePasses != null) + { + finalPasses = ~disablePasses.Value; + } + if (addPasses != null) + { + finalPasses |= addPasses.Value; + } + if (removePasses != null) + { + finalPasses &= ~removePasses.Value; + } + finalPasses &= globalEnabledPasses; + } + } + + class SpecBase + { + public string name; + public NameMatcher nameMatcher; + public PassRule rule; + } + + class MethodSpec : SpecBase + { + } + + class FieldSpec : SpecBase + { + } + + class PropertySpec : SpecBase + { + } + + class EventSpec : SpecBase + { + } + + class TypeSpec : SpecBase + { + public List fields = new List(); + public List methods = new List(); + public List properties = new List(); + public List events = new List(); + } + + class AssemblySpec + { + public string name; + public NameMatcher nameMatcher; + public PassRule rule; + public List types = new List(); + } + + private readonly ObfuscationPassType _enabledPasses; + private readonly HashSet _toObfuscatedAssemblyNames; + private readonly List _assemblySpecs = new List(); + private readonly PassRule _defaultPassRule; + + private string _curLoadingConfig; + + public ConfigurablePassPolicy(IEnumerable toObfuscatedAssemblyNames, ObfuscationPassType enabledPasses, List configFiles) + { + _toObfuscatedAssemblyNames = new HashSet(toObfuscatedAssemblyNames); + _enabledPasses = enabledPasses; + _defaultPassRule = new PassRule { finalPasses = enabledPasses }; + LoadConfigs(configFiles); + InheritParentRules(enabledPasses); + } + + private void LoadConfigs(IEnumerable configFiles) + { + foreach (var configFile in configFiles) + { + LoadConfig(configFile); + } + } + + private void InheritParentRules(ObfuscationPassType enablePasses) + { + var defaultRule = new PassRule + { + enablePasses = enablePasses, + finalPasses = enablePasses, + }; + foreach (AssemblySpec assSpec in _assemblySpecs) + { + assSpec.rule.InheritParent(defaultRule, enablePasses); + foreach (TypeSpec typeSpec in assSpec.types) + { + typeSpec.rule.InheritParent(assSpec.rule, enablePasses); + foreach (FieldSpec fieldSpec in typeSpec.fields) + { + fieldSpec.rule.InheritParent(typeSpec.rule, enablePasses); + } + foreach (MethodSpec methodSpec in typeSpec.methods) + { + methodSpec.rule.InheritParent(typeSpec.rule, enablePasses); + } + foreach (PropertySpec propertySpec in typeSpec.properties) + { + propertySpec.rule.InheritParent(typeSpec.rule, enablePasses); + } + foreach (EventSpec eventSpec in typeSpec.events) + { + eventSpec.rule.InheritParent(typeSpec.rule, enablePasses); + } + } + } + } + + public void LoadConfig(string configFile) + { + if (string.IsNullOrEmpty(configFile)) + { + throw new Exception($"Invalid xml file {configFile}, file name is empty"); + } + _curLoadingConfig = configFile; + + Debug.Log($"ConfigurablePassPolicy::LoadConfig {configFile}"); + var doc = new XmlDocument(); + doc.Load(configFile); + var root = doc.DocumentElement; + if (root.Name != "obfuz") + { + throw new Exception($"Invalid xml file {configFile}, root name should be 'obfuz'"); + } + foreach (XmlNode node in root.ChildNodes) + { + if (!(node is XmlElement ele)) + { + continue; + } + switch (ele.Name) + { + case "assembly": + { + AssemblySpec assSpec = ParseAssembly(ele); + _assemblySpecs.Add(assSpec); + break; + } + default: + { + throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); + } + } + } + } + + (bool, ObfuscationPassType) ParseObfuscationType(string obfuscationPassTypesStr) + { + bool delta = false; + if (obfuscationPassTypesStr[0] == '+' || obfuscationPassTypesStr[0] == '-') + { + delta = true; + obfuscationPassTypesStr = obfuscationPassTypesStr.Substring(1); + } + ObfuscationPassType passType = ObfuscationPassType.None; + foreach (var passName in obfuscationPassTypesStr.Split('|')) + { + if (Enum.TryParse(typeof(ObfuscationPassType), passName, out var pass)) + { + passType |= (ObfuscationPassType)pass; + } + else + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, unknown pass type {passName}"); + } + } + return (delta, passType); + } + + private PassRule ParseRule(XmlElement ele) + { + var r = new PassRule(); + if (ele.HasAttribute("enable")) + { + string enablePassStr = ele.GetAttribute("enable"); + if (string.IsNullOrEmpty(enablePassStr)) + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, enable attribute is empty"); + } + var (delta, passType) = ParseObfuscationType(enablePassStr); + if (delta) + { + r.addPasses = passType; + } + else + { + r.enablePasses = passType; + } + } + if (ele.HasAttribute("disable")) + { + string disablePassStr = ele.GetAttribute("disable"); + if (string.IsNullOrEmpty(disablePassStr)) + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, disable attribute is empty"); + } + var (delta, passType) = ParseObfuscationType(disablePassStr); + if (delta) + { + r.removePasses = passType; + } + else + { + r.disablePasses = passType; + } + } + if (r.enablePasses != null && (r.disablePasses != null || r.addPasses != null || r.removePasses != null)) + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, enable and disable can't be used together"); + } + if (r.disablePasses != null && (r.enablePasses != null || r.addPasses != null || r.removePasses != null)) + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, disable and enable can't be used together"); + } + return r; + } + + private AssemblySpec ParseAssembly(XmlElement ele) + { + var assemblySpec = new AssemblySpec(); + string name = ele.GetAttribute("name"); + if (!_toObfuscatedAssemblyNames.Contains(name)) + { + throw new Exception($"Invalid xml file {_curLoadingConfig}, assembly name {name} isn't in toObfuscatedAssemblyNames"); + } + assemblySpec.name = name; + assemblySpec.nameMatcher = new NameMatcher(name); + assemblySpec.rule = ParseRule(ele); + + + var types = assemblySpec.types; + foreach (XmlNode node in ele.ChildNodes) + { + if (!(node is XmlElement childEle)) + { + continue; + } + switch (childEle.Name) + { + case "type": + { + types.Add(ParseType(childEle)); + break; + } + default: + { + throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); + } + } + } + return assemblySpec; + } + + private TypeSpec ParseType(XmlElement element) + { + var typeSpec = new TypeSpec(); + + string name = element.GetAttribute("name"); + typeSpec.name = name; + typeSpec.nameMatcher = new NameMatcher(name); + typeSpec.rule = ParseRule(element); + + List fields = typeSpec.fields; + List methods = typeSpec.methods; + List properties = typeSpec.properties; + List events = typeSpec.events; + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement ele)) + { + continue; + } + switch (ele.Name) + { + case "field": + { + fields.Add(ParseField(ele)); + break; + } + case "method": + { + methods.Add(ParseMethod(ele)); + break; + } + case "property": + { + properties.Add(ParseProperty(ele)); + break; + } + case "event": + { + events.Add(ParseEvent(ele)); + break; + } + default: + { + throw new Exception($"Invalid xml file, unknown node {ele.Name}"); + } + } + } + return typeSpec; + } + + private void ParseSpecObject(XmlElement element, SpecBase obj) + { + string name = element.GetAttribute("name"); + obj.name = name; + obj.nameMatcher = new NameMatcher(name); + obj.rule = ParseRule(element); + } + + private FieldSpec ParseField(XmlElement element) + { + var fieldSpec = new FieldSpec(); + ParseSpecObject(element, fieldSpec); + return fieldSpec; + } + + private MethodSpec ParseMethod(XmlElement element) + { + var methodSpec = new MethodSpec(); + ParseSpecObject(element, methodSpec); + return methodSpec; + } + + private PropertySpec ParseProperty(XmlElement element) + { + var propertySpec = new PropertySpec(); + ParseSpecObject(element, propertySpec); + return propertySpec; + } + + private EventSpec ParseEvent(XmlElement element) + { + var eventSpec = new EventSpec(); + ParseSpecObject(element, eventSpec); + return eventSpec; + } + + private readonly Dictionary _modulePassRuleCaches = new Dictionary(); + private readonly Dictionary _typePassRuleCaches = new Dictionary(); + private readonly Dictionary _methodPassRuleCaches = new Dictionary(); + private readonly Dictionary _fieldPassRuleCaches = new Dictionary(); + private readonly Dictionary _propertyPassRuleCaches = new Dictionary(); + private readonly Dictionary _eventPassRuleCaches = new Dictionary(); + + + private (AssemblySpec, PassRule) GetAssemblySpec(ModuleDef module) + { + if (!_modulePassRuleCaches.TryGetValue(module, out var result)) + { + result = (null, _defaultPassRule); + string assName = module.Assembly.Name; + foreach (var ass in _assemblySpecs) + { + if (ass.nameMatcher.IsMatch(assName)) + { + result = (ass, _defaultPassRule); + break; + } + } + _modulePassRuleCaches.Add(module, result); + } + return result; + } + + private (TypeSpec, PassRule) GetTypeSpec(TypeDef type) + { + if (!_typePassRuleCaches.TryGetValue(type, out var result)) + { + var assResult = GetAssemblySpec(type.Module); + result = (null, assResult.Item2); + if (assResult.Item1 != null) + { + string typeName = type.FullName; + foreach (var typeSpec in assResult.Item1.types) + { + if (typeSpec.nameMatcher.IsMatch(typeName)) + { + result = (typeSpec, typeSpec.rule); + break; + } + } + } + _typePassRuleCaches.Add(type, result); + } + return result; + } + + private (MethodSpec, PassRule) GetMethodSpec(MethodDef method) + { + if (!_methodPassRuleCaches.TryGetValue(method, out var result)) + { + var typeResult = GetTypeSpec(method.DeclaringType); + result = (null, typeResult.Item2); + if (typeResult.Item1 != null) + { + string methodName = method.Name; + foreach (var methodSpec in typeResult.Item1.methods) + { + if (methodSpec.nameMatcher.IsMatch(methodName)) + { + result = (methodSpec, methodSpec.rule); + break; + } + } + } + _methodPassRuleCaches.Add(method, result); + } + return result; + } + + private (FieldSpec, PassRule) GetFieldSpec(FieldDef field) + { + if (!_fieldPassRuleCaches.TryGetValue(field, out var result)) + { + var typeResult = GetTypeSpec(field.DeclaringType); + result = (null, typeResult.Item2); + if (typeResult.Item1 != null) + { + string fieldName = field.Name; + foreach (var fieldSpec in typeResult.Item1.fields) + { + if (fieldSpec.nameMatcher.IsMatch(fieldName)) + { + result = (fieldSpec, fieldSpec.rule); + break; + } + } + } + _fieldPassRuleCaches.Add(field, result); + } + return result; + } + + private (PropertySpec, PassRule) GetPropertySpec(PropertyDef property) + { + if (!_propertyPassRuleCaches.TryGetValue(property, out var result)) + { + var typeResult = GetTypeSpec(property.DeclaringType); + result = (null, typeResult.Item2); + if (typeResult.Item1 != null) + { + string propertyName = property.Name; + foreach (var propertySpec in typeResult.Item1.properties) + { + if (propertySpec.nameMatcher.IsMatch(propertyName)) + { + result = (propertySpec, propertySpec.rule); + break; + } + } + } + _propertyPassRuleCaches.Add(property, result); + } + return result; + } + + private (EventSpec, PassRule) GetEventSpec(EventDef eventDef) + { + if (!_eventPassRuleCaches.TryGetValue(eventDef, out var result)) + { + var typeResult = GetTypeSpec(eventDef.DeclaringType); + result = (null, typeResult.Item2); + if (typeResult.Item1 != null) + { + string eventName = eventDef.Name; + foreach (var eventSpec in typeResult.Item1.events) + { + if (eventSpec.nameMatcher.IsMatch(eventName)) + { + result = (eventSpec, eventSpec.rule); + break; + } + } + } + _eventPassRuleCaches.Add(eventDef, result); + } + return result; + } + + + public ObfuscationPassType GetAssemblyObfuscationPasses(ModuleDef module) + { + return GetAssemblySpec(module).Item2.finalPasses; + } + + public ObfuscationPassType GetTypeObfuscationPasses(TypeDef type) + { + return GetTypeSpec(type).Item2.finalPasses; + } + + public ObfuscationPassType GetMethodObfuscationPasses(MethodDef method) + { + return GetMethodSpec(method).Item2.finalPasses; + } + + public ObfuscationPassType GetFieldObfuscationPasses(FieldDef field) + { + return GetFieldSpec(field).Item2.finalPasses; + } + + public ObfuscationPassType GetPropertyObfuscationPasses(PropertyDef property) + { + return GetPropertySpec(property).Item2.finalPasses; + } + + public ObfuscationPassType GetEventObfuscationPasses(EventDef eventDef) + { + return GetEventSpec(eventDef).Item2.finalPasses; + } + } +} diff --git a/Editor/IObfuscationPass.cs b/Editor/IObfuscationPass.cs index 6d1acb4..230c08b 100644 --- a/Editor/IObfuscationPass.cs +++ b/Editor/IObfuscationPass.cs @@ -1,4 +1,5 @@ -using System; +using Obfuz.ObfusPasses; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,6 +9,8 @@ namespace Obfuz { public interface IObfuscationPass { + ObfuscationPassType Type { get; } + void Start(ObfuscationPassContext ctx); void Stop(ObfuscationPassContext ctx); diff --git a/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs b/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs index 5cd7d20..b94a721 100644 --- a/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs +++ b/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs @@ -13,23 +13,24 @@ namespace Obfuz.ObfusPasses public override void Process(ObfuscationPassContext ctx) { NotObfuscatedMethodWhiteList whiteList = ctx.whiteList; + ConfigurablePassPolicy passPolicy = ctx.passPolicy; foreach (ModuleDef mod in ctx.toObfuscatedModules) { - if (whiteList.IsInWhiteList(mod)) + if (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod))) { continue; } // ToArray to avoid modify list exception foreach (TypeDef type in mod.GetTypes().ToArray()) { - if (whiteList.IsInWhiteList(type)) + if (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type))) { continue; } // ToArray to avoid modify list exception foreach (MethodDef method in type.Methods.ToArray()) { - if (!method.HasBody || ctx.whiteList.IsInWhiteList(method) || !NeedObfuscateMethod(method)) + if (!method.HasBody || ctx.whiteList.IsInWhiteList(method) || !Support(passPolicy.GetMethodObfuscationPasses(method)) || !NeedObfuscateMethod(method)) { continue; } diff --git a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs index 48f30e7..b51e5a0 100644 --- a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs +++ b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs @@ -22,6 +22,8 @@ namespace Obfuz.ObfusPasses.CallObfus private IObfuscator _dynamicProxyObfuscator; private IObfuscationPolicy _dynamicProxyPolicy; + public override ObfuscationPassType Type => ObfuscationPassType.CallObfus; + public CallObfusPass(CallObfusSettings settings) { _configFiles = settings.configFiles.ToList(); diff --git a/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs b/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs index 1c65e82..ace7d0a 100644 --- a/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs +++ b/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs @@ -10,6 +10,8 @@ namespace Obfuz.ObfusPasses.CleanUp { public class CleanUpInstructionPass : ObfuscationPassBase { + public override ObfuscationPassType Type => ObfuscationPassType.None; + public override void Start(ObfuscationPassContext ctx) { } diff --git a/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs b/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs index 77fa5a7..0b62a82 100644 --- a/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs +++ b/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs @@ -19,6 +19,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt private readonly int _encryptionLevel; private IEncryptPolicy _dataObfuscatorPolicy; private IConstEncryptor _dataObfuscator; + public override ObfuscationPassType Type => ObfuscationPassType.ConstEncrypt; public ConstEncryptPass(ConstEncryptSettings settings) { diff --git a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs index 0f56054..f854ecb 100644 --- a/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs +++ b/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs @@ -10,7 +10,7 @@ namespace Obfuz.ObfusPasses.ExprObfus { public class ExprObfusPass : InstructionObfuscationPassBase { - + public override ObfuscationPassType Type => ObfuscationPassType.ExprObfus; public override void Start(ObfuscationPassContext ctx) { diff --git a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs index af8f77b..f5356bb 100644 --- a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs +++ b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs @@ -17,6 +17,8 @@ namespace Obfuz.ObfusPasses.FieldEncrypt private IEncryptPolicy _encryptionPolicy; private IFieldEncryptor _memoryEncryptor; + public override ObfuscationPassType Type => ObfuscationPassType.FieldEncrypt; + public FieldEncryptPass(FieldEncryptSettings settings) { _configFiles = settings.configFiles.ToList(); diff --git a/Editor/ObfusPasses/InstructionObfuscationPassBase.cs b/Editor/ObfusPasses/InstructionObfuscationPassBase.cs index e7777a6..737a448 100644 --- a/Editor/ObfusPasses/InstructionObfuscationPassBase.cs +++ b/Editor/ObfusPasses/InstructionObfuscationPassBase.cs @@ -15,23 +15,24 @@ namespace Obfuz.ObfusPasses { var modules = NeedProcessNotObfuscatedAssembly ? ctx.obfuscatedAndNotObfuscatedModules : ctx.toObfuscatedModules; NotObfuscatedMethodWhiteList whiteList = ctx.whiteList; + ConfigurablePassPolicy passPolicy = ctx.passPolicy; foreach (ModuleDef mod in modules) { - if (whiteList.IsInWhiteList(mod)) + if (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod))) { continue; } // ToArray to avoid modify list exception foreach (TypeDef type in mod.GetTypes().ToArray()) { - if (whiteList.IsInWhiteList(type)) + if (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type))) { continue; } // ToArray to avoid modify list exception foreach (MethodDef method in type.Methods.ToArray()) { - if (!method.HasBody || ctx.whiteList.IsInWhiteList(method) || !NeedObfuscateMethod(method)) + if (!method.HasBody || ctx.whiteList.IsInWhiteList(method) || !Support(passPolicy.GetMethodObfuscationPasses(method)) || !NeedObfuscateMethod(method)) { continue; } diff --git a/Editor/ObfusPasses/ObfuscationPassBase.cs b/Editor/ObfusPasses/ObfuscationPassBase.cs index ac04509..5b37576 100644 --- a/Editor/ObfusPasses/ObfuscationPassBase.cs +++ b/Editor/ObfusPasses/ObfuscationPassBase.cs @@ -4,6 +4,13 @@ namespace Obfuz.ObfusPasses { public abstract class ObfuscationPassBase : IObfuscationPass { + public abstract ObfuscationPassType Type { get; } + + public bool Support(ObfuscationPassType passType) + { + return passType.HasFlag(Type); + } + public abstract void Start(ObfuscationPassContext ctx); public abstract void Stop(ObfuscationPassContext ctx); diff --git a/Editor/ObfusPasses/ObfuscationPassType.cs b/Editor/ObfusPasses/ObfuscationPassType.cs index c0f909d..ec28ad3 100644 --- a/Editor/ObfusPasses/ObfuscationPassType.cs +++ b/Editor/ObfusPasses/ObfuscationPassType.cs @@ -15,6 +15,11 @@ namespace Obfuz.ObfusPasses ExprObfus = 0x400, ControlFlowObfus = 0x800, + AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus, + AllEncrypt = ConstEncrypt | FieldEncrypt, + + MethodBodyObfusOrEncrypt = ConstEncrypt | CallObfus | ExprObfus | ControlFlowObfus, + All = ~0, } } diff --git a/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs b/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs new file mode 100644 index 0000000..1d0cb6b --- /dev/null +++ b/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs @@ -0,0 +1,50 @@ +using dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz.ObfusPasses.SymbolObfus.Policies +{ + internal class SupportPassPolicy : ObfuscationPolicyBase + { + private readonly ConfigurablePassPolicy _policy; + + + private bool Support(ObfuscationPassType passType) + { + return passType.HasFlag(ObfuscationPassType.SymbolObfus); + } + + public SupportPassPolicy(ConfigurablePassPolicy policy) + { + _policy = policy; + } + + public override bool NeedRename(TypeDef typeDef) + { + return Support(_policy.GetTypeObfuscationPasses(typeDef)); + } + + public override bool NeedRename(MethodDef methodDef) + { + return Support(_policy.GetMethodObfuscationPasses(methodDef)); + } + + public override bool NeedRename(FieldDef fieldDef) + { + return Support(_policy.GetFieldObfuscationPasses(fieldDef)); + } + + public override bool NeedRename(PropertyDef propertyDef) + { + return Support(_policy.GetPropertyObfuscationPasses(propertyDef)); + } + + public override bool NeedRename(EventDef eventDef) + { + return Support(_policy.GetEventObfuscationPasses(eventDef)); + } + } +} diff --git a/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs b/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs index bf000ce..9a73d65 100644 --- a/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs +++ b/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs @@ -11,6 +11,8 @@ namespace Obfuz.ObfusPasses.SymbolObfus { private SymbolRename _symbolRename; + public override ObfuscationPassType Type => ObfuscationPassType.SymbolObfus; + public SymbolObfusPass(SymbolObfusSettings settings) { _symbolRename = new SymbolRename(settings); diff --git a/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs b/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs index f511e7c..735eab7 100644 --- a/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs +++ b/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs @@ -70,7 +70,7 @@ namespace Obfuz.ObfusPasses.SymbolObfus _obfuscatedAndNotObfuscatedModules = ctx.obfuscatedAndNotObfuscatedModules; _toObfuscatedModuleSet = ctx.toObfuscatedModules.ToHashSet(); var obfuscateRuleConfig = new ConfigurableRenamePolicy(ctx.toObfuscatedAssemblyNames, _obfuscationRuleFiles); - _renamePolicy = new CacheRenamePolicy(new CombineRenamePolicy(new SystemRenamePolicy(), new UnityRenamePolicy(), obfuscateRuleConfig)); + _renamePolicy = new CacheRenamePolicy(new CombineRenamePolicy(new SupportPassPolicy(ctx.passPolicy), new SystemRenamePolicy(), new UnityRenamePolicy(), obfuscateRuleConfig)); BuildCustomAttributeArguments(); } diff --git a/Editor/ObfuscationPassContext.cs b/Editor/ObfuscationPassContext.cs index b5bfdb1..e563aa6 100644 --- a/Editor/ObfuscationPassContext.cs +++ b/Editor/ObfuscationPassContext.cs @@ -29,5 +29,6 @@ namespace Obfuz public ConstFieldAllocator constFieldAllocator; public RvaDataAllocator rvaDataAllocator; public NotObfuscatedMethodWhiteList whiteList; + public ConfigurablePassPolicy passPolicy; } } diff --git a/Editor/Obfuscator.cs b/Editor/Obfuscator.cs index 7d277ea..a55d94c 100644 --- a/Editor/Obfuscator.cs +++ b/Editor/Obfuscator.cs @@ -27,6 +27,8 @@ namespace Obfuz private readonly List _notObfuscatedAssemblyNamesReferencingObfuscated; private readonly List _assemblySearchDirs; + private readonly ConfigurablePassPolicy _passPolicy; + private readonly Pipeline _pipeline1 = new Pipeline(); private readonly Pipeline _pipeline2 = new Pipeline(); private readonly byte[] _secret; @@ -51,6 +53,8 @@ namespace Obfuz _obfuscatedAssemblyOutputDir = builder.ObfuscatedAssemblyOutputDir; _assemblySearchDirs = builder.AssemblySearchDirs; + _passPolicy = new ConfigurablePassPolicy(_toObfuscatedAssemblyNames, builder.EnableObfuscationPasses, builder.ObfuscationPassConfigFiles); + foreach (var pass in builder.ObfuscationPasses) { if (pass is SymbolObfusPass symbolObfusPass) @@ -176,6 +180,7 @@ namespace Obfuz rvaDataAllocator = rvaDataAllocator, constFieldAllocator = constFieldAllocator, whiteList = new NotObfuscatedMethodWhiteList(), + passPolicy = _passPolicy, }; pipeline.Start(_ctx); } diff --git a/Editor/ObfuscatorBuilder.cs b/Editor/ObfuscatorBuilder.cs index 1c937f7..516c74e 100644 --- a/Editor/ObfuscatorBuilder.cs +++ b/Editor/ObfuscatorBuilder.cs @@ -27,6 +27,9 @@ namespace Obfuz private List _assemblySearchDirs = new List(); private string _obfuscatedAssemblyOutputDir; + private List _obfuscationPassConfigFiles; + + private ObfuscationPassType _enabledObfuscationPasses; private List _obfuscationPasses = new List(); public string Secret @@ -89,7 +92,23 @@ namespace Obfuz set => _obfuscatedAssemblyOutputDir = value; } - public List ObfuscationPasses { get => _obfuscationPasses; set => _obfuscationPasses = value; } + public ObfuscationPassType EnableObfuscationPasses + { + get => _enabledObfuscationPasses; + set => _enabledObfuscationPasses = value; + } + + public List ObfuscationPassConfigFiles + { + get => _obfuscationPassConfigFiles; + set => _obfuscationPassConfigFiles = value; + } + + public List ObfuscationPasses + { + get => _obfuscationPasses; + set => _obfuscationPasses = value; + } public void InsertTopPriorityAssemblySearchDirs(List assemblySearchDirs) { @@ -139,6 +158,8 @@ namespace Obfuz _notObfuscatedAssemblyNamesReferencingObfuscated = settings.assemblySettings.notObfuscatedAssemblyNamesReferencingObfuscated.ToList(), _assemblySearchDirs = BuildUnityAssemblySearchPaths().Concat(settings.assemblySettings.extraAssemblySearchDirs).ToList(), _obfuscatedAssemblyOutputDir = settings.GetObfuscatedAssemblyOutputDir(target), + _enabledObfuscationPasses = settings.obfuscationPassSettings.enabledPasses, + _obfuscationPassConfigFiles = settings.obfuscationPassSettings.configFiles.ToList(), }; ObfuscationPassType obfuscationPasses = settings.obfuscationPassSettings.enabledPasses; if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt))