diff --git a/Editor/Conf/XmlFieldRuleParser.cs b/Editor/Conf/XmlFieldRuleParser.cs new file mode 100644 index 0000000..591271e --- /dev/null +++ b/Editor/Conf/XmlFieldRuleParser.cs @@ -0,0 +1,208 @@ +using dnlib.DotNet; +using Obfuz.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using UnityEditor.VersionControl; +using UnityEngine; + +namespace Obfuz.Conf +{ + + + + public class XmlFieldRuleParser where R : class, new() + { + private readonly HashSet _toObfuscatedAssemblyNames; + private readonly Func _ruleParser; + private readonly Action _unknownNodeTypeHandler; + private readonly Dictionary _assemblySpecs = new Dictionary(); + + + private class FieldSpec + { + public string Name { get; set; } + public NameMatcher NameMatcher { get; set; } + + public R Rule { get; set; } + } + + private class TypeSpec + { + public string Name { get; set; } + + public NameMatcher NameMatcher { get; set; } + + public List Fields { get; set; } + } + + private class AssemblySpec + { + public string Name { get; set; } + + public List Types { get; set; } + } + + public XmlFieldRuleParser(IEnumerable toObfuscatedAssemblyNames, Func ruleParser, Action unknownNodeTypeHandler) + { + _toObfuscatedAssemblyNames = new HashSet(toObfuscatedAssemblyNames); + _ruleParser = ruleParser; + _unknownNodeTypeHandler = unknownNodeTypeHandler; + } + + public void LoadConfigs(IEnumerable configFiles) + { + foreach (var configFile in configFiles) + { + LoadConfig(configFile); + } + } + + public void LoadConfig(string configFile) + { + if (string.IsNullOrEmpty(configFile)) + { + throw new Exception($"Invalid xml file {configFile}, file name is empty"); + } + 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(configFile, ele); + _assemblySpecs.Add(assSpec.Name, assSpec); + break; + } + default: + { + if (_unknownNodeTypeHandler == null) + { + throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); + } + _unknownNodeTypeHandler(configFile, ele); + break; + } + } + } + } + + private AssemblySpec ParseAssembly(string configFile, XmlElement ele) + { + var assemblySpec = new AssemblySpec(); + string name = ele.GetAttribute("name"); + if (!_toObfuscatedAssemblyNames.Contains(name)) + { + throw new Exception($"Invalid xml file {configFile}, assembly name {name} isn't in toObfuscatedAssemblyNames"); + } + if (_assemblySpecs.ContainsKey(name)) + { + throw new Exception($"Invalid xml file {configFile}, assembly name {name} is duplicated"); + } + assemblySpec.Name = name; + + var types = new List(); + assemblySpec.Types = types; + foreach (XmlNode node in ele.ChildNodes) + { + if (!(node is XmlElement childEle)) + { + continue; + } + switch (childEle.Name) + { + case "type": + { + types.Add(ParseType(configFile, childEle)); + break; + } + default: + { + throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); + } + } + } + return assemblySpec; + } + + private TypeSpec ParseType(string configFile, XmlElement element) + { + var typeSpec = new TypeSpec(); + + string name = element.GetAttribute("name"); + typeSpec.Name = name; + typeSpec.NameMatcher = new NameMatcher(name); + + var fields = new List(); + typeSpec.Fields = fields; + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement ele)) + { + continue; + } + switch (ele.Name) + { + case "field": + { + fields.Add(ParseField(configFile, ele)); + break; + } + default: + { + throw new Exception($"Invalid xml file, unknown node {ele.Name}"); + } + } + } + return typeSpec; + } + + private FieldSpec ParseField(string configFile, XmlElement element) + { + var fieldSpec = new FieldSpec(); + string name = element.GetAttribute("name"); + fieldSpec.Name = name; + fieldSpec.NameMatcher = new NameMatcher(name); + fieldSpec.Rule = _ruleParser(configFile, element); + return fieldSpec; + } + + public R GetFieldRule(FieldDef field) + { + var assemblyName = field.DeclaringType.Module.Assembly.Name; + if (!_assemblySpecs.TryGetValue(assemblyName, out var assSpec)) + { + return null; + } + string declaringTypeName = field.DeclaringType.FullName; + foreach (var typeSpec in assSpec.Types) + { + if (typeSpec.NameMatcher.IsMatch(declaringTypeName)) + { + foreach (var fieldSpec in typeSpec.Fields) + { + if (fieldSpec.NameMatcher.IsMatch(field.Name)) + { + return fieldSpec.Rule; + } + } + } + } + return null; + } + } +} diff --git a/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs b/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs index 8ae8961..9f09832 100644 --- a/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs +++ b/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs @@ -1,19 +1,36 @@ using dnlib.DotNet; +using Obfuz.Conf; +using Obfuz.Utils; +using System; +using System.Collections.Generic; +using System.Xml; namespace Obfuz.ObfusPasses.FieldEncrypt { public class ConfigurableEncryptPolicy : EncryptPolicyBase { + class ObfuscationRule + { + + } + + private readonly XmlFieldRuleParser _configParser; + + public ConfigurableEncryptPolicy(List toObfuscatedAssemblyNames, List configFiles) + { + _configParser = new XmlFieldRuleParser(toObfuscatedAssemblyNames, ParseRule, null); + _configParser.LoadConfigs(configFiles); + } + + private ObfuscationRule ParseRule(string configFile, XmlElement ele) + { + return new ObfuscationRule(); + } public override bool NeedEncrypt(FieldDef field) { - TypeDef type = field.DeclaringType; - // TODO - if (type.Name == "EncryptField" || type.Name == "EncryptProperty") - { - return true; - } - return false; + var rule = _configParser.GetFieldRule(field); + return rule != null; } } } diff --git a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs index b779f83..713e6f8 100644 --- a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs +++ b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs @@ -1,8 +1,10 @@ using dnlib.DotNet; using dnlib.DotNet.Emit; using Obfuz; +using Obfuz.Settings; using System.Collections; using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace Obfuz.ObfusPasses.FieldEncrypt @@ -10,13 +12,21 @@ namespace Obfuz.ObfusPasses.FieldEncrypt public class FieldEncryptPass : InstructionObfuscationPassBase { - private readonly IEncryptPolicy _encryptionPolicy = new ConfigurableEncryptPolicy(); + private readonly List _configFiles; + private IEncryptPolicy _encryptionPolicy; private IFieldEncryptor _memoryEncryptor; + public FieldEncryptPass(FieldEncryptSettings settings) + { + _configFiles = settings.configFiles.ToList(); + } + + protected override bool NeedProcessNotObfuscatedAssembly => true; + public override void Start(ObfuscationPassContext ctx) { _memoryEncryptor = new DefaultFieldEncryptor(ctx.random, ctx.encryptor); - + _encryptionPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); } public override void Stop(ObfuscationPassContext ctx) @@ -57,11 +67,6 @@ namespace Obfuz.ObfusPasses.FieldEncrypt { return false; } - var ctx = new MemoryEncryptionContext - { - module = callingMethod.Module, - currentInstruction = inst, - }; switch (code) { case Code.Ldfld: diff --git a/Editor/ObfusPasses/InstructionObfuscationPassBase.cs b/Editor/ObfusPasses/InstructionObfuscationPassBase.cs index 55d30ce..57532e3 100644 --- a/Editor/ObfusPasses/InstructionObfuscationPassBase.cs +++ b/Editor/ObfusPasses/InstructionObfuscationPassBase.cs @@ -7,11 +7,14 @@ namespace Obfuz.ObfusPasses { public abstract class InstructionObfuscationPassBase : ObfuscationPassBase { + protected virtual bool NeedProcessNotObfuscatedAssembly => false; + protected abstract bool NeedObfuscateMethod(MethodDef method); public override void Process(ObfuscationPassContext ctx) { - foreach (ModuleDef mod in ctx.toObfuscatedModules) + var modules = NeedProcessNotObfuscatedAssembly ? ctx.obfuscatedAndNotObfuscatedModules : ctx.toObfuscatedModules; + foreach (ModuleDef mod in modules) { // ToArray to avoid modify list exception foreach (TypeDef type in mod.GetTypes().ToArray()) diff --git a/Editor/ObfuscatorBuilder.cs b/Editor/ObfuscatorBuilder.cs index d6f092d..467a123 100644 --- a/Editor/ObfuscatorBuilder.cs +++ b/Editor/ObfuscatorBuilder.cs @@ -76,7 +76,7 @@ namespace Obfuz ObfuscationPassType obfuscationPasses = settings.enabledObfuscationPasses; if (obfuscationPasses.HasFlag(ObfuscationPassType.MemoryEncryption)) { - builder.AddPass(new FieldEncryptPass()); + builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings)); } if (obfuscationPasses.HasFlag(ObfuscationPassType.CallProxy)) { diff --git a/Editor/Settings/ObfuzSettings.cs b/Editor/Settings/ObfuzSettings.cs index 482c7af..7d76a95 100644 --- a/Editor/Settings/ObfuzSettings.cs +++ b/Editor/Settings/ObfuzSettings.cs @@ -32,6 +32,9 @@ namespace Obfuz.Settings [Tooltip("const encryption settings")] public ConstEncryptSettings constEncryptSettings; + [Tooltip("field encryption settings")] + public FieldEncryptSettings fieldEncryptSettings; + [Tooltip("call obfuscation settings")] public CallObfusSettings callObfusSettings; diff --git a/Editor/Settings/ObfuzSettingsProvider.cs b/Editor/Settings/ObfuzSettingsProvider.cs index b133515..0285964 100644 --- a/Editor/Settings/ObfuzSettingsProvider.cs +++ b/Editor/Settings/ObfuzSettingsProvider.cs @@ -37,6 +37,7 @@ namespace Obfuz.Settings private SerializedProperty _symbolObfusSettings; private SerializedProperty _constEncryptSettings; + private SerializedProperty _fieldEncryptSettings; private SerializedProperty _callObfusSettings; public ObfuzSettingsProvider() : base("Project/Obfuz", SettingsScope.Project) @@ -67,6 +68,7 @@ namespace Obfuz.Settings _symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings"); _constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings"); + _fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings"); _callObfusSettings = _serializedObject.FindProperty("callObfusSettings"); } @@ -87,6 +89,7 @@ namespace Obfuz.Settings EditorGUILayout.PropertyField(_symbolObfusSettings); EditorGUILayout.PropertyField(_constEncryptSettings); + EditorGUILayout.PropertyField(_fieldEncryptSettings); EditorGUILayout.PropertyField(_callObfusSettings);