You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

火山引擎 最新活动