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 const DWORD wait_result = WaitForSingleObject(hThead, max_wait);
215 if (wait_result == WAIT_TIMEOUT) {
216#ifdef _DEBUG
217 std::cerr << "[!] [" << GetProcessId(orig_hndl) << "] Cannot create reflection: timeout passed!\n";
218#endif
219 TerminateThread(hThead, 0);
220 CloseHandle(hThead);
221 return NULL;
222 }
223 CloseHandle(hThead);
224 if (args.is_ok) {
225 if (args.returned_hndl == NULL || args.returned_hndl == INVALID_HANDLE_VALUE) {
226 return NULL;
227 }
228#ifdef _DEBUG
229 std::cout << "Created reflection, PID = " << std::dec << args.returned_pid << "\n";
230#endif
231 return args.returned_hndl;
232 }
233 return NULL;
234 }
235
236 HPSS make_process_snapshot(HANDLE orig_hndl)
237 {
239 return NULL;
240 }
241
242 const auto capture_flags =
248 );
249
250 HPSS snapShot = { 0 };
251 DWORD ret = _PssCaptureSnapshot(orig_hndl, capture_flags, 0, &snapShot);
252 if (ret != ERROR_SUCCESS) {
253#ifdef _DEBUG
254 std::cout << "PssCaptureSnapshot failed: " << std::hex << " ret: " << ret << " err: " << ret << "\n";
255#endif
256 return NULL;
257 }
258 return snapShot;
259 }
260
262 {
263 if (!snapshot) return false;
264 DWORD ret = _PssFreeSnapshot(GetCurrentProcess(), snapshot);
265 const BOOL is_ok = (ret == ERROR_SUCCESS) ? true : false;
266#ifdef _DEBUG
267 std::cout << "Released process snapshot, res: " << std::hex << ret << "\n";
268#endif
269 return is_ok;
270 }
271
273 {
275 DWORD ret = _PssQuerySnapshot(snapshot, PSS_QUERY_VA_CLONE_INFORMATION, &info, sizeof(info));
276 if (ret != ERROR_SUCCESS) {
277 return NULL;
278 }
279 HANDLE clone = info.VaCloneHandle;
280#ifdef _DEBUG
281 DWORD clone_pid = GetProcessId(clone);
282 std::cout << "Clone PID = " << std::dec << clone_pid << "\n";
283#endif
284 return clone;
285 }
286
287 };
288};
289
291{
292#ifdef USE_PROCESS_SNAPSHOT
294 return true;
295 }
296#endif
297#ifdef USE_RTL_PROCESS_REFLECTION
299 return true;
300 }
301#endif
302 return false;
303}
304
306{
307 if (!orig_hndl) {
308 return nullptr;
309 }
310 HANDLE clone = NULL;
311#ifdef USE_PROCESS_SNAPSHOT
313 HPSS snapshot = make_process_snapshot(orig_hndl);
314 clone = make_process_reflection2(snapshot);
315
316 if (clone) {
317 return new ProcessRefl(clone, snapshot);
318 }
319 release_process_snapshot(snapshot);
320 }
321#endif
322#ifdef USE_RTL_PROCESS_REFLECTION
324 clone = make_process_reflection1(orig_hndl);
325
326 if (clone) {
327 return new ProcessRefl(clone);
328 }
329 }
330#endif
331 return nullptr;
332}
333
334//---
335
344
346{
347 if (!hReflHndl) {
348 return false;
349 }
350#ifdef _DEBUG
351 DWORD clone_pid = GetProcessId(hReflHndl);
352 std::cout << "Releasing Clone, PID = " << std::dec << clone_pid << "\n";
353#endif
354 BOOL is_ok = TerminateProcess(hReflHndl, 0);
355 CloseHandle(hReflHndl);
356 hReflHndl = NULL;
357
358#ifdef _DEBUG
359 std::cout << "Released process reflection\n";
360#endif
361 return is_ok ? true : false;
362}
ProcessRefl * make_process_reflection(HANDLE orig_hndl)
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
bool release_process_snapshot(HPSS snapshot)
@ PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION
PSS_CAPTURE_FLAGS DWORD HPSS * SnapshotHandle
ULONG PVOID PVOID StartContext
PSS_QUERY_INFORMATION_CLASS void DWORD BufferLength
BOOL(CALLBACK *_MiniDumpWriteDump)(HANDLE hProcess
bool load_RtlCreateProcessReflection()
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
PSS_QUERY_INFORMATION_CLASS void * Buffer
HANDLE make_process_reflection2(HPSS snapshot)
std::string info()
The string with the basic information about the scanner.
Definition pe_sieve.cpp:276
#define HPSS
#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES