13 if (!payload || !destAddress)
return false;
15 BYTE* payload_nt_hdr =
get_nt_hdrs(payload, payload_size);
16 if (payload_nt_hdr == NULL) {
17 LOG_ERROR(
"Invalid PE at 0x%llx.", (
unsigned long long)payload);
21 const bool is64b =
is64bit(payload);
23 IMAGE_FILE_HEADER *fileHdr = NULL;
27 IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*) payload_nt_hdr;
28 fileHdr = &(payload_nt_hdr64->FileHeader);
29 hdrsSize = payload_nt_hdr64->OptionalHeader.SizeOfHeaders;
30 secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr64->OptionalHeader) + fileHdr->SizeOfOptionalHeader);
32 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*) payload_nt_hdr;
33 fileHdr = &(payload_nt_hdr32->FileHeader);
34 hdrsSize = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
35 secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr32->OptionalHeader) + fileHdr->SizeOfOptionalHeader);
41 SIZE_T raw_end = hdrsSize;
42 for (WORD i = 0; i < fileHdr->NumberOfSections; i++) {
43 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)((ULONGLONG)secptr + (IMAGE_SIZEOF_SECTION_HEADER * i));
44 if (!
validate_ptr(payload, payload_size, next_sec, IMAGE_SIZEOF_SECTION_HEADER)) {
48 LPVOID section_mapped = (BYTE*) payload + next_sec->VirtualAddress;
49 LPVOID section_raw_ptr = destAddress + next_sec->PointerToRawData;
50 SIZE_T sec_size = next_sec->SizeOfRawData;
52 size_t new_end = sec_size + next_sec->PointerToRawData;
53 if (new_end > raw_end) raw_end = new_end;
55 if ((next_sec->VirtualAddress + sec_size) > payload_size) {
56 sec_size = (payload_size > next_sec->VirtualAddress) ? SIZE_T(payload_size - next_sec->VirtualAddress) : 0;
57 LOG_WARNING(
"Section %u: virtual size exceeds buffer, truncating to 0x%zx.", i, sec_size);
59 if (next_sec->VirtualAddress >= payload_size && sec_size != 0) {
60 LOG_ERROR(
"Section %u: VirtualAddress 0x%lx is out of bounds.", i, next_sec->VirtualAddress);
63 if (next_sec->PointerToRawData + sec_size > payload_size) {
64 LOG_ERROR(
"Section %u: raw data exceeds buffer (size: 0x%zx).", i, sec_size);
67 LOG_DEBUG(
"Section %u: copying to raw offset %p.", i, section_raw_ptr);
70 LOG_WARNING(
"Section %u: source out of bounds, skipping.", i);
75 LOG_WARNING(
"Section %u: destination out of bounds, skipping.", i);
78 memcpy(section_raw_ptr, section_mapped, sec_size);
79 if (first_raw == 0 || (next_sec->PointerToRawData < first_raw)) {
80 first_raw = next_sec->PointerToRawData;
83 if (raw_end > payload_size) raw_end = payload_size;
84 if (raw_size_ptr != NULL) {
85 (*raw_size_ptr) = raw_end;
91 LOG_DEBUG(
"SizeOfHeaders not set, using first section raw offset as fallback: 0x%lx.", hdrsSize);
93 if (!
validate_ptr(payload, payload_size, payload, hdrsSize)) {
96 memcpy(destAddress, payload, hdrsSize);
103 IN ULONGLONG loadBase,
104 OUT
size_t &out_size,
105 IN OPTIONAL
bool rebuffer
109 if (out_buf == NULL)
return NULL;
111 BYTE* in_buf = payload;
114 if (in_buf == NULL) {
118 memcpy(in_buf, payload, in_size);
127 LOG_ERROR(
"Failed relocating the module.");
130 LOG_WARNING(
"The module could not be relocated, so the ImageBase has been changed instead.");
139 if (rebuffer && in_buf != NULL) {
153 IN
const BYTE* payload,
155 IN ULONGLONG loadBase,
165 memcpy(out_buf, payload, in_size);
173 LOG_ERROR(
"Failed relocating the module.");
176 LOG_WARNING(
"The module could not be relocated, so the ImageBase has been changed instead.");
187 for (
size_t i = 0; i < sections_count; i++) {
192 sec->SizeOfRawData = sec->Misc.VirtualSize;
193 sec->PointerToRawData = sec->VirtualAddress;
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
#define LOG_ERROR(fmt,...)
#define LOG_WARNING(fmt,...)
bool set_sec_alignment(IN OUT BYTE *pe_buffer, IN const bool is_raw, IN const DWORD new_alignment)
DWORD get_virtual_sec_size(IN const BYTE *pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
bool update_image_base(IN OUT BYTE *payload, IN ULONGLONG destImageBase)
ULONGLONG get_image_base(IN const BYTE *pe_buffer)
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, void *desired_base=nullptr)
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)
BYTE * pe_virtual_to_raw(IN BYTE *payload, IN size_t in_size, IN ULONGLONG loadBase, OUT size_t &outputSize, IN OPTIONAL bool rebuffer=true)
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0)
DWORD get_sec_alignment(IN const BYTE *modulePtr, IN bool is_raw)
bool is64bit(IN const BYTE *pe_buffer)
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_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)
bool relocate_module(IN PBYTE modulePtr, IN SIZE_T moduleSize, IN ULONGLONG newBase, IN ULONGLONG oldBase=0)
BYTE * pe_realign_raw_to_virtual(IN const BYTE *payload, IN size_t in_size, IN ULONGLONG loadBase, OUT size_t &outputSize)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
bool sections_virtual_to_raw(BYTE *payload, SIZE_T payload_size, OUT BYTE *destAddress, OUT SIZE_T *raw_size_ptr)
Converting PE from virtual to raw format.
Operating on PE file's relocations table.
Miscellaneous utility functions.