From c181d3ba281c00d2279538f67dd86229a0a3ae11 Mon Sep 17 00:00:00 2001 From: Kevin O'Reilly Date: Thu, 17 Apr 2025 10:42:59 +0100 Subject: [PATCH] Replace internal CreateThread calls with an internal implementation to avoid monitor detection by NtQueryInformationThread using ThreadQuerySetWin32StartAddress --- misc.c | 41 +++++++++++++++++++++++++++++++++++++++++ misc.h | 9 +++++++++ unhook.c | 17 ++++++----------- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/misc.c b/misc.c index df4d996..8606fb0 100644 --- a/misc.c +++ b/misc.c @@ -799,6 +799,47 @@ DWORD tid_from_thread_handle(HANDLE thread_handle) return (DWORD)(ULONG_PTR)cid.UniqueThread; } +VOID CALLBACK thread_callback(PVOID context_param, BOOLEAN timeout) +{ + THREAD_CONTEXT *context = (THREAD_CONTEXT*)context_param; + + if (context->thread_id) + *context->thread_id = GetCurrentThreadId(); + + context->start_routine(context->parameter); + + SetEvent(context->event); + CloseHandle(context->event); + free(context); +} + +HANDLE our_createthread(PTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD *lpThreadId) +{ + HANDLE timer = NULL; + + THREAD_CONTEXT *context = (THREAD_CONTEXT*)calloc(1, sizeof(THREAD_CONTEXT)); + if (!context) + return NULL; + + context->start_routine = lpStartAddress; + context->parameter = lpParameter; + context->thread_id = lpThreadId; + + context->event = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!context->event) { + free(context); + return NULL; + } + + if (!CreateTimerQueueTimer(&timer, NULL, thread_callback, context, 0, 0, WT_EXECUTEDEFAULT)) { + CloseHandle(context->event); + free(context); + return NULL; + } + + return context->event; +} + DWORD our_getprocessid(HANDLE Process) { DWORD ret; diff --git a/misc.h b/misc.h index c8c3c31..bbedffa 100644 --- a/misc.h +++ b/misc.h @@ -126,6 +126,14 @@ typedef SIZE_T (WINAPI *_RtlCompareMemory)( _In_ SIZE_T Length ); +typedef struct _THREAD_CONTEXT +{ + PTHREAD_START_ROUTINE start_routine; + LPVOID parameter; + HANDLE event; + LPDWORD thread_id; +} THREAD_CONTEXT; + _NtSetInformationProcess pNtSetInformationProcess; _NtMapViewOfSection pNtMapViewOfSection; _NtUnmapViewOfSection pNtUnmapViewOfSection; @@ -195,6 +203,7 @@ struct dll_range { DWORD get_pid_by_tid(DWORD tid); DWORD our_getprocessid(HANDLE Process); +HANDLE our_createthread(PTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD *lpThreadId); BOOL is_in_dll_range(ULONG_PTR addr); void add_all_dlls_to_dll_ranges(void); void add_dll_range(ULONG_PTR start, ULONG_PTR end); diff --git a/unhook.c b/unhook.c index dc53fbe..c5cbeb0 100644 --- a/unhook.c +++ b/unhook.c @@ -254,15 +254,12 @@ DWORD g_unhook_watcher_thread_id; int unhook_init_detection() { - g_unhook_thread_handle = - CreateThread(NULL, 0, &_unhook_detect_thread, NULL, 0, &g_unhook_detect_thread_id); + g_unhook_thread_handle = our_createthread(&_unhook_detect_thread, NULL, &g_unhook_detect_thread_id); - g_watcher_thread_handle = - CreateThread(NULL, 0, &_unhook_watch_thread, NULL, 0, &g_unhook_watcher_thread_id); + g_watcher_thread_handle = our_createthread(&_unhook_watch_thread, NULL, &g_unhook_watcher_thread_id); - if(g_unhook_thread_handle != NULL && g_watcher_thread_handle != NULL) { + if (g_unhook_thread_handle != NULL && g_watcher_thread_handle != NULL) return 0; - } pipe("CRITICAL:Error initializing unhook detection threads!"); return -1; @@ -338,8 +335,7 @@ int terminate_event_init() sa.lpSecurityDescriptor = &sd; g_terminate_event_handle = CreateEventA(&sa, FALSE, FALSE, g_config.terminate_event_name); - g_terminate_event_thread_handle = - CreateThread(NULL, 0, &_terminate_event_thread, NULL, 0, &g_terminate_event_thread_id); + g_terminate_event_thread_handle = our_createthread(&_terminate_event_thread, NULL, &g_terminate_event_thread_id); if (g_terminate_event_handle != NULL && g_terminate_event_thread_handle != NULL) return 0; @@ -397,8 +393,7 @@ int procname_watch_init() InitialProcessPath.Buffer = (PWSTR)calloc(mod->FullDllName.MaximumLength, 1); memcpy(InitialProcessPath.Buffer, mod->FullDllName.Buffer, InitialProcessPath.Length); - g_procname_watch_thread_handle = - CreateThread(NULL, 0, &_procname_watch_thread, NULL, 0, &g_procname_watcher_thread_id); + g_procname_watch_thread_handle = our_createthread(&_procname_watch_thread, NULL, &g_procname_watcher_thread_id); if (g_procname_watch_thread_handle != NULL) return 0; @@ -482,7 +477,7 @@ int init_watchdog() DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainthreadhandle, THREAD_ALL_ACCESS, FALSE, 0); - CreateThread(NULL, 0, &_watchdog_thread, mainthreadhandle, 0, &g_watchdog_thread_id); + our_createthread(&_watchdog_thread, mainthreadhandle, &g_watchdog_thread_id); return 0; }