Code:
//-----------------------------------------------------------------------------------------------------------------------------------
/****************************************************************
Coded by: JoshRose
Type: D3D VTable Base Hook
Credits: Strife, R4z8r, Zoomgod, Roverturbo and MSDN. Thanks all
for helping me when i got stuck.
****************************************************************/
//----------------------------------------------------------------------------------------------------------------------------------
#include <windows.h>
//----------------------------------------------------------------------------------------------------------------------------------
#include "Main.h"
//-----------------------------------------------------------------------------------------------------------------------------------
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
//-----------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
//-----------------------------------------------------------------------------------------------------------------------------------
#include <fstream>
//-----------------------------------------------------------------------------------------------------------------------------------
#include "detours.h"
#pragma comment(lib,"detours.lib")
//-----------------------------------------------------------------------------------------------------------------------------------
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
//-----------------------------------------------------------------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------
#define HOOK(func,addy) o##func = (t##func)DetourFunction((PBYTE)addy,(PBYTE)hk##func) //Quick Hook using MS Detour
#define UNHOOK(func,addy) o##func = (t##func)DetourFunction((PBYTE)addy,(PBYTE)o##func) //Quick Unook using MS Detour
//---------------------------------------------------------------------------------------------------------------------------------
#define ES 0 //EndScene
#define DIP 1 //DrawIndexedPrimitive
#define RES 2 //Reset
#define CQ 3 //CreateQuery
#define SSS 4 //SetStreamSource
//---------------------------------------------------------------------------------------------------------------------------------
LPDIRECT3DDEVICE9 npDevice; //pDevice is stored here so we can hook through the VTable
//---------------------------------------------------------------------------------------------------------------------------------
LPD3DXFONT g_pFont = NULL; //D3D Font
LPD3DXLINE g_pLine = NULL; //D3D Line
D3DVIEWPORT9 g_ViewPort; //ViewPort
//---------------------------------------------------------------------------------------------------------------------------------
//LPDIRECT3DVERTEXBUFFER9 Stream_Data;
//UINT Offset = 0;
//UINT Stride = 0;
unsigned int m_Stride;
bool Chams;
IDirect3DPixelShader9 *shaderRed;
IDirect3DPixelShader9 *shaderBlue;
//---------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------
typedef HRESULT (WINAPI* tSetStreamSource)(LPDIRECT3DDEVICE9 pDevice,UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride);
tSetStreamSource oSetStreamSource;
typedef HRESULT (WINAPI* tEndScene)(LPDIRECT3DDEVICE9 pDevice);
tEndScene oEndScene = NULL;
typedef HRESULT (WINAPI* tDrawIndexedPrimitive)(LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE PrimType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount);
tDrawIndexedPrimitive oDrawIndexedPrimitive = NULL;
typedef HRESULT(WINAPI* tReset)(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters);
tReset oReset = NULL;
typedef HRESULT (WINAPI* tCreateQuery)(LPDIRECT3DDEVICE9 pDevice, D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery);
tCreateQuery oCreateQuery;
//---------------------------------------------------------------------------------------------------------------------------------
PBYTE HookVTableFunction( PDWORD* dwVTable, PBYTE dwHook, INT Index )
{
DWORD dwOld = 0;
VirtualProtect((void*)((*dwVTable) + (Index*4) ), 4, PAGE_EXECUTE_READWRITE, &dwOld);
PBYTE pOrig = ((PBYTE)(*dwVTable)[Index]);
(*dwVTable)[Index] = (DWORD)dwHook;
VirtualProtect((void*)((*dwVTable) + (Index*4)), 4, dwOld, &dwOld);
return pOrig;
}
//-----------------------------------------------------------------------------------------------------------------------------------
HRESULT GenerateShader( IDirect3DDevice9 *pDevice, IDirect3DPixelShader9 **pShader, float r, float g, float b )
{
char szShader[ 256 ];
ID3DXBuffer *pShaderBuf = NULL;
sprintf_s( szShader, "ps_3_0\ndef c0, %f, %f, %f, %f\nmov oC0,c0", r, g, b, 1.0f );
if( D3DXAssembleShader( szShader, sizeof( szShader ), NULL, NULL, 0, &pShaderBuf, NULL ) == D3D_OK )
pDevice->CreatePixelShader( ( const DWORD* )pShaderBuf->GetBufferPointer(), pShader );
else
return E_FAIL;
return S_OK;
}
//-----------------------------------------------------------------------------------------------------------------------------------
HRESULT WINAPI hkCreateQuery(LPDIRECT3DDEVICE9 pDevice, D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery)
{
if (m_Stride = 36)
{
if( Type == D3DQUERYTYPE_OCCLUSION )
{
Type = D3DQUERYTYPE_EVENT;
}
}
return oCreateQuery( pDevice, Type, ppQuery );
}
//-----------------------------------------------------------------------------------------------------------------------------------
HRESULT WINAPI hkSetStreamSource(LPDIRECT3DDEVICE9 pDevice,UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride)
{
if(StreamNumber == 0){
m_Stride = Stride;
}
return oSetStreamSource(pDevice, StreamNumber, pStreamData, OffsetInBytes, Stride);
}
//-----------------------------------------------------------------------------------------------------------------------------------
HRESULT WINAPI hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
while(!npDevice) {
npDevice = pDevice; //Here we store pDevice so we can re-hook with a VTable hook later.
}
if (GetAsyncKeyState(VK_INSERT)&1)
{
Chams = !Chams;
}
if(g_pFont == NULL) D3DXCreateFont(pDevice, 15, 0, FW_BOLD, 1, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Verdana", &g_pFont); //Create fonts
if(g_pLine == NULL) D3DXCreateLine(pDevice, &g_pLine); //Create lines
pDevice->GetViewport(&g_ViewPort);
GenerateShader(pDevice, &shaderBlue, 0.0f, 0.0f, 1.0f);
GenerateShader(pDevice, &shaderRed, 1.0f, 0.0f, 0.0f);
return oEndScene(pDevice);
}
//---------------------------------------------------------------------------------------------------------------------------------
HRESULT WINAPI hkDrawIndexedPrimitive(LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE PrimType,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount)
{
//if(pDevice->GetStreamSource(0, &Stream_Data, &Offset, &Stride) == D3D_OK)
//Stream_Data->Release();
if (Chams)
{
if ((m_Stride == 36 && ((primCount >= 1000))))//FIX THIS
{
pDevice->SetRenderState((D3DRENDERSTATETYPE)0x28, FALSE);
pDevice->SetRenderState(D3DRS_LASTPIXEL, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
pDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
//
pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
pDevice->SetPixelShader( shaderBlue ); //behind color
oDrawIndexedPrimitive(pDevice, PrimType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
pDevice->SetPixelShader( shaderRed ); //isvisible color
//pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
oDrawIndexedPrimitive(pDevice, PrimType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
//pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
}
}
return oDrawIndexedPrimitive(pDevice, PrimType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
}
//---------------------------------------------------------------------------------------------------------------------------------
HRESULT WINAPI hkReset(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
if( g_pFont )
g_pFont->OnLostDevice();
if( g_pLine )
g_pLine->OnLostDevice();
HRESULT iReturnValue = oReset(pDevice, pPresentationParameters);
if(iReturnValue == D3D_OK) {
if( g_pFont )
g_pFont->OnResetDevice();
if( g_pLine )
g_pLine->OnResetDevice();
}
return iReturnValue;
}
//-----------------------------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){return DefWindowProc(hwnd, uMsg, wParam, lParam);}
void DX_Init(DWORD* table)
{
WNDCLASSEX wc = {sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,0L,0L,GetModuleHandle(NULL),NULL,NULL,NULL,NULL,"DX",NULL};
RegisterClassEx(&wc);
HWND hWnd = CreateWindow("DX",NULL,WS_OVERLAPPED,100,100,300,300,GetDesktopWindow(),NULL,wc.hInstance,NULL);
LPDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
LPDIRECT3DDEVICE9 pd3dDevice;
pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&pd3dDevice);
DWORD* pVTable = (DWORD*)pd3dDevice;
pVTable = (DWORD*)pVTable[0];
table[ES] = pVTable[42]; //EndScene address
table[DIP] = pVTable[82]; //DrawIndexedPrimitive address
table[RES] = pVTable[16]; //Reset address
table[CQ] = pVTable[118]; //CreateQuery address
table[SSS] = pVTable[100]; //SetStreamSource address
DestroyWindow(hWnd);
}
//------------------------------------------------------------------------------------------------------------------------------------
DWORD WINAPI VirtualMethodTableRepatchingLoopToCounterExtensionRepatching( LPVOID Param )
{
while(1) {
Sleep(100);
HookVTableFunction((PDWORD*)npDevice, (PBYTE)hkDrawIndexedPrimitive, 82); //Hook DrawIndexedPrimitive
HookVTableFunction((PDWORD*)npDevice, (PBYTE)hkEndScene, 42); //Hook EndScene
HookVTableFunction((PDWORD*)npDevice, (PBYTE)hkReset, 16); //Hook Reset
HookVTableFunction((PDWORD*)npDevice, (PBYTE)hkCreateQuery, 118); //Hook CreateQuery
HookVTableFunction((PDWORD*)npDevice, (PBYTE)hkSetStreamSource, 100); //Hook SetStreamSource
}
return 1;
}
//------------------------------------------------------------------------------------------------------------------------------------
bool hooked = false;
DWORD WINAPI LoopFunction( LPVOID lpParam )
{
if( hooked == false) {
DWORD VTable[5] = {0};
while(GetModuleHandle("d3d9.dll")==NULL) {
Sleep(250);
}
DX_Init(VTable);
HOOK(EndScene,VTable[ES]); //Hook EndScene as a device discovery hook
while(!npDevice) {
Sleep(50); //Sleep until npDevice is not equal to NULL
}
UNHOOK(EndScene, VTable[ES]); //Unhook as soon as we have a valid pointer to pDevice
*(PDWORD)&oDrawIndexedPrimitive = VTable[DIP];
*(PDWORD)&oEndScene = VTable[ES];
*(PDWORD)&oReset = VTable[RES];
*(PDWORD)&oCreateQuery = VTable[CQ];
*(PDWORD)&oSetStreamSource = VTable[SSS];
CreateThread(NULL,0,&VirtualMethodTableRepatchingLoopToCounterExtensionRepatching,NULL,0,NULL); //Create hooking thread
hooked = true;
Sleep(200);
}
return 0;
}
//------------------------------------------------------------------------------------------------------------------------------------
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved)
{
if(dwReason == DLL_PROCESS_ATTACH) {
CreateThread(0, 0, LoopFunction, 0, 0, 0);
}
else if(dwReason == DLL_PROCESS_DETACH) {
}
return TRUE;
}
//------------------------------------------------------------------------------------------------------------------------------------