0x1 前言

之前几篇文章讲述了Windows PE结构的各个部分,本篇文章会应用前文中的知识,借助C++实现一个PE Parser,可以解析PE32和PE32+,可以解析PE文件中的下列部分

  • DOS Header
  • Rich Header
  • NT Headers
  • Data Directory
  • Section Headers
  • Import Table
  • Relocation Table

0x2 PE Parser Readme

  1. 以二进制形式读取一个PE文件
  2. 通过校验DOS头中的Signature和NT头中的Signature这两个固定值,判断它是否有效的PE文件
  3. 通过PE可选头中的字段判断它是32位PE还是64位PE
  4. 解析下列结构
  • DOS Header
  • Rich Header
  • NT Headers
  • Section Headers
  • Import Data Directory
  • Relocation Data Directory
  1. 输出下列信息
  • 文件名和类型
  • DOS头中的签名以及PE文件的实际起始地址
  • 富有头中的每一项
  • PE文件Signature
  • PE文件头中节的数量、PE可选头的大小
  • PE可选头中代码节的大小、初始化数据节的大小、未初始化数据节的大小、入口点的地址、代码节的起始RVA、期望的映像基址、节对齐、文件对齐、映像文件大小、各类头的大小
  • 数据目录中每一项的名字、RVA、大小
  • 节头中节的名字、节在文件中的起始地址和大小、节在内存中的起始地址和大小、节的属性
  • 导入表中每个DLL的名字、ILT和IAT、是否使用绑定导入、使用名称还是需要搜索函数、函数名称表的RVA
  • 重定位表中每个块对应的页面RVA、块大小、块项的数量

0x3 整理用到的结构体

代码实现中会用到定义在winnt.h中的类型、常量、结构体,整理后放到winntdef.h中,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned long long QWORD;
typedef unsigned long LONG;
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;

#define ___IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define ___IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define ___IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define ___IMAGE_DOS_SIGNATURE 0x5A4D

#define ___IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define ___IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define ___IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define ___IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define ___IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define ___IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define ___IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define ___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
#define ___IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define ___IMAGE_DIRECTORY_ENTRY_TLS 9
#define ___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define ___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
#define ___IMAGE_DIRECTORY_ENTRY_IAT 12
#define ___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
#define ___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14

#define ___IMAGE_SIZEOF_SHORT_NAME 8
#define ___IMAGE_SIZEOF_SECTION_HEADER 40

typedef struct __IMAGE_DOS_HEADER {
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} ___IMAGE_DOS_HEADER, * ___PIMAGE_DOS_HEADER;

typedef struct __IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} ___IMAGE_DATA_DIRECTORY, * ___PIMAGE_DATA_DIRECTORY;


typedef struct __IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
___IMAGE_DATA_DIRECTORY DataDirectory[___IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} ___IMAGE_OPTIONAL_HEADER32, * ___PIMAGE_OPTIONAL_HEADER32;

typedef struct __IMAGE_OPTIONAL_HEADER64 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
ULONGLONG ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
___IMAGE_DATA_DIRECTORY DataDirectory[___IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} ___IMAGE_OPTIONAL_HEADER64, * ___PIMAGE_OPTIONAL_HEADER64;

typedef struct __IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} ___IMAGE_FILE_HEADER, * ___PIMAGE_FILE_HEADER;

typedef struct __IMAGE_NT_HEADERS64 {
DWORD Signature;
___IMAGE_FILE_HEADER FileHeader;
___IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} ___IMAGE_NT_HEADERS64, * ___PIMAGE_NT_HEADERS64;

typedef struct __IMAGE_NT_HEADERS {
DWORD Signature;
___IMAGE_FILE_HEADER FileHeader;
___IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} ___IMAGE_NT_HEADERS32, * ___PIMAGE_NT_HEADERS32;

typedef struct __IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
} DUMMYUNIONNAME;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} ___IMAGE_IMPORT_DESCRIPTOR, * ___PIMAGE_IMPORT_DESCRIPTOR;

typedef struct __IMAGE_IMPORT_BY_NAME {
WORD Hint;
char Name[100];
} ___IMAGE_IMPORT_BY_NAME, * ___PIMAGE_IMPORT_BY_NAME;

typedef struct __IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
} ___IMAGE_BASE_RELOCATION, * ___PIMAGE_BASE_RELOCATION;

typedef struct __IMAGE_SECTION_HEADER {
BYTE Name[___IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} ___IMAGE_SECTION_HEADER, * ___PIMAGE_SECTION_HEADER;

0x4 自定义结构体

自定义一些结构体,方便解析PE文件,放到PEFILE_CUSTOM_STRUCTS.h中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma once
#include "winntdef.h"

typedef struct __RICH_HEADER_INFO {
int size;
char* ptrToBuffer;
int entries;
} RICH_HEADER_INFO, * PRICH_HEADER_INFO;

typedef struct __RICH_HEADER_ENTRY {
WORD prodID;
WORD buildID;
DWORD useCount;
} RICH_HEADER_ENTRY, * PRICH_HEADER_ENTRY;

typedef struct __RICH_HEADER {
PRICH_HEADER_ENTRY entries;
} RICH_HEADER, * PRICH_HEADER;

typedef struct __ILT_ENTRY_64 {
union {
DWORD ORDINAL : 16;
DWORD HINT_NAME_TABE : 32;
} FIELD_2;
DWORD ORDINAL_NAME_FLAG : 1;
} ILT_ENTRY_64, * PILT_ENTRY_64;

typedef struct __ILT_ENTRY_32 {
union {
DWORD ORDINAL : 16;
DWORD HINT_NAME_TABE : 32;
DWORD ORDINAL_NAME_FLAG : 1;
} FIELD_1;
} ILT_ENTRY_32, * PILT_ENTRY_32;

typedef struct __BASE_RELOC_ENTRY {
WORD OFFSET : 12;
WORD TYPE : 4;
} BASE_RELOC_ENTRY, * PBASE_RELOC_ENTRY;

0x5 代码实现

整理逻辑是PE-Parser.cpp调用PEFILE,PEFILE根据PE文件是32位还是64位,传给PE32FILE还是PE64FILE,定义在.h文件中,实现在.cpp文件中

PE-Parser.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <fstream>
#include "PEFILE.h"

int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: %s [path to executable]\n", argv[0]);
return 1;
}

FILE* PpeFile;
fopen_s(&PpeFile, argv[1], "rb");

if (PpeFile == NULL) {
printf("Can't open file.\n");
return 1;
}

if (INITPARSE(PpeFile) == 1) {
exit(1);
}
else if (INITPARSE(PpeFile) == 32) {
PE32FILE PeFile_1(argv[1], PpeFile);
PeFile_1.PrintInfo();
fclose(PpeFile);
exit(0);
}
else if (INITPARSE(PpeFile) == 64) {
PE64FILE PeFile_1(argv[1], PpeFile);
PeFile_1.PrintInfo();
fclose(PpeFile);
exit(0);
}

return 0;
}

PEFILE.h

1
2
3
4
5
#pragma once
#include "PE32FILE.h"
#include "PE64FILE.h"

int INITPARSE(FILE* PpeFile);

PEFILE.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "PEFILE.h"

// INITIAL PARSE //

int INITPARSE(FILE* PpeFile) {
___IMAGE_DOS_HEADER TMP_DOS_HEADER;
WORD PEFILE_TYPE;

fseek(PpeFile, 0, SEEK_SET);
fread(&TMP_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, PpeFile);

if (TMP_DOS_HEADER.e_magic != ___IMAGE_DOS_SIGNATURE) {
printf("Error. Not a PE file.\n");
return 1;
}

fseek(PpeFile, (TMP_DOS_HEADER.e_lfanew + sizeof(DWORD) + sizeof(___IMAGE_FILE_HEADER)), SEEK_SET);
fread(&PEFILE_TYPE, sizeof(WORD), 1, PpeFile);

if (PEFILE_TYPE == ___IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
return 32;
}
else if (PEFILE_TYPE == ___IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
return 64;
}
else {
printf("Error while parsing IMAGE_OPTIONAL_HEADER.Magic. Unknown Type.\n");
return 1;
}

}

PE32FILE.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#pragma once
#include "winntdef.h"
#include "PEFILE_CUSTOM_STRUCTS.h"
#include <string>

class PE32FILE
{
public:
PE32FILE(char* _NAME, FILE* Ppefile);

void PrintInfo();

private:
char* NAME;
FILE* Ppefile;
int _import_directory_count, _import_directory_size;
int _basreloc_directory_count;

// HEADERS
___IMAGE_DOS_HEADER PEFILE_DOS_HEADER;
___IMAGE_NT_HEADERS32 PEFILE_NT_HEADERS;

// DOS HEADER
DWORD PEFILE_DOS_HEADER_EMAGIC;
LONG PEFILE_DOS_HEADER_LFANEW;

// RICH HEADER
RICH_HEADER_INFO PEFILE_RICH_HEADER_INFO;
RICH_HEADER PEFILE_RICH_HEADER;

// NT_HEADERS.Signature
DWORD PEFILE_NT_HEADERS_SIGNATURE;

// NT_HEADERS.FileHeader
WORD PEFILE_NT_HEADERS_FILE_HEADER_MACHINE;
WORD PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS;
WORD PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER;

// NT_HEADERS.OptionalHeader
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE;
ULONGLONG PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS;

___IMAGE_DATA_DIRECTORY PEFILE_EXPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_RESOURCE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_EXCEPTION_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_SECURITY_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BASERELOC_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DEBUG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_ARCHITECTURE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_GLOBALPTR_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_TLS_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_LOAD_CONFIG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BOUND_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IAT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DELAY_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_COM_DESCRIPTOR_DIRECTORY;

// SECTION HEADERS
___PIMAGE_SECTION_HEADER PEFILE_SECTION_HEADERS;

// IMPORT TABLE
___PIMAGE_IMPORT_DESCRIPTOR PEFILE_IMPORT_TABLE;

// BASE RELOCATION TABLE
___PIMAGE_BASE_RELOCATION PEFILE_BASERELOC_TABLE;

// FUNCTIONS

// ADDRESS RESOLVERS
int locate(DWORD VA);
DWORD resolve(DWORD VA, int index);

// PARSERS
void ParseFile();
void ParseDOSHeader();
void ParseNTHeaders();
void ParseSectionHeaders();
void ParseImportDirectory();
void ParseBaseReloc();
void ParseRichHeader();

// PRINT INFO
void PrintFileInfo();
void PrintDOSHeaderInfo();
void PrintRichHeaderInfo();
void PrintNTHeadersInfo();
void PrintSectionHeadersInfo();
void PrintImportTableInfo();
void PrintBaseRelocationsInfo();
};

PE32FILE.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
#include "PE32FILE.h"

// CONSTRUCTOR
PE32FILE::PE32FILE(char* _NAME, FILE* _Ppefile) {

NAME = _NAME;
Ppefile = _Ppefile;

ParseFile();

}

// ADDRESS RESOLVERS
int PE32FILE::locate(DWORD VA) {

int index;

for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
if (VA >= PEFILE_SECTION_HEADERS[i].VirtualAddress
&& VA < (PEFILE_SECTION_HEADERS[i].VirtualAddress + PEFILE_SECTION_HEADERS[i].Misc.VirtualSize)) {
index = i;
break;
}
}
return index;

}

DWORD PE32FILE::resolve(DWORD VA, int index) {

return (VA - PEFILE_SECTION_HEADERS[index].VirtualAddress) + PEFILE_SECTION_HEADERS[index].PointerToRawData;

}

// PARSERS
void PE32FILE::ParseDOSHeader() {

fseek(Ppefile, 0, SEEK_SET);
fread(&PEFILE_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, Ppefile);

PEFILE_DOS_HEADER_EMAGIC = PEFILE_DOS_HEADER.e_magic;
PEFILE_DOS_HEADER_LFANEW = PEFILE_DOS_HEADER.e_lfanew;

}

void PE32FILE::ParseNTHeaders() {

fseek(Ppefile, PEFILE_DOS_HEADER.e_lfanew, SEEK_SET);
fread(&PEFILE_NT_HEADERS, sizeof(PEFILE_NT_HEADERS), 1, Ppefile);

PEFILE_NT_HEADERS_SIGNATURE = PEFILE_NT_HEADERS.Signature;

PEFILE_NT_HEADERS_FILE_HEADER_MACHINE = PEFILE_NT_HEADERS.FileHeader.Machine;
PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS = PEFILE_NT_HEADERS.FileHeader.NumberOfSections;
PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER = PEFILE_NT_HEADERS.FileHeader.SizeOfOptionalHeader;

PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC = PEFILE_NT_HEADERS.OptionalHeader.Magic;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfInitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfUninitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT = PEFILE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.BaseOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE = PEFILE_NT_HEADERS.OptionalHeader.ImageBase;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.SectionAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.FileAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfImage;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS = PEFILE_NT_HEADERS.OptionalHeader.SizeOfHeaders;

PEFILE_EXPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXPORT];
PEFILE_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IMPORT];
PEFILE_RESOURCE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_RESOURCE];
PEFILE_EXCEPTION_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXCEPTION];
PEFILE_SECURITY_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_SECURITY];
PEFILE_BASERELOC_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BASERELOC];
PEFILE_DEBUG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DEBUG];
PEFILE_ARCHITECTURE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE];
PEFILE_GLOBALPTR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_GLOBALPTR];
PEFILE_TLS_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_TLS];
PEFILE_LOAD_CONFIG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
PEFILE_BOUND_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
PEFILE_IAT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IAT];
PEFILE_DELAY_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
PEFILE_COM_DESCRIPTOR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];

}

void PE32FILE::ParseSectionHeaders() {

PEFILE_SECTION_HEADERS = new ___IMAGE_SECTION_HEADER[PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS];
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
int offset = (PEFILE_DOS_HEADER.e_lfanew + sizeof(PEFILE_NT_HEADERS)) + (i * ___IMAGE_SIZEOF_SECTION_HEADER);
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_SECTION_HEADERS[i], ___IMAGE_SIZEOF_SECTION_HEADER, 1, Ppefile);
}

}

void PE32FILE::ParseImportDirectory() {

DWORD _import_directory_address = resolve(PEFILE_IMPORT_DIRECTORY.VirtualAddress, locate(PEFILE_IMPORT_DIRECTORY.VirtualAddress));
_import_directory_count = 0;

while (true) {
___IMAGE_IMPORT_DESCRIPTOR tmp;
int offset = (_import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);

if (tmp.Name == 0x00000000 && tmp.FirstThunk == 0x00000000) {
_import_directory_count -= 1;
_import_directory_size = _import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR);
break;
}

_import_directory_count++;
}

PEFILE_IMPORT_TABLE = new ___IMAGE_IMPORT_DESCRIPTOR[_import_directory_count];

for (int i = 0; i < _import_directory_count; i++) {
int offset = (i * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_IMPORT_TABLE[i], sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
}

}

void PE32FILE::ParseBaseReloc() {

DWORD _basereloc_directory_address = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
_basreloc_directory_count = 0;
int _basereloc_size_counter = 0;

while (true) {
___IMAGE_BASE_RELOCATION tmp;

int offset = (_basereloc_size_counter + _basereloc_directory_address);

fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);

if (tmp.VirtualAddress == 0x00000000 &&
tmp.SizeOfBlock == 0x00000000) {
break;
}

_basreloc_directory_count++;
_basereloc_size_counter += tmp.SizeOfBlock;
}

PEFILE_BASERELOC_TABLE = new ___IMAGE_BASE_RELOCATION[_basreloc_directory_count];

_basereloc_size_counter = 0;

for (int i = 0; i < _basreloc_directory_count; i++) {
int offset = _basereloc_directory_address + _basereloc_size_counter;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_BASERELOC_TABLE[i], sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
_basereloc_size_counter += PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
}

}

void PE32FILE::ParseRichHeader() {

char* dataPtr = new char[PEFILE_DOS_HEADER_LFANEW];
fseek(Ppefile, 0, SEEK_SET);
fread(dataPtr, PEFILE_DOS_HEADER_LFANEW, 1, Ppefile);

int index_ = 0;

for (int i = 0; i <= PEFILE_DOS_HEADER_LFANEW; i++) {
if (dataPtr[i] == 0x52 && dataPtr[i + 1] == 0x69) {
index_ = i;
break;
}
}

if (index_ == 0) {
printf("Error while parsing Rich Header.");
PEFILE_RICH_HEADER_INFO.entries = 0;
return;
}

char key[4];
memcpy(key, dataPtr + (index_ + 4), 4);

int indexpointer = index_ - 4;
int RichHeaderSize = 0;

while (true) {
char tmpchar[4];
memcpy(tmpchar, dataPtr + indexpointer, 4);

for (int i = 0; i < 4; i++) {
tmpchar[i] = tmpchar[i] ^ key[i];
}

indexpointer -= 4;
RichHeaderSize += 4;

if (tmpchar[1] = 0x61 && tmpchar[0] == 0x44) {
break;
}
}

char* RichHeaderPtr = new char[RichHeaderSize];
memcpy(RichHeaderPtr, dataPtr + (index_ - RichHeaderSize), RichHeaderSize);

for (int i = 0; i < RichHeaderSize; i += 4) {

for (int x = 0; x < 4; x++) {
RichHeaderPtr[i + x] = RichHeaderPtr[i + x] ^ key[x];
}

}

PEFILE_RICH_HEADER_INFO.size = RichHeaderSize;
PEFILE_RICH_HEADER_INFO.ptrToBuffer = RichHeaderPtr;
PEFILE_RICH_HEADER_INFO.entries = (RichHeaderSize - 16) / 8;

delete[] dataPtr;

PEFILE_RICH_HEADER.entries = new RICH_HEADER_ENTRY[PEFILE_RICH_HEADER_INFO.entries];

for (int i = 16; i < RichHeaderSize; i += 8) {
WORD PRODID = (uint16_t)((unsigned char)RichHeaderPtr[i + 3] << 8) | (unsigned char)RichHeaderPtr[i + 2];
WORD BUILDID = (uint16_t)((unsigned char)RichHeaderPtr[i + 1] << 8) | (unsigned char)RichHeaderPtr[i];
DWORD USECOUNT = (uint32_t)((unsigned char)RichHeaderPtr[i + 7] << 24) | (unsigned char)RichHeaderPtr[i + 6] << 16 | (unsigned char)RichHeaderPtr[i + 5] << 8 | (unsigned char)RichHeaderPtr[i + 4];
PEFILE_RICH_HEADER.entries[(i / 8) - 2] = {
PRODID,
BUILDID,
USECOUNT
};

if (i + 8 >= RichHeaderSize) {
PEFILE_RICH_HEADER.entries[(i / 8) - 1] = { 0x0000, 0x0000, 0x00000000 };
}

}

delete[] PEFILE_RICH_HEADER_INFO.ptrToBuffer;

}

// PRINT INFO
void PE32FILE::PrintFileInfo() {

printf(" FILE: %s\n", NAME);
printf(" TYPE: 0x%X (PE32)\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);

}

void PE32FILE::PrintDOSHeaderInfo() {

printf(" DOS HEADER:\n");
printf(" -----------\n\n");

printf(" Magic: 0x%X\n", PEFILE_DOS_HEADER_EMAGIC);
printf(" File address of new exe header: 0x%X\n", PEFILE_DOS_HEADER_LFANEW);

}

void PE32FILE::PrintRichHeaderInfo() {

printf(" RICH HEADER:\n");
printf(" ------------\n\n");

for (int i = 0; i < PEFILE_RICH_HEADER_INFO.entries; i++) {
printf(" 0x%X 0x%X 0x%X: %d.%d.%d\n",
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount,
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount);
}

}

void PE32FILE::PrintNTHeadersInfo() {

printf(" NT HEADERS:\n");
printf(" -----------\n\n");

printf(" PE Signature: 0x%X\n", PEFILE_NT_HEADERS_SIGNATURE);

printf("\n File Header:\n\n");
printf(" Machine: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_MACHINE);
printf(" Number of sections: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS);
printf(" Size of optional header: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER);

printf("\n Optional Header:\n\n");
printf(" Magic: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
printf(" Size of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE);
printf(" Size of initialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA);
printf(" Size of uninitialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA);
printf(" Address of entry point: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT);
printf(" RVA of start of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE);
printf(" Desired image base: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE);
printf(" Section alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT);
printf(" File alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT);
printf(" Size of image: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE);
printf(" Size of headers: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS);

printf("\n Data Directories:\n");
printf("\n * Export Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXPORT_DIRECTORY.Size);

printf("\n * Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IMPORT_DIRECTORY.Size);

printf("\n * Resource Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.Size);

printf("\n * Exception Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.Size);

printf("\n * Security Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_SECURITY_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_SECURITY_DIRECTORY.Size);

printf("\n * Base Relocation Table:\n");
printf(" RVA: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.Size);

printf("\n * Debug Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_DEBUG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DEBUG_DIRECTORY.Size);

printf("\n * Architecture Specific Data:\n");
printf(" RVA: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.Size);

printf("\n * RVA of GlobalPtr:\n");
printf(" RVA: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.Size);

printf("\n * TLS Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_TLS_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_TLS_DIRECTORY.Size);

printf("\n * Load Configuration Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.Size);

printf("\n * Bound Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.Size);

printf("\n * Import Address Table:\n");
printf(" RVA: 0x%X\n", PEFILE_IAT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IAT_DIRECTORY.Size);

printf("\n * Delay Load Import Descriptors:\n");
printf(" RVA: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.Size);

printf("\n * COM Runtime Descriptor:\n");
printf(" RVA: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.Size);

}

void PE32FILE::PrintSectionHeadersInfo() {

printf(" SECTION HEADERS:\n");
printf(" ----------------\n\n");

for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
printf(" * %.8s:\n", PEFILE_SECTION_HEADERS[i].Name);
printf(" VirtualAddress: 0x%X\n", PEFILE_SECTION_HEADERS[i].VirtualAddress);
printf(" VirtualSize: 0x%X\n", PEFILE_SECTION_HEADERS[i].Misc.VirtualSize);
printf(" PointerToRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].PointerToRawData);
printf(" SizeOfRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].SizeOfRawData);
printf(" Characteristics: 0x%X\n\n", PEFILE_SECTION_HEADERS[i].Characteristics);
}

}

void PE32FILE::PrintImportTableInfo() {

printf(" IMPORT TABLE:\n");
printf(" ----------------\n\n");

for (int i = 0; i < _import_directory_count; i++) {
DWORD NameAddr = resolve(PEFILE_IMPORT_TABLE[i].Name, locate(PEFILE_IMPORT_TABLE[i].Name));
int NameSize = 0;

while (true) {
char tmp;
fseek(Ppefile, (NameAddr + NameSize), SEEK_SET);
fread(&tmp, sizeof(char), 1, Ppefile);

if (tmp == 0x00) {
break;
}

NameSize++;
}

char* Name = new char[NameSize + 2];
fseek(Ppefile, NameAddr, SEEK_SET);
fread(Name, (NameSize * sizeof(char)) + 1, 1, Ppefile);
printf(" * %s:\n", Name);
delete[] Name;

printf(" ILT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk);
printf(" IAT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].FirstThunk);

if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == 0) {
printf(" Bound: FALSE\n");
}
else if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == -1) {
printf(" Bound: TRUE\n");
}

printf("\n");

DWORD ILTAddr = resolve(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk, locate(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk));
int entrycounter = 0;

while (true) {

ILT_ENTRY_32 entry;

fseek(Ppefile, (ILTAddr + (entrycounter * sizeof(DWORD))), SEEK_SET);
fread(&entry, sizeof(ILT_ENTRY_32), 1, Ppefile);

BYTE flag = entry.FIELD_1.ORDINAL_NAME_FLAG;
DWORD HintRVA = 0x0;
WORD ordinal = 0x0;

if (flag == 0x0) {
HintRVA = entry.FIELD_1.HINT_NAME_TABE;
}
else if (flag == 0x01) {
ordinal = entry.FIELD_1.ORDINAL;
}

if (flag == 0x0 && HintRVA == 0x0 && ordinal == 0x0) {
break;
}

printf("\n Entry:\n");

if (flag == 0x0) {
___IMAGE_IMPORT_BY_NAME hint;

DWORD HintAddr = resolve(HintRVA, locate(HintRVA));
fseek(Ppefile, HintAddr, SEEK_SET);
fread(&hint, sizeof(___IMAGE_IMPORT_BY_NAME), 1, Ppefile);
printf(" Name: %s\n", hint.Name);
printf(" Hint RVA: 0x%X\n", HintRVA);
printf(" Hint: 0x%X\n", hint.Hint);
}
else if (flag == 1) {
printf(" Ordinal: 0x%X\n", ordinal);
}

entrycounter++;
}

printf("\n ----------------------\n\n");

}

}

void PE32FILE::PrintBaseRelocationsInfo() {

printf(" BASE RELOCATIONS TABLE:\n");
printf(" -----------------------\n");

int szCounter = sizeof(___IMAGE_BASE_RELOCATION);

for (int i = 0; i < _basreloc_directory_count; i++) {

DWORD PAGERVA, BLOCKSIZE, BASE_RELOC_ADDR;
int ENTRIES;

BASE_RELOC_ADDR = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
PAGERVA = PEFILE_BASERELOC_TABLE[i].VirtualAddress;
BLOCKSIZE = PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
ENTRIES = (BLOCKSIZE - sizeof(___IMAGE_BASE_RELOCATION)) / sizeof(WORD);

printf("\n Block 0x%X: \n", i);
printf(" Page RVA: 0x%X\n", PAGERVA);
printf(" Block size: 0x%X\n", BLOCKSIZE);
printf(" Number of entries: 0x%X\n", ENTRIES);
printf("\n Entries:\n");

for (int i = 0; i < ENTRIES; i++) {

BASE_RELOC_ENTRY entry;

int offset = (BASE_RELOC_ADDR + szCounter + (i * sizeof(WORD)));

fseek(Ppefile, offset, SEEK_SET);
fread(&entry, sizeof(WORD), 1, Ppefile);

printf("\n * Value: 0x%X\n", entry);
printf(" Relocation Type: 0x%X\n", entry.TYPE);
printf(" Offset: 0x%X\n", entry.OFFSET);

}
printf("\n ----------------------\n\n");
szCounter += BLOCKSIZE;
}

}

// MAIN
void PE32FILE::ParseFile() {

// PARSE DOS HEADER
ParseDOSHeader();

// PARSE RICH HEADER
ParseRichHeader();

//PARSE NT HEADERS
ParseNTHeaders();

// PARSE SECTION HEADERS
ParseSectionHeaders();

// PARSE IMPORT DIRECTORY
ParseImportDirectory();

// PARSE BASE RELOCATIONS
ParseBaseReloc();

}

void PE32FILE::PrintInfo() {

printf("\n\n");

PrintFileInfo();
printf("\n ----------------------------------\n\n");

PrintDOSHeaderInfo();
printf("\n ----------------------------------\n\n");

PrintRichHeaderInfo();
printf("\n ----------------------------------\n\n");

PrintNTHeadersInfo();
printf("\n ----------------------------------\n\n");

PrintSectionHeadersInfo();
printf("\n ----------------------------------\n\n");

PrintImportTableInfo();
printf("\n ----------------------------------\n\n");

PrintBaseRelocationsInfo();
printf("\n ----------------------------------\n\n");

return;

}

PE64FILE.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#pragma once
#include "winntdef.h"
#include "PEFILE_CUSTOM_STRUCTS.h"
#include <string>

class PE64FILE
{
public:
PE64FILE(char* _NAME, FILE* Ppefile);

void PrintInfo();

private:
char* NAME;
FILE* Ppefile;
int _import_directory_count, _import_directory_size;
int _basreloc_directory_count;

// HEADERS
___IMAGE_DOS_HEADER PEFILE_DOS_HEADER;
___IMAGE_NT_HEADERS64 PEFILE_NT_HEADERS;

// DOS HEADER
DWORD PEFILE_DOS_HEADER_EMAGIC;
LONG PEFILE_DOS_HEADER_LFANEW;

// RICH HEADER
RICH_HEADER_INFO PEFILE_RICH_HEADER_INFO;
RICH_HEADER PEFILE_RICH_HEADER;

// NT_HEADERS.Signature
DWORD PEFILE_NT_HEADERS_SIGNATURE;

// NT_HEADERS.FileHeader
WORD PEFILE_NT_HEADERS_FILE_HEADER_MACHINE;
WORD PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS;
WORD PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER;

// NT_HEADERS.OptionalHeader
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE;
ULONGLONG PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS;

___IMAGE_DATA_DIRECTORY PEFILE_EXPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_RESOURCE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_EXCEPTION_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_SECURITY_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BASERELOC_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DEBUG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_ARCHITECTURE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_GLOBALPTR_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_TLS_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_LOAD_CONFIG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BOUND_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IAT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DELAY_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_COM_DESCRIPTOR_DIRECTORY;

// SECTION HEADERS
___PIMAGE_SECTION_HEADER PEFILE_SECTION_HEADERS;

// IMPORT TABLE
___PIMAGE_IMPORT_DESCRIPTOR PEFILE_IMPORT_TABLE;

// BASE RELOCATION TABLE
___PIMAGE_BASE_RELOCATION PEFILE_BASERELOC_TABLE;

// FUNCTIONS

// ADDRESS RESOLVERS
int locate(DWORD VA);
DWORD resolve(DWORD VA, int index);

// PARSERS
void ParseFile();
void ParseDOSHeader();
void ParseNTHeaders();
void ParseSectionHeaders();
void ParseImportDirectory();
void ParseBaseReloc();
void ParseRichHeader();

// PRINT INFO
void PrintFileInfo();
void PrintDOSHeaderInfo();
void PrintRichHeaderInfo();
void PrintNTHeadersInfo();
void PrintSectionHeadersInfo();
void PrintImportTableInfo();
void PrintBaseRelocationsInfo();
};

PE64FILE.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
#include "PE64FILE.h"

// CONSTRUCTOR
PE64FILE::PE64FILE(char* _NAME, FILE* _Ppefile) {

NAME = _NAME;
Ppefile = _Ppefile;

ParseFile();

}

// ADDRESS RESOLVERS
int PE64FILE::locate(DWORD VA) {

int index;

for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
if (VA >= PEFILE_SECTION_HEADERS[i].VirtualAddress
&& VA < (PEFILE_SECTION_HEADERS[i].VirtualAddress + PEFILE_SECTION_HEADERS[i].Misc.VirtualSize)) {
index = i;
break;
}
}
return index;
}

DWORD PE64FILE::resolve(DWORD VA, int index) {

return (VA - PEFILE_SECTION_HEADERS[index].VirtualAddress) + PEFILE_SECTION_HEADERS[index].PointerToRawData;

}

// PARSERS
void PE64FILE::ParseDOSHeader() {

fseek(Ppefile, 0, SEEK_SET);
fread(&PEFILE_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, Ppefile);

PEFILE_DOS_HEADER_EMAGIC = PEFILE_DOS_HEADER.e_magic;
PEFILE_DOS_HEADER_LFANEW = PEFILE_DOS_HEADER.e_lfanew;

}

void PE64FILE::ParseNTHeaders() {

fseek(Ppefile, PEFILE_DOS_HEADER.e_lfanew, SEEK_SET);
fread(&PEFILE_NT_HEADERS, sizeof(PEFILE_NT_HEADERS), 1, Ppefile);

PEFILE_NT_HEADERS_SIGNATURE = PEFILE_NT_HEADERS.Signature;

PEFILE_NT_HEADERS_FILE_HEADER_MACHINE = PEFILE_NT_HEADERS.FileHeader.Machine;
PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS = PEFILE_NT_HEADERS.FileHeader.NumberOfSections;
PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER = PEFILE_NT_HEADERS.FileHeader.SizeOfOptionalHeader;

PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC = PEFILE_NT_HEADERS.OptionalHeader.Magic;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfInitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfUninitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT = PEFILE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.BaseOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE = PEFILE_NT_HEADERS.OptionalHeader.ImageBase;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.SectionAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.FileAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfImage;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS = PEFILE_NT_HEADERS.OptionalHeader.SizeOfHeaders;

PEFILE_EXPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXPORT];
PEFILE_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IMPORT];
PEFILE_RESOURCE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_RESOURCE];
PEFILE_EXCEPTION_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXCEPTION];
PEFILE_SECURITY_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_SECURITY];
PEFILE_BASERELOC_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BASERELOC];
PEFILE_DEBUG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DEBUG];
PEFILE_ARCHITECTURE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE];
PEFILE_GLOBALPTR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_GLOBALPTR];
PEFILE_TLS_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_TLS];
PEFILE_LOAD_CONFIG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
PEFILE_BOUND_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
PEFILE_IAT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IAT];
PEFILE_DELAY_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
PEFILE_COM_DESCRIPTOR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];

}

void PE64FILE::ParseSectionHeaders() {

PEFILE_SECTION_HEADERS = new ___IMAGE_SECTION_HEADER[PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS];
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
int offset = (PEFILE_DOS_HEADER.e_lfanew + sizeof(PEFILE_NT_HEADERS)) + (i * ___IMAGE_SIZEOF_SECTION_HEADER);
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_SECTION_HEADERS[i], ___IMAGE_SIZEOF_SECTION_HEADER, 1, Ppefile);
}

}

void PE64FILE::ParseImportDirectory() {

DWORD _import_directory_address = resolve(PEFILE_IMPORT_DIRECTORY.VirtualAddress, locate(PEFILE_IMPORT_DIRECTORY.VirtualAddress));
_import_directory_count = 0;

while (true) {
___IMAGE_IMPORT_DESCRIPTOR tmp;
int offset = (_import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);

if (tmp.Name == 0x00000000 && tmp.FirstThunk == 0x00000000) {
_import_directory_count -= 1;
_import_directory_size = _import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR);
break;
}

_import_directory_count++;
}

PEFILE_IMPORT_TABLE = new ___IMAGE_IMPORT_DESCRIPTOR[_import_directory_count];

for (int i = 0; i < _import_directory_count; i++) {
int offset = (i * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_IMPORT_TABLE[i], sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
}

}

void PE64FILE::ParseBaseReloc() {

DWORD _basereloc_directory_address = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
_basreloc_directory_count = 0;
int _basereloc_size_counter = 0;

while (true) {
___IMAGE_BASE_RELOCATION tmp;

int offset = (_basereloc_size_counter + _basereloc_directory_address);

fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);

if (tmp.VirtualAddress == 0x00000000 &&
tmp.SizeOfBlock == 0x00000000) {
break;
}

_basreloc_directory_count++;
_basereloc_size_counter += tmp.SizeOfBlock;
}

PEFILE_BASERELOC_TABLE = new ___IMAGE_BASE_RELOCATION[_basreloc_directory_count];

_basereloc_size_counter = 0;

for (int i = 0; i < _basreloc_directory_count; i++) {
int offset = _basereloc_directory_address + _basereloc_size_counter;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_BASERELOC_TABLE[i], sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
_basereloc_size_counter += PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
}

}

void PE64FILE::ParseRichHeader() {

char* dataPtr = new char[PEFILE_DOS_HEADER_LFANEW];
fseek(Ppefile, 0, SEEK_SET);
fread(dataPtr, PEFILE_DOS_HEADER_LFANEW, 1, Ppefile);

int index_ = 0;

for (int i = 0; i <= PEFILE_DOS_HEADER_LFANEW; i++) {
if (dataPtr[i] == 0x52 && dataPtr[i + 1] == 0x69) {
index_ = i;
break;
}
}

if (index_ == 0) {
printf("Error while parsing Rich Header.");
PEFILE_RICH_HEADER_INFO.entries = 0;
return;
}

char key[4];
memcpy(key, dataPtr + (index_ + 4), 4);

int indexpointer = index_ - 4;
int RichHeaderSize = 0;

while (true) {
char tmpchar[4];
memcpy(tmpchar, dataPtr + indexpointer, 4);

for (int i = 0; i < 4; i++) {
tmpchar[i] = tmpchar[i] ^ key[i];
}

indexpointer -= 4;
RichHeaderSize += 4;

if (tmpchar[1] = 0x61 && tmpchar[0] == 0x44) {
break;
}
}

char* RichHeaderPtr = new char[RichHeaderSize];
memcpy(RichHeaderPtr, dataPtr + (index_ - RichHeaderSize), RichHeaderSize);

for (int i = 0; i < RichHeaderSize; i += 4) {

for (int x = 0; x < 4; x++) {
RichHeaderPtr[i + x] = RichHeaderPtr[i + x] ^ key[x];
}

}

PEFILE_RICH_HEADER_INFO.size = RichHeaderSize;
PEFILE_RICH_HEADER_INFO.ptrToBuffer = RichHeaderPtr;
PEFILE_RICH_HEADER_INFO.entries = (RichHeaderSize - 16) / 8;

delete[] dataPtr;

PEFILE_RICH_HEADER.entries = new RICH_HEADER_ENTRY[PEFILE_RICH_HEADER_INFO.entries];

for (int i = 16; i < RichHeaderSize; i += 8) {
WORD PRODID = (uint16_t)((unsigned char)RichHeaderPtr[i + 3] << 8) | (unsigned char)RichHeaderPtr[i + 2];
WORD BUILDID = (uint16_t)((unsigned char)RichHeaderPtr[i + 1] << 8) | (unsigned char)RichHeaderPtr[i];
DWORD USECOUNT = (uint32_t)((unsigned char)RichHeaderPtr[i + 7] << 24) | (unsigned char)RichHeaderPtr[i + 6] << 16 | (unsigned char)RichHeaderPtr[i + 5] << 8 | (unsigned char)RichHeaderPtr[i + 4];
PEFILE_RICH_HEADER.entries[(i / 8) - 2] = {
PRODID,
BUILDID,
USECOUNT
};

if (i + 8 >= RichHeaderSize) {
PEFILE_RICH_HEADER.entries[(i / 8) - 1] = { 0x0000, 0x0000, 0x00000000 };
}

}

delete[] PEFILE_RICH_HEADER_INFO.ptrToBuffer;

}

// PRINT INFO
void PE64FILE::PrintFileInfo() {

printf(" FILE: %s\n", NAME);
printf(" TYPE: 0x%X (PE32+)\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);

}

void PE64FILE::PrintDOSHeaderInfo() {

printf(" DOS HEADER:\n");
printf(" -----------\n\n");

printf(" Magic: 0x%X\n", PEFILE_DOS_HEADER_EMAGIC);
printf(" File address of new exe header: 0x%X\n", PEFILE_DOS_HEADER_LFANEW);

}

void PE64FILE::PrintRichHeaderInfo() {

printf(" RICH HEADER:\n");
printf(" ------------\n\n");

for (int i = 0; i < PEFILE_RICH_HEADER_INFO.entries; i++) {
printf(" 0x%X 0x%X 0x%X: %d.%d.%d\n",
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount,
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount);
}

}

void PE64FILE::PrintNTHeadersInfo() {

printf(" NT HEADERS:\n");
printf(" -----------\n\n");

printf(" PE Signature: 0x%X\n", PEFILE_NT_HEADERS_SIGNATURE);

printf("\n File Header:\n\n");
printf(" Machine: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_MACHINE);
printf(" Number of sections: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS);
printf(" Size of optional header: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER);

printf("\n Optional Header:\n\n");
printf(" Magic: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
printf(" Size of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE);
printf(" Size of initialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA);
printf(" Size of uninitialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA);
printf(" Address of entry point: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT);
printf(" RVA of start of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE);
printf(" Desired image base: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE);
printf(" Section alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT);
printf(" File alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT);
printf(" Size of image: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE);
printf(" Size of headers: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS);

printf("\n Data Directories:\n");
printf("\n * Export Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXPORT_DIRECTORY.Size);

printf("\n * Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IMPORT_DIRECTORY.Size);

printf("\n * Resource Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.Size);

printf("\n * Exception Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.Size);

printf("\n * Security Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_SECURITY_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_SECURITY_DIRECTORY.Size);

printf("\n * Base Relocation Table:\n");
printf(" RVA: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.Size);

printf("\n * Debug Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_DEBUG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DEBUG_DIRECTORY.Size);

printf("\n * Architecture Specific Data:\n");
printf(" RVA: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.Size);

printf("\n * RVA of GlobalPtr:\n");
printf(" RVA: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.Size);

printf("\n * TLS Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_TLS_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_TLS_DIRECTORY.Size);

printf("\n * Load Configuration Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.Size);

printf("\n * Bound Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.Size);

printf("\n * Import Address Table:\n");
printf(" RVA: 0x%X\n", PEFILE_IAT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IAT_DIRECTORY.Size);

printf("\n * Delay Load Import Descriptors:\n");
printf(" RVA: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.Size);

printf("\n * COM Runtime Descriptor:\n");
printf(" RVA: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.Size);

}

void PE64FILE::PrintSectionHeadersInfo() {

printf(" SECTION HEADERS:\n");
printf(" ----------------\n\n");

for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
printf(" * %.8s:\n", PEFILE_SECTION_HEADERS[i].Name);
printf(" VirtualAddress: 0x%X\n", PEFILE_SECTION_HEADERS[i].VirtualAddress);
printf(" VirtualSize: 0x%X\n", PEFILE_SECTION_HEADERS[i].Misc.VirtualSize);
printf(" PointerToRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].PointerToRawData);
printf(" SizeOfRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].SizeOfRawData);
printf(" Characteristics: 0x%X\n\n", PEFILE_SECTION_HEADERS[i].Characteristics);
}

}

void PE64FILE::PrintImportTableInfo() {

printf(" IMPORT TABLE:\n");
printf(" ----------------\n\n");

for (int i = 0; i < _import_directory_count; i++) {
DWORD NameAddr = resolve(PEFILE_IMPORT_TABLE[i].Name, locate(PEFILE_IMPORT_TABLE[i].Name));
int NameSize = 0;

while (true) {
char tmp;
fseek(Ppefile, (NameAddr + NameSize), SEEK_SET);
fread(&tmp, sizeof(char), 1, Ppefile);

if (tmp == 0x00) {
break;
}

NameSize++;
}

char* Name = new char[NameSize + 2];
fseek(Ppefile, NameAddr, SEEK_SET);
fread(Name, (NameSize * sizeof(char)) + 1, 1, Ppefile);
printf(" * %s:\n", Name);
delete[] Name;

printf(" ILT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk);
printf(" IAT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].FirstThunk);

if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == 0) {
printf(" Bound: FALSE\n");
}
else if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == -1) {
printf(" Bound: TRUE\n");
}

printf("\n");

DWORD ILTAddr = resolve(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk, locate(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk));
int entrycounter = 0;

while (true) {

ILT_ENTRY_64 entry;

fseek(Ppefile, (ILTAddr + (entrycounter * sizeof(QWORD))), SEEK_SET);
fread(&entry, sizeof(ILT_ENTRY_64), 1, Ppefile);

BYTE flag = entry.ORDINAL_NAME_FLAG;
DWORD HintRVA = 0x0;
WORD ordinal = 0x0;

if (flag == 0x0) {
HintRVA = entry.FIELD_2.HINT_NAME_TABE;
}
else if (flag == 0x01) {
ordinal = entry.FIELD_2.ORDINAL;
}

if (flag == 0x0 && HintRVA == 0x0 && ordinal == 0x0) {
break;
}

printf("\n Entry:\n");

if (flag == 0x0) {
___IMAGE_IMPORT_BY_NAME hint;

DWORD HintAddr = resolve(HintRVA, locate(HintRVA));
fseek(Ppefile, HintAddr, SEEK_SET);
fread(&hint, sizeof(___IMAGE_IMPORT_BY_NAME), 1, Ppefile);
printf(" Name: %s\n", hint.Name);
printf(" Hint RVA: 0x%X\n", HintRVA);
printf(" Hint: 0x%X\n", hint.Hint);
}
else if (flag == 1) {
printf(" Ordinal: 0x%X\n", ordinal);
}

entrycounter++;
}

printf("\n ----------------------\n\n");

}

}

void PE64FILE::PrintBaseRelocationsInfo() {

printf(" BASE RELOCATIONS TABLE:\n");
printf(" -----------------------\n");

int szCounter = sizeof(___IMAGE_BASE_RELOCATION);

for (int i = 0; i < _basreloc_directory_count; i++) {

DWORD PAGERVA, BLOCKSIZE, BASE_RELOC_ADDR;
int ENTRIES;

BASE_RELOC_ADDR = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
PAGERVA = PEFILE_BASERELOC_TABLE[i].VirtualAddress;
BLOCKSIZE = PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
ENTRIES = (BLOCKSIZE - sizeof(___IMAGE_BASE_RELOCATION)) / sizeof(WORD);

printf("\n Block 0x%X: \n", i);
printf(" Page RVA: 0x%X\n", PAGERVA);
printf(" Block size: 0x%X\n", BLOCKSIZE);
printf(" Number of entries: 0x%X\n", ENTRIES);
printf("\n Entries:\n");

for (int i = 0; i < ENTRIES; i++) {

BASE_RELOC_ENTRY entry;

int offset = (BASE_RELOC_ADDR + szCounter + (i * sizeof(WORD)));

fseek(Ppefile, offset, SEEK_SET);
fread(&entry, sizeof(WORD), 1, Ppefile);

printf("\n * Value: 0x%X\n", entry);
printf(" Relocation Type: 0x%X\n", entry.TYPE);
printf(" Offset: 0x%X\n", entry.OFFSET);

}
printf("\n ----------------------\n\n");
szCounter += BLOCKSIZE;
}

}

// MAIN
void PE64FILE::ParseFile() {

// PARSE DOS HEADER
ParseDOSHeader();

// PARSE RICH HEADER
ParseRichHeader();

//PARSE NT HEADERS
ParseNTHeaders();

// PARSE SECTION HEADERS
ParseSectionHeaders();

// PARSE IMPORT DIRECTORY
ParseImportDirectory();

// PARSE BASE RELOCATIONS
ParseBaseReloc();

}

void PE64FILE::PrintInfo() {

printf("\n\n");

PrintFileInfo();
printf("\n ----------------------------------\n\n");

PrintDOSHeaderInfo();
printf("\n ----------------------------------\n\n");

PrintRichHeaderInfo();
printf("\n ----------------------------------\n\n");

PrintNTHeadersInfo();
printf("\n ----------------------------------\n\n");

PrintSectionHeadersInfo();
printf("\n ----------------------------------\n\n");

PrintImportTableInfo();
printf("\n ----------------------------------\n\n");

PrintBaseRelocationsInfo();
printf("\n ----------------------------------\n\n");

return;

}

最终效果如下
image

代码放到:https://github.com/ybdt/evasion-hub/tree/master/Misc/PE-Parser