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/image.cpp
Views: 11779
1
//////////////////////////////////////////////////////////////////////////////
2
//
3
// Image manipulation functions (image.cpp of detours.lib)
4
//
5
// Microsoft Research Detours Package, Version 2.1.
6
//
7
// Copyright (c) Microsoft Corporation. All rights reserved.
8
//
9
// Used for for payloads, byways, and imports.
10
//
11
12
#include <windows.h>
13
#if (_MSC_VER < 1310)
14
#else
15
#include <strsafe.h>
16
#endif
17
18
#if (_MSC_VER < 1299)
19
#pragma warning(disable: 4710)
20
#else
21
#endif
22
23
//#define DETOUR_DEBUG 1
24
#define DETOURS_INTERNAL
25
26
#include "detours.h"
27
28
namespace Detour
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
class CImageData
121
{
122
friend class CImage;
123
124
public:
125
CImageData(PBYTE pbData, DWORD cbData);
126
~CImageData();
127
128
PBYTE Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
129
PBYTE Find(REFGUID rguid, DWORD *pcbData);
130
PBYTE Set(REFGUID rguid, PBYTE pbData, DWORD cbData);
131
132
BOOL Delete(REFGUID rguid);
133
BOOL Purge();
134
135
BOOL IsEmpty() { return m_cbData == 0; }
136
BOOL IsValid();
137
138
protected:
139
BOOL SizeTo(DWORD cbData);
140
141
protected:
142
PBYTE m_pbData;
143
DWORD m_cbData;
144
DWORD m_cbAlloc;
145
};
146
147
class CImageImportFile
148
{
149
friend class CImage;
150
friend class CImageImportName;
151
152
public:
153
CImageImportFile();
154
~CImageImportFile();
155
156
public:
157
CImageImportFile * m_pNextFile;
158
BOOL m_fByway;
159
160
CImageImportName * m_pImportNames;
161
DWORD m_nImportNames;
162
163
DWORD m_rvaOriginalFirstThunk;
164
DWORD m_rvaFirstThunk;
165
166
DWORD m_nForwarderChain;
167
PCHAR m_pszOrig;
168
PCHAR m_pszName;
169
};
170
171
class CImageImportName
172
{
173
friend class CImage;
174
friend class CImageImportFile;
175
176
public:
177
CImageImportName();
178
~CImageImportName();
179
180
public:
181
WORD m_nHint;
182
ULONG m_nOrig;
183
ULONG m_nOrdinal;
184
PCHAR m_pszOrig;
185
PCHAR m_pszName;
186
};
187
188
class CImage
189
{
190
friend class CImageThunks;
191
friend class CImageChars;
192
friend class CImageImportFile;
193
friend class CImageImportName;
194
195
public:
196
CImage();
197
~CImage();
198
199
static CImage * IsValid(PDETOUR_BINARY pBinary);
200
201
public: // File Functions
202
BOOL Read(HANDLE hFile);
203
BOOL Write(HANDLE hFile);
204
BOOL Close();
205
206
public: // Manipulation Functions
207
PBYTE DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
208
PBYTE DataFind(REFGUID rguid, DWORD *pcbData);
209
PBYTE DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData);
210
BOOL DataDelete(REFGUID rguid);
211
BOOL DataPurge();
212
213
BOOL EditImports(PVOID pContext,
214
PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
215
PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
216
PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
217
PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback);
218
219
protected:
220
BOOL WriteFile(HANDLE hFile,
221
LPCVOID lpBuffer,
222
DWORD nNumberOfBytesToWrite,
223
LPDWORD lpNumberOfBytesWritten);
224
BOOL CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData);
225
BOOL ZeroFileData(HANDLE hFile, DWORD cbData);
226
BOOL AlignFileData(HANDLE hFile);
227
228
BOOL SizeOutputBuffer(DWORD cbData);
229
PBYTE AllocateOutput(DWORD cbData, DWORD *pnVirtAddr);
230
231
PVOID RvaToVa(ULONG_PTR nRva);
232
DWORD RvaToFileOffset(DWORD nRva);
233
234
DWORD FileAlign(DWORD nAddr);
235
DWORD SectionAlign(DWORD nAddr);
236
237
BOOL CheckImportsNeeded(DWORD *pnTables,
238
DWORD *pnThunks,
239
DWORD *pnChars);
240
241
CImageImportFile * NewByway(__in_z PCHAR pszName);
242
243
private:
244
DWORD m_dwValidSignature;
245
CImageData * m_pImageData; // Read & Write
246
247
HANDLE m_hMap; // Read & Write
248
PBYTE m_pMap; // Read & Write
249
250
DWORD m_nNextFileAddr; // Write
251
DWORD m_nNextVirtAddr; // Write
252
253
IMAGE_DOS_HEADER m_DosHeader; // Read & Write
254
IMAGE_NT_HEADERS m_NtHeader; // Read & Write
255
IMAGE_SECTION_HEADER m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
256
257
DWORD m_nPrePE;
258
DWORD m_cbPrePE;
259
DWORD m_cbPostPE;
260
261
DWORD m_nPeOffset;
262
DWORD m_nSectionsOffset;
263
DWORD m_nExtraOffset;
264
DWORD m_nFileSize;
265
266
DWORD m_nOutputVirtAddr;
267
DWORD m_nOutputVirtSize;
268
DWORD m_nOutputFileAddr;
269
270
PBYTE m_pbOutputBuffer;
271
DWORD m_cbOutputBuffer;
272
273
CImageImportFile * m_pImportFiles;
274
DWORD m_nImportFiles;
275
276
BOOL m_fHadDetourSection;
277
278
private:
279
enum {
280
DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01, // "Dtr\0"
281
};
282
};
283
284
//////////////////////////////////////////////////////////////////////////////
285
//
286
static BYTE s_rbDosCode[0x10] = {
287
0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,
288
0x21,0xB8,0x01,0x4C,0xCD,0x21,'*','*'
289
};
290
291
static inline DWORD Max(DWORD a, DWORD b)
292
{
293
return a > b ? a : b;
294
}
295
296
static inline DWORD Align(DWORD a, DWORD size)
297
{
298
size--;
299
return (a + size) & ~size;
300
}
301
302
static inline DWORD QuadAlign(DWORD a)
303
{
304
return Align(a, 8);
305
}
306
307
static PCHAR DuplicateString(__in_z PCHAR pszIn)
308
{
309
if (pszIn) {
310
UINT nIn = (UINT)strlen(pszIn);
311
PCHAR pszOut = new CHAR [nIn + 1];
312
if (pszOut == NULL) {
313
SetLastError(ERROR_OUTOFMEMORY);
314
}
315
else {
316
CopyMemory(pszOut, pszIn, nIn + 1);
317
}
318
return pszOut;
319
}
320
return NULL;
321
}
322
323
static PCHAR ReplaceString(__deref_out PCHAR *ppsz, __in_z PCHAR pszIn)
324
{
325
if (ppsz == NULL) {
326
return NULL;
327
}
328
329
UINT nIn;
330
if (*ppsz != NULL) {
331
if (strcmp(*ppsz, pszIn) == 0) {
332
return *ppsz;
333
}
334
nIn = (UINT)strlen(pszIn);
335
336
if (strlen(*ppsz) == nIn) {
337
CopyMemory(*ppsz, pszIn, nIn + 1);
338
return *ppsz;
339
}
340
else {
341
delete[] *ppsz;
342
*ppsz = NULL;
343
}
344
}
345
else {
346
nIn = (UINT)strlen(pszIn);
347
}
348
349
*ppsz = new CHAR [nIn + 1];
350
if (*ppsz == NULL) {
351
SetLastError(ERROR_OUTOFMEMORY);
352
}
353
else {
354
CopyMemory(*ppsz, pszIn, nIn + 1);
355
}
356
return *ppsz;
357
}
358
359
//////////////////////////////////////////////////////////////////////////////
360
//
361
CImageImportFile::CImageImportFile()
362
{
363
m_pNextFile = NULL;
364
m_fByway = FALSE;
365
366
m_pImportNames = NULL;
367
m_nImportNames = 0;
368
369
m_rvaOriginalFirstThunk = 0;
370
m_rvaFirstThunk = 0;
371
372
m_nForwarderChain = (UINT)0;
373
m_pszName = NULL;
374
m_pszOrig = NULL;
375
}
376
377
CImageImportFile::~CImageImportFile()
378
{
379
if (m_pNextFile) {
380
delete m_pNextFile;
381
m_pNextFile = NULL;
382
}
383
if (m_pImportNames) {
384
delete[] m_pImportNames;
385
m_pImportNames = NULL;
386
m_nImportNames = 0;
387
}
388
if (m_pszName) {
389
delete[] m_pszName;
390
m_pszName = NULL;
391
}
392
if (m_pszOrig) {
393
delete[] m_pszOrig;
394
m_pszOrig = NULL;
395
}
396
}
397
398
CImageImportName::CImageImportName()
399
{
400
m_nOrig = 0;
401
m_nOrdinal = 0;
402
m_nHint = 0;
403
m_pszName = NULL;
404
m_pszOrig = NULL;
405
}
406
407
CImageImportName::~CImageImportName()
408
{
409
if (m_pszName) {
410
delete[] m_pszName;
411
m_pszName = NULL;
412
}
413
if (m_pszOrig) {
414
delete[] m_pszOrig;
415
m_pszOrig = NULL;
416
}
417
}
418
419
//////////////////////////////////////////////////////////////////////////////
420
//
421
CImageData::CImageData(PBYTE pbData, DWORD cbData)
422
{
423
m_pbData = pbData;
424
m_cbData = cbData;
425
m_cbAlloc = 0;
426
}
427
428
CImageData::~CImageData()
429
{
430
IsValid();
431
432
if (m_cbAlloc == 0) {
433
m_pbData = NULL;
434
}
435
if (m_pbData) {
436
delete[] m_pbData;
437
m_pbData = NULL;
438
}
439
m_cbData = 0;
440
m_cbAlloc = 0;
441
}
442
443
BOOL CImageData::SizeTo(DWORD cbData)
444
{
445
IsValid();
446
447
if (cbData <= m_cbAlloc) {
448
return TRUE;
449
}
450
451
PBYTE pbNew = new BYTE [cbData];
452
if (pbNew == NULL) {
453
SetLastError(ERROR_OUTOFMEMORY);
454
return FALSE;
455
}
456
457
if (m_pbData) {
458
CopyMemory(pbNew, m_pbData, m_cbData);
459
if (m_cbAlloc > 0) {
460
delete[] m_pbData;
461
}
462
m_pbData = NULL;
463
}
464
m_pbData = pbNew;
465
m_cbAlloc = cbData;
466
467
IsValid();
468
469
return TRUE;
470
}
471
472
BOOL CImageData::Purge()
473
{
474
m_cbData = 0;
475
476
IsValid();
477
478
return TRUE;
479
}
480
481
BOOL CImageData::IsValid()
482
{
483
if (m_pbData == NULL) {
484
return TRUE;
485
}
486
487
PBYTE pbBeg = m_pbData;
488
PBYTE pbEnd = m_pbData + m_cbData;
489
490
for (PBYTE pbIter = pbBeg; pbIter < pbEnd;) {
491
PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)pbIter;
492
493
if (pRecord->cbBytes < sizeof(DETOUR_SECTION_RECORD)) {
494
return FALSE;
495
}
496
if (pRecord->nReserved != 0) {
497
return FALSE;
498
}
499
500
pbIter += pRecord->cbBytes;
501
}
502
return TRUE;
503
}
504
505
PBYTE CImageData::Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
506
{
507
IsValid();
508
509
if (pnIterator == NULL ||
510
m_cbData < *pnIterator + sizeof(DETOUR_SECTION_RECORD)) {
511
512
if (pcbData) {
513
*pcbData = 0;
514
}
515
if (pGuid) {
516
ZeroMemory(pGuid, sizeof(*pGuid));
517
}
518
return NULL;
519
}
520
521
PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + *pnIterator);
522
523
if (pGuid) {
524
*pGuid = pRecord->guid;
525
}
526
if (pcbData) {
527
*pcbData = pRecord->cbBytes - sizeof(DETOUR_SECTION_RECORD);
528
}
529
*pnIterator = (LONG)(((PBYTE)pRecord - m_pbData) + pRecord->cbBytes);
530
531
return (PBYTE)(pRecord + 1);
532
}
533
534
PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)
535
{
536
IsValid();
537
538
DWORD cbBytes = sizeof(DETOUR_SECTION_RECORD);
539
for (DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes) {
540
PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + nOffset);
541
542
cbBytes = pRecord->cbBytes;
543
if (cbBytes > m_cbData) {
544
break;
545
}
546
if (cbBytes < sizeof(DETOUR_SECTION_RECORD)) {
547
continue;
548
}
549
550
if (pRecord->guid.Data1 == rguid.Data1 &&
551
pRecord->guid.Data2 == rguid.Data2 &&
552
pRecord->guid.Data3 == rguid.Data3 &&
553
pRecord->guid.Data4[0] == rguid.Data4[0] &&
554
pRecord->guid.Data4[1] == rguid.Data4[1] &&
555
pRecord->guid.Data4[2] == rguid.Data4[2] &&
556
pRecord->guid.Data4[3] == rguid.Data4[3] &&
557
pRecord->guid.Data4[4] == rguid.Data4[4] &&
558
pRecord->guid.Data4[5] == rguid.Data4[5] &&
559
pRecord->guid.Data4[6] == rguid.Data4[6] &&
560
pRecord->guid.Data4[7] == rguid.Data4[7]) {
561
562
*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
563
return (PBYTE)(pRecord + 1);
564
}
565
}
566
567
if (pcbData) {
568
*pcbData = 0;
569
}
570
return NULL;
571
}
572
573
BOOL CImageData::Delete(REFGUID rguid)
574
{
575
IsValid();
576
577
PBYTE pbFound = NULL;
578
DWORD cbFound = 0;
579
580
pbFound = Find(rguid, &cbFound);
581
if (pbFound == NULL) {
582
SetLastError(ERROR_MOD_NOT_FOUND);
583
return FALSE;
584
}
585
586
pbFound -= sizeof(DETOUR_SECTION_RECORD);
587
cbFound += sizeof(DETOUR_SECTION_RECORD);
588
589
PBYTE pbRestData = pbFound + cbFound;
590
DWORD cbRestData = m_cbData - (LONG)(pbRestData - m_pbData);
591
592
if (cbRestData) {
593
MoveMemory(pbFound, pbRestData, cbRestData);
594
}
595
m_cbData -= cbFound;
596
597
IsValid();
598
return TRUE;
599
}
600
601
PBYTE CImageData::Set(REFGUID rguid, PBYTE pbData, DWORD cbData)
602
{
603
IsValid();
604
Delete(rguid);
605
606
DWORD cbAlloc = QuadAlign(cbData);
607
608
if (!SizeTo(m_cbData + cbAlloc + sizeof(DETOUR_SECTION_RECORD))) {
609
return NULL;
610
}
611
612
PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + m_cbData);
613
pRecord->cbBytes = cbAlloc + sizeof(DETOUR_SECTION_RECORD);
614
pRecord->nReserved = 0;
615
pRecord->guid = rguid;
616
617
PBYTE pbDest = (PBYTE)(pRecord + 1);
618
if (pbData) {
619
CopyMemory(pbDest, pbData, cbData);
620
if (cbData < cbAlloc) {
621
ZeroMemory(pbDest + cbData, cbAlloc - cbData);
622
}
623
}
624
else {
625
if (cbAlloc > 0) {
626
ZeroMemory(pbDest, cbAlloc);
627
}
628
}
629
630
m_cbData += cbAlloc + sizeof(DETOUR_SECTION_RECORD);
631
632
IsValid();
633
return pbDest;
634
}
635
636
//////////////////////////////////////////////////////////////////////////////
637
//
638
class CImageThunks
639
{
640
private:
641
CImage * m_pImage;
642
PIMAGE_THUNK_DATA m_pThunks;
643
DWORD m_nThunks;
644
DWORD m_nThunksMax;
645
DWORD m_nThunkVirtAddr;
646
647
public:
648
CImageThunks(CImage *pImage, DWORD nThunksMax, DWORD *pnAddr)
649
{
650
m_pImage = pImage;
651
m_nThunks = 0;
652
m_nThunksMax = nThunksMax;
653
m_pThunks = (PIMAGE_THUNK_DATA)
654
m_pImage->AllocateOutput(sizeof(IMAGE_THUNK_DATA) * nThunksMax,
655
&m_nThunkVirtAddr);
656
*pnAddr = m_nThunkVirtAddr;
657
}
658
659
PIMAGE_THUNK_DATA Current(DWORD *pnVirtAddr)
660
{
661
if (m_nThunksMax > 1) {
662
*pnVirtAddr = m_nThunkVirtAddr;
663
return m_pThunks;
664
}
665
*pnVirtAddr = 0;
666
return NULL;
667
}
668
669
PIMAGE_THUNK_DATA Allocate(ULONG_PTR nData, DWORD *pnVirtAddr)
670
{
671
if (m_nThunks < m_nThunksMax) {
672
*pnVirtAddr = m_nThunkVirtAddr;
673
674
m_nThunks++;
675
m_nThunkVirtAddr += sizeof(IMAGE_THUNK_DATA);
676
m_pThunks->u1.Ordinal = nData;
677
return m_pThunks++;
678
}
679
*pnVirtAddr = 0;
680
return NULL;
681
}
682
683
DWORD Size()
684
{
685
return m_nThunksMax * sizeof(IMAGE_THUNK_DATA);
686
}
687
};
688
689
//////////////////////////////////////////////////////////////////////////////
690
//
691
class CImageChars
692
{
693
private:
694
CImage * m_pImage;
695
PCHAR m_pChars;
696
DWORD m_nChars;
697
DWORD m_nCharsMax;
698
DWORD m_nCharVirtAddr;
699
700
public:
701
CImageChars(CImage *pImage, DWORD nCharsMax, DWORD *pnAddr)
702
{
703
m_pImage = pImage;
704
m_nChars = 0;
705
m_nCharsMax = nCharsMax;
706
m_pChars = (PCHAR)m_pImage->AllocateOutput(nCharsMax, &m_nCharVirtAddr);
707
*pnAddr = m_nCharVirtAddr;
708
}
709
710
PCHAR Allocate(__in_z PCHAR pszString, DWORD *pnVirtAddr)
711
{
712
DWORD nLen = (DWORD)strlen(pszString) + 1;
713
nLen += (nLen & 1);
714
715
if (m_nChars + nLen > m_nCharsMax) {
716
*pnVirtAddr = 0;
717
return NULL;
718
}
719
720
*pnVirtAddr = m_nCharVirtAddr;
721
HRESULT hrRet = StringCchCopyA(m_pChars,m_nCharsMax, pszString);
722
723
if (FAILED(hrRet)) {
724
return NULL;
725
}
726
727
pszString = m_pChars;
728
729
m_pChars += nLen;
730
m_nChars += nLen;
731
m_nCharVirtAddr += nLen;
732
733
return pszString;
734
}
735
736
PCHAR Allocate(PCHAR pszString, DWORD nHint, DWORD *pnVirtAddr)
737
{
738
DWORD nLen = (DWORD)strlen(pszString) + 1 + sizeof(USHORT);
739
nLen += (nLen & 1);
740
741
if (m_nChars + nLen > m_nCharsMax) {
742
*pnVirtAddr = 0;
743
return NULL;
744
}
745
746
*pnVirtAddr = m_nCharVirtAddr;
747
*(USHORT *)m_pChars = (USHORT)nHint;
748
749
HRESULT hrRet = StringCchCopyA(m_pChars + sizeof(USHORT), m_nCharsMax, pszString);
750
if (FAILED(hrRet)) {
751
return NULL;
752
}
753
754
pszString = m_pChars + sizeof(USHORT);
755
756
m_pChars += nLen;
757
m_nChars += nLen;
758
m_nCharVirtAddr += nLen;
759
760
return pszString;
761
}
762
763
DWORD Size()
764
{
765
return m_nChars;
766
}
767
};
768
769
//////////////////////////////////////////////////////////////////////////////
770
//
771
CImage * CImage::IsValid(PDETOUR_BINARY pBinary)
772
{
773
if (pBinary) {
774
CImage *pImage = (CImage *)pBinary;
775
776
if (pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE) {
777
return pImage;
778
}
779
}
780
SetLastError(ERROR_INVALID_HANDLE);
781
return NULL;
782
}
783
784
CImage::CImage()
785
{
786
m_dwValidSignature = (DWORD)DETOUR_IMAGE_VALID_SIGNATURE;
787
788
m_hMap = NULL;
789
m_pMap = NULL;
790
791
m_nPeOffset = 0;
792
m_nSectionsOffset = 0;
793
794
m_pbOutputBuffer = NULL;
795
m_cbOutputBuffer = 0;
796
797
m_pImageData = NULL;
798
799
m_pImportFiles = NULL;
800
m_nImportFiles = 0;
801
802
m_fHadDetourSection = FALSE;
803
}
804
805
CImage::~CImage()
806
{
807
Close();
808
m_dwValidSignature = 0;
809
}
810
811
BOOL CImage::Close()
812
{
813
if (m_pImportFiles) {
814
delete m_pImportFiles;
815
m_pImportFiles = NULL;
816
m_nImportFiles = 0;
817
}
818
819
if (m_pImageData) {
820
delete m_pImageData;
821
m_pImageData = NULL;
822
}
823
824
if (m_pMap != NULL) {
825
UnmapViewOfFile(m_pMap);
826
m_pMap = NULL;
827
}
828
829
if (m_hMap) {
830
CloseHandle(m_hMap);
831
m_hMap = NULL;
832
}
833
834
if (m_pbOutputBuffer) {
835
delete[] m_pbOutputBuffer;
836
m_pbOutputBuffer = NULL;
837
m_cbOutputBuffer = 0;
838
}
839
return TRUE;
840
}
841
842
//////////////////////////////////////////////////////////////////////////////
843
//
844
PBYTE CImage::DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
845
{
846
if (m_pImageData == NULL) {
847
return NULL;
848
}
849
return m_pImageData->Enumerate(pGuid, pcbData, pnIterator);
850
}
851
852
PBYTE CImage::DataFind(REFGUID rguid, DWORD *pcbData)
853
{
854
if (m_pImageData == NULL) {
855
return NULL;
856
}
857
return m_pImageData->Find(rguid, pcbData);
858
}
859
860
PBYTE CImage::DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData)
861
{
862
if (m_pImageData == NULL) {
863
return NULL;
864
}
865
return m_pImageData->Set(rguid, pbData, cbData);
866
}
867
868
BOOL CImage::DataDelete(REFGUID rguid)
869
{
870
if (m_pImageData == NULL) {
871
return FALSE;
872
}
873
return m_pImageData->Delete(rguid);
874
}
875
876
BOOL CImage::DataPurge()
877
{
878
if (m_pImageData == NULL) {
879
return TRUE;
880
}
881
return m_pImageData->Purge();
882
}
883
884
//////////////////////////////////////////////////////////////////////////////
885
//
886
BOOL CImage::SizeOutputBuffer(DWORD cbData)
887
{
888
if (m_cbOutputBuffer < cbData) {
889
if (cbData < 1024) {//65536
890
cbData = 1024;
891
}
892
cbData = FileAlign(cbData);
893
894
PBYTE pOutput = new BYTE [cbData];
895
if (pOutput == NULL) {
896
SetLastError(ERROR_OUTOFMEMORY);
897
return FALSE;
898
}
899
900
if (m_pbOutputBuffer) {
901
CopyMemory(pOutput, m_pbOutputBuffer, m_cbOutputBuffer);
902
903
delete[] m_pbOutputBuffer;
904
m_pbOutputBuffer = NULL;
905
}
906
907
ZeroMemory(pOutput + m_cbOutputBuffer, cbData - m_cbOutputBuffer),
908
909
m_pbOutputBuffer = pOutput;
910
m_cbOutputBuffer = cbData;
911
}
912
return TRUE;
913
}
914
915
PBYTE CImage::AllocateOutput(DWORD cbData, DWORD *pnVirtAddr)
916
{
917
cbData = QuadAlign(cbData);
918
919
PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize;
920
921
*pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize;
922
m_nOutputVirtSize += cbData;
923
924
if (m_nOutputVirtSize > m_cbOutputBuffer) {
925
SetLastError(ERROR_OUTOFMEMORY);
926
return NULL;
927
}
928
929
ZeroMemory(pbData, cbData);
930
931
return pbData;
932
}
933
934
//////////////////////////////////////////////////////////////////////////////
935
//
936
DWORD CImage::FileAlign(DWORD nAddr)
937
{
938
return Align(nAddr, m_NtHeader.OptionalHeader.FileAlignment);
939
}
940
941
DWORD CImage::SectionAlign(DWORD nAddr)
942
{
943
return Align(nAddr, m_NtHeader.OptionalHeader.SectionAlignment);
944
}
945
946
//////////////////////////////////////////////////////////////////////////////
947
//
948
PVOID CImage::RvaToVa(ULONG_PTR nRva)
949
{
950
if (nRva == 0) {
951
return NULL;
952
}
953
954
for (DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
955
DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
956
DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
957
958
if (nRva >= vaStart && nRva < vaEnd) {
959
return (PBYTE)m_pMap
960
+ m_SectionHeaders[n].PointerToRawData
961
+ nRva - m_SectionHeaders[n].VirtualAddress;
962
}
963
}
964
return NULL;
965
}
966
967
DWORD CImage::RvaToFileOffset(DWORD nRva)
968
{
969
DWORD n;
970
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
971
DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
972
DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
973
974
if (nRva >= vaStart && nRva < vaEnd) {
975
return m_SectionHeaders[n].PointerToRawData
976
+ nRva - m_SectionHeaders[n].VirtualAddress;
977
}
978
}
979
return 0;
980
}
981
982
//////////////////////////////////////////////////////////////////////////////
983
//
984
BOOL CImage::WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
985
LPDWORD lpNumberOfBytesWritten)
986
{
987
return ::WriteFile(hFile,
988
lpBuffer,
989
nNumberOfBytesToWrite,
990
lpNumberOfBytesWritten,
991
NULL);
992
}
993
994
995
BOOL CImage::CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData)
996
{
997
DWORD cbDone = 0;
998
return WriteFile(hFile, m_pMap + nOldPos, cbData, &cbDone);
999
}
1000
1001
BOOL CImage::ZeroFileData(HANDLE hFile, DWORD cbData)
1002
{
1003
if (!SizeOutputBuffer(4096)) {
1004
return FALSE;
1005
}
1006
1007
ZeroMemory(m_pbOutputBuffer, 4096);
1008
1009
for (DWORD cbLeft = cbData; cbLeft > 0;) {
1010
DWORD cbStep = cbLeft > sizeof(m_pbOutputBuffer)
1011
? sizeof(m_pbOutputBuffer) : cbLeft;
1012
DWORD cbDone = 0;
1013
1014
if (!WriteFile(hFile, m_pbOutputBuffer, cbStep, &cbDone)) {
1015
return FALSE;
1016
}
1017
if (cbDone == 0) {
1018
break;
1019
}
1020
1021
cbLeft -= cbDone;
1022
}
1023
return TRUE;
1024
}
1025
1026
BOOL CImage::AlignFileData(HANDLE hFile)
1027
{
1028
DWORD nLastFileAddr = m_nNextFileAddr;
1029
1030
m_nNextFileAddr = FileAlign(m_nNextFileAddr);
1031
m_nNextVirtAddr = SectionAlign(m_nNextVirtAddr);
1032
1033
if (hFile != INVALID_HANDLE_VALUE) {
1034
if (m_nNextFileAddr > nLastFileAddr) {
1035
if (SetFilePointer(hFile, nLastFileAddr, NULL, FILE_BEGIN) == ~0u) {
1036
return FALSE;
1037
}
1038
return ZeroFileData(hFile, m_nNextFileAddr - nLastFileAddr);
1039
}
1040
}
1041
return TRUE;
1042
}
1043
1044
BOOL CImage::Read(HANDLE hFile)
1045
{
1046
DWORD n;
1047
PBYTE pbData = NULL;
1048
DWORD cbData = 0;
1049
1050
if (hFile == INVALID_HANDLE_VALUE) {
1051
SetLastError(ERROR_INVALID_HANDLE);
1052
return FALSE;
1053
}
1054
1055
///////////////////////////////////////////////////////// Create mapping.
1056
//
1057
m_nFileSize = GetFileSize(hFile, NULL);
1058
if (m_nFileSize == (DWORD)-1) {
1059
return FALSE;
1060
}
1061
1062
m_hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
1063
if (m_hMap == NULL) {
1064
return FALSE;
1065
}
1066
1067
m_pMap = (PBYTE)MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0);
1068
if (m_pMap == NULL) {
1069
return FALSE;
1070
}
1071
1072
////////////////////////////////////////////////////// Process DOS Header.
1073
//
1074
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)m_pMap;
1075
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
1076
SetLastError(ERROR_BAD_EXE_FORMAT);
1077
return FALSE;
1078
}
1079
m_nPeOffset = pDosHeader->e_lfanew;
1080
m_nPrePE = 0;
1081
m_cbPrePE = QuadAlign(pDosHeader->e_lfanew);
1082
1083
CopyMemory(&m_DosHeader, m_pMap + m_nPrePE, sizeof(m_DosHeader));
1084
1085
/////////////////////////////////////////////////////// Process PE Header.
1086
//
1087
CopyMemory(&m_NtHeader, m_pMap + m_nPeOffset, sizeof(m_NtHeader));
1088
if (m_NtHeader.Signature != IMAGE_NT_SIGNATURE) {
1089
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
1090
return FALSE;
1091
}
1092
if (m_NtHeader.FileHeader.SizeOfOptionalHeader == 0) {
1093
SetLastError(ERROR_EXE_MARKED_INVALID);
1094
return FALSE;
1095
}
1096
m_nSectionsOffset = m_nPeOffset
1097
+ sizeof(m_NtHeader.Signature)
1098
+ sizeof(m_NtHeader.FileHeader)
1099
+ m_NtHeader.FileHeader.SizeOfOptionalHeader;
1100
1101
///////////////////////////////////////////////// Process Section Headers.
1102
//
1103
if (m_NtHeader.FileHeader.NumberOfSections > (sizeof(m_SectionHeaders) /
1104
sizeof(m_SectionHeaders[0]))) {
1105
SetLastError(ERROR_EXE_MARKED_INVALID);
1106
return FALSE;
1107
}
1108
CopyMemory(&m_SectionHeaders,
1109
m_pMap + m_nSectionsOffset,
1110
sizeof(m_SectionHeaders[0]) * m_NtHeader.FileHeader.NumberOfSections);
1111
1112
/////////////////////////////////////////////////// Parse .detour Section.
1113
//
1114
DWORD rvaOriginalImageDirectory = 0;
1115
DWORD rvaDetourBeg = 0;
1116
DWORD rvaDetourEnd = 0;
1117
1118
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1119
if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
1120
DETOUR_SECTION_HEADER dh;
1121
CopyMemory(&dh,
1122
m_pMap + m_SectionHeaders[n].PointerToRawData,
1123
sizeof(dh));
1124
1125
rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress;
1126
if (dh.cbPrePE != 0) {
1127
m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof(dh);
1128
m_cbPrePE = dh.cbPrePE;
1129
}
1130
rvaDetourBeg = m_SectionHeaders[n].VirtualAddress;
1131
rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData;
1132
}
1133
}
1134
1135
//////////////////////////////////////////////////////// Get Import Table.
1136
//
1137
DWORD rvaImageDirectory = m_NtHeader.OptionalHeader
1138
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1139
PIMAGE_IMPORT_DESCRIPTOR iidp
1140
= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaImageDirectory);
1141
PIMAGE_IMPORT_DESCRIPTOR oidp
1142
= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaOriginalImageDirectory);
1143
1144
if (oidp == NULL) {
1145
oidp = iidp;
1146
}
1147
if (iidp == NULL || oidp == NULL) {
1148
SetLastError(ERROR_EXE_MARKED_INVALID);
1149
return FALSE;
1150
}
1151
1152
DWORD nFiles = 0;
1153
for (; iidp[nFiles].OriginalFirstThunk != 0; nFiles++) {
1154
}
1155
1156
CImageImportFile **ppLastFile = &m_pImportFiles;
1157
m_pImportFiles = NULL;
1158
1159
for (n = 0; n < nFiles; n++, iidp++) {
1160
ULONG_PTR rvaName = iidp->Name;
1161
PCHAR pszName = (PCHAR)RvaToVa(rvaName);
1162
if (pszName == NULL) {
1163
SetLastError(ERROR_EXE_MARKED_INVALID);
1164
goto fail;
1165
}
1166
1167
CImageImportFile *pImportFile = new CImageImportFile;
1168
if (pImportFile == NULL) {
1169
SetLastError(ERROR_OUTOFMEMORY);
1170
goto fail;
1171
}
1172
1173
*ppLastFile = pImportFile;
1174
ppLastFile = &pImportFile->m_pNextFile;
1175
m_nImportFiles++;
1176
1177
pImportFile->m_pszName = DuplicateString(pszName);
1178
if (pImportFile->m_pszName == NULL) {
1179
goto fail;
1180
}
1181
1182
pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk;
1183
pImportFile->m_rvaFirstThunk = iidp->FirstThunk;
1184
pImportFile->m_nForwarderChain = iidp->ForwarderChain;
1185
pImportFile->m_pImportNames = NULL;
1186
pImportFile->m_nImportNames = 0;
1187
pImportFile->m_fByway = FALSE;
1188
1189
if ((ULONG)iidp->FirstThunk >= rvaDetourBeg &&
1190
(ULONG)iidp->FirstThunk < rvaDetourEnd) {
1191
1192
pImportFile->m_pszOrig = NULL;
1193
pImportFile->m_fByway = TRUE;
1194
continue;
1195
}
1196
1197
rvaName = oidp->Name;
1198
pszName = (PCHAR)RvaToVa(rvaName);
1199
if (pszName == NULL) {
1200
SetLastError(ERROR_EXE_MARKED_INVALID);
1201
goto fail;
1202
}
1203
pImportFile->m_pszOrig = DuplicateString(pszName);
1204
if (pImportFile->m_pszOrig == NULL) {
1205
goto fail;
1206
}
1207
1208
DWORD rvaThunk = iidp->OriginalFirstThunk;
1209
PIMAGE_THUNK_DATA pAddrThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
1210
rvaThunk = oidp->OriginalFirstThunk;
1211
PIMAGE_THUNK_DATA pLookThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
1212
1213
DWORD nNames = 0;
1214
if (pAddrThunk) {
1215
for (; pAddrThunk[nNames].u1.Ordinal; nNames++) {
1216
}
1217
}
1218
1219
if (pAddrThunk && nNames) {
1220
pImportFile->m_nImportNames = nNames;
1221
pImportFile->m_pImportNames = new CImageImportName [nNames];
1222
if (pImportFile->m_pImportNames == NULL) {
1223
SetLastError(ERROR_OUTOFMEMORY);
1224
goto fail;
1225
}
1226
1227
CImageImportName *pImportName = &pImportFile->m_pImportNames[0];
1228
1229
for (DWORD f = 0; f < nNames; f++, pImportName++) {
1230
pImportName->m_nOrig = 0;
1231
pImportName->m_nOrdinal = 0;
1232
pImportName->m_nHint = 0;
1233
pImportName->m_pszName = NULL;
1234
pImportName->m_pszOrig = NULL;
1235
1236
rvaName = pAddrThunk[f].u1.Ordinal;
1237
if (rvaName & IMAGE_ORDINAL_FLAG) {
1238
pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
1239
pImportName->m_nOrdinal = pImportName->m_nOrig;
1240
}
1241
else {
1242
PIMAGE_IMPORT_BY_NAME pName
1243
= (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
1244
if (pName) {
1245
pImportName->m_nHint = pName->Hint;
1246
pImportName->m_pszName = DuplicateString((PCHAR)pName->Name);
1247
if (pImportName->m_pszName == NULL) {
1248
goto fail;
1249
}
1250
}
1251
1252
rvaName = pLookThunk[f].u1.Ordinal;
1253
if (rvaName & IMAGE_ORDINAL_FLAG) {
1254
pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
1255
pImportName->m_nOrdinal = (ULONG)IMAGE_ORDINAL(rvaName);
1256
}
1257
else {
1258
pName = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
1259
if (pName) {
1260
pImportName->m_pszOrig
1261
= DuplicateString((PCHAR)pName->Name);
1262
if (pImportName->m_pszOrig == NULL) {
1263
goto fail;
1264
}
1265
}
1266
}
1267
}
1268
}
1269
}
1270
oidp++;
1271
}
1272
1273
////////////////////////////////////////////////////////// Parse Sections.
1274
//
1275
m_nExtraOffset = 0;
1276
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1277
m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
1278
m_SectionHeaders[n].SizeOfRawData,
1279
m_nExtraOffset);
1280
1281
if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
1282
DETOUR_SECTION_HEADER dh;
1283
CopyMemory(&dh,
1284
m_pMap + m_SectionHeaders[n].PointerToRawData,
1285
sizeof(dh));
1286
1287
if (dh.nDataOffset == 0) {
1288
dh.nDataOffset = dh.cbHeaderSize;
1289
}
1290
1291
cbData = dh.cbDataSize - dh.nDataOffset;
1292
pbData = (m_pMap +
1293
m_SectionHeaders[n].PointerToRawData +
1294
dh.nDataOffset);
1295
1296
m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
1297
m_SectionHeaders[n].SizeOfRawData,
1298
m_nExtraOffset);
1299
1300
m_NtHeader.FileHeader.NumberOfSections--;
1301
1302
m_NtHeader.OptionalHeader
1303
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1304
= dh.nOriginalImportVirtualAddress;
1305
m_NtHeader.OptionalHeader
1306
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
1307
= dh.nOriginalImportSize;
1308
1309
m_NtHeader.OptionalHeader
1310
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress
1311
= dh.nOriginalBoundImportVirtualAddress;
1312
m_NtHeader.OptionalHeader
1313
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size
1314
= dh.nOriginalBoundImportSize;
1315
1316
m_NtHeader.OptionalHeader
1317
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress
1318
= dh.nOriginalIatVirtualAddress;
1319
m_NtHeader.OptionalHeader
1320
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size
1321
= dh.nOriginalIatSize;
1322
1323
m_NtHeader.OptionalHeader.CheckSum = 0;
1324
m_NtHeader.OptionalHeader.SizeOfImage
1325
= dh.nOriginalSizeOfImage;
1326
1327
m_fHadDetourSection = TRUE;
1328
}
1329
}
1330
1331
m_pImageData = new CImageData(pbData, cbData);
1332
if (m_pImageData == NULL) {
1333
SetLastError(ERROR_OUTOFMEMORY);
1334
}
1335
return TRUE;
1336
1337
fail:
1338
return FALSE;
1339
}
1340
1341
static inline BOOL strneq(__in_z PCHAR pszOne, __in_z PCHAR pszTwo)
1342
{
1343
if (pszOne == pszTwo) {
1344
return FALSE;
1345
}
1346
if (!pszOne || !pszTwo) {
1347
return TRUE;
1348
}
1349
return (strcmp(pszOne, pszTwo) != 0);
1350
}
1351
1352
BOOL CImage::CheckImportsNeeded(DWORD *pnTables, DWORD *pnThunks, DWORD *pnChars)
1353
{
1354
DWORD nTables = 0;
1355
DWORD nThunks = 0;
1356
DWORD nChars = 0;
1357
BOOL fNeedDetourSection = FALSE;
1358
1359
for (CImageImportFile *pImportFile = m_pImportFiles;
1360
pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {
1361
1362
nChars += (int)strlen(pImportFile->m_pszName) + 1;
1363
nChars += nChars & 1;
1364
1365
if (pImportFile->m_fByway) {
1366
fNeedDetourSection = TRUE;
1367
nThunks++;
1368
}
1369
else {
1370
if (!fNeedDetourSection &&
1371
strneq(pImportFile->m_pszName, pImportFile->m_pszOrig)) {
1372
1373
fNeedDetourSection = TRUE;
1374
}
1375
for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {
1376
CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1377
1378
if (!fNeedDetourSection &&
1379
strneq(pImportName->m_pszName, pImportName->m_pszOrig)) {
1380
1381
fNeedDetourSection = TRUE;
1382
}
1383
1384
if (pImportName->m_pszName) {
1385
nChars += sizeof(WORD); // Hint
1386
nChars += (int)strlen(pImportName->m_pszName) + 1;
1387
nChars += nChars & 1;
1388
}
1389
nThunks++;
1390
}
1391
}
1392
nThunks++;
1393
nTables++;
1394
}
1395
nTables++;
1396
1397
*pnTables = nTables;
1398
*pnThunks = nThunks;
1399
*pnChars = nChars;
1400
1401
return fNeedDetourSection;
1402
}
1403
1404
//////////////////////////////////////////////////////////////////////////////
1405
//
1406
CImageImportFile * CImage::NewByway(__in_z PCHAR pszName)
1407
{
1408
CImageImportFile *pImportFile = new CImageImportFile;
1409
if (pImportFile == NULL) {
1410
SetLastError(ERROR_OUTOFMEMORY);
1411
goto fail;
1412
}
1413
1414
pImportFile->m_pNextFile = NULL;
1415
pImportFile->m_fByway = TRUE;
1416
1417
pImportFile->m_pszName = DuplicateString(pszName);
1418
if (pImportFile->m_pszName == NULL) {
1419
goto fail;
1420
}
1421
1422
pImportFile->m_rvaOriginalFirstThunk = 0;
1423
pImportFile->m_rvaFirstThunk = 0;
1424
pImportFile->m_nForwarderChain = (UINT)0;
1425
pImportFile->m_pImportNames = NULL;
1426
pImportFile->m_nImportNames = 0;
1427
1428
m_nImportFiles++;
1429
return pImportFile;
1430
1431
fail:
1432
if (pImportFile) {
1433
delete pImportFile;
1434
pImportFile = NULL;
1435
}
1436
return NULL;
1437
}
1438
1439
BOOL CImage::EditImports(PVOID pContext,
1440
PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
1441
PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
1442
PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
1443
PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback)
1444
{
1445
CImageImportFile *pImportFile = NULL;
1446
CImageImportFile **ppLastFile = &m_pImportFiles;
1447
1448
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1449
1450
while ((pImportFile = *ppLastFile) != NULL) {
1451
1452
if (pfBywayCallback) {
1453
PCHAR pszFile = NULL;
1454
if (!(*pfBywayCallback)(pContext, pszFile, &pszFile)) {
1455
goto fail;
1456
}
1457
1458
if (pszFile) {
1459
// Insert a new Byway.
1460
CImageImportFile *pByway = NewByway(pszFile);
1461
if (pByway == NULL) {
1462
return FALSE;
1463
}
1464
1465
pByway->m_pNextFile = pImportFile;
1466
*ppLastFile = pByway;
1467
ppLastFile = &pByway->m_pNextFile;
1468
continue; // Retry after Byway.
1469
}
1470
}
1471
1472
if (pImportFile->m_fByway) {
1473
if (pfBywayCallback) {
1474
PCHAR pszFile = pImportFile->m_pszName;
1475
1476
if (!(*pfBywayCallback)(pContext, pszFile, &pszFile)) {
1477
goto fail;
1478
}
1479
1480
if (pszFile) { // Replace? Byway
1481
if (ReplaceString(&pImportFile->m_pszName, pszFile) == NULL) {
1482
goto fail;
1483
}
1484
}
1485
else { // Delete Byway
1486
*ppLastFile = pImportFile->m_pNextFile;
1487
pImportFile->m_pNextFile = NULL;
1488
delete pImportFile;
1489
pImportFile = *ppLastFile;
1490
m_nImportFiles--;
1491
continue; // Retry after delete.
1492
}
1493
}
1494
}
1495
else {
1496
if (pfFileCallback) {
1497
PCHAR pszFile = pImportFile->m_pszName;
1498
1499
if (!(*pfFileCallback)(pContext, pImportFile->m_pszOrig,
1500
pszFile, &pszFile)) {
1501
goto fail;
1502
}
1503
1504
if (pszFile != NULL) {
1505
if (ReplaceString(&pImportFile->m_pszName, pszFile) == NULL) {
1506
goto fail;
1507
}
1508
}
1509
}
1510
1511
if (pfSymbolCallback) {
1512
for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {
1513
CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1514
1515
PCHAR pszName = pImportName->m_pszName;
1516
ULONG nOrdinal = pImportName->m_nOrdinal;
1517
if (!(*pfSymbolCallback)(pContext,
1518
pImportName->m_nOrig,
1519
nOrdinal,
1520
&nOrdinal,
1521
pImportName->m_pszOrig,
1522
pszName,
1523
&pszName)) {
1524
goto fail;
1525
}
1526
1527
if (pszName != NULL) {
1528
pImportName->m_nOrdinal = 0;
1529
if (ReplaceString(&pImportName->m_pszName, pszName) == NULL) {
1530
goto fail;
1531
}
1532
}
1533
else if (nOrdinal != 0) {
1534
pImportName->m_nOrdinal = nOrdinal;
1535
1536
if (pImportName->m_pszName != NULL) {
1537
delete[] pImportName->m_pszName;
1538
pImportName->m_pszName = NULL;
1539
}
1540
}
1541
}
1542
}
1543
}
1544
1545
ppLastFile = &pImportFile->m_pNextFile;
1546
pImportFile = pImportFile->m_pNextFile;
1547
}
1548
1549
for (;;) {
1550
if (pfBywayCallback) {
1551
PCHAR pszFile = NULL;
1552
if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) {
1553
goto fail;
1554
}
1555
if (pszFile) {
1556
// Insert a new Byway.
1557
CImageImportFile *pByway = NewByway(pszFile);
1558
if (pByway == NULL) {
1559
return FALSE;
1560
}
1561
1562
pByway->m_pNextFile = pImportFile;
1563
*ppLastFile = pByway;
1564
ppLastFile = &pByway->m_pNextFile;
1565
continue; // Retry after Byway.
1566
}
1567
}
1568
break;
1569
}
1570
1571
if (pfCommitCallback) {
1572
if (!(*pfCommitCallback)(pContext)) {
1573
goto fail;
1574
}
1575
}
1576
1577
SetLastError(NO_ERROR);
1578
return TRUE;
1579
1580
fail:
1581
return FALSE;
1582
}
1583
1584
BOOL CImage::Write(HANDLE hFile)
1585
{
1586
DWORD cbDone;
1587
1588
if (hFile == INVALID_HANDLE_VALUE) {
1589
SetLastError(ERROR_INVALID_HANDLE);
1590
return FALSE;
1591
}
1592
1593
m_nNextFileAddr = 0;
1594
m_nNextVirtAddr = 0;
1595
1596
DWORD nTables = 0;
1597
DWORD nThunks = 0;
1598
DWORD nChars = 0;
1599
BOOL fNeedDetourSection = CheckImportsNeeded(&nTables, &nThunks, &nChars);
1600
1601
//////////////////////////////////////////////////////////// Copy Headers.
1602
//
1603
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1604
return FALSE;
1605
}
1606
if (!CopyFileData(hFile, 0, m_NtHeader.OptionalHeader.SizeOfHeaders)) {
1607
return FALSE;
1608
}
1609
1610
if (fNeedDetourSection || !m_pImageData->IsEmpty()) {
1611
// Replace the file's DOS header with our own.
1612
m_nPeOffset = sizeof(m_DosHeader) + sizeof(s_rbDosCode);
1613
m_nSectionsOffset = m_nPeOffset
1614
+ sizeof(m_NtHeader.Signature)
1615
+ sizeof(m_NtHeader.FileHeader)
1616
+ m_NtHeader.FileHeader.SizeOfOptionalHeader;
1617
m_DosHeader.e_lfanew = m_nPeOffset;
1618
1619
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1620
return FALSE;
1621
}
1622
if (!WriteFile(hFile, &m_DosHeader, sizeof(m_DosHeader), &cbDone)) {
1623
return FALSE;
1624
}
1625
if (!WriteFile(hFile, &s_rbDosCode, sizeof(s_rbDosCode), &cbDone)) {
1626
return FALSE;
1627
}
1628
}
1629
else {
1630
// Restore the file's original DOS header.
1631
if (m_nPrePE != 0) {
1632
m_nPeOffset = m_cbPrePE;
1633
m_nSectionsOffset = m_nPeOffset
1634
+ sizeof(m_NtHeader.Signature)
1635
+ sizeof(m_NtHeader.FileHeader)
1636
+ m_NtHeader.FileHeader.SizeOfOptionalHeader;
1637
m_DosHeader.e_lfanew = m_nPeOffset;
1638
1639
1640
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1641
return FALSE;
1642
}
1643
if (!CopyFileData(hFile, m_nPrePE, m_cbPrePE)) {
1644
return FALSE;
1645
}
1646
}
1647
}
1648
1649
m_nNextFileAddr = m_NtHeader.OptionalHeader.SizeOfHeaders;
1650
m_nNextVirtAddr = 0;
1651
if (!AlignFileData(hFile)) {
1652
return FALSE;
1653
}
1654
1655
/////////////////////////////////////////////////////////// Copy Sections.
1656
//
1657
DWORD n = 0;
1658
for (; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1659
if (m_SectionHeaders[n].SizeOfRawData) {
1660
if (SetFilePointer(hFile,
1661
m_SectionHeaders[n].PointerToRawData,
1662
NULL, FILE_BEGIN) == ~0u) {
1663
return FALSE;
1664
}
1665
if (!CopyFileData(hFile,
1666
m_SectionHeaders[n].PointerToRawData,
1667
m_SectionHeaders[n].SizeOfRawData)) {
1668
return FALSE;
1669
}
1670
}
1671
m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData +
1672
m_SectionHeaders[n].SizeOfRawData,
1673
m_nNextFileAddr);
1674
m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress +
1675
m_SectionHeaders[n].Misc.VirtualSize,
1676
m_nNextVirtAddr);
1677
m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset);
1678
1679
if (!AlignFileData(hFile)) {
1680
return FALSE;
1681
}
1682
}
1683
1684
if (fNeedDetourSection || !m_pImageData->IsEmpty()) {
1685
////////////////////////////////////////////// Insert .detour Section.
1686
//
1687
DWORD nSection = m_NtHeader.FileHeader.NumberOfSections++;
1688
DETOUR_SECTION_HEADER dh;
1689
1690
ZeroMemory(&dh, sizeof(dh));
1691
ZeroMemory(&m_SectionHeaders[nSection], sizeof(m_SectionHeaders[nSection]));
1692
1693
dh.cbHeaderSize = sizeof(DETOUR_SECTION_HEADER);
1694
dh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
1695
1696
dh.nOriginalImportVirtualAddress = m_NtHeader.OptionalHeader
1697
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1698
dh.nOriginalImportSize = m_NtHeader.OptionalHeader
1699
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
1700
1701
dh.nOriginalBoundImportVirtualAddress
1702
= m_NtHeader.OptionalHeader
1703
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
1704
dh.nOriginalBoundImportSize = m_NtHeader.OptionalHeader
1705
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size;
1706
1707
dh.nOriginalIatVirtualAddress = m_NtHeader.OptionalHeader
1708
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
1709
dh.nOriginalIatSize = m_NtHeader.OptionalHeader
1710
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
1711
1712
dh.nOriginalSizeOfImage = m_NtHeader.OptionalHeader.SizeOfImage;
1713
1714
DWORD clrAddr = m_NtHeader.OptionalHeader
1715
.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
1716
DWORD clrSize = m_NtHeader.OptionalHeader
1717
.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
1718
if (clrAddr && clrSize) {
1719
PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);
1720
if (pHdr != NULL) {
1721
DETOUR_CLR_HEADER hdr;
1722
hdr = *pHdr;
1723
1724
dh.nOriginalClrFlags = hdr.Flags;
1725
}
1726
}
1727
1728
HRESULT hrRet = StringCchCopyA((PCHAR)m_SectionHeaders[nSection].Name, IMAGE_SIZEOF_SHORT_NAME , ".detour");
1729
if (FAILED(hrRet))
1730
return FALSE;
1731
1732
m_SectionHeaders[nSection].Characteristics
1733
= IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
1734
1735
m_nOutputVirtAddr = m_nNextVirtAddr;
1736
m_nOutputVirtSize = 0;
1737
m_nOutputFileAddr = m_nNextFileAddr;
1738
1739
dh.nDataOffset = 0; // pbData
1740
dh.cbDataSize = m_pImageData->m_cbData;
1741
dh.cbPrePE = m_cbPrePE;
1742
1743
//////////////////////////////////////////////////////////////////////////
1744
//
1745
1746
DWORD rvaImportTable = 0;
1747
DWORD rvaLookupTable = 0;
1748
DWORD rvaBoundTable = 0;
1749
DWORD rvaNameTable = 0;
1750
DWORD nImportTableSize = nTables * sizeof(IMAGE_IMPORT_DESCRIPTOR);
1751
1752
if (!SizeOutputBuffer(QuadAlign(sizeof(dh))
1753
+ m_cbPrePE
1754
+ QuadAlign(m_pImageData->m_cbData)
1755
+ QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)
1756
+ QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)
1757
+ QuadAlign(nChars)
1758
+ QuadAlign(nImportTableSize))) {
1759
return FALSE;
1760
}
1761
1762
DWORD vaHead = 0;
1763
PBYTE pbHead = NULL;
1764
DWORD vaPrePE = 0;
1765
PBYTE pbPrePE = NULL;
1766
DWORD vaData = 0;
1767
PBYTE pbData = NULL;
1768
1769
if ((pbHead = AllocateOutput(sizeof(dh), &vaHead)) == NULL) {
1770
return FALSE;
1771
}
1772
1773
if ((pbPrePE = AllocateOutput(m_cbPrePE, &vaPrePE)) == NULL) {
1774
return FALSE;
1775
}
1776
1777
CImageThunks lookupTable(this, nThunks, &rvaLookupTable);
1778
CImageThunks boundTable(this, nThunks, &rvaBoundTable);
1779
CImageChars nameTable(this, nChars, &rvaNameTable);
1780
1781
if ((pbData = AllocateOutput(m_pImageData->m_cbData, &vaData)) == NULL) {
1782
return FALSE;
1783
}
1784
1785
dh.nDataOffset = vaData - vaHead;
1786
dh.cbDataSize = dh.nDataOffset + m_pImageData->m_cbData;
1787
CopyMemory(pbHead, &dh, sizeof(dh));
1788
CopyMemory(pbPrePE, m_pMap + m_nPrePE, m_cbPrePE);
1789
CopyMemory(pbData, m_pImageData->m_pbData, m_pImageData->m_cbData);
1790
1791
PIMAGE_IMPORT_DESCRIPTOR piidDst = (PIMAGE_IMPORT_DESCRIPTOR)
1792
AllocateOutput(nImportTableSize, &rvaImportTable);
1793
if (piidDst == NULL) {
1794
return FALSE;
1795
}
1796
1797
//////////////////////////////////////////////// Step Through Imports.
1798
//
1799
for (CImageImportFile *pImportFile = m_pImportFiles;
1800
pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {
1801
1802
ZeroMemory(piidDst, sizeof(piidDst));
1803
nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name);
1804
piidDst->TimeDateStamp = 0;
1805
piidDst->ForwarderChain = pImportFile->m_nForwarderChain;
1806
1807
if (pImportFile->m_fByway) {
1808
ULONG rvaIgnored;
1809
1810
lookupTable.Allocate(IMAGE_ORDINAL_FLAG+1,
1811
(DWORD *)&piidDst->OriginalFirstThunk);
1812
boundTable.Allocate(IMAGE_ORDINAL_FLAG+1,
1813
(DWORD *)&piidDst->FirstThunk);
1814
1815
lookupTable.Allocate(0, &rvaIgnored);
1816
boundTable.Allocate(0, &rvaIgnored);
1817
}
1818
else {
1819
ULONG rvaIgnored;
1820
1821
piidDst->FirstThunk = (ULONG)pImportFile->m_rvaFirstThunk;
1822
lookupTable.Current((DWORD *)&piidDst->OriginalFirstThunk);
1823
1824
for (n = 0; n < pImportFile->m_nImportNames; n++) {
1825
CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1826
1827
if (pImportName->m_pszName) {
1828
ULONG nDstName = 0;
1829
1830
nameTable.Allocate(pImportName->m_pszName,
1831
pImportName->m_nHint,
1832
&nDstName);
1833
lookupTable.Allocate(nDstName, &rvaIgnored);
1834
}
1835
else {
1836
lookupTable.Allocate(IMAGE_ORDINAL_FLAG + pImportName->m_nOrdinal,
1837
&rvaIgnored);
1838
}
1839
}
1840
lookupTable.Allocate(0, &rvaIgnored);
1841
}
1842
piidDst++;
1843
}
1844
ZeroMemory(piidDst, sizeof(piidDst));
1845
1846
//////////////////////////////////////////////////////////////////////////
1847
//
1848
m_nNextVirtAddr += m_nOutputVirtSize;
1849
m_nNextFileAddr += FileAlign(m_nOutputVirtSize);
1850
1851
if (!AlignFileData(hFile)) {
1852
return FALSE;
1853
}
1854
1855
//////////////////////////////////////////////////////////////////////////
1856
//
1857
m_SectionHeaders[nSection].VirtualAddress = m_nOutputVirtAddr;
1858
m_SectionHeaders[nSection].Misc.VirtualSize = m_nOutputVirtSize;
1859
m_SectionHeaders[nSection].PointerToRawData = m_nOutputFileAddr;
1860
m_SectionHeaders[nSection].SizeOfRawData = FileAlign(m_nOutputVirtSize);
1861
1862
m_NtHeader.OptionalHeader
1863
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1864
= rvaImportTable;
1865
m_NtHeader.OptionalHeader
1866
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
1867
= nImportTableSize;
1868
1869
m_NtHeader.OptionalHeader
1870
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
1871
m_NtHeader.OptionalHeader
1872
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
1873
1874
//////////////////////////////////////////////////////////////////////////
1875
//
1876
if (SetFilePointer(hFile, m_SectionHeaders[nSection].PointerToRawData,
1877
NULL, FILE_BEGIN) == ~0u) {
1878
return FALSE;
1879
}
1880
if (!WriteFile(hFile, m_pbOutputBuffer, m_SectionHeaders[nSection].SizeOfRawData,
1881
&cbDone)) {
1882
return FALSE;
1883
}
1884
}
1885
1886
///////////////////////////////////////////////////// Adjust Extra Data.
1887
//
1888
LONG nExtraAdjust = m_nNextFileAddr - m_nExtraOffset;
1889
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1890
if (m_SectionHeaders[n].PointerToRawData > m_nExtraOffset) {
1891
m_SectionHeaders[n].PointerToRawData += nExtraAdjust;
1892
}
1893
if (m_SectionHeaders[n].PointerToRelocations > m_nExtraOffset) {
1894
m_SectionHeaders[n].PointerToRelocations += nExtraAdjust;
1895
}
1896
if (m_SectionHeaders[n].PointerToLinenumbers > m_nExtraOffset) {
1897
m_SectionHeaders[n].PointerToLinenumbers += nExtraAdjust;
1898
}
1899
}
1900
if (m_NtHeader.FileHeader.PointerToSymbolTable > m_nExtraOffset) {
1901
m_NtHeader.FileHeader.PointerToSymbolTable += nExtraAdjust;
1902
}
1903
1904
m_NtHeader.OptionalHeader.CheckSum = 0;
1905
m_NtHeader.OptionalHeader.SizeOfImage = m_nNextVirtAddr;
1906
1907
////////////////////////////////////////////////// Adjust Debug Directory.
1908
//
1909
DWORD debugAddr = m_NtHeader.OptionalHeader
1910
.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
1911
DWORD debugSize = m_NtHeader.OptionalHeader
1912
.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
1913
if (debugAddr && debugSize) {
1914
DWORD nFileOffset = RvaToFileOffset(debugAddr);
1915
if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {
1916
return FALSE;
1917
}
1918
1919
PIMAGE_DEBUG_DIRECTORY pDir = (PIMAGE_DEBUG_DIRECTORY)RvaToVa(debugAddr);
1920
if (pDir == NULL) {
1921
return FALSE;
1922
}
1923
1924
DWORD nEntries = debugSize / sizeof(*pDir);
1925
for (n = 0; n < nEntries; n++) {
1926
IMAGE_DEBUG_DIRECTORY dir = pDir[n];
1927
1928
if (dir.PointerToRawData > m_nExtraOffset) {
1929
dir.PointerToRawData += nExtraAdjust;
1930
}
1931
if (!WriteFile(hFile, &dir, sizeof(dir), &cbDone)) {
1932
return FALSE;
1933
}
1934
}
1935
}
1936
1937
/////////////////////////////////////////////////////// Adjust CLR Header.
1938
//
1939
DWORD clrAddr = m_NtHeader.OptionalHeader
1940
.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
1941
DWORD clrSize = m_NtHeader.OptionalHeader
1942
.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
1943
if (clrAddr && clrSize && fNeedDetourSection) {
1944
DWORD nFileOffset = RvaToFileOffset(clrAddr);
1945
if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {
1946
return FALSE;
1947
}
1948
1949
PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);
1950
if (pHdr == NULL) {
1951
return FALSE;
1952
}
1953
1954
DETOUR_CLR_HEADER hdr;
1955
hdr = *pHdr;
1956
hdr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
1957
1958
if (!WriteFile(hFile, &hdr, sizeof(hdr), &cbDone)) {
1959
return FALSE;
1960
}
1961
}
1962
1963
///////////////////////////////////////////////// Copy Left-over Data.
1964
//
1965
if (m_nFileSize > m_nExtraOffset) {
1966
if (SetFilePointer(hFile, m_nNextFileAddr, NULL, FILE_BEGIN) == ~0u) {
1967
return FALSE;
1968
}
1969
if (!CopyFileData(hFile, m_nExtraOffset, m_nFileSize - m_nExtraOffset)) {
1970
return FALSE;
1971
}
1972
}
1973
1974
1975
//////////////////////////////////////////////////// Finalize Headers.
1976
//
1977
1978
if (SetFilePointer(hFile, m_nPeOffset, NULL, FILE_BEGIN) == ~0u) {
1979
return FALSE;
1980
}
1981
if (!WriteFile(hFile, &m_NtHeader, sizeof(m_NtHeader), &cbDone)) {
1982
return FALSE;
1983
}
1984
1985
if (SetFilePointer(hFile, m_nSectionsOffset, NULL, FILE_BEGIN) == ~0u) {
1986
return FALSE;
1987
}
1988
if (!WriteFile(hFile, &m_SectionHeaders,
1989
sizeof(m_SectionHeaders[0])
1990
* m_NtHeader.FileHeader.NumberOfSections,
1991
&cbDone)) {
1992
return FALSE;
1993
}
1994
1995
m_cbPostPE = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1996
if (m_cbPostPE == ~0u) {
1997
return FALSE;
1998
}
1999
m_cbPostPE = m_NtHeader.OptionalHeader.SizeOfHeaders - m_cbPostPE;
2000
2001
return TRUE;
2002
}
2003
2004
}; // namespace Detour
2005
2006
2007
//////////////////////////////////////////////////////////////////////////////
2008
//
2009
PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile)
2010
{
2011
Detour::CImage *pImage = new Detour::CImage;
2012
if (pImage == NULL) {
2013
SetLastError(ERROR_OUTOFMEMORY);
2014
return FALSE;
2015
}
2016
2017
if (!pImage->Read(hFile)) {
2018
delete pImage;
2019
return FALSE;
2020
}
2021
2022
return (PDETOUR_BINARY)pImage;
2023
}
2024
2025
BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pdi, HANDLE hFile)
2026
{
2027
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2028
if (pImage == NULL) {
2029
return FALSE;
2030
}
2031
2032
return pImage->Write(hFile);
2033
}
2034
2035
PVOID WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pdi,
2036
GUID *pGuid,
2037
DWORD *pcbData,
2038
DWORD *pnIterator)
2039
{
2040
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2041
if (pImage == NULL) {
2042
return FALSE;
2043
}
2044
2045
return pImage->DataEnum(pGuid, pcbData, pnIterator);
2046
}
2047
2048
PVOID WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pdi,
2049
REFGUID rguid,
2050
DWORD *pcbData)
2051
{
2052
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2053
if (pImage == NULL) {
2054
return FALSE;
2055
}
2056
2057
return pImage->DataFind(rguid, pcbData);
2058
}
2059
2060
PVOID WINAPI DetourBinarySetPayload(PDETOUR_BINARY pdi,
2061
REFGUID rguid,
2062
PVOID pvData,
2063
DWORD cbData)
2064
{
2065
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2066
if (pImage == NULL) {
2067
return FALSE;
2068
}
2069
2070
return pImage->DataSet(rguid, (PBYTE)pvData, cbData);
2071
}
2072
2073
BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pdi,
2074
REFGUID rguid)
2075
{
2076
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2077
if (pImage == NULL) {
2078
return FALSE;
2079
}
2080
2081
return pImage->DataDelete(rguid);
2082
}
2083
2084
BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pdi)
2085
{
2086
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2087
if (pImage == NULL) {
2088
return FALSE;
2089
}
2090
2091
return pImage->DataPurge();
2092
}
2093
2094
//////////////////////////////////////////////////////////////////////////////
2095
//
2096
static BOOL CALLBACK ResetBywayCallback(PVOID pContext,
2097
__in_z PCHAR pszFile,
2098
__deref PCHAR *ppszOutFile)
2099
{
2100
(void)pContext;
2101
(void)pszFile;
2102
2103
*ppszOutFile = NULL;
2104
return TRUE;
2105
}
2106
2107
static BOOL CALLBACK ResetFileCallback(PVOID pContext,
2108
__in_z PCHAR pszOrigFile,
2109
__in_z PCHAR pszFile,
2110
__deref PCHAR *ppszOutFile)
2111
{
2112
(void)pContext;
2113
(void)pszFile;
2114
2115
*ppszOutFile = pszOrigFile;
2116
return TRUE;
2117
}
2118
2119
static BOOL CALLBACK ResetSymbolCallback(PVOID pContext,
2120
ULONG nOrigOrdinal,
2121
ULONG nOrdinal,
2122
ULONG *pnOutOrdinal,
2123
__in_z PCHAR pszOrigSymbol,
2124
__in_z PCHAR pszSymbol,
2125
__deref PCHAR *ppszOutSymbol)
2126
{
2127
(void)pContext;
2128
(void)nOrdinal;
2129
(void)pszSymbol;
2130
2131
*pnOutOrdinal = nOrigOrdinal;
2132
*ppszOutSymbol = pszOrigSymbol;
2133
return TRUE;
2134
}
2135
2136
BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pdi)
2137
{
2138
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2139
if (pImage == NULL) {
2140
return FALSE;
2141
}
2142
2143
return pImage->EditImports(NULL,
2144
ResetBywayCallback,
2145
ResetFileCallback,
2146
ResetSymbolCallback,
2147
NULL);
2148
}
2149
2150
//////////////////////////////////////////////////////////////////////////////
2151
//
2152
BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pdi,
2153
PVOID pContext,
2154
PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
2155
PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
2156
PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
2157
PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback)
2158
{
2159
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2160
if (pImage == NULL) {
2161
return FALSE;
2162
}
2163
2164
return pImage->EditImports(pContext,
2165
pfBywayCallback,
2166
pfFileCallback,
2167
pfSymbolCallback,
2168
pfCommitCallback);
2169
}
2170
2171
BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pdi)
2172
{
2173
Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2174
if (pImage == NULL) {
2175
return FALSE;
2176
}
2177
2178
BOOL bSuccess = pImage->Close();
2179
delete pImage;
2180
pImage = NULL;
2181
2182
return bSuccess;
2183
}
2184
2185
//
2186
///////////////////////////////////////////////////////////////// End of File.
2187
2188