12 if (!pe_buffer)
return nullptr;
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))) {
25 if (idh->e_magic != IMAGE_DOS_SIGNATURE) {
28 const LONG kMaxOffset = 1024;
29 LONG pe_offset = idh->e_lfanew;
31 if (pe_offset > kMaxOffset)
return nullptr;
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))) {
45 if (inh->Signature != IMAGE_NT_SIGNATURE) {
53 if (!payload)
return nullptr;
56 if (!ptr)
return nullptr;
59 return (IMAGE_NT_HEADERS32*)ptr;
66 if (payload ==
nullptr)
return nullptr;
69 if (!ptr)
return nullptr;
72 return (IMAGE_NT_HEADERS64*)ptr;
85 image_size = nt64->OptionalHeader.SizeOfImage;
88 image_size = nt32->OptionalHeader.SizeOfImage;
100 nt64->OptionalHeader.SizeOfImage = image_size;
104 nt32->OptionalHeader.SizeOfImage = image_size;
114 IMAGE_NT_HEADERS32 *inh =
static_cast<IMAGE_NT_HEADERS32*
>(ptr);
118 return inh->OptionalHeader.Magic;
124 if (arch == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
132 if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
return nullptr;
135 if (!nt_headers)
return nullptr;
137 IMAGE_DATA_DIRECTORY* peDir =
nullptr;
139 IMAGE_NT_HEADERS64* nt_headers64 = (IMAGE_NT_HEADERS64*)nt_headers;
140 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
143 IMAGE_NT_HEADERS32* nt_headers64 = (IMAGE_NT_HEADERS32*)nt_headers;
144 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
146 if (!allow_empty && peDir->VirtualAddress == NULL) {
154 bool is64b =
is64bit(pe_buffer);
157 if (!payload_nt_hdr) {
160 ULONGLONG img_base = 0;
162 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
163 img_base = payload_nt_hdr64->OptionalHeader.ImageBase;
165 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
166 img_base =
static_cast<ULONGLONG
>(payload_nt_hdr32->OptionalHeader.ImageBase);
175 if (!payload_nt_hdr) {
178 const bool is64b =
is64bit(pe_buffer);
181 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
182 value = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint;
184 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
185 value = payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint;
192 bool is64b =
is64bit(pe_buffer);
195 if (!payload_nt_hdr) {
199 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
200 payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint = value;
202 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
203 payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint = value;
210 bool is64b =
is64bit(pe_buffer);
212 if (!payload_nt_hdr) {
217 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
218 hdrs_size = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
220 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
221 hdrs_size = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
230 if (!payload_nt_hdr) {
234 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
235 payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
238 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
239 payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase;
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)
247 if (!payload || !payload_nt_hdr)
return nullptr;
249 const IMAGE_FILE_HEADER *fileHdr = &(payload_nt_hdr->FileHeader);
251 if (!
validate_ptr((
const LPVOID)payload, buffer_size, (
const LPVOID)fileHdr,
sizeof(IMAGE_FILE_HEADER))) {
259 if (!payload)
return nullptr;
261 BYTE* payload_nt_hdr =
get_nt_hdrs(payload, buffer_size);
262 if (!payload_nt_hdr) {
266 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
268 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
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)
274 if (!payload)
return nullptr;
276 const IMAGE_FILE_HEADER *fileHdr = fetch_file_hdr<IMAGE_NT_HEADERS_T>(payload, buffer_size, payload_nt_hdr);
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)) {
290 if (!payload)
return nullptr;
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) {
298 return fetch_opt_hdr<IMAGE_NT_HEADERS64>(payload,buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
300 return fetch_opt_hdr<IMAGE_NT_HEADERS32>(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
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)
306 const IMAGE_FILE_HEADER *fileHdr = fetch_file_hdr<IMAGE_NT_HEADERS_T>(payload, buffer_size, payload_nt_hdr);
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)) {
316 return (LPVOID)(opt_hdr + opt_size);
321 const IMAGE_FILE_HEADER* fileHdr =
get_file_hdr(payload, buffer_size);
325 return fileHdr->NumberOfSections;
331 if (sec_count == 0) {
335 PIMAGE_SECTION_HEADER last_hdr =
get_section_hdr(buffer, buffer_size, sec_count - 1);
345 if (!payload)
return nullptr;
348 if (section_num >= sections_count) {
353 if (!nt_hdrs)
return nullptr;
355 LPVOID secptr =
nullptr;
358 secptr = fetch_section_hdrs_ptr<IMAGE_NT_HEADERS64>(payload, buffer_size, (IMAGE_NT_HEADERS64*)nt_hdrs);
361 secptr = fetch_section_hdrs_ptr<IMAGE_NT_HEADERS32>(payload, buffer_size, (IMAGE_NT_HEADERS32*)nt_hdrs);
364 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)(
365 (ULONGLONG)secptr + (IMAGE_SIZEOF_SECTION_HEADER * section_num)
368 if (!
validate_ptr((
const LPVOID) payload, buffer_size, (
const LPVOID) next_sec,
sizeof(IMAGE_SECTION_HEADER))) {
376 if (!payload)
return 0;
380 if (!payload_nt_hdr) {
383 IMAGE_FILE_HEADER *fileHdr =
nullptr;
385 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
386 fileHdr = &(payload_nt_hdr64->FileHeader);
389 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
390 fileHdr = &(payload_nt_hdr32->FileHeader);
392 return fileHdr->Characteristics;
397 if (!payload)
return false;
399 return ((charact & IMAGE_FILE_DLL) != 0);
404 if (!payload)
return 0;
408 if (!payload_nt_hdr) {
413 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
414 charact = payload_nt_hdr64->OptionalHeader.DllCharacteristics;
417 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
418 charact = payload_nt_hdr32->OptionalHeader.DllCharacteristics;
425 if (!payload)
return false;
429 if (!payload_nt_hdr) {
433 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
434 payload_nt_hdr64->OptionalHeader.Subsystem = subsystem;
436 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
437 payload_nt_hdr32->OptionalHeader.Subsystem = subsystem;
444 if (!payload)
return 0;
447 if (payload_nt_hdr == NULL) {
450 const bool is64b =
is64bit(payload);
452 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
453 return payload_nt_hdr64->OptionalHeader.Subsystem;
455 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
456 return payload_nt_hdr32->OptionalHeader.Subsystem;
462 IMAGE_DATA_DIRECTORY* relocDir =
get_directory_entry(pe_buffer, IMAGE_DIRECTORY_ENTRY_BASERELOC);
471 return get_type_directory<IMAGE_EXPORT_DIRECTORY>(modulePtr, IMAGE_DIRECTORY_ENTRY_EXPORT);
475IMAGE_COR20_HEADER *
peconv::get_dotnet_hdr(IN
const BYTE* module, IN
size_t const module_size, IN
const IMAGE_DATA_DIRECTORY * dotNetDir)
477 DWORD rva = dotNetDir->VirtualAddress;
478 DWORD hdr_size = dotNetDir->Size;
482 IMAGE_COR20_HEADER *dnet_hdr = (IMAGE_COR20_HEADER*)(module + rva);
483 if (!
peconv::validate_ptr(module, module_size, module + dnet_hdr->MetaData.VirtualAddress, dnet_hdr->MetaData.Size)) {
486 DWORD* signature_ptr = (DWORD*)(module + dnet_hdr->MetaData.VirtualAddress);
487 const DWORD dotNetSign = 0x424A5342;
488 if (*signature_ptr != dotNetSign) {
495template <
typename IMAGE_NT_HEADERS_T>
498 IMAGE_NT_HEADERS_T* hdrs =
reinterpret_cast<IMAGE_NT_HEADERS_T*
>(
peconv::get_nt_hdrs(modulePtr));
499 if (!hdrs)
return nullptr;
501 return &hdrs->OptionalHeader.FileAlignment;
503 return &hdrs->OptionalHeader.SectionAlignment;
508 DWORD* alignment = 0;
510 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
512 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
514 if (!alignment)
return 0;
520 DWORD* alignment = 0;
522 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS64>(modulePtr, is_raw);
525 alignment = _get_sec_alignment_ptr<IMAGE_NT_HEADERS32>(modulePtr, is_raw);
527 if (!alignment)
return false;
529 *alignment = new_alignment;
535 if (!pe_hdr || !sec_hdr) {
539 return sec_hdr->Misc.VirtualSize;;
543 DWORD vsize = sec_hdr->Misc.VirtualSize;
545 DWORD units = vsize / alignment;
546 if ((vsize % alignment) > 0) units++;
548 vsize = units * alignment;
552 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
553 vsize = sec_hdr->Misc.VirtualSize;
562 if (sections_count == 0) {
565 PIMAGE_SECTION_HEADER last_sec =
nullptr;
567 for (
size_t i = 0; i < sections_count; i++) {
571 size_t new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
572 if (new_end > module_end) {
573 module_end = new_end;
584 if (sections_count == 0) {
588 for (
size_t i = 0; i < sections_count; i++) {
592 DWORD new_end = is_raw ? (sec->PointerToRawData + sec->SizeOfRawData) : (sec->VirtualAddress + sec->Misc.VirtualSize);
593 if (new_end > module_end) module_end = new_end;
600 if (payload == NULL)
return false;
605 std::cout <<
"Section alignment cannot be 0\n";
610 if (sections_count == 0) {
614 for (
size_t i = 0; i < sections_count; i++) {
616 if (!next_sec)
return false;
618 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
620 SIZE_T sec_size = is_raw ? next_sec->SizeOfRawData : next_sec->Misc.VirtualSize;
621 if (sec_size == 0)
continue;
622 if (next_sec->Misc.VirtualSize == 0) {
625 if (next_sec_addr == 0) {
631 if (my_align && next_sec_addr % my_align != 0) {
633 std::cout <<
"Section is misaligned\n";
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 validate_ptr(IN const void *buffer_bgn, IN SIZE_T buffer_size, IN const void *field_bgn, IN SIZE_T field_size)
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)
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)
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)
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.