You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:33:35