13#define EXECUTABLE_FLAGS (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
14#define MAX_PROCESSES 65536
31 lastScanStart = lastScanEnd = 0;
35 void setProcessStart()
51 std::cout << std::dec <<
"Deleting thread: " << thread->get_id() << std::endl;
53 if (thread->joinable()) {
63ProceesStat procStats[MAX_PROCESSES] = { 0 };
75bool isDelayedLoad(std::uint32_t pid)
77 if (!procStats[pid].startTime)
true;
81 if (now - procStats[pid].startTime > 1) {
88bool isCooldown(std::uint32_t pid)
90 if (procStats[pid].cooldown)
95 if (now - procStats[pid].cooldown > 1)
96 procStats[pid].resetCooldown();
105void updateCooldown(std::uint32_t pid)
107 if (procStats[pid].cooldown)
109 time(&procStats[pid].cooldown);
114bool isAllocationExecutable(std::uint32_t pid, LPVOID baseAddress)
116 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION, FALSE, pid);
117 if (!hProcess)
return false;
123 LPVOID addr = baseAddress;
124 MEMORY_BASIC_INFORMATION mbi = { 0 };
128 if (VirtualQueryEx(hProcess, addr, &mbi,
sizeof(MEMORY_BASIC_INFORMATION)) && mbi.AllocationBase)
133 base = mbi.AllocationBase;
137 if (base == mbi.AllocationBase)
139 if (mbi.AllocationProtect & EXECUTABLE_FLAGS || mbi.Protect & EXECUTABLE_FLAGS)
143 std::cout <<
"New Executable Section: " <<
" (" << pid <<
") 0x" << std::hex << addr <<
" Flags=[Alloc: " << mbi.AllocationProtect <<
" | Now: " << mbi.Protect <<
"] " << std::dec << std::endl;
149 addr =
static_cast<char*
>(addr) + mbi.RegionSize;
157 }
while (!stop && !isExec);
159 CloseHandle(hProcess);
164inline std::wstring getProcessName(
const DWORD pid)
166 WCHAR processName[MAX_PATH] = { 0 };
170 std::wstring pName(processName);
171 std::transform(pName.begin(), pName.end(), pName.begin(), tolower);
172 std::size_t found = pName.find_last_of(L
"/\\");
173 if (found == (-1) || found >= pName.length()) {
176 return pName.substr(found + 1);
180bool isWatchedPid(
const DWORD pid)
183 const std::wstring wImgFileName = getProcessName(pid);
191bool isWatchedName(
const std::string& imgFileName)
193 const std::wstring wImgFileName(imgFileName.begin(), imgFileName.end());
215 hhunter.summarizeScan(report, pesieve::SHOW_SUSPICIOUS);
224 procStats[pid].lastScanEnd = now;
228void runHHScan(std::uint32_t pid)
230 static std::mutex mutx;
231 const std::lock_guard<std::mutex> lock(mutx);
236 bool shouldScan =
false;
237 if (procStats[pid].lastScanStart == 0 ||
238 (procStats[pid].lastScanEnd != 0 && (now - procStats[pid].lastScanEnd) > 1)) {
244 std::cout << std::dec << pid <<
" : " << now <<
": Skipping the scan...\n";
248 procStats[pid].lastScanStart = now;
249 procStats[pid].lastScanEnd = 0;
257 procStats[pid].cleanupThread();
258 procStats[pid].thread =
new std::thread(runHHinNewThread, args);
262 std::cout << std::dec << pid <<
" : Running a new thread: " << procStats[pid].thread->get_id() << std::endl;
267void printAllProperties(krabs::parser &parser)
269 for (krabs::property& prop : parser.properties()) {
270 std::wcout << prop.name() <<
"\n";
274std::string ipv4FromDword(DWORD ip_dword)
276 std::ostringstream oss;
277 BYTE* ip_bytes = (BYTE*)&ip_dword;
278 const size_t chunks =
sizeof(DWORD);
279 for (
int i = 0; i < chunks; i++) {
280 oss << std::dec << (
unsigned int)ip_bytes[i];
281 if (i < (chunks - 1))
289 krabs::kernel_trace trace(L
"HollowsHunter");
290 g_initTime = time(NULL);
292 krabs::kernel::process_provider processProvider;
293 krabs::kernel::image_load_provider imageLoadProvider;
294 krabs::kernel::virtual_alloc_provider virtualAllocProvider;
295 krabs::kernel::network_tcpip_provider tcpIpProvider;
296 krabs::kernel::object_manager_provider objectMgrProvider;
299 processProvider.add_on_event_callback([](
const EVENT_RECORD& record,
const krabs::trace_context& trace_context)
301 const int OPCODE_START = 0x1;
302 const int OPCODE_STOP = 0x2;
303 krabs::schema schema(record, trace_context.schema_locator);
304 if (schema.event_opcode() == OPCODE_STOP) {
305 krabs::parser parser(schema);
306 std::uint32_t pid = parser.parse<std::uint32_t>(L
"ProcessId");
307 procStats[pid].cleanupThread();
309 if (schema.event_opcode() == OPCODE_START)
311 krabs::parser parser(schema);
312 std::uint32_t parentPid = parser.parse<std::uint32_t>(L
"ParentId");
314 std::string filename = parser.parse<std::string>(L
"ImageFileName");
315 if (isWatchedName(filename)) {
316 std::uint32_t pid = parser.parse<std::uint32_t>(L
"ProcessId");
318 procStats[pid].cleanupThread();
319 procStats[pid].init();
320 procStats[pid].setProcessStart();
323 std::cout << std::dec << time(NULL) <<
" : New Process: " << filename <<
" (" << pid <<
") Parent: " << parentPid << std::endl;
328 if (isWatchedPid(parentPid)) {
329 runHHScan(parentPid);
334 imageLoadProvider.add_on_event_callback([](
const EVENT_RECORD& record,
const krabs::trace_context& trace_context)
336 krabs::schema schema(record, trace_context.schema_locator);
338 if (schema.event_opcode() == 10) {
339 krabs::parser parser(schema);
340 std::uint32_t pid = parser.parse<std::uint32_t>(L
"ProcessId");
341 if (!isWatchedPid(pid))
return;
343 std::wstring filename = parser.parse<std::wstring>(L
"FileName");
344 if (!isDelayedLoad(pid)) {
347 std::wcout <<
" LOADING " << std::dec << pid <<
" : " << time(NULL) <<
" : IMAGE:" << filename << std::endl;
353 std::wcout << std::dec << pid <<
" : " << time(NULL) <<
" : IMAGE:" << filename << std::endl;
359 tcpIpProvider.add_on_event_callback([](
const EVENT_RECORD& record,
const krabs::trace_context& trace_context)
361 krabs::schema schema(record, trace_context.schema_locator);
362 krabs::parser parser(schema);
363 std::uint32_t pid = parser.parse<std::uint32_t>(L
"PID");
364 if (!isWatchedPid(pid))
return;
366 krabs::ip_address daddr = parser.parse<krabs::ip_address>(L
"daddr");
371 std::wcout << std::dec << pid <<
" : " << schema.task_name() <<
" : " << schema.opcode_name();
372 if (!daddr.is_ipv6) {
373 long ipv4 = daddr.v4;
374 std::cout <<
" -> " << ipv4FromDword(ipv4);
381 objectMgrProvider.add_on_event_callback([](
const EVENT_RECORD& record,
const krabs::trace_context& trace_context)
383 krabs::schema schema(record, trace_context.schema_locator);
384 if (schema.event_opcode() == 34)
386 krabs::parser parser(schema);
387 std::uint32_t pid = parser.parse<std::uint32_t>(L
"TargetProcessId");
388 if (!isWatchedPid(pid))
return;
392 std::wcout << std::dec << pid <<
" : " << schema.task_name() <<
" : " << schema.opcode_name() <<
"\n";
398 virtualAllocProvider.add_on_event_callback([](
const EVENT_RECORD& record,
const krabs::trace_context& trace_context)
400 krabs::schema schema(record, trace_context.schema_locator);
401 if (schema.event_opcode() == 98)
403 krabs::parser parser(schema);
404 std::uint32_t targetPid = parser.parse<std::uint32_t>(L
"ProcessId");
405 if (!isWatchedPid(targetPid))
return;
407 if (!isCooldown(targetPid))
return;
410 LPVOID baseAddress = parser.parse<LPVOID>(L
"BaseAddress");
414 doScan = isAllocationExecutable(targetPid, baseAddress);
419 updateCooldown(targetPid);
420 runHHScan(targetPid);
426 if (settings.
tcpip) trace.enable(tcpIpProvider);
427 if (settings.
obj_mgr) trace.enable(objectMgrProvider);
429 if (settings.
img_load) trace.enable(imageLoadProvider);
430 if (settings.
allocation) trace.enable(virtualAllocProvider);
432 std::cout <<
"Starting listener..." << std::endl;
435 catch (std::runtime_error& err) {
436 std::cerr <<
"[ERROR] " << err.what() << std::endl;
size_t countReports(const pesieve::t_results_filter rfilter) const
static t_single_scan_status shouldScanProcess(const hh_params &hh_args, const time_t hh_initTime, const DWORD pid, const WCHAR *exe_file)
enum single_status t_single_scan_status
bool get_process_path(DWORD processID, WCHAR *szProcessName, size_t processNameSize)
std::set< long > pids_list
std::set< std::wstring > names_list