如何在运行时将IL注入方法

时间:2011-01-29 22:07:32

标签: c# .net code-injection il

标题或多或少都说明了一切。根据{{​​3}}文章,我想出了这个:

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");
    }
}

至于文章中的代码......我根本无法使用它。

任何想法/替代品?

1 个答案:

答案 0 :(得分:8)

这会产生许多糟糕的假设,这些假设会让你陷入困境。

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

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

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