HyperDbg Debugger
Loading...
Searching...
No Matches
pe-parser.cpp File Reference

Portable Executable parser. More...

#include "pch.h"

Functions

VOID PeHexDump (CHAR *Ptr, int Size, int SecAddress)
 Show hex dump of sections of PE.
 
BOOLEAN PeShowSectionInformationAndDump (const WCHAR *AddressOfFile, const CHAR *SectionToShow, BOOLEAN Is32Bit)
 Show information about different sections of PE and the dump of sections.
 
BOOLEAN PeIsPE32BitOr64Bit (const WCHAR *AddressOfFile, PBOOLEAN Is32Bit)
 Detect whether PE is a 32-bit PE or 64-bit PE.
 

Detailed Description

Portable Executable parser.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2021-12-26

Function Documentation

◆ PeHexDump()

VOID PeHexDump ( CHAR * Ptr,
int Size,
int SecAddress )

Show hex dump of sections of PE.

Parameters
Ptr
Size
SecAddress
Returns
VOID
24{
25 int i = 1, Temp = 0;
26
27 //
28 // Buffer to store the character dump displayed at the
29 // right side
30 //
31 wchar_t Buf[18];
32 ShowMessages("\n\n%x: |", SecAddress);
33
34 Buf[Temp] = ' '; // initial space
35 Buf[Temp + 16] = ' '; // final space
36 Buf[Temp + 17] = 0; // End of Buf
37 Temp++; // Temp = 1;
38
39 for (; i <= Size; i++, Ptr++, Temp++)
40 {
41 Buf[Temp] = !iswcntrl((*Ptr) & 0xff) ? (*Ptr) & 0xff : '.';
42 ShowMessages("%-3.2x", (*Ptr) & 0xff);
43
44 if (i % 16 == 0)
45 {
46 //
47 // print the character dump to the right
48 //
49 _putws(Buf);
50 if (i + 1 <= Size)
51 ShowMessages("%x: ", SecAddress += 16);
52 Temp = 0;
53 }
54 if (i % 4 == 0)
55 ShowMessages("| ");
56 }
57 if (i % 16 != 0)
58 {
59 Buf[Temp] = 0;
60 for (; i % 16 != 0; i++)
61 ShowMessages("%-3.2c", ' ');
62 _putws(Buf);
63 }
64}
VOID ShowMessages(const char *Fmt,...)
Show messages.
Definition libhyperdbg.cpp:96

◆ PeIsPE32BitOr64Bit()

BOOLEAN PeIsPE32BitOr64Bit ( const WCHAR * AddressOfFile,
PBOOLEAN Is32Bit )

Detect whether PE is a 32-bit PE or 64-bit PE.

Parameters
AddressOfFile
Is32Bit
Returns
BOOLEAN
483{
484 BOOLEAN Result = FALSE;
485 HANDLE MapObjectHandle, FileHandle; // File Mapping Object
486 LPVOID BaseAddr; // Pointer to the base memory of mapped file
487 PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header
488 PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit
489 IMAGE_OPTIONAL_HEADER32 OpHeader32; // Optional Header of PE files present in NT Header structure
490 IMAGE_FILE_HEADER Header; // Pointer to image file header of NT Header
491
492 //
493 // Open the EXE File
494 //
495 FileHandle = CreateFileW(AddressOfFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
496 if (FileHandle == INVALID_HANDLE_VALUE)
497 {
498 ShowMessages("err, unable to read the file (%x)\n", GetLastError());
499 return FALSE;
500 };
501
502 //
503 // Mapping Given EXE file to Memory
504 //
505 MapObjectHandle =
506 CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
507
508 if (MapObjectHandle == NULL)
509 {
510 CloseHandle(FileHandle);
511
512 ShowMessages("err, unable to create file mappings (%x)\n", GetLastError());
513 return FALSE;
514 }
515
516 BaseAddr = MapViewOfFile(MapObjectHandle, FILE_MAP_READ, 0, 0, 0);
517
518 if (BaseAddr == NULL)
519 {
520 CloseHandle(FileHandle);
521
522 ShowMessages("err, unable to create map view of file (%x)\n", GetLastError());
523 return FALSE;
524 }
525
526 //
527 // Get the DOS Header Base
528 //
529 DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000
530
531 //
532 // Check for Valid DOS file
533 //
534 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
535 {
536 Result = FALSE;
537
538 ShowMessages("err, the selected file is not in a valid PE format\n");
539 goto Finished;
540 }
541
542 //
543 // Offset of NT Header is found at 0x3c location in DOS header specified by
544 // e_lfanew
545 // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE
546 // header
547 //
548
549 NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew));
550
551 //
552 // Identify for valid PE file
553 //
554 if (NtHeader32->Signature != IMAGE_NT_SIGNATURE)
555 {
556 Result = FALSE;
557
558 ShowMessages("err, invalid image NT signature\n");
559 goto Finished;
560 }
561
562 //
563 // Info about Optional Header
564 //
565 OpHeader32 = NtHeader32->OptionalHeader;
566
567 //
568 // Get the IMAGE FILE HEADER Structure
569 //
570 Header = NtHeader32->FileHeader;
571
572 //
573 // Only few are determined (for remaining refer
574 // to the above specification)
575 //
576 switch (Header.Machine)
577 {
578 case IMAGE_FILE_MACHINE_I386:
579 *Is32Bit = TRUE;
580 Result = TRUE;
581 goto Finished;
582 break;
583 case IMAGE_FILE_MACHINE_AMD64:
584 *Is32Bit = FALSE;
585 Result = TRUE;
586 goto Finished;
587 break;
588 default:
589 ShowMessages("err, PE file is not i386 or AMD64; thus, it's not supported "
590 "in HyperDbg\n");
591 Result = FALSE;
592 goto Finished;
593 break;
594 }
595
596Finished:
597 //
598 // Unmap and close the handles
599 //
600 UnmapViewOfFile(BaseAddr);
601 CloseHandle(MapObjectHandle);
602
603 return Result;
604}
UCHAR BOOLEAN
Definition BasicTypes.h:39
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
unsigned __int64 UINT64
Definition BasicTypes.h:21
PHANDLE FileHandle
Definition Hooks.h:129
#define IMAGE_NT_SIGNATURE
Definition Hooks.h:47
#define IMAGE_DOS_SIGNATURE
Special signatures.
Definition Hooks.h:43
NULL()
Definition test-case-generator.py:530

◆ PeShowSectionInformationAndDump()

BOOLEAN PeShowSectionInformationAndDump ( const WCHAR * AddressOfFile,
const CHAR * SectionToShow,
BOOLEAN Is32Bit )

Show information about different sections of PE and the dump of sections.

Parameters
AddressOfFile
SectionToShow
Is32Bit
Returns
BOOLEAN
76{
77 BOOLEAN Result = FALSE;
78 HANDLE MapObjectHandle, FileHandle; // File Mapping Object
79 UINT32 NumberOfSections; // Number of sections
80 LPVOID BaseAddr; // Pointer to the base memory of mapped file
81 PIMAGE_DOS_HEADER DosHeader; // Pointer to DOS Header
82 PIMAGE_NT_HEADERS32 NtHeader32 = NULL; // Pointer to NT Header 32 bit
83 PIMAGE_NT_HEADERS64 NtHeader64 = NULL; // Pointer to NT Header 64 bit
84 IMAGE_FILE_HEADER Header; // Pointer to image file header of NT Header
85 IMAGE_OPTIONAL_HEADER32 OpHeader32; // Optional Header of PE files present in NT Header structure
86 IMAGE_OPTIONAL_HEADER64 OpHeader64; // Optional Header of PE files present in NT Header structure
87 PIMAGE_SECTION_HEADER SecHeader; // Section Header or Section Table Header
88
89 //
90 // Open the EXE File
91 //
92 FileHandle = CreateFileW(AddressOfFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
93 if (FileHandle == INVALID_HANDLE_VALUE)
94 {
95 ShowMessages("err, could not open the file specified\n");
96 return FALSE;
97 };
98
99 //
100 // Mapping Given EXE file to Memory
101 //
102 MapObjectHandle =
103 CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
104
105 if (MapObjectHandle == NULL)
106 {
107 CloseHandle(FileHandle);
108 return FALSE;
109 }
110
111 BaseAddr = MapViewOfFile(MapObjectHandle, FILE_MAP_READ, 0, 0, 0);
112
113 if (BaseAddr == NULL)
114 {
115 CloseHandle(FileHandle);
116 return FALSE;
117 }
118
119 //
120 // Get the DOS Header Base
121 //
122 DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; // 0x04000000
123
124 //
125 // Check for Valid DOS file
126 //
127 if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE)
128 {
129 //
130 // Dump the Dos Header info
131 //
132 ShowMessages("\nValid Dos Exe File\n------------------\n");
133 ShowMessages("\nDumping DOS Header Info....\n---------------------------");
134 ShowMessages("\n%-36s%s ",
135 "Magic number : ",
136 DosHeader->e_magic == 0x5a4d ? "MZ" : "-");
137 ShowMessages("\n%-36s%#x", "Bytes on last page of file :", DosHeader->e_cblp);
138 ShowMessages("\n%-36s%#x", "Pages in file : ", DosHeader->e_cp);
139 ShowMessages("\n%-36s%#x", "Relocation : ", DosHeader->e_crlc);
140 ShowMessages("\n%-36s%#x",
141 "Size of header in paragraphs : ",
142 DosHeader->e_cparhdr);
143 ShowMessages("\n%-36s%#x",
144 "Minimum extra paragraphs needed : ",
145 DosHeader->e_minalloc);
146 ShowMessages("\n%-36s%#x",
147 "Maximum extra paragraphs needed : ",
148 DosHeader->e_maxalloc);
149 ShowMessages("\n%-36s%#x", "Initial (relative) SS value : ", DosHeader->e_ss);
150 ShowMessages("\n%-36s%#x", "Initial SP value : ", DosHeader->e_sp);
151 ShowMessages("\n%-36s%#x", "Checksum : ", DosHeader->e_csum);
152 ShowMessages("\n%-36s%#x", "Initial IP value : ", DosHeader->e_ip);
153 ShowMessages("\n%-36s%#x", "Initial (relative) CS value : ", DosHeader->e_cs);
154 ShowMessages("\n%-36s%#x",
155 "File address of relocation table : ",
156 DosHeader->e_lfarlc);
157 ShowMessages("\n%-36s%#x", "Overlay number : ", DosHeader->e_ovno);
158 ShowMessages("\n%-36s%#x", "OEM identifier : ", DosHeader->e_oemid);
159 ShowMessages("\n%-36s%#x",
160 "OEM information(e_oemid specific) :",
161 DosHeader->e_oeminfo);
162 ShowMessages("\n%-36s%#x", "RVA address of PE header : ", DosHeader->e_lfanew);
163 ShowMessages("\n==============================================================="
164 "================\n");
165 }
166 else
167 {
168 ShowMessages("\nGiven File is not a valid DOS file\n");
169 Result = FALSE;
170 goto Finished;
171 }
172
173 //
174 // Offset of NT Header is found at 0x3c location in DOS header specified by
175 // e_lfanew
176 // Get the Base of NT Header(PE Header) = DosHeader + RVA address of PE
177 // header
178 //
179 if (Is32Bit)
180 {
181 NtHeader32 = (PIMAGE_NT_HEADERS32)((UINT64)(DosHeader) + (DosHeader->e_lfanew));
182 }
183 else
184 {
185 NtHeader64 = (PIMAGE_NT_HEADERS64)((UINT64)(DosHeader) + (DosHeader->e_lfanew));
186 }
187
188 //
189 // Identify for valid PE file
190 //
191 if (Is32Bit && NtHeader32->Signature == IMAGE_NT_SIGNATURE)
192 {
193 ShowMessages("\nValid PE32 file \n-------------\n");
194 }
195 else if (!Is32Bit && NtHeader64->Signature == IMAGE_NT_SIGNATURE)
196 {
197 ShowMessages("\nValid PE64 file \n-------------\n");
198 }
199 else
200 {
201 ShowMessages("err, the specified file is not a valid PE file");
202 Result = FALSE;
203 goto Finished;
204 }
205
206 //
207 // Dump NT Header Info....
208 //
209 ShowMessages("\nDumping COFF/PE Header "
210 "Info....\n--------------------------------");
211 ShowMessages("\n%-36s%s", "Signature :", "PE");
212
213 //
214 // Get the IMAGE FILE HEADER Structure
215 //
216 if (Is32Bit)
217 {
218 Header = NtHeader32->FileHeader;
219 }
220 else
221 {
222 Header = NtHeader64->FileHeader;
223 }
224
225 //
226 // Determine Machine Architecture
227 //
228 ShowMessages("\n%-36s", "Machine Architecture :");
229
230 //
231 // Only few are determined (for remaining refer
232 // to the above specification)
233 //
234 switch (Header.Machine)
235 {
236 case 0x0:
237 ShowMessages("All ");
238 break;
239 case 0x14d:
240 ShowMessages("Intel i860");
241 break;
242 case 0x14c:
243 ShowMessages("Intel i386, i486, i586");
244 break;
245 case 0x200:
246 ShowMessages("Intel Itanium processor");
247 break;
248 case 0x8664:
249 ShowMessages("AMD x64");
250 break;
251 case 0x162:
252 ShowMessages("MIPS R3000");
253 break;
254 case 0x166:
255 ShowMessages("MIPS R4000");
256 break;
257 case 0x183:
258 ShowMessages("DEC Alpha AXP");
259 break;
260 default:
261 ShowMessages("Not Found");
262 break;
263 }
264
265 //
266 // Determine the characteristics of the given file
267 //
268 ShowMessages("\n%-36s", "Characteristics : ");
269 if ((Header.Characteristics & 0x0002) == 0x0002)
270 ShowMessages("Executable Image, ");
271 if ((Header.Characteristics & 0x0020) == 0x0020)
272 ShowMessages("Application can address > 2GB, ");
273 if ((Header.Characteristics & 0x1000) == 0x1000)
274 ShowMessages("System file (Kernel Mode Driver(I think)), ");
275 if ((Header.Characteristics & 0x2000) == 0x2000)
276 ShowMessages("Dll file, ");
277 if ((Header.Characteristics & 0x4000) == 0x4000)
278 ShowMessages("Application runs only in Uniprocessor, ");
279
280 //
281 // Determine Time Stamp
282 //
283 ShowMessages("\n%-36s%s",
284 "Time Stamp :",
285 ctime((const time_t *)&(Header.TimeDateStamp)));
286
287 //
288 // Determine number of sections
289 //
290 ShowMessages("%-36s%d", "No.sections(size) :", Header.NumberOfSections);
291 ShowMessages("\n%-36s%d", "No.entries in symbol table :", Header.NumberOfSymbols);
292 ShowMessages("\n%-36s%d",
293 "Size of optional header :",
294 Header.SizeOfOptionalHeader);
295
296 ShowMessages("\n\nDumping PE Optional Header "
297 "Info....\n-----------------------------------");
298
299 if (Is32Bit)
300 {
301 //
302 // Info about Optional Header
303 //
304 OpHeader32 = NtHeader32->OptionalHeader;
305 ShowMessages("\n\nInfo of optional Header\n-----------------------");
306 ShowMessages("\n%-36s%#x",
307 "Address of Entry Point : ",
308 OpHeader32.AddressOfEntryPoint);
309 ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader32.ImageBase);
310 ShowMessages("\n%-36s%s", "SubSystem type : ", OpHeader32.Subsystem == 1 ? "Device Driver(Native windows Process)" : OpHeader32.Subsystem == 2 ? "Windows GUI"
311 : OpHeader32.Subsystem == 3 ? "Windows CLI"
312 : OpHeader32.Subsystem == 3 ? "Windows CLI"
313 : OpHeader32.Subsystem == 9 ? "Windows CE GUI"
314 : "Unknown");
315 ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader32.Magic == 0x20b ? "PE32+(64)" : "PE32");
316 ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader32.SizeOfCode);
317 ShowMessages("\n%-36s%#x",
318 "Base address of code segment(RVA) :",
319 OpHeader32.BaseOfCode);
320 ShowMessages("\n%-36s%d",
321 "Size of Initialized data : ",
322 OpHeader32.SizeOfInitializedData);
323
324 ShowMessages("\n%-36s%#x",
325 "Base address of data segment(RVA) :",
326 OpHeader32.BaseOfData);
327
328 ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader32.SectionAlignment);
329 ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader32.MajorLinkerVersion);
330 ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader32.MinorLinkerVersion);
331 }
332 else
333 {
334 //
335 // Info about Optional Header
336 //
337 OpHeader64 = NtHeader64->OptionalHeader;
338 ShowMessages("\n\nInfo of optional Header\n-----------------------");
339 ShowMessages("\n%-36s%#x",
340 "Address of Entry Point : ",
341 OpHeader64.AddressOfEntryPoint);
342 ShowMessages("\n%-36s%#llx", "Base Address of the Image : ", OpHeader64.ImageBase);
343 ShowMessages("\n%-36s%s", "SubSystem type : ", OpHeader64.Subsystem == 1 ? "Device Driver(Native windows Process)" : OpHeader64.Subsystem == 2 ? "Windows GUI"
344 : OpHeader64.Subsystem == 3 ? "Windows CLI"
345 : OpHeader64.Subsystem == 3 ? "Windows CLI"
346 : OpHeader64.Subsystem == 9 ? "Windows CE GUI"
347 : "Unknown");
348 ShowMessages("\n%-36s%s", "Given file is a : ", OpHeader64.Magic == 0x20b ? "PE32+(64)" : "PE32");
349 ShowMessages("\n%-36s%d", "Size of code segment(.text) : ", OpHeader64.SizeOfCode);
350 ShowMessages("\n%-36s%#x",
351 "Base address of code segment(RVA) :",
352 OpHeader64.BaseOfCode);
353 ShowMessages("\n%-36s%d",
354 "Size of Initialized data : ",
355 OpHeader64.SizeOfInitializedData);
356
357 ShowMessages("\n%-36s%#x", "Section Alignment :", OpHeader64.SectionAlignment);
358 ShowMessages("\n%-36s%d", "Major Linker Version : ", OpHeader64.MajorLinkerVersion);
359 ShowMessages("\n%-36s%d", "Minor Linker Version : ", OpHeader64.MinorLinkerVersion);
360 }
361
362 ShowMessages("\n\nDumping Sections Header "
363 "Info....\n--------------------------------");
364
365 //
366 // Retrieve a pointer to First Section Header(or Section Table Entry)
367 //
368 if (Is32Bit)
369 {
370 SecHeader = IMAGE_FIRST_SECTION(NtHeader32);
371 NumberOfSections = NtHeader32->FileHeader.NumberOfSections;
372 }
373 else
374 {
375 SecHeader = IMAGE_FIRST_SECTION(NtHeader64);
376 NumberOfSections = NtHeader64->FileHeader.NumberOfSections;
377 }
378
379 for (UINT32 i = 0; i < NumberOfSections; i++, SecHeader++)
380 {
381 if (Is32Bit)
382 {
383 ShowMessages("\n\nSection Info (%d of %d)", i + 1, NtHeader32->FileHeader.NumberOfSections);
384 }
385 else
386 {
387 ShowMessages("\n\nSection Info (%d of %d)", i + 1, NtHeader64->FileHeader.NumberOfSections);
388 }
389
390 ShowMessages("\n---------------------");
391 ShowMessages("\n%-36s%s", "Section Header name : ", SecHeader->Name);
392 ShowMessages("\n%-36s%#x",
393 "ActualSize of code or data : ",
394 SecHeader->Misc.VirtualSize);
395 ShowMessages("\n%-36s%#x", "Virtual Address(RVA) :", SecHeader->VirtualAddress);
396 ShowMessages("\n%-36s%#x",
397 "Size of raw data (rounded to FA) : ",
398 SecHeader->SizeOfRawData);
399 ShowMessages("\n%-36s%#x",
400 "Pointer to Raw Data : ",
401 SecHeader->PointerToRawData);
402 ShowMessages("\n%-36s%#x",
403 "Pointer to Relocations : ",
404 SecHeader->PointerToRelocations);
405 ShowMessages("\n%-36s%#x",
406 "Pointer to Line numbers : ",
407 SecHeader->PointerToLinenumbers);
408 ShowMessages("\n%-36s%#x",
409 "Number of relocations : ",
410 SecHeader->NumberOfRelocations);
411 ShowMessages("\n%-36s%#x",
412 "Number of line numbers : ",
413 SecHeader->NumberOfLinenumbers);
414 ShowMessages("\n%-36s%s", "Characteristics : ", "Contains ");
415 if ((SecHeader->Characteristics & 0x20) == 0x20)
416 ShowMessages("executable code, ");
417 if ((SecHeader->Characteristics & 0x40) == 0x40)
418 ShowMessages("initialized data, ");
419 if ((SecHeader->Characteristics & 0x80) == 0x80)
420 ShowMessages("uninitialized data, ");
421 if ((SecHeader->Characteristics & 0x200) == 0x200)
422 ShowMessages("comments and linker commands, ");
423 if ((SecHeader->Characteristics & 0x10000000) == 0x10000000)
424 ShowMessages("shareable data(via DLLs), ");
425 if ((SecHeader->Characteristics & 0x40000000) == 0x40000000)
426 ShowMessages("Readable, ");
427 if ((SecHeader->Characteristics & 0x80000000) == 0x80000000)
428 ShowMessages("Writable, ");
429
430 //
431 // show the hex dump if the user needs it
432 //
433 if (SectionToShow != NULL)
434 {
435 if (!_strcmpi(SectionToShow, (const char *)SecHeader->Name))
436 {
437 if (SecHeader->SizeOfRawData != 0)
438 {
439 if (Is32Bit)
440 {
441 PeHexDump((char *)((UINT64)DosHeader + SecHeader->PointerToRawData),
442 SecHeader->SizeOfRawData,
443 OpHeader32.ImageBase + SecHeader->VirtualAddress);
444 }
445 else
446 {
447 PeHexDump((char *)((UINT64)DosHeader + SecHeader->PointerToRawData),
448 SecHeader->SizeOfRawData,
449 (int)(OpHeader64.ImageBase + SecHeader->VirtualAddress));
450 }
451 }
452 }
453 }
454 }
455
456 ShowMessages("\n==============================================================="
457 "================\n");
458
459 //
460 // Set result to true
461 //
462 Result = TRUE;
463
464Finished:
465 //
466 // Unmap and close the handles
467 //
468 UnmapViewOfFile(BaseAddr);
469 CloseHandle(MapObjectHandle);
470
471 return Result;
472}
unsigned int UINT32
Definition BasicTypes.h:48
VOID PeHexDump(CHAR *Ptr, int Size, int SecAddress)
Show hex dump of sections of PE.
Definition pe-parser.cpp:23