CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/byakugan/detours/creatwth.cpp
Views: 11779
1
//////////////////////////////////////////////////////////////////////////////
2
//
3
// Create a process with a DLL (creatwth.cpp of detours.lib)
4
//
5
// Microsoft Research Detours Package, Version 2.1.
6
//
7
// Copyright (c) Microsoft Corporation. All rights reserved.
8
//
9
10
#include <windows.h>
11
#include <stddef.h>
12
#if (_MSC_VER < 1299)
13
typedef DWORD DWORD_PTR;
14
#endif
15
#if (_MSC_VER < 1310)
16
#else
17
#include <strsafe.h>
18
#endif
19
20
//#define DETOUR_DEBUG 1
21
#define DETOURS_INTERNAL
22
23
#include "detours.h"
24
25
#define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
26
#define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]
27
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
28
#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
29
30
//////////////////////////////////////////////////////////////////////////////
31
//
32
#ifndef _STRSAFE_H_INCLUDED_
33
static inline HRESULT StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
34
{
35
HRESULT hr = S_OK;
36
size_t cchMaxPrev = cchMax;
37
38
if (cchMax > 2147483647)
39
{
40
return ERROR_INVALID_PARAMETER;
41
}
42
43
while (cchMax && (*psz != '\0'))
44
{
45
psz++;
46
cchMax--;
47
}
48
49
if (cchMax == 0)
50
{
51
// the string is longer than cchMax
52
hr = ERROR_INVALID_PARAMETER;
53
}
54
55
if (SUCCEEDED(hr) && pcch)
56
{
57
*pcch = cchMaxPrev - cchMax;
58
}
59
60
return hr;
61
}
62
63
64
static inline HRESULT StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
65
{
66
HRESULT hr = S_OK;
67
68
if (cchDest == 0)
69
{
70
// can not null terminate a zero-byte dest buffer
71
hr = ERROR_INVALID_PARAMETER;
72
}
73
else
74
{
75
while (cchDest && (*pszSrc != '\0'))
76
{
77
*pszDest++ = *pszSrc++;
78
cchDest--;
79
}
80
81
if (cchDest == 0)
82
{
83
// we are going to truncate pszDest
84
pszDest--;
85
hr = ERROR_INVALID_PARAMETER;
86
}
87
88
*pszDest= '\0';
89
}
90
91
return hr;
92
}
93
94
static inline HRESULT StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
95
{
96
HRESULT hr;
97
size_t cchDestCurrent;
98
99
if (cchDest > 2147483647)
100
{
101
return ERROR_INVALID_PARAMETER;
102
}
103
104
hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent);
105
106
if (SUCCEEDED(hr))
107
{
108
hr = StringCchCopyA(pszDest + cchDestCurrent,
109
cchDest - cchDestCurrent,
110
pszSrc);
111
}
112
113
return hr;
114
}
115
116
#endif
117
118
//////////////////////////////////////////////////////////////////////////////
119
//
120
static WORD detour_sum_minus(WORD wSum, WORD wMinus)
121
{
122
wSum = (WORD)(wSum - ((wSum < wMinus) ? 1 : 0));
123
wSum = (WORD)(wSum - wMinus);
124
return wSum;
125
}
126
127
static WORD detour_sum_done(DWORD PartialSum)
128
{
129
// Fold final carry into a single word result and return the resultant value.
130
return (WORD)(((PartialSum >> 16) + PartialSum) & 0xffff);
131
}
132
133
static WORD detour_sum_data(DWORD dwSum, PBYTE pbData, DWORD cbData)
134
{
135
while (cbData > 0) {
136
dwSum += *((PWORD&)pbData)++;
137
dwSum = (dwSum >> 16) + (dwSum & 0xffff);
138
cbData -= sizeof(WORD);
139
}
140
return detour_sum_done(dwSum);
141
}
142
143
static WORD detour_sum_final(WORD wSum, PIMAGE_NT_HEADERS pinh)
144
{
145
DETOUR_TRACE((".... : %08x (value: %08x)\n", wSum, pinh->OptionalHeader.CheckSum));
146
147
// Subtract the two checksum words in the optional header from the computed.
148
wSum = detour_sum_minus(wSum, ((PWORD)(&pinh->OptionalHeader.CheckSum))[0]);
149
wSum = detour_sum_minus(wSum, ((PWORD)(&pinh->OptionalHeader.CheckSum))[1]);
150
151
return wSum;
152
}
153
154
static WORD ChkSumRange(WORD wSum, HANDLE hProcess, PBYTE pbBeg, PBYTE pbEnd)
155
{
156
BYTE rbPage[4096];
157
158
while (pbBeg < pbEnd) {
159
if (!ReadProcessMemory(hProcess, pbBeg, rbPage, sizeof(rbPage), NULL)) {
160
DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
161
break;
162
}
163
wSum = detour_sum_data(wSum, rbPage, sizeof(rbPage));
164
pbBeg += sizeof(rbPage);
165
}
166
return wSum;
167
}
168
169
static WORD ComputeChkSum(HANDLE hProcess, PBYTE pbModule, PIMAGE_NT_HEADERS pinh)
170
{
171
// See LdrVerifyMappedImageMatchesChecksum.
172
173
MEMORY_BASIC_INFORMATION mbi;
174
ZeroMemory(&mbi, sizeof(mbi));
175
WORD wSum = 0;
176
177
for (PBYTE pbLast = pbModule;;
178
pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
179
180
if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
181
if (GetLastError() == ERROR_INVALID_PARAMETER) {
182
break;
183
}
184
DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
185
pbLast, GetLastError()));
186
break;
187
}
188
189
if (mbi.AllocationBase != pbModule) {
190
break;
191
}
192
193
wSum = ChkSumRange(wSum,
194
hProcess,
195
(PBYTE)mbi.BaseAddress,
196
(PBYTE)mbi.BaseAddress + mbi.RegionSize);
197
198
DETOUR_TRACE(("[%8p..%8p] : %04x\n",
199
(PBYTE)mbi.BaseAddress,
200
(PBYTE)mbi.BaseAddress + mbi.RegionSize,
201
wSum));
202
}
203
204
return detour_sum_final(wSum, pinh);
205
}
206
207
//////////////////////////////////////////////////////////////////////////////
208
//
209
// Find a region of memory in which we can create a replacement import table.
210
//
211
static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbBase, DWORD cbAlloc)
212
{
213
MEMORY_BASIC_INFORMATION mbi;
214
ZeroMemory(&mbi, sizeof(mbi));
215
216
for (PBYTE pbLast = pbBase;;
217
pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
218
219
if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
220
if (GetLastError() == ERROR_INVALID_PARAMETER) {
221
break;
222
}
223
DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
224
pbLast, GetLastError()));
225
break;
226
}
227
228
// Skip uncommitted regions and guard pages.
229
//
230
if ((mbi.State != MEM_FREE)) {
231
continue;
232
}
233
234
PBYTE pbAddress = (PBYTE)(((DWORD_PTR)mbi.BaseAddress + 0xffff) & ~(DWORD_PTR)0xffff);
235
236
DETOUR_TRACE(("Free region %p..%p\n",
237
mbi.BaseAddress,
238
(PBYTE)mbi.BaseAddress + mbi.RegionSize));
239
240
for (; pbAddress < (PBYTE)mbi.BaseAddress + mbi.RegionSize; pbAddress += 0x10000) {
241
PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
242
MEM_RESERVE, PAGE_READWRITE);
243
if (pbAlloc == NULL) {
244
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
245
continue;
246
}
247
pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
248
MEM_COMMIT, PAGE_READWRITE);
249
if (pbAlloc == NULL) {
250
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
251
continue;
252
}
253
DETOUR_TRACE(("[%p..%p] Allocated for import table.\n",
254
pbAlloc, pbAlloc + cbAlloc));
255
return pbAlloc;
256
}
257
}
258
return NULL;
259
}
260
261
static inline DWORD PadToDword(DWORD dw)
262
{
263
return (dw + 3) & ~3u;
264
}
265
266
static inline DWORD PadToDwordPtr(DWORD dw)
267
{
268
return (dw + 7) & ~7u;
269
}
270
271
static BOOL IsExe(HANDLE hProcess, PBYTE pbModule)
272
{
273
IMAGE_DOS_HEADER idh;
274
ZeroMemory(&idh, sizeof(idh));
275
276
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
277
DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
278
return FALSE;
279
}
280
281
if (idh.e_magic != IMAGE_DOS_SIGNATURE) {
282
// DETOUR_TRACE((" No IMAGE_DOS_SIGNATURE\n"));
283
return FALSE;
284
}
285
286
IMAGE_NT_HEADERS inh;
287
ZeroMemory(&inh, sizeof(inh));
288
289
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
290
DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
291
return FALSE;
292
}
293
294
if (inh.Signature != IMAGE_NT_SIGNATURE) {
295
DETOUR_TRACE((" No IMAGE_NT_SIGNATURE\n"));
296
return FALSE;
297
}
298
299
if (inh.FileHeader.Characteristics & IMAGE_FILE_DLL) {
300
DETOUR_TRACE((" Characteristics: %08x\n", inh.FileHeader.Characteristics));
301
return FALSE;
302
}
303
304
return TRUE;
305
}
306
307
PVOID FindExe(HANDLE hProcess)
308
{
309
MEMORY_BASIC_INFORMATION mbi;
310
ZeroMemory(&mbi, sizeof(mbi));
311
312
// Find the next memory region that contains a mapped PE image.
313
//
314
for (PBYTE pbLast = (PBYTE)0x10000;;
315
pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
316
317
if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
318
if (GetLastError() == ERROR_INVALID_PARAMETER) {
319
break;
320
}
321
DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
322
pbLast, GetLastError()));
323
break;
324
}
325
326
// Skip uncommitted regions and guard pages.
327
//
328
if ((mbi.State != MEM_COMMIT) || (mbi.Protect & PAGE_GUARD)) {
329
continue;
330
}
331
332
DETOUR_TRACE(("%8p..%8p [%8p]\n",
333
mbi.BaseAddress,
334
(PBYTE)mbi.BaseAddress + mbi.RegionSize,
335
mbi.AllocationBase));
336
337
if (IsExe(hProcess, pbLast)) {
338
#if DETOUR_DEBUG
339
for (PBYTE pbNext = (PBYTE)mbi.BaseAddress + mbi.RegionSize;;
340
pbNext = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
341
342
if (VirtualQueryEx(hProcess, (PVOID)pbNext, &mbi, sizeof(mbi)) <= 0) {
343
if (GetLastError() == ERROR_INVALID_PARAMETER) {
344
break;
345
}
346
DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
347
pbNext, GetLastError()));
348
break;
349
}
350
351
// Skip uncommitted regions and guard pages.
352
//
353
if ((mbi.State != MEM_COMMIT) || (mbi.Protect & PAGE_GUARD)) {
354
continue;
355
}
356
DETOUR_TRACE(("%8p..%8p [%8p]\n",
357
mbi.BaseAddress,
358
(PBYTE)mbi.BaseAddress + mbi.RegionSize,
359
mbi.AllocationBase));
360
361
IsExe(hProcess, pbNext);
362
}
363
#endif
364
return pbLast;
365
}
366
}
367
return NULL;
368
}
369
370
static BOOL UpdateImports(HANDLE hProcess, LPCSTR *plpDlls, DWORD nDlls)
371
{
372
BOOL fSucceeded = FALSE;
373
BYTE * pbNew = NULL;
374
DETOUR_EXE_RESTORE der;
375
DWORD i;
376
377
ZeroMemory(&der, sizeof(der));
378
der.cb = sizeof(der);
379
380
PBYTE pbModule = (PBYTE)FindExe(hProcess);
381
382
IMAGE_DOS_HEADER idh;
383
ZeroMemory(&idh, sizeof(idh));
384
385
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
386
DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
387
388
finish:
389
if (pbNew != NULL) {
390
delete[] pbNew;
391
pbNew = NULL;
392
}
393
return fSucceeded;
394
}
395
CopyMemory(&der.idh, &idh, sizeof(idh));
396
der.pidh = (PIMAGE_DOS_HEADER)pbModule;
397
398
if (idh.e_magic != IMAGE_DOS_SIGNATURE) {
399
goto finish;
400
}
401
402
IMAGE_NT_HEADERS inh;
403
ZeroMemory(&inh, sizeof(inh));
404
405
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
406
DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
407
goto finish;
408
}
409
CopyMemory(&der.inh, &inh, sizeof(inh));
410
der.pinh = (PIMAGE_NT_HEADERS)(pbModule + idh.e_lfanew);
411
412
if (inh.Signature != IMAGE_NT_SIGNATURE) {
413
goto finish;
414
}
415
416
if (inh.IMPORT_DIRECTORY.VirtualAddress == 0) {
417
DETOUR_TRACE(("No IMAGE_DIRECTORY_ENTRY_IMPORT\n"));
418
goto finish;
419
}
420
421
// Zero out the bound table so loader doesn't use it instead of our new table.
422
inh.BOUND_DIRECTORY.VirtualAddress = 0;
423
inh.BOUND_DIRECTORY.Size = 0;
424
425
// Find the size of the mapped file.
426
DWORD dwFileSize = 0;
427
DWORD dwSec = idh.e_lfanew +
428
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) +
429
inh.FileHeader.SizeOfOptionalHeader;
430
431
for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
432
IMAGE_SECTION_HEADER ish;
433
ZeroMemory(&ish, sizeof(ish));
434
435
if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
436
sizeof(ish), NULL)) {
437
DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
438
goto finish;
439
}
440
441
DETOUR_TRACE(("ish[%d] : va=%p sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData));
442
443
// If the file didn't have an IAT_DIRECTORY, we create one...
444
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
445
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
446
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
447
448
inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
449
inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
450
}
451
452
// Find the end of the file...
453
if (dwFileSize < ish.PointerToRawData + ish.SizeOfRawData) {
454
dwFileSize = ish.PointerToRawData + ish.SizeOfRawData;
455
}
456
}
457
DETOUR_TRACE(("dwFileSize = %08x\n", dwFileSize));
458
459
// Find the current checksum.
460
WORD wBefore = ComputeChkSum(hProcess, pbModule, &inh);
461
DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wBefore, dwFileSize, wBefore + dwFileSize));
462
463
DETOUR_TRACE((" Imports: %8p..%8p\n",
464
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
465
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
466
inh.IMPORT_DIRECTORY.Size));
467
468
DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
469
DWORD obTab = PadToDwordPtr(obRem + inh.IMPORT_DIRECTORY.Size);
470
DWORD obDll = obTab + sizeof(DWORD_PTR) * 4 * nDlls;
471
DWORD obStr = obDll;
472
DWORD cbNew = obStr;
473
DWORD n;
474
for (n = 0; n < nDlls; n++) {
475
cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
476
}
477
478
pbNew = new BYTE [cbNew];
479
if (pbNew == NULL) {
480
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
481
goto finish;
482
}
483
ZeroMemory(pbNew, cbNew);
484
485
PBYTE pbBase = pbModule;
486
PBYTE pbNext = pbBase
487
+ inh.OptionalHeader.BaseOfCode
488
+ inh.OptionalHeader.SizeOfCode
489
+ inh.OptionalHeader.SizeOfInitializedData
490
+ inh.OptionalHeader.SizeOfUninitializedData;
491
if (pbBase < pbNext) {
492
pbBase = pbNext;
493
}
494
DETOUR_TRACE(("pbBase = %p\n", pbBase));
495
496
PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbBase, cbNew);
497
if (pbNewIid == NULL) {
498
DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
499
goto finish;
500
}
501
502
DWORD dwProtect = 0;
503
der.impDirProt = 0;
504
if (!VirtualProtectEx(hProcess,
505
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
506
inh.IMPORT_DIRECTORY.Size, PAGE_EXECUTE_READWRITE, &dwProtect)) {
507
DETOUR_TRACE(("VirtualProtextEx(import) write failed: %d\n", GetLastError()));
508
goto finish;
509
}
510
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect));
511
der.impDirProt = dwProtect;
512
513
DWORD obBase = (DWORD)(pbNewIid - pbModule);
514
515
if (!ReadProcessMemory(hProcess,
516
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
517
pbNew + obRem,
518
inh.IMPORT_DIRECTORY.Size, NULL)) {
519
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError()));
520
goto finish;
521
}
522
523
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
524
DWORD_PTR *pt;
525
526
for (n = 0; n < nDlls; n++) {
527
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
528
if (FAILED(hrRet))
529
{
530
DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError()));
531
goto finish;
532
}
533
534
DWORD nOffset = obTab + (sizeof(DWORD_PTR) * (4 * n));
535
piid[n].OriginalFirstThunk = obBase + nOffset;
536
pt = ((DWORD_PTR*)(pbNew + nOffset));
537
pt[0] = IMAGE_ORDINAL_FLAG + 1;
538
pt[1] = 0;
539
540
nOffset = obTab + (sizeof(DWORD_PTR) * ((4 * n) + 2));
541
piid[n].FirstThunk = obBase + nOffset;
542
pt = ((DWORD_PTR*)(pbNew + nOffset));
543
pt[0] = IMAGE_ORDINAL_FLAG + 1;
544
pt[1] = 0;
545
piid[n].TimeDateStamp = 0;
546
piid[n].ForwarderChain = 0;
547
piid[n].Name = obBase + obStr;
548
549
obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
550
}
551
552
for (i = 0; i < nDlls + (inh.IMPORT_DIRECTORY.Size / sizeof(*piid)); i++) {
553
DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
554
i,
555
piid[i].OriginalFirstThunk,
556
piid[i].TimeDateStamp,
557
piid[i].ForwarderChain,
558
piid[i].Name,
559
piid[i].FirstThunk));
560
if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
561
break;
562
}
563
}
564
565
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
566
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError()));
567
goto finish;
568
}
569
570
DETOUR_TRACE(("obBase = %p..%p\n",
571
inh.IMPORT_DIRECTORY.VirtualAddress,
572
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
573
DETOUR_TRACE(("obBase = %p..%p\n", obBase, obBase + obStr));
574
575
inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
576
inh.IMPORT_DIRECTORY.Size = cbNew;
577
578
/////////////////////////////////////////////////// Update the CLR header.
579
//
580
if (inh.CLR_DIRECTORY.VirtualAddress != 0 &&
581
inh.CLR_DIRECTORY.Size != 0) {
582
583
DETOUR_CLR_HEADER clr;
584
PBYTE pbClr = pbModule + inh.CLR_DIRECTORY.VirtualAddress;
585
586
if (!ReadProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) {
587
DETOUR_TRACE(("ReadProcessMemory(clr) failed: %d\n", GetLastError()));
588
goto finish;
589
}
590
591
der.pclrFlags = (PULONG)(pbClr + offsetof(DETOUR_CLR_HEADER, Flags));
592
der.clrFlags = clr.Flags;
593
594
clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
595
596
if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
597
DETOUR_TRACE(("VirtualProtextEx(clr) write failed: %d\n", GetLastError()));
598
goto finish;
599
}
600
601
if (!WriteProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) {
602
DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError()));
603
goto finish;
604
}
605
606
if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), dwProtect, &dwProtect)) {
607
DETOUR_TRACE(("VirtualProtextEx(clr) restore failed: %d\n", GetLastError()));
608
goto finish;
609
}
610
}
611
612
/////////////////////// Update the NT header for the import new directory.
613
/////////////////////////////// Update the DOS header to fix the checksum.
614
//
615
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
616
PAGE_EXECUTE_READWRITE, &dwProtect)) {
617
DETOUR_TRACE(("VirtualProtextEx(inh) write failed: %d\n", GetLastError()));
618
goto finish;
619
}
620
621
idh.e_res[0] = 0;
622
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
623
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
624
goto finish;
625
}
626
627
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
628
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError()));
629
goto finish;
630
}
631
632
WORD wDuring = ComputeChkSum(hProcess, pbModule, &inh);
633
DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wDuring, dwFileSize, wDuring + dwFileSize));
634
635
idh.e_res[0] = detour_sum_minus(idh.e_res[0], detour_sum_minus(wDuring, wBefore));
636
637
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
638
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
639
goto finish;
640
}
641
642
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
643
dwProtect, &dwProtect)) {
644
DETOUR_TRACE(("VirtualProtextEx(idh) restore failed: %d\n", GetLastError()));
645
goto finish;
646
}
647
648
WORD wAfter = ComputeChkSum(hProcess, pbModule, &inh);
649
DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wAfter, dwFileSize, wAfter + dwFileSize));
650
DETOUR_TRACE(("Before: %08x, After: %08x\n", wBefore + dwFileSize, wAfter + dwFileSize));
651
652
if (wBefore != wAfter) {
653
DETOUR_TRACE(("Restore of checksum failed %04x != %04x.\n", wBefore, wAfter));
654
goto finish;
655
}
656
657
if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
658
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
659
goto finish;
660
}
661
662
fSucceeded = TRUE;
663
goto finish;
664
}
665
666
//////////////////////////////////////////////////////////////////////////////
667
//
668
BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName,
669
__in_z LPSTR lpCommandLine,
670
LPSECURITY_ATTRIBUTES lpProcessAttributes,
671
LPSECURITY_ATTRIBUTES lpThreadAttributes,
672
BOOL bInheritHandles,
673
DWORD dwCreationFlags,
674
LPVOID lpEnvironment,
675
LPCSTR lpCurrentDirectory,
676
LPSTARTUPINFOA lpStartupInfo,
677
LPPROCESS_INFORMATION lpProcessInformation,
678
LPCSTR lpDetouredDllFullName,
679
LPCSTR lpDllName,
680
PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA)
681
{
682
DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED);
683
PROCESS_INFORMATION pi;
684
685
if (pfCreateProcessA == NULL) {
686
pfCreateProcessA = CreateProcessA;
687
}
688
689
if (!pfCreateProcessA(lpApplicationName,
690
lpCommandLine,
691
lpProcessAttributes,
692
lpThreadAttributes,
693
bInheritHandles,
694
dwMyCreationFlags,
695
lpEnvironment,
696
lpCurrentDirectory,
697
lpStartupInfo,
698
&pi)) {
699
return FALSE;
700
}
701
702
LPCSTR rlpDlls[2];
703
DWORD nDlls = 0;
704
if (lpDetouredDllFullName != NULL) {
705
rlpDlls[nDlls++] = lpDetouredDllFullName;
706
}
707
if (lpDllName != NULL) {
708
rlpDlls[nDlls++] = lpDllName;
709
}
710
711
if (!UpdateImports(pi.hProcess, rlpDlls, nDlls)) {
712
return FALSE;
713
}
714
715
if (lpProcessInformation) {
716
CopyMemory(lpProcessInformation, &pi, sizeof(pi));
717
}
718
719
if (!(dwCreationFlags & CREATE_SUSPENDED)) {
720
ResumeThread(pi.hThread);
721
}
722
return TRUE;
723
}
724
725
726
BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName,
727
__in_z LPWSTR lpCommandLine,
728
LPSECURITY_ATTRIBUTES lpProcessAttributes,
729
LPSECURITY_ATTRIBUTES lpThreadAttributes,
730
BOOL bInheritHandles,
731
DWORD dwCreationFlags,
732
LPVOID lpEnvironment,
733
LPCWSTR lpCurrentDirectory,
734
LPSTARTUPINFOW lpStartupInfo,
735
LPPROCESS_INFORMATION lpProcessInformation,
736
LPCSTR lpDetouredDllFullName,
737
LPCSTR lpDllName,
738
PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW)
739
{
740
DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED);
741
PROCESS_INFORMATION pi;
742
743
if (pfCreateProcessW == NULL) {
744
pfCreateProcessW = CreateProcessW;
745
}
746
747
if (!pfCreateProcessW(lpApplicationName,
748
lpCommandLine,
749
lpProcessAttributes,
750
lpThreadAttributes,
751
bInheritHandles,
752
dwMyCreationFlags,
753
lpEnvironment,
754
lpCurrentDirectory,
755
lpStartupInfo,
756
&pi)) {
757
return FALSE;
758
}
759
760
LPCSTR rlpDlls[2];
761
DWORD nDlls = 0;
762
if (lpDetouredDllFullName != NULL) {
763
rlpDlls[nDlls++] = lpDetouredDllFullName;
764
}
765
if (lpDllName != NULL) {
766
rlpDlls[nDlls++] = lpDllName;
767
}
768
769
if (!UpdateImports(pi.hProcess, rlpDlls, nDlls)) {
770
return FALSE;
771
}
772
773
if (lpProcessInformation) {
774
CopyMemory(lpProcessInformation, &pi, sizeof(pi));
775
}
776
777
if (!(dwCreationFlags & CREATE_SUSPENDED)) {
778
ResumeThread(pi.hThread);
779
}
780
return TRUE;
781
}
782
783
BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess,
784
REFGUID rguid,
785
PVOID pData,
786
DWORD cbData)
787
{
788
DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
789
sizeof(IMAGE_NT_HEADERS) +
790
sizeof(IMAGE_SECTION_HEADER) +
791
sizeof(DETOUR_SECTION_HEADER) +
792
sizeof(DETOUR_SECTION_RECORD) +
793
cbData);
794
795
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
796
MEM_COMMIT, PAGE_READWRITE);
797
if (pbBase == NULL) {
798
DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError()));
799
return FALSE;
800
}
801
802
PBYTE pbTarget = pbBase;
803
IMAGE_DOS_HEADER idh;
804
IMAGE_NT_HEADERS inh;
805
IMAGE_SECTION_HEADER ish;
806
DETOUR_SECTION_HEADER dsh;
807
DETOUR_SECTION_RECORD dsr;
808
SIZE_T cbWrote = 0;
809
810
ZeroMemory(&idh, sizeof(idh));
811
idh.e_magic = IMAGE_DOS_SIGNATURE;
812
idh.e_lfanew = sizeof(idh);
813
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
814
cbWrote != sizeof(idh)) {
815
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
816
return FALSE;
817
}
818
pbTarget += sizeof(idh);
819
820
ZeroMemory(&inh, sizeof(inh));
821
inh.Signature = IMAGE_NT_SIGNATURE;
822
inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader);
823
inh.FileHeader.Characteristics = IMAGE_FILE_DLL;
824
inh.FileHeader.NumberOfSections = 1;
825
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
826
cbWrote != sizeof(inh)) {
827
return FALSE;
828
}
829
pbTarget += sizeof(inh);
830
831
ZeroMemory(&ish, sizeof(ish));
832
memcpy(ish.Name, ".detour", sizeof(ish.Name));
833
ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase);
834
ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) +
835
sizeof(DETOUR_SECTION_RECORD) +
836
cbData);
837
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
838
cbWrote != sizeof(ish)) {
839
return FALSE;
840
}
841
pbTarget += sizeof(ish);
842
843
ZeroMemory(&dsh, sizeof(dsh));
844
dsh.cbHeaderSize = sizeof(dsh);
845
dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
846
dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER);
847
dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) +
848
sizeof(DETOUR_SECTION_RECORD) +
849
cbData);
850
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
851
cbWrote != sizeof(dsh)) {
852
return FALSE;
853
}
854
pbTarget += sizeof(dsh);
855
856
ZeroMemory(&dsr, sizeof(dsr));
857
dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD);
858
dsr.nReserved = 0;
859
dsr.guid = rguid;
860
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
861
cbWrote != sizeof(dsr)) {
862
return FALSE;
863
}
864
pbTarget += sizeof(dsr);
865
866
if (!WriteProcessMemory(hProcess, pbTarget, pData, cbData, &cbWrote) ||
867
cbWrote != cbData) {
868
return FALSE;
869
}
870
pbTarget += cbData;
871
872
DETOUR_TRACE(("Copied %d bytes into target process at %p\n",
873
cbTotal, pbTarget - cbTotal));
874
return TRUE;
875
}
876
877
//
878
///////////////////////////////////////////////////////////////// End of File.
879
880