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, IN OPTIONAL const LONG max_pe_offset)
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 pe_offset = idh->e_lfanew;
27 if (pe_offset < 0 || pe_offset > max_pe_offset) return nullptr;
28
29 IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)(pe_buffer + pe_offset);
30 if (buffer_size != 0) {
31 if (!peconv::validate_ptr(pe_buffer, buffer_size, inh, sizeof(IMAGE_NT_HEADERS32))) {
32 return nullptr;
33 }
34 }
35 else {
36 if (peconv::is_bad_read_ptr(inh, sizeof(IMAGE_NT_HEADERS32))) {
37 return nullptr;
38 }
39 }
40
41 if (inh->Signature != IMAGE_NT_SIGNATURE) {
42 return nullptr;
43 }
44 return (BYTE*)inh;
45}
46
47IMAGE_NT_HEADERS32* peconv::get_nt_hdrs32(IN const BYTE *payload)
48{
49 if (!payload) return nullptr;
50
51 BYTE *ptr = get_nt_hdrs(payload);
52 if (!ptr) return nullptr;
53
54 if (!is64bit(payload)) {
55 return (IMAGE_NT_HEADERS32*)ptr;
56 }
57 return nullptr;
58}
59
60IMAGE_NT_HEADERS64* peconv::get_nt_hdrs64(IN const BYTE *payload)
61{
62 if (payload == nullptr) return nullptr;
63
64 BYTE *ptr = get_nt_hdrs(payload);
65 if (!ptr) return nullptr;
66
67 if (is64bit(payload)) {
68 return (IMAGE_NT_HEADERS64*)ptr;
69 }
70 return nullptr;
71}
72
73DWORD peconv::get_image_size(IN const BYTE *payload)
74{
75 if (!get_nt_hdrs(payload)) {
76 return 0;
77 }
78 DWORD image_size = 0;
79 if (is64bit(payload)) {
80 IMAGE_NT_HEADERS64* nt64 = get_nt_hdrs64(payload);
81 image_size = nt64->OptionalHeader.SizeOfImage;
82 } else {
83 IMAGE_NT_HEADERS32* nt32 = get_nt_hdrs32(payload);
84 image_size = nt32->OptionalHeader.SizeOfImage;
85 }
86 return image_size;
87}
88
89bool peconv::update_image_size(IN OUT BYTE* payload, IN DWORD image_size)
90{
91 if (!get_nt_hdrs(payload)) {
92 return false;
93 }
94 if (is64bit(payload)) {
95 IMAGE_NT_HEADERS64* nt64 = get_nt_hdrs64(payload);
96 nt64->OptionalHeader.SizeOfImage = image_size;
97 }
98 else {
99 IMAGE_NT_HEADERS32* nt32 = get_nt_hdrs32(payload);
100 nt32->OptionalHeader.SizeOfImage = image_size;
101 }
102 return true;
103}
104
105WORD peconv::get_nt_hdr_architecture(IN const BYTE *pe_buffer)
106{
107 void *ptr = get_nt_hdrs(pe_buffer);
108 if (!ptr) return 0;
109
110 IMAGE_NT_HEADERS32 *inh = static_cast<IMAGE_NT_HEADERS32*>(ptr);
111 if (peconv::is_bad_read_ptr(inh, sizeof(IMAGE_NT_HEADERS32))) {
112 return 0;
113 }
114 return inh->OptionalHeader.Magic;
115}
116
117bool peconv::is64bit(IN const BYTE *pe_buffer)
118{
119 WORD arch = get_nt_hdr_architecture(pe_buffer);
120 if (arch == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
121 return true;
122 }
123 return false;
124}
125
126IMAGE_DATA_DIRECTORY* peconv::get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty)
127{
128 if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return nullptr;
129
130 BYTE* nt_headers = get_nt_hdrs((BYTE*)pe_buffer);
131 if (!nt_headers) return nullptr;
132
133 IMAGE_DATA_DIRECTORY* peDir = nullptr;
134 if (is64bit(pe_buffer)) {
135 IMAGE_NT_HEADERS64* nt_headers64 = (IMAGE_NT_HEADERS64*)nt_headers;
136 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
137 }
138 else {
139 IMAGE_NT_HEADERS32* nt_headers32 = (IMAGE_NT_HEADERS32*)nt_headers;
140 peDir = &(nt_headers32->OptionalHeader.DataDirectory[dir_id]);
141 }
142 if (!allow_empty && !peDir->VirtualAddress) {
143 return nullptr;
144 }
145 return peDir;
146}
147
148ULONGLONG peconv::get_image_base(IN const BYTE *pe_buffer)
149{
150 bool is64b = is64bit(pe_buffer);
151 //update image base in the written content:
152 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
153 if (!payload_nt_hdr) {
154 return 0;
155 }
156 ULONGLONG img_base = 0;
157 if (is64b) {
158 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
159 img_base = payload_nt_hdr64->OptionalHeader.ImageBase;
160 } else {
161 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
162 img_base = static_cast<ULONGLONG>(payload_nt_hdr32->OptionalHeader.ImageBase);
163 }
164 return img_base;
165}
166
167DWORD peconv::get_entry_point_rva(IN const BYTE *pe_buffer)
168{
169 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
170 if (!payload_nt_hdr) {
171 return 0;
172 }
173 DWORD value = 0;
174 const bool is64b = is64bit(pe_buffer);
175 if (is64b) {
176 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
177 value = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint;
178 } else {
179 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
180 value = payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint;
181 }
182 return value;
183}
184
185bool peconv::update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD value)
186{
187 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
188 if (!payload_nt_hdr) {
189 return false;
190 }
191 const bool is64b = is64bit(pe_buffer);
192 if (is64b) {
193 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
194 payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint = value;
195 } else {
196 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
197 payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint = value;
198 }
199 return true;
200}
201
202DWORD peconv::get_hdrs_size(IN const BYTE *pe_buffer)
203{
204 BYTE* payload_nt_hdr = get_nt_hdrs(pe_buffer);
205 if (!payload_nt_hdr) {
206 return 0;
207 }
208 const bool is64b = is64bit(pe_buffer);
209 DWORD hdrs_size = 0;
210 if (is64b) {
211 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
212 hdrs_size = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
213 } else {
214 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
215 hdrs_size = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
216 }
217 return hdrs_size;
218}
219
220bool peconv::update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase)
221{
222 BYTE* payload_nt_hdr = get_nt_hdrs(payload);
223 if (!payload_nt_hdr) {
224 return false;
225 }
226 const bool is64b = is64bit(payload);
227 if (is64b) {
228 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
229 payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
230 }
231 else {
232 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
233 payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase;
234 }
235 return true;
236}
237
238namespace {
239 template <typename IMAGE_NT_HEADERS_T>
240 inline 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)
241 {
242 if (!payload || !payload_nt_hdr) return nullptr;
243
244 const IMAGE_FILE_HEADER* fileHdr = &(payload_nt_hdr->FileHeader);
245
246 if (!validate_ptr((const LPVOID)payload, buffer_size, (const LPVOID)fileHdr, sizeof(IMAGE_FILE_HEADER))) {
247 return nullptr;
248 }
249 return fileHdr;
250 }
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}
266namespace {
267 template <typename IMAGE_NT_HEADERS_T>
268 inline 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};
284
285
286LPVOID peconv::get_optional_hdr(IN const BYTE* payload, IN const size_t buffer_size)
287{
288 if (!payload) return nullptr;
289
290 BYTE* payload_nt_hdr = get_nt_hdrs(payload, buffer_size);
291 const IMAGE_FILE_HEADER* fileHdr = get_file_hdr(payload, buffer_size);
292 if (!payload_nt_hdr || !fileHdr) {
293 return nullptr;
294 }
295 if (is64bit(payload)) {
296 return fetch_opt_hdr<IMAGE_NT_HEADERS64>(payload,buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
297 }
298 return fetch_opt_hdr<IMAGE_NT_HEADERS32>(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
299}
300
301namespace {
302 template <typename IMAGE_NT_HEADERS_T>
303 inline LPVOID fetch_section_hdrs_ptr(IN const BYTE* payload, IN const size_t buffer_size, IN const IMAGE_NT_HEADERS_T* payload_nt_hdr)
304 {
305 const IMAGE_FILE_HEADER* fileHdr = fetch_file_hdr<IMAGE_NT_HEADERS_T>(payload, buffer_size, payload_nt_hdr);
306 if (!fileHdr) {
307 return nullptr;
308 }
309 const size_t opt_size = fileHdr->SizeOfOptionalHeader;
310 BYTE* opt_hdr = (BYTE*)fetch_opt_hdr(payload, buffer_size, payload_nt_hdr);
311 if (!validate_ptr((const LPVOID)payload, buffer_size, opt_hdr, opt_size)) {
312 return nullptr;
313 }
314 //sections headers starts right after the end of the optional header
315 return (LPVOID)(opt_hdr + opt_size);
316 }
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) {
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
487IMAGE_COR20_HEADER * peconv::get_dotnet_hdr(IN const BYTE* module, IN size_t const module_size, IN const IMAGE_DATA_DIRECTORY * dotNetDir)
488{
489 DWORD rva = dotNetDir->VirtualAddress;
490 DWORD hdr_size = dotNetDir->Size;
491 if (!peconv::validate_ptr(module, module_size, module + rva, hdr_size)) {
492 return nullptr;
493 }
494 IMAGE_COR20_HEADER *dnet_hdr = (IMAGE_COR20_HEADER*)(module + rva);
495 if (!peconv::validate_ptr(module, module_size, module + dnet_hdr->MetaData.VirtualAddress, dnet_hdr->MetaData.Size)) {
496 return nullptr;
497 }
498 DWORD* signature_ptr = (DWORD*)(module + dnet_hdr->MetaData.VirtualAddress);
499 const DWORD dotNetSign = 0x424A5342;
500 if (*signature_ptr != dotNetSign) {
501 //invalid header
502 return nullptr;
503 }
504 return dnet_hdr;
505}
506
507namespace {
508
509 template <typename IMAGE_NT_HEADERS_T>
510 DWORD* _get_sec_alignment_ptr(const BYTE* modulePtr, const bool is_raw)
511 {
512 IMAGE_NT_HEADERS_T* hdrs = reinterpret_cast<IMAGE_NT_HEADERS_T*>(peconv::get_nt_hdrs(modulePtr));
513 if (!hdrs) return nullptr;
514 if (is_raw) {
515 return &hdrs->OptionalHeader.FileAlignment;
516 }
517 return &hdrs->OptionalHeader.SectionAlignment;
518 }
519
520};
521
522DWORD peconv::get_sec_alignment(IN const BYTE* modulePtr, IN bool is_raw)
523{
524 DWORD* alignment = 0;
525 if (peconv::is64bit(modulePtr)) {
526 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
527 } else {
528 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
529 }
530 if (!alignment) return 0;
531 return *alignment;
532}
533
534bool peconv::set_sec_alignment(IN OUT BYTE* modulePtr, IN const bool is_raw, IN const DWORD new_alignment)
535{
536 DWORD* alignment = 0;
537 if (peconv::is64bit(modulePtr)) {
538 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
539 }
540 else {
541 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
542 }
543 if (!alignment) return false;
544
545 *alignment = new_alignment;
546 return true;
547}
548
549DWORD peconv::get_virtual_sec_size(IN const BYTE* pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
550{
551 if (!pe_hdr || !sec_hdr) {
552 return 0;
553 }
554 if (!rounded) {
555 return sec_hdr->Misc.VirtualSize;
556 }
557 // calculate real size, round up to Virtual Alignment
558 const DWORD alignment = peconv::get_sec_alignment((const PBYTE)pe_hdr, false);
559 DWORD vsize = peconv::round_up_to_unit(sec_hdr->Misc.VirtualSize, alignment);
560 const DWORD image_size = peconv::get_image_size(pe_hdr);
561 // if it is bigger than the image size, use the size from the headers
562 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
563 vsize = sec_hdr->Misc.VirtualSize;
564 }
565 return vsize;
566}
567
568PIMAGE_SECTION_HEADER peconv::get_last_section(IN const PBYTE pe_buffer, IN const size_t pe_size, IN const bool is_raw)
569{
570 SIZE_T module_end = peconv::get_hdrs_size(pe_buffer);
571 const size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
572 if (sections_count == 0) {
573 return nullptr;
574 }
575 PIMAGE_SECTION_HEADER last_sec = nullptr;
576 //walk through sections
577 for (size_t i = 0; i < sections_count; i++) {
578 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
579 if (!sec) break;
580
581 const size_t raw_end = sec->PointerToRawData + sec->SizeOfRawData;
582 const size_t virt_end = sec->VirtualAddress + sec->Misc.VirtualSize;
583 if (raw_end < sec->PointerToRawData || virt_end < sec->VirtualAddress) {
584 LOG_WARNING("Wrap on section [%lld] size: exceeding DWORD value", (unsigned long long)i);
585 continue;
586 }
587 const size_t new_end = is_raw ? raw_end : virt_end;
588 if (new_end > module_end) {
589 module_end = new_end;
590 last_sec = sec;
591 }
592 }
593 return last_sec;
594}
595
596DWORD peconv::calc_pe_size(IN const PBYTE pe_buffer, IN const size_t pe_size, IN const bool is_raw)
597{
598 DWORD module_end = peconv::get_hdrs_size(pe_buffer);
599 const size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
600 if (sections_count == 0) {
601 return module_end;
602 }
603 //walk through sections
604 for (size_t i = 0; i < sections_count; i++) {
605 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
606 if (!sec) break;
607
608 const DWORD raw_end = sec->PointerToRawData + sec->SizeOfRawData;
609 const DWORD virt_end = sec->VirtualAddress + sec->Misc.VirtualSize;
610 if (raw_end < sec->PointerToRawData || virt_end < sec->VirtualAddress) {
611 LOG_WARNING("Wrap on section [%lld] size: exceeding DWORD value", (unsigned long long)i);
612 continue;
613 }
614 const DWORD new_end = is_raw ? raw_end : virt_end;
615 if (new_end > module_end) {
616 module_end = new_end;
617 }
618 }
619 return module_end;
620}
621
622bool peconv::is_valid_sections_alignment(IN const BYTE* payload, IN const SIZE_T payload_size, IN const bool is_raw)
623{
624 if (!payload) return false;
625
626 const DWORD my_align = peconv::get_sec_alignment(payload, is_raw);
627 if (my_align == 0) {
628 LOG_DEBUG("Section alignment cannot be 0.");
629 return false;
630 }
631 const size_t sections_count = peconv::get_sections_count(payload, payload_size);
632 if (sections_count == 0) {
633 //no sections
634 return false;
635 }
636 for (size_t i = 0; i < sections_count; i++) {
637 PIMAGE_SECTION_HEADER next_sec = peconv::get_section_hdr(payload, payload_size, i);
638 if (!next_sec) return false; //the number of the sections in header is out of scope
639
640 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
641
642 SIZE_T sec_size = is_raw ? next_sec->SizeOfRawData : next_sec->Misc.VirtualSize;
643 if (sec_size == 0) continue;
644 if (next_sec->Misc.VirtualSize == 0) {
645 continue; // if the VirtualSize == 0 the section will not be mapped anyways
646 }
647 if (next_sec_addr == 0) {
648 //if cannot be 0 if the size is not 0
649 return false;
650 }
651
652 //check only if raw_align is non-zero
653 if (next_sec_addr % my_align != 0) {
654 LOG_DEBUG("Section is misaligned.");
655 return false; //misaligned
656 }
657 }
658 return true;
659}
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
Definition: logger.h:80
#define LOG_WARNING(fmt,...)
Definition: logger.h:68
bool update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD ep)
bool has_relocations(IN const BYTE *pe_buffer)
DWORD get_entry_point_rva(IN const BYTE *pe_buffer)
bool set_sec_alignment(IN OUT BYTE *pe_buffer, IN const bool is_raw, IN const DWORD new_alignment)
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)
PIMAGE_SECTION_HEADER get_last_section(IN const PBYTE pe_buffer, IN const size_t pe_size, IN const bool is_raw)
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 const 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)
Definition: buffer_util.cpp:9
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)
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
Definition: util.h:43
bool is64bit(IN const BYTE *pe_buffer)
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
Definition: util.cpp:156
DWORD calc_pe_size(IN const PBYTE pe_buffer, IN const size_t pe_size, IN const bool is_raw)
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)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0, IN OPTIONAL const LONG max_pe_offset=MAX_HEADER_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)
WORD get_dll_characteristics(IN const BYTE *payload)
IMAGE_EXPORT_DIRECTORY * get_export_directory(IN HMODULE modulePtr)
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)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
Miscellaneous utility functions.