支持pass配置
parent
ac15ef8ebc
commit
d3e6e13419
|
@ -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<FieldSpec> fields = new List<FieldSpec>();
|
||||||
|
public List<MethodSpec> methods = new List<MethodSpec>();
|
||||||
|
public List<PropertySpec> properties = new List<PropertySpec>();
|
||||||
|
public List<EventSpec> events = new List<EventSpec>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssemblySpec
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public NameMatcher nameMatcher;
|
||||||
|
public PassRule rule;
|
||||||
|
public List<TypeSpec> types = new List<TypeSpec>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ObfuscationPassType _enabledPasses;
|
||||||
|
private readonly HashSet<string> _toObfuscatedAssemblyNames;
|
||||||
|
private readonly List<AssemblySpec> _assemblySpecs = new List<AssemblySpec>();
|
||||||
|
private readonly PassRule _defaultPassRule;
|
||||||
|
|
||||||
|
private string _curLoadingConfig;
|
||||||
|
|
||||||
|
public ConfigurablePassPolicy(IEnumerable<string> toObfuscatedAssemblyNames, ObfuscationPassType enabledPasses, List<string> configFiles)
|
||||||
|
{
|
||||||
|
_toObfuscatedAssemblyNames = new HashSet<string>(toObfuscatedAssemblyNames);
|
||||||
|
_enabledPasses = enabledPasses;
|
||||||
|
_defaultPassRule = new PassRule { finalPasses = enabledPasses };
|
||||||
|
LoadConfigs(configFiles);
|
||||||
|
InheritParentRules(enabledPasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadConfigs(IEnumerable<string> 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<FieldSpec> fields = typeSpec.fields;
|
||||||
|
List<MethodSpec> methods = typeSpec.methods;
|
||||||
|
List<PropertySpec> properties = typeSpec.properties;
|
||||||
|
List<EventSpec> 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<ModuleDef, (AssemblySpec, PassRule)> _modulePassRuleCaches = new Dictionary<ModuleDef, (AssemblySpec, PassRule)>();
|
||||||
|
private readonly Dictionary<TypeDef, (TypeSpec, PassRule)> _typePassRuleCaches = new Dictionary<TypeDef, (TypeSpec, PassRule)>();
|
||||||
|
private readonly Dictionary<MethodDef, (MethodSpec, PassRule)> _methodPassRuleCaches = new Dictionary<MethodDef, (MethodSpec, PassRule)>();
|
||||||
|
private readonly Dictionary<FieldDef, (FieldSpec, PassRule)> _fieldPassRuleCaches = new Dictionary<FieldDef, (FieldSpec, PassRule)>();
|
||||||
|
private readonly Dictionary<PropertyDef, (PropertySpec, PassRule)> _propertyPassRuleCaches = new Dictionary<PropertyDef, (PropertySpec, PassRule)>();
|
||||||
|
private readonly Dictionary<EventDef, (EventSpec, PassRule)> _eventPassRuleCaches = new Dictionary<EventDef, (EventSpec, PassRule)>();
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using Obfuz.ObfusPasses;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -8,6 +9,8 @@ namespace Obfuz
|
||||||
{
|
{
|
||||||
public interface IObfuscationPass
|
public interface IObfuscationPass
|
||||||
{
|
{
|
||||||
|
ObfuscationPassType Type { get; }
|
||||||
|
|
||||||
void Start(ObfuscationPassContext ctx);
|
void Start(ObfuscationPassContext ctx);
|
||||||
|
|
||||||
void Stop(ObfuscationPassContext ctx);
|
void Stop(ObfuscationPassContext ctx);
|
||||||
|
|
|
@ -13,23 +13,24 @@ namespace Obfuz.ObfusPasses
|
||||||
public override void Process(ObfuscationPassContext ctx)
|
public override void Process(ObfuscationPassContext ctx)
|
||||||
{
|
{
|
||||||
NotObfuscatedMethodWhiteList whiteList = ctx.whiteList;
|
NotObfuscatedMethodWhiteList whiteList = ctx.whiteList;
|
||||||
|
ConfigurablePassPolicy passPolicy = ctx.passPolicy;
|
||||||
foreach (ModuleDef mod in ctx.toObfuscatedModules)
|
foreach (ModuleDef mod in ctx.toObfuscatedModules)
|
||||||
{
|
{
|
||||||
if (whiteList.IsInWhiteList(mod))
|
if (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 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())
|
||||||
{
|
{
|
||||||
if (whiteList.IsInWhiteList(type))
|
if (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// ToArray to avoid modify list exception
|
// ToArray to avoid modify list exception
|
||||||
foreach (MethodDef method in type.Methods.ToArray())
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace Obfuz.ObfusPasses.CallObfus
|
||||||
private IObfuscator _dynamicProxyObfuscator;
|
private IObfuscator _dynamicProxyObfuscator;
|
||||||
private IObfuscationPolicy _dynamicProxyPolicy;
|
private IObfuscationPolicy _dynamicProxyPolicy;
|
||||||
|
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.CallObfus;
|
||||||
|
|
||||||
public CallObfusPass(CallObfusSettings settings)
|
public CallObfusPass(CallObfusSettings settings)
|
||||||
{
|
{
|
||||||
_configFiles = settings.configFiles.ToList();
|
_configFiles = settings.configFiles.ToList();
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace Obfuz.ObfusPasses.CleanUp
|
||||||
{
|
{
|
||||||
public class CleanUpInstructionPass : ObfuscationPassBase
|
public class CleanUpInstructionPass : ObfuscationPassBase
|
||||||
{
|
{
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.None;
|
||||||
|
|
||||||
public override void Start(ObfuscationPassContext ctx)
|
public override void Start(ObfuscationPassContext ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
private readonly int _encryptionLevel;
|
private readonly int _encryptionLevel;
|
||||||
private IEncryptPolicy _dataObfuscatorPolicy;
|
private IEncryptPolicy _dataObfuscatorPolicy;
|
||||||
private IConstEncryptor _dataObfuscator;
|
private IConstEncryptor _dataObfuscator;
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.ConstEncrypt;
|
||||||
|
|
||||||
public ConstEncryptPass(ConstEncryptSettings settings)
|
public ConstEncryptPass(ConstEncryptSettings settings)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Obfuz.ObfusPasses.ExprObfus
|
||||||
{
|
{
|
||||||
public class ExprObfusPass : InstructionObfuscationPassBase
|
public class ExprObfusPass : InstructionObfuscationPassBase
|
||||||
{
|
{
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.ExprObfus;
|
||||||
|
|
||||||
public override void Start(ObfuscationPassContext ctx)
|
public override void Start(ObfuscationPassContext ctx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,8 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
private IEncryptPolicy _encryptionPolicy;
|
private IEncryptPolicy _encryptionPolicy;
|
||||||
private IFieldEncryptor _memoryEncryptor;
|
private IFieldEncryptor _memoryEncryptor;
|
||||||
|
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.FieldEncrypt;
|
||||||
|
|
||||||
public FieldEncryptPass(FieldEncryptSettings settings)
|
public FieldEncryptPass(FieldEncryptSettings settings)
|
||||||
{
|
{
|
||||||
_configFiles = settings.configFiles.ToList();
|
_configFiles = settings.configFiles.ToList();
|
||||||
|
|
|
@ -15,23 +15,24 @@ namespace Obfuz.ObfusPasses
|
||||||
{
|
{
|
||||||
var modules = NeedProcessNotObfuscatedAssembly ? ctx.obfuscatedAndNotObfuscatedModules : ctx.toObfuscatedModules;
|
var modules = NeedProcessNotObfuscatedAssembly ? ctx.obfuscatedAndNotObfuscatedModules : ctx.toObfuscatedModules;
|
||||||
NotObfuscatedMethodWhiteList whiteList = ctx.whiteList;
|
NotObfuscatedMethodWhiteList whiteList = ctx.whiteList;
|
||||||
|
ConfigurablePassPolicy passPolicy = ctx.passPolicy;
|
||||||
foreach (ModuleDef mod in modules)
|
foreach (ModuleDef mod in modules)
|
||||||
{
|
{
|
||||||
if (whiteList.IsInWhiteList(mod))
|
if (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 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())
|
||||||
{
|
{
|
||||||
if (whiteList.IsInWhiteList(type))
|
if (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// ToArray to avoid modify list exception
|
// ToArray to avoid modify list exception
|
||||||
foreach (MethodDef method in type.Methods.ToArray())
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,13 @@ namespace Obfuz.ObfusPasses
|
||||||
{
|
{
|
||||||
public abstract class ObfuscationPassBase : IObfuscationPass
|
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 Start(ObfuscationPassContext ctx);
|
||||||
|
|
||||||
public abstract void Stop(ObfuscationPassContext ctx);
|
public abstract void Stop(ObfuscationPassContext ctx);
|
||||||
|
|
|
@ -15,6 +15,11 @@ namespace Obfuz.ObfusPasses
|
||||||
ExprObfus = 0x400,
|
ExprObfus = 0x400,
|
||||||
ControlFlowObfus = 0x800,
|
ControlFlowObfus = 0x800,
|
||||||
|
|
||||||
|
AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus,
|
||||||
|
AllEncrypt = ConstEncrypt | FieldEncrypt,
|
||||||
|
|
||||||
|
MethodBodyObfusOrEncrypt = ConstEncrypt | CallObfus | ExprObfus | ControlFlowObfus,
|
||||||
|
|
||||||
All = ~0,
|
All = ~0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ namespace Obfuz.ObfusPasses.SymbolObfus
|
||||||
{
|
{
|
||||||
private SymbolRename _symbolRename;
|
private SymbolRename _symbolRename;
|
||||||
|
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.SymbolObfus;
|
||||||
|
|
||||||
public SymbolObfusPass(SymbolObfusSettings settings)
|
public SymbolObfusPass(SymbolObfusSettings settings)
|
||||||
{
|
{
|
||||||
_symbolRename = new SymbolRename(settings);
|
_symbolRename = new SymbolRename(settings);
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace Obfuz.ObfusPasses.SymbolObfus
|
||||||
_obfuscatedAndNotObfuscatedModules = ctx.obfuscatedAndNotObfuscatedModules;
|
_obfuscatedAndNotObfuscatedModules = ctx.obfuscatedAndNotObfuscatedModules;
|
||||||
_toObfuscatedModuleSet = ctx.toObfuscatedModules.ToHashSet();
|
_toObfuscatedModuleSet = ctx.toObfuscatedModules.ToHashSet();
|
||||||
var obfuscateRuleConfig = new ConfigurableRenamePolicy(ctx.toObfuscatedAssemblyNames, _obfuscationRuleFiles);
|
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();
|
BuildCustomAttributeArguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,6 @@ namespace Obfuz
|
||||||
public ConstFieldAllocator constFieldAllocator;
|
public ConstFieldAllocator constFieldAllocator;
|
||||||
public RvaDataAllocator rvaDataAllocator;
|
public RvaDataAllocator rvaDataAllocator;
|
||||||
public NotObfuscatedMethodWhiteList whiteList;
|
public NotObfuscatedMethodWhiteList whiteList;
|
||||||
|
public ConfigurablePassPolicy passPolicy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace Obfuz
|
||||||
private readonly List<string> _notObfuscatedAssemblyNamesReferencingObfuscated;
|
private readonly List<string> _notObfuscatedAssemblyNamesReferencingObfuscated;
|
||||||
private readonly List<string> _assemblySearchDirs;
|
private readonly List<string> _assemblySearchDirs;
|
||||||
|
|
||||||
|
private readonly ConfigurablePassPolicy _passPolicy;
|
||||||
|
|
||||||
private readonly Pipeline _pipeline1 = new Pipeline();
|
private readonly Pipeline _pipeline1 = new Pipeline();
|
||||||
private readonly Pipeline _pipeline2 = new Pipeline();
|
private readonly Pipeline _pipeline2 = new Pipeline();
|
||||||
private readonly byte[] _secret;
|
private readonly byte[] _secret;
|
||||||
|
@ -51,6 +53,8 @@ namespace Obfuz
|
||||||
_obfuscatedAssemblyOutputDir = builder.ObfuscatedAssemblyOutputDir;
|
_obfuscatedAssemblyOutputDir = builder.ObfuscatedAssemblyOutputDir;
|
||||||
_assemblySearchDirs = builder.AssemblySearchDirs;
|
_assemblySearchDirs = builder.AssemblySearchDirs;
|
||||||
|
|
||||||
|
_passPolicy = new ConfigurablePassPolicy(_toObfuscatedAssemblyNames, builder.EnableObfuscationPasses, builder.ObfuscationPassConfigFiles);
|
||||||
|
|
||||||
foreach (var pass in builder.ObfuscationPasses)
|
foreach (var pass in builder.ObfuscationPasses)
|
||||||
{
|
{
|
||||||
if (pass is SymbolObfusPass symbolObfusPass)
|
if (pass is SymbolObfusPass symbolObfusPass)
|
||||||
|
@ -176,6 +180,7 @@ namespace Obfuz
|
||||||
rvaDataAllocator = rvaDataAllocator,
|
rvaDataAllocator = rvaDataAllocator,
|
||||||
constFieldAllocator = constFieldAllocator,
|
constFieldAllocator = constFieldAllocator,
|
||||||
whiteList = new NotObfuscatedMethodWhiteList(),
|
whiteList = new NotObfuscatedMethodWhiteList(),
|
||||||
|
passPolicy = _passPolicy,
|
||||||
};
|
};
|
||||||
pipeline.Start(_ctx);
|
pipeline.Start(_ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ namespace Obfuz
|
||||||
private List<string> _assemblySearchDirs = new List<string>();
|
private List<string> _assemblySearchDirs = new List<string>();
|
||||||
|
|
||||||
private string _obfuscatedAssemblyOutputDir;
|
private string _obfuscatedAssemblyOutputDir;
|
||||||
|
private List<string> _obfuscationPassConfigFiles;
|
||||||
|
|
||||||
|
private ObfuscationPassType _enabledObfuscationPasses;
|
||||||
private List<IObfuscationPass> _obfuscationPasses = new List<IObfuscationPass>();
|
private List<IObfuscationPass> _obfuscationPasses = new List<IObfuscationPass>();
|
||||||
|
|
||||||
public string Secret
|
public string Secret
|
||||||
|
@ -89,7 +92,23 @@ namespace Obfuz
|
||||||
set => _obfuscatedAssemblyOutputDir = value;
|
set => _obfuscatedAssemblyOutputDir = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IObfuscationPass> ObfuscationPasses { get => _obfuscationPasses; set => _obfuscationPasses = value; }
|
public ObfuscationPassType EnableObfuscationPasses
|
||||||
|
{
|
||||||
|
get => _enabledObfuscationPasses;
|
||||||
|
set => _enabledObfuscationPasses = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> ObfuscationPassConfigFiles
|
||||||
|
{
|
||||||
|
get => _obfuscationPassConfigFiles;
|
||||||
|
set => _obfuscationPassConfigFiles = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IObfuscationPass> ObfuscationPasses
|
||||||
|
{
|
||||||
|
get => _obfuscationPasses;
|
||||||
|
set => _obfuscationPasses = value;
|
||||||
|
}
|
||||||
|
|
||||||
public void InsertTopPriorityAssemblySearchDirs(List<string> assemblySearchDirs)
|
public void InsertTopPriorityAssemblySearchDirs(List<string> assemblySearchDirs)
|
||||||
{
|
{
|
||||||
|
@ -139,6 +158,8 @@ namespace Obfuz
|
||||||
_notObfuscatedAssemblyNamesReferencingObfuscated = settings.assemblySettings.notObfuscatedAssemblyNamesReferencingObfuscated.ToList(),
|
_notObfuscatedAssemblyNamesReferencingObfuscated = settings.assemblySettings.notObfuscatedAssemblyNamesReferencingObfuscated.ToList(),
|
||||||
_assemblySearchDirs = BuildUnityAssemblySearchPaths().Concat(settings.assemblySettings.extraAssemblySearchDirs).ToList(),
|
_assemblySearchDirs = BuildUnityAssemblySearchPaths().Concat(settings.assemblySettings.extraAssemblySearchDirs).ToList(),
|
||||||
_obfuscatedAssemblyOutputDir = settings.GetObfuscatedAssemblyOutputDir(target),
|
_obfuscatedAssemblyOutputDir = settings.GetObfuscatedAssemblyOutputDir(target),
|
||||||
|
_enabledObfuscationPasses = settings.obfuscationPassSettings.enabledPasses,
|
||||||
|
_obfuscationPassConfigFiles = settings.obfuscationPassSettings.configFiles.ToList(),
|
||||||
};
|
};
|
||||||
ObfuscationPassType obfuscationPasses = settings.obfuscationPassSettings.enabledPasses;
|
ObfuscationPassType obfuscationPasses = settings.obfuscationPassSettings.enabledPasses;
|
||||||
if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt))
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt))
|
||||||
|
|
Loading…
Reference in New Issue