c# - 如何在 MSIL 中调用正在执行的程序集之外的方法?

标签 c# hook clr jit cil

我可以访问这样的函数体中间语言:

byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();

我能够修改其 IL 代码,以便在执行方法主体之前调用名为 OnChangeField 的以下方法:

public static void OnChangeField()
{
    Console.WriteLine("VICTORY");
    return;
}

到目前为止我是这样做的:

我定义了我要调用的方法的调用指令:

MethodInfo OnStfld = typeof(MethodBoundaryAspect).GetMethod("OnChangeField");
byte[] callIL = new byte[5];
callIL[0] = (byte)OpCodes.Call.Value;
callIL[1] = (byte)(OnStfld.MetadataToken & 0xFF);
callIL[2] = (byte)(OnStfld.MetadataToken >> 8 & 0xFF);
callIL[3] = (byte)(OnStfld.MetadataToken >> 16 & 0xFF);
callIL[4] = (byte)(OnStfld.MetadataToken >> 24 & 0xFF);

请注意,OnChangeField 位于 MethodBoundaryAspect 类中。此类位于正在编辑的方法的程序集之外。

这就是我改变原始(NestedFoo(...))方法主体的方法:

byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
InjectionHelper.UpdateILCodes(NestedFooInfo, callIL.Concat(ilCodes).ToArray());

我得到一个:

System.BadImageFormatException: 'Index not found. (Exception from HRESULT: 0x80131124)'

但是如果 Hook 方法OnChangeField位于执行程序集之外(或者我是这么理解的)。如果我将 OnChangeField 移动到与 NestedFoo 相同的类中或 NestedFoo 程序集的另一个类中,则它可以正常工作。

我知道元数据 token 指向无效的内存位置。有办法改变吗?

这里的引用资料是: 更改后的方法的方法体如下所示:

public class ExceptionHandlingService : IExceptionHandlingService
{
        public static string var1 = "initialValue";
        public static string Var2 { get; set; } = "initialValue";
        public string var3 = "initialValue";
        public string Var4 { get; set; } = "initialValue";

        public string NestedFoo(SampleClass bar)
        {
            var1 = "value set in NestedFoo()";
            Var2 = "value set in NestedFoo()";
            var3 = "value set in NestedFoo()";
            Var4 = "value set in NestedFoo()";
            AddPerson("From", "NestedFoo", 2);
            return Foo();
        }
        [...]
}

以及我如何调用改变的方法:

var a = new ExceptionHandlingService();
var b = new SampleClass("bonjour", 2, 3L); // Not really relevant
a.NestedFoo(b);

对于那些想知道魔法发生在哪里的人 InjectionHelper.UpdateILCodes(NestedFooInfo, newIlCodes); 你可以检查 this link它展示了如何在运行时编辑 Il 代码。

最佳答案

您需要将记录添加到 MemberRef 以及连续的 TypeRefTypeSpec 元数据表中,以包含对类型的引用并引用这些标记。这还涉及正确编写签名 blob。

请参阅 ECMA-335 的第 II 部分 22.38、22.25

关于c# - 如何在 MSIL 中调用正在执行的程序集之外的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64891113/

相关文章:

c# - 使用 emgucv 测量两个图像的差异

c# - 在 Azure 中设置 ASP.NET Core Web 应用程序的 SQL 连接字符串

java - 如何在java中使用SetWindowsHookEx函数?

delphi - 为什么 Alt 键没有触发我的低级键盘 Hook ?

c# - 无法找到运行时 clr.dll 以使用 sos

c# - Datagridview 添加工具提示

c# - 隐藏成员函数不起作用

liferay - 在 liferay 门户中自定义用户管理的问题

clr - 编写Iron Python调试器

c# - 在 ReflectionOnlyLoad 期间忽略缺失的依赖项