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
process_reflection.cpp
Go to the documentation of this file.
2#include <iostream>
3
4#ifndef RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED
5#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001
6#endif
7
8#ifndef RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES
9#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002
10#endif
11
12#ifndef RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE
13#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004 // don't update synchronization objects
14#endif
15
16#ifndef HPSS
17#define HPSS HANDLE
18#endif
19
20namespace pesieve {
21 namespace util {
22
23 typedef struct {
26
27 typedef struct {
31
38
39 // Win >= 7
40 NTSTATUS (NTAPI *_RtlCreateProcessReflection) (
41 HANDLE ProcessHandle,
42 ULONG Flags,
47 ) = NULL;
48
49 // Win >= 8.1
50
76
88
89 DWORD (__stdcall *_PssCaptureSnapshot)( //from Kernel32.dll
90 HANDLE ProcessHandle,
94 ) = NULL;
95
96 DWORD (__stdcall *_PssFreeSnapshot)(
97 HANDLE ProcessHandle,
99 ) = NULL;
100
101 DWORD (__stdcall *_PssQuerySnapshot)(
104 void* Buffer,
106 ) = NULL;
107
109 {
110 if (_PssCaptureSnapshot == NULL || _PssFreeSnapshot == NULL || _PssQuerySnapshot == NULL) {
111 HMODULE lib = LoadLibraryA("kernel32.dll");
112 if (!lib) return false;
113
114 FARPROC proc1 = GetProcAddress(lib, "PssCaptureSnapshot");
115 if (!proc1) return false;
116
117 FARPROC proc2 = GetProcAddress(lib, "PssFreeSnapshot");
118 if (!proc2) return false;
119
120 FARPROC proc3 = GetProcAddress(lib, "PssQuerySnapshot");
121 if (!proc3) return false;
122
123 _PssCaptureSnapshot = (DWORD(__stdcall *)(
124 HANDLE,
126 DWORD,
127 HPSS*
128 )) proc1;
129
130 _PssFreeSnapshot = (DWORD(__stdcall *)(
131 HANDLE,
132 HPSS
133 )) proc2;
134
135 _PssQuerySnapshot = (DWORD(__stdcall *)(
136 HPSS,
138 void*,
139 DWORD
140 )) proc3;
141 }
142 if (_PssCaptureSnapshot == NULL || _PssFreeSnapshot == NULL || _PssQuerySnapshot == NULL) {
143 return false;
144 }
145 return true;
146 }
147
149 {
150 if (_RtlCreateProcessReflection == NULL) {
151 HMODULE lib = LoadLibraryA("ntdll.dll");
152 if (!lib) return false;
153
154 FARPROC proc = GetProcAddress(lib, "RtlCreateProcessReflection");
155 if (!proc) return false;
156
157 _RtlCreateProcessReflection = (NTSTATUS(NTAPI *) (
158 HANDLE,
159 ULONG,
160 PVOID,
161 PVOID,
162 HANDLE,
164 )) proc;
165
166 }
167 if (_RtlCreateProcessReflection == NULL) return false;
168 return true;
169 }
170
171 typedef struct {
172 HANDLE orig_hndl;
175 bool is_ok;
176 } t_refl_args;
177
178 DWORD WINAPI refl_creator(LPVOID lpParam)
179 {
180 t_refl_args *args = static_cast<t_refl_args*>(lpParam);
181 if (!args) {
182 return !S_OK;
183 }
184 args->is_ok = false;
185
187 NTSTATUS ret = _RtlCreateProcessReflection(args->orig_hndl, RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES, NULL, NULL, NULL, &info);
188 if (ret == S_OK) {
189 args->is_ok = true;
190 args->returned_hndl = info.ReflectionProcessHandle;
191 args->returned_pid = static_cast<DWORD>(reinterpret_cast<uintptr_t>(info.ReflectionClientId.UniqueProcess));
192 }
193 return ret;
194 }
195
196 HANDLE make_process_reflection1(HANDLE orig_hndl)
197 {
198 const DWORD max_wait = 1000;
200 return NULL;
201 }
202
203 t_refl_args args = { 0 };
204 args.orig_hndl = orig_hndl;
205
206 HANDLE hThead = CreateThread(
207 NULL, // default security attributes
208 0, // use default stack size
209 refl_creator, // thread function name
210 &args, // argument to thread function
211 0, // use default creation flags
212 0); // returns the thread identifier
213
214 DWORD wait_result = WaitForSingleObject(hThead, max_wait);
215 if (wait_result == WAIT_TIMEOUT) {
216 std::cerr << "[!] [" << GetProcessId(orig_hndl) << "] Cannot create reflection: timeout passed!\n";
217 TerminateThread(hThead, 0);
218 CloseHandle(hThead);
219 return NULL;
220 }
221 CloseHandle(hThead);
222 if (args.is_ok) {
223 if (args.returned_hndl == NULL || args.returned_hndl == INVALID_HANDLE_VALUE) {
224 return NULL;
225 }
226#ifdef _DEBUG
227 std::cout << "Created reflection, PID = " << std::dec << args.returned_pid << "\n";
228#endif
229 return args.returned_hndl;
230 }
231 return NULL;
232 }
233
234 HPSS make_process_snapshot(HANDLE orig_hndl)
235 {
237 return NULL;
238 }
244 //| PSS_CAPTURE_HANDLE_TRACE
246 //| PSS_CAPTURE_THREAD_CONTEXT
247 //| PSS_CAPTURE_THREAD_CONTEXT_EXTENDED
251 //| PSS_CREATE_BREAKAWAY_OPTIONAL
253 //| PSS_CREATE_RELEASE_SECTION
254 );
255
256 HPSS snapShot = { 0 };
257 DWORD ret = _PssCaptureSnapshot(orig_hndl, capture_flags, 0, &snapShot);
258 if (ret != ERROR_SUCCESS) {
259#ifdef _DEBUG
260 std::cout << "PssCaptureSnapshot failed: " << std::hex << " ret: " << ret << " err: " << GetLastError() << "\n";
261#endif
262 return NULL;
263 }
264 return snapShot;
265 }
266
267 bool release_process_snapshot(HANDLE procHndl, HPSS snapshot)
268 {
269 if (procHndl && snapshot) {
270 BOOL is_ok = _PssFreeSnapshot(procHndl, snapshot);
271#ifdef _DEBUG
272 if (is_ok) std::cout << "Released process snapshot\n";
273#endif
274 return is_ok ? true : false;
275 }
276 return false;
277 }
278
280 {
282 DWORD ret = _PssQuerySnapshot(snapshot, PSS_QUERY_VA_CLONE_INFORMATION, &info, sizeof(info));
283 if (ret != ERROR_SUCCESS) {
284 return NULL;
285 }
286 HANDLE clone = info.VaCloneHandle;
287#ifdef _DEBUG
288 DWORD clone_pid = GetProcessId(clone);
289 std::cout << "Clone PID = " << std::dec << clone_pid << "\n";
290#endif
291 return clone;
292 }
293
294 };
295};
296
298{
299#ifdef USE_PROCESS_SNAPSHOT
301 return true;
302 }
303#endif
304#ifdef USE_RTL_PROCESS_REFLECTION
306 return true;
307 }
308#endif
309 return false;
310}
311
313{
314 if (orig_hndl == NULL) {
315 return NULL;
316 }
317 HANDLE clone = NULL;
318#ifdef USE_PROCESS_SNAPSHOT
320 HPSS snapshot = make_process_snapshot(orig_hndl);
321 clone = make_process_reflection2(snapshot);
322 release_process_snapshot(orig_hndl, snapshot);
323 if (clone) {
324 return clone;
325 }
326 }
327#endif
328#ifdef USE_RTL_PROCESS_REFLECTION
330 clone = make_process_reflection1(orig_hndl);
331 }
332#endif
333 return clone;
334}
335
337{
338 if (procHndl == NULL || *procHndl == NULL) {
339 return false;
340 }
341#ifdef _DEBUG
342 DWORD clone_pid = GetProcessId(*procHndl);
343 std::cout << "Releasing Clone, PID = " << std::dec << clone_pid << "\n";
344#endif
345 BOOL is_ok = TerminateProcess(*procHndl, 0);
346 CloseHandle(*procHndl);
347 *procHndl = NULL;
348
349#ifdef _DEBUG
350 std::cout << "Released process reflection\n";
351#endif
352 return is_ok ? true : false;
353}
PSS_CAPTURE_FLAGS DWORD ThreadContextFlags
PSS_CAPTURE_FLAGS CaptureFlags
ULONG PVOID StartRoutine
NTSTATUS(NTAPI *_RtlCreateProcessReflection)(HANDLE ProcessHandle
PSS_QUERY_INFORMATION_CLASS InformationClass
HANDLE make_process_reflection1(HANDLE orig_hndl)
ULONG PVOID PVOID HANDLE T_RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION * ReflectionInformation
DWORD WINAPI refl_creator(LPVOID lpParam)
HPSS make_process_snapshot(HANDLE orig_hndl)
ULONG PVOID PVOID HANDLE EventHandle
@ PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION
PSS_CAPTURE_FLAGS DWORD HPSS * SnapshotHandle
ULONG PVOID PVOID StartContext
PSS_QUERY_INFORMATION_CLASS void DWORD BufferLength
bool release_process_snapshot(HANDLE procHndl, HPSS snapshot)
BOOL(CALLBACK *_MiniDumpWriteDump)(HANDLE hProcess
bool load_RtlCreateProcessReflection()
bool release_process_reflection(HANDLE *reflection_hndl)
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
PSS_QUERY_INFORMATION_CLASS void * Buffer
HANDLE make_process_reflection(HANDLE orig_hndl)
HANDLE make_process_reflection2(HPSS snapshot)
std::string info()
The string with the basic information about the scanner.
Definition pe_sieve.cpp:274
#define HPSS
#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES