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;
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) {
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)
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;
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 (!pe_buffer)
return false;
407 if (!dotnet_ptr)
return false;
417 if (!payload)
return 0;
421 if (!payload_nt_hdr) {
426 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
427 charact = payload_nt_hdr64->OptionalHeader.DllCharacteristics;
430 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
431 charact = payload_nt_hdr32->OptionalHeader.DllCharacteristics;
438 if (!payload)
return false;
442 if (!payload_nt_hdr) {
446 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
447 payload_nt_hdr64->OptionalHeader.Subsystem = subsystem;
449 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
450 payload_nt_hdr32->OptionalHeader.Subsystem = subsystem;
457 if (!payload)
return 0;
460 if (payload_nt_hdr == NULL) {
463 const bool is64b =
is64bit(payload);
465 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
466 return payload_nt_hdr64->OptionalHeader.Subsystem;
468 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
469 return payload_nt_hdr32->OptionalHeader.Subsystem;
475 IMAGE_DATA_DIRECTORY* relocDir =
get_directory_entry(pe_buffer, IMAGE_DIRECTORY_ENTRY_BASERELOC);
488IMAGE_COR20_HEADER *
peconv::get_dotnet_hdr(IN
const BYTE* module, IN
size_t const module_size, IN
const IMAGE_DATA_DIRECTORY * dotNetDir)
490 DWORD rva = dotNetDir->VirtualAddress;
491 DWORD hdr_size = dotNetDir->Size;
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)) {
499 DWORD* signature_ptr = (DWORD*)(module + dnet_hdr->MetaData.VirtualAddress);
500 const DWORD dotNetSign = 0x424A5342;
501 if (*signature_ptr != dotNetSign) {
508template <
typename IMAGE_NT_HEADERS_T>
511 IMAGE_NT_HEADERS_T* hdrs =
reinterpret_cast<IMAGE_NT_HEADERS_T*
>(
peconv::get_nt_hdrs(modulePtr));
512 if (!hdrs)
return nullptr;
514 return &hdrs->OptionalHeader.FileAlignment;
516 return &hdrs->OptionalHeader.SectionAlignment;
521 DWORD* alignment = 0;
527 if (!alignment)
return 0;
533 DWORD* alignment = 0;
540 if (!alignment)
return false;
542 *alignment = new_alignment;
548 if (!pe_hdr || !sec_hdr) {
552 return sec_hdr->Misc.VirtualSize;;
559 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
560 vsize = sec_hdr->Misc.VirtualSize;
569 if (sections_count == 0) {
572 PIMAGE_SECTION_HEADER last_sec =
nullptr;
574 for (
size_t i = 0; i < sections_count; i++) {
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;
591 if (sections_count == 0) {
595 for (
size_t i = 0; i < sections_count; i++) {
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;
607 if (payload == NULL)
return false;
612 std::cout <<
"Section alignment cannot be 0\n";
617 if (sections_count == 0) {
621 for (
size_t i = 0; i < sections_count; i++) {
623 if (!next_sec)
return false;
625 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
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) {
632 if (next_sec_addr == 0) {
638 if (my_align && next_sec_addr % my_align != 0) {
640 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 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)
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.