这个方法不需要在主线程运行前注入,CE和直播软件OBS也是用了这个方法,所以推荐使用
理论上同一个类的虚函数地址是一样的,所以我们可以自己创建一个IDirect3DDevice9,然后就能获取虚函数地址了
经测试不同IDirect3DDevice9的虚函数表指针不一样,所以只能用inline hook,不能用虚函数表hook
void* endSceneAddr = NULL;
BYTE endSceneOldCode[sizeof(JmpCode)];
HRESULT STDMETHODCALLTYPE MyEndScene(IDirect3DDevice9* thiz)
{
// 这里放我们的绘制代码
unhook(endSceneAddr, endSceneOldCode);
HRESULT hr = thiz->EndScene();
hook(endSceneAddr, MyEndScene, endSceneOldCode);
return hr;
}
DWORD WINAPI initHookThread(LPVOID dllMainThread)
{
// 等待DllMain(LoadLibrary线程)结束
WaitForSingleObject(dllMainThread, INFINITE);
CloseHandle(dllMainThread);
// 创建一个窗口用于初始化D3D
WNDCLASSEX wc = {};
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = _T("DummyWindow");
if (RegisterClassEx(&wc) == 0)
{
MessageBox(NULL, _T("注册窗口类失败"), _T(""), MB_OK);
return 0;
}
HWND hwnd = CreateWindowEx(0, wc.lpszClassName, _T(""), WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, NULL, NULL, wc.hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, _T("创建窗口失败"), _T(""), MB_OK);
return 0;
}
// 初始化D3D
IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d9 == NULL)
{
MessageBox(NULL, _T("创建D3D失败"), _T(""), MB_OK);
DestroyWindow(hwnd);
return 0;
}
D3DPRESENT_PARAMETERS pp = {};
pp.Windowed = TRUE;
pp.SwapEffect = D3DSWAPEFFECT_COPY;
IDirect3DDevice9* device;
if (FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &device)))
{
MessageBox(NULL, _T("创建设备失败"), _T(""), MB_OK);
d3d9->Release();
DestroyWindow(hwnd);
return 0;
}
// hook EndScene
endSceneAddr = (*(void***)device)[42]; // EndScene是IDirect3DDevice9第43个函数
hook(endSceneAddr, MyEndScene, endSceneOldCode);
// 释放
d3d9->Release();
device->Release();
DestroyWindow(hwnd);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// 取当前线程句柄
HANDLE curThread;
if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &curThread, SYNCHRONIZE, FALSE, 0))
return FALSE;
// DllMain中不能使用COM组件,所以要在另一个线程初始化
CloseHandle(CreateThread(NULL, 0, initHookThread, curThread, 0, NULL));
break;
case DLL_PROCESS_DETACH:
if (endSceneAddr != NULL)
unhook(endSceneAddr, endSceneOldCode);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
绘制文字
这部分就直接用D3D的API了,不懂的去看看D3D教程...
HRESULT STDMETHODCALLTYPE MyEndScene(IDirect3DDevice9* thiz)
{
static RECT rect = { 0, 0, 200, 200 };
g_font->DrawText(NULL, _T("Hello World"), -1, &rect, DT_TOP | DT_LEFT, D3DCOLOR_XRGB(255, 0, 0));
return RealEndScene(thiz);
}
HRESULT STDMETHODCALLTYPE MyCreateDevice(IDirect3D9* thiz, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
{
unhookVTable(g_d3d9, 16, RealCreateDevice);
HRESULT res = RealCreateDevice(thiz, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
g_device = *ppReturnedDeviceInterface;
D3DXFONT_DESC d3dFont = {};
d3dFont.Height = 25;
d3dFont.Width = 12;
d3dFont.Weight = 500;
d3dFont.Italic = FALSE;
d3dFont.CharSet = DEFAULT_CHARSET;
wcscpy_s(d3dFont.FaceName, L"Times New Roman");
D3DXCreateFontIndirect(g_device, &d3dFont, &g_font);
// 测试中不知道为什么第一次调用DrawText后device的虚函数表会恢复,没办法只好在hook前调用一次
static RECT rect = { 0, 0, 200, 200 };
g_font->DrawText(NULL, _T("Hello World"), -1, &rect, DT_TOP | DT_LEFT, D3DCOLOR_XRGB(255, 0, 0));
hookVTable(g_device, 42, MyEndScene, &RealEndScene); // EndScene是IDirect3DDevice9第43个函数
return res;
}
版权属于: 顾锦歌——发现生活的美!
本文链接: https://main.huat.fun/index.php/archives/22/
本文最后更新于2022年03月08日 ,已超过1051天没有更新,若内容或图片失效,请留言反馈。
本文允许转载,但请在转载时请以超链接或其它形式标明文章出处
Your go-to source for leads. We can provide business to business and business to consumer leads, custom-tailored to your needs. CustomDatabases.org
Hi, It is with sad regret to inform you TopDataList.com is shutting down. We are ceasing operations on TopDataList.com and have made our leads available at a $149 once off fee. Visit us on TopDataList.com Regards, Otilia
Hello, from CustomData.click we are a provider of unique databases that could help your business. Please visit us at CustomData.click to see if we can help you. Regards, Ervin
Hello. It is with sad regret to inform you TopDataList.com is shutting down. We have made all our databases available for you for a once off fee. Visit us on TopDataList.com
ZippyLeads.org is running an easter special till the 18th of April. Get all the leads you need for your company with our easter special.
Hello. My name is Johan Fourie and I am looking to sell DataList.biz. We are a data company that has been in the industry for 12 years. We do around $170k/year in revenue. 1) I am looking to sell 50% of the business for $5k. 2) It would be helpful if you are knowledgeable about the Data Business. 3) I am looking for someone that is willing to take over administration, support, client relations. 4) I will continue to do the marketing for new products. 5) You will accept all future income and pay me from it. Please contact me on WhatsApp +27 72 280 1952 or my personal email: johanfourieinc@gmail.com if you are interested in this and we can have a call. Regards, Johan Fourie
Hi, I am interested in some of your products. Please give me a call on +1 304-873-4360
欢迎加入 Typecho 大家族