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