PE-sieve
Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).
Toggle main menu visibility
Loading...
Searching...
No Matches
postprocessors
imp_rec
iat_block.cpp
Go to the documentation of this file.
1
#include "
iat_block.h
"
2
#include <peconv.h>
3
4
namespace
pesieve
{
5
size_t
get_longest_func_name
(std::map<ULONGLONG, std::set<peconv::ExportedFunc>> &addrToFunc)
6
{
7
size_t
max_len = 0;
8
std::map<ULONGLONG, std::set<peconv::ExportedFunc>>::iterator itr;
9
for
(itr = addrToFunc.begin(); itr != addrToFunc.end(); ++itr) {
10
std::set<peconv::ExportedFunc> &expSet = itr->second;
11
const
peconv::ExportedFunc& exp = *(expSet.begin());
12
if
(exp.isByOrdinal) {
13
continue
;
14
}
15
if
(exp.funcName.length() > max_len) {
16
max_len = exp.funcName.length();
17
}
18
}
19
return
max_len;
20
}
21
};
22
23
//---
24
25
bool
pesieve::IATThunksSeries::makeCoverage
(IN
const
peconv::ExportsMapper* exportsMap)
26
{
27
delete
cov;
//delete previous
28
cov =
new
peconv::ImportedDllCoverage(funcAddresses, *exportsMap);
29
if
(!cov->findCoveringDll()) {
30
// DLL not found
31
return
false
;
32
}
33
size_t
covered_count = cov->mapAddressesToFunctions(cov->dllName);
34
this->dllFullName = exportsMap->get_dll_fullname(cov->dllName);
35
this->covered = (covered_count == this->funcAddresses.size());
36
return
this->covered;
37
}
38
39
bool
pesieve::IATThunksSeries::fillNamesSpace
(
const
BYTE* buf_start,
size_t
buf_size, DWORD bufRVA,
bool
is64b)
40
{
41
if
(!buf_start || !this->cov)
return
false
;
42
43
if
(!this->cov->isMappingComplete()) {
44
return
false
;
//TODO: make a workaround for this case
45
}
46
47
const
size_t
longest_name =
get_longest_func_name
(this->cov->addrToFunc);
48
const
size_t
field_size = is64b ?
sizeof
(ULONGLONG) :
sizeof
(DWORD);
49
50
const
size_t
thunks_count = this->
funcCount
();
51
const
size_t
thunks_area_size = (thunks_count * field_size) + field_size;
52
53
size_t
names_rva = bufRVA + thunks_area_size;
54
55
//fill thunks:
56
BYTE *buf =
const_cast<
BYTE*
>
(buf_start);
57
const
BYTE *buf_end = buf_start + buf_size;
58
for
(
size_t
i = 0; i < thunks_count; i++) {
59
if
(buf >= buf_end) {
60
#ifdef _DEBUG
61
std::cerr <<
"ERR: run out of buffer for names! Failed to make space for the name\n"
;
62
#endif
63
break
;
64
}
65
if
(is64b) {
66
ULONGLONG *val = (ULONGLONG*)buf;
67
*val = names_rva;
68
}
69
else
{
70
DWORD *val = (DWORD*)buf;
71
*val =
MASK_TO_DWORD
(names_rva);
72
}
73
//no need to fill names, they will be autofilled during dumping
74
buf += field_size;
75
names_rva +=
sizeof
(IMAGE_IMPORT_BY_NAME) + longest_name;
76
}
77
return
true
;
78
}
79
80
size_t
pesieve::IATThunksSeries::sizeOfNamesSpace
(
bool
is64b)
81
{
82
if
(!cov)
return
0;
83
84
size_t
space_size = 0;
85
if
(!this->cov->isMappingComplete()) {
86
return
0;
//TODO: make a workaround for this case
87
}
88
const
size_t
longest_name =
get_longest_func_name
(this->cov->addrToFunc);
89
const
size_t
field_size = is64b ?
sizeof
(ULONGLONG) :
sizeof
(DWORD);
90
const
size_t
entriesCount = this->
funcCount
();
91
for
(
size_t
i = 0; i < entriesCount; i++) {
92
space_size += field_size;
93
space_size +=
sizeof
(IMAGE_IMPORT_BY_NAME) + longest_name;
94
}
95
if
(space_size > 0) {
96
space_size +=
sizeof
(field_size);
97
}
98
return
space_size;
99
}
100
101
std::string
pesieve::IATThunksSeries::getDllName
()
102
{
103
return
this->dllFullName;
104
}
105
106
//---
107
108
bool
pesieve::IATBlock::makeCoverage
(IN
const
peconv::ExportsMapper* exportsMap)
109
{
110
if
(!exportsMap)
return
false
;
111
112
IATThunksSeriesSet::iterator itr;
113
std::set<IATThunksSeries*>to_split;
114
115
for
(itr = this->
thunkSeries
.begin(); itr !=
thunkSeries
.end(); ++itr) {
116
117
IATThunksSeries
* series = *itr;
118
if
(!series->
makeCoverage
(exportsMap)) {
119
to_split.insert(series);
120
}
121
}
122
123
std::set<IATThunksSeries*>::iterator sItr;
124
for
(sItr = to_split.begin(); sItr != to_split.end(); ++sItr) {
125
IATThunksSeries
*series = *sItr;
126
IATThunksSeriesSet
splitted =
splitSeries
(series, *exportsMap);
127
if
(!splitted.size()) {
128
continue
;
129
}
130
#ifdef _DEBUG
131
std::cout <<
"Uncovered series: "
<< std::hex << series->
startOffset
<<
" splitted into: "
<< std::dec << splitted.size() <<
" series\n"
;
132
#endif
133
134
this->
thunkSeries
.erase(series);
135
this->
thunkSeries
.insert(splitted.begin(), splitted.end());
136
137
delete
series;
// delete the series that have been splitted
138
}
139
140
size_t
covered_count = 0;
141
for
(itr = this->
thunkSeries
.begin(); itr !=
thunkSeries
.end(); ++itr) {
142
IATThunksSeries
* series = *itr;
143
144
if
(series->
isCovered
() || series ->
makeCoverage
(exportsMap)) {
145
covered_count++;
146
}
147
}
148
#ifdef _DEBUG
149
size_t
total = 0;
150
for
(
auto
it1 =
thunkSeries
.begin(); it1 !=
thunkSeries
.end(); ++it1) {
151
total += (*it1)->funcCount();
152
}
153
std::cout <<
"[#] IAT block: "
<< std::hex << this->
iatOffset
<<
" Total: "
<< std::dec << total <<
" Missed: "
<< (this->
countThunks
() - total) << std::endl;
154
#endif
155
isCoverageComplete
= (covered_count == this->
thunkSeries
.size());
156
return
isCoverageComplete
;
157
}
158
159
pesieve::IATThunksSeriesSet
pesieve::IATBlock::splitSeries
(IN
IATThunksSeries
* series, IN
const
peconv::ExportsMapper &exportsMap)
160
{
161
IATThunksSeriesSet
splitted;
162
if
(!series)
return
splitted;
163
164
std::map<DWORD, ULONGLONG> addresses = series->getRvaToFuncMap();
165
166
IATThunksSeries
*new_series =
nullptr
;
167
std::map<DWORD, ULONGLONG>::iterator itr;
168
std::string last_dll =
""
;
169
170
for
(itr = addresses.begin(); itr != addresses.end(); ++itr) {
171
ULONGLONG func_addr = itr->second;
172
DWORD offset = itr->first;
173
const
peconv::ExportedFunc *func = exportsMap.find_export_by_va(func_addr);
174
if
(new_series && (!func || func->libName != last_dll)) {
175
//close series
176
splitted.insert(new_series);
177
new_series =
nullptr
;
178
last_dll =
""
;
179
}
180
if
(!func)
continue
;
181
182
if
(!new_series) {
183
new_series =
new
IATThunksSeries
(offset);
184
last_dll = func->libName;
185
#ifdef _DEBUG
186
std::cout << std::hex <<
"addr: "
<< offset <<
" set DLL: "
<< last_dll <<
"\n"
;
187
#endif
188
}
189
new_series->
insert
(offset, func_addr);
190
}
191
if
(new_series) {
192
splitted.insert(new_series);
193
}
194
return
splitted;
195
}
196
197
size_t
pesieve::IATBlock::maxDllLen
()
198
{
199
size_t
max_size = 0;
200
IATThunksSeriesSet::iterator itr;
201
for
(itr = this->
thunkSeries
.begin(); itr !=
thunkSeries
.end(); ++itr) {
202
IATThunksSeries
* series = *itr;
203
size_t
curr_size = series->
getDllName
().length() + 1;
204
if
(curr_size > max_size) max_size = curr_size;
205
}
206
return
max_size;
207
}
208
209
size_t
pesieve::IATBlock::sizeOfDllsSpace
()
210
{
211
const
size_t
max_len =
maxDllLen
();
212
return
max_len * (
thunkSeries
.size() + 1);
213
}
214
215
std::string
pesieve::IATBlock::toString
()
216
{
217
std::stringstream stream;
218
stream <<
"---\nIAT at: "
<< std::hex <<
iatOffset
<<
", size: "
<<
iatSize
<<
", thunks: "
219
<<
countThunks
() <<
", is_terminated: "
<<
isTerminated
<<
", in_main: "
<<
isInMain
<<
"\n"
;
220
221
if
(this->
importTableOffset
) {
222
stream <<
"ImportTable: "
<< std::hex <<
importTableOffset
<<
"\n"
;
223
}
224
stream <<
"---\n"
;
225
std::map<ULONGLONG, const peconv::ExportedFunc*>::const_iterator itr;
226
for
(itr =
functions
.begin(); itr !=
functions
.end(); ++itr) {
227
ULONGLONG offset = itr->first;
228
const
peconv::ExportedFunc* exp = itr->second;
229
230
stream << std::hex << offset <<
","
<<
addrToFunctionVA
[offset] <<
","
<< exp->toString() <<
"\n"
;
231
}
232
return
stream.str();
233
}
pesieve::IATBlock::isCoverageComplete
bool isCoverageComplete
Definition
iat_block.h:179
pesieve::IATBlock::isInMain
bool isInMain
Definition
iat_block.h:166
pesieve::IATBlock::functions
std::map< ULONGLONG, const peconv::ExportedFunc * > functions
Definition
iat_block.h:181
pesieve::IATBlock::iatOffset
DWORD iatOffset
Definition
iat_block.h:168
pesieve::IATBlock::countThunks
size_t countThunks() const
Definition
iat_block.h:144
pesieve::IATBlock::maxDllLen
size_t maxDllLen()
Definition
iat_block.cpp:197
pesieve::IATBlock::importTableOffset
DWORD importTableOffset
Definition
iat_block.h:171
pesieve::IATBlock::toString
std::string toString()
Definition
iat_block.cpp:215
pesieve::IATBlock::iatSize
size_t iatSize
Definition
iat_block.h:169
pesieve::IATBlock::sizeOfDllsSpace
size_t sizeOfDllsSpace()
Definition
iat_block.cpp:209
pesieve::IATBlock::makeCoverage
bool makeCoverage(IN const peconv::ExportsMapper *exportsMap)
Definition
iat_block.cpp:108
pesieve::IATBlock::thunkSeries
IATThunksSeriesSet thunkSeries
Definition
iat_block.h:176
pesieve::IATBlock::addrToFunctionVA
std::map< ULONGLONG, ULONGLONG > addrToFunctionVA
Definition
iat_block.h:182
pesieve::IATBlock::splitSeries
IATThunksSeriesSet splitSeries(IN IATThunksSeries *notCoveredSeries, IN const peconv::ExportsMapper &exportsMap)
Definition
iat_block.cpp:159
pesieve::IATBlock::isTerminated
bool isTerminated
Definition
iat_block.h:165
pesieve::IATThunksSeries
Definition
iat_block.h:12
pesieve::IATThunksSeries::makeCoverage
bool makeCoverage(IN const peconv::ExportsMapper *exportsMap)
Definition
iat_block.cpp:25
pesieve::IATThunksSeries::getDllName
std::string getDllName()
Definition
iat_block.cpp:101
pesieve::IATThunksSeries::startOffset
DWORD startOffset
Definition
iat_block.h:64
pesieve::IATThunksSeries::insert
bool insert(DWORD rva, ULONGLONG funcAddr)
Definition
iat_block.h:29
pesieve::IATThunksSeries::sizeOfNamesSpace
size_t sizeOfNamesSpace(bool is64b)
Definition
iat_block.cpp:80
pesieve::IATThunksSeries::fillNamesSpace
bool fillNamesSpace(const BYTE *buf_start, size_t buf_size, DWORD bufRVA, bool is64b)
Definition
iat_block.cpp:39
pesieve::IATThunksSeries::funcCount
size_t funcCount()
Definition
iat_block.h:46
pesieve::IATThunksSeries::isCovered
bool isCovered()
Definition
iat_block.h:41
iat_block.h
MASK_TO_DWORD
#define MASK_TO_DWORD(val)
Definition
iat_finder.h:9
pesieve
Definition
pesieve.py:1
pesieve::get_longest_func_name
size_t get_longest_func_name(std::map< ULONGLONG, std::set< peconv::ExportedFunc > > &addrToFunc)
Definition
iat_block.cpp:5
pesieve::IATThunksSeriesSet
std::set< IATThunksSeries *, IATThunksSeriesPtrCompare > IATThunksSeriesSet
Definition
iat_block.h:85
Generated by
1.17.0