diff --git a/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs b/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs index 96cc1a5..3a0d5ca 100644 --- a/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs +++ b/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs @@ -13,9 +13,6 @@ namespace Obfuz.ObfusPasses.CallObfus { public class ConfigurableObfuscationPolicy : ObfuscationPolicyBase { - private readonly List _toObfuscatedAssemblyNames; - - class WhiteListAssembly { public string name; @@ -91,15 +88,13 @@ namespace Obfuz.ObfusPasses.CallObfus private ObfuscationRule _global; private readonly List _whiteListAssemblies = new List(); - private readonly Dictionary _assemblySpecs = new Dictionary(); private readonly Dictionary _whiteListMethodCache = new Dictionary(MethodEqualityComparer.CompareDeclaringTypes); private readonly Dictionary _methodRuleCache = new Dictionary(); public ConfigurableObfuscationPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) { - _toObfuscatedAssemblyNames = toObfuscatedAssemblyNames; - _configParser = new XmlAssemblyTypeMethodRuleParser(_toObfuscatedAssemblyNames, + _configParser = new XmlAssemblyTypeMethodRuleParser(toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobalElement); LoadConfigs(xmlConfigFiles); } @@ -237,16 +232,11 @@ namespace Obfuz.ObfusPasses.CallObfus return method; } - private ObfuscationRule ComputeMethodObfuscationRule(MethodDef method) - { - return _configParser.GetMethodRule(method, s_default); - } - private ObfuscationRule GetMethodObfuscationRule(MethodDef method) { if (!_methodRuleCache.TryGetValue(method, out var rule)) { - rule = ComputeMethodObfuscationRule(method); + rule = _configParser.GetMethodRule(method, s_default); _methodRuleCache[method] = rule; } return rule; diff --git a/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs b/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs index 941b8cb..93ac37a 100644 --- a/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs +++ b/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs @@ -1,4 +1,5 @@ using dnlib.DotNet; +using Obfuz.Conf; using Obfuz.Utils; using System; using System.Collections.Generic; @@ -10,23 +11,10 @@ using UnityEngine; namespace Obfuz.ObfusPasses.ConstEncrypt { + public class ConfigurableEncryptPolicy : EncryptPolicyBase { - private readonly List _toObfuscatedAssemblyNames; - - class NumberRange where T : struct - { - public readonly T? min; - public readonly T? max; - - public NumberRange(T? min, T? max) - { - this.min = min; - this.max = max; - } - } - - class ObfuscationRule + class ObfuscationRule : IRule { public bool? disableEncrypt; public bool? encryptInt; @@ -44,16 +32,6 @@ namespace Obfuz.ObfusPasses.ConstEncrypt public bool? cacheStringInLoop; public bool? cacheStringNotInLoop; - public HashSet notEncryptInts = new HashSet(); - public HashSet notEncryptLongs = new HashSet(); - public HashSet notEncryptStrings = new HashSet(); - public List> notEncryptIntRanges = new List>(); - public List> notEncryptLongRanges = new List>(); - public List> notEncryptFloatRanges = new List>(); - public List> notEncryptDoubleRanges = new List>(); - public List> notEncryptArrayLengthRanges = new List>(); - public List> notEncryptStringLengthRanges = new List>(); - public void InheritParent(ObfuscationRule parentRule) { if (disableEncrypt == null) @@ -84,39 +62,19 @@ namespace Obfuz.ObfusPasses.ConstEncrypt cacheStringInLoop = parentRule.cacheStringInLoop; if (cacheStringNotInLoop == null) cacheStringNotInLoop = parentRule.cacheStringNotInLoop; - - notEncryptInts.AddRange(parentRule.notEncryptInts); - notEncryptLongs.AddRange(parentRule.notEncryptLongs); - notEncryptStrings.AddRange(parentRule.notEncryptStrings); - notEncryptIntRanges.AddRange(parentRule.notEncryptIntRanges); - notEncryptLongRanges.AddRange(parentRule.notEncryptLongRanges); - notEncryptFloatRanges.AddRange(parentRule.notEncryptFloatRanges); - notEncryptDoubleRanges.AddRange(parentRule.notEncryptDoubleRanges); - notEncryptArrayLengthRanges.AddRange(parentRule.notEncryptArrayLengthRanges); - notEncryptStringLengthRanges.AddRange(parentRule.notEncryptStringLengthRanges); } } - class MethodSpec + class MethodSpec : MethodRuleBase { - public string name; - public NameMatcher nameMatcher; - public ObfuscationRule rule; } - class TypeSpec + class TypeSpec : TypeRuleBase { - public string name; - public NameMatcher nameMatcher; - public ObfuscationRule rule; - public List methods = new List(); } - class AssemblySpec + class AssemblySpec : AssemblyRuleBase { - public string name; - public ObfuscationRule rule; - public List types = new List(); } private static readonly ObfuscationRule s_default = new ObfuscationRule() @@ -137,79 +95,32 @@ namespace Obfuz.ObfusPasses.ConstEncrypt }; private ObfuscationRule _global; + + public HashSet notEncryptInts = new HashSet(); + public HashSet notEncryptLongs = new HashSet(); + public HashSet notEncryptStrings = new HashSet(); + public List> notEncryptIntRanges = new List>(); + public List> notEncryptLongRanges = new List>(); + public List> notEncryptFloatRanges = new List>(); + public List> notEncryptDoubleRanges = new List>(); + public List> notEncryptArrayLengthRanges = new List>(); + public List> notEncryptStringLengthRanges = new List>(); + + private readonly XmlAssemblyTypeMethodRuleParser _xmlParser; + private readonly Dictionary _assemblySpecs = new Dictionary(); private readonly Dictionary _methodRuleCache = new Dictionary(); public ConfigurableEncryptPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) { - _toObfuscatedAssemblyNames = toObfuscatedAssemblyNames; + _xmlParser = new XmlAssemblyTypeMethodRuleParser( + toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobalElement); LoadConfigs(xmlConfigFiles); - InheritParentRules(); } private void LoadConfigs(List configFiles) { - if (configFiles == null || configFiles.Count == 0) - { - Debug.LogWarning($"ConfigurableObfuscationPolicy::LoadConfigs configFiles is empty, using default policy"); - return; - } - foreach (var configFile in configFiles) - { - if (string.IsNullOrEmpty(configFile)) - { - throw new Exception($"ObfuzSettings.constEncryptSettings.configFiles contains empty file name"); - } - LoadConfig(configFile); - } - } - - private void LoadConfig(string configFile) - { - if (string.IsNullOrEmpty(configFile)) - { - Debug.LogWarning($"ConfigurableObfuscationPolicy::LoadConfig configFile is empty, using default policy"); - return; - } - Debug.Log($"ConfigurableObfuscationPolicy::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 "global": _global = ParseObfuscationRule(ele, true); break; - case "assembly": - { - AssemblySpec assSpec = ParseAssembly(ele); - string name = assSpec.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"); - } - _assemblySpecs.Add(name, assSpec); - break; - } - default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - } - } - - private void InheritParentRules() - { + _xmlParser.LoadConfigs(configFiles); if (_global == null) { _global = s_default; @@ -218,21 +129,19 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { _global.InheritParent(s_default); } - foreach (AssemblySpec assSpec in _assemblySpecs.Values) + _xmlParser.InheritParentRules(_global); + } + + private void ParseGlobalElement(string configFile, XmlElement ele) + { + switch (ele.Name) { - assSpec.rule.InheritParent(_global); - foreach (TypeSpec typeSpec in assSpec.types) - { - typeSpec.rule.InheritParent(assSpec.rule); - foreach (MethodSpec methodSpec in typeSpec.methods) - { - methodSpec.rule.InheritParent(typeSpec.rule); - } - } + case "global": _global = ParseObfuscationRule(configFile, ele); break; + default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); } } - private ObfuscationRule ParseObfuscationRule(XmlElement ele, bool parseWhitelist) + private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele) { var rule = new ObfuscationRule(); if (ele.HasAttribute("disableEncrypt")) @@ -288,14 +197,10 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { rule.cacheStringNotInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheStringNotInLoop")); } - if (parseWhitelist) - { - ParseWhitelist(ele, rule); - } return rule; } - private void ParseWhitelist(XmlElement ruleEle, ObfuscationRule rule) + private void ParseWhitelist(string configFile, XmlElement ruleEle) { foreach (XmlNode xmlNode in ruleEle.ChildNodes) { @@ -317,17 +222,17 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { case "int": { - rule.notEncryptInts.AddRange(value.Split(",").Select(s => int.Parse(s.Trim()))); + notEncryptInts.AddRange(value.Split(",").Select(s => int.Parse(s.Trim()))); break; } case "long": { - rule.notEncryptLongs.AddRange(value.Split(",").Select(s => long.Parse(s.Trim()))); + notEncryptLongs.AddRange(value.Split(",").Select(s => long.Parse(s.Trim()))); break; } case "string": { - rule.notEncryptStrings.AddRange(value.Split(",").Select(s => s.Trim())); + notEncryptStrings.AddRange(value.Split(",").Select(s => s.Trim())); break; } case "int-range": @@ -337,7 +242,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, int-range {value} is invalid"); } - rule.notEncryptIntRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); + notEncryptIntRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); break; } case "long-range": @@ -347,7 +252,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, long-range {value} is invalid"); } - rule.notEncryptLongRanges.Add(new NumberRange(ConfigUtil.ParseNullableLong(parts[0]), ConfigUtil.ParseNullableLong(parts[1]))); + notEncryptLongRanges.Add(new NumberRange(ConfigUtil.ParseNullableLong(parts[0]), ConfigUtil.ParseNullableLong(parts[1]))); break; } case "float-range": @@ -357,7 +262,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, float-range {value} is invalid"); } - rule.notEncryptFloatRanges.Add(new NumberRange(ConfigUtil.ParseNullableFloat(parts[0]), ConfigUtil.ParseNullableFloat(parts[1]))); + notEncryptFloatRanges.Add(new NumberRange(ConfigUtil.ParseNullableFloat(parts[0]), ConfigUtil.ParseNullableFloat(parts[1]))); break; } case "double-range": @@ -367,7 +272,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, double-range {value} is invalid"); } - rule.notEncryptDoubleRanges.Add(new NumberRange(ConfigUtil.ParseNullableDouble(parts[0]), ConfigUtil.ParseNullableDouble(parts[1]))); + notEncryptDoubleRanges.Add(new NumberRange(ConfigUtil.ParseNullableDouble(parts[0]), ConfigUtil.ParseNullableDouble(parts[1]))); break; } case "string-length-range": @@ -377,7 +282,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, string-length-range {value} is invalid"); } - rule.notEncryptStringLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); + notEncryptStringLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); break; } case "array-length-range": @@ -387,7 +292,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { throw new Exception($"Invalid xml file, array-length-range {value} is invalid"); } - rule.notEncryptArrayLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); + notEncryptArrayLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); break; } default: throw new Exception($"Invalid xml file, unknown whitelist type {type} in {childEle.Name} node"); @@ -399,105 +304,11 @@ namespace Obfuz.ObfusPasses.ConstEncrypt } } - private AssemblySpec ParseAssembly(XmlElement element) - { - var assemblySpec = new AssemblySpec(); - assemblySpec.name = element.GetAttribute("name"); - if (string.IsNullOrEmpty(assemblySpec.name)) - { - throw new Exception($"Invalid xml file, assembly name is empty"); - } - assemblySpec.rule = ParseObfuscationRule(element, false); - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "type": - assemblySpec.types.Add(ParseType(ele)); - break; - default: - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - return assemblySpec; - } - - private TypeSpec ParseType(XmlElement element) - { - var typeSpec = new TypeSpec(); - typeSpec.name = element.GetAttribute("name"); - typeSpec.nameMatcher = new NameMatcher(typeSpec.name); - if (string.IsNullOrEmpty(typeSpec.name)) - { - throw new Exception($"Invalid xml file, type name is empty"); - } - typeSpec.rule = ParseObfuscationRule(element, false); - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "method": - typeSpec.methods.Add(ParseMethod(ele)); - break; - default: - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - return typeSpec; - } - - private MethodSpec ParseMethod(XmlElement element) - { - var methodSpec = new MethodSpec(); - methodSpec.name = element.GetAttribute("name"); - methodSpec.nameMatcher = new NameMatcher(methodSpec.name); - if (string.IsNullOrEmpty(methodSpec.name)) - { - throw new Exception($"Invalid xml file, method name is empty"); - } - methodSpec.rule = ParseObfuscationRule(element, false); - return methodSpec; - } - - - private ObfuscationRule ComputeMethodObfuscationRule(MethodDef method) - { - var assemblyName = method.DeclaringType.Module.Assembly.Name; - if (!_assemblySpecs.TryGetValue(assemblyName, out var assSpec)) - { - return _global; - } - string declaringTypeName = method.DeclaringType.FullName; - foreach (var typeSpec in assSpec.types) - { - if (typeSpec.nameMatcher.IsMatch(declaringTypeName)) - { - foreach (var methodSpec in typeSpec.methods) - { - if (methodSpec.nameMatcher.IsMatch(method.Name)) - { - return methodSpec.rule; - } - } - return typeSpec.rule; - } - } - return assSpec.rule; - } - private ObfuscationRule GetMethodObfuscationRule(MethodDef method) { if (!_methodRuleCache.TryGetValue(method, out var rule)) { - rule = ComputeMethodObfuscationRule(method); + rule = _xmlParser.GetMethodRule(method, _global); _methodRuleCache[method] = rule; } return rule; @@ -532,11 +343,11 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - if (rule.notEncryptInts.Contains(value)) + if (notEncryptInts.Contains(value)) { return false; } - foreach (var range in rule.notEncryptIntRanges) + foreach (var range in notEncryptIntRanges) { if (range.min != null && value < range.min) { @@ -562,11 +373,11 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - if (rule.notEncryptLongs.Contains(value)) + if (notEncryptLongs.Contains(value)) { return false; } - foreach (var range in rule.notEncryptLongRanges) + foreach (var range in notEncryptLongRanges) { if (range.min != null && value < range.min) { @@ -592,7 +403,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - foreach (var range in rule.notEncryptFloatRanges) + foreach (var range in notEncryptFloatRanges) { if (range.min != null && value < range.min) { @@ -618,7 +429,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - foreach (var range in rule.notEncryptDoubleRanges) + foreach (var range in notEncryptDoubleRanges) { if (range.min != null && value < range.min) { @@ -644,11 +455,11 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - if (rule.notEncryptStrings.Contains(value)) + if (notEncryptStrings.Contains(value)) { return false; } - foreach (var range in rule.notEncryptStringLengthRanges) + foreach (var range in notEncryptStringLengthRanges) { if (range.min != null && value.Length < range.min) { @@ -674,7 +485,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt { return false; } - foreach (var range in rule.notEncryptArrayLengthRanges) + foreach (var range in notEncryptArrayLengthRanges) { if (range.min != null && array.Length < range.min) { diff --git a/Editor/Utils/NumberRange.cs b/Editor/Utils/NumberRange.cs new file mode 100644 index 0000000..90d55e0 --- /dev/null +++ b/Editor/Utils/NumberRange.cs @@ -0,0 +1,14 @@ +namespace Obfuz.Utils +{ + public class NumberRange where T : struct + { + public readonly T? min; + public readonly T? max; + + public NumberRange(T? min, T? max) + { + this.min = min; + this.max = max; + } + } +}