-
Notifications
You must be signed in to change notification settings - Fork 0
/
dxhook.cpp
309 lines (268 loc) · 13.7 KB
/
dxhook.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
//------------------------------------------------------------------------------------------
//
// DXhook.cpp - A dll used to intercept function calls to dx9. It needs to be injected to
// a compiled binary file (.exe) in order to hook it correctly.
// Implemented by Omer Ofir and Roey Ben-Haim
//
//------------------------------------------------------------------------------------------
//
// DXhook library was written with the help of Wiccaan's post in www.extalia.com:
// http://www.extalia.com/forums/viewtopic.php?f=45&t=2578
//
//------------------------------------------------------------------------------------------
#pragma comment(lib, "Detours\\detours.lib")
#include "stdafx.h"
#include "Detours\detours.h"
#include "ID3D9Wrapper.h"
#include <iostream>
#include <fstream>
#include <string>
#include <xstring>
using std::ofstream;
using std::ios;
using std::string;
using std::wstring;
// ------------------------------- Macros ----------------------------------------
#define LOGFILE(text) if (false)\
{ofstream log;\
log.open("D:\\log.txt", ios::app);\
log << (text);\
log.close();}
// ------------------------------- Forward Decelerations -------------------------
LPSTR UnicodeToAnsi(LPCWSTR s);
void StyleSettings(DWORD &dwExStyle, DWORD &dwStyle);
LRESULT CALLBACK Mine_WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
// ------------------------------- Global Variables ------------------------------
HANDLE HookHandle = NULL;
HWND GameHwnd = NULL;
DWORD dwGameStyle = NULL;
DWORD dwGameStyleEx = NULL;
//------------------------------------------------------------------------------------------
// Defining the trampoline prototype for the detour to intercept.
// It's the assential, Direct3DCreate9, which is the basis for every DX based game.
//------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"
{
#endif
//--------------------------------------------------------------------------------------
// DirectX detoured function
//--------------------------------------------------------------------------------------
DETOUR_TRAMPOLINE(IDirect3D9 *WINAPI Real_Direct3DCreate9(UINT SDKVersion), Direct3DCreate9);
//--------------------------------------------------------------------------------------
// Various windows API detoured functions
//--------------------------------------------------------------------------------------
DETOUR_TRAMPOLINE( HWND WINAPI Real_CreateWindowExA (DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam), CreateWindowExA);
DETOUR_TRAMPOLINE( HWND WINAPI Real_CreateWindowExW (DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam), CreateWindowExW);
DETOUR_TRAMPOLINE( ATOM WINAPI Real_RegisterClassExW (CONST WNDCLASSEXW* wndClass), RegisterClassExW);
DETOUR_TRAMPOLINE( ATOM WINAPI Real_RegisterClassExA (CONST WNDCLASSEXA* wndClass), RegisterClassExA);
#ifdef __cplusplus
}
#endif
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// Our Intercepted Functions
//
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Function name: Mine_Direct3DCreate9
// Description: The trampoline for Direct3DCreate9 call. In it we create our own IDirect3D9
// object, which inherits IDirect3D9. It enables us to manipulate calls used
// for this device as we are the middle man in this configuration.
// Parameters: SDKVersion : The SDK version for us to use.
// Returns: Our IDirect3D9 instance which encapsulate a real IDirect3D9
//------------------------------------------------------------------------------------------
IDirect3D9* WINAPI Mine_Direct3DCreate9(UINT SDKVersion)
{
LOGFILE("Direct3DCreate9 called.\n");
IDirect3D9* Direct3D = Real_Direct3DCreate9(SDKVersion);
IDirect3D9* Mine_Direct3D = new Direct3D9Wrapper(Direct3D);
return Mine_Direct3D;
}
//------------------------------------------------------------------------------------------
// Function name: Mine_CreateWindowExA
// Description: The trampoline for CreateWindowExA call. We use this intercepted function
// to try and figure out the application main window handler for later keyboard
// input recieving.
// Parameters: Regular CreateWindowExA Parameters. We don't really need to know what they do
// as our only purpose is to send it to a CreateWindowExA call, initiated by us.
// Returns: The new window handler
//------------------------------------------------------------------------------------------
HWND WINAPI Mine_CreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
if (nWidth > 280 && nWidth < 100000 && !GameHwnd){ // This might be our game window
// ************************ Game window settings override ***********************
StyleSettings(dwExStyle, dwStyle);
string winName(lpClassName);
char tmp[256];
sprintf(tmp, "Entered CreateWindowExW. name: '%s'. size: (%d, %d)\n", winName.c_str() ,nWidth, nHeight);
LOGFILE(tmp);
GameHwnd = Real_CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
return GameHwnd;
}
return Real_CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}
//------------------------------------------------------------------------------------------
// Function name: Mine_CreateWindowExW
// Description: The trampoline for CreateWindowExW call. Same as the function above, only this
// function deals with unicode strings (as the window name etc).
// Parameters: Regular CreateWindowExW Parameters. We don't really need to know what they do
// as our only purpose is to send it to a CreateWindowExA call, initiated by us.
// Returns: The new window handler
//------------------------------------------------------------------------------------------
HWND WINAPI Mine_CreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
if (nWidth > 280 && nWidth < 100000 && !GameHwnd){ // This might be our game window
// ************************ Game window settings override ***********************
StyleSettings(dwExStyle, dwStyle);
string winName(UnicodeToAnsi(lpWindowName));
char tmp[256];
sprintf(tmp, "Entered CreateWindowExW. name: '%s'. size: (%d, %d)\n", winName.c_str() ,nWidth, nHeight);
LOGFILE(tmp);
winName = UnicodeToAnsi(lpClassName);
sprintf(tmp, "Classname: '%s'.\n", winName.c_str());
LOGFILE(tmp);
GameHwnd = Real_CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
return GameHwnd;
}
return Real_CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}
//------------------------------------------------------------------------------------------
// Function name: Mine_RegisterClassExW
// Description: The trampoline for RegisterClassExW call. Used for debug purposes, in order
// to try and figure out how a certain application is executing.
// Parameters: WNDCLASSEXW - a class containing fields for class registration
// Returns: Operation is\not successful
//------------------------------------------------------------------------------------------
ATOM WINAPI Mine_RegisterClassExW(WNDCLASSEXW *wndClass)
{
if (wndClass){
char tmp[256];
LOGFILE("Mine_RegisterClassExW: ");
if (wndClass->lpszClassName){
string wndClassName(UnicodeToAnsi(wndClass->lpszClassName));
sprintf(tmp, "className: %s", wndClassName.c_str());
LOGFILE(tmp);
}
if (wndClass->lpszMenuName){
string wndMenuName(UnicodeToAnsi(wndClass->lpszMenuName));
sprintf(tmp, "menuName: %s", wndMenuName.c_str());
LOGFILE(tmp);
}
if (wndClass->lpfnWndProc){
LOGFILE("There's a WNDPROC.");
}
LOGFILE("\n");
}
return Real_RegisterClassExW(wndClass);
}
//------------------------------------------------------------------------------------------
// Function name: Mine_RegisterClassExA
// Description: The trampoline for RegisterClassExA call. Same as above. Difference with
// the strings.
// Parameters: WNDCLASSEXW - a class containing fields for class registration
// Returns: Operation is\not successful
//------------------------------------------------------------------------------------------
ATOM WINAPI Mine_RegisterClassExA (CONST WNDCLASSEXA* wndClass)
{
#ifdef LOG_REGISTERCLASS
LOGFILE(Mine_RegisterClassExA, "Mine_RegisterClassExA");
#endif
return Real_RegisterClassExA(wndClass);
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// The hooking operations
//
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Function name: HookAPI
// Description: Hooking the real functions and our intercepted ones.
//------------------------------------------------------------------------------------------
void HookAPI()
{
LOGFILE("----------------------------- Hooking API ---------------------\n");
DetourFunctionWithTrampoline( (PBYTE)Real_Direct3DCreate9, (PBYTE)Mine_Direct3DCreate9);
DetourFunctionWithTrampoline( (PBYTE)Real_CreateWindowExA, (PBYTE)Mine_CreateWindowExA );
DetourFunctionWithTrampoline( (PBYTE)Real_CreateWindowExW, (PBYTE)Mine_CreateWindowExW );
}
//------------------------------------------------------------------------------------------
// Function name: UnhookAPI
// Description: Unhooking the real functions and our intercepted ones, upon exit.
//------------------------------------------------------------------------------------------
void UnhookAPI()
{
LOGFILE("----------------------------- Unhooking API ---------------------\n");
DetourRemove( (PBYTE)Real_Direct3DCreate9, (PBYTE)Mine_Direct3DCreate9);
DetourRemove( (PBYTE)Real_CreateWindowExA, (PBYTE)Mine_CreateWindowExA );
DetourRemove( (PBYTE)Real_CreateWindowExW, (PBYTE)Mine_CreateWindowExW );
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// Helper functions
//
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
//------------------------------------------------------------------------------------------
// Function name: UnicodeToAnsi
// Description: This function gets a string in LPCWSTR format and returns a LPSTR one.
// Parameters: The string in LPCWSTR format.
// Returns: The string in LPSTR format.
//------------------------------------------------------------------------------------------
LPSTR UnicodeToAnsi(LPCWSTR s)
{
if (s==NULL) return NULL;
int cw=lstrlenW(s);
if (cw==0) {CHAR *psz=new CHAR[1];*psz='\0';return psz;}
int cc=WideCharToMultiByte(CP_ACP,0,s,cw,NULL,0,NULL,NULL);
if (cc==0) return NULL;
CHAR *psz=new CHAR[cc+1];
cc=WideCharToMultiByte(CP_ACP,0,s,cw,psz,cc,NULL,NULL);
if (cc==0) {delete[] psz;return NULL;}
psz[cc]='\0';
return psz;
}
//------------------------------------------------------------------------------------------
// Function name: StyleSettings
// Description: Setting the style settings words for window creation.
// Parameters: dwExStyle - Reference for the style DWORD need to be set.
// dwStyle - Reference for another style DWORD need to be set.
//------------------------------------------------------------------------------------------
void StyleSettings(DWORD &dwExStyle, DWORD &dwStyle)
{
dwStyle = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPEDWINDOW;
// ** Remove Extra Settings From The Style If They Exist
if( dwExStyle & WS_EX_CLIENTEDGE )
dwExStyle -= WS_EX_CLIENTEDGE;
if( dwExStyle & WS_EX_DLGMODALFRAME )
dwExStyle -= WS_EX_DLGMODALFRAME;
if( dwExStyle & WS_EX_WINDOWEDGE )
dwExStyle -= WS_EX_WINDOWEDGE;
if( dwExStyle & WS_EX_STATICEDGE )
dwExStyle -= WS_EX_STATICEDGE;
}
//------------------------------------------------------------------------------------------
// Function name: DllMain
// Description: The dll's main entry point
// Parameters: Parameters are used to determine the creation purpose.
// Returns: TRUE.
//------------------------------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
HookHandle = hModule;
HookAPI();
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
UnhookAPI();
}
return TRUE;
}