当使用DirectX attack游戏时,你需要钩住D3DDevice的某些成员函数并知道它的地址。许多人会使用模式扫描来获取功能或设备的地址。这不是一个通用的方法。
首选的、推荐的和最好的方法是创建自己的虚拟设备,复制虚函数表项,这样就可以钩住函数。
虚拟设备的方法
这种方法是100倍的更好和通用的。你创建你自己的设备对象,它获得你可以复制的vTable地址。这是一个由所有设备对象共享的vTable。你现在可以使用常规钩子或vTable钩子,它们会影响游戏的设备。您还可以通过连接这些函数并从eax寄存器中抓取“this指针”来获取设备地址。
下面是我复制d3d9和d3d11接口的虚函数。当然可以在x86和x64上工作。
Direct3d9
static HWND window;
BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam)
{
DWORD wndProcId;
GetWindowThreadProcessId(handle, &wndProcId);
if (GetCurrentProcessId() != wndProcId)
return TRUE; // skip to next window
window = handle;
return FALSE; // window found abort search
}
HWND GetProcessWindow()
{
window = NULL;
EnumWindows(EnumWindowsCallback, NULL);
return window;
}
bool GetD3D9Device(void ** pTable, size_t Size)
{
if (!pTable)
return false;
IDirect3D9 * pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!pD3D)
return false;
IDirect3DDevice9 * pDummyDevice = NULL;
// options to create dummy device
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = false;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = GetProcessWindow();
HRESULT dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
if (dummyDeviceCreated != S_OK)
{
// may fail in windowed fullscreen mode, trying again with windowed mode
d3dpp.Windowed = !d3dpp.Windowed;
dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
if (dummyDeviceCreated != S_OK)
{
pD3D->Release();
return false;
}
}
memcpy(pTable, *reinterpret_cast<void***>(pDummyDevice), Size);
pDummyDevice->Release();
pD3D->Release();
return true;
}
void * d3d9Device[119];
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device)))
{
//hook stuff using the dumped addresses
}
Direct3d11
template <class T>
void SAFE_RELEASE(T * t)
{
if (t)
{
t->Release();
}
}
bool GetD3D11SwapchainDeviceContext(void ** pSwapchainTable, size_t Size_Swapchain, void ** pDeviceTable, size_t Size_Device, void ** pContextTable, size_t Size_Context)
{
WNDCLASSEX wc{ 0 };
wc.cbSize = sizeof(wc);
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = TEXT("dummy class");
if (!RegisterClassEx(&wc))
{
return false;
}
HWND hWnd = CreateWindow(wc.lpszClassName, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, nullptr);
DXGI_SWAP_CHAIN_DESC swapChainDesc{ 0 };
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Windowed = TRUE;
D3D_FEATURE_LEVEL featureLevel[] =
{
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_12_1
};
IDXGISwapChain * pDummySwapChain = nullptr;
ID3D11Device * pDummyDevice = nullptr;
ID3D11DeviceContext * pDummyContext = nullptr;
if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &pDummySwapChain, &pDummyDevice, nullptr, &pDummyContext)))
{
DestroyWindow(swapChainDesc.OutputWindow);
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
return false;
}
if (pSwapchainTable && pDummySwapChain)
{
memcpy(pSwapchainTable, *reinterpret_cast<void***>(pDummySwapChain), Size_Swapchain);
}
if (pDeviceTable && pDummyDevice)
{
memcpy(pDeviceTable, *reinterpret_cast<void***>(pDummyDevice), Size_Device);
}
if (pContextTable && pDummyContext)
{
memcpy(pContextTable, *reinterpret_cast<void***>(pDummyContext), Size_Context);
}
SAFE_RELEASE(pDummySwapChain);
SAFE_RELEASE(pDummyDevice);
SAFE_RELEASE(pDummyContext);
DestroyWindow(swapChainDesc.OutputWindow);
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
return true;
}
void * SwapChain[18];
void * Device[40];
void * Context[108];
if (GetD3D11SwapchainDeviceContext(SwapChain, sizeof(SwapChain), Device, sizeof(Device), Context, sizeof(Context)))
{
//hook stuff using the dumped addresses
}
通用钩子dxd9 - dxd12, opengl和vulkan
#include "kiero.h"
#include <d3d9.h>
#include <MinHook.h>
#include <Windows.h>
typedef long(__stdcall* EndScene)(LPDIRECT3DDEVICE);
EndScene oEndScene = NULL;
long __stdcall hkEndScene(LPDIRECT3DDEVICE pDevice)
{
static bool init = false;
if (!init)
{
MessageBox(0, "Boom! It's works!", "Kiero", MB_OK);
init = true;
}
return oEndScene(pDevice);
}
int kieroExampleThread()
{
if (kiero::init(kiero::RenderType::D3D9) == kiero::Status::Success)
{
kiero::bind(42, oEndScene, hkEndScene);
}
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID)
{
DisableThreadLibraryCalls(hInstance);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)kieroExampleThread, NULL, 0, NULL);
break;
}
return TRUE;
}