如何从委托中获取函数内存地址

How to get a function memory address from a Delegate

我想从同一进程中加载​​的 DLL 挂钩一个函数,因此每次调用该函数时,我的自定义函数都会被执行。

为了做到这一点,我声明了一个虚拟函数,它将被执行以替换 DLL 中的原始函数:

 public static bool hookFunc(string a, ulong b, string c, IntPtr d)
{
     Console.WriteLine("hi");
     return true;
}

之后,我声明了一个 Delegate 并生成了一个指向我的 hookFunc 函数的新实例,然后我使用 [= =14=]。我还生成了将用于修补原始函数内存的字节序列,并使用函数的内存地址 hookFunc(从新指针获得)完成此序列:

public delegate bool hookDel(string a, ulong b, string c, IntPtr d);

public void hookManager()
        {

            var a = new hookDel(hookFunc);
            var hookPtr = Marshal.GetFunctionPointerForDelegate(a);
            var hookPointerBytes = BitConverter.GetBytes(hookPtr.ToInt64());
            newBytes = new byte[] { 0x49, 0xbb, hookPointerBytes[0], hookPointerBytes[1], hookPointerBytes[2], hookPointerBytes[3], hookPointerBytes[4], hookPointerBytes[5],
                                    hookPointerBytes[6], hookPointerBytes[7], 0x41, 0xff, 0xe3 };
        }

此时变量newBytes翻译成汇编的内容应该是如下指令:

mov r11, [memory address of my hookFunc function]
jmp r11

最后,我使用 GetProcAddress 获取原始 DLL 的函数内存地址,并使用 WriteProcessMemory 修补第一个字节,使用变量 newBytes 的内容进行替换。在收到几个 Whosebug 错误后,我用 WinDbg 调试了代码,我发现变量 hookPointerBytes 不包含 hookFunc[=39= 的地址],因此当钩子被触发时,jmp 指令将代码执行流驱动到没有可执行代码的内存地址,这可能是我的程序崩溃的原因。

我已验证 DLL 的函数挂钩已成功完成并且正在执行 jmp 指令。我的问题是,为什么我不能使用从Delegate获得的指针获得hookFunc的真实内存地址?在 C# 中还有其他方法可以获取我的 hookFunc 函数的内存地址吗?

我不确定您是否打算在没有不安全代码的情况下使它正常工作。 我认为您将需要一个非托管指针,您可以通过 IntPtr.

上的 ToPointer 获得该指针
byte* pointer = (byte*) hookPtr.ToPointer();

for (int k = 0; k < 7; k++) {
    newBytes[k+2] = *(pointer + k);
}

我自己没有尝试过,但是你可以在这里找到一个例子:https://github.com/wledfor2/PlayHooky

具体class: https://github.com/wledfor2/PlayHooky/blob/master/HookManager.cs