设计哲学:零外部依赖
许多保护工具要求用户分发运行时 DLL(如 VMProtectSDK32.dll)。我们的设计:所有运行时类型在保护时完整克隆到目标程序集。InjectHelper:dnlib 深度克隆引擎
public static class InjectHelper
{
// === 入口 1:克隆整个类型到目标模块 ===
public static TypeDef Inject(TypeDef typeDef, ModuleDef target)
{
var ctx = new InjectContext(typeDef.Module, target);
return (TypeDef)ctx.Import(typeDef);
}// === 入口 2:克隆单个方法 ===
public static MethodDef Inject(MethodDef methodDef, ModuleDef target)
{
var ctx = new InjectContext(methodDef.Module, target);
return (MethodDef)ctx.Import(methodDef);
}// === 入口 3:批量克隆(共享上下文,处理交叉引用) ===
public static List InjectMany(
IEnumerable typeDefs, ModuleDef target)
{
var ctx = new InjectContext(typeDefs.First().Module, target);
return typeDefs.Select(t => (TypeDef)ctx.Import(t)).ToList();
}
}
克隆管道:浅拷贝 → 深拷贝 → 签名修复
class InjectContext : ImportMapper
{
// 映射表:origin → clone
Dictionary<IMemberRef, IMemberRef> _map = new();IMemberRef Import(IMemberRef member)
{
// 1. 已克隆?→ 直接返回映射
if (_map.TryGetValue(member, out var mapped))
return mapped;// 2. 根据类型深度克隆 return member switch { TypeDef td => Clone(td), MethodDef md => Clone(md), FieldDef fd => Clone(fd), TypeRef tr => TargetModule.Import(tr), MemberRef mr => TargetModule.Import(mr), _ => member };}
TypeDef Clone(TypeDef origin)
{
var clone = new TypeDefUser(origin.Namespace, origin.Name)
{
Attributes = origin.Attributes,
BaseType = Import(origin.BaseType)
};// 记录映射 _map[origin] = clone; // 克隆接口 foreach (var iface in origin.Interfaces) clone.Interfaces.Add(new InterfaceImplUser(Import(iface.Interface))); // 克隆属性 foreach (var prop in origin.Properties) clone.Properties.Add(Clone(prop)); // 克隆字段 foreach (var field in origin.Fields) clone.Fields.Add(Clone(field)); // 克隆方法(含方法体 IL) foreach (var method in origin.Methods) clone.Methods.Add(Clone(method)); return clone;}
MethodDef Clone(MethodDef origin)
{
var clone = new MethodDefUser(
origin.Name,
Import(origin.MethodSig),
origin.ImplAttributes,
origin.Attributes);_map[origin] = clone; // 克隆方法体(IL 指令、局部变量、异常处理器) if (origin.HasBody) { clone.Body = new CilBody(); clone.Body.InitLocals = origin.Body.InitLocals; clone.Body.MaxStack = origin.Body.MaxStack; // 复制局部变量 foreach (var local in origin.Body.Variables) clone.Body.Variables.Add(new Local(Import(local.Type))); // 复制 IL 指令(映射操作数) foreach (var instr in origin.Body.Instructions) { var cloneInstr = new Instruction( instr.OpCode, MapOperand(instr.Operand)); clone.Body.Instructions.Add(cloneInstr); } // 复制异常处理器 foreach (var eh in origin.Body.ExceptionHandlers) { clone.Body.ExceptionHandlers.Add(new ExceptionHandler(eh.HandlerType) { CatchType = Import(eh.CatchType), TryStart = Map(eh.TryStart), TryEnd = Map(eh.TryEnd), HandlerStart = Map(eh.HandlerStart), HandlerEnd = Map(eh.HandlerEnd), }); } } return clone;}
}InjectContext:ImportMapper 与框架重定向
.NET Core 的 UI 外观程序集(System.Runtime.dll 等)需要重定向到核心库:
public override IMemberRef Map(IMemberRef member)
{
var asm = member.DeclaringType?.DefinitionAssembly;
if (asm == null) return base.Map(member);
// 0a. .NET Framework 目标遇到 System.Private.CoreLib → 重定向到 mscorlib if (!TargetIsNetCore && IsCoreLib(asm)) return RedirectTo(asm, TargetModule.CorLibTypes.AssemblyRef); // 0. 外观程序集 → 重定向到 System.Private.CoreLib 或 mscorlib if (IsFacadeAssembly(asm)) { var corlib = TargetModule.CorLibTypes.AssemblyRef; return RedirectTo(asm, corlib); } // 1. 目标模块已有同名引用?→ 使用已有的 var existingRef = TargetModule.GetAssemblyRef(asm.Name); if (existingRef != null && existingRef.Version == asm.Version) return existingRef; return base.Map(member);}
static readonly HashSet _facadeAsmNames = new()
{
“System.Runtime”, “System.IO”, “System.Linq”, “System.Collections”,
“System.Threading”, “System.Reflection”, “System.Diagnostics”,
“netstandard”, “System.Net.Http”, “System.ComponentModel”,
// … 40+ 个框架外观程序集
};
4. MutationHelper:占位符替换引擎
public static class MutationHelper
{
// 映射:Mutation 字段名 → key 索引
static readonly Dictionary<string, int> field2index = new()
{
{ “KeyI0”, 0 }, { “KeyI1”, 1 }, { “KeyI2”, 2 }, { “KeyI3”, 3 },
{ “KeyI4”, 4 }, { “KeyI5”, 5 }, { “KeyI6”, 6 }, { “KeyI7”, 7 },
{ “KeyI8”, 8 }, { “KeyI9”, 9 }, { “KeyI10”, 10 }, { “KeyI11”, 11 },
{ “KeyI12”, 12 }, { “KeyI13”, 13 }, { “KeyI14”, 14 }, { “KeyI15”, 15 },
};
// 替换 Key 占位符 public static void InjectKey(MethodDef method, int keyId, int value) { foreach (var instr in method.Body.Instructions) { if (instr.OpCode != OpCodes.Ldsfld) continue; var field = (IField)instr.Operand; // TWSoft.Runtime.Mutation.KeyI0 → ldc.i4 <value> if (field.DeclaringType.Name == "Mutation" && field2index.TryGetValue(field.Name, out int id) && id == keyId) { instr.OpCode = OpCodes.Ldc_I4; instr.Operand = value; } } } // 替换 Placeholder 调用 public static void ReplacePlaceholder( MethodDef method, Func<Instruction[], Instruction[]> repl) { foreach (var instr in method.Body.Instructions.ToList()) { if (instr.OpCode != OpCodes.Call) continue; var called = (IMethod)instr.Operand; // Mutation.Placeholder<T>(T val) → 替换为真实指令序列 if (called.Name == "Placeholder") { // 追踪参数来源 Instruction[] argInstructions = TraceArguments(instr); // 移除原 call 指令 int index = method.Body.Instructions.IndexOf(instr); method.Body.Instructions.RemoveAt(index); // 插入替换指令 var replacement = repl(argInstructions); foreach (var replInstr in replacement.Reverse()) method.Body.Instructions.Insert(index, replInstr); } } }}
5. RuntimeService:从保护工具自身加载运行时
public sealed class RuntimeService
{
ModuleDef? _rtModule;
public TypeDef GetRuntimeType(string fullName) { _rtModule ??= LoadSelfModule(); // 首次调用懒加载 return _rtModule.Find(fullName, true) ?? throw new InvalidOperationException( $"Runtime type '{fullName}' not found"); } static ModuleDef LoadSelfModule() { var asm = typeof(RuntimeService).Assembly; return ModuleDefMD.Load(asm.Location, new ModuleCreationOptions { TryToLoadPdbFromDisk = false }); }}
使用示例:
var runtime = context.Runtime; // 从 ProtectionContext 获取
var constantType = runtime.GetRuntimeType(“TWSoft.Runtime.Constant”);
var clonedConstant = InjectHelper.Inject(constantType, context.Module); // 克隆
6. 完整注入流程示例
以字符串加密为例,完整注入流程:
// Step 1: 获取运行时类型模板
var constantType = context.Runtime.GetRuntimeType(“TWSoft.Runtime.Constant”);
// Step 2: 深度克隆到目标模块
var clonedType = InjectHelper.Inject(constantType, context.Module);
// Step 3: 替换占位符为真实值
var initMethod = clonedType.FindMethod(“Initialize”);
MutationHelper.InjectKey(initMethod, 0, bufferLength); // KeyI0 → 真实长度
MutationHelper.InjectKey(initMethod, 1, seed); // KeyI1 → 真实种子
MutationHelper.ReplacePlaceholder(initMethod, args => // Placeholder → 数组初始化 IL
CreateArrayInitInstructions(args));
// Step 4: 重命名注入成员为不可见 Unicode
foreach (var method in clonedType.Methods)
method.Name = GenerateInvisibleName(random);
// Step 5: 标记不可被混淆
MarkAsNotRenameable(clonedType);
// Step 6: 插入 .cctor 初始化调用
InsertCctorCall(context.Module, clonedType, “Initialize”);
7. 结语
InjectHelper + MutationHelper + RuntimeService 构成了整个保护引擎的基础设施。所有运行时类型(Constant、MethodGuard、VirtualMachine、AntiTamper、AntiDebug、AntiDump、ResourceEncryptor)