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
10BYTE* peconv::get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size)
11{
12 if (!pe_buffer) return nullptr;
13
14 IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER*)pe_buffer;
15 if (buffer_size != 0) {
16 if (!peconv::validate_ptr((LPVOID)pe_buffer, buffer_size, (LPVOID)idh, sizeof(IMAGE_DOS_HEADER))) {
17 return nullptr;
18 }
19 }
20 else {
21 if (peconv::is_bad_read_ptr(idh, sizeof(IMAGE_DOS_HEADER))) {
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
33 IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)(pe_buffer + pe_offset);
34 if (buffer_size != 0) {
35 if (!peconv::validate_ptr((LPVOID)pe_buffer, buffer_size, (LPVOID)inh, sizeof(IMAGE_NT_HEADERS32))) {
36 return nullptr;
37 }
38 }
39 else {
40 if (peconv::is_bad_read_ptr(inh, sizeof(IMAGE_NT_HEADERS32))) {
41 return nullptr;
42 }
43 }
44
45 if (inh->Signature != IMAGE_NT_SIGNATURE) {
46 return nullptr;
47 }
48 return (BYTE*)inh;
49}
50
51IMAGE_NT_HEADERS32* peconv::get_nt_hdrs32(IN const BYTE *payload)
52{
53 if (!payload) return nullptr;
54
55 BYTE *ptr = get_nt_hdrs(payload);
56 if (!ptr) return nullptr;
57
58 if (!is64bit(payload)) {
59 return (IMAGE_NT_HEADERS32*)ptr;
60 }
61 return nullptr;
62}
63
64IMAGE_NT_HEADERS64* peconv::get_nt_hdrs64(IN const BYTE *payload)
65{
66 if (payload == nullptr) return nullptr;
67
68 BYTE *ptr = get_nt_hdrs(payload);
69 if (!ptr) return nullptr;
70
71 if (is64bit(payload)) {
72 return (IMAGE_NT_HEADERS64*)ptr;
73 }
74 return nullptr;
75}
76
77DWORD peconv::get_image_size(IN const BYTE *payload)
78{
79 if (!get_nt_hdrs(payload)) {
80 return 0;
81 }
82 DWORD image_size = 0;
83 if (is64bit(payload)) {
84 IMAGE_NT_HEADERS64* nt64 = get_nt_hdrs64(payload);
85 image_size = nt64->OptionalHeader.SizeOfImage;
86 } else {
87 IMAGE_NT_HEADERS32* nt32 = get_nt_hdrs32(payload);
88 image_size = nt32->OptionalHeader.SizeOfImage;
89 }
90 return image_size;
91}
92
93bool peconv::update_image_size(IN OUT BYTE* payload, IN DWORD image_size)
94{
95 if (!get_nt_hdrs(payload)) {
96 return false;
97 }
98 if (is64bit(payload)) {
99 IMAGE_NT_HEADERS64* nt64 = get_nt_hdrs64(payload);
100 nt64->OptionalHeader.SizeOfImage = image_size;
101 }
102 else {
103 IMAGE_NT_HEADERS32* nt32 = get_nt_hdrs32(payload);
104 nt32->OptionalHeader.SizeOfImage = image_size;
105 }
106 return true;
107}
108
109WORD peconv::get_nt_hdr_architecture(IN const BYTE *pe_buffer)
110{
111 void *ptr = get_nt_hdrs(pe_buffer);
112 if (!ptr) return 0;
113
114 IMAGE_NT_HEADERS32 *inh = static_cast<IMAGE_NT_HEADERS32*>(ptr);
115 if (peconv::is_bad_read_ptr(inh, sizeof(IMAGE_NT_HEADERS32))) {
116 return 0;
117 }
118 return inh->OptionalHeader.Magic;
119}
120
121bool peconv::is64bit(IN const BYTE *pe_buffer)
122{
123 WORD arch = get_nt_hdr_architecture(pe_buffer);
124 if (arch == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
125 return true;
126 }
127 return false;
128}
129
130IMAGE_DATA_DIRECTORY* peconv::get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty)
131{
132 if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return nullptr;
133
134 BYTE* nt_headers = get_nt_hdrs((BYTE*)pe_buffer);
135 if (!nt_headers) return nullptr;
136
137 IMAGE_DATA_DIRECTORY* peDir = nullptr;
138 if (is64bit(pe_buffer)) {
139 IMAGE_NT_HEADERS64* nt_headers64 = (IMAGE_NT_HEADERS64*)nt_headers;
140 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
141 }
142 else {
143 IMAGE_NT_HEADERS32* nt_headers64 = (IMAGE_NT_HEADERS32*)nt_headers;
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
152ULONGLONG peconv::get_image_base(IN const BYTE *pe_buffer)
153{
154 bool is64b = is64bit(pe_buffer);
155 //update image base in the written content:
156 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
157 if (!payload_nt_hdr) {
158 return 0;
159 }
160 ULONGLONG img_base = 0;
161 if (is64b) {
162 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
163 img_base = payload_nt_hdr64->OptionalHeader.ImageBase;
164 } else {
165 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
166 img_base = static_cast<ULONGLONG>(payload_nt_hdr32->OptionalHeader.ImageBase);
167 }
168 return img_base;
169}
170
171DWORD peconv::get_entry_point_rva(IN const BYTE *pe_buffer)
172{
173 //update image base in the written content:
174 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
175 if (!payload_nt_hdr) {
176 return 0;
177 }
178 const bool is64b = is64bit(pe_buffer);
179 DWORD value = 0;
180 if (is64b) {
181 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
182 value = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint;
183 } else {
184 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
185 value = payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint;
186 }
187 return value;
188}
189
190bool peconv::update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD value)
191{
192 bool is64b = is64bit(pe_buffer);
193 //update image base in the written content:
194 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
195 if (!payload_nt_hdr) {
196 return false;
197 }
198 if (is64b) {
199 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
200 payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint = value;
201 } else {
202 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
203 payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint = value;
204 }
205 return true;
206}
207
208DWORD peconv::get_hdrs_size(IN const BYTE *pe_buffer)
209{
210 bool is64b = is64bit(pe_buffer);
211 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
212 if (!payload_nt_hdr) {
213 return 0;
214 }
215 DWORD hdrs_size = 0;
216 if (is64b) {
217 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
218 hdrs_size = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
219 } else {
220 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
221 hdrs_size = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
222 }
223 return hdrs_size;
224}
225
226bool peconv::update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase)
227{
228 bool is64b = is64bit(payload);
229 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
230 if (!payload_nt_hdr) {
231 return false;
232 }
233 if (is64b) {
234 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
235 payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
236 }
237 else {
238 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
239 payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase;
240 }
241 return true;
242}
243
244template <typename IMAGE_NT_HEADERS_T>
245inline 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)
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
257const IMAGE_FILE_HEADER* peconv::get_file_hdr(IN const BYTE* payload, IN const size_t buffer_size)
258{
259 if (!payload) return nullptr;
260
261 BYTE* payload_nt_hdr = get_nt_hdrs(payload, buffer_size);
262 if (!payload_nt_hdr) {
263 return nullptr;
264 }
265 if (is64bit(payload)) {
266 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
267 }
268 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
269}
270
271template <typename IMAGE_NT_HEADERS_T>
272inline const LPVOID fetch_opt_hdr(IN const BYTE* payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T *payload_nt_hdr)
273{
274 if (!payload) return nullptr;
275
276 const IMAGE_FILE_HEADER *fileHdr = fetch_file_hdr<IMAGE_NT_HEADERS_T>(payload, buffer_size, payload_nt_hdr);
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;
282 if (!validate_ptr((const LPVOID)payload, buffer_size, opt_hdr, opt_size)) {
283 return nullptr;
284 }
285 return opt_hdr;
286}
287
288LPVOID peconv::get_optional_hdr(IN const BYTE* payload, IN const size_t buffer_size)
289{
290 if (!payload) return nullptr;
291
292 BYTE* payload_nt_hdr = get_nt_hdrs(payload, buffer_size);
293 const IMAGE_FILE_HEADER* fileHdr = get_file_hdr(payload, buffer_size);
294 if (!payload_nt_hdr || !fileHdr) {
295 return nullptr;
296 }
297 if (is64bit(payload)) {
298 return fetch_opt_hdr<IMAGE_NT_HEADERS64>(payload,buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
299 }
300 return fetch_opt_hdr<IMAGE_NT_HEADERS32>(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
301}
302
303template <typename IMAGE_NT_HEADERS_T>
304inline LPVOID fetch_section_hdrs_ptr(IN const BYTE* payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T *payload_nt_hdr)
305{
306 const IMAGE_FILE_HEADER *fileHdr = fetch_file_hdr<IMAGE_NT_HEADERS_T>(payload, buffer_size, payload_nt_hdr);
307 if (!fileHdr) {
308 return nullptr;
309 }
310 const size_t opt_size = fileHdr->SizeOfOptionalHeader;
311 BYTE* opt_hdr = (BYTE*)fetch_opt_hdr(payload, buffer_size, payload_nt_hdr);
312 if (!validate_ptr((const LPVOID)payload, buffer_size, opt_hdr, opt_size)) {
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
319size_t peconv::get_sections_count(IN const BYTE* payload, IN const size_t buffer_size)
320{
321 const IMAGE_FILE_HEADER* fileHdr = get_file_hdr(payload, buffer_size);
322 if (!fileHdr) {
323 return 0;
324 }
325 return fileHdr->NumberOfSections;
326}
327
328bool peconv::is_valid_sections_hdr_offset(IN const BYTE* buffer, IN const size_t buffer_size)
329{
330 size_t sec_count = peconv::get_sections_count(buffer, buffer_size);
331 if (sec_count == 0) {
332 //no sections found - a valid PE should have at least one section
333 return false;
334 }
335 PIMAGE_SECTION_HEADER last_hdr = get_section_hdr(buffer, buffer_size, sec_count - 1);
336 if (!last_hdr) {
337 //could not fetch the last section
338 return false;
339 }
340 return true;
341}
342
343PIMAGE_SECTION_HEADER peconv::get_section_hdr(IN const BYTE* payload, IN const size_t buffer_size, IN size_t section_num)
344{
345 if (!payload) return nullptr;
346
347 const size_t sections_count = peconv::get_sections_count(payload, buffer_size);
348 if (section_num >= sections_count) {
349 return nullptr;
350 }
351
352 LPVOID nt_hdrs = peconv::get_nt_hdrs(payload, buffer_size);
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)) {
358 secptr = fetch_section_hdrs_ptr<IMAGE_NT_HEADERS64>(payload, buffer_size, (IMAGE_NT_HEADERS64*)nt_hdrs);
359 }
360 else {
361 secptr = fetch_section_hdrs_ptr<IMAGE_NT_HEADERS32>(payload, buffer_size, (IMAGE_NT_HEADERS32*)nt_hdrs);
362 }
363 //get the section header of given number:
364 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)(
365 (ULONGLONG)secptr + (IMAGE_SIZEOF_SECTION_HEADER * section_num)
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
374WORD peconv::get_file_characteristics(IN const BYTE* payload)
375{
376 if (!payload) return 0;
377
378 bool is64b = is64bit(payload);
379 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
380 if (!payload_nt_hdr) {
381 return 0;
382 }
383 IMAGE_FILE_HEADER *fileHdr = nullptr;
384 if (is64b) {
385 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
386 fileHdr = &(payload_nt_hdr64->FileHeader);
387 }
388 else {
389 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
390 fileHdr = &(payload_nt_hdr32->FileHeader);
391 }
392 return fileHdr->Characteristics;
393}
394
395bool peconv::is_module_dll(IN const BYTE* payload)
396{
397 if (!payload) return false;
398 WORD charact = get_file_characteristics(payload);
399 return ((charact & IMAGE_FILE_DLL) != 0);
400}
401
402bool peconv::is_dot_net(BYTE *pe_buffer, size_t pe_buffer_size)
403{
404 if (!pe_buffer) return false;
405
406 IMAGE_DATA_DIRECTORY* dotnet_ptr = peconv::get_directory_entry(pe_buffer, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, false);
407 if (!dotnet_ptr) return false;
408
409 if (peconv::get_dotnet_hdr(pe_buffer, pe_buffer_size, dotnet_ptr)) {
410 return true;
411 }
412 return false;
413}
414
415WORD peconv::get_dll_characteristics(IN const BYTE* payload)
416{
417 if (!payload) return 0;
418
419 bool is64b = is64bit(payload);
420 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
421 if (!payload_nt_hdr) {
422 return 0;
423 }
424 WORD charact = 0;
425 if (is64b) {
426 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
427 charact = payload_nt_hdr64->OptionalHeader.DllCharacteristics;
428 }
429 else {
430 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
431 charact = payload_nt_hdr32->OptionalHeader.DllCharacteristics;
432 }
433 return charact;
434}
435
436bool peconv::set_subsystem(IN OUT BYTE* payload, IN WORD subsystem)
437{
438 if (!payload) return false;
439
440 bool is64b = is64bit(payload);
441 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
442 if (!payload_nt_hdr) {
443 return false;
444 }
445 if (is64b) {
446 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
447 payload_nt_hdr64->OptionalHeader.Subsystem = subsystem;
448 } else {
449 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
450 payload_nt_hdr32->OptionalHeader.Subsystem = subsystem;
451 }
452 return true;
453}
454
455WORD peconv::get_subsystem(IN const BYTE* payload)
456{
457 if (!payload) return 0;
458
459 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
460 if (payload_nt_hdr == NULL) {
461 return 0;
462 }
463 const bool is64b = is64bit(payload);
464 if (is64b) {
465 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
466 return payload_nt_hdr64->OptionalHeader.Subsystem;
467 } else {
468 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
469 return payload_nt_hdr32->OptionalHeader.Subsystem;
470 }
471}
472
473bool peconv::has_relocations(IN const BYTE *pe_buffer)
474{
475 IMAGE_DATA_DIRECTORY* relocDir = get_directory_entry(pe_buffer, IMAGE_DIRECTORY_ENTRY_BASERELOC);
476 if (!relocDir) {
477 return false;
478 }
479 return true;
480}
481
482IMAGE_EXPORT_DIRECTORY* peconv::get_export_directory(IN HMODULE modulePtr)
483{
484 return get_type_directory<IMAGE_EXPORT_DIRECTORY>(modulePtr, IMAGE_DIRECTORY_ENTRY_EXPORT);
485}
486
487
488IMAGE_COR20_HEADER * peconv::get_dotnet_hdr(IN const BYTE* module, IN size_t const module_size, IN const IMAGE_DATA_DIRECTORY * dotNetDir)
489{
490 DWORD rva = dotNetDir->VirtualAddress;
491 DWORD hdr_size = dotNetDir->Size;
492 if (!peconv::validate_ptr(module, module_size, module + rva, hdr_size)) {
493 return nullptr;
494 }
495 IMAGE_COR20_HEADER *dnet_hdr = (IMAGE_COR20_HEADER*)(module + rva);
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
519DWORD peconv::get_sec_alignment(IN const BYTE* modulePtr, IN bool is_raw)
520{
521 DWORD* alignment = 0;
522 if (peconv::is64bit(modulePtr)) {
523 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
524 } else {
525 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
526 }
527 if (!alignment) return 0;
528 return *alignment;
529}
530
531bool peconv::set_sec_alignment(IN OUT BYTE* modulePtr, IN bool is_raw, IN DWORD new_alignment)
532{
533 DWORD* alignment = 0;
534 if (peconv::is64bit(modulePtr)) {
535 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
536 }
537 else {
538 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
539 }
540 if (!alignment) return false;
541
542 *alignment = new_alignment;
543 return true;
544}
545
546DWORD peconv::get_virtual_sec_size(IN const BYTE* pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
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
555 DWORD alignment = peconv::get_sec_alignment((const PBYTE)pe_hdr, false);
556 DWORD vsize = peconv::round_up_to_unit(sec_hdr->Misc.VirtualSize, alignment);
557 DWORD image_size = peconv::get_image_size(pe_hdr);
558 //if it is bigger than the image size, use the size from the headers
559 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
560 vsize = sec_hdr->Misc.VirtualSize;
561 }
562 return vsize;
563}
564
565PIMAGE_SECTION_HEADER peconv::get_last_section(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw)
566{
567 SIZE_T module_end = peconv::get_hdrs_size(pe_buffer);
568 const size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
569 if (sections_count == 0) {
570 return nullptr;
571 }
572 PIMAGE_SECTION_HEADER last_sec = nullptr;
573 //walk through sections
574 for (size_t i = 0; i < sections_count; i++) {
575 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
576 if (!sec) break;
577
578 size_t new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
579 if (new_end > module_end) {
580 module_end = new_end;
581 last_sec = sec;
582 }
583 }
584 return last_sec;
585}
586
587DWORD peconv::calc_pe_size(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw)
588{
589 DWORD module_end = peconv::get_hdrs_size(pe_buffer);
590 const size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
591 if (sections_count == 0) {
592 return module_end;
593 }
594 //walk through sections
595 for (size_t i = 0; i < sections_count; i++) {
596 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
597 if (!sec) break;
598
599 DWORD new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
600 if (new_end > module_end) module_end = new_end;
601 }
602 return module_end;
603}
604
605bool peconv::is_valid_sectons_alignment(IN const BYTE* payload, IN const SIZE_T payload_size, IN bool is_raw)
606{
607 if (payload == NULL) return false;
608
609 const DWORD my_align = peconv::get_sec_alignment(payload, is_raw);
610 if (my_align == 0) {
611#ifdef _DEBUG
612 std::cout << "Section alignment cannot be 0\n";
613#endif
614 return false;
615 }
616 const size_t sections_count = peconv::get_sections_count(payload, payload_size);
617 if (sections_count == 0) {
618 //no sections
619 return false;
620 }
621 for (size_t i = 0; i < sections_count; i++) {
622 PIMAGE_SECTION_HEADER next_sec = peconv::get_section_hdr(payload, payload_size, i);
623 if (!next_sec) return false; //the number of the sections in header is out of scope
624
625 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
626
627 SIZE_T sec_size = is_raw ? next_sec->SizeOfRawData : next_sec->Misc.VirtualSize;
628 if (sec_size == 0) continue;
629 if (next_sec->Misc.VirtualSize == 0) {
630 continue; // if the VirtualSize == 0 the section will not be mapped anyways
631 }
632 if (next_sec_addr == 0) {
633 //if cannot be 0 if the size is not 0
634 return false;
635 }
636
637 //check only if raw_align is non-zero
638 if (my_align && next_sec_addr % my_align != 0) {
639#ifdef _DEBUG
640 std::cout << "Section is misaligned\n";
641#endif
642 return false; //misaligned
643 }
644 }
645 return true;
646}
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_TYPE_DIRECTORY * get_type_directory(IN HMODULE modulePtr, IN DWORD dir_id)
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)
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
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.