libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
pe_raw_to_virtual.cpp
Go to the documentation of this file.
2
3#include "peconv/util.h"
5
6#include <iostream>
7
8using namespace peconv;
9
10// Map raw PE into virtual memory of local process:
11bool sections_raw_to_virtual(IN const BYTE* payload, IN SIZE_T payloadSize, OUT BYTE* destBuffer, IN SIZE_T destBufferSize)
12{
13 if (!payload || !destBuffer) return false;
14
15 BYTE* payload_nt_hdr = get_nt_hdrs(payload, payloadSize);
16 if (payload_nt_hdr == NULL) {
17 std::cerr << "Invalid payload: " << std::hex << (ULONGLONG) payload << std::endl;
18 return false;
19 }
20
21 const bool is64b = is64bit(payload);
22
23 IMAGE_FILE_HEADER *fileHdr = NULL;
24 DWORD hdrsSize = 0;
25 LPVOID secptr = NULL;
26 if (is64b) {
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);
31 }
32 else {
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 = (LPVOID)((ULONGLONG)&(payload_nt_hdr32->OptionalHeader) + fileHdr->SizeOfOptionalHeader);
37 }
38 DWORD first_raw = 0;
39 //copy all the sections, one by one:
40 for (WORD i = 0; i < fileHdr->NumberOfSections; i++) {
41 PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)((ULONGLONG)secptr + ((ULONGLONG)IMAGE_SIZEOF_SECTION_HEADER * i));
42 if (!validate_ptr((const LPVOID)payload, payloadSize, next_sec, IMAGE_SIZEOF_SECTION_HEADER) // check if fits in the source size
43 || !validate_ptr((const LPVOID)payload, destBufferSize, next_sec, IMAGE_SIZEOF_SECTION_HEADER)) // check if fits in the destination size
44 {
45 return false;
46 }
47 if (next_sec->PointerToRawData == 0 || next_sec->SizeOfRawData == 0) {
48 continue; //skipping empty
49 }
50 LPVOID section_mapped = destBuffer + next_sec->VirtualAddress;
51 LPVOID section_raw_ptr = (BYTE*)payload + next_sec->PointerToRawData;
52 size_t sec_size = next_sec->SizeOfRawData;
53
54 if ((next_sec->VirtualAddress + sec_size) > destBufferSize) {
55 std::cerr << "[!] Virtual section size is out ouf bounds: " << std::hex << sec_size << std::endl;
56 sec_size = (destBufferSize > next_sec->VirtualAddress) ? SIZE_T(destBufferSize - next_sec->VirtualAddress) : 0;
57 std::cerr << "[!] Truncated to maximal size: " << std::hex << sec_size << ", buffer size:" << destBufferSize << std::endl;
58 }
59 if (next_sec->VirtualAddress >= destBufferSize && sec_size != 0) {
60 std::cerr << "[-] VirtualAddress of section is out ouf bounds: " << std::hex << next_sec->VirtualAddress << std::endl;
61 return false;
62 }
63 if (next_sec->PointerToRawData + sec_size > destBufferSize) {
64 std::cerr << "[-] Raw section size is out ouf bounds: " << std::hex << sec_size << std::endl;
65 return false;
66 }
67
68 // validate source:
69 if (!validate_ptr((const LPVOID)payload, payloadSize, section_raw_ptr, sec_size)) {
70 if (next_sec->PointerToRawData > payloadSize) {
71 std::cerr << "[-] Section " << i << ": out ouf bounds, skipping... " << std::endl;
72 continue;
73 }
74 // trim section
75 sec_size = payloadSize - (next_sec->PointerToRawData);
76 }
77 // validate destination:
78 if (!peconv::validate_ptr(destBuffer, destBufferSize, section_mapped, sec_size)) {
79 std::cerr << "[-] Section " << i << ": out ouf bounds, skipping... " << std::endl;
80 continue;
81 }
82 memcpy(section_mapped, section_raw_ptr, sec_size);
83 if (first_raw == 0 || (next_sec->PointerToRawData < first_raw)) {
84 first_raw = next_sec->PointerToRawData;
85 }
86 }
87
88 //copy payload's headers:
89 if (hdrsSize == 0) {
90 hdrsSize= first_raw;
91#ifdef _DEBUG
92 std::cout << "hdrsSize not filled, using calculated size: " << std::hex << hdrsSize << "\n";
93#endif
94 }
95 if (!validate_ptr((const LPVOID)payload, destBufferSize, (const LPVOID)payload, hdrsSize)) {
96 return false;
97 }
98 memcpy(destBuffer, payload, hdrsSize);
99 return true;
100}
101
103 IN const BYTE* payload,
104 IN size_t in_size,
105 OUT size_t &out_size,
106 IN OPTIONAL bool executable,
107 IN OPTIONAL ULONGLONG desired_base
108)
109{
110 //check payload:
111 BYTE* nt_hdr = get_nt_hdrs(payload);
112 if (nt_hdr == NULL) {
113 std::cerr << "Invalid payload: " << std::hex << (ULONGLONG) payload << std::endl;
114 return nullptr;
115 }
116 DWORD payloadImageSize = 0;
117
118 const bool is64 = is64bit(payload);
119 if (is64) {
120 IMAGE_NT_HEADERS64* payload_nt_hdr = (IMAGE_NT_HEADERS64*)nt_hdr;
121 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
122 }
123 else {
124 IMAGE_NT_HEADERS32* payload_nt_hdr = (IMAGE_NT_HEADERS32*)nt_hdr;
125 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
126 }
127 payloadImageSize = peconv::round_up_to_unit(payloadImageSize, (DWORD)PAGE_SIZE);
128
129 DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
130 //first we will prepare the payload image in the local memory, so that it will be easier to edit it, apply relocations etc.
131 //when it will be ready, we will copy it into the space reserved in the target process
132 BYTE* localCopyAddress = alloc_pe_buffer(payloadImageSize, protect, desired_base);
133 if (localCopyAddress == NULL) {
134 std::cerr << "Could not allocate memory in the current process" << std::endl;
135 return NULL;
136 }
137 //printf("Allocated local memory: %p size: %x\n", localCopyAddress, payloadImageSize);
138 if (!sections_raw_to_virtual(payload, in_size, (BYTE*)localCopyAddress, payloadImageSize)) {
139 std::cerr << "Could not copy PE file" << std::endl;
140 return NULL;
141 }
142 out_size = payloadImageSize;
143 return localCopyAddress;
144}
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, ULONGLONG desired_base=NULL)
BYTE * pe_raw_to_virtual(IN const BYTE *rawPeBuffer, IN size_t rawPeSize, OUT size_t &outputSize, IN OPTIONAL bool executable=true, IN OPTIONAL ULONGLONG desired_base=0)
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
bool is64bit(IN const BYTE *pe_buffer)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
#define PAGE_SIZE
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.