From a109511f9eed14ddb727b345539224e8fbd791e1 Mon Sep 17 00:00:00 2001 From: walon Date: Tue, 10 Jun 2025 13:56:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20ObfuscationTypeMapper?= =?UTF-8?q?=E5=8F=8A=E7=9B=B8=E5=BA=94=E7=9A=84Instinct=E5=87=BD=E6=95=B0R?= =?UTF-8?q?egisterReflectionType?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/Emit/DefaultMetadataImporter.cs | 8 +++ Editor/ObfusPasses/Instinct/InstinctPass.cs | 13 +++- Runtime/ObfuscationInstincts.cs | 9 +++ Runtime/ObfuscationTypeMapper.cs | 76 +++++++++++++++++++++ Runtime/ObfuscationTypeMapper.cs.meta | 11 +++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 Runtime/ObfuscationTypeMapper.cs create mode 100644 Runtime/ObfuscationTypeMapper.cs.meta diff --git a/Editor/Emit/DefaultMetadataImporter.cs b/Editor/Emit/DefaultMetadataImporter.cs index 639d47f..7c9ecec 100644 --- a/Editor/Emit/DefaultMetadataImporter.cs +++ b/Editor/Emit/DefaultMetadataImporter.cs @@ -1,5 +1,6 @@ using dnlib.DotNet; using System; +using System.Reflection; using UnityEngine.Assertions; namespace Obfuz.Emit @@ -143,6 +144,9 @@ namespace Obfuz.Emit _verifySecretKey = mod.Import(typeof(AssetUtility).GetMethod("VerifySecretKey", new[] { typeof(int), typeof(int) })); Assert.IsNotNull(_verifySecretKey, "VerifySecretKey not found"); + _obfuscationTypeMapperRegisterType = mod.Import(typeof(ObfuscationTypeMapper).GetMethod("RegisterType", 1, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null)); + Assert.IsNotNull(_obfuscationTypeMapperRegisterType, "ObfuscationTypeMapper.RegisterType not found"); + _staticDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService)); _dynamicDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService)); if (_encryptionScopeProvider.IsDynamicSecretAssembly(mod)) @@ -168,6 +172,8 @@ namespace Obfuz.Emit private IMethod _initializeArray; private IMethod _verifySecretKey; + private IMethod _obfuscationTypeMapperRegisterType; + public IMethod CastIntAsFloat => _castIntAsFloat; public IMethod CastLongAsDouble => _castLongAsDouble; public IMethod CastFloatAsInt => _castFloatAsInt; @@ -177,6 +183,8 @@ namespace Obfuz.Emit public IMethod VerifySecretKey => _verifySecretKey; + public IMethod ObfuscationTypeMapperRegisterType => _obfuscationTypeMapperRegisterType; + public IMethod EncryptBlock => _defaultEncryptionServiceMetadataImporter.EncryptBlock; public IMethod DecryptBlock => _defaultEncryptionServiceMetadataImporter.DecryptBlock; diff --git a/Editor/ObfusPasses/Instinct/InstinctPass.cs b/Editor/ObfusPasses/Instinct/InstinctPass.cs index d00e1c3..52f172c 100644 --- a/Editor/ObfusPasses/Instinct/InstinctPass.cs +++ b/Editor/ObfusPasses/Instinct/InstinctPass.cs @@ -25,7 +25,6 @@ namespace Obfuz.ObfusPasses.Instinct public override void Start() { - var ctx = ObfuscationPassContext.Current; } public override void Stop() @@ -92,11 +91,15 @@ namespace Obfuz.ObfusPasses.Instinct return false; } + ObfuscationPassContext ctx = ObfuscationPassContext.Current; + var importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(callingMethod.Module, ctx.encryptionScopeProvider); + string methodName = methodDef.Name; switch (methodName) { case "FullNameOf": case "NameOf": + case "RegisterReflectionType": { MethodSpec methodSpec = (MethodSpec)method; GenericInstMethodSig gims = methodSpec.GenericInstMethodSig; @@ -116,6 +119,14 @@ namespace Obfuz.ObfusPasses.Instinct outputInstructions.Add(Instruction.Create(OpCodes.Ldstr, typeName)); break; } + case "RegisterReflectionType": + { + string typeFullName = GetTypeFullName(type); + outputInstructions.Add(Instruction.Create(OpCodes.Ldstr, typeFullName)); + var finalMethod = new MethodSpecUser((IMethodDefOrRef)importer.ObfuscationTypeMapperRegisterType, gims); + outputInstructions.Add(Instruction.Create(OpCodes.Call, finalMethod)); + break; + } default: throw new NotSupportedException($"Unsupported instinct method: {methodDef.FullName}"); } break; diff --git a/Runtime/ObfuscationInstincts.cs b/Runtime/ObfuscationInstincts.cs index 96e5087..8faa0ce 100644 --- a/Runtime/ObfuscationInstincts.cs +++ b/Runtime/ObfuscationInstincts.cs @@ -27,5 +27,14 @@ namespace Obfuz { return typeof(T).Name; } + + /// + /// register original type name to type mapping. + /// + /// + public static void RegisterReflectionType() + { + ObfuscationTypeMapper.RegisterType(typeof(T).FullName); + } } } diff --git a/Runtime/ObfuscationTypeMapper.cs b/Runtime/ObfuscationTypeMapper.cs new file mode 100644 index 0000000..c279cdb --- /dev/null +++ b/Runtime/ObfuscationTypeMapper.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz +{ + public static class ObfuscationTypeMapper + { + private static readonly Dictionary _type2OriginalFullName = new Dictionary(); + private static readonly Dictionary> _originalFullName2Types = new Dictionary>(); + + internal static void RegisterType(string originalFullName) + { + RegisterType(typeof(T), originalFullName); + } + + internal static void RegisterType(Type type, string originalFullName) + { + if (_type2OriginalFullName.ContainsKey(type)) + { + throw new ArgumentException($"Type '{type.FullName}' is already registered with original name '{_type2OriginalFullName[type]}'."); + } + _type2OriginalFullName.Add(type, originalFullName); + Assembly assembly = type.Assembly; + if (!_originalFullName2Types.TryGetValue(assembly, out var originalFullName2Types)) + { + originalFullName2Types = new Dictionary(); + _originalFullName2Types[assembly] = originalFullName2Types; + } + if (originalFullName2Types.ContainsKey(originalFullName)) + { + throw new ArgumentException($"Original full name '{originalFullName}' is already registered with type '{originalFullName2Types[originalFullName].FullName}'."); + } + originalFullName2Types.Add(originalFullName, type); + } + + public static string GetOriginalTypeFullName(Type type) + { + return _type2OriginalFullName.TryGetValue(type, out string originalFullName) + ? originalFullName + : throw new KeyNotFoundException($"Type '{type.FullName}' not found in the obfuscation mapping."); + } + + public static string GetOriginalTypeFullNameOrCurrent(Type type) + { + if (_type2OriginalFullName.TryGetValue(type, out string originalFullName)) + { + return originalFullName; + } + return type.FullName; + } + + public static Type GetTypeByOriginalFullName(Assembly assembly, string originalFullName) + { + if (_originalFullName2Types.TryGetValue(assembly, out var n2t)) + { + if (n2t.TryGetValue(originalFullName, out Type type)) + { + return type; + } + } + return null; + } + + public static void Clear() + { + _type2OriginalFullName.Clear(); + _originalFullName2Types.Clear(); + } + } + +} diff --git a/Runtime/ObfuscationTypeMapper.cs.meta b/Runtime/ObfuscationTypeMapper.cs.meta new file mode 100644 index 0000000..f496249 --- /dev/null +++ b/Runtime/ObfuscationTypeMapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db6168acedd85984fa2c197fee1b0c15 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: