Здравствуйте! Необходимо реализовать снятие скриншота в DirectX приложениях (играх). Поискав информацию в сети, пришёл к выводу, что для этого мне надо внедрять dll в приложение и перехватывать функцию D3DEndScene. Нашёл несколько примеров, но не удалось ни один из них заставить работать.
С внедрерением проблем нет. DLL внедряется, DllMain выполняется. А вот сделать хук D3DEndScene не выходит. Важно, чтобы я мог внедрить эту DLL уже непосредственно в работающую программу, а не при запуске. Может кто-то помочь в решении данной проблемы?
Текущий код DLL:
Код | #include <d3d9.h> #include <d3dx9.h>
#pragma comment (lib, "d3d9.lib") #pragma comment (lib, "d3dx9.lib")
#pragma once
typedef HRESULT (WINAPI *CreateDevice_t)(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface); typedef HRESULT (WINAPI *EndScene_t)(IDirect3DDevice9* surface);
CreateDevice_t D3DCreateDevice_orig; EndScene_t D3DEndScene_orig;
HRESULT WINAPI D3DCreateDevice_hook(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface); HRESULT WINAPI D3DEndScene_hook(IDirect3DDevice9* device);
PDWORD IDirect3D9_vtable = NULL;
#define CREATEDEVICE_VTI 16 #define ENDSCENE_VTI 42
HRESULT WINAPI HookCreateDevice(); DWORD WINAPI VTablePatchThread(LPVOID threadParam);
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { HMODULE d3dmodule; PBYTE funcAddress; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBoxA(NULL, "DLL Injected", "DLL Injected", MB_ICONEXCLAMATION); if (HookCreateDevice() == D3D_OK) { return TRUE; } else { return FALSE; }
break; case DLL_THREAD_ATTACH: MessageBoxA(NULL, "DLL_THREAD_ATTACH", "DLL", MB_ICONEXCLAMATION); break; case DLL_THREAD_DETACH: MessageBoxA(NULL, "DLL_THREAD_DETACH", "DLL", MB_ICONEXCLAMATION); break; case DLL_PROCESS_DETACH: MessageBoxA(NULL, "DLL_PROCESS_DETACH", "DLL", MB_ICONEXCLAMATION); break; } return TRUE; }
HRESULT WINAPI HookCreateDevice() { IDirect3D9* device = Direct3DCreate9(D3D_SDK_VERSION); if (!device) { return D3DERR_INVALIDCALL; } IDirect3D9_vtable = (DWORD*)*(DWORD*)device; device->Release();
DWORD protectFlag; if (VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), PAGE_READWRITE, &protectFlag)) { *(DWORD*)&D3DCreateDevice_orig = IDirect3D9_vtable[CREATEDEVICE_VTI]; *(DWORD*)&IDirect3D9_vtable[CREATEDEVICE_VTI] = (DWORD)D3DCreateDevice_hook;
if (!VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), protectFlag, &protectFlag)) { return D3DERR_INVALIDCALL; } } else { return D3DERR_INVALIDCALL; } return D3D_OK; }
HRESULT WINAPI D3DCreateDevice_hook(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { HRESULT result = D3DCreateDevice_orig(Direct3D_Object, Adapter, DeviceType, hFocusWindow, BehaviorFlags | D3DCREATE_MULTITHREADED, pPresentationParameters, ppReturnedDeviceInterface);
DWORD protectFlag; if (VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), PAGE_READWRITE, &protectFlag)) { *(DWORD*)&IDirect3D9_vtable[CREATEDEVICE_VTI] = (DWORD)D3DCreateDevice_orig;
if (!VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), protectFlag, &protectFlag)) { return D3DERR_INVALIDCALL; } } else { return D3DERR_INVALIDCALL; }
if (result == D3D_OK) { IDirect3D9_vtable = (DWORD*)*(DWORD*)*ppReturnedDeviceInterface; *(PDWORD)&D3DEndScene_orig = (DWORD)IDirect3D9_vtable[ENDSCENE_VTI];
if (!CreateThread(NULL, 0, VTablePatchThread, NULL, NULL, NULL)) { return D3DERR_INVALIDCALL; } }
return result; }
DWORD WINAPI VTablePatchThread(LPVOID threadParam) { while (true) { Sleep(100);
*(DWORD*)&IDirect3D9_vtable[ENDSCENE_VTI] = (DWORD)D3DEndScene_hook; } }
HRESULT WINAPI D3DEndScene_hook(IDirect3DDevice9* device) { MessageBoxA(NULL, "Endscene", "4", MB_ICONEXCLAMATION); HRESULT result = NULL;
return result; }
|
|