blob: 81539ff9594b021d78bbffea18ce49d3717871c1 [file] [log] [blame]
José Fonsecabd4937e2012-12-04 13:23:03 +00001/**************************************************************************
2 *
Jose Fonsecaff5a5852016-09-07 16:06:09 +01003 * Copyright 2016 VMware, Inc.
José Fonsecabd4937e2012-12-04 13:23:03 +00004 * Copyright 2011-2012 Jose Fonseca
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 **************************************************************************/
26
27
28/*
29 * Code for the DLL that will be injected in the target process.
30 *
31 * The injected DLL will manipulate the import tables to hook the
32 * modules/functions of interest.
33 *
34 * See also:
35 * - http://www.codeproject.com/KB/system/api_spying_hack.aspx
36 * - http://www.codeproject.com/KB/threads/APIHooking.aspx
37 * - http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
38 */
39
40
41#include <assert.h>
42#include <stdio.h>
43#include <stdarg.h>
José Fonseca5e6332c2014-09-03 14:34:44 +010044#include <string.h>
José Fonsecabd4937e2012-12-04 13:23:03 +000045
José Fonseca3e60c242014-09-26 19:44:29 +010046#include <algorithm>
Jose Fonseca159d62d2014-06-18 14:54:47 +010047#include <set>
José Fonseca5e6332c2014-09-03 14:34:44 +010048#include <map>
49#include <functional>
Jose Fonsecaff5a5852016-09-07 16:06:09 +010050#include <iterator>
Jose Fonseca159d62d2014-06-18 14:54:47 +010051
José Fonsecabd4937e2012-12-04 13:23:03 +000052#include <windows.h>
53#include <tlhelp32.h>
José Fonseca8255d9e2014-09-12 09:10:02 +010054#include <delayimp.h>
José Fonsecabd4937e2012-12-04 13:23:03 +000055
56#include "inject.h"
Jose Fonsecaff5a5852016-09-07 16:06:09 +010057#include "mhook.h"
José Fonsecabd4937e2012-12-04 13:23:03 +000058
Jose Fonsecaeb7e8742017-08-04 16:49:02 +010059#include "os_symbols.hpp"
60
José Fonsecabd4937e2012-12-04 13:23:03 +000061
Jose Fonseca59f21c42015-07-06 16:41:55 +010062static int VERBOSITY = 0;
José Fonsecabd4937e2012-12-04 13:23:03 +000063#define NOOP 0
64
65
Jose Fonseca94bbf782015-11-16 15:02:00 +000066static CRITICAL_SECTION g_Mutex;
José Fonsecabd4937e2012-12-04 13:23:03 +000067
68
José Fonseca02c6ece2014-08-26 15:32:28 +010069
70static HMODULE g_hThisModule = NULL;
José Fonseca5e6332c2014-09-03 14:34:44 +010071static HMODULE g_hHookModule = NULL;
José Fonseca02c6ece2014-08-26 15:32:28 +010072
73
Jose Fonsecaff5a5852016-09-07 16:06:09 +010074static std::map<PVOID, PVOID>
75g_pRealFunctions;
76
77
Jose Fonseca8a154262016-09-19 22:35:44 +010078typedef HMODULE
79(WINAPI *PFNLOADLIBRARYA)(LPCSTR);
80
81typedef HMODULE
82(WINAPI *PFNLOADLIBRARYW)(LPCWSTR);
83
84typedef HMODULE
85(WINAPI *PFNLOADLIBRARYEXA)(LPCSTR, HANDLE, DWORD);
86
87typedef HMODULE
88(WINAPI *PFNLOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
89
90typedef BOOL
91(WINAPI *PFNFREELIBRARY)(HMODULE);
92
93static PFNLOADLIBRARYA RealLoadLibraryA = LoadLibraryA;
94static PFNLOADLIBRARYW RealLoadLibraryW = LoadLibraryW;
95static PFNLOADLIBRARYEXA RealLoadLibraryExA = LoadLibraryExA;
96static PFNLOADLIBRARYEXW RealLoadLibraryExW = LoadLibraryExW;
97static PFNFREELIBRARY RealFreeLibrary = FreeLibrary;
98
Jose Fonsecaff5a5852016-09-07 16:06:09 +010099typedef FARPROC (WINAPI * PFNGETPROCADDRESS)(HMODULE hModule, LPCSTR lpProcName);
100
101static PFNGETPROCADDRESS RealGetProcAddress = GetProcAddress;
102
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100103typedef BOOL
104(WINAPI *PFNCREATEPROCESSA) (LPCSTR, LPSTR,
105 LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,
106 LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
107
108static PFNCREATEPROCESSA RealCreateProcessA = CreateProcessA;
109
110typedef BOOL
111(WINAPI *PFNCREATEPROCESSW) (LPCWSTR, LPWSTR,
112 LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,
113 LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
114
115static PFNCREATEPROCESSW RealCreateProcessW = CreateProcessW;
116
117typedef BOOL
118(WINAPI *PFNCREATEPROCESSASUSERW) (HANDLE, LPCWSTR, LPWSTR,
119 LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,
120 LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
121
122static PFNCREATEPROCESSASUSERW RealCreateProcessAsUserW = CreateProcessAsUserW;
123
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100124
José Fonsecabd4937e2012-12-04 13:23:03 +0000125static void
126debugPrintf(const char *format, ...)
127{
José Fonseca1a617aa2013-02-22 09:41:54 +0000128 char buf[512];
José Fonsecabd4937e2012-12-04 13:23:03 +0000129
130 va_list ap;
131 va_start(ap, format);
132 _vsnprintf(buf, sizeof buf, format, ap);
133 va_end(ap);
134
135 OutputDebugStringA(buf);
José Fonsecabd4937e2012-12-04 13:23:03 +0000136}
137
138
Jose Fonseca5c9ad112015-07-06 16:42:21 +0100139EXTERN_C void
140_assert(const char *_Message, const char *_File, unsigned _Line)
141{
142 debugPrintf("Assertion failed: %s, file %s, line %u\n", _Message, _File, _Line);
143 TerminateProcess(GetCurrentProcess(), 1);
144}
145
146
Robert Tarasov34921b22020-11-14 18:04:40 -0800147#ifndef __MINGW32__
148
Jose Fonseca5c9ad112015-07-06 16:42:21 +0100149EXTERN_C void
150_wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line)
151{
152 debugPrintf("Assertion failed: %S, file %S, line %u\n", _Message, _File, _Line);
153 TerminateProcess(GetCurrentProcess(), 1);
154}
155
Robert Tarasov34921b22020-11-14 18:04:40 -0800156#endif /* !__MINGW32__ */
157
Jose Fonseca5c9ad112015-07-06 16:42:21 +0100158
José Fonseca02c6ece2014-08-26 15:32:28 +0100159static void
160MyCreateProcessCommon(BOOL bRet,
161 DWORD dwCreationFlags,
162 LPPROCESS_INFORMATION lpProcessInformation)
163{
164 if (!bRet) {
Jose Fonseca6ddfd982015-08-03 11:58:35 +0100165 debugPrintf("inject: warning: failed to create child process\n");
José Fonseca02c6ece2014-08-26 15:32:28 +0100166 return;
167 }
168
Jose Fonseca953907a2015-06-26 10:50:16 +0100169 DWORD dwLastError = GetLastError();
170
Jose Fonseca6ddfd982015-08-03 11:58:35 +0100171 if (isDifferentArch(lpProcessInformation->hProcess)) {
172 debugPrintf("inject: error: child process %lu has different architecture\n",
173 GetProcessId(lpProcessInformation->hProcess));
174 } else {
175 char szDllPath[MAX_PATH];
176 GetModuleFileNameA(g_hThisModule, szDllPath, sizeof szDllPath);
José Fonseca02c6ece2014-08-26 15:32:28 +0100177
Jose Fonseca6ddfd982015-08-03 11:58:35 +0100178 if (!injectDll(lpProcessInformation->hProcess, szDllPath)) {
179 debugPrintf("inject: warning: failed to inject into child process %lu\n",
180 GetProcessId(lpProcessInformation->hProcess));
181 }
José Fonseca02c6ece2014-08-26 15:32:28 +0100182 }
183
184 if (!(dwCreationFlags & CREATE_SUSPENDED)) {
185 ResumeThread(lpProcessInformation->hThread);
186 }
Jose Fonseca953907a2015-06-26 10:50:16 +0100187
188 SetLastError(dwLastError);
José Fonseca02c6ece2014-08-26 15:32:28 +0100189}
190
José Fonseca51a70172014-06-19 13:23:14 +0100191static BOOL WINAPI
192MyCreateProcessA(LPCSTR lpApplicationName,
193 LPSTR lpCommandLine,
194 LPSECURITY_ATTRIBUTES lpProcessAttributes,
195 LPSECURITY_ATTRIBUTES lpThreadAttributes,
196 BOOL bInheritHandles,
197 DWORD dwCreationFlags,
198 LPVOID lpEnvironment,
199 LPCSTR lpCurrentDirectory,
200 LPSTARTUPINFOA lpStartupInfo,
José Fonseca02c6ece2014-08-26 15:32:28 +0100201 LPPROCESS_INFORMATION lpProcessInformation)
202{
203 if (VERBOSITY >= 2) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100204 debugPrintf("inject: intercepting %s(\"%s\", \"%s\", ...)\n",
José Fonseca02c6ece2014-08-26 15:32:28 +0100205 __FUNCTION__,
206 lpApplicationName,
207 lpCommandLine);
208 }
209
210 BOOL bRet;
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100211 bRet = RealCreateProcessA(lpApplicationName,
212 lpCommandLine,
213 lpProcessAttributes,
214 lpThreadAttributes,
215 bInheritHandles,
216 dwCreationFlags | CREATE_SUSPENDED,
217 lpEnvironment,
218 lpCurrentDirectory,
219 lpStartupInfo,
220 lpProcessInformation);
José Fonseca02c6ece2014-08-26 15:32:28 +0100221
222 MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
223
224 return bRet;
225}
José Fonseca51a70172014-06-19 13:23:14 +0100226
227static BOOL WINAPI
228MyCreateProcessW(LPCWSTR lpApplicationName,
229 LPWSTR lpCommandLine,
230 LPSECURITY_ATTRIBUTES lpProcessAttributes,
231 LPSECURITY_ATTRIBUTES lpThreadAttributes,
232 BOOL bInheritHandles,
233 DWORD dwCreationFlags,
234 LPVOID lpEnvironment,
235 LPCWSTR lpCurrentDirectory,
236 LPSTARTUPINFOW lpStartupInfo,
José Fonseca02c6ece2014-08-26 15:32:28 +0100237 LPPROCESS_INFORMATION lpProcessInformation)
238{
239 if (VERBOSITY >= 2) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100240 debugPrintf("inject: intercepting %s(\"%S\", \"%S\", ...)\n",
José Fonseca02c6ece2014-08-26 15:32:28 +0100241 __FUNCTION__,
242 lpApplicationName,
243 lpCommandLine);
244 }
245
246 BOOL bRet;
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100247 bRet = RealCreateProcessW(lpApplicationName,
248 lpCommandLine,
249 lpProcessAttributes,
250 lpThreadAttributes,
251 bInheritHandles,
252 dwCreationFlags | CREATE_SUSPENDED,
253 lpEnvironment,
254 lpCurrentDirectory,
255 lpStartupInfo,
256 lpProcessInformation);
José Fonseca02c6ece2014-08-26 15:32:28 +0100257
258 MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
259
260 return bRet;
261}
José Fonseca51a70172014-06-19 13:23:14 +0100262
José Fonseca193c5b22014-08-26 15:32:56 +0100263static BOOL WINAPI
José Fonseca193c5b22014-08-26 15:32:56 +0100264MyCreateProcessAsUserW(HANDLE hToken,
265 LPCWSTR lpApplicationName,
266 LPWSTR lpCommandLine,
267 LPSECURITY_ATTRIBUTES lpProcessAttributes,
268 LPSECURITY_ATTRIBUTES lpThreadAttributes,
269 BOOL bInheritHandles,
270 DWORD dwCreationFlags,
271 LPVOID lpEnvironment,
272 LPCWSTR lpCurrentDirectory,
273 LPSTARTUPINFOW lpStartupInfo,
274 LPPROCESS_INFORMATION lpProcessInformation)
275{
276 if (VERBOSITY >= 2) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100277 debugPrintf("inject: intercepting %s(\"%S\", \"%S\", ...)\n",
José Fonseca193c5b22014-08-26 15:32:56 +0100278 __FUNCTION__,
279 lpApplicationName,
280 lpCommandLine);
281 }
282
283 BOOL bRet;
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100284 bRet = RealCreateProcessAsUserW(hToken,
285 lpApplicationName,
286 lpCommandLine,
287 lpProcessAttributes,
288 lpThreadAttributes,
289 bInheritHandles,
Jose Fonseca460cf722020-04-15 15:39:35 +0100290 dwCreationFlags | CREATE_SUSPENDED,
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100291 lpEnvironment,
292 lpCurrentDirectory,
293 lpStartupInfo,
294 lpProcessInformation);
José Fonseca193c5b22014-08-26 15:32:56 +0100295
296 MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
297
298 return bRet;
299}
300
José Fonsecabd4937e2012-12-04 13:23:03 +0000301
José Fonseca5e6332c2014-09-03 14:34:44 +0100302template< class T, class I >
303inline T *
304rvaToVa(HMODULE hModule, I rva)
305{
José Fonseca8255d9e2014-09-12 09:10:02 +0100306 assert(rva != 0);
José Fonseca5e6332c2014-09-03 14:34:44 +0100307 return reinterpret_cast<T *>(reinterpret_cast<PBYTE>(hModule) + rva);
308}
309
310
José Fonseca5e6332c2014-09-03 14:34:44 +0100311static PIMAGE_OPTIONAL_HEADER
Jose Fonseca8a25d7e2015-10-09 16:06:25 +0100312getOptionalHeader(HMODULE hModule,
313 const char *szModule)
José Fonseca5e6332c2014-09-03 14:34:44 +0100314{
José Fonseca8255d9e2014-09-12 09:10:02 +0100315 PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hModule);
Jose Fonseca8a25d7e2015-10-09 16:06:25 +0100316 if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
317 debugPrintf("inject: warning: %s: unexpected DOS header magic (0x%04x)\n",
318 szModule, pDosHeader->e_magic);
319 return NULL;
320 }
José Fonseca5e6332c2014-09-03 14:34:44 +0100321 PIMAGE_NT_HEADERS pNtHeaders = rvaToVa<IMAGE_NT_HEADERS>(hModule, pDosHeader->e_lfanew);
Jose Fonseca8a25d7e2015-10-09 16:06:25 +0100322 if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
323 debugPrintf("inject: warning: %s: unexpected NT header signature (0x%08lx)\n",
324 szModule, pNtHeaders->Signature);
325 return NULL;
326 }
José Fonseca5e6332c2014-09-03 14:34:44 +0100327 PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNtHeaders->OptionalHeader;
328 return pOptionalHeader;
329}
330
José Fonseca8255d9e2014-09-12 09:10:02 +0100331static PVOID
332getImageDirectoryEntry(HMODULE hModule,
333 const char *szModule,
334 UINT Entry)
José Fonsecabd4937e2012-12-04 13:23:03 +0000335{
336 MEMORY_BASIC_INFORMATION MemoryInfo;
337 if (VirtualQuery(hModule, &MemoryInfo, sizeof MemoryInfo) != sizeof MemoryInfo) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100338 debugPrintf("inject: warning: %s: VirtualQuery failed\n", szModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000339 return NULL;
340 }
341 if (MemoryInfo.Protect & (PAGE_NOACCESS | PAGE_EXECUTE)) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100342 debugPrintf("inject: warning: %s: no read access (Protect = 0x%08lx)\n", szModule, MemoryInfo.Protect);
José Fonsecabd4937e2012-12-04 13:23:03 +0000343 return NULL;
344 }
345
Jose Fonseca8a25d7e2015-10-09 16:06:25 +0100346 PIMAGE_OPTIONAL_HEADER pOptionalHeader = getOptionalHeader(hModule, szModule);
347 if (!pOptionalHeader ||
348 pOptionalHeader->DataDirectory[Entry].Size == 0) {
José Fonseca387352f2014-09-03 13:05:57 +0100349 return NULL;
350 }
José Fonsecabd4937e2012-12-04 13:23:03 +0000351
José Fonseca8255d9e2014-09-12 09:10:02 +0100352 UINT_PTR ImportAddress = pOptionalHeader->DataDirectory[Entry].VirtualAddress;
José Fonsecabd4937e2012-12-04 13:23:03 +0000353 if (!ImportAddress) {
354 return NULL;
355 }
356
José Fonseca8255d9e2014-09-12 09:10:02 +0100357 return rvaToVa<VOID>(hModule, ImportAddress);
358}
José Fonsecabd4937e2012-12-04 13:23:03 +0000359
José Fonseca8255d9e2014-09-12 09:10:02 +0100360
José Fonseca387352f2014-09-03 13:05:57 +0100361static PIMAGE_EXPORT_DIRECTORY
362getExportDescriptor(HMODULE hModule)
363{
José Fonseca8255d9e2014-09-12 09:10:02 +0100364 PVOID pEntry = getImageDirectoryEntry(hModule, "(wrapper)", IMAGE_DIRECTORY_ENTRY_EXPORT);
365 return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(pEntry);
José Fonsecabd4937e2012-12-04 13:23:03 +0000366}
367
368
Jose Fonseca159d62d2014-06-18 14:54:47 +0100369/* Set of previously hooked modules */
370static std::set<HMODULE>
371g_hHookedModules;
372
José Fonsecabd4937e2012-12-04 13:23:03 +0000373
José Fonseca3e60c242014-09-26 19:44:29 +0100374enum Action {
375 ACTION_HOOK,
376 ACTION_UNHOOK,
377
378};
379
380
José Fonsecabd4937e2012-12-04 13:23:03 +0000381static void
José Fonseca5e6332c2014-09-03 14:34:44 +0100382patchModule(HMODULE hModule,
José Fonseca3e60c242014-09-26 19:44:29 +0100383 const char *szModule,
384 Action action)
José Fonsecabd4937e2012-12-04 13:23:03 +0000385{
José Fonseca5e6332c2014-09-03 14:34:44 +0100386 /* Never patch this module */
387 if (hModule == g_hThisModule) {
388 return;
389 }
390
391 /* Never patch our hook module */
392 if (hModule == g_hHookModule) {
393 return;
394 }
395
Jose Fonseca159d62d2014-06-18 14:54:47 +0100396 /* Hook modules only once */
José Fonseca3e60c242014-09-26 19:44:29 +0100397 if (action == ACTION_HOOK) {
398 std::pair< std::set<HMODULE>::iterator, bool > ret;
Jose Fonseca94bbf782015-11-16 15:02:00 +0000399 EnterCriticalSection(&g_Mutex);
José Fonseca3e60c242014-09-26 19:44:29 +0100400 ret = g_hHookedModules.insert(hModule);
Jose Fonseca94bbf782015-11-16 15:02:00 +0000401 LeaveCriticalSection(&g_Mutex);
José Fonseca3e60c242014-09-26 19:44:29 +0100402 if (!ret.second) {
403 return;
404 }
Jose Fonseca159d62d2014-06-18 14:54:47 +0100405 }
406
José Fonseca5e6332c2014-09-03 14:34:44 +0100407 if (VERBOSITY > 0) {
408 debugPrintf("inject: found module %s\n", szModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000409 }
José Fonseca5e6332c2014-09-03 14:34:44 +0100410
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100411 const char *szBaseName = getBaseName(szModule);
José Fonseca5e6332c2014-09-03 14:34:44 +0100412
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100413 if (stricmp(szBaseName, "opengl32.dll") != 0 &&
414 stricmp(szBaseName, "dxgi.dll") != 0 &&
415 stricmp(szBaseName, "d3d10.dll") != 0 &&
416 stricmp(szBaseName, "d3d10_1.dll") != 0 &&
417 stricmp(szBaseName, "d3d11.dll") != 0 &&
418 stricmp(szBaseName, "d3d9.dll") != 0 &&
419 stricmp(szBaseName, "d3d8.dll") != 0 &&
420 stricmp(szBaseName, "ddraw.dll") != 0 &&
421 stricmp(szBaseName, "dcomp.dll") != 0 &&
422 stricmp(szBaseName, "dxva2.dll") != 0 &&
423 stricmp(szBaseName, "d2d1.dll") != 0 &&
424 stricmp(szBaseName, "dwrite.dll") != 0) {
425 return;
José Fonseca5e6332c2014-09-03 14:34:44 +0100426 }
427
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100428 PIMAGE_EXPORT_DIRECTORY pExportDescriptor = getExportDescriptor(g_hHookModule);
429 assert(pExportDescriptor);
430
431 DWORD *pAddressOfNames = (DWORD *)((BYTE *)g_hHookModule + pExportDescriptor->AddressOfNames);
432 for (DWORD i = 0; i < pExportDescriptor->NumberOfNames; ++i) {
433 const char *szFunctionName = (const char *)((BYTE *)g_hHookModule + pAddressOfNames[i]);
434
435 LPVOID lpOrigAddress = (LPVOID)RealGetProcAddress(hModule, szFunctionName);
436 if (lpOrigAddress) {
437 LPVOID lpHookAddress = (LPVOID)RealGetProcAddress(g_hHookModule, szFunctionName);
438 assert(lpHookAddress);
439
440 // With mhook we intercept the inner gl* calls, so no need to trace the
441 // outer wglUseFont* calls.
442 if (strncmp(szFunctionName, "wglUseFont", strlen("wglUseFont")) == 0) {
443 debugPrintf("inject: not hooking %s!%s\n", szBaseName, szFunctionName);
444 continue;
José Fonseca8255d9e2014-09-12 09:10:02 +0100445 }
446
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100447 if (VERBOSITY > 0) {
448 debugPrintf("inject: hooking %s!%s\n", szModule, szFunctionName);
449 }
José Fonseca8255d9e2014-09-12 09:10:02 +0100450
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100451 LPVOID lpRealAddress = lpOrigAddress;
452 if (!Mhook_SetHook(&lpRealAddress, lpHookAddress)) {
453 debugPrintf("inject: error: failed to hook %s!%s\n", szModule, szFunctionName);
454 }
455
456 EnterCriticalSection(&g_Mutex);
457 g_pRealFunctions[lpOrigAddress] = lpRealAddress;
458 LeaveCriticalSection(&g_Mutex);
459
460 pSharedMem->bReplaced = TRUE;
José Fonseca8255d9e2014-09-12 09:10:02 +0100461 }
462 }
José Fonsecabd4937e2012-12-04 13:23:03 +0000463}
464
José Fonseca3e60c242014-09-26 19:44:29 +0100465
José Fonsecabd4937e2012-12-04 13:23:03 +0000466static void
José Fonseca3e60c242014-09-26 19:44:29 +0100467patchAllModules(Action action)
José Fonsecabd4937e2012-12-04 13:23:03 +0000468{
469 HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
470 if (hModuleSnap == INVALID_HANDLE_VALUE) {
471 return;
472 }
473
474 MODULEENTRY32 me32;
475 me32.dwSize = sizeof me32;
José Fonsecabd4937e2012-12-04 13:23:03 +0000476 if (Module32First(hModuleSnap, &me32)) {
477 do {
José Fonseca3e60c242014-09-26 19:44:29 +0100478 patchModule(me32.hModule, me32.szExePath, action);
José Fonsecabd4937e2012-12-04 13:23:03 +0000479 } while (Module32Next(hModuleSnap, &me32));
480 }
481
482 CloseHandle(hModuleSnap);
483}
484
485
José Fonsecabd4937e2012-12-04 13:23:03 +0000486static HMODULE WINAPI
José Fonsecabd4937e2012-12-04 13:23:03 +0000487MyLoadLibraryA(LPCSTR lpLibFileName)
488{
Jose Fonseca8a154262016-09-19 22:35:44 +0100489 HMODULE hModule = RealLoadLibraryA(lpLibFileName);
Jose Fonseca953907a2015-06-26 10:50:16 +0100490 DWORD dwLastError = GetLastError();
José Fonsecaac114ee2015-02-19 20:16:33 +0000491
José Fonsecabd4937e2012-12-04 13:23:03 +0000492 if (VERBOSITY >= 2) {
José Fonsecaac114ee2015-02-19 20:16:33 +0000493 debugPrintf("inject: intercepting %s(\"%s\") = 0x%p\n",
494 __FUNCTION__ + 2, lpLibFileName, hModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000495 }
496
José Fonsecaac114ee2015-02-19 20:16:33 +0000497 // Hook all new modules (and not just this one, to pick up any dependencies)
José Fonseca3e60c242014-09-26 19:44:29 +0100498 patchAllModules(ACTION_HOOK);
José Fonsecaac114ee2015-02-19 20:16:33 +0000499
Jose Fonseca953907a2015-06-26 10:50:16 +0100500 SetLastError(dwLastError);
José Fonsecaac114ee2015-02-19 20:16:33 +0000501 return hModule;
José Fonsecabd4937e2012-12-04 13:23:03 +0000502}
503
504static HMODULE WINAPI
505MyLoadLibraryW(LPCWSTR lpLibFileName)
506{
Jose Fonseca8a154262016-09-19 22:35:44 +0100507 HMODULE hModule = RealLoadLibraryW(lpLibFileName);
Jose Fonseca953907a2015-06-26 10:50:16 +0100508 DWORD dwLastError = GetLastError();
José Fonsecaac114ee2015-02-19 20:16:33 +0000509
José Fonsecabd4937e2012-12-04 13:23:03 +0000510 if (VERBOSITY >= 2) {
José Fonsecaac114ee2015-02-19 20:16:33 +0000511 debugPrintf("inject: intercepting %s(L\"%S\") = 0x%p\n",
512 __FUNCTION__ + 2, lpLibFileName, hModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000513 }
514
José Fonsecaac114ee2015-02-19 20:16:33 +0000515 // Hook all new modules (and not just this one, to pick up any dependencies)
José Fonseca3e60c242014-09-26 19:44:29 +0100516 patchAllModules(ACTION_HOOK);
José Fonsecabd4937e2012-12-04 13:23:03 +0000517
Jose Fonseca953907a2015-06-26 10:50:16 +0100518 SetLastError(dwLastError);
José Fonsecaac114ee2015-02-19 20:16:33 +0000519 return hModule;
José Fonsecabd4937e2012-12-04 13:23:03 +0000520}
521
José Fonsecaa1ddea32015-02-19 20:55:28 +0000522#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
523#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
524#endif
525#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
526#define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200
527#endif
528#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
529#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
530#endif
531#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
532#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
533#endif
534#ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
535#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
536#endif
537
538static inline DWORD
539adjustFlags(DWORD dwFlags)
540{
541 /*
542 * XXX: LoadLibraryEx seems to interpret "application directory" in respect
543 * to the module that's calling it. So when the application restricts the
544 * search path to application directory via
545 * LOAD_LIBRARY_SEARCH_APPLICATION_DIR or LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
546 * flags, kernel32.dll ends up searching on the directory of the inject.dll
547 * module.
548 *
549 * XXX: What about SetDefaultDllDirectories?
550 *
551 */
552 if (dwFlags & (LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
553 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) {
554 dwFlags &= ~(LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
555 LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
556 LOAD_LIBRARY_SEARCH_USER_DIRS |
557 LOAD_LIBRARY_SEARCH_SYSTEM32 |
558 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
559 }
560
561 return dwFlags;
562}
563
José Fonsecabd4937e2012-12-04 13:23:03 +0000564static HMODULE WINAPI
565MyLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
566{
Jose Fonseca8a154262016-09-19 22:35:44 +0100567 HMODULE hModule = RealLoadLibraryExA(lpLibFileName, hFile, adjustFlags(dwFlags));
Jose Fonseca953907a2015-06-26 10:50:16 +0100568 DWORD dwLastError = GetLastError();
José Fonsecaac114ee2015-02-19 20:16:33 +0000569
José Fonsecabd4937e2012-12-04 13:23:03 +0000570 if (VERBOSITY >= 2) {
José Fonsecaac114ee2015-02-19 20:16:33 +0000571 debugPrintf("inject: intercepting %s(\"%s\", 0x%p, 0x%lx) = 0x%p\n",
572 __FUNCTION__ + 2, lpLibFileName, hFile, dwFlags, hModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000573 }
José Fonsecaac114ee2015-02-19 20:16:33 +0000574
575 // Hook all new modules (and not just this one, to pick up any dependencies)
José Fonseca3e60c242014-09-26 19:44:29 +0100576 patchAllModules(ACTION_HOOK);
José Fonsecaac114ee2015-02-19 20:16:33 +0000577
Jose Fonseca953907a2015-06-26 10:50:16 +0100578 SetLastError(dwLastError);
José Fonsecaac114ee2015-02-19 20:16:33 +0000579 return hModule;
José Fonsecabd4937e2012-12-04 13:23:03 +0000580}
581
582static HMODULE WINAPI
583MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
584{
Jose Fonseca8a154262016-09-19 22:35:44 +0100585 HMODULE hModule = RealLoadLibraryExW(lpLibFileName, hFile, adjustFlags(dwFlags));
Jose Fonseca953907a2015-06-26 10:50:16 +0100586 DWORD dwLastError = GetLastError();
José Fonsecaac114ee2015-02-19 20:16:33 +0000587
José Fonsecabd4937e2012-12-04 13:23:03 +0000588 if (VERBOSITY >= 2) {
José Fonsecaac114ee2015-02-19 20:16:33 +0000589 debugPrintf("inject: intercepting %s(L\"%S\", 0x%p, 0x%lx) = 0x%p\n",
590 __FUNCTION__ + 2, lpLibFileName, hFile, dwFlags, hModule);
José Fonsecabd4937e2012-12-04 13:23:03 +0000591 }
592
José Fonsecaac114ee2015-02-19 20:16:33 +0000593 // Hook all new modules (and not just this one, to pick up any dependencies)
José Fonseca3e60c242014-09-26 19:44:29 +0100594 patchAllModules(ACTION_HOOK);
José Fonsecabd4937e2012-12-04 13:23:03 +0000595
Jose Fonseca953907a2015-06-26 10:50:16 +0100596 SetLastError(dwLastError);
José Fonsecaac114ee2015-02-19 20:16:33 +0000597 return hModule;
José Fonsecabd4937e2012-12-04 13:23:03 +0000598}
599
José Fonsecafdda3862014-09-10 11:35:30 +0100600
601static void
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100602logGetProcAddress(PCSTR szAction, HMODULE hModule, LPCSTR lpProcName, HMODULE hCallerModule)
603{
604 char szCaller[MAX_PATH];
605 DWORD dwRet = GetModuleFileNameA(hCallerModule, szCaller, sizeof szCaller);
606 assert(dwRet);
607
José Fonsecafdda3862014-09-10 11:35:30 +0100608 if (HIWORD(lpProcName) == 0) {
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100609 debugPrintf("inject: %s %s(%u) from %s\n", szAction, "GetProcAddress", LOWORD(lpProcName), szCaller);
José Fonsecafdda3862014-09-10 11:35:30 +0100610 } else {
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100611 debugPrintf("inject: %s %s(\"%s\") from %s\n", szAction, "GetProcAddress", lpProcName, szCaller);
José Fonsecafdda3862014-09-10 11:35:30 +0100612 }
613}
614
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100615static HMODULE
616GetModuleFromAddress(PVOID pAddress)
617{
618 HMODULE hModule = nullptr;
619 BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
620 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
621 (LPCTSTR)pAddress,
622 &hModule);
623 return bRet ? hModule : nullptr;
624}
625
626
José Fonsecabd4937e2012-12-04 13:23:03 +0000627static FARPROC WINAPI
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100628MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
629{
630 FARPROC lpProcAddress = RealGetProcAddress(hModule, lpProcName);
631 LPCSTR szAction = "ignoring";
José Fonsecabd4937e2012-12-04 13:23:03 +0000632
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100633 void *pCallerAddr = ReturnAddress();
634 HMODULE hCallerModule = GetModuleFromAddress(pCallerAddr);
José Fonsecabd4937e2012-12-04 13:23:03 +0000635
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100636 if (lpProcAddress) {
637 if (hCallerModule == g_hThisModule ||
638 hCallerModule == g_hHookModule) {
José Fonsecabd4937e2012-12-04 13:23:03 +0000639
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100640 assert(HIWORD(lpProcName) != 0);
641
642 if (hCallerModule == g_hHookModule) {
643 EnterCriticalSection(&g_Mutex);
644 auto search = g_pRealFunctions.find((PVOID)lpProcAddress);
645 if (search != g_pRealFunctions.end()) {
646 szAction = "overriding";
647 lpProcAddress = (FARPROC)search->second;
648 }
649 LeaveCriticalSection(&g_Mutex);
José Fonsecafdda3862014-09-10 11:35:30 +0100650 }
651
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100652 // Check for recursion
653 HMODULE hResultModule = GetModuleFromAddress((PVOID)lpProcAddress);
654 if (hResultModule == g_hThisModule ||
655 hResultModule == g_hHookModule) {
656 debugPrintf("inject: error: recursion in GetProcAddress(\"%s\")\n", lpProcName);
657 TerminateProcess(GetCurrentProcess(), 1);
José Fonsecabd4937e2012-12-04 13:23:03 +0000658 }
659 }
660 }
José Fonsecabd4937e2012-12-04 13:23:03 +0000661
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100662 if (VERBOSITY >= 3) {
663 /* XXX this can cause segmentation faults */
664 logGetProcAddress(szAction, hModule, lpProcName, hCallerModule);
665 }
666
667 return lpProcAddress;
José Fonsecabd4937e2012-12-04 13:23:03 +0000668}
669
670
José Fonseca16736092015-02-07 23:16:58 +0000671static BOOL WINAPI
672MyFreeLibrary(HMODULE hModule)
673{
674 if (VERBOSITY >= 2) {
675 debugPrintf("inject: intercepting %s(0x%p)\n", __FUNCTION__, hModule);
676 }
677
Jose Fonseca8a154262016-09-19 22:35:44 +0100678 BOOL bRet = RealFreeLibrary(hModule);
Jose Fonseca953907a2015-06-26 10:50:16 +0100679 DWORD dwLastError = GetLastError();
José Fonseca16736092015-02-07 23:16:58 +0000680
Jose Fonsecae7daf652016-09-05 11:31:51 +0100681 std::set<HMODULE> hCurrentModules;
682 HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
683 if (hModuleSnap != INVALID_HANDLE_VALUE) {
684 MODULEENTRY32 me32;
685 me32.dwSize = sizeof me32;
686 if (Module32First(hModuleSnap, &me32)) {
687 do {
688 hCurrentModules.insert(me32.hModule);
689 } while (Module32Next(hModuleSnap, &me32));
690 }
691 CloseHandle(hModuleSnap);
692 }
693
694 // Clear the modules that have been freed
Jose Fonseca94bbf782015-11-16 15:02:00 +0000695 EnterCriticalSection(&g_Mutex);
Jose Fonsecae7daf652016-09-05 11:31:51 +0100696 std::set<HMODULE> hIntersectedModules;
697 std::set_intersection(g_hHookedModules.begin(), g_hHookedModules.end(),
698 hCurrentModules.begin(), hCurrentModules.end(),
699 std::inserter(hIntersectedModules, hIntersectedModules.begin()));
700 g_hHookedModules = std::move(hIntersectedModules);
Jose Fonseca94bbf782015-11-16 15:02:00 +0000701 LeaveCriticalSection(&g_Mutex);
José Fonseca16736092015-02-07 23:16:58 +0000702
Jose Fonseca953907a2015-06-26 10:50:16 +0100703 SetLastError(dwLastError);
José Fonseca16736092015-02-07 23:16:58 +0000704 return bRet;
705}
706
707
José Fonseca5e6332c2014-09-03 14:34:44 +0100708static void
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100709setHooks(void)
José Fonseca5e6332c2014-09-03 14:34:44 +0100710{
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100711 HMODULE hKernel32 = GetModuleHandleA("kernel32");
712 assert(hKernel32);
713
Jose Fonseca35fb4652016-09-19 20:26:29 +0100714# define SET_HOOK(_name) \
715 Real##_name = reinterpret_cast<decltype(Real##_name)>(RealGetProcAddress(hKernel32, #_name)); \
716 assert(Real##_name); \
717 assert(Real##_name != My##_name); \
718 if (!Mhook_SetHook((PVOID*)&Real##_name, (PVOID)My##_name)) { \
719 debugPrintf("inject: error: failed to hook " #_name "\n"); \
720 }
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100721
Jose Fonseca8a154262016-09-19 22:35:44 +0100722 SET_HOOK(LoadLibraryA)
723 SET_HOOK(LoadLibraryW)
724 SET_HOOK(LoadLibraryExA)
725 SET_HOOK(LoadLibraryExW)
726 SET_HOOK(FreeLibrary)
Jose Fonseca35fb4652016-09-19 20:26:29 +0100727 SET_HOOK(GetProcAddress)
728 SET_HOOK(CreateProcessA)
729 SET_HOOK(CreateProcessW)
730 SET_HOOK(CreateProcessAsUserW)
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100731
Jose Fonseca35fb4652016-09-19 20:26:29 +0100732# undef SET_HOOK
José Fonseca5e6332c2014-09-03 14:34:44 +0100733}
734
José Fonseca5e6332c2014-09-03 14:34:44 +0100735
José Fonsecabd4937e2012-12-04 13:23:03 +0000736EXTERN_C BOOL WINAPI
Jose Fonsecab57679e2015-07-15 15:24:05 +0100737DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
José Fonsecabd4937e2012-12-04 13:23:03 +0000738{
739 const char *szNewDllName = NULL;
José Fonsecabd4937e2012-12-04 13:23:03 +0000740
741 switch (fdwReason) {
742 case DLL_PROCESS_ATTACH:
Jose Fonseca94bbf782015-11-16 15:02:00 +0000743 InitializeCriticalSection(&g_Mutex);
Jose Fonseca482c17d2015-11-16 14:34:42 +0000744
José Fonsecabd4937e2012-12-04 13:23:03 +0000745 g_hThisModule = hinstDLL;
746
José Fonsecabd4937e2012-12-04 13:23:03 +0000747 /*
748 * Calling LoadLibrary inside DllMain is strongly discouraged. But it
749 * works quite well, provided that the loaded DLL does not require or do
750 * anything special in its DllMain, which seems to be the general case.
751 *
752 * See also:
753 * - http://stackoverflow.com/questions/4370812/calling-loadlibrary-from-dllmain
754 * - http://msdn.microsoft.com/en-us/library/ms682583
755 */
756
Jose Fonseca1f2a2c52014-06-18 15:10:11 +0100757 if (!USE_SHARED_MEM) {
758 szNewDllName = getenv("INJECT_DLL");
759 if (!szNewDllName) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100760 debugPrintf("inject: warning: INJECT_DLL not set\n");
Jose Fonseca1f2a2c52014-06-18 15:10:11 +0100761 return FALSE;
762 }
763 } else {
Jose Fonseca498710d2015-07-15 16:07:05 +0100764 SharedMem *pSharedMem = OpenSharedMemory(NULL);
Jose Fonseca0eb4fe72015-07-06 16:16:13 +0100765 if (!pSharedMem) {
766 debugPrintf("inject: error: failed to open shared memory\n");
767 return FALSE;
768 }
769
Jose Fonseca59f21c42015-07-06 16:41:55 +0100770 VERBOSITY = pSharedMem->cVerbosity;
771
Jose Fonseca1f2a2c52014-06-18 15:10:11 +0100772 static char szSharedMemCopy[MAX_PATH];
Jose Fonseca0eb4fe72015-07-06 16:16:13 +0100773 strncpy(szSharedMemCopy, pSharedMem->szDllName, _countof(szSharedMemCopy) - 1);
774 szSharedMemCopy[_countof(szSharedMemCopy) - 1] = '\0';
775
Jose Fonseca1f2a2c52014-06-18 15:10:11 +0100776 szNewDllName = szSharedMemCopy;
José Fonsecabd4937e2012-12-04 13:23:03 +0000777 }
Jose Fonseca1f2a2c52014-06-18 15:10:11 +0100778
José Fonseca1a617aa2013-02-22 09:41:54 +0000779 if (VERBOSITY > 0) {
Jose Fonseca42b31cf2015-07-13 12:01:45 +0100780 debugPrintf("inject: DLL_PROCESS_ATTACH\n");
781 }
782
783 if (VERBOSITY > 0) {
784 char szProcess[MAX_PATH];
785 GetModuleFileNameA(NULL, szProcess, sizeof szProcess);
786 debugPrintf("inject: attached to process %s\n", szProcess);
787 }
788
789 if (VERBOSITY > 0) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100790 debugPrintf("inject: loading %s\n", szNewDllName);
José Fonseca1a617aa2013-02-22 09:41:54 +0000791 }
José Fonsecabd4937e2012-12-04 13:23:03 +0000792
José Fonseca5e6332c2014-09-03 14:34:44 +0100793 g_hHookModule = LoadLibraryA(szNewDllName);
794 if (!g_hHookModule) {
795 debugPrintf("inject: warning: failed to load %s\n", szNewDllName);
José Fonsecabd4937e2012-12-04 13:23:03 +0000796 return FALSE;
797 }
798
José Fonseca3e60c242014-09-26 19:44:29 +0100799 patchAllModules(ACTION_HOOK);
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100800
Jose Fonseca1706ffd2016-09-18 20:39:11 +0100801 setHooks();
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100802
José Fonsecabd4937e2012-12-04 13:23:03 +0000803 break;
804
805 case DLL_THREAD_ATTACH:
806 break;
807
808 case DLL_THREAD_DETACH:
809 break;
810
811 case DLL_PROCESS_DETACH:
José Fonseca1a617aa2013-02-22 09:41:54 +0000812 if (VERBOSITY > 0) {
José Fonseca5e6332c2014-09-03 14:34:44 +0100813 debugPrintf("inject: DLL_PROCESS_DETACH\n");
José Fonseca1a617aa2013-02-22 09:41:54 +0000814 }
José Fonseca3e60c242014-09-26 19:44:29 +0100815
Jose Fonsecab57679e2015-07-15 15:24:05 +0100816 assert(!lpvReserved);
817
José Fonseca3e60c242014-09-26 19:44:29 +0100818 patchAllModules(ACTION_UNHOOK);
819
820 if (g_hHookModule) {
821 FreeLibrary(g_hHookModule);
822 }
Jose Fonsecaff5a5852016-09-07 16:06:09 +0100823
824 Mhook_Unhook((PVOID*)&RealGetProcAddress);
825
José Fonsecabd4937e2012-12-04 13:23:03 +0000826 break;
827 }
828 return TRUE;
829}
Jose Fonsecab57679e2015-07-15 15:24:05 +0100830
831
832/*
833 * Prevent the C/C++ runtime from destroying things when the program
834 * terminates.
835 *
836 * There is no effective way to control the order DLLs receive
837 * DLL_PROCESS_DETACH -- patched DLLs might get detacched after we are --, and
838 * unpatching our hooks doesn't always work. So instead just do nothing (and
839 * prevent C/C++ runtime from doing anything too), so our hooks can still work
840 * after we are dettached.
841 */
842
843#ifdef _MSC_VER
844# define DLLMAIN_CRT_STARTUP _DllMainCRTStartup
845#else
846# define DLLMAIN_CRT_STARTUP DllMainCRTStartup
847# pragma GCC optimize ("no-stack-protector")
848#endif
849
850EXTERN_C BOOL WINAPI
851DLLMAIN_CRT_STARTUP(HANDLE hDllHandle, DWORD dwReason, LPVOID lpvReserved);
852
853EXTERN_C BOOL WINAPI
854DllMainStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpvReserved)
855{
856 if (dwReason == DLL_PROCESS_DETACH && lpvReserved) {
857 if (VERBOSITY > 0) {
858 debugPrintf("inject: DLL_PROCESS_DETACH\n");
859 }
860 return TRUE;
861 }
862
863 return DLLMAIN_CRT_STARTUP(hDllHandle, dwReason, lpvReserved);
864}