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
workingset_enum.cpp
Go to the documentation of this file.
1#include "workingset_enum.h"
2
3#include <iostream>
4
5#include <psapi.h>
6#pragma comment(lib,"psapi.lib")
7
8#ifdef _WIN64
9 const ULONGLONG mask = ULONGLONG(-1);
10#else
11 const ULONGLONG mask = DWORD(-1);
12#endif
13
14namespace pesieve {
15 namespace util {
16
18 {
20
21 while (start_va < mask) {
22 //std::cout << "Checking: " << std::hex << start_va << std::endl;
24 const SIZE_T out = VirtualQueryEx(processHandle, (LPCVOID)start_va, &page_info, page_info_size);
25 const bool is_read = (out == page_info_size) ? true : false;
28 //nothing more to read
29#ifdef _DEBUG
30 std::cout << "Nothing more to read: " << std::hex << start_va << std::endl;
31#endif
32 break;
33 }
35 std::cerr << "[ERROR] Cannot query the memory region. " << std::hex << start_va << " Error: " << std::dec << error << std::endl;
36 break;
37 }
38 if (!is_read) {
39 // on any other error:
40 std::cerr << "[WARNING] Cannot query the memory region. " << std::hex<< start_va << " Error: " << std::dec << error << ", skipping the page..." << std::endl;
41 start_va += PAGE_SIZE;
42 continue;
43 }
44 if ((page_info.State & MEM_FREE) || (page_info.State & MEM_COMMIT) == 0) {
45 if (page_info.RegionSize != 0) {
46 //std::cout << "Free: " << std::hex << start_va << " RegionSize:" << page_info.RegionSize << std::endl;
47 start_va += page_info.RegionSize;
48 continue;
49 }
50 }
51 if (page_info.RegionSize == 0) {
52 start_va += PAGE_SIZE;
53 continue;
54 }
55 //std::cout << "Commited: " << std::hex << start_va << " RegionSize: " << page_info.RegionSize << " Err: " << std::dec << error << std::endl;
56 return true;
57 }
58 return false;
59 }
60
61 };
62};
63
64size_t pesieve::util::enum_workingset(HANDLE processHandle, std::set<mem_region_info> &region_bases)
65{
66 region_bases.clear();
67
68 MEMORY_BASIC_INFORMATION page_info = { 0 };
69 ULONGLONG next_va = 0;
70 while (get_next_commited_region(processHandle, next_va, page_info))
71 {
72 ULONGLONG base = (ULONGLONG)page_info.BaseAddress;
73 next_va = base + page_info.RegionSize; //end of the region
74 mem_region_info curr_info((ULONGLONG)page_info.AllocationBase, base, page_info.RegionSize);
75
76 if (region_bases.find(curr_info) != region_bases.end()) {
77 // don't let it stuck on adding the same region over and over again
78 break;
79 }
80 region_bases.insert(curr_info);
81 }
82 return region_bases.size();
83}
84
86{
87 DWORD number_of_entries = 1;
88 DWORD buffer_size = sizeof(PSAPI_WORKING_SET_INFORMATION) + (number_of_entries * sizeof(PSAPI_WORKING_SET_BLOCK));
89 PSAPI_WORKING_SET_INFORMATION* buffer = reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>(calloc(1, buffer_size));
90 if (!buffer) {
91 return 0; //this should not happen
92 }
93 DWORD res = QueryWorkingSet(processHandle, buffer, buffer_size);
94 if (res == FALSE && GetLastError() == ERROR_BAD_LENGTH) {
95 // ERROR_BAD_LENGTH is normal: we didn't provide the buffer that could fit all the entries
96 res = TRUE;
97 }
98 number_of_entries = static_cast<DWORD>(buffer->NumberOfEntries);
99 free(buffer); buffer = NULL;
100
101 if (!res) {
102 return 0;
103 }
104#ifdef _DEBUG
105 std::cout << "Number of entries: " << std::dec << number_of_entries << std::endl;
106#endif
107 return number_of_entries;
108}
DWORD count_workingset_entries(HANDLE processHandle)
bool get_next_commited_region(HANDLE processHandle, ULONGLONG start_va, MEMORY_BASIC_INFORMATION &page_info)
size_t enum_workingset(HANDLE processHandle, std::set< mem_region_info > &regions)
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
size_t fill_iat(BYTE *vBuf, size_t vBufSize, IN const peconv::ExportsMapper *exportsMap, IN OUT IATBlock &iat, IN ThunkFoundCallback *callback)
Definition iat_finder.h:31
const ULONGLONG mask
#define PAGE_SIZE