你自己先用 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];
}
如下参考
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];
}
她们是一致的。
接口方法和普通函数是一致的,只是第一个参数为 this .我 hook DirectX 游戏,都是直接 Hook 的。
也就是说游戏已经在运行中的。我在 DirectX 中也创建一个 IDirect3DDeviceXX 的接口。
根据这个接口就可以知道接口方法的入口,然后,直接 hook 这个函数,就像你说的 EndScene 。
所有的 IDirect3DDeviceXX 方法都是同一个。所以我创建的和 DirectX 程序自己创建的 IDirect3DDeviceXX 指向的方法是一致的。
感谢大神~你说的完全正确,我一开始没有认真思考,另外不清楚虚函数表是怎么查的。后来在往上找了找,也试了一些,终于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);
}另外请教个问题,虚函数表,通过什么方式能查出来?
#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;
}