Получение скриншота DirectX через внедренную dll
Необходимо реализовать снятие скриншота в 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;
}
#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;
}
Проблема решена.
если не сложно скажите как проблема решилась, буду очень признателен!
всем спасибо что откликнулись... проблема решена.