diff --git a/classpesieve_1_1_thread_scan_report.html b/classpesieve_1_1_thread_scan_report.html index b04509a6d..f3a3716fe 100644 --- a/classpesieve_1_1_thread_scan_report.html +++ b/classpesieve_1_1_thread_scan_report.html @@ -365,7 +365,7 @@

-

Definition at line 101 of file thread_scanner.cpp.

+

Definition at line 103 of file thread_scanner.cpp.

diff --git a/classpesieve_1_1_thread_scanner.html b/classpesieve_1_1_thread_scanner.html index bbeb6327c..fb556424b 100644 --- a/classpesieve_1_1_thread_scanner.html +++ b/classpesieve_1_1_thread_scanner.html @@ -242,7 +242,7 @@

-

Definition at line 122 of file thread_scanner.cpp.

+

Definition at line 124 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -288,7 +288,7 @@

-

Definition at line 211 of file thread_scanner.cpp.

+

Definition at line 213 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -333,7 +333,7 @@

-

Definition at line 318 of file thread_scanner.cpp.

+

Definition at line 320 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -408,7 +408,7 @@

-

Definition at line 176 of file thread_scanner.cpp.

+

Definition at line 178 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -445,7 +445,7 @@

-

Definition at line 245 of file thread_scanner.cpp.

+

Definition at line 247 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -482,7 +482,7 @@

-

Definition at line 257 of file thread_scanner.cpp.

+

Definition at line 259 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -519,7 +519,7 @@

-

Definition at line 287 of file thread_scanner.cpp.

+

Definition at line 289 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -562,7 +562,7 @@

-

Definition at line 331 of file thread_scanner.cpp.

+

Definition at line 333 of file thread_scanner.cpp.

Here is the call graph for this function:
@@ -604,7 +604,7 @@

pesieve::ProcessFeatureScanner.

-

Definition at line 391 of file thread_scanner.cpp.

+

Definition at line 382 of file thread_scanner.cpp.

Here is the call graph for this function:
diff --git a/scanner_8cpp_source.html b/scanner_8cpp_source.html index a3b1332a9..9443dc254 100644 --- a/scanner_8cpp_source.html +++ b/scanner_8cpp_source.html @@ -718,7 +718,7 @@
A report from the thread scan, generated by ThreadScanner.
-
virtual ThreadScanReport * scanRemote()
+
virtual ThreadScanReport * scanRemote()
A report from the working set scan, generated by WorkingSetScanner.
diff --git a/thread__scanner_8cpp.html b/thread__scanner_8cpp.html index 414e3103c..a26f7b2f4 100644 --- a/thread__scanner_8cpp.html +++ b/thread__scanner_8cpp.html @@ -208,7 +208,7 @@

-

Definition at line 305 of file thread_scanner.cpp.

+

Definition at line 307 of file thread_scanner.cpp.

@@ -227,7 +227,7 @@

-

Definition at line 362 of file thread_scanner.cpp.

+

Definition at line 364 of file thread_scanner.cpp.

Here is the call graph for this function:
diff --git a/thread__scanner_8cpp_source.html b/thread__scanner_8cpp_source.html index 96f950a67..2d910e5bf 100644 --- a/thread__scanner_8cpp_source.html +++ b/thread__scanner_8cpp_source.html @@ -194,412 +194,403 @@
92 case Executive: return "Executive";
93 case UserRequest: return "UserRequest";
94 case WrUserRequest: return "WrUserRequest";
-
95 }
-
96 std::stringstream ss;
-
97 ss << "Other: " << std::dec << thread_wait_reason;
-
98 return ss.str();
-
99}
+
95 case WrEventPair: return "WrEventPair";
+
96 case WrQueue: return "WrQueue";
+
97 }
+
98 std::stringstream ss;
+
99 ss << "Other: " << std::dec << thread_wait_reason;
+
100 return ss.str();
+
101}
-
100
-
-
101std::string ThreadScanReport::translate_thread_state(DWORD thread_state)
-
102{
-
103 switch (thread_state) {
-
104 case Initialized: return "Initialized";
-
105 case Ready: return "Ready";
-
106 case Running: return "Running";
-
107 case Standby: return "Standby";
-
108 case Terminated: return "Terminated";
-
109 case Waiting: return "Waiting";
-
110 case Transition: return "Transition";
-
111 case DeferredReady: return "DeferredReady";
-
112 case GateWaitObsolete: return "GateWaitObsolete";
-
113 case WaitingForProcessInSwap: return "WaitingForProcessInSwap";
-
114 }
-
115 std::stringstream ss;
-
116 ss << "Other: " << std::dec << thread_state;
-
117 return ss.str();
-
118}
+
102
+
+
103std::string ThreadScanReport::translate_thread_state(DWORD thread_state)
+
104{
+
105 switch (thread_state) {
+
106 case Initialized: return "Initialized";
+
107 case Ready: return "Ready";
+
108 case Running: return "Running";
+
109 case Standby: return "Standby";
+
110 case Terminated: return "Terminated";
+
111 case Waiting: return "Waiting";
+
112 case Transition: return "Transition";
+
113 case DeferredReady: return "DeferredReady";
+
114 case GateWaitObsolete: return "GateWaitObsolete";
+
115 case WaitingForProcessInSwap: return "WaitingForProcessInSwap";
+
116 }
+
117 std::stringstream ss;
+
118 ss << "Other: " << std::dec << thread_state;
+
119 return ss.str();
+
120}
-
119
-
120//---
121
-
-
122size_t pesieve::ThreadScanner::analyzeStackFrames(IN const std::vector<ULONGLONG> stack_frame, IN OUT ctx_details& cDetails)
-
123{
-
124 size_t processedCntr = 0;
-
125 bool has_shellcode = false;
-
126 cDetails.is_managed = false;
-
127#ifdef _SHOW_THREAD_INFO
-
128 std::cout << "\n" << "Stack frame Size: " << std::dec << stack_frame.size() << "\n===\n";
-
129#endif //_SHOW_THREAD_INFO
-
130 for (auto itr = stack_frame.rbegin();
-
131 itr != stack_frame.rend()
-
132 && (!cDetails.is_managed && !has_shellcode); // break on first found shellcode, (for now) discontinue analysis if the module is .NET to avoid FP
-
133 ++itr, ++processedCntr)
-
134 {
-
135 const ULONGLONG next_return = *itr;
-
136#ifdef _SHOW_THREAD_INFO
-
137 if (symbols) {
-
138 symbols->dumpSymbolInfo(next_return);
-
139 }
-
140 std::cout << "\t";
-
141 printResolvedAddr(next_return);
-
142#endif //_SHOW_THREAD_INFO
-
143 bool is_curr_shc = false;
-
144 const ScannedModule* mod = modulesInfo.findModuleContaining(next_return);
-
145 const std::string mod_name = mod ? mod->getModName() : "";
-
146 if (mod_name.length() == 0) {
-
147 if (!cDetails.is_managed) {
-
148 has_shellcode = is_curr_shc = true;
-
149#ifdef _SHOW_THREAD_INFO
-
150 std::cout << "\t" << std::hex << next_return << " <=== SHELLCODE\n";
-
151#endif //_SHOW_THREAD_INFO
-
152 } else {
-
153#ifdef _SHOW_THREAD_INFO
-
154 std::cout << "\t" << std::hex << next_return << " <=== .NET JIT\n";
-
155#endif //_SHOW_THREAD_INFO
-
156 }
-
157 }
-
158 if (!has_shellcode || is_curr_shc) {
-
159 // store the last address, till the first called shellcode:
-
160 cDetails.ret_addr = next_return;
-
161 }
-
162 // check if the found shellcode is a .NET JIT:
-
163 if (mod_name == "clr.dll") {
-
164 cDetails.is_managed = true;
-
165#ifdef _SHOW_THREAD_INFO
-
166 std::cout << "\t" << std::hex << next_return << " <--- .NET\n";
-
167#endif //_SHOW_THREAD_INFO
-
168 }
-
169 }
-
170#ifdef _SHOW_THREAD_INFO
-
171 std::cout << "\n===\n";
-
172#endif //_SHOW_THREAD_INFO
-
173 return processedCntr;
-
174}
+
122//---
+
123
+
+
124size_t pesieve::ThreadScanner::analyzeStackFrames(IN const std::vector<ULONGLONG> stack_frame, IN OUT ctx_details& cDetails)
+
125{
+
126 size_t processedCntr = 0;
+
127 bool has_shellcode = false;
+
128 cDetails.is_managed = false;
+
129#ifdef _SHOW_THREAD_INFO
+
130 std::cout << "\n" << "Stack frame Size: " << std::dec << stack_frame.size() << "\n===\n";
+
131#endif //_SHOW_THREAD_INFO
+
132 for (auto itr = stack_frame.rbegin();
+
133 itr != stack_frame.rend()
+
134 && (!cDetails.is_managed && !has_shellcode) // break on first found shellcode, (for now) discontinue analysis if the module is .NET to avoid FP
+
135 ;++itr, ++processedCntr)
+
136 {
+
137 const ULONGLONG next_return = *itr;
+
138#ifdef _SHOW_THREAD_INFO
+
139 if (symbols) {
+
140 symbols->dumpSymbolInfo(next_return);
+
141 }
+
142 std::cout << "\t";
+
143 printResolvedAddr(next_return);
+
144#endif //_SHOW_THREAD_INFO
+
145 bool is_curr_shc = false;
+
146 const ScannedModule* mod = modulesInfo.findModuleContaining(next_return);
+
147 const std::string mod_name = mod ? mod->getModName() : "";
+
148 if (mod_name.length() == 0) {
+
149 if (!cDetails.is_managed) {
+
150 has_shellcode = is_curr_shc = true;
+
151#ifdef _SHOW_THREAD_INFO
+
152 std::cout << "\t" << std::hex << next_return << " <=== SHELLCODE\n";
+
153#endif //_SHOW_THREAD_INFO
+
154 } else {
+
155#ifdef _SHOW_THREAD_INFO
+
156 std::cout << "\t" << std::hex << next_return << " <=== .NET JIT\n";
+
157#endif //_SHOW_THREAD_INFO
+
158 }
+
159 }
+
160 if (!has_shellcode || is_curr_shc) {
+
161 // store the last address, till the first called shellcode:
+
162 cDetails.ret_addr = next_return;
+
163 }
+
164 // check if the found shellcode is a .NET JIT:
+
165 if (mod_name == "clr.dll") {
+
166 cDetails.is_managed = true;
+
167#ifdef _SHOW_THREAD_INFO
+
168 std::cout << "\t" << std::hex << next_return << " <--- .NET\n";
+
169#endif //_SHOW_THREAD_INFO
+
170 }
+
171 }
+
172#ifdef _SHOW_THREAD_INFO
+
173 std::cout << "\n===\n";
+
174#endif //_SHOW_THREAD_INFO
+
175 return processedCntr;
+
176}
-
175
-
-
176size_t pesieve::ThreadScanner::fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details& cDetails)
-
177{
-
178 // do it in a new thread to prevent stucking...
-
179 t_stack_enum_params args(hProcess, hThread, ctx, &cDetails);
-
180
-
181 const size_t max_wait = 1000;
-
182 {
-
183 HANDLE enumThread = CreateThread(
-
184 NULL, // default security attributes
-
185 0, // use default stack size
-
186 enum_stack_thread, // thread function name
-
187 &args, // argument to thread function
-
188 0, // use default creation flags
-
189 0); // returns the thread identifiee
-
190
-
191 if (enumThread) {
-
192 DWORD wait_result = WaitForSingleObject(enumThread, max_wait);
-
193 if (wait_result == WAIT_TIMEOUT) {
-
194 std::cerr << "[!] Cannot retrieve stack frame: timeout passed!\n";
-
195 TerminateThread(enumThread, 0);
-
196 CloseHandle(enumThread);
-
197 return 0;
-
198 }
-
199 CloseHandle(enumThread);
-
200 }
-
201 }
-
202 if (!args.is_ok) {
-
203 return 0;
-
204 }
-
205#ifdef _SHOW_THREAD_INFO
-
206 std::cout << "\n=== TID " << std::dec << GetThreadId(hThread) << " ===\n";
-
207#endif //_SHOW_THREAD_INFO
-
208 return analyzeStackFrames(args.stack_frame, cDetails);
-
209}
+
177
+
+
178size_t pesieve::ThreadScanner::fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details& cDetails)
+
179{
+
180 // do it in a new thread to prevent stucking...
+
181 t_stack_enum_params args(hProcess, hThread, ctx, &cDetails);
+
182
+
183 const size_t max_wait = 1000;
+
184 {
+
185 HANDLE enumThread = CreateThread(
+
186 NULL, // default security attributes
+
187 0, // use default stack size
+
188 enum_stack_thread, // thread function name
+
189 &args, // argument to thread function
+
190 0, // use default creation flags
+
191 0); // returns the thread identifiee
+
192
+
193 if (enumThread) {
+
194 DWORD wait_result = WaitForSingleObject(enumThread, max_wait);
+
195 if (wait_result == WAIT_TIMEOUT) {
+
196 std::cerr << "[!] Cannot retrieve stack frame: timeout passed!\n";
+
197 TerminateThread(enumThread, 0);
+
198 CloseHandle(enumThread);
+
199 return 0;
+
200 }
+
201 CloseHandle(enumThread);
+
202 }
+
203 }
+
204 if (!args.is_ok) {
+
205 return 0;
+
206 }
+
207#ifdef _SHOW_THREAD_INFO
+
208 std::cout << "\n=== TID " << std::dec << GetThreadId(hThread) << " ===\n";
+
209#endif //_SHOW_THREAD_INFO
+
210 return analyzeStackFrames(args.stack_frame, cDetails);
+
211}
-
210
-
-
211bool pesieve::ThreadScanner::fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details& cDetails)
-
212{
-
213 bool is_ok = false;
-
214 BOOL is_wow64 = FALSE;
-
215#ifdef _WIN64
-
216 pesieve::util::is_process_wow64(hProcess, &is_wow64);
-
217
-
218 if (is_wow64) {
-
219 WOW64_CONTEXT ctx = { 0 };
-
220 ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
-
221 if (pesieve::util::wow64_get_thread_context(hThread, &ctx)) {
-
222 is_ok = true;
-
223 cDetails.init(false, ctx.Eip, ctx.Esp, ctx.Ebp);
-
224 fillStackFrameInfo(hProcess, hThread, &ctx, cDetails);
-
225 }
-
226 }
-
227#endif
-
228 if (!is_ok) {
-
229
-
230 CONTEXT ctx = { 0 };
-
231 ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
-
232 if (GetThreadContext(hThread, &ctx)) {
-
233 is_ok = true;
-
234#ifdef _WIN64
-
235 cDetails.init(true, ctx.Rip, ctx.Rsp, ctx.Rbp);
-
236#else
-
237 cDetails.init(false, ctx.Eip, ctx.Esp, ctx.Ebp);
-
238#endif
-
239 fillStackFrameInfo(hProcess, hThread, &ctx, cDetails);
-
240 }
-
241 }
-
242 return is_ok;
-
243}
+
212
+
+
213bool pesieve::ThreadScanner::fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details& cDetails)
+
214{
+
215 bool is_ok = false;
+
216 BOOL is_wow64 = FALSE;
+
217#ifdef _WIN64
+
218 pesieve::util::is_process_wow64(hProcess, &is_wow64);
+
219
+
220 if (is_wow64) {
+
221 WOW64_CONTEXT ctx = { 0 };
+
222 ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
223 if (pesieve::util::wow64_get_thread_context(hThread, &ctx)) {
+
224 is_ok = true;
+
225 cDetails.init(false, ctx.Eip, ctx.Esp, ctx.Ebp);
+
226 fillStackFrameInfo(hProcess, hThread, &ctx, cDetails);
+
227 }
+
228 }
+
229#endif
+
230 if (!is_ok) {
+
231
+
232 CONTEXT ctx = { 0 };
+
233 ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
234 if (GetThreadContext(hThread, &ctx)) {
+
235 is_ok = true;
+
236#ifdef _WIN64
+
237 cDetails.init(true, ctx.Rip, ctx.Rsp, ctx.Rbp);
+
238#else
+
239 cDetails.init(false, ctx.Eip, ctx.Esp, ctx.Ebp);
+
240#endif
+
241 fillStackFrameInfo(hProcess, hThread, &ctx, cDetails);
+
242 }
+
243 }
+
244 return is_ok;
+
245}
-
244
-
- -
246{
-
247 ScannedModule* mod = modulesInfo.findModuleContaining(addr);
-
248 if (!mod) return true;
-
249
-
250 //the module is named
-
251 if (mod->getModName().length() > 0) {
-
252 return false;
-
253 }
-
254 return true;
-
255}
+
246
+
+ +
248{
+
249 ScannedModule* mod = modulesInfo.findModuleContaining(addr);
+
250 if (!mod) return true;
+
251
+
252 //the module is named
+
253 if (mod->getModName().length() > 0) {
+
254 return false;
+
255 }
+
256 return true;
+
257}
-
256
-
- -
258{
-
259 bool is_resolved = false;
-
260 std::cout << std::hex << addr;
-
261 ScannedModule* mod = modulesInfo.findModuleContaining(addr);
-
262 if (mod) {
-
263 std::cout << " : " << mod->getModName();
-
264 is_resolved = true;
-
265 }
-
266 if (exportsMap && is_resolved) {
-
267 bool search_name = false;
-
268 if (mod->getModName() == "ntdll.dll" || mod->getModName() == "win32u.dll") {
-
269 search_name = true;
-
270 }
-
271 for (size_t i = 0; i < 25; i++) {
-
272 const peconv::ExportedFunc* exp = exportsMap->find_export_by_va(addr - i);
-
273 if (exp) {
-
274 std::cout << " : " << exp->toString();
-
275 is_resolved = true;
-
276 break;
-
277 }
-
278 if (!search_name) {
-
279 break;
-
280 }
-
281 }
-
282 }
-
283 std::cout << std::endl;
-
284 return is_resolved;
-
285}
+
258
+
+ +
260{
+
261 bool is_resolved = false;
+
262 std::cout << std::hex << addr;
+
263 ScannedModule* mod = modulesInfo.findModuleContaining(addr);
+
264 if (mod) {
+
265 std::cout << " : " << mod->getModName();
+
266 is_resolved = true;
+
267 }
+
268 if (exportsMap && is_resolved) {
+
269 bool search_name = false;
+
270 if (mod->getModName() == "ntdll.dll" || mod->getModName() == "win32u.dll") {
+
271 search_name = true;
+
272 }
+
273 for (size_t i = 0; i < 25; i++) {
+
274 const peconv::ExportedFunc* exp = exportsMap->find_export_by_va(addr - i);
+
275 if (exp) {
+
276 std::cout << " : " << exp->toString();
+
277 is_resolved = true;
+
278 break;
+
279 }
+
280 if (!search_name) {
+
281 break;
+
282 }
+
283 }
+
284 }
+
285 std::cout << std::endl;
+
286 return is_resolved;
+
287}
-
286
-
- -
288{
-
289 std::cout << std::dec << "TID: " << threadi.tid << "\n";
-
290 std::cout << std::hex << "\tStart : ";
-
291 printResolvedAddr(threadi.start_addr);
-
292
-
293 if (threadi.is_extended) {
-
294 std::cout << std::hex << "\tSysStart: ";
-
295 printResolvedAddr(threadi.ext.sys_start_addr);
-
296 std::cout << "\tState: [" << ThreadScanReport::translate_thread_state(threadi.ext.state) << "]";
-
297 if (threadi.ext.state == Waiting) {
-
298 std::cout << " Reason: [" << ThreadScanReport::translate_wait_reason(threadi.ext.wait_reason) << "] Time: " << threadi.ext.wait_time;
-
299 }
-
300 std::cout << "\n";
-
301 }
-
302 std::cout << "\n";
-
303}
+
288
+
+ +
290{
+
291 std::cout << std::dec << "TID: " << threadi.tid << "\n";
+
292 std::cout << std::hex << "\tStart : ";
+
293 printResolvedAddr(threadi.start_addr);
+
294
+
295 if (threadi.is_extended) {
+
296 std::cout << std::hex << "\tSysStart: ";
+
297 printResolvedAddr(threadi.ext.sys_start_addr);
+
298 std::cout << "\tState: [" << ThreadScanReport::translate_thread_state(threadi.ext.state) << "]";
+
299 if (threadi.ext.state == Waiting) {
+
300 std::cout << " Reason: [" << ThreadScanReport::translate_wait_reason(threadi.ext.wait_reason) << "] Time: " << threadi.ext.wait_time;
+
301 }
+
302 std::cout << "\n";
+
303 }
+
304 std::cout << "\n";
+
305}
-
304
-
-
305bool get_page_details(HANDLE processHandle, LPVOID start_va, MEMORY_BASIC_INFORMATION &page_info)
-
306{
-
307 size_t page_info_size = sizeof(MEMORY_BASIC_INFORMATION);
-
308 const SIZE_T out = VirtualQueryEx(processHandle, (LPCVOID)start_va, &page_info, page_info_size);
-
309 const bool is_read = (out == page_info_size) ? true : false;
-
310 const DWORD error = is_read ? ERROR_SUCCESS : GetLastError();
-
311 if (error != ERROR_SUCCESS) {
-
312 //nothing to read
-
313 return false;
-
314 }
-
315 return true;
-
316}
+
306
+
+
307bool get_page_details(HANDLE processHandle, LPVOID start_va, MEMORY_BASIC_INFORMATION &page_info)
+
308{
+
309 size_t page_info_size = sizeof(MEMORY_BASIC_INFORMATION);
+
310 const SIZE_T out = VirtualQueryEx(processHandle, (LPCVOID)start_va, &page_info, page_info_size);
+
311 const bool is_read = (out == page_info_size) ? true : false;
+
312 const DWORD error = is_read ? ERROR_SUCCESS : GetLastError();
+
313 if (error != ERROR_SUCCESS) {
+
314 //nothing to read
+
315 return false;
+
316 }
+
317 return true;
+
318}
-
317
-
- -
319{
-
320 if (!my_report) return false;
-
321
-
322 ULONG_PTR end_va = (ULONG_PTR)my_report->module + my_report->moduleSize;
-
323 MemPageData mem(this->processHandle, this->isReflection, (ULONG_PTR)my_report->module, end_va);
-
324 if (!mem.fillInfo() || !mem.load()) {
-
325 return false;
-
326 }
- -
328 return calc.fill(my_report->stats, nullptr);
-
329}
+
319
+
+ +
321{
+
322 if (!my_report) return false;
+
323
+
324 ULONG_PTR end_va = (ULONG_PTR)my_report->module + my_report->moduleSize;
+
325 MemPageData mem(this->processHandle, this->isReflection, (ULONG_PTR)my_report->module, end_va);
+
326 if (!mem.fillInfo() || !mem.load()) {
+
327 return false;
+
328 }
+ +
330 return calc.fill(my_report->stats, nullptr);
+
331}
-
330
-
- -
332{
-
333 MEMORY_BASIC_INFORMATION page_info = { 0 };
-
334 if (!get_page_details(processHandle, (LPVOID)susp_addr, page_info)) {
-
335 return false;
-
336 }
-
337 if (page_info.State & MEM_FREE) {
-
338 return false;
-
339 }
-
340 ULONGLONG base = (ULONGLONG)page_info.BaseAddress;
-
341 if (this->info.is_extended) {
-
342 my_report->thread_state = info.ext.state;
-
343 my_report->thread_wait_reason = info.ext.wait_reason;
-
344 my_report->thread_wait_time = info.ext.wait_time;
-
345 }
-
346 my_report->module = (HMODULE)base;
-
347 my_report->moduleSize = page_info.RegionSize;
-
348 my_report->protection = page_info.AllocationProtect;
-
349
-
350 my_report->susp_addr = susp_addr;
-
351 my_report->status = SCAN_SUSPICIOUS;
-
352 const bool isStatFilled = fillAreaStats(my_report);
-
353#ifndef NO_ENTROPY_CHECK
-
354 if (isStatFilled && (my_report->stats.entropy < ENTROPY_TRESHOLD)) {
-
355 my_report->status = SCAN_NOT_SUSPICIOUS;
-
356 }
-
357#endif
-
358 return true;
-
359}
+
332
+
+ +
334{
+
335 MEMORY_BASIC_INFORMATION page_info = { 0 };
+
336 if (!get_page_details(processHandle, (LPVOID)susp_addr, page_info)) {
+
337 return false;
+
338 }
+
339 if (page_info.State & MEM_FREE) {
+
340 return false;
+
341 }
+
342 ULONGLONG base = (ULONGLONG)page_info.BaseAddress;
+
343 if (this->info.is_extended) {
+
344 my_report->thread_state = info.ext.state;
+
345 my_report->thread_wait_reason = info.ext.wait_reason;
+
346 my_report->thread_wait_time = info.ext.wait_time;
+
347 }
+
348 my_report->module = (HMODULE)base;
+
349 my_report->moduleSize = page_info.RegionSize;
+
350 my_report->protection = page_info.AllocationProtect;
+
351
+
352 my_report->susp_addr = susp_addr;
+
353 my_report->status = SCAN_SUSPICIOUS;
+
354 const bool isStatFilled = fillAreaStats(my_report);
+
355#ifndef NO_ENTROPY_CHECK
+
356 if (isStatFilled && (my_report->stats.entropy < ENTROPY_TRESHOLD)) {
+
357 my_report->status = SCAN_NOT_SUSPICIOUS;
+
358 }
+
359#endif
+
360 return true;
+
361}
-
360
-
361// if extended info given, allow to filter out from the scan basing on the thread state and conditions
-
- -
363{
-
364 if (!info.is_extended) {
-
365 return true;
-
366 }
-
367 const KTHREAD_STATE state = (KTHREAD_STATE)info.ext.state;
-
368 if (state == Ready) {
-
369 return true;
-
370 }
-
371 if (state == Terminated) {
-
372 return false;
-
373 }
-
374 if (state == Waiting) {
-
375 if (info.ext.sys_start_addr == 0) {
-
376 return true;
-
377 }
-
378 if (info.ext.wait_reason == DelayExecution
-
379 || info.ext.wait_reason == Suspended
-
380 || info.ext.wait_reason == Executive // the thread is waiting got the scheduler
-
381 || info.ext.wait_reason == UserRequest // i.e. WaitForSingleObject/WaitForMultipleObjects
-
382 || info.ext.wait_reason == WrUserRequest // i.e. when the thread calls GetMessage
-
383 )
-
384 {
-
385 return true;
-
386 }
-
387 }
-
388 return false;
-
389}
+
362
+
363// if extended info given, allow to filter out from the scan basing on the thread state and conditions
+
+ +
365{
+
366 if (!info.is_extended) {
+
367 return true;
+
368 }
+
369 const KTHREAD_STATE state = (KTHREAD_STATE)info.ext.state;
+
370 if (state == Ready) {
+
371 return true;
+
372 }
+
373 if (state == Terminated) {
+
374 return false;
+
375 }
+
376 if (state == Waiting) {
+
377 return true;
+
378 }
+
379 return false;
+
380}
-
390
-
- -
392{
-
393 ThreadScanReport* my_report = new ThreadScanReport(info.tid);
-
394 if (!my_report) return nullptr;
-
395#ifdef _SHOW_THREAD_INFO
-
396 printThreadInfo(info);
-
397#endif // _SHOW_THREAD_INFO
-
398 bool is_shc = isAddrInShellcode(info.start_addr);
-
399 if (is_shc) {
-
400 if (reportSuspiciousAddr(my_report, info.start_addr)) {
-
401 return my_report;
-
402 }
-
403 }
-
404#ifndef _DEBUG
-
405 // if NOT compiled in a debug mode, make this check BEFORE scan
- -
407 my_report->status = SCAN_NOT_SUSPICIOUS;
-
408 return my_report;
-
409 }
-
410#endif
-
411 // proceed with detailed checks:
-
412 HANDLE hThread = OpenThread(
-
413 THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | SYNCHRONIZE,
-
414 FALSE,
-
415 info.tid
-
416 );
-
417 if (!hThread) {
-
418#ifdef _DEBUG
-
419 std::cerr << "[-] Could not OpenThread. Error: " << GetLastError() << std::endl;
-
420#endif
-
421 return nullptr;
-
422 }
-
423
-
424 ctx_details cDetails = { 0 };
-
425 const bool is_ok = fetchThreadCtxDetails(processHandle, hThread, cDetails);
-
426
-
427 DWORD exit_code = 0;
-
428 GetExitCodeThread(hThread, &exit_code);
-
429 CloseHandle(hThread);
-
430
-
431 if (!is_ok) {
-
432 // could not fetch the thread context and information
-
433 my_report->status = SCAN_ERROR;
-
434 return my_report;
+
381
+
+ +
383{
+
384 ThreadScanReport* my_report = new ThreadScanReport(info.tid);
+
385 if (!my_report) return nullptr;
+
386#ifdef _SHOW_THREAD_INFO
+
387 printThreadInfo(info);
+
388#endif // _SHOW_THREAD_INFO
+
389 bool is_shc = isAddrInShellcode(info.start_addr);
+
390 if (is_shc) {
+
391 if (reportSuspiciousAddr(my_report, info.start_addr)) {
+
392 return my_report;
+
393 }
+
394 }
+
395#ifndef _DEBUG
+
396 // if NOT compiled in a debug mode, make this check BEFORE scan
+ +
398 my_report->status = SCAN_NOT_SUSPICIOUS;
+
399 return my_report;
+
400 }
+
401#endif
+
402 // proceed with detailed checks:
+
403 HANDLE hThread = OpenThread(
+
404 THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | SYNCHRONIZE,
+
405 FALSE,
+
406 info.tid
+
407 );
+
408 if (!hThread) {
+
409#ifdef _DEBUG
+
410 std::cerr << "[-] Could not OpenThread. Error: " << GetLastError() << std::endl;
+
411#endif
+
412 return nullptr;
+
413 }
+
414
+
415 ctx_details cDetails = { 0 };
+
416 const bool is_ok = fetchThreadCtxDetails(processHandle, hThread, cDetails);
+
417
+
418 DWORD exit_code = 0;
+
419 GetExitCodeThread(hThread, &exit_code);
+
420 CloseHandle(hThread);
+
421
+
422 if (!is_ok) {
+
423 // could not fetch the thread context and information
+
424 my_report->status = SCAN_ERROR;
+
425 return my_report;
+
426 }
+
427#ifdef _DEBUG
+
428 std::string bits = cDetails.is64b ? "64" : "32";
+
429 std::cout << "[" << bits << "-bit] " << std::hex << " Rip: " << cDetails.rip << " Rsp: " << cDetails.rsp;
+
430 if (exit_code != STILL_ACTIVE)
+
431 std::cout << " ExitCode: " << exit_code;
+
432
+
433 if (cDetails.ret_addr != 0) {
+
434 std::cout << std::hex << " Ret: " << cDetails.ret_addr;
435 }
-
436#ifdef _DEBUG
-
437 std::string bits = cDetails.is64b ? "64" : "32";
-
438 std::cout << "[" << bits << "-bit] " << std::hex << " Rip: " << cDetails.rip << " Rsp: " << cDetails.rsp;
-
439 if (exit_code != STILL_ACTIVE)
-
440 std::cout << " ExitCode: " << exit_code;
-
441
-
442 if (cDetails.ret_addr != 0) {
-
443 std::cout << std::hex << " Ret: " << cDetails.ret_addr;
-
444 }
-
445 std::cout << "\n";
-
446#endif
-
447
-
448 if (exit_code != STILL_ACTIVE) {
-
449 my_report->status = SCAN_NOT_SUSPICIOUS;
-
450 return my_report;
-
451 }
-
452#ifdef _DEBUG
-
453 // if compiled in a debug mode, make this check AFTER scan
-
454 // (so that we can see first what was skipped)
- -
456 my_report->status = SCAN_NOT_SUSPICIOUS;
-
457 return my_report;
-
458 }
-
459#endif
-
460
-
461 is_shc = isAddrInShellcode(cDetails.rip);
-
462 if (is_shc) {
-
463 if (reportSuspiciousAddr(my_report, cDetails.rip)) {
-
464 return my_report;
-
465 }
-
466 }
-
467 if ((cDetails.ret_addr != 0) && (cDetails.is_managed == false)) {
-
468 is_shc = isAddrInShellcode(cDetails.ret_addr);
-
469 if (is_shc) {
-
470 if (reportSuspiciousAddr(my_report, cDetails.ret_addr)) {
-
471 return my_report;
-
472 }
-
473 }
-
474 }
-
475 return my_report;
-
476}
+
436 std::cout << "\n";
+
437#endif
+
438
+
439 if (exit_code != STILL_ACTIVE) {
+
440 my_report->status = SCAN_NOT_SUSPICIOUS;
+
441 return my_report;
+
442 }
+
443#ifdef _DEBUG
+
444 // if compiled in a debug mode, make this check AFTER scan
+
445 // (so that we can see first what was skipped)
+ +
447 my_report->status = SCAN_NOT_SUSPICIOUS;
+
448 return my_report;
+
449 }
+
450#endif
+
451
+
452 is_shc = isAddrInShellcode(cDetails.rip);
+
453 if (is_shc) {
+
454 if (reportSuspiciousAddr(my_report, cDetails.rip)) {
+
455 return my_report;
+
456 }
+
457 }
+
458 if ((cDetails.ret_addr != 0) && (cDetails.is_managed == false)) {
+
459 is_shc = isAddrInShellcode(cDetails.ret_addr);
+
460 if (is_shc) {
+
461 if (reportSuspiciousAddr(my_report, cDetails.ret_addr)) {
+
462 return my_report;
+
463 }
+
464 }
+
465 }
+
466 return my_report;
+
467}
A class responsible for filling in the statistics with the data from the particular buffer.
Definition stats.h:73
@@ -621,16 +612,16 @@
static std::string translate_wait_reason(DWORD thread_wait_reason)
-
static std::string translate_thread_state(DWORD thread_state)
-
virtual ThreadScanReport * scanRemote()
-
bool reportSuspiciousAddr(ThreadScanReport *my_report, ULONGLONG susp_addr)
-
size_t fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details &cDetails)
-
void printThreadInfo(const util::thread_info &threadi)
-
bool fillAreaStats(ThreadScanReport *my_report)
-
bool isAddrInShellcode(ULONGLONG addr)
-
bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details &c)
-
bool printResolvedAddr(ULONGLONG addr)
-
size_t analyzeStackFrames(IN const std::vector< ULONGLONG > stack_frame, IN OUT ctx_details &cDetails)
+
static std::string translate_thread_state(DWORD thread_state)
+
virtual ThreadScanReport * scanRemote()
+
bool reportSuspiciousAddr(ThreadScanReport *my_report, ULONGLONG susp_addr)
+
size_t fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details &cDetails)
+
void printThreadInfo(const util::thread_info &threadi)
+
bool fillAreaStats(ThreadScanReport *my_report)
+
bool isAddrInShellcode(ULONGLONG addr)
+
bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details &c)
+
bool printResolvedAddr(ULONGLONG addr)
+
size_t analyzeStackFrames(IN const std::vector< ULONGLONG > stack_frame, IN OUT ctx_details &cDetails)
BOOL is_process_wow64(IN HANDLE processHandle, OUT BOOL *isProcWow64)
BOOL wow64_get_thread_context(IN HANDLE hThread, IN OUT PWOW64_CONTEXT lpContext)
@@ -667,10 +658,10 @@
struct _t_stack_enum_params t_stack_enum_params
-
bool get_page_details(HANDLE processHandle, LPVOID start_va, MEMORY_BASIC_INFORMATION &page_info)
+
bool get_page_details(HANDLE processHandle, LPVOID start_va, MEMORY_BASIC_INFORMATION &page_info)
DWORD WINAPI enum_stack_thread(LPVOID lpParam)
#define ENTROPY_TRESHOLD
-
bool should_scan_context(const util::thread_info &info)
+
bool should_scan_context(const util::thread_info &info)
diff --git a/thread__scanner_8h_source.html b/thread__scanner_8h_source.html index d88524d2d..0e555e688 100644 --- a/thread__scanner_8h_source.html +++ b/thread__scanner_8h_source.html @@ -266,23 +266,23 @@
virtual const bool toJSON(std::stringstream &outs, size_t level, const pesieve::t_json_level &jdetails)
-
static std::string translate_thread_state(DWORD thread_state)
+
static std::string translate_thread_state(DWORD thread_state)
ThreadScanner(HANDLE hProc, bool _isReflection, const util::thread_info &_info, ModulesInfo &_modulesInfo, peconv::ExportsMapper *_exportsMap, ProcessSymbolsManager *_symbols)
-
virtual ThreadScanReport * scanRemote()
-
bool reportSuspiciousAddr(ThreadScanReport *my_report, ULONGLONG susp_addr)
-
size_t fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details &cDetails)
-
void printThreadInfo(const util::thread_info &threadi)
-
bool fillAreaStats(ThreadScanReport *my_report)
-
bool isAddrInShellcode(ULONGLONG addr)
+
virtual ThreadScanReport * scanRemote()
+
bool reportSuspiciousAddr(ThreadScanReport *my_report, ULONGLONG susp_addr)
+
size_t fillStackFrameInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details &cDetails)
+
void printThreadInfo(const util::thread_info &threadi)
+
bool fillAreaStats(ThreadScanReport *my_report)
+
bool isAddrInShellcode(ULONGLONG addr)
peconv::ExportsMapper * exportsMap
const util::thread_info & info
-
bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details &c)
-
bool printResolvedAddr(ULONGLONG addr)
+
bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details &c)
+
bool printResolvedAddr(ULONGLONG addr)
ProcessSymbolsManager * symbols
-
size_t analyzeStackFrames(IN const std::vector< ULONGLONG > stack_frame, IN OUT ctx_details &cDetails)
+
size_t analyzeStackFrames(IN const std::vector< ULONGLONG > stack_frame, IN OUT ctx_details &cDetails)
#define OUT_PADDED(stream, field_size, str)
Definition format_util.h:12