EndScene 钩子问题

EndScene hook questions

所以最近我想使用 DirectX 向示例 window 添加一个 imgui 界面,所以我看了一个视频,我必须使用 DirectX9sdk 挂钩 EndScene 函数才能添加我的自定义 imgui 界面。

但是我有一些问题:

  1. 我在哪里可以找到 DirectX9 函数和类型的任何文档(如果有的话,因为我不明白为什么我们必须特别挂钩 EndScene 函数)或者我在哪里可以找到任何更深入解释的文章directX 是如何工作的?
  2. 到目前为止,我已经看到了 EndScene 的两个版本,一个带有 patternScanning 函数,该函数扫描 shaderapi dll 中的签名,另一个创建 DirectXDevice,然后从那里访问 vtable;网上有资源吗,还是我们必须自己做? 这是我的版本:
while (!DirectXDevice) // loops until it finds the device
        DirectXDevice = **(DWORD**)(FindPattern("shaderapidx9.dll", "A1 ?? ?? ?? ?? 50 8B 08 FF 51 0C") + 0x1);

    void** pVTable = *reinterpret_cast<void***>(DirectXDevice); // getting the vtable array
    oEndScene = (f_EndScene)DetourFunction((PBYTE)pVTable[42], (PBYTE)Hooked_EndScene)//getting the 42th virtual function and detouring it to our own
  1. 我真的不明白 __stdcall 在这里做什么,我知道它是用来调用 WINAPI 函数的,但是这里有什么用?
HRESULT __stdcall Hooked_EndScene(IDirect3DDevice9* pDevice){//some code}

注意:这是我挂接到原始结束场景的函数。

非常感谢,如果有很多问题,我很抱歉,但我真的无法解决这个问题。

你怎么知道你需要hook哪些函数?

说白了,您必须是经验丰富的 DirectX 图形程序员才能发现这一点。不要指望能够挂钩到一个你不理解的框架中。碰巧 EndScene 总是在渲染目标上的所有其他绘制调用之后被调用。

有大量在线和纸质形式的 D3D9 编程资源可用。他们中的大多数都不是免费的。恐怕这不是您想要的答案。

模式扫描或创建临时 D3D9 设备有什么用?

Microsoft 没有做出任何明确的努力使 EndScene 可挂接。它只是 碰巧是可挂钩的 因为每个普通函数都是可挂钩的。你需要一种在内存中找到函数的方法,因为函数不会总是在同一个地址。

一种方法是扫描出现在函数内部的已知指令。需要有人成为第一个发现您可以扫描的模式的人。你远不是第一个 hook 的人 EndScene,所以很多人之前已经对函数进行了逆向工程并共享了可搜索的模式。

注意:模式不一定需要直接在目标函数内。它也可能首先将您带到其他地方,在您的情况下, ID3D9Device 实例。重要的是您可以通过某种方式找到 EndScene 函数。

另一种方法是获取指向函数的指针。如果它是一个常规的 C 函数,那将很容易。这里很难,因为 OOP 往往会使这些事情变得困难 - 你必须通过各种接口努力获得正确的 vtable。

这两种方法各有利弊——创建 D3D9 设备更安全,但也更具侵入性,因为目标进程可能不希望有人随机创建新设备。

为什么钩子函数需要__stdcall?

由于您用挂钩版本替换了原始函数,因此挂钩函数的调用约定必须与原始函数的调用约定相同。 EndScene 的调用者期望(并且被编译为)__stdcall 约定,因此新函数也必须以相同的方式运行,否则堆栈将被破坏。您替换函数的行为不会改变调用者调用它的方式。