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
threads_util.cpp
Go to the documentation of this file.
1#include "threads_util.h"
2
3#include <peconv.h>
4#include <tlhelp32.h>
5#include "../utils/ntddk.h"
6
7#ifdef _DEBUG
8#include <iostream>
9#endif
10
11bool pesieve::util::fetch_threads_info(DWORD pid, std::vector<thread_info>& threads_info)
12{
13 BYTE* buffer = nullptr;
14 ULONG buffer_size = 0;
15 ULONG ret_len = 0;
16
17 NTSTATUS status = STATUS_UNSUCCESSFUL;
18 while (status != STATUS_SUCCESS) {
19 status = NtQuerySystemInformation(SystemProcessInformation, buffer, buffer_size, &ret_len);
20 if (status == STATUS_INFO_LENGTH_MISMATCH) {
21 free(buffer);
22 buffer = nullptr;
23 buffer_size = 0;
24 buffer = (BYTE*)calloc(ret_len, 1);
25 if (!buffer) {
26 return false;
27 }
28 buffer_size = ret_len;
29 continue; // try again
30 }
31 break; //other error, or success
32 };
33
34 if (status != STATUS_SUCCESS) {
35 free(buffer);
36 return false;
37 }
38
39 bool found = false;
40 SYSTEM_PROCESS_INFORMATION* info = (SYSTEM_PROCESS_INFORMATION*)buffer;
41 while (info) {
42 if (info->UniqueProcessId == pid) {
43 found = true;
44 break;
45 }
46 if (!info->NextEntryOffset) {
47 break;
48 }
49 size_t record_size = info->NextEntryOffset;
50 if (record_size < sizeof(SYSTEM_PROCESS_INFORMATION)) {
51 // Record size smaller than expected, probably it is an old system that doesn not support the new version of this API
52#ifdef _DEBUG
53 std::cout << "The new version of SYSTEM_PROCESS_INFORMATION is not supported!\n";
54#endif
55 break;
56 }
57 info = (SYSTEM_PROCESS_INFORMATION*)((ULONG_PTR)info + info->NextEntryOffset);
58 if (!peconv::validate_ptr(buffer, buffer_size, info, sizeof(SYSTEM_PROCESS_INFORMATION))) {
59 break;
60 }
61 }
62
63 if (!found) {
64 free(buffer);
65 return false;
66 }
67
68 size_t thread_count = info->NumberOfThreads;
69 for (size_t i = 0; i < thread_count; i++) {
70 thread_info threadi;
71
72 threadi.tid = MASK_TO_DWORD((ULONGLONG)info->Threads[i].ClientId.UniqueThread);
73 threadi.is_extended = true;
74 threadi.ext.start_addr = (ULONG_PTR)info->Threads[i].StartAddress;
75 threadi.ext.state = info->Threads[i].ThreadState;
76 threadi.ext.wait_reason = info->Threads[i].WaitReason;
77 threadi.ext.wait_time = info->Threads[i].WaitTime;
78 threads_info.push_back(threadi);
79 }
80
81 free(buffer);
82 return true;
83}
84
85bool pesieve::util::fetch_threads_by_snapshot(DWORD pid, std::vector<thread_info>& threads_info)
86{
87 HANDLE hThreadSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
88 if (hThreadSnapShot == INVALID_HANDLE_VALUE) {
89 const DWORD err = GetLastError();
90#ifdef _DEBUG
91 std::cerr << "[-] Could not create threads snapshot. Error: " << std::dec << err << std::endl;
92#endif
93 return false;
94 }
95 THREADENTRY32 th32 = { 0 };
96 th32.dwSize = sizeof(THREADENTRY32);
97
98 //check all threads in the process:
99 if (!Thread32First(hThreadSnapShot, &th32)) {
100 CloseHandle(hThreadSnapShot);
101#ifdef _DEBUG
102 std::cerr << "[-] Could not enumerate thread. Error: " << GetLastError() << std::endl;
103#endif
104 return false;
105 }
106 do {
107 if (th32.th32OwnerProcessID != pid) {
108 continue;
109 }
110
111 thread_info threadi;
112 threadi.tid = th32.th32ThreadID;
113 threadi.is_extended = false;
114 threads_info.push_back(threadi);
115
116 } while (Thread32Next(hThreadSnapShot, &th32));
117
118 CloseHandle(hThreadSnapShot);
119 return true;
120}
#define MASK_TO_DWORD(val)
Definition iat_finder.h:9
bool fetch_threads_info(DWORD pid, std::vector< thread_info > &threads_info)
NTSTATUS(NTAPI *_RtlCreateProcessReflection)(HANDLE ProcessHandle
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
bool fetch_threads_by_snapshot(DWORD pid, std::vector< thread_info > &threads_info)
std::string info()
The string with the basic information about the scanner.
Definition pe_sieve.cpp:268