调整和重构CallObfus的代码

backup
walon 2025-05-09 20:18:24 +08:00
parent cf67f63066
commit 83c0b921e3
15 changed files with 108 additions and 51 deletions

View File

@ -268,7 +268,7 @@ namespace Obfuz.Data
private ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleConstFieldAllocator>(mod, m => new ModuleConstFieldAllocator(_encryptor, _random, _rvaDataAllocator));
return EmitManager.Ins.GetEmitManager<ModuleConstFieldAllocator>(mod, () => new ModuleConstFieldAllocator(_encryptor, _random, _rvaDataAllocator));
}
public FieldDef Allocate(ModuleDef mod, int value)

View File

@ -28,9 +28,9 @@ namespace Obfuz.Data
public class ModuleRvaDataAllocator : ModuleEmitManagerBase
{
// randomized
const int maxRvaDataSize = 0x100;
const int maxRvaDataSize = 0x1000;
private readonly ModuleDef _module;
private ModuleDef _module;
private readonly IRandom _random;
private readonly IEncryptor _encryptor;
@ -69,16 +69,15 @@ namespace Obfuz.Data
private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>();
public ModuleRvaDataAllocator(ModuleDef mod, IRandom random, IEncryptor encryptor)
public ModuleRvaDataAllocator(IRandom random, IEncryptor encryptor)
{
_module = mod;
_random = random;
_encryptor = encryptor;
}
public override void Init(ModuleDef mod)
{
_module = mod;
}
private (FieldDef, FieldDef) CreateDataHolderRvaField(TypeDef dataHolderType)
@ -297,7 +296,7 @@ namespace Obfuz.Data
private ModuleRvaDataAllocator GetModuleRvaDataAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleRvaDataAllocator>(mod, mod => new ModuleRvaDataAllocator(mod, _random, _encryptor));
return EmitManager.Ins.GetEmitManager<ModuleRvaDataAllocator>(mod, () => new ModuleRvaDataAllocator(_random, _encryptor));
}
public RvaData Allocate(ModuleDef mod, int value)

View File

@ -29,7 +29,7 @@ namespace Obfuz.Emit
Ins = new EmitManager();
}
public T GetEmitManager<T>(ModuleDef mod, Func<ModuleDef, T> creator = null) where T : IModuleEmitManager
public T GetEmitManager<T>(ModuleDef mod, Func<T> creator = null) where T : IModuleEmitManager
{
var key = (mod, typeof(T));
if (_moduleEmitManagers.TryGetValue(key, out var emitManager))
@ -41,7 +41,7 @@ namespace Obfuz.Emit
T newEmitManager;
if (creator != null)
{
newEmitManager = creator(mod);
newEmitManager = creator();
}
else
{

View File

@ -9,20 +9,23 @@ using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.Assertions;
using Obfuz.Settings;
namespace Obfuz.ObfusPasses.CallObfus
{
public class ProxyCallPass : InstructionObfuscationPassBase
public class CallObfusPass : InstructionObfuscationPassBase
{
private readonly IRandom _random;
private readonly IProxyCallPolicy _dynamicProxyPolicy;
private readonly IProxyCallObfuscator _dynamicProxyObfuscator;
private readonly IEncryptor _encryptor;
private readonly ICallObfusPolicy _dynamicProxyPolicy;
private readonly ICallObfuscator _dynamicProxyObfuscator;
public ProxyCallPass()
public CallObfusPass(CallObfusSettings settings)
{
_random = new RandomWithKey(new byte[] { 0x1, 0x2, 0x3, 0x4 }, 0x5);
_dynamicProxyPolicy = new ConfigProxyCallPolicy();
_dynamicProxyObfuscator = new DefaultProxyCallObfuscator(_random);
_encryptor = new DefaultEncryptor(new byte[] { 0x1A, 0x2B, 0x3C, 0x4D });
_dynamicProxyPolicy = new ConfigurableCallObfusPolicy();
_dynamicProxyObfuscator = new DefaultProxyCallObfuscator(_random, _encryptor);
}
public override void Stop(ObfuscationPassContext ctx)

View File

@ -2,7 +2,7 @@
namespace Obfuz.ObfusPasses.CallObfus
{
public abstract class ProxyCallPolicyBase : IProxyCallPolicy
public abstract class CallObfusPolicyBase : ICallObfusPolicy
{
public abstract bool NeedDynamicProxyCallInMethod(MethodDef method);

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace Obfuz.ObfusPasses.CallObfus
{
public abstract class ProxyCallObfuscatorBase : IProxyCallObfuscator
public abstract class CallObfuscatorBase : ICallObfuscator
{
public abstract void Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions);
public abstract void Done();

View File

@ -1,5 +1,6 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using Obfuz.Utils;
using System;
using System.Collections.Generic;
@ -14,19 +15,24 @@ namespace Obfuz.ObfusPasses.CallObfus
public struct ProxyCallMethodData
{
public readonly MethodDef proxyMethod;
public readonly int secret;
public readonly int encryptOps;
public readonly int salt;
public readonly int encryptedIndex;
public ProxyCallMethodData(MethodDef proxyMethod, int secret)
public ProxyCallMethodData(MethodDef proxyMethod, int encryptOps, int salt, int encryptedIndex)
{
this.proxyMethod = proxyMethod;
this.secret = secret;
this.encryptOps = encryptOps;
this.salt = salt;
this.encryptedIndex = encryptedIndex;
}
}
class ModuleDynamicProxyMethodAllocator
class ModuleCallProxyAllocator : IModuleEmitManager
{
private readonly ModuleDef _module;
private ModuleDef _module;
private readonly IRandom _random;
private readonly IEncryptor _encryptor;
class MethodKey : IEquatable<MethodKey>
{
@ -55,7 +61,11 @@ namespace Obfuz.ObfusPasses.CallObfus
class MethodProxyInfo
{
public MethodDef proxyMethod;
public int secret;
public int index;
public int encryptedOps;
public int salt;
public int encryptedIndex;
}
private readonly Dictionary<MethodKey, MethodProxyInfo> _methodProxys = new Dictionary<MethodKey, MethodProxyInfo>();
@ -72,7 +82,6 @@ namespace Obfuz.ObfusPasses.CallObfus
class DispatchMethodInfo
{
public MethodDef methodDef;
public int secret;
public List<CallInfo> methods = new List<CallInfo>();
}
@ -81,10 +90,15 @@ namespace Obfuz.ObfusPasses.CallObfus
private TypeDef _proxyTypeDef;
public ModuleDynamicProxyMethodAllocator(ModuleDef module, IRandom random)
public ModuleCallProxyAllocator(IRandom random, IEncryptor encryptor)
{
_module = module;
_random = random;
_encryptor = encryptor;
}
public void Init(ModuleDef mod)
{
_module = mod;
}
private TypeDef CreateProxyTypeDef()
@ -128,11 +142,21 @@ namespace Obfuz.ObfusPasses.CallObfus
break;
}
}
// extra param for secret
// extra param for index
methodSig.Params.Add(_module.CorLibTypes.Int32);
return MethodSig.CreateStatic(methodSig.RetType, methodSig.Params.ToArray());
}
private int GenerateSalt()
{
return _random.NextInt();
}
private int GenerateEncryptOps()
{
return _random.NextInt();
}
private DispatchMethodInfo GetDispatchMethod(IMethod method)
{
MethodSig methodSig = CreateDispatchMethodSig(method);
@ -146,7 +170,6 @@ namespace Obfuz.ObfusPasses.CallObfus
var newDispatchMethodInfo = new DispatchMethodInfo
{
methodDef = CreateDispatchMethodInfo(methodSig),
secret = 0,
};
dispatchMethods.Add(newDispatchMethodInfo);
}
@ -159,15 +182,23 @@ namespace Obfuz.ObfusPasses.CallObfus
if (!_methodProxys.TryGetValue(key, out var proxyInfo))
{
var methodDispatcher = GetDispatchMethod(method);
int index = methodDispatcher.methods.Count;
int encryptOps = GenerateEncryptOps();
int salt = GenerateSalt();
int encryptedIndex = _encryptor.Encrypt(index, encryptOps, salt);
proxyInfo = new MethodProxyInfo()
{
proxyMethod = methodDispatcher.methodDef,
secret = methodDispatcher.methods.Count,
index = index,
encryptedOps = encryptOps,
salt = salt,
encryptedIndex = encryptedIndex,
};
methodDispatcher.methods.Add(new CallInfo { method = method, callVir = callVir});
_methodProxys.Add(key, proxyInfo);
}
return new ProxyCallMethodData(proxyInfo.proxyMethod, proxyInfo.secret);
return new ProxyCallMethodData(proxyInfo.proxyMethod, proxyInfo.encryptedOps, proxyInfo.salt, proxyInfo.encryptedIndex);
}
public void Done()
@ -175,7 +206,6 @@ namespace Obfuz.ObfusPasses.CallObfus
foreach (DispatchMethodInfo dispatchMethod in _dispatchMethods.Values.SelectMany(ms => ms))
{
var methodDef = dispatchMethod.methodDef;
var secret = dispatchMethod.secret;
var methodSig = methodDef.MethodSig;
@ -204,34 +234,34 @@ namespace Obfuz.ObfusPasses.CallObfus
}
}
public class ProxyCallAllocator
public class CallProxyAllocator
{
private readonly IRandom _random;
private readonly IEncryptor _encryptor;
private readonly Dictionary<ModuleDef, ModuleDynamicProxyMethodAllocator> _moduleAllocators = new Dictionary<ModuleDef, ModuleDynamicProxyMethodAllocator>();
public ProxyCallAllocator(IRandom random)
public CallProxyAllocator(IRandom random, IEncryptor encryptor)
{
_random = random;
_encryptor = encryptor;
}
private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleCallProxyAllocator>(mod, () => new ModuleCallProxyAllocator(_random, _encryptor));
}
public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir)
{
if (!_moduleAllocators.TryGetValue(mod, out var allocator))
{
allocator = new ModuleDynamicProxyMethodAllocator(mod, _random);
_moduleAllocators.Add(mod, allocator);
}
ModuleCallProxyAllocator allocator = GetModuleAllocator(mod);
return allocator.Allocate(method, callVir);
}
public void Done()
{
foreach (var allocator in _moduleAllocators.Values)
foreach (var allocator in EmitManager.Ins.GetEmitManagers<ModuleCallProxyAllocator>())
{
allocator.Done();
}
_moduleAllocators.Clear();
}
}
}

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Obfuz.ObfusPasses.CallObfus
{
public class ConfigProxyCallPolicy : ProxyCallPolicyBase
public class ConfigurableCallObfusPolicy : CallObfusPolicyBase
{
public override bool NeedDynamicProxyCallInMethod(MethodDef method)
{

View File

@ -6,15 +6,17 @@ using Obfuz.Emit;
namespace Obfuz.ObfusPasses.CallObfus
{
public class DefaultProxyCallObfuscator : ProxyCallObfuscatorBase
public class DefaultProxyCallObfuscator : CallObfuscatorBase
{
private readonly IRandom _random;
private readonly ProxyCallAllocator _proxyCallAllocator;
private readonly IEncryptor _encryptor;
private readonly CallProxyAllocator _proxyCallAllocator;
public DefaultProxyCallObfuscator(IRandom random)
public DefaultProxyCallObfuscator(IRandom random, IEncryptor encryptor)
{
_random = random;
_proxyCallAllocator = new ProxyCallAllocator(random);
_encryptor = encryptor;
_proxyCallAllocator = new CallProxyAllocator(random, _encryptor);
}
public override void Done()
@ -26,7 +28,11 @@ namespace Obfuz.ObfusPasses.CallObfus
{
MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod));
ProxyCallMethodData proxyCallMethodData = _proxyCallAllocator.Allocate(callingMethod.Module, calledMethod, callVir);
obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.secret));
DefaultModuleMetadataImporter importer = MetadataImporter.Instance.GetDefaultModuleMetadataImporter(callingMethod.Module);
obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.encryptedIndex));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.encryptOps));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptInt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, proxyCallMethodData.proxyMethod));
}
}

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Obfuz.ObfusPasses.CallObfus
{
public interface IProxyCallPolicy
public interface ICallObfusPolicy
{
bool NeedDynamicProxyCallInMethod(MethodDef method);

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace Obfuz.ObfusPasses.CallObfus
{
public interface IProxyCallObfuscator
public interface ICallObfuscator
{
void Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions);

View File

@ -81,7 +81,7 @@ namespace Obfuz
}
if (obfuscationPasses.HasFlag(ObfuscationPassType.CallProxy))
{
builder.AddPass(new ProxyCallPass());
builder.AddPass(new CallObfusPass(settings.callObfusSettings));
}
if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncryption))
{

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Settings
{
[Serializable]
public class CallObfusSettings
{
}
}

View File

@ -32,6 +32,9 @@ namespace Obfuz.Settings
[Tooltip("const encryption settings")]
public ConstEncryptSettings constEncryptSettings;
[Tooltip("call obfuscation settings")]
public CallObfusSettings callObfusSettings;
public string ObfuzRootDir => $"Library/Obfuz";
public string GetObfuscatedAssemblyOutputDir(BuildTarget target)

View File

@ -37,6 +37,7 @@ namespace Obfuz.Settings
private SerializedProperty _symbolObfusSettings;
private SerializedProperty _constEncryptSettings;
private SerializedProperty _callObfusSettings;
public ObfuzSettingsProvider() : base("Project/Obfuz", SettingsScope.Project)
{
@ -66,6 +67,7 @@ namespace Obfuz.Settings
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
_callObfusSettings = _serializedObject.FindProperty("callObfusSettings");
}
public override void OnGUI(string searchContext)
@ -85,6 +87,7 @@ namespace Obfuz.Settings
EditorGUILayout.PropertyField(_symbolObfusSettings);
EditorGUILayout.PropertyField(_constEncryptSettings);
EditorGUILayout.PropertyField(_callObfusSettings);
if (EditorGUI.EndChangeCheck())