11bool sections_raw_to_virtual(IN
const BYTE* payload, IN SIZE_T payloadSize, OUT BYTE* destBuffer, IN SIZE_T destBufferSize)
13 if (!payload || !destBuffer)
return false;
15 BYTE* payload_nt_hdr =
get_nt_hdrs(payload, payloadSize);
16 if (!payload_nt_hdr) {
17 LOG_ERROR(
"Invalid PE at 0x%llx.", (
unsigned long long)payload);
21 const bool is64b =
is64bit(payload);
23 IMAGE_FILE_HEADER *fileHdr =
nullptr;
25 void* secptr =
nullptr;
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 = (
void*)((ULONG_PTR)&(payload_nt_hdr64->OptionalHeader) + fileHdr->SizeOfOptionalHeader);
33 IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr;
34 fileHdr = &(payload_nt_hdr32->FileHeader);
35 hdrsSize = payload_nt_hdr32->OptionalHeader.SizeOfHeaders;
36 secptr = (
void*)((ULONG_PTR)&(payload_nt_hdr32->OptionalHeader) + fileHdr->SizeOfOptionalHeader);
40 for (WORD i = 0; i < fileHdr->NumberOfSections; i++) {
41 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)((ULONG_PTR)secptr + ((ULONG_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
42 if (!
validate_ptr(
static_cast<const void*
>(payload), payloadSize, next_sec, IMAGE_SIZEOF_SECTION_HEADER)) {
45 const BYTE* next_sec_dest = destBuffer + (
reinterpret_cast<const BYTE*
>(next_sec) - payload);
46 if (!
validate_ptr(
static_cast<const void*
>(destBuffer), destBufferSize, next_sec_dest, IMAGE_SIZEOF_SECTION_HEADER)) {
49 if (next_sec->PointerToRawData == 0 || next_sec->SizeOfRawData == 0) {
52 void* section_mapped = destBuffer + next_sec->VirtualAddress;
53 void* section_raw_ptr = (BYTE*)payload + next_sec->PointerToRawData;
54 size_t sec_size = next_sec->SizeOfRawData;
56 if ((next_sec->VirtualAddress + sec_size) > destBufferSize) {
57 sec_size = (destBufferSize > next_sec->VirtualAddress) ? SIZE_T(destBufferSize - next_sec->VirtualAddress) : 0;
58 LOG_WARNING(
"Section %u: virtual size exceeds buffer, truncating to 0x%zx (buffer: 0x%zx).", i, sec_size, destBufferSize);
60 if (next_sec->VirtualAddress >= destBufferSize && sec_size != 0) {
61 LOG_ERROR(
"Section %u: VirtualAddress 0x%lx is out of bounds.", i, next_sec->VirtualAddress);
64 if (next_sec->PointerToRawData + sec_size > destBufferSize) {
65 LOG_ERROR(
"Section %u: raw data exceeds buffer (size: 0x%zx).", i, sec_size);
70 if (!
validate_ptr(
static_cast<const void*
>(payload), payloadSize, section_raw_ptr, sec_size)) {
71 if (next_sec->PointerToRawData > payloadSize) {
72 LOG_WARNING(
"Section %u: PointerToRawData out of bounds, skipping.", i);
76 sec_size = payloadSize - (next_sec->PointerToRawData);
80 LOG_WARNING(
"Section %u: destination out of bounds, skipping.", i);
83 ::memcpy(section_mapped, section_raw_ptr, sec_size);
84 if (first_raw == 0 || (next_sec->PointerToRawData < first_raw)) {
85 first_raw = next_sec->PointerToRawData;
90 if (hdrsSize == 0 || hdrsSize > payloadSize) {
93 if (hdrsSize > payloadSize) hdrsSize = payloadSize;
94 LOG_INFO(
"SizeOfHeaders invalid, using a fallback value: 0x%lx.", hdrsSize);
96 if (hdrsSize > destBufferSize) {
99 ::memcpy(destBuffer, payload, hdrsSize);
104 IN
const BYTE* payload,
106 OUT
size_t &out_size,
107 IN OPTIONAL
bool executable,
108 IN OPTIONAL ULONG_PTR desired_base
114 LOG_ERROR(
"Invalid PE at 0x%llx.", (
unsigned long long)(ULONG_PTR)payload);
117 DWORD payloadImageSize = 0;
119 const bool is64 =
is64bit(payload);
121 IMAGE_NT_HEADERS64* payload_nt_hdr = (IMAGE_NT_HEADERS64*)nt_hdr;
122 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
125 IMAGE_NT_HEADERS32* payload_nt_hdr = (IMAGE_NT_HEADERS32*)nt_hdr;
126 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
130 DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
133 BYTE* localCopyAddress =
alloc_pe_buffer(payloadImageSize, protect,
reinterpret_cast<void*
>(desired_base));
134 if (!localCopyAddress) {
135 LOG_ERROR(
"Could not allocate memory in the current process.");
138 LOG_DEBUG(
"Allocated local memory: %p size: %x", localCopyAddress, payloadImageSize);
140 LOG_ERROR(
"Could not copy PE file into virtual buffer.");
144 out_size = payloadImageSize;
145 return localCopyAddress;
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
#define LOG_INFO(fmt,...)
#define LOG_ERROR(fmt,...)
#define LOG_WARNING(fmt,...)
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)
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0)
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
bool is64bit(IN const BYTE *pe_buffer)
BYTE * pe_raw_to_virtual(IN const BYTE *rawPeBuffer, IN size_t rawPeSize, OUT size_t &outputSize, IN OPTIONAL bool executable=true, IN OPTIONAL ULONG_PTR desired_base=0)
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)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
bool sections_raw_to_virtual(IN const BYTE *payload, IN SIZE_T payloadSize, OUT BYTE *destBuffer, IN SIZE_T destBufferSize)
Converting PE from raw to virtual format.
Miscellaneous utility functions.