【问题标题】:How to get a function memory address from a Delegate [closed]如何从委托中获取函数内存地址[关闭]
【发布时间】:2020-12-04 13:22:55
【问题描述】:

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

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

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

之后,我声明了一个Delegate,并生成了一个指向我的hookFunc 函数的新实例,然后我使用GetFunctionPointerForDelegate() 从委托中获取了一个指针。我还生成了用于修补原始函数内存的字节序列,并使用函数 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 的内容进行替换。在遇到几个 StackOverflow 错误后,我用 WinDbg 调试了代码,我发现变量 hookPointerBytes 不包含 hookFunc 的地址,因此触发钩子时jmp 指令将代码执行流驱动到没有可执行代码的内存地址,这可能是我的程序崩溃的原因。

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

【问题讨论】:

  • 我的猜测是您的问题是委托正在被垃圾收集。根据Marshal.GetFunctionPointerForDelegate 的文档:“您必须手动阻止垃圾收集器从托管代码中收集委托。垃圾收集器不会跟踪对非托管代码的引用。”
  • @RossRidge 我已经尝试了你所说的在委托和指针上使用 GC.KeepAlive() ,但仍然得到同样的错误。
  • @KuroshD。你想要GCHandle.Alloc() 而不是GC.KeepAlive()

标签: c# assembly delegates hook function-pointers


【解决方案1】:

我不确定您是否会在没有不安全代码的情况下使其工作。 我认为您将需要一个非托管指针,您可以通过 ToPointer 在您的 IntPtr 上获得它。

byte* pointer = (byte*) hookPtr.ToPointer();

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

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

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

【讨论】:

  • 我使用了不同的方法,但你是对的,我需要不安全的代码。此外,PlayHooky 代码是完成此任务的完美指南,因此我将您的答案投票为正确。
猜你喜欢
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 2012-07-05
  • 2018-09-09
  • 2014-02-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-28
相关资源
最近更新 更多