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
thread_scanner.h
Go to the documentation of this file.
1#pragma once
2
3#include <windows.h>
4
5#include "module_scanner.h"
8#include "../stats/stats.h"
10
11namespace pesieve {
12
13
16 {
17 public:
18 static const DWORD THREAD_STATE_UNKNOWN = (-1);
19 static const DWORD THREAD_STATE_WAITING = 5;
20
21 static std::string translate_thread_state(DWORD thread_state);
22 static std::string translate_wait_reason(DWORD thread_wait_reason);
23
24 //---
25
33
34 const virtual void fieldsToJSON(std::stringstream &outs, size_t level, const pesieve::t_json_level &jdetails)
35 {
36 ModuleScanReport::_toJSON(outs, level);
37 outs << ",\n";
38 OUT_PADDED(outs, level, "\"thread_id\" : ");
39 outs << std::dec << tid;
40 if (susp_addr) {
41 outs << ",\n";
42 if (this->module && this->moduleSize) {
43 OUT_PADDED(outs, level, "\"susp_addr\" : ");
44 }
45 else {
46 OUT_PADDED(outs, level, "\"susp_return_addr\" : ");
47 }
48 outs << "\"" << std::hex << susp_addr << "\"";
49 }
50 if (stack_ptr) {
51 outs << ",\n";
52 OUT_PADDED(outs, level, "\"susp_callstack\" : ");
53 outs << "\"" << std::hex << stack_ptr << "\"";
54 }
56 outs << ",\n";
57 OUT_PADDED(outs, level, "\"thread_state\" : ");
58 outs << "\"" << translate_thread_state(thread_state) << "\"";
59
61 outs << ",\n";
62 OUT_PADDED(outs, level, "\"thread_wait_reason\" : ");
63 outs << "\"" << translate_wait_reason(thread_wait_reason) << "\"";
64 }
65 }
66 if (susp_addr) {
67 outs << ",\n";
68 OUT_PADDED(outs, level, "\"protection\" : ");
69 outs << "\"" << std::hex << protection << "\"";
70 if (stats.isFilled()) {
71 outs << ",\n";
72 stats.toJSON(outs, level);
73 }
74 }
75 }
76
77 const virtual bool toJSON(std::stringstream& outs, size_t level, const pesieve::t_json_level &jdetails)
78 {
79 OUT_PADDED(outs, level, "\"thread_scan\" : {\n");
80 fieldsToJSON(outs, level + 1, jdetails);
81 outs << "\n";
82 OUT_PADDED(outs, level, "}");
83 return true;
84 }
85
86 DWORD tid;
87 ULONGLONG susp_addr;
89 ULONGLONG stack_ptr;
94 };
95
97 typedef struct _ctx_details {
98 bool is64b;
99 ULONGLONG rip;
100 ULONGLONG rsp;
101 ULONGLONG rbp;
102 ULONGLONG last_ret; // the last return address on the stack
103 ULONGLONG ret_on_stack; // the last return address stored on the stack
106 bool is_managed; // does it contain .NET modules
108 std::set<ULONGLONG> shcCandidates;
109
110 _ctx_details(bool _is64b = false, ULONGLONG _rip = 0, ULONGLONG _rsp = 0, ULONGLONG _rbp = 0, ULONGLONG _ret_addr = 0)
111 : is64b(_is64b), rip(_rip), rsp(_rsp), rbp(_rbp), last_ret(_ret_addr), ret_on_stack(0), is_ret_as_syscall(false), is_ret_in_frame(false),
113 is_managed(false)
114 {
115 }
116
117 void init(bool _is64b = false, ULONGLONG _rip = 0, ULONGLONG _rsp = 0, ULONGLONG _rbp = 0, ULONGLONG _ret_addr = 0)
118 {
119 this->is64b = _is64b;
120 this->rip = _rip;
121 this->rsp = _rsp;
122 this->rbp = _rbp;
123 this->last_ret = _ret_addr;
124 }
125
127
131 public:
132 ThreadScanner(HANDLE hProc, bool _isReflection, const util::thread_info& _info, ModulesInfo& _modulesInfo, peconv::ExportsMapper* _exportsMap, ProcessSymbolsManager* _symbols)
133 : ProcessFeatureScanner(hProc), isReflection(_isReflection),
134 info(_info), modulesInfo(_modulesInfo), exportsMap(_exportsMap), symbols(_symbols)
135 {
136 }
137
138 virtual ThreadScanReport* scanRemote();
139
140 protected:
141 bool scanRemoteThreadCtx(HANDLE hThread, ThreadScanReport* my_report);
142 bool isAddrInShellcode(ULONGLONG addr);
143 void printThreadInfo(const util::thread_info& threadi);
144 bool printResolvedAddr(ULONGLONG addr);
145 bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details& c);
146 size_t fillCallStackInfo(IN HANDLE hProcess, IN HANDLE hThread, IN LPVOID ctx, IN OUT ctx_details& cDetails);
147 size_t analyzeCallStack(IN const std::vector<ULONGLONG> &stack_frame, IN OUT ctx_details& cDetails);
148 bool checkReturnAddrIntegrity(IN const std::vector<ULONGLONG>& callStack);
149 bool fillAreaStats(ThreadScanReport* my_report);
150 bool reportSuspiciousAddr(ThreadScanReport* my_report, ULONGLONG susp_addr);
151
155 peconv::ExportsMapper* exportsMap;
157 };
158
159}; //namespace pesieve
bool isFilled() const
Definition stats.h:40
virtual const bool toJSON(std::stringstream &outs, size_t level)
Definition stats.h:49
A base class of all the reports detailing on the output of the performed module's scan.
virtual const bool _toJSON(std::stringstream &outs, size_t level=JSON_LEVEL, const pesieve::t_json_level &jdetails=JSON_BASIC)
A container of all the process modules that were scanned.
A base class for all the scanners checking appropriate process' features.
A report from the thread scan, generated by ThreadScanner.
virtual const void fieldsToJSON(std::stringstream &outs, size_t level, const pesieve::t_json_level &jdetails)
static std::string translate_wait_reason(DWORD thread_wait_reason)
static const DWORD THREAD_STATE_UNKNOWN
static const DWORD THREAD_STATE_WAITING
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)
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 fillCallStackInfo(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)
size_t analyzeCallStack(IN const std::vector< ULONGLONG > &stack_frame, IN OUT ctx_details &cDetails)
peconv::ExportsMapper * exportsMap
const util::thread_info & info
bool fetchThreadCtxDetails(IN HANDLE hProcess, IN HANDLE hThread, OUT ctx_details &c)
bool printResolvedAddr(ULONGLONG addr)
ProcessSymbolsManager * symbols
bool scanRemoteThreadCtx(HANDLE hThread, ThreadScanReport *my_report)
bool checkReturnAddrIntegrity(IN const std::vector< ULONGLONG > &callStack)
#define OUT_PADDED(stream, field_size, str)
Definition format_util.h:12
struct pesieve::_ctx_details ctx_details
A custom structure keeping a fragment of a thread context.
A custom structure keeping a fragment of a thread context.
void init(bool _is64b=false, ULONGLONG _rip=0, ULONGLONG _rsp=0, ULONGLONG _rbp=0, ULONGLONG _ret_addr=0)
std::set< ULONGLONG > shcCandidates
_ctx_details(bool _is64b=false, ULONGLONG _rip=0, ULONGLONG _rsp=0, ULONGLONG _rbp=0, ULONGLONG _ret_addr=0)