添加ControlFlowObfus基础代码

dev
walon 2025-06-22 10:39:57 +08:00
parent 0ad96daa32
commit 0508421850
11 changed files with 326 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 02fb097cf61874c41923b3ef23fee199
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,137 @@
using dnlib.DotNet;
using Obfuz.Conf;
using Obfuz.Settings;
using System;
using System.Collections.Generic;
using System.Xml;
namespace Obfuz.ObfusPasses.ControlFlowObfus
{
struct ObfuscationRuleData
{
public readonly ObfuscationLevel obfuscationLevel;
public ObfuscationRuleData(ObfuscationLevel level)
{
obfuscationLevel = level;
}
}
interface IObfuscationPolicy
{
bool NeedObfuscate(MethodDef method);
ObfuscationRuleData GetObfuscationRuleData(MethodDef method);
}
abstract class ObfuscationPolicyBase : IObfuscationPolicy
{
public abstract bool NeedObfuscate(MethodDef method);
public abstract ObfuscationRuleData GetObfuscationRuleData(MethodDef method);
}
class ConfigurableObfuscationPolicy : ObfuscationPolicyBase
{
class ObfuscationRule : IRule<ObfuscationRule>
{
public ObfuscationLevel? obfuscationLevel;
public void InheritParent(ObfuscationRule parentRule)
{
if (obfuscationLevel == null)
obfuscationLevel = parentRule.obfuscationLevel;
}
}
class MethodSpec : MethodRuleBase<ObfuscationRule>
{
}
class TypeSpec : TypeRuleBase<MethodSpec, ObfuscationRule>
{
}
class AssemblySpec : AssemblyRuleBase<TypeSpec, MethodSpec, ObfuscationRule>
{
}
private static readonly ObfuscationRule s_default = new ObfuscationRule()
{
obfuscationLevel = ObfuscationLevel.Basic,
};
private ObfuscationRule _global;
private readonly XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule> _xmlParser;
private readonly Dictionary<MethodDef, ObfuscationRule> _methodRuleCache = new Dictionary<MethodDef, ObfuscationRule>();
public ConfigurableObfuscationPolicy(List<string> toObfuscatedAssemblyNames, List<string> xmlConfigFiles)
{
_xmlParser = new XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule>(
toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobal);
LoadConfigs(xmlConfigFiles);
}
private void LoadConfigs(List<string> configFiles)
{
_xmlParser.LoadConfigs(configFiles);
if (_global == null)
{
_global = s_default;
}
else
{
_global.InheritParent(s_default);
}
_xmlParser.InheritParentRules(_global);
}
private void ParseGlobal(string configFile, XmlElement ele)
{
switch (ele.Name)
{
case "global": _global = ParseObfuscationRule(configFile, ele); break;
default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}");
}
}
private ObfuscationLevel ParseObfuscationLevel(string str)
{
return (ObfuscationLevel)Enum.Parse(typeof(ObfuscationLevel), str);
}
private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele)
{
var rule = new ObfuscationRule();
if (ele.HasAttribute("obfuscationLevel"))
{
rule.obfuscationLevel = ParseObfuscationLevel(ele.GetAttribute("obfuscationLevel"));
}
return rule;
}
private ObfuscationRule GetMethodObfuscationRule(MethodDef method)
{
if (!_methodRuleCache.TryGetValue(method, out var rule))
{
rule = _xmlParser.GetMethodRule(method, s_default);
_methodRuleCache[method] = rule;
}
return rule;
}
public override bool NeedObfuscate(MethodDef method)
{
ObfuscationRule rule = GetMethodObfuscationRule(method);
return rule.obfuscationLevel.Value > ObfuscationLevel.None;
}
public override ObfuscationRuleData GetObfuscationRuleData(MethodDef method)
{
var rule = GetMethodObfuscationRule(method);
return new ObfuscationRuleData(rule.obfuscationLevel.Value);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6983877d8859df4882c30f75be7a70e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,73 @@
using dnlib.DotNet;
using Obfuz.Data;
using Obfuz.Emit;
using Obfuz.Settings;
using Obfuz.Utils;
namespace Obfuz.ObfusPasses.ControlFlowObfus
{
class ObfusMethodContext
{
public MethodDef method;
public LocalVariableAllocator localVariableAllocator;
public IRandom localRandom;
public EncryptionScopeInfo encryptionScope;
public DefaultMetadataImporter importer;
public ModuleConstFieldAllocator constFieldAllocator;
}
internal class ControlFlowObfusPass : ObfuscationMethodPassBase
{
private readonly ControlFlowObfuscationSettingsFacade _settings;
private IObfuscationPolicy _obfuscationPolicy;
private IObfuscator _obfuscator;
public ControlFlowObfusPass(ControlFlowObfuscationSettingsFacade settings)
{
_settings = settings;
_obfuscator = new DefaultObfuscator();
}
public override ObfuscationPassType Type => ObfuscationPassType.ControlFlowObfus;
public override void Start()
{
ObfuscationPassContext ctx = ObfuscationPassContext.Current;
_obfuscationPolicy = new ConfigurableObfuscationPolicy(
ctx.coreSettings.assembliesToObfuscate,
_settings.ruleFiles);
}
public override void Stop()
{
}
protected override bool NeedObfuscateMethod(MethodDef method)
{
return _obfuscationPolicy.NeedObfuscate(method);
}
protected override void ObfuscateData(MethodDef method)
{
//Debug.Log($"Obfuscating method: {method.FullName} with EvalStackObfusPass");
ObfuscationPassContext ctx = ObfuscationPassContext.Current;
var calc = new BasicBlockCollection(method, false);
var encryptionScope = ctx.encryptionScopeProvider.GetScope(method.Module);
var ruleData = _obfuscationPolicy.GetObfuscationRuleData(method);
var localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method));
var obfusMethodCtx = new ObfusMethodContext
{
method = method,
localVariableAllocator = new LocalVariableAllocator(method),
encryptionScope = encryptionScope,
constFieldAllocator = ctx.constFieldAllocator.GetModuleAllocator(method.Module),
localRandom = localRandom,
importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, ctx.encryptionScopeProvider),
};
_obfuscator.Obfuscate(calc, obfusMethodCtx);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf62db4d3137e6447bd5cb2a65f101d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using Obfuz.Emit;
namespace Obfuz.ObfusPasses.ControlFlowObfus
{
class DefaultObfuscator : ObfuscatorBase
{
public override bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx)
{
throw new System.NotImplementedException();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8aa2a2e43fa066541b982dbb63452458
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
using Obfuz.Emit;
namespace Obfuz.ObfusPasses.ControlFlowObfus
{
interface IObfuscator
{
bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx);
}
abstract class ObfuscatorBase : IObfuscator
{
public abstract bool Obfuscate(BasicBlockCollection basicBlocks, ObfusMethodContext ctx);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ada5f6005768f745a18dc8b968e1684
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Obfuz.Settings
{
public class ControlFlowObfuscationSettingsFacade
{
public List<string> ruleFiles;
}
[Serializable]
public class ControlFlowObfuscationSettings
{
[Tooltip("rule config xml files")]
public string[] ruleFiles;
public ControlFlowObfuscationSettingsFacade ToFacade()
{
return new ControlFlowObfuscationSettingsFacade
{
ruleFiles = new List<string>(ruleFiles ?? Array.Empty<string>()),
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d40d2fb33f081b2458505c7566b1bc8f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: