libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
pe_hdrs_helper.cpp
Go to the documentation of this file.
2#include "peconv/util.h"
3
4using namespace peconv;
5
6#ifdef _DEBUG
7#include <iostream>
8#endif
9
11{
12 if (!pe_buffer) return nullptr;
13
15 if (buffer_size != 0) {
17 return nullptr;
18 }
19 }
20 else {
22 return nullptr;
23 }
24 }
25 if (idh->e_magic != IMAGE_DOS_SIGNATURE) {
26 return nullptr;
27 }
28 const LONG kMaxOffset = 1024;
29 LONG pe_offset = idh->e_lfanew;
30
31 if (pe_offset > kMaxOffset) return nullptr;
32
34 if (buffer_size != 0) {
36 return nullptr;
37 }
38 }
39 else {
41 return nullptr;
42 }
43 }
44
45 if (inh->Signature != IMAGE_NT_SIGNATURE) {
46 return nullptr;
47 }
48 return (BYTE*)inh;
49}
50
52{
53 if (!payload) return nullptr;
54
56 if (!ptr) return nullptr;
57
58 if (!is64bit(payload)) {
59 return (IMAGE_NT_HEADERS32*)ptr;
60 }
61 return nullptr;
62}
63
65{
66 if (payload == nullptr) return nullptr;
67
69 if (!ptr) return nullptr;
70
71 if (is64bit(payload)) {
72 return (IMAGE_NT_HEADERS64*)ptr;
73 }
74 return nullptr;
75}
76
78{
79 if (!get_nt_hdrs(payload)) {
80 return 0;
81 }
82 DWORD image_size = 0;
83 if (is64bit(payload)) {
85 image_size = nt64->OptionalHeader.SizeOfImage;
86 } else {
88 image_size = nt32->OptionalHeader.SizeOfImage;
89 }
90 return image_size;
91}
92
94{
95 if (!get_nt_hdrs(payload)) {
96 return false;
97 }
98 if (is64bit(payload)) {
100 nt64->OptionalHeader.SizeOfImage = image_size;
101 }
102 else {
104 nt32->OptionalHeader.SizeOfImage = image_size;
105 }
106 return true;
107}
108
110{
111 void *ptr = get_nt_hdrs(pe_buffer);
112 if (!ptr) return 0;
113
116 return 0;
117 }
118 return inh->OptionalHeader.Magic;
119}
120
122{
125 return true;
126 }
127 return false;
128}
129
131{
132 if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return nullptr;
133
135 if (!nt_headers) return nullptr;
136
137 IMAGE_DATA_DIRECTORY* peDir = nullptr;
138 if (is64bit(pe_buffer)) {
140 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
141 }
142 else {
144 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
145 }
146 if (!allow_empty && peDir->VirtualAddress == NULL) {
147 return nullptr;
148 }
149 return peDir;
150}
151
153{
154 bool is64b = is64bit(pe_buffer);
155 //update image base in the written content:
157 if (!payload_nt_hdr) {
158 return 0;
159 }
161 if (is64b) {
163 img_base = payload_nt_hdr64->OptionalHeader.ImageBase;
164 } else {
166 img_base = static_cast<ULONGLONG>(payload_nt_hdr32->OptionalHeader.ImageBase);
167 }
168 return img_base;
169}
170
172{
173 //update image base in the written content:
175 if (!payload_nt_hdr) {
176 return 0;
177 }
178 const bool is64b = is64bit(pe_buffer);
179 DWORD value = 0;
180 if (is64b) {
182 value = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint;
183 } else {
185 value = payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint;
186 }
187 return value;
188}
189
191{
192 bool is64b = is64bit(pe_buffer);
193 //update image base in the written content:
195 if (!payload_nt_hdr) {
196 return false;
197 }
198 if (is64b) {
200 payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint = value;
201 } else {
203 payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint = value;
204 }
205 return true;
206}
207
209{
210 bool is64b = is64bit(pe_buffer);
212 if (!payload_nt_hdr) {
213 return 0;
214 }
215 DWORD hdrs_size = 0;
216 if (is64b) {
218 hdrs_size = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
219 } else {
221 hdrs_size = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
222 }
223 return hdrs_size;
224}
225
227{
228 bool is64b = is64bit(payload);
230 if (!payload_nt_hdr) {
231 return false;
232 }
233 if (is64b) {
235 payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
236 }
237 else {
239 payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase;
240 }
241 return true;
242}
243
244template <typename IMAGE_NT_HEADERS_T>
246{
247 if (!payload || !payload_nt_hdr) return nullptr;
248
249 const IMAGE_FILE_HEADER *fileHdr = &(payload_nt_hdr->FileHeader);
250
251 if (!validate_ptr((const LPVOID)payload, buffer_size, (const LPVOID)fileHdr, sizeof(IMAGE_FILE_HEADER))) {
252 return nullptr;
253 }
254 return fileHdr;
255}
256
258{
259 if (!payload) return nullptr;
260
262 if (!payload_nt_hdr) {
263 return nullptr;
264 }
265 if (is64bit(payload)) {
267 }
269}
270
271template <typename IMAGE_NT_HEADERS_T>
273{
274 if (!payload) return nullptr;
275
277 if (!fileHdr) {
278 return nullptr;
279 }
280 const LPVOID opt_hdr = (const LPVOID) &(payload_nt_hdr->OptionalHeader);
281 const size_t opt_size = fileHdr->SizeOfOptionalHeader;
283 return nullptr;
284 }
285 return opt_hdr;
286}
287
302
303template <typename IMAGE_NT_HEADERS_T>
305{
307 if (!fileHdr) {
308 return nullptr;
309 }
310 const size_t opt_size = fileHdr->SizeOfOptionalHeader;
313 return nullptr;
314 }
315 //sections headers starts right after the end of the optional header
316 return (LPVOID)(opt_hdr + opt_size);
317}
318
320{
322 if (!fileHdr) {
323 return 0;
324 }
325 return fileHdr->NumberOfSections;
326}
327
329{
331 if (sec_count == 0) {
332 //no sections found - a valid PE should have at least one section
333 return false;
334 }
336 if (!last_hdr) {
337 //could not fetch the last section
338 return false;
339 }
340 return true;
341}
342
344{
345 if (!payload) return nullptr;
346
349 return nullptr;
350 }
351
353 if (!nt_hdrs) return nullptr; //this should never happened, because the get_sections_count did not fail
354
355 LPVOID secptr = nullptr;
356 //get the beginning of sections headers:
357 if (is64bit(payload)) {
359 }
360 else {
362 }
363 //get the section header of given number:
366 );
367 //validate pointer:
368 if (!validate_ptr((const LPVOID) payload, buffer_size, (const LPVOID) next_sec, sizeof(IMAGE_SECTION_HEADER))) {
369 return nullptr;
370 }
371 return next_sec;
372}
373
375{
376 if (!payload) return 0;
377
378 bool is64b = is64bit(payload);
380 if (!payload_nt_hdr) {
381 return 0;
382 }
383 IMAGE_FILE_HEADER *fileHdr = nullptr;
384 if (is64b) {
386 fileHdr = &(payload_nt_hdr64->FileHeader);
387 }
388 else {
390 fileHdr = &(payload_nt_hdr32->FileHeader);
391 }
392 return fileHdr->Characteristics;
393}
394
396{
397 if (!payload) return false;
399 return ((charact & IMAGE_FILE_DLL) != 0);
400}
401
403{
404 if (!pe_buffer) return false;
405
407 if (!dotnet_ptr) return false;
408
410 return true;
411 }
412 return false;
413}
414
416{
417 if (!payload) return 0;
418
419 bool is64b = is64bit(payload);
421 if (!payload_nt_hdr) {
422 return 0;
423 }
424 WORD charact = 0;
425 if (is64b) {
427 charact = payload_nt_hdr64->OptionalHeader.DllCharacteristics;
428 }
429 else {
431 charact = payload_nt_hdr32->OptionalHeader.DllCharacteristics;
432 }
433 return charact;
434}
435
437{
438 if (!payload) return false;
439
440 bool is64b = is64bit(payload);
442 if (!payload_nt_hdr) {
443 return false;
444 }
445 if (is64b) {
447 payload_nt_hdr64->OptionalHeader.Subsystem = subsystem;
448 } else {
450 payload_nt_hdr32->OptionalHeader.Subsystem = subsystem;
451 }
452 return true;
453}
454
456{
457 if (!payload) return 0;
458
460 if (payload_nt_hdr == NULL) {
461 return 0;
462 }
463 const bool is64b = is64bit(payload);
464 if (is64b) {
466 return payload_nt_hdr64->OptionalHeader.Subsystem;
467 } else {
469 return payload_nt_hdr32->OptionalHeader.Subsystem;
470 }
471}
472
474{
476 if (!relocDir) {
477 return false;
478 }
479 return true;
480}
481
486
487
489{
490 DWORD rva = dotNetDir->VirtualAddress;
491 DWORD hdr_size = dotNetDir->Size;
493 return nullptr;
494 }
496 if (!peconv::validate_ptr(module, module_size, module + dnet_hdr->MetaData.VirtualAddress, dnet_hdr->MetaData.Size)) {
497 return nullptr;
498 }
499 DWORD* signature_ptr = (DWORD*)(module + dnet_hdr->MetaData.VirtualAddress);
500 const DWORD dotNetSign = 0x424A5342;
501 if (*signature_ptr != dotNetSign) {
502 //invalid header
503 return nullptr;
504 }
505 return dnet_hdr;
506}
507
508template <typename IMAGE_NT_HEADERS_T>
509DWORD* _get_sec_alignment_ptr(const BYTE* modulePtr, bool is_raw)
510{
511 IMAGE_NT_HEADERS_T* hdrs = reinterpret_cast<IMAGE_NT_HEADERS_T*>(peconv::get_nt_hdrs(modulePtr));
512 if (!hdrs) return nullptr;
513 if (is_raw) {
514 return &hdrs->OptionalHeader.FileAlignment;
515 }
516 return &hdrs->OptionalHeader.SectionAlignment;
517}
518
520{
521 DWORD* alignment = 0;
522 if (peconv::is64bit(modulePtr)) {
524 } else {
526 }
527 if (!alignment) return 0;
528 return *alignment;
529}
530
532{
533 DWORD* alignment = 0;
534 if (peconv::is64bit(modulePtr)) {
536 }
537 else {
539 }
540 if (!alignment) return false;
541
543 return true;
544}
545
547{
548 if (!pe_hdr || !sec_hdr) {
549 return 0;
550 }
551 if (!rounded) {
552 return sec_hdr->Misc.VirtualSize;;
553 }
554 //TODO: calculate real size, round up to Virtual Alignment
556 DWORD vsize = sec_hdr->Misc.VirtualSize;
557 if (alignment != 0) {
559 if ((vsize % alignment) > 0) units++;
560
562 }
564 //if it is bigger than the image size, use the size from the headers
565 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
566 vsize = sec_hdr->Misc.VirtualSize;
567 }
568 return vsize;
569}
570
572{
575 if (sections_count == 0) {
576 return nullptr;
577 }
579 //walk through sections
580 for (size_t i = 0; i < sections_count; i++) {
582 if (!sec) break;
583
584 size_t new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
585 if (new_end > module_end) {
587 last_sec = sec;
588 }
589 }
590 return last_sec;
591}
592
594{
597 if (sections_count == 0) {
598 return module_end;
599 }
600 //walk through sections
601 for (size_t i = 0; i < sections_count; i++) {
603 if (!sec) break;
604
605 DWORD new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
607 }
608 return module_end;
609}
610
612{
613 if (payload == NULL) return false;
614
616 if (my_align == 0) {
617#ifdef _DEBUG
618 std::cout << "Section alignment cannot be 0\n";
619#endif
620 return false;
621 }
623 if (sections_count == 0) {
624 //no sections
625 return false;
626 }
627 for (size_t i = 0; i < sections_count; i++) {
629 if (!next_sec) return false; //the number of the sections in header is out of scope
630
631 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
632
633 SIZE_T sec_size = is_raw ? next_sec->SizeOfRawData : next_sec->Misc.VirtualSize;
634 if (sec_size == 0) continue;
635 if (next_sec->Misc.VirtualSize == 0) {
636 continue; // if the VirtualSize == 0 the section will not be mapped anyways
637 }
638 if (next_sec_addr == 0) {
639 //if cannot be 0 if the size is not 0
640 return false;
641 }
642
643 //check only if raw_align is non-zero
644 if (my_align && next_sec_addr % my_align != 0) {
645#ifdef _DEBUG
646 std::cout << "Section is misaligned\n";
647#endif
648 return false; //misaligned
649 }
650 }
651 return true;
652}
bool parse_delayed_desc(BYTE *modulePtr, const size_t moduleSize, const ULONGLONG img_base, LPSTR lib_name, const T_FIELD ordinal_flag, IMAGE_DELAYLOAD_DESCRIPTOR *desc, peconv::t_function_resolver *func_resolver)
bool update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD ep)
bool set_sec_alignment(IN OUT BYTE *pe_buffer, IN bool is_raw, IN DWORD new_alignment)
bool has_relocations(IN const BYTE *pe_buffer)
DWORD get_entry_point_rva(IN const BYTE *pe_buffer)
WORD get_nt_hdr_architecture(IN const BYTE *pe_buffer)
bool set_subsystem(IN OUT BYTE *payload, IN WORD subsystem)
bool is_dot_net(BYTE *pe_buffer, size_t pe_buffer_size)
DWORD get_virtual_sec_size(IN const BYTE *pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
const IMAGE_FILE_HEADER * get_file_hdr(IN const BYTE *payload, IN const size_t buffer_size)
bool update_image_base(IN OUT BYTE *payload, IN ULONGLONG destImageBase)
bool is_valid_sections_hdr_offset(IN const BYTE *buffer, IN const size_t buffer_size)
ULONGLONG get_image_base(IN const BYTE *pe_buffer)
WORD get_file_characteristics(IN const BYTE *payload)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
PIMAGE_SECTION_HEADER get_section_hdr(IN const BYTE *pe_buffer, IN const size_t buffer_size, IN size_t section_num)
IMAGE_NT_HEADERS64 * get_nt_hdrs64(IN const BYTE *pe_buffer)
IMAGE_COR20_HEADER * get_dotnet_hdr(IN const BYTE *pe_buffer, IN size_t const buffer_size, IN const IMAGE_DATA_DIRECTORY *dotNetDir)
DWORD get_image_size(IN const BYTE *payload)
DWORD get_sec_alignment(IN const BYTE *modulePtr, IN bool is_raw)
bool is64bit(IN const BYTE *pe_buffer)
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
Definition util.cpp:150
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
IMAGE_NT_HEADERS32 * get_nt_hdrs32(IN const BYTE *pe_buffer)
bool update_image_size(IN OUT BYTE *payload, IN DWORD new_img_size)
DWORD get_hdrs_size(IN const BYTE *pe_buffer)
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)
PIMAGE_SECTION_HEADER get_last_section(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw)
WORD get_dll_characteristics(IN const BYTE *payload)
IMAGE_EXPORT_DIRECTORY * get_export_directory(IN HMODULE modulePtr)
bool is_valid_sectons_alignment(IN const BYTE *buffer, IN const SIZE_T buffer_size, IN bool is_raw)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0)
DWORD calc_pe_size(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw)
bool is_module_dll(IN const BYTE *payload)
WORD get_subsystem(IN const BYTE *payload)
LPVOID get_optional_hdr(IN const BYTE *payload, IN const size_t buffer_size)
const IMAGE_FILE_HEADER * fetch_file_hdr(IN const BYTE *payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T *payload_nt_hdr)
LPVOID fetch_section_hdrs_ptr(IN const BYTE *payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T *payload_nt_hdr)
DWORD * _get_sec_alignment_ptr(const BYTE *modulePtr, bool is_raw)
const LPVOID fetch_opt_hdr(IN const BYTE *payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T *payload_nt_hdr)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
Miscellaneous utility functions.