支持FieldEncrypt
parent
f0bec3fab9
commit
18800f78c4
|
@ -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<R> where R : class, new()
|
||||||
|
{
|
||||||
|
private readonly HashSet<string> _toObfuscatedAssemblyNames;
|
||||||
|
private readonly Func<string, XmlElement, R> _ruleParser;
|
||||||
|
private readonly Action<string, XmlElement> _unknownNodeTypeHandler;
|
||||||
|
private readonly Dictionary<string, AssemblySpec> _assemblySpecs = new Dictionary<string, AssemblySpec>();
|
||||||
|
|
||||||
|
|
||||||
|
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<FieldSpec> Fields { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AssemblySpec
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public List<TypeSpec> Types { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlFieldRuleParser(IEnumerable<string> toObfuscatedAssemblyNames, Func<string, XmlElement, R> ruleParser, Action<string, XmlElement> unknownNodeTypeHandler)
|
||||||
|
{
|
||||||
|
_toObfuscatedAssemblyNames = new HashSet<string>(toObfuscatedAssemblyNames);
|
||||||
|
_ruleParser = ruleParser;
|
||||||
|
_unknownNodeTypeHandler = unknownNodeTypeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadConfigs(IEnumerable<string> 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<TypeSpec>();
|
||||||
|
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<FieldSpec>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,36 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using Obfuz.Conf;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.FieldEncrypt
|
namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
{
|
{
|
||||||
public class ConfigurableEncryptPolicy : EncryptPolicyBase
|
public class ConfigurableEncryptPolicy : EncryptPolicyBase
|
||||||
{
|
{
|
||||||
|
class ObfuscationRule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly XmlFieldRuleParser<ObfuscationRule> _configParser;
|
||||||
|
|
||||||
|
public ConfigurableEncryptPolicy(List<string> toObfuscatedAssemblyNames, List<string> configFiles)
|
||||||
|
{
|
||||||
|
_configParser = new XmlFieldRuleParser<ObfuscationRule>(toObfuscatedAssemblyNames, ParseRule, null);
|
||||||
|
_configParser.LoadConfigs(configFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObfuscationRule ParseRule(string configFile, XmlElement ele)
|
||||||
|
{
|
||||||
|
return new ObfuscationRule();
|
||||||
|
}
|
||||||
|
|
||||||
public override bool NeedEncrypt(FieldDef field)
|
public override bool NeedEncrypt(FieldDef field)
|
||||||
{
|
{
|
||||||
TypeDef type = field.DeclaringType;
|
var rule = _configParser.GetFieldRule(field);
|
||||||
// TODO
|
return rule != null;
|
||||||
if (type.Name == "EncryptField" || type.Name == "EncryptProperty")
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
using Obfuz;
|
using Obfuz;
|
||||||
|
using Obfuz.Settings;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.FieldEncrypt
|
namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
|
@ -10,13 +12,21 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
|
|
||||||
public class FieldEncryptPass : InstructionObfuscationPassBase
|
public class FieldEncryptPass : InstructionObfuscationPassBase
|
||||||
{
|
{
|
||||||
private readonly IEncryptPolicy _encryptionPolicy = new ConfigurableEncryptPolicy();
|
private readonly List<string> _configFiles;
|
||||||
|
private IEncryptPolicy _encryptionPolicy;
|
||||||
private IFieldEncryptor _memoryEncryptor;
|
private IFieldEncryptor _memoryEncryptor;
|
||||||
|
|
||||||
|
public FieldEncryptPass(FieldEncryptSettings settings)
|
||||||
|
{
|
||||||
|
_configFiles = settings.configFiles.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool NeedProcessNotObfuscatedAssembly => true;
|
||||||
|
|
||||||
public override void Start(ObfuscationPassContext ctx)
|
public override void Start(ObfuscationPassContext ctx)
|
||||||
{
|
{
|
||||||
_memoryEncryptor = new DefaultFieldEncryptor(ctx.random, ctx.encryptor);
|
_memoryEncryptor = new DefaultFieldEncryptor(ctx.random, ctx.encryptor);
|
||||||
|
_encryptionPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Stop(ObfuscationPassContext ctx)
|
public override void Stop(ObfuscationPassContext ctx)
|
||||||
|
@ -57,11 +67,6 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var ctx = new MemoryEncryptionContext
|
|
||||||
{
|
|
||||||
module = callingMethod.Module,
|
|
||||||
currentInstruction = inst,
|
|
||||||
};
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case Code.Ldfld:
|
case Code.Ldfld:
|
||||||
|
|
|
@ -7,11 +7,14 @@ namespace Obfuz.ObfusPasses
|
||||||
{
|
{
|
||||||
public abstract class InstructionObfuscationPassBase : ObfuscationPassBase
|
public abstract class InstructionObfuscationPassBase : ObfuscationPassBase
|
||||||
{
|
{
|
||||||
|
protected virtual bool NeedProcessNotObfuscatedAssembly => false;
|
||||||
|
|
||||||
protected abstract bool NeedObfuscateMethod(MethodDef method);
|
protected abstract bool NeedObfuscateMethod(MethodDef method);
|
||||||
|
|
||||||
public override void Process(ObfuscationPassContext ctx)
|
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
|
// ToArray to avoid modify list exception
|
||||||
foreach (TypeDef type in mod.GetTypes().ToArray())
|
foreach (TypeDef type in mod.GetTypes().ToArray())
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace Obfuz
|
||||||
ObfuscationPassType obfuscationPasses = settings.enabledObfuscationPasses;
|
ObfuscationPassType obfuscationPasses = settings.enabledObfuscationPasses;
|
||||||
if (obfuscationPasses.HasFlag(ObfuscationPassType.MemoryEncryption))
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.MemoryEncryption))
|
||||||
{
|
{
|
||||||
builder.AddPass(new FieldEncryptPass());
|
builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings));
|
||||||
}
|
}
|
||||||
if (obfuscationPasses.HasFlag(ObfuscationPassType.CallProxy))
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.CallProxy))
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace Obfuz.Settings
|
||||||
[Tooltip("const encryption settings")]
|
[Tooltip("const encryption settings")]
|
||||||
public ConstEncryptSettings constEncryptSettings;
|
public ConstEncryptSettings constEncryptSettings;
|
||||||
|
|
||||||
|
[Tooltip("field encryption settings")]
|
||||||
|
public FieldEncryptSettings fieldEncryptSettings;
|
||||||
|
|
||||||
[Tooltip("call obfuscation settings")]
|
[Tooltip("call obfuscation settings")]
|
||||||
public CallObfusSettings callObfusSettings;
|
public CallObfusSettings callObfusSettings;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
private SerializedProperty _symbolObfusSettings;
|
private SerializedProperty _symbolObfusSettings;
|
||||||
private SerializedProperty _constEncryptSettings;
|
private SerializedProperty _constEncryptSettings;
|
||||||
|
private SerializedProperty _fieldEncryptSettings;
|
||||||
private SerializedProperty _callObfusSettings;
|
private SerializedProperty _callObfusSettings;
|
||||||
|
|
||||||
public ObfuzSettingsProvider() : base("Project/Obfuz", SettingsScope.Project)
|
public ObfuzSettingsProvider() : base("Project/Obfuz", SettingsScope.Project)
|
||||||
|
@ -67,6 +68,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
|
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
|
||||||
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
|
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
|
||||||
|
_fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings");
|
||||||
_callObfusSettings = _serializedObject.FindProperty("callObfusSettings");
|
_callObfusSettings = _serializedObject.FindProperty("callObfusSettings");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +89,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_symbolObfusSettings);
|
EditorGUILayout.PropertyField(_symbolObfusSettings);
|
||||||
EditorGUILayout.PropertyField(_constEncryptSettings);
|
EditorGUILayout.PropertyField(_constEncryptSettings);
|
||||||
|
EditorGUILayout.PropertyField(_fieldEncryptSettings);
|
||||||
EditorGUILayout.PropertyField(_callObfusSettings);
|
EditorGUILayout.PropertyField(_callObfusSettings);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue