使用dnlib注入含方法的类遇解析异常,求无需改dnlib的方案
解决dnlib注入类方法时的MemberRefResolveException问题
我明白你现在的困境:想用dnlib往目标模块里注入带方法的类,不想修改dnlib源码,但用Importer写的代码直接报错了。咱们来一步步拆解问题,找到不用改dnlib的解决方案。
为什么你的代码会抛出异常?
你原来的代码里,importer.Import(typeof(AntiDumpRuntime).GetMethod("Initialize"))得到的是一个方法引用(MemberRef),它只是指向外部程序集里的方法,并不是方法的实际定义。当你调用method.ResolveMethodDefThrow()时,dnlib会尝试在目标模块(manifestModule)里找这个方法的定义,但目标模块里根本没有,自然就抛出找不到方法的异常了。Importer的作用是让目标模块能引用外部成员,而不是把成员的定义复制到目标模块里。
不用修改dnlib的解决方案:复制方法定义到目标模块
要解决这个问题,咱们得直接把源方法的定义完整复制到目标模块里,而不是只导入引用。可以用dnlib自带的MemberCloner来处理这个过程,它会自动帮我们转换方法里的类型、成员引用,适配目标模块。
下面是完整的代码示例:
// 1. 获取包含AntiDumpRuntime的源模块(如果是当前程序集,直接加载即可) ModuleDef sourceModule = ModuleDefMD.Load(typeof(AntiDumpRuntime).Assembly.Location); // 2. 从源模块里找到目标类型和方法的定义 TypeDef sourceAntiDumpType = sourceModule.Types.First(t => t.FullName == typeof(AntiDumpRuntime).FullName); MethodDef sourceInitMethod = sourceAntiDumpType.Methods.First(m => m.Name == "Initialize"); // 3. 目标模块就是你要注入的模块 ModuleDef targetModule = assembly.ManifestModule; // 4. 使用MemberCloner把源方法复制到目标模块 MemberCloner cloner = new MemberCloner(sourceInitMethod, targetModule); MethodDef clonedInitMethod = cloner.Clone() as MethodDef; // 5. 创建你要注入的新类型 TypeDef antiDumpType = new TypeDefUser(null, "AntiDump", targetModule.CorLibTypes.Object.TypeDefOrRef); // 根据需求设置类型属性,比如公开类 antiDumpType.Attributes = TypeAttributes.Class | TypeAttributes.Public; // 6. 把复制好的方法添加到新类型里 antiDumpType.Methods.Add(clonedInitMethod); // 7. 最后把新类型加入目标模块 targetModule.Types.Add(antiDumpType);
额外说明
- 如果
AntiDumpRuntime里还有其他依赖的类型、字段或者方法,MemberCloner会自动处理这些引用的转换,把它们转换成目标模块能识别的形式。 - 这个思路和ConfuserEx的InjectHelper核心逻辑一致,都是手动复制成员定义并处理引用,只不过咱们用了dnlib自带的工具类,不用去修改dnlib的源码。
内容的提问来源于stack exchange,提问作者nop




