From 23009867cac2faaf8418d474b056690427c528d4 Mon Sep 17 00:00:00 2001 From: walon Date: Sun, 13 Apr 2025 22:41:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=99=9A=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/CollectionExtensions.cs | 19 ++++ Editor/Obfuz.Editor.asmdef | 2 +- Editor/Rename/NameMaker.cs | 4 +- Editor/Rename/RenameRecordMap.cs | 35 +++++++ Editor/Rename/SymbolRename.cs | 56 +++++++++++ Editor/Rename/VirtualMethodGroupCalculator.cs | 99 +++++++++++++++++++ 6 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 Editor/CollectionExtensions.cs create mode 100644 Editor/Rename/VirtualMethodGroupCalculator.cs diff --git a/Editor/CollectionExtensions.cs b/Editor/CollectionExtensions.cs new file mode 100644 index 0000000..b03df01 --- /dev/null +++ b/Editor/CollectionExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz +{ + public static class CollectionExtensions + { + public static void AddRange(this HashSet values, IEnumerable newValues) + { + foreach (var value in newValues) + { + values.Add(value); + } + } + } +} diff --git a/Editor/Obfuz.Editor.asmdef b/Editor/Obfuz.Editor.asmdef index 57139e1..910467f 100644 --- a/Editor/Obfuz.Editor.asmdef +++ b/Editor/Obfuz.Editor.asmdef @@ -1,5 +1,5 @@ { - "name": "Obfuz.Editor", + "name": "Obfuz", "rootNamespace": "", "references": [ "GUID:167b4b7f91c16bb4183f7298af665076" diff --git a/Editor/Rename/NameMaker.cs b/Editor/Rename/NameMaker.cs index 4036a2e..5ff4440 100644 --- a/Editor/Rename/NameMaker.cs +++ b/Editor/Rename/NameMaker.cs @@ -28,9 +28,11 @@ namespace Obfuz.Rename public class NameMaker : INameMaker { + private int _nextIndex; + private string GetDefaultNewName(string originName) { - return originName + "_xxx__"; + return $"{originName}>{_nextIndex++}"; } public string GetNewName(ModuleDefMD mod, string originalName) diff --git a/Editor/Rename/RenameRecordMap.cs b/Editor/Rename/RenameRecordMap.cs index 96c153e..283bc1f 100644 --- a/Editor/Rename/RenameRecordMap.cs +++ b/Editor/Rename/RenameRecordMap.cs @@ -1,4 +1,5 @@ using dnlib.DotNet; +using Obfuz.Rename; using System.Collections.Generic; namespace Obfuz @@ -24,6 +25,7 @@ namespace Obfuz private readonly Dictionary _fieldRenames = new Dictionary(); private readonly Dictionary _propertyRenames = new Dictionary(); private readonly Dictionary _eventRenames = new Dictionary(); + private readonly Dictionary _virtualMethodGroups = new Dictionary(); public void AddRenameRecord(ModuleDefMD mod, string oldName, string newName) @@ -56,6 +58,29 @@ namespace Obfuz }); } + public void AddRenameRecord(VirtualMethodGroup methodGroup, string oldName, string newName) + { + _virtualMethodGroups.Add(methodGroup, new RenameRecord + { + status = RenameStatus.Renamed, + oldName = oldName, + newName = newName + }); + } + + public bool TryGetRenameRecord(VirtualMethodGroup group, out string oldName, out string newName) + { + if (_virtualMethodGroups.TryGetValue(group, out var record)) + { + oldName = record.oldName; + newName = record.newName; + return true; + } + oldName = null; + newName = null; + return false; + } + public void AddRenameRecord(FieldDef field, string oldName, string newName) { _fieldRenames.Add(field, new RenameRecord @@ -116,6 +141,16 @@ namespace Obfuz }); } + public void AddUnRenameRecord(VirtualMethodGroup methodGroup) + { + _virtualMethodGroups.Add(methodGroup, new RenameRecord + { + status = RenameStatus.NotRenamed, + oldName = methodGroup.methods[0].Name, + newName = null, + }); + } + public void AddUnRenameRecord(FieldDef fieldDef) { _fieldRenames.Add(fieldDef, new RenameRecord diff --git a/Editor/Rename/SymbolRename.cs b/Editor/Rename/SymbolRename.cs index 9aafa56..f98dcc7 100644 --- a/Editor/Rename/SymbolRename.cs +++ b/Editor/Rename/SymbolRename.cs @@ -17,10 +17,12 @@ namespace Obfuz { private readonly ObfuscatorContext _ctx; + private readonly HashSet _obfuscatedModules = new HashSet(); private readonly IRenamePolicy _renamePolicy; private readonly INameMaker _nameMaker; private readonly Dictionary> _customAttributeArgumentsWithTypeByMods = new Dictionary>(); private readonly RenameRecordMap _renameRecordMap = new RenameRecordMap(); + private readonly VirtualMethodGroupCalculator _virtualMethodGroupCalculator = new VirtualMethodGroupCalculator(); class CustomAttributeInfo { @@ -34,6 +36,11 @@ namespace Obfuz _ctx = ctx; _renamePolicy = ctx.renamePolicy; _nameMaker = ctx.nameMaker; + + foreach (var mod in ctx.assemblies) + { + _obfuscatedModules.Add(mod.module); + } BuildCustomAttributeArguments(); } @@ -106,6 +113,7 @@ namespace Obfuz public void Process() { + var virtualMethods = new List(); foreach (ObfuzAssemblyInfo ass in _ctx.assemblies) { if (_renamePolicy.NeedRename(ass.module)) @@ -118,6 +126,7 @@ namespace Obfuz } foreach (TypeDef type in ass.module.GetTypes()) { + _virtualMethodGroupCalculator.CalculateType(type); if (_renamePolicy.NeedRename(type)) { Rename(type); @@ -139,6 +148,11 @@ namespace Obfuz } foreach (MethodDef method in type.Methods) { + if (method.IsVirtual) + { + virtualMethods.Add(method); + continue; + } if (_renamePolicy.NeedRename(method)) { Rename(method); @@ -179,6 +193,43 @@ namespace Obfuz } } } + + var visitedVirtualMethods = new HashSet(); + var groupNeedRenames = new Dictionary(); + foreach (var method in virtualMethods) + { + if (!visitedVirtualMethods.Add(method)) + { + continue; + } + VirtualMethodGroup group = _virtualMethodGroupCalculator.GetMethodGroup(method); + if (!groupNeedRenames.TryGetValue(group, out var needRename)) + { + needRename = group.methods.All(m => _obfuscatedModules.Contains(m.DeclaringType.Module) && _renamePolicy.NeedRename(m)); + groupNeedRenames.Add(group, needRename); + if (needRename) + { + _renameRecordMap.AddRenameRecord(group, method.Name, _nameMaker.GetNewName(method, method.Name)); + } + else + { + _renameRecordMap.AddUnRenameRecord(group); + } + } + if (!needRename) + { + _renameRecordMap.AddUnRenameRecord(method); + continue; + } + if (_renameRecordMap.TryGetRenameRecord(group, out var oldName, out var newName)) + { + Rename(method, oldName, newName); + } + else + { + throw new Exception($"group:{group} method:{method} not found in rename record map"); + } + } } private List GetReferenceMeAssemblies(ModuleDef mod) @@ -597,6 +648,11 @@ namespace Obfuz { string oldName = method.Name; string newName = _nameMaker.GetNewName(method, oldName); + Rename(method, oldName, newName); + } + + private void Rename(MethodDef method, string oldName, string newName) + { ModuleDefMD mod = (ModuleDefMD)method.DeclaringType.Module; RenameMethodBody(method); diff --git a/Editor/Rename/VirtualMethodGroupCalculator.cs b/Editor/Rename/VirtualMethodGroupCalculator.cs new file mode 100644 index 0000000..3de4685 --- /dev/null +++ b/Editor/Rename/VirtualMethodGroupCalculator.cs @@ -0,0 +1,99 @@ +using dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz.Rename +{ + + public class VirtualMethodGroup + { + public List methods; + } + + public class VirtualMethodGroupCalculator + { + + private class TypeFlatMethods + { + public HashSet flatMethods = new HashSet(); + + + public bool TryFindMatchVirtualMethod(MethodDef method, out MethodDef matchMethodDef) + { + foreach (var parentOrInterfaceMethod in flatMethods) + { + if (parentOrInterfaceMethod.Name == method.Name && parentOrInterfaceMethod.GetParamCount() == method.GetParamCount()) + { + matchMethodDef = parentOrInterfaceMethod; + return true; + } + } + matchMethodDef = null; + return false; + } + } + + + private readonly Dictionary _methodGroups = new Dictionary(); + private readonly Dictionary _visitedTypes = new Dictionary(); + + + + public VirtualMethodGroup GetMethodGroup(MethodDef methodDef) + { + if (_methodGroups.TryGetValue(methodDef, out var group)) + { + return group; + } + return null; + } + + public void CalculateType(TypeDef typeDef) + { + if (_visitedTypes.ContainsKey(typeDef)) + { + return; + } + + var typeMethods = new TypeFlatMethods(); + + if (typeDef.BaseType != null) + { + TypeDef baseTypeDef = MetaUtil.GetTypeDefOrGenericTypeBase(typeDef.BaseType); + CalculateType(baseTypeDef); + typeMethods.flatMethods.AddRange(_visitedTypes[baseTypeDef].flatMethods); + foreach (var intfType in typeDef.Interfaces) + { + TypeDef intfTypeDef = MetaUtil.GetTypeDefOrGenericTypeBase(intfType.Interface); + CalculateType(intfTypeDef); + typeMethods.flatMethods.AddRange(_visitedTypes[intfTypeDef].flatMethods); + } + } + foreach (var method in typeDef.Methods) + { + if (!method.IsVirtual) + { + continue; + } + if (typeMethods.TryFindMatchVirtualMethod(method, out var matchMethodDef)) + { + var group = _methodGroups[matchMethodDef]; + group.methods.Add(method); + _methodGroups.Add(method, group); + } + else + { + _methodGroups.Add(method, new VirtualMethodGroup() { methods = new List { method } }); + } + if (method.IsNewSlot) + { + typeMethods.flatMethods.Add(method); + } + } + _visitedTypes.Add(typeDef, typeMethods); + } + } +}