【问题标题】:How to inject IL into a method at runtime如何在运行时将 IL 注入方法
【发布时间】:2011-06-17 21:46:44
【问题描述】:

标题或多或少说明了一切。根据this 文章,我想出了这个:

public static unsafe void Replace(this MethodBase destination, MethodBase source)
{
    IntPtr srcHandle = source.MethodHandle.GetFunctionPointer();
    IntPtr dstHandle = destination.MethodHandle.GetFunctionPointer();

    int* dstPtr = (int*)dstHandle.ToPointer();
    *dstPtr = srcHandle.ToInt32();
}

这确实有效...偶尔-.-

例如,这是可行的。

public static class Program
{
    public static void Main(string[] args)
    {
        MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
        MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);

        methodA.Replace(methodB);

        A();
        B();
    }

    public static void A()
    {
        Console.WriteLine("Hai World");
    }

    public static void B()
    {
        Console.WriteLine("Bai World");
    }
}

但是,这不是 (SEHException)。我所做的只是改变定义函数的顺序。

public static class Program
{
    public static void Main(string[] args)
    {
        MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
        MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);

        methodA.Replace(methodB);

        A();
        B();
    }

    public static void B()
    {
        Console.WriteLine("Bai World");
    }

    public static void A()
    {
        Console.WriteLine("Hai World");
    }
}

至于文章中的代码......我根本无法让它工作。

有什么想法/选择吗?

【问题讨论】:

  • 为什么要这样做?这听起来像个可怕的主意。
  • 别担心 - 没有恶意。只是为了知识:D
  • 我认为唯一安全的方法是在程序集加载之前注入代码。
  • @Porges 也许是这样,但我认为更明智的做法是假设这永远不安全。永远。
  • 这是个好问题。我希望有一个答案。

标签: c# .net code-injection il


【解决方案1】:

这是在做出很多糟糕的假设,会让你大吃一惊。

首先,通过反射返回的结构在任何情况下都不能保证指向任何运行时结构。因此试图修改它包含或返回的指针是完全错误的。

其次,如果您希望执行诸如注入前/后方法调用不变量之类的操作(例如),那么您可能应该构造运行时代理对象并注入它们。或者通过 Emit 命名空间使用动态方法构造。试图通过未记录/未知的行为(例如上面的代码)来操纵事物是行不通的。

您还需要了解 JIT 决定何时运行。有时它针对整个类运行,有时它只针对单个方法运行。您的代码没有尝试确定该方法是否已经被 JITted,并且盲目地假设返回的函数指针可以被修改。

【讨论】:

  • 在那种情况下... a) 那么它到底指的是什么? b) 如何判断一个方法是否被 JITted?
  • b) 不能,除非程序在执行前通过 NGen 处理。
  • 简单的答案是:你不知道它指向什么。它只是一个指针,它有用途,但更改它是一个未定义且容易出错的操作,永远不应该这样做。您可以通过使用调试接口判断一个方法是否已被 JITted。但是,这仍然不能改变指针不是你应该摆弄的事实。
  • 那么我应该摆弄什么?
  • 简单地说:您不会更改方法在运行时指向的位置。曾经。例如,您上面的这两种方法通常都由 JIT 内联。因此,更改该指针并没有什么好处,即使它确实做了您和(文章的)原作者认为的那样。如果您想做一些可以更改在运行时调用的方法的事情,那就是委托的用途。
猜你喜欢
  • 2012-06-16
  • 2018-06-15
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多