10 if (!pe_buffer)
return nullptr;
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))) {
23 if (idh->e_magic != IMAGE_DOS_SIGNATURE) {
26 const LONG kMaxOffset = 1024;
27 LONG pe_offset = idh->e_lfanew;
29 if (pe_offset < 0 || pe_offset > kMaxOffset)
return nullptr;
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))) {
43 if (inh->Signature != IMAGE_NT_SIGNATURE) {
51 if (!payload)
return nullptr;
54 if (!ptr)
return nullptr;
57 return (IMAGE_NT_HEADERS32*)ptr;
64 if (payload ==
nullptr)
return nullptr;
67 if (!ptr)
return nullptr;
70 return (IMAGE_NT_HEADERS64*)ptr;
83 image_size = nt64->OptionalHeader.SizeOfImage;
86 image_size = nt32->OptionalHeader.SizeOfImage;
98 nt64->OptionalHeader.SizeOfImage = image_size;
102 nt32->OptionalHeader.SizeOfImage = image_size;
112 IMAGE_NT_HEADERS32 *inh =
static_cast<IMAGE_NT_HEADERS32*
>(ptr);
116 return inh->OptionalHeader.Magic;
122 if (arch == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
130 if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
return nullptr;
133 if (!nt_headers)
return nullptr;
135 IMAGE_DATA_DIRECTORY* peDir =
nullptr;
137 IMAGE_NT_HEADERS64* nt_headers64 = (IMAGE_NT_HEADERS64*)nt_headers;
138 peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]);
141 IMAGE_NT_HEADERS32* nt_headers32 = (IMAGE_NT_HEADERS32*)nt_headers;
142 peDir = &(nt_headers32->OptionalHeader.DataDirectory[dir_id]);
144 if (!allow_empty && !peDir->VirtualAddress) {
152 bool is64b =
is64bit(pe_buffer);
155 if (!payload_nt_hdr) {
158 ULONGLONG img_base = 0;
160 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
161 img_base = payload_nt_hdr64->OptionalHeader.ImageBase;
163 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
164 img_base =
static_cast<ULONGLONG
>(payload_nt_hdr32->OptionalHeader.ImageBase);
172 if (!payload_nt_hdr) {
176 const bool is64b =
is64bit(pe_buffer);
178 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
179 value = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint;
181 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
182 value = payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint;
190 if (!payload_nt_hdr) {
193 const bool is64b =
is64bit(pe_buffer);
195 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
196 payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint = value;
198 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
199 payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint = value;
207 if (!payload_nt_hdr) {
210 const bool is64b =
is64bit(pe_buffer);
213 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
214 hdrs_size = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
216 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
217 hdrs_size = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
225 if (!payload_nt_hdr) {
228 const bool is64b =
is64bit(payload);
230 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
231 payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase;
234 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
235 payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase;
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)
243 if (!payload || !payload_nt_hdr)
return nullptr;
245 const IMAGE_FILE_HEADER *fileHdr = &(payload_nt_hdr->FileHeader);
247 if (!
validate_ptr((
const LPVOID)payload, buffer_size, (
const LPVOID)fileHdr,
sizeof(IMAGE_FILE_HEADER))) {
255 if (!payload)
return nullptr;
257 BYTE* payload_nt_hdr =
get_nt_hdrs(payload, buffer_size);
258 if (!payload_nt_hdr) {
262 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS64*)payload_nt_hdr);
264 return fetch_file_hdr(payload, buffer_size, (IMAGE_NT_HEADERS32*)payload_nt_hdr);
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)
270 if (!payload)
return nullptr;
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)) {
286 if (!payload)
return nullptr;
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) {
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)
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)) {
312 return (LPVOID)(opt_hdr + opt_size);
317 const IMAGE_FILE_HEADER* fileHdr =
get_file_hdr(payload, buffer_size);
321 return fileHdr->NumberOfSections;
327 if (sec_count == 0) {
331 PIMAGE_SECTION_HEADER last_hdr =
get_section_hdr(buffer, buffer_size, sec_count - 1);
341 if (!payload)
return nullptr;
344 if (section_num >= sections_count) {
349 if (!nt_hdrs)
return nullptr;
351 LPVOID secptr =
nullptr;
360 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)(
361 (ULONGLONG)secptr + (IMAGE_SIZEOF_SECTION_HEADER * section_num)
364 if (!
validate_ptr((
const LPVOID) payload, buffer_size, (
const LPVOID) next_sec,
sizeof(IMAGE_SECTION_HEADER))) {
372 if (!payload)
return 0;
376 if (!payload_nt_hdr) {
379 IMAGE_FILE_HEADER *fileHdr =
nullptr;
381 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
382 fileHdr = &(payload_nt_hdr64->FileHeader);
385 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
386 fileHdr = &(payload_nt_hdr32->FileHeader);
388 return fileHdr->Characteristics;
393 if (!payload)
return false;
395 return ((charact & IMAGE_FILE_DLL) != 0);
400 if (!pe_buffer)
return false;
403 if (!dotnet_ptr)
return false;
413 if (!payload)
return 0;
417 if (!payload_nt_hdr) {
422 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
423 charact = payload_nt_hdr64->OptionalHeader.DllCharacteristics;
426 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
427 charact = payload_nt_hdr32->OptionalHeader.DllCharacteristics;
434 if (!payload)
return false;
438 if (!payload_nt_hdr) {
442 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
443 payload_nt_hdr64->OptionalHeader.Subsystem = subsystem;
445 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
446 payload_nt_hdr32->OptionalHeader.Subsystem = subsystem;
453 if (!payload)
return 0;
456 if (!payload_nt_hdr) {
459 const bool is64b =
is64bit(payload);
461 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr;
462 return payload_nt_hdr64->OptionalHeader.Subsystem;
464 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
465 return payload_nt_hdr32->OptionalHeader.Subsystem;
471 IMAGE_DATA_DIRECTORY* relocDir =
get_directory_entry(pe_buffer, IMAGE_DIRECTORY_ENTRY_BASERELOC);
484IMAGE_COR20_HEADER *
peconv::get_dotnet_hdr(IN
const BYTE* module, IN
size_t const module_size, IN
const IMAGE_DATA_DIRECTORY * dotNetDir)
486 DWORD rva = dotNetDir->VirtualAddress;
487 DWORD hdr_size = dotNetDir->Size;
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)) {
495 DWORD* signature_ptr = (DWORD*)(module + dnet_hdr->MetaData.VirtualAddress);
496 const DWORD dotNetSign = 0x424A5342;
497 if (*signature_ptr != dotNetSign) {
504template <
typename IMAGE_NT_HEADERS_T>
507 IMAGE_NT_HEADERS_T* hdrs =
reinterpret_cast<IMAGE_NT_HEADERS_T*
>(
peconv::get_nt_hdrs(modulePtr));
508 if (!hdrs)
return nullptr;
510 return &hdrs->OptionalHeader.FileAlignment;
512 return &hdrs->OptionalHeader.SectionAlignment;
517 DWORD* alignment = 0;
523 if (!alignment)
return 0;
529 DWORD* alignment = 0;
536 if (!alignment)
return false;
538 *alignment = new_alignment;
544 if (!pe_hdr || !sec_hdr) {
548 return sec_hdr->Misc.VirtualSize;
555 if ((sec_hdr->VirtualAddress + vsize) > image_size) {
556 vsize = sec_hdr->Misc.VirtualSize;
565 if (sections_count == 0) {
568 PIMAGE_SECTION_HEADER last_sec =
nullptr;
570 for (
size_t i = 0; i < sections_count; i++) {
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;
587 if (sections_count == 0) {
591 for (
size_t i = 0; i < sections_count; i++) {
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;
603 if (!payload)
return false;
607 LOG_DEBUG(
"Section alignment cannot be 0.");
611 if (sections_count == 0) {
615 for (
size_t i = 0; i < sections_count; i++) {
617 if (!next_sec)
return false;
619 const DWORD next_sec_addr = is_raw ? (next_sec->PointerToRawData) : (next_sec->VirtualAddress);
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) {
626 if (next_sec_addr == 0) {
632 if (next_sec_addr % my_align != 0) {
#define LOG_DEBUG(fmt,...)
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)
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.