你自己先用 CoCreateInstance 创建这样一个对象, 从这个对象获取虚函数的地址
如下参考
hInit = CoInitialize(NULL);
hr = CoCreateInstance(classId, NULL, CLSCTX_INPROC_SERVER, interfaceId, (VOID **)&pUnknow);
if(FAILED(hr))
{
m_pHookMgr->SendFmtString("GetInterfaceAddr.CoCreateInstance(%08X): %s", hr, pFunName);
if(hInit == S_OK)
CoUninitialize();
return FALSE;
} fnAddr = (FARPROC)NSys::GetClassVirFun(pUnknow, dwFunIndex);
pUnknow->Release();
//  if(hInit == S_OK)
//  CoUninitialize(); //释放后会导致模块free, 导致函数Hook失败 if(IsBadCodePtr(fnAddr))
{
m_pHookMgr->SendFmtString("GetInterfaceAddr.BadCodePtr: %08X", fnAddr);
return FALSE;
} m_fnRealFunProc = fnAddr;
m_pHookMgr->SendFmtString("GetInterfaceAddr OK(%08X): %s", fnAddr, pFunName);
VOID * NSys::GetClassVirFun(VOID * pClass, int nVirFunIndex)
{
VOID ** pVft;
pVft = *(VOID ***)pClass;
return pVft[nVirFunIndex];
}

解决方案 »

  1.   

    你 hook 这么多函数,怎么 EndScene 就不知道这么 hook 了。
    她们是一致的。
    接口方法和普通函数是一致的,只是第一个参数为 this .我 hook DirectX 游戏,都是直接 Hook 的。
    也就是说游戏已经在运行中的。我在 DirectX 中也创建一个 IDirect3DDeviceXX 的接口。
    根据这个接口就可以知道接口方法的入口,然后,直接 hook 这个函数,就像你说的 EndScene 。
    所有的 IDirect3DDeviceXX 方法都是同一个。所以我创建的和 DirectX 程序自己创建的 IDirect3DDeviceXX 指向的方法是一致的。
      

  2.   


    感谢大神~你说的完全正确,我一开始没有认真思考,另外不清楚虚函数表是怎么查的。后来在往上找了找,也试了一些,终于35的时候可以了。DWORD* MypVtableNext = GetVtableAddress(d3ddev);
    record_memory_s((int)MypVtableNext);
    HookFunction(MypVtableNext, (void*)&hook_EndScene, (void*)&orig_EndScene, 35);HRESULT APIENTRY hook_EndScene(IDirect3DDevice8* pInterface){
    __asm pushad
    My_DrawText((LPDIRECT3DDEVICE8)pInterface, TEXT("hello world"), 11);
    __asm popad
    //record_memory("画完了", sizeof("画完了"));
    //record_memory_s((int)pInterface);
    return orig_EndScene(pInterface);
    }另外请教个问题,虚函数表,通过什么方式能查出来?
      

  3.   

    不需要 push 那些寄存器的。
      

  4.   

    HOOK 虚表和接口方法:放在一个单独的文件中,如果是 C++ 需要先定义 CINTERFACE 宏,使用 C 模式的接口。其中 Real_IDirect3DDevice9Present = pDevice->lpVtbl->Present; 就是根据接口找到的 渲染 方法的函数。
    #define CINTERFACE BOOL SetDirect3DHook(HWND hDirectXWindow)
    {
    TR(L"Direct3D9 挂钩函数开始……");
    #ifdef HOOK_MODE
    #ifdef HOOK_RENDER
    BOOL bResult = FALSE;
    IDirect3D9 * pD3D = NULL;
    IDirect3DDevice9 * pDevice = NULL;
    HRESULT hr = CreateHookDevice(hDirectXWindow, &pD3D, &pDevice);
    if (SUCCEEDED(hr))
    {
    Real_IDirect3DDevice9Present = pDevice->lpVtbl->Present;
    bResult = HOOK_FUNCTION(IDirect3DDevice9Present);
    if (bResult)
    {
    bResult = SetDirect3DAcquireHook(pDevice);
    if (!bResult)
    {
    UNHOOK_FUNCTION(IDirect3DDevice9Present);
    }
    }
    pDevice->lpVtbl->Release(pDevice);
    pD3D->lpVtbl->Release(pD3D);
    }
    #else
    BOOL bResult = TRUE;
    #endif
    #else
    BOOL bResult = TRUE;
    #endif
    if (bResult)
    {
    TR(L"Direct3D9 挂钩函数成功结束。");
    }
    else
    {
    DR(L"Direct3D9 挂钩函数返回失败。");
    }
    return bResult;
    }