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
import_table_finder.h
Go to the documentation of this file.
1#pragma once
2#include <peconv.h>
3
4namespace pesieve {
5
6 template <typename FIELD_T>
7 bool is_valid_import_descriptor(BYTE* vBuf, size_t vBufSize, IN const peconv::ExportsMapper* exportsMap, IMAGE_IMPORT_DESCRIPTOR* desc)
8 {
9 if (!peconv::validate_ptr(vBuf, vBufSize, desc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
10 return false; //buffer finished
11 }
12 if (desc->TimeDateStamp != 0 && desc->TimeDateStamp != (-1)) {
13 return false; // candidate doesn't fit
14 }
15 char* name_ptr = (char*)vBuf + desc->Name;
16 if (!peconv::validate_ptr(vBuf, vBufSize, name_ptr, sizeof(char))) {
17 return false; // candidate doesn't fit
18 }
19 if (desc->Name) {
20 if (!peconv::is_valid_import_name(vBuf, vBufSize, name_ptr)) return 0; //invalid name, validation failed
21#ifdef _DEBUG
22 std::cout << "DLL: " << name_ptr << "\n";
23#endif
24 }
25 if (desc->FirstThunk == 0 && desc->OriginalFirstThunk == 0) {
26 //probably the last chunk
27 return true;
28 }
29 FIELD_T* orig_thunk_ptr = (FIELD_T*)(vBuf + desc->OriginalFirstThunk);
30 if (!peconv::validate_ptr(vBuf, vBufSize, orig_thunk_ptr, sizeof(FIELD_T))) {
31 return false; // candidate doesn't fit
32 }
33 FIELD_T *thunk_ptr = (FIELD_T*)(vBuf + desc->FirstThunk);
34 if (!peconv::validate_ptr(vBuf, vBufSize, thunk_ptr, sizeof(FIELD_T))) {
35 return false; // candidate doesn't fit
36 }
37 const peconv::ExportedFunc *exp = exportsMap->find_export_by_va(*thunk_ptr);
38 if (!exp) {
39 return false; //no such import: validation failed
40 }
41 return true;
42 }
43
44 template <typename FIELD_T>
45 size_t calc_import_table_size(BYTE* vBuf, size_t vBufSize, IN const peconv::ExportsMapper* exportsMap, IMAGE_IMPORT_DESCRIPTOR* first_desc)
46 {
47 if (!vBuf || !exportsMap || !first_desc) return 0;
48
49 IMAGE_IMPORT_DESCRIPTOR *desc = nullptr;
50 for (desc = first_desc; ; desc++) {
51 if (!peconv::validate_ptr(vBuf, vBufSize, desc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
52 break; //buffer finished
53 }
54 if (!is_valid_import_descriptor<FIELD_T>(vBuf, vBufSize, exportsMap, desc)) {
55 return 0;
56 }
57 if (desc->FirstThunk == 0 && desc->OriginalFirstThunk == 0) {
58 //probably the last chunk
59 break;
60 }
61 }
62 size_t diff = (BYTE*)desc - (BYTE*)first_desc;
63 return diff + sizeof(IMAGE_IMPORT_DESCRIPTOR);
64 }
65
66 template <typename FIELD_T>
67 IMAGE_IMPORT_DESCRIPTOR* find_first_import_descriptor(BYTE* vBuf, size_t vBufSize, IN const peconv::ExportsMapper* exportsMap, IMAGE_IMPORT_DESCRIPTOR* found_desc)
68 {
69 if (!vBuf || !exportsMap || !found_desc) return nullptr;
70
71 IMAGE_IMPORT_DESCRIPTOR *first_desc = nullptr;
72 size_t prev_table_size = 0;
73
74 for (IMAGE_IMPORT_DESCRIPTOR *desc = found_desc; ; desc--) {
75 size_t table_size = calc_import_table_size<FIELD_T>(vBuf, vBufSize, exportsMap, desc);
76 if (table_size == 0 || table_size < prev_table_size) {
77 break; // if it is valid, the table size should grow
78 }
79 prev_table_size = table_size;
80 first_desc = desc;
81 //std::cout << "!!! Valid DESC: " << std::hex << (ULONGLONG)((BYTE*)desc - vBuf) << std::endl;
82 }
83 return first_desc;
84 }
85
86 template <typename FIELD_T>
87 IMAGE_IMPORT_DESCRIPTOR* find_import_table_tpl(IN BYTE* vBuf,
88 IN size_t vBufSize,
89 IN const peconv::ExportsMapper* exportsMap,
90 IN DWORD iat_offset,
91 OUT size_t &table_size,
92 IN OPTIONAL size_t search_offset)
93 {
94 table_size = 0;
95 if (!vBuf || !iat_offset) return nullptr;
96 if (search_offset > vBufSize || (vBufSize - search_offset) < sizeof(DWORD)) {
97 return nullptr; //size check failed
98 }
99 size_t max_check = vBufSize - sizeof(DWORD);
100 for (BYTE* ptr = vBuf + search_offset; ptr < vBuf + max_check; ptr++) {
101 DWORD *to_check = (DWORD*)ptr;
102 if (*to_check != iat_offset) {
103 continue; //candidate not found
104 }
105 size_t offset = (BYTE*)to_check - vBuf;
106 //std::cout << "Found IAT offset in the binary: " << std::hex << offset << "\n";
107 size_t desc_diff = sizeof(IMAGE_IMPORT_DESCRIPTOR) - sizeof(DWORD);
108 IMAGE_IMPORT_DESCRIPTOR *desc = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)to_check - desc_diff);
109 if (!peconv::validate_ptr(vBuf, vBufSize, desc, sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
110 continue; // candidate doesn't fit
111 }
112 //now try to find the first one in the table:
113 IMAGE_IMPORT_DESCRIPTOR* first_desc = find_first_import_descriptor<FIELD_T>(vBuf, vBufSize, exportsMap, desc);
114 size_t _table_size = calc_import_table_size<FIELD_T>(vBuf, vBufSize, exportsMap, first_desc);
115 if (_table_size > 0) {
116 table_size = _table_size;
117 return first_desc;
118 }
119 }
120 //std::cout << "Import table not found\n";
121 return nullptr;
122 }
123
124 IMAGE_IMPORT_DESCRIPTOR* find_import_table(
125 IN bool is64bit,
126 IN BYTE* vBuf,
127 IN size_t vBufSize,
128 IN const peconv::ExportsMapper* exportsMap,
129 IN DWORD iat_offset,
130 OUT size_t &table_size,
131 IN OPTIONAL size_t search_offset
132 );
133
134}; //namespace pesieve
135
IMAGE_IMPORT_DESCRIPTOR * find_import_table_tpl(IN BYTE *vBuf, IN size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IN DWORD iat_offset, OUT size_t &table_size, IN OPTIONAL size_t search_offset)
size_t calc_import_table_size(BYTE *vBuf, size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IMAGE_IMPORT_DESCRIPTOR *first_desc)
IMAGE_IMPORT_DESCRIPTOR * find_first_import_descriptor(BYTE *vBuf, size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IMAGE_IMPORT_DESCRIPTOR *found_desc)
IMAGE_IMPORT_DESCRIPTOR * find_import_table(IN bool is64bit, IN BYTE *vBuf, IN size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IN DWORD iat_offset, OUT size_t &table_size, IN OPTIONAL size_t search_offset)
bool is_valid_import_descriptor(BYTE *vBuf, size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IMAGE_IMPORT_DESCRIPTOR *desc)