libPeConv
A library to load, manipulate, dump PE files.
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
39 DWORD first_raw = 0;
40 //copy all the sections, one by one:
41 SIZE_T raw_end = 0;
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((const LPVOID)payload, destBufferSize, next_sec, IMAGE_SIZEOF_SECTION_HEADER)) {
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 raw_end = next_sec->SizeOfRawData + next_sec->PointerToRawData;
54
55 if ((next_sec->VirtualAddress + sec_size) > destBufferSize) {
56 std::cerr << "[!] Virtual section size is out ouf bounds: " << std::hex << sec_size << std::endl;
57 sec_size = (destBufferSize > next_sec->VirtualAddress) ? SIZE_T(destBufferSize - next_sec->VirtualAddress) : 0;
58 std::cerr << "[!] Truncated to maximal size: " << std::hex << sec_size << ", buffer size:" << destBufferSize << std::endl;
59 }
60 if (next_sec->VirtualAddress >= destBufferSize && sec_size != 0) {
61 std::cerr << "[-] VirtualAddress of section is out ouf bounds: " << std::hex << next_sec->VirtualAddress << std::endl;
62 return false;
63 }
64 if (next_sec->PointerToRawData + sec_size > destBufferSize) {
65 std::cerr << "[-] Raw section size is out ouf bounds: " << std::hex << sec_size << std::endl;
66 return false;
67 }
68 // validate source:
69 if (!validate_ptr((const LPVOID)payload, payloadSize, section_raw_ptr, sec_size)) {
70 std::cerr << "[-] Section " << i << ": out ouf bounds, skipping... " << std::endl;
71 continue;
72 }
73 // validate destination:
74 if (!peconv::validate_ptr(destBuffer, destBufferSize, section_mapped, sec_size)) {
75 std::cerr << "[-] Section " << i << ": out ouf bounds, skipping... " << std::endl;
76 continue;
77 }
78 memcpy(section_mapped, section_raw_ptr, sec_size);
79 if (first_raw == 0 || (next_sec->PointerToRawData < first_raw)) {
80 first_raw = next_sec->PointerToRawData;
81 }
82 }
83
84 //copy payload's headers:
85 if (hdrsSize == 0) {
86 hdrsSize= first_raw;
87#ifdef _DEBUG
88 std::cout << "hdrsSize not filled, using calculated size: " << std::hex << hdrsSize << "\n";
89#endif
90 }
91 if (!validate_ptr((const LPVOID)payload, destBufferSize, (const LPVOID)payload, hdrsSize)) {
92 return false;
93 }
94 memcpy(destBuffer, payload, hdrsSize);
95 return true;
96}
97
99 IN const BYTE* payload,
100 IN size_t in_size,
101 OUT size_t &out_size,
102 IN OPTIONAL bool executable,
103 IN OPTIONAL ULONGLONG desired_base
104)
105{
106 //check payload:
107 BYTE* nt_hdr = get_nt_hdrs(payload);
108 if (nt_hdr == NULL) {
109 std::cerr << "Invalid payload: " << std::hex << (ULONGLONG) payload << std::endl;
110 return nullptr;
111 }
112 DWORD payloadImageSize = 0;
113
114 bool is64 = is64bit(payload);
115 if (is64) {
116 IMAGE_NT_HEADERS64* payload_nt_hdr = (IMAGE_NT_HEADERS64*)nt_hdr;
117 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
118 }
119 else {
120 IMAGE_NT_HEADERS32* payload_nt_hdr = (IMAGE_NT_HEADERS32*)nt_hdr;
121 payloadImageSize = payload_nt_hdr->OptionalHeader.SizeOfImage;
122 }
123
124 DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
125
126 //first we will prepare the payload image in the local memory, so that it will be easier to edit it, apply relocations etc.
127 //when it will be ready, we will copy it into the space reserved in the target process
128 BYTE* localCopyAddress = alloc_pe_buffer(payloadImageSize, protect, desired_base);
129 if (localCopyAddress == NULL) {
130 std::cerr << "Could not allocate memory in the current process" << std::endl;
131 return NULL;
132 }
133 //printf("Allocated local memory: %p size: %x\n", localCopyAddress, payloadImageSize);
134 if (!sections_raw_to_virtual(payload, in_size, (BYTE*)localCopyAddress, payloadImageSize)) {
135 std::cerr << "Could not copy PE file" << std::endl;
136 return NULL;
137 }
138 out_size = payloadImageSize;
139 return localCopyAddress;
140}
bool validate_ptr(IN const void *buffer_bgn, IN SIZE_T buffer_size, IN const void *field_bgn, IN SIZE_T field_size)
Definition: buffer_util.cpp:9
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, ULONGLONG desired_base=NULL)
Definition: buffer_util.cpp:78
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)
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.
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.