如何基于Dnlib从已加载程序集中执行指定RVA地址的方法?
用dnlib定位并执行已加载程序集中的方法
我注意到你已经在尝试用dnlib来操作已加载程序集的方法,但这里有个容易踩的坑:dnlib的TypeDef是元数据层面的类型定义,不是CLR运行时的System.Type对象——直接调用type.GetType()只会拿到dnlib.DotNet.TypeDef本身的类型,根本不是你要找的目标程序集里的类型。
下面是完整的实现思路和修正后的代码,帮你走完从RVA定位方法到最终执行的全流程:
1. 确认已通过RVA找到目标MethodDef
假设你已经通过硬编码的RVA在module(dnlib的ModuleDef实例)中定位到了目标MethodDef,如果这一步还没完成,可以用这段代码快速定位:
MethodDef targetMethod = module.GetMethods() .FirstOrDefault(m => m.RVA == yourTargetRva); if (targetMethod == null) throw new InvalidOperationException("未找到指定RVA的方法");
2. 把dnlib的元数据对象映射到CLR运行时对象
要执行方法,必须拿到CLR的MethodInfo。首先得获取目标程序集的CLRAssembly实例,再通过类型全名匹配到System.Type:
// 获取已加载到当前AppDomain的目标程序集 Assembly targetAssembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.GetName().Name.Equals(module.Assembly.Name.Name, StringComparison.Ordinal)); if (targetAssembly == null) throw new InvalidOperationException("目标程序集未加载到当前AppDomain"); // 通过dnlib TypeDef的FullName获取CLR Type Type targetType = targetAssembly.GetType(targetMethod.DeclaringType.FullName); if (targetType == null) throw new InvalidOperationException("未找到目标类型");
3. 获取MethodInfo并执行方法
接下来根据方法是静态还是实例类型,准备参数并执行:
// 覆盖所有可能的方法访问修饰符 BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; // 构建参数类型数组(必须严格匹配方法签名) Type[] paramTypes = targetMethod.Parameters .Select(p => targetAssembly.GetType(p.Type.FullName)) .ToArray(); // 获取匹配的MethodInfo MethodInfo methodInfo = targetType.GetMethod( targetMethod.Name, bindingFlags, null, paramTypes, null ); if (methodInfo == null) throw new InvalidOperationException("未找到匹配的CLR方法"); // 执行方法 object result; if (methodInfo.IsStatic) { // 静态方法无需实例,直接传参数 object[] methodParams = { /* 这里传入你的方法参数,注意类型完全匹配 */ }; result = methodInfo.Invoke(null, methodParams); } else { // 实例方法需要先创建类型实例(如果类型有默认构造函数) object typeInstance = Activator.CreateInstance(targetType); object[] methodParams = { /* 传入方法参数 */ }; result = methodInfo.Invoke(typeInstance, methodParams); } // 处理执行结果 Console.WriteLine($"方法执行结果:{result}");
几个关键提醒
- 元数据≠运行时对象:dnlib操作的是磁盘上的程序集元数据,CLR反射操作的是内存中加载的类型/方法,必须通过全名做好两者的映射。
- 参数类型要严格匹配:获取
MethodInfo时,参数类型的全名必须和目标方法完全一致,否则会匹配失败。 - 确保程序集已加载:如果目标程序集还没加载到AppDomain,可以用
Assembly.LoadFrom()或Assembly.Load()先加载。 - 异常处理不可少:实际使用时要加try-catch块,处理反射执行时可能出现的参数不匹配、权限不足、构造函数缺失等异常。
内容的提问来源于stack exchange,提问作者Bloodaxe
相关产品推荐
相关产品推荐

