支持FieldEncrypt

backup
walon 2025-05-10 19:50:03 +08:00
parent f0bec3fab9
commit 18800f78c4
7 changed files with 255 additions and 16 deletions

View File

@ -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;
}
}
}

View File

@ -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<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)
{
TypeDef type = field.DeclaringType;
// TODO
if (type.Name == "EncryptField" || type.Name == "EncryptProperty")
{
return true;
}
return false;
var rule = _configParser.GetFieldRule(field);
return rule != null;
}
}
}

View File

@ -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<string> _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:

View File

@ -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())

View File

@ -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))
{

View File

@ -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;

View File

@ -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);