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
artefacts_util.cpp
Go to the documentation of this file.
1#include "artefacts_util.h"
2#include <peconv.h>
3#include "code_patterns.h"
4#ifdef _DEBUG
5 #include <iostream>
6#endif
7
8using namespace sig_finder;
9
10BYTE* pesieve::util::find_pattern(BYTE* buffer, size_t buf_size, BYTE* pattern_buf, size_t pattern_size, size_t max_iter)
11{
12 for (size_t i = 0; (i + pattern_size) < buf_size; i++) {
13 if (max_iter != 0 && i > max_iter) break;
14 if (memcmp(buffer + i, pattern_buf, pattern_size) == 0) {
15 return (buffer + i);
16 }
17 }
18 return nullptr;
19}
20
21namespace pesieve {
22
23 std::set<DWORD> HardcodedPatterns;
25
26 size_t init_32_patterns(Node* rootN)
27 {
29 if (!rootN) return 0;
30
31 size_t added = 0;
32 for (size_t i = 0; i < _countof(patterns32); i++)
33 {
34 const t_pattern& pattern = patterns32[i];
35 std::string name = "prolog32_" + std::to_string((ULONGLONG)i);
36 Signature sign(name, pattern.ptr, pattern.size);
37 if (rootN->addPattern(sign)) {
38 HardcodedPatterns.insert(sign.checksum());
39 added++;
40 }
41 }
42 return added;
43 }
44
45 size_t init_64_patterns(Node* rootN)
46 {
48 if (!rootN) return 0;
49
50 size_t added = 0;
51 for (size_t i = 0; i < _countof(patterns64); i++)
52 {
53 const t_pattern &pattern = patterns64[i];
54 std::string name = "prolog64_" + std::to_string((ULONGLONG)i);
55 Signature sign(name, pattern.ptr, pattern.size);
56 if (rootN->addPattern(sign)) {
57 HardcodedPatterns.insert(sign.checksum());
58 added++;
59 }
60 }
61 return added;
62 }
63
64 inline size_t search_till_pattern(sig_finder::Node& rootN, const BYTE* loadedData, size_t loadedSize)
65 {
66 Match m = sig_finder::find_first_match(rootN, loadedData, loadedSize);
67 if (!m.sign) {
68 return PATTERN_NOT_FOUND;
69 }
70 return m.offset;
71 }
72
73}; //namespace pesieve
74
75size_t pesieve::util::is_32bit_code(BYTE *loadedData, size_t loadedSize)
76{
77 static sig_finder::Node rootN;
78 if(rootN.isEnd()) {
79 init_32_patterns(&rootN);
80 }
81 return search_till_pattern(rootN, loadedData, loadedSize);
82}
83
84size_t pesieve::util::is_64bit_code(BYTE* loadedData, size_t loadedSize)
85{
86 static sig_finder::Node rootN;
87 if (rootN.isEnd()) {
88 init_64_patterns(&rootN);
89 }
90 return search_till_pattern(rootN, loadedData, loadedSize);
91}
92
93bool pesieve::util::is_code(BYTE* loadedData, size_t loadedSize)
94{
95 static sig_finder::Node rootN;
96 if (peconv::is_padding(loadedData, loadedSize, 0)) {
97 return false;
98 }
99 if (rootN.isEnd()) {
100 init_32_patterns(&rootN);
101 init_64_patterns(&rootN);
102 }
103 if ((search_till_pattern(rootN, loadedData, loadedSize)) != PATTERN_NOT_FOUND) {
104 return true;
105 }
106 return false;
107}
108
109bool pesieve::util::is_executable(DWORD mapping_type, DWORD protection)
110{
111 const bool is_any_exec = (protection & PAGE_EXECUTE_READWRITE)
112 || (protection & PAGE_EXECUTE_READ)
113 || (protection & PAGE_EXECUTE)
114 || (protection & PAGE_EXECUTE_WRITECOPY);
115 return is_any_exec;
116}
117
118bool pesieve::util::is_readable(DWORD mapping_type, DWORD protection)
119{
120 const bool is_read = (protection & PAGE_READWRITE)
121 || (protection & PAGE_READONLY);
122 return is_read;
123}
124
125bool pesieve::util::is_normal_inaccessible(DWORD state, DWORD mapping_type, DWORD protection)
126{
127 if ((state & MEM_COMMIT) == 0) {
128 //not committed
129 return false;
130 }
131 if (mapping_type != MEM_IMAGE && (mapping_type != MEM_MAPPED) && mapping_type != MEM_PRIVATE) {
132 // invalid mapping type
133 return false;
134 }
135 if (protection & PAGE_NOACCESS) {
136 // inaccessible found
137 return true;
138 }
139 return false;
140}
141
142//---
143// matcher:
144
146{
148 return (mainMatcher.isEnd()) ? false : true;
149}
150
152{
153 util::MutexLocker guard(mainMatcherMutex);
154 static bool isLoaded = false;
155 if (isLoaded) return 0; // allow to load file only once
156
157 isLoaded = true;
158 std::vector<Signature*> signatures;
159 Signature::loadFromFile(filename, signatures);
160 const size_t added = mainMatcher.addPatterns(signatures);
161 // delete the loaded signatures:
162 for (auto itr = signatures.begin(); itr != signatures.end(); ++itr) {
163 Signature* sign = *itr;
164 delete sign;
165 }
166 std::cout << "Added patterns: " << std::dec << added << "\n";
167 return added;
168}
169
171{
172 util::MutexLocker guard(mainMatcherMutex);
173 static bool isLoaded = false;
174 if (isLoaded) return false; // allow to load only once
175
176 isLoaded = true;
177 init_32_patterns(&mainMatcher);
178 init_64_patterns(&mainMatcher);
179 return true;
180}
181
182size_t pesieve::PatternMatcher::findAllPatterns(BYTE* loadedData, size_t loadedSize, std::vector<sig_finder::Match>& allMatches)
183{
184 if (!isReady()) {
185 return false;
186 }
187 if (peconv::is_padding(loadedData, loadedSize, 0)) {
188 return false;
189 }
190 const size_t matches = sig_finder::find_all_matches(mainMatcher, loadedData, loadedSize, allMatches);
191 return matches;
192}
193
194size_t pesieve::PatternMatcher::filterCustom(std::vector<sig_finder::Match>& allMatches, std::vector<sig_finder::Match>& customPatternMatches)
195{
197 size_t customCount = 0;
198 for (auto itr = allMatches.begin(); itr != allMatches.end(); ++itr) {
199 sig_finder::Match m = *itr;
200 if (m.sign) {
201 const DWORD checks = m.sign->checksum();
202 if (HardcodedPatterns.find(checks) != HardcodedPatterns.end()) {
203 continue;
204 }
205 customPatternMatches.push_back(m);
206 customCount++;
207 }
208 }
209 return customCount;
210}
#define PATTERN_NOT_FOUND
pesieve::util::Mutex mainMatcherMutex
sig_finder::Node mainMatcher
size_t loadPatternFile(const char *filename)
size_t findAllPatterns(BYTE *loadedData, size_t loadedSize, ::std::vector< sig_finder::Match > &allMatches)
size_t filterCustom(::std::vector< sig_finder::Match > &allMatches, ::std::vector< sig_finder::Match > &customPatternMatches)
size_t is_32bit_code(BYTE *loadedData, size_t loadedSize)
bool is_readable(DWORD mapping_type, DWORD protection)
BYTE * find_pattern(BYTE *buffer, size_t buf_size, BYTE *pattern_buf, size_t pattern_size, size_t max_iter=0)
bool is_normal_inaccessible(DWORD state, DWORD mapping_type, DWORD protection)
bool is_code(BYTE *loadedData, size_t loadedSize)
bool is_executable(DWORD mapping_type, DWORD protection)
size_t is_64bit_code(BYTE *loadedData, size_t loadedSize)
size_t init_32_patterns(Node *rootN)
t_pattern patterns32[]
size_t search_till_pattern(sig_finder::Node &rootN, const BYTE *loadedData, size_t loadedSize)
pesieve::util::Mutex g_HardcodedPatternsMutex
t_pattern patterns64[]
size_t init_64_patterns(Node *rootN)
std::set< DWORD > HardcodedPatterns