编写回调和蹦床¶
即使你可以从 VF 表获得 EndScene() 地址,EndScene() 函数实际上并不遵循 __thiscall 约定。Direct3D 类是 C API 周围的简单包装器,所有成员函数调用都转发到把类实例作为第一个参数的 __stdcall 函数。这意味着你的蹦床只需从栈抓取设备,把它传给回调,然后跳回 EndScene()。回调只需在返回蹦床前移除跳转钩子。
这个跳转钩子的回调和蹦床的最终代码看起来像这样:
LPDIRECT3DDEVICE9 discoveredDevice;
DWORD __stdcall reportInitEndScene(LPDIRECT3DDEVICE
9 device)
{
discoveredDevice = device;
unhookWithJump(EndSceneAddress, originals);
return EndSceneAddress;
}
__declspec(naked) void endSceneTrampoline()
{
__asm {
MOV EAX, DWORD PTR SS:[ESP + 0x4]
PUSH EAX // 把设备交给回调