【C++】实现D3D9 的 Inline hook - 水风井
source link: https://www.cnblogs.com/water-wells/p/16619679.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
【C++】实现D3D9 的 Inline hook
#include<process.h> int __stdcall DllMain(void* _DllHandle, unsigned long _Reason, void*_Reserved) { if (_Reason == DLL_PROCESS_ATTACH) { _beginthreadex(nullptr, 0, initialize_d3d9, nullptr, 0, nullptr); } return 1; }// 注:initialize_d3d9是d3d9部分的函数
#pragma once #include<Windows.h> constexpr int byte_length = 5; //修改函数的前五个字节,修改为jmp class inline_hook { private: using uchar = unsigned char; using dword = DWORD; uchar m_original_byte[byte_length]; uchar m_self_byte[byte_length]; int m_original_address; //原始函数的地址 int m_self_address;//自己函数的地址 dword motify_memory_attribute(int address, dword attribute = PAGE_EXECUTE_READWRITE) { dword old_attributes; VirtualProtect(reinterpret_cast<void*>(address), byte_length, attribute, &old_attributes); return old_attributes; } public: inline_hook(int original_address, int self_address) :m_original_address(original_address), m_self_address(self_address) { m_self_byte[0] = '\xe9'; //jmp的硬编码 int offset = self_address - (original_address + byte_length); //计算偏移 memcpy(&m_self_byte[1], &offset, byte_length - 1); //构造字节 dword attribute = motify_memory_attribute(original_address); //修改内存属性 memcpy(m_original_byte, reinterpret_cast<void*>(original_address), byte_length); //将程序原来的函数代码保存到 m_original_byte motify_memory_attribute(original_address, attribute); // 还原内存属性 } void motify_address() //修改原来的函数 { dword attribute = motify_memory_attribute(m_original_address); //修改内存属性 //写入自己构造的字节 memcpy(reinterpret_cast<void*>(m_original_address), m_self_byte, byte_length);// 将构造好的字节,覆盖到原来的函数的地方 motify_memory_attribute(m_original_address, attribute); //还原内存属性 } void restore_address() //恢复原来的函数 { dword attribute = motify_memory_attribute(m_original_address); memcpy(reinterpret_cast<void*>(m_original_address), m_original_byte, byte_length); motify_memory_attribute(m_original_address, attribute); } };
代码部分(D3D9部分):
/*需要包含的头文件*/ #include<d3d9.h> #include<HOOK部分代码> #pragma comment(lib,"d3d9.lib") /*一些必要的全局变量*/ IDirect3D9 * g_direct3d9 = nullptr; IDirect3DDevice9 *g_direct3ddevice9 = nullptr; D3DPRESENT_PARAMETERS g_present; HWND g_hwnd = FindWindowA(nullptr, "Counter-Strike: Global Offensive - Direct3D 9"); //HWND g_hwnd = FindWindowA("Valve001",nullptr); inline_hook*g_Reset_hook = nullptr; //hook Reset 函数 inline_hook*g_EndScene_hook = nullptr; inline_hook*g_DrawIndexedPrimitive_hook = nullptr; /*如果需要劫持Reset函数,则写一个函数代替原来的Reset*/ HRESULT __stdcall self_Reset(IDirect3DDevice9 *g_direct3ddevice9, D3DPRESENT_PARAMETERS* pPresentationParameters) { printf("join\n"); //自己需要实现的功能写在这里 HRESULT result = D3D_OK; g_Reset_hook->restore_address(); if (g_direct3ddevice9) { ImGui_ImplDX9_InvalidateDeviceObjects(); HRESULT result = g_direct3ddevice9->Reset(pPresentationParameters); //调用原来的Reset函数 ImGui_ImplDX9_CreateDeviceObjects(); } g_Reset_hook->motify_address(); return result; } /*DLL注入后执行此函数*/ unsigned int __stdcall initialize_d3d9(void*data) { AllocConsole(); freopen("CON", "w", stdout); g_direct3d9 = Direct3DCreate9(D3D_SDK_VERSION); check_error(g_direct3d9, "Direct3DCreate9失败"); memset(&g_present, 0, sizeof(g_present)); g_present.Windowed = TRUE; g_present.SwapEffect = D3DSWAPEFFECT_DISCARD; g_present.BackBufferFormat = D3DFMT_UNKNOWN; g_present.EnableAutoDepthStencil = TRUE; g_present.AutoDepthStencilFormat = D3DFMT_D16; HRESULT result = g_direct3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_present, &g_direct3ddevice9); check_error(result == 0, "CreateDevice失败"); int *direct3d9_table = (int*)*(int *)g_direct3d9; int *direct3ddevice9_table = (int*)*(int *)g_direct3ddevice9;//这里是一个表,储存了direct的函数,通过劫持这些函数,转接到自己的函数,通过速览IDirect3DDevice9的定义可以看到函数 g_Reset_hook = new inline_hook(direct3ddevice9_table[16], (int)self_Reset); //hook掉了reset g_Reset_hook->motify_address(); //还原了Reset //direct3ddevice9_table[下标],下标通过速览定义IDirect3DDevice9结构可知,看需要hook掉的函数在结构的第几位,减去一则是下标 return 0; }
此时以DLL编译,完成后用DLL注入器注入,则完成D3D9的inline hook,需要HOOK其他函数,则仿照Reset_hook 的写法
g_Reset_hook = new inline_hook(direct3ddevice9_table[16], (int)self_Reset); //hook掉了reset g_Reset_hook->motify_address(); //还原了Reset
HOOK 掉 DrawIndexedPrimitive举例
先写自己的函数
HRESULT __stdcall self_DrawIndexedPrimitive(IDirect3DDevice9 *g_direct3ddevice9,D3DPRIMITIVETYPE type, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) { HRESULT result = D3D_OK; { /*自己的功能*/ } g_DrawIndexedPrimitive_hook->restore_address(); result = g_direct3ddevice9->DrawIndexedPrimitive(type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); g_DrawIndexedPrimitive_hook->motify_address(); return result; }
在 initialize_d3d9 函数中增加
g_DrawIndexedPrimitive_hook = new inline_hook(direct3ddevice9_table[82], (int)self_DrawIndexedPrimitive); //hook掉了DrawIndexedPrimitive
g_DrawIndexedPrimitive_hook->motify_address();
至此,完成对DrawIndexedPrimitive的HOOK
ENDING.............
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK