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
imp_reconstructor.h
Go to the documentation of this file.
1#pragma once
2
3#include <windows.h>
4#include <map>
5
6#include <peconv.h>
7#include "pe_sieve_types.h"
8
9#include "../pe_buffer.h"
10#include "iat_block.h"
11#include "../utils/artefacts_util.h"
12
13namespace pesieve {
14
16 {
17 public:
18
19 ImportTableBuffer(DWORD _descriptorsRVA)
20 : descriptors(nullptr), descriptosCount(0),
21 descriptorsRVA(_descriptorsRVA),
22 namesRVA(0), namesBuf(nullptr), namesBufSize(0),
23 dllsRVA(0), dllsBufSize(0), dllsBuf(nullptr)
24 {
25 }
26
28 {
29 delete[]descriptors;
30 delete[]namesBuf;
31 delete[]dllsBuf;
32 }
33
34 bool allocDesciptors(size_t descriptors_count)
35 {
36 descriptors = new(std::nothrow) IMAGE_IMPORT_DESCRIPTOR[descriptors_count];
37 if (!descriptors) {
38 return false;
39 }
40 memset(descriptors, 0, descriptors_count);
41 size_t size_bytes = sizeof(IMAGE_IMPORT_DESCRIPTOR) * descriptors_count;
42 memset(descriptors, 0, size_bytes);
43 descriptosCount = descriptors_count;
44 return true;
45 }
46
47 bool allocNamesSpace(DWORD names_rva, size_t names_size)
48 {
49 delete[]namesBuf;
50 this->namesBuf = new(std::nothrow) BYTE[names_size];
51 if (!this->namesBuf) {
52 this->namesBufSize = 0;
53 return false;
54 }
55 memset(this->namesBuf, 0, names_size);
56 this->namesBufSize = names_size;
57 this->namesRVA = names_rva;
58 return true;
59 }
60
61 bool allocDllsSpace(DWORD dlls_rva, size_t dlls_area_size)
62 {
63 delete[]dllsBuf;
64 this->dllsBuf = new(std::nothrow) BYTE[dlls_area_size];
65 if (!this->dllsBuf) {
66 this->dllsBufSize = 0;
67 return false;
68 }
69 memset(this->dllsBuf, 0, dlls_area_size);
70 this->dllsBufSize = dlls_area_size;
71 this->dllsRVA = dlls_rva;
72 return true;
73 }
74
76 {
77 return descriptosCount;
78 }
79
81 {
82 if (!descriptors) return 0;
83 const size_t size_bytes = sizeof(IMAGE_IMPORT_DESCRIPTOR) * descriptosCount;
84 return size_bytes;
85 }
86
87 size_t getNamesSize()
88 {
89 if (!this->namesBuf) return 0;
90 return this->namesBufSize;
91 }
92
94 {
95 return dllsBufSize;
96 }
97
98 DWORD getRVA()
99 {
100 return descriptorsRVA;
101 }
102
103 //copy table to the Virtual PE buffer
104 bool setTableInPe(BYTE *vBuf, size_t vBufSize)
105 {
106 if (!descriptors || !namesBuf || !dllsBuf) {
107 return false;
108 }
109 const size_t descriptors_size_b = getDescriptorsSize();
110 if ((descriptorsRVA + descriptors_size_b) > vBufSize || (namesRVA + namesBufSize) > vBufSize) {
111 // buffer too small
112 return false;
113 }
114 IMAGE_DATA_DIRECTORY* imp_dir = peconv::get_directory_entry(vBuf, IMAGE_DIRECTORY_ENTRY_IMPORT, true);
115 if (!imp_dir) {
116 //cannot retrieve import directory
117 return false;
118 }
119
120 const size_t import_table_size = getDescriptorsSize() + getNamesSize();
121
122 //copy buffers into PE:
123 memcpy(vBuf + descriptorsRVA, descriptors, descriptors_size_b);
124 memcpy(vBuf + namesRVA, namesBuf, namesBufSize);
125 memcpy(vBuf + dllsRVA, dllsBuf, dllsBufSize);
126
127 //overwrite the Data Directory:
128 imp_dir->VirtualAddress = descriptorsRVA;
129 imp_dir->Size = MASK_TO_DWORD(import_table_size);
130 return true;
131 }
132
133 protected:
134
135 BYTE * getNamesSpaceAt(const DWORD rva, size_t required_size);
136
137 BYTE* getDllSpaceAt(const DWORD rva, size_t required_size);
138
139 IMAGE_IMPORT_DESCRIPTOR* descriptors;
140 friend class ImpReconstructor;
141
142 private:
143
144 DWORD descriptorsRVA;
145 size_t descriptosCount;
146
147 DWORD namesRVA;
148 BYTE* namesBuf;
149 size_t namesBufSize;
150
151 DWORD dllsRVA;
152 BYTE* dllsBuf;
153 size_t dllsBufSize;
154 };
155
157
158 public:
159
161 : peBuffer(_peBuffer), is64bit(false)
162 {
163 if (!peBuffer.vBuf) return;
164 if (peBuffer.isValidPe()) {
165 this->is64bit = peconv::is64bit(peBuffer.vBuf);
166 }
167 else {
168 const size_t found_pattern = pesieve::util::is_64bit_code(peBuffer.vBuf, peBuffer.vBufSize);
169 this->is64bit = (found_pattern != PATTERN_NOT_FOUND);
170 }
171 collectMainIatData();
172 }
173
175 {
176 deleteFoundIATs();
177 }
178
185
198
199 t_imprec_res rebuildImportTable(const IN peconv::ExportsMapper* exportsMap, IN const pesieve::t_imprec_mode &imprec_mode);
200
201 bool printFoundIATs(const std::string &reportPath);
202
203 private:
204
205 t_imprec_res _recreateImportTableFiltered(const IN peconv::ExportsMapper* exportsMap, IN const pesieve::t_imprec_mode& imprec_mode);
206
207 IATBlock* findIATBlock(IN const peconv::ExportsMapper* exportsMap, size_t start_offset);
208 IATBlock* findIAT(IN const peconv::ExportsMapper* exportsMap, size_t start_offset);
209 void collectMainIatData();
210
212 bool hasDynamicIAT() const;
213
214 size_t getMainIATSize() const;
215
216 size_t getMaxDynamicIATSize(IN bool isIatTerminated) const;
217
218 bool findImportTable(IN const peconv::ExportsMapper* exportsMap);
219 size_t collectIATs(IN const peconv::ExportsMapper* exportsMap);
220
221 bool isDefaultImportValid(IN const peconv::ExportsMapper* exportsMap);
222
223 bool findIATsCoverage(IN const peconv::ExportsMapper* exportsMap, t_imprec_filter filter);
224 ImportTableBuffer* constructImportTable();
225 bool appendImportTable(ImportTableBuffer &importTable);
226
227 bool appendFoundIAT(DWORD iat_offset, IATBlock* found_block)
228 {
229 if (foundIATs.find(iat_offset) != foundIATs.end()) {
230 return false; //already exist
231 }
232 foundIATs[iat_offset] = found_block;
233 return true;
234 }
235
236 void deleteFoundIATs()
237 {
238 std::map<DWORD, IATBlock*>::iterator itr;
239 for (itr = foundIATs.begin(); itr != foundIATs.end(); ++itr) {
240 delete itr->second;
241 }
242 foundIATs.clear();
243 }
244
245 PeBuffer &peBuffer;
246 bool is64bit;
247 std::map<DWORD, IATBlock*> foundIATs;
248
249 std::set<DWORD> mainIatThunks; //< RVAs of the Thunks of the main IAT
250 };
251
252}; // namespace pesieve
t_imprec_res rebuildImportTable(const IN peconv::ExportsMapper *exportsMap, IN const pesieve::t_imprec_mode &imprec_mode)
ImpReconstructor(PeBuffer &_peBuffer)
bool printFoundIATs(const std::string &reportPath)
enum pesieve::ImpReconstructor::imprec_filter t_imprec_filter
enum pesieve::ImpReconstructor::imprec_res t_imprec_res
bool allocDllsSpace(DWORD dlls_rva, size_t dlls_area_size)
bool allocNamesSpace(DWORD names_rva, size_t names_size)
BYTE * getDllSpaceAt(const DWORD rva, size_t required_size)
ImportTableBuffer(DWORD _descriptorsRVA)
BYTE * getNamesSpaceAt(const DWORD rva, size_t required_size)
bool setTableInPe(BYTE *vBuf, size_t vBufSize)
bool allocDesciptors(size_t descriptors_count)
IMAGE_IMPORT_DESCRIPTOR * descriptors
#define MASK_TO_DWORD(val)
Definition iat_finder.h:9
The types used by PE-sieve API.