PE-sieve
Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).
Loading...
Searching...
No Matches
pe_buffer.cpp
Go to the documentation of this file.
1#include "pe_buffer.h"
2
3#include <iostream>
6
7size_t pesieve::PeBuffer::calcRemoteImgSize(ULONGLONG modBaseAddr) const
8{
9 const size_t hdr_buffer_size = PAGE_SIZE;
10 BYTE hdr_buffer[hdr_buffer_size] = { 0 };
11 size_t pe_vsize = 0;
12
13 PIMAGE_SECTION_HEADER hdr_ptr = NULL;
14 if (peconv::read_remote_pe_header(this->processHndl, (BYTE*)modBaseAddr, hdr_buffer, hdr_buffer_size)) {
15 hdr_ptr = peconv::get_section_hdr(hdr_buffer, hdr_buffer_size, 0);
16 }
17 if (!hdr_ptr) {
18 pe_vsize = peconv::fetch_region_size(this->processHndl, (PBYTE)modBaseAddr);
19 //std::cout << "[!] Image size at: " << std::hex << modBaseAddr << " undetermined, using region size instead: " << pe_vsize << std::endl;
20 return pe_vsize;
21 }
22 pe_vsize = ArtefactScanner::calcImgSize(this->processHndl, (HMODULE)modBaseAddr, hdr_buffer, hdr_buffer_size, hdr_ptr);
23 //std::cout << "[!] Image size at: " << std::hex << modBaseAddr << " undetermined, using calculated img size: " << pe_vsize << std::endl;
24 return pe_vsize;
25}
26
27bool pesieve::PeBuffer::readRemote(ULONGLONG module_base, size_t pe_vsize)
28{
29 if (pe_vsize == 0) {
30 // if not size supplied, try with the size fetched from the header
31 pe_vsize = peconv::get_remote_image_size(processHndl, (BYTE*)module_base);
32 }
33 if (_readRemote(module_base, pe_vsize)) {
34 return true; //success
35 }
36 // try with the calculated size
37 pe_vsize = calcRemoteImgSize(module_base);
38#ifdef _DEBUG
39 std::cout << "[!] Image size at: " << std::hex << module_base << " undetermined, using calculated size: " << pe_vsize << std::endl;
40#endif
41 return _readRemote(module_base, pe_vsize);
42}
43
44bool pesieve::PeBuffer::fillFromBuffer(ULONGLONG module_base, util::ByteBuffer& data_cache)
45{
46 size_t cached_size = data_cache.getDataSize();
47 if (!cached_size) {
48 return false;
49 }
50 if (!allocBuffer(cached_size)) {
51 return false;
52 }
53 this->moduleBase = module_base;
54 this->relocBase = module_base; //by default set the same as module base
55
56 ::memcpy(this->vBuf, data_cache.getData(), cached_size);
57 return true;
58}
59
60bool pesieve::PeBuffer::_readRemote(const ULONGLONG module_base, size_t pe_vsize)
61{
62 if (pe_vsize == 0) {
63 return false;
64 }
65 if (!allocBuffer(pe_vsize)) {
66 return false;
67 }
68
69 // store the base no matter if reading succeeded or failed
70 this->moduleBase = module_base;
71 this->relocBase = module_base; //by default set the same as module base
72
73 const bool can_force_access = this->isRefl ? true : false;
74 size_t read_size = peconv::read_remote_area(processHndl, (BYTE*)this->moduleBase, vBuf, pe_vsize, can_force_access);
75 if (read_size != pe_vsize) {
76#ifdef _DEBUG
77 std::cout << "[!] Failed reading Image at: " << std::hex << this->moduleBase << " img size: " << pe_vsize << std::endl;
78#endif
79 freeBuffer();
80 return false;
81 }
82 return true;
83}
84
86{
87 if (!vBuf) return false;
88
89 BYTE *new_buf = peconv::alloc_aligned(new_size, PAGE_READWRITE);
90 if (!new_buf) {
91 return false;
92 }
93
94 size_t smaller_size = (vBufSize < new_size) ? vBufSize : new_size;
95 memcpy(new_buf, this->vBuf, smaller_size);
96 freeBuffer();
97
98 this->vBuf = new_buf;
99 this->vBufSize = new_size;
100 return true;
101}
102
104{
105 if (!vBuf) return false;
106
107 PIMAGE_SECTION_HEADER last_sec = peconv::get_last_section(vBuf, vBufSize, false);
108 if (!last_sec) {
109 return false;
110 }
111
112 if (new_img_size < last_sec->VirtualAddress) {
113 return false;
114 }
115
116 const size_t new_sec_vsize = new_img_size - last_sec->VirtualAddress;
117 const size_t new_sec_rsize = new_sec_vsize;
118
119 if (last_sec->VirtualAddress + new_sec_vsize > this->vBufSize) {
120 //buffer too small
121 return false;
122 }
123
124 if (!peconv::update_image_size(vBuf, MASK_TO_DWORD(new_img_size))) {
125 return false;
126 }
127
128 last_sec->Misc.VirtualSize = MASK_TO_DWORD(new_sec_vsize);
129 last_sec->SizeOfRawData = MASK_TO_DWORD(new_sec_rsize);
130 return true;
131}
132
134 IN std::string dumpFileName,
135 IN OUT peconv::t_pe_dump_mode &dumpMode,
136 IN OPTIONAL const peconv::ExportsMapper* exportsMap,
137 OUT OPTIONAL peconv::ImpsNotCovered *notCovered
138)
139{
140 if (!vBuf || !isValidPe()) return false;
141#ifdef _DEBUG
142 std::cout << "Dumping using relocBase: " << std::hex << relocBase << "\n";
143#endif
144 if (exportsMap != nullptr) {
145 const bool fixed = peconv::fix_imports(this->vBuf, this->vBufSize, *exportsMap, notCovered);
146#ifdef _DEBUG
147 if (!fixed) {
148 std::cerr << "[-] Unable to fix imports!" << std::endl;
149 }
150#endif
151 }
152 if (dumpMode == peconv::PE_DUMP_AUTO) {
153 bool is_raw_alignment_valid = peconv::is_valid_sectons_alignment(vBuf, vBufSize, true);
154 bool is_virtual_alignment_valid = peconv::is_valid_sectons_alignment(vBuf, vBufSize, false);
155#ifdef _DEBUG
156 std::cout << "Is raw alignment valid: " << is_raw_alignment_valid << std::endl;
157 std::cout << "Is virtual alignment valid: " << is_virtual_alignment_valid << std::endl;
158#endif
159 if (!is_raw_alignment_valid && is_virtual_alignment_valid) {
160 //in case if raw alignment is invalid and virtual valid, try to dump using Virtual Alignment first
161 dumpMode = peconv::PE_DUMP_REALIGN;
162 bool is_dumped = peconv::dump_pe(dumpFileName.c_str(), this->vBuf, this->vBufSize, this->relocBase, dumpMode);
163 if (is_dumped) {
164 return is_dumped;
165 }
166 dumpMode = peconv::PE_DUMP_AUTO; //revert and try again
167 }
168 }
169 // dump PE in a given dump mode:
170 return peconv::dump_pe(dumpFileName.c_str(), this->vBuf, this->vBufSize, this->relocBase, dumpMode);
171}
172
173bool pesieve::PeBuffer::dumpToFile(IN std::string dumpFileName)
174{
175 if (!vBuf) return false;
176 return peconv::dump_to_file(dumpFileName.c_str(), vBuf, vBufSize);
177}
178
180{
181 if (!vBuf) return false;
182 return pesieve::util::is_code(vBuf, vBufSize);
183}
static size_t calcImgSize(HANDLE processHandle, HMODULE modBaseAddr, BYTE *headerBuffer, size_t headerBufferSize, IMAGE_SECTION_HEADER *hdr_ptr=NULL)
bool fillFromBuffer(ULONGLONG module_base, util::ByteBuffer &data_cache)
Definition pe_buffer.cpp:44
size_t calcRemoteImgSize(ULONGLONG module_base) const
Definition pe_buffer.cpp:7
bool _readRemote(ULONGLONG module_base, size_t pe_vsize)
Definition pe_buffer.cpp:60
bool readRemote(ULONGLONG module_base, size_t pe_vsize)
Definition pe_buffer.cpp:27
bool dumpPeToFile(IN std::string dumpFileName, IN OUT peconv::t_pe_dump_mode &dumpMode, IN OPTIONAL const peconv::ExportsMapper *exportsMap=NULL, OUT OPTIONAL peconv::ImpsNotCovered *notCovered=NULL)
bool resizeLastSection(size_t new_img_size)
bool resizeBuffer(size_t new_size)
Definition pe_buffer.cpp:85
bool dumpToFile(IN std::string dumpFileName)
#define MASK_TO_DWORD(val)
Definition iat_finder.h:9
bool is_code(BYTE *loadedData, size_t loadedSize)
size_t getDataSize(bool trimmed=false) const
Definition byte_buffer.h:55
const BYTE * getData(bool trimmed=false) const
Definition byte_buffer.h:65
#define PAGE_SIZE