From 2db985a55b47da9b0f1eb25e3dcaa53475450ae4 Mon Sep 17 00:00:00 2001 From: zeffy Date: Fri, 2 Mar 2018 19:06:42 -0800 Subject: [PATCH] changed context member types, add crash detection (untested!) --- src/wufuc/context.c | 121 +++++++++++++++++++++++++++++-------------- src/wufuc/context.h | 51 +++++++++--------- src/wufuc/rundll32.c | 31 ++++++++++- src/wufuc/wufuc.c | 2 + src/wufuc/wufuc.h | 4 ++ 5 files changed, 141 insertions(+), 68 deletions(-) diff --git a/src/wufuc/context.c b/src/wufuc/context.c index 871b33c..69910d0 100644 --- a/src/wufuc/context.c +++ b/src/wufuc/context.c @@ -3,13 +3,13 @@ #include -static bool ctxp_remove_handle(context *ctx, unsigned Index) +static bool ctxp_remove_handle(context *ctx, DWORD Index) { if ( !ctx || Index > _countof(ctx->handles) || Index > ctx->count ) return false; EnterCriticalSection(&ctx->cs); - for ( unsigned i = Index; i < ctx->count - 1; i++ ) { + for ( DWORD i = Index; i < ctx->count - 1; i++ ) { ctx->handles[i] = ctx->handles[i + 1]; ctx->tags[i] = ctx->tags[i + 1]; } @@ -83,15 +83,15 @@ static bool ctxp_create_event_with_string_security_descriptor( return false; } -static unsigned ctxp_find_handle_index(context *ctx, HANDLE Handle) +static DWORD ctxp_find_handle_index(context *ctx, HANDLE Handle) { - unsigned result = -1; + DWORD result = -1; if ( !ctx || !Handle || Handle == INVALID_HANDLE_VALUE ) return -1; EnterCriticalSection(&ctx->cs); - for ( unsigned i = 0; i < ctx->count; i++ ) { + for ( DWORD i = 0; i < ctx->count; i++ ) { if ( ctx->handles[i] == Handle ) { result = i; break; @@ -103,15 +103,15 @@ static unsigned ctxp_find_handle_index(context *ctx, HANDLE Handle) bool ctx_create(context *ctx, const wchar_t *MutexName, - unsigned MutexTag, + DWORD MutexTag, const wchar_t *EventName, const wchar_t *EventStringSecurityDescriptor, - unsigned EventTag) + DWORD EventTag) { bool result = false; - + if ( !ctx ) return false; - + ZeroMemory(ctx, sizeof *ctx); InitializeCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs); @@ -146,16 +146,16 @@ bool ctx_delete(context *ctx) return true; } -unsigned ctx_add_handle(context *ctx, HANDLE Handle, unsigned Tag) +DWORD ctx_add_handle(context *ctx, HANDLE Handle, DWORD Tag) { - unsigned result = -1; + DWORD result = -1; if ( !ctx || !Handle ) return -1; EnterCriticalSection(&ctx->cs); result = ctxp_find_handle_index(ctx, Handle); - if ( result != -1) { + if ( result != -1 ) { ctx->tags[result] = Tag; } else if ( ctx->count < _countof(ctx->handles) ) { ctx->handles[ctx->count] = Handle; @@ -167,10 +167,10 @@ unsigned ctx_add_handle(context *ctx, HANDLE Handle, unsigned Tag) return result; } -bool ctx_get_tag(context *ctx, HANDLE Handle, unsigned *pTag) +bool ctx_get_tag(context *ctx, HANDLE Handle, DWORD *pTag) { bool result = false; - unsigned index; + DWORD index; if ( !ctx || !Handle || !pTag ) return false; @@ -187,14 +187,14 @@ bool ctx_get_tag(context *ctx, HANDLE Handle, unsigned *pTag) return result; } -unsigned ctx_add_new_mutex(context *ctx, +DWORD ctx_add_new_mutex(context *ctx, bool InitialOwner, const wchar_t *Name, - unsigned Tag, + DWORD Tag, HANDLE *pMutexHandle) { HANDLE hMutex; - unsigned result = -1; + DWORD result = -1; EnterCriticalSection(&ctx->cs); if ( ctxp_create_new_mutex(InitialOwner, Name, &hMutex) ) { @@ -210,15 +210,15 @@ unsigned ctx_add_new_mutex(context *ctx, return result; } -unsigned ctx_add_new_mutex_fmt(context *ctx, +DWORD ctx_add_new_mutex_fmt(context *ctx, bool InitialOwner, - unsigned Tag, + DWORD Tag, HANDLE *pMutexHandle, const wchar_t *const NameFormat, ...) { HANDLE hMutex; - unsigned result = -1; + DWORD result = -1; va_list arglist; EnterCriticalSection(&ctx->cs); @@ -237,13 +237,13 @@ unsigned ctx_add_new_mutex_fmt(context *ctx, return result; } -unsigned ctx_add_event(context *ctx, +DWORD ctx_add_event(context *ctx, const wchar_t *Name, const wchar_t *StringSecurityDescriptor, - unsigned Tag, + DWORD Tag, HANDLE *pEventHandle) { - unsigned result = -1; + DWORD result = -1; HANDLE hEvent; EnterCriticalSection(&ctx->cs); @@ -265,10 +265,12 @@ unsigned ctx_add_event(context *ctx, return result; } -bool ctx_wait(context *ctx, bool WaitAll, bool Alertable, DWORD *pResult) +bool ctx_wait_all(context *ctx, + bool Alertable, + DWORD *pResult) { int ret; - unsigned count; + DWORD count; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; EnterCriticalSection(&ctx->cs); @@ -276,22 +278,63 @@ bool ctx_wait(context *ctx, bool WaitAll, bool Alertable, DWORD *pResult) ret = memcpy_s(handles, sizeof(handles), ctx->handles, count * (sizeof *handles)); LeaveCriticalSection(&ctx->cs); - if ( !ret ) { - *pResult = WaitForMultipleObjectsEx(count, - handles, - WaitAll, - INFINITE, - Alertable); - return true; - } - return false; + if ( ret ) + return false; + + *pResult = WaitForMultipleObjectsEx(count, + handles, + TRUE, + INFINITE, + Alertable); + return true; } -bool ctx_close_and_remove_handle(context *ctx, - HANDLE Handle) +DWORD ctx_wait_any(context *ctx, + bool Alertable, + DWORD *pResult, + HANDLE *pHandle, + DWORD *pTag) +{ + DWORD count; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + DWORD tags[MAXIMUM_WAIT_OBJECTS]; + int ret; + DWORD result; + DWORD index; + + EnterCriticalSection(&ctx->cs); + // make copies of the struct members on the stack before waiting, because + // WaitForMultipleObjects(Ex) doesn't like it when you modify the contents of + // the array it is waiting on. + count = ctx->count; + ret = memcpy_s(handles, sizeof(handles), ctx->handles, count * (sizeof *handles)); + if ( !ret ) + ret = memcpy_s(tags, sizeof(tags), ctx->tags, count * (sizeof *tags)); + LeaveCriticalSection(&ctx->cs); + + if ( ret ) + return -1; + + result = WaitForMultipleObjectsEx(count, handles, FALSE, INFINITE, Alertable); + + if ( result >= WAIT_OBJECT_0 || result < WAIT_OBJECT_0 + count ) + index = result - WAIT_OBJECT_0; + else if ( result >= WAIT_ABANDONED_0 || result < WAIT_ABANDONED_0 + count ) + index = result - WAIT_ABANDONED_0; + + if ( pHandle ) + *pHandle = handles[index]; + if ( pTag ) + *pTag = tags[index]; + + *pResult = result; + return count; +} + +bool ctx_close_and_remove_handle(context *ctx, HANDLE Handle) { bool result = false; - unsigned index; + DWORD index; EnterCriticalSection(&ctx->cs); index = ctxp_find_handle_index(ctx, Handle); @@ -307,12 +350,12 @@ bool ctx_duplicate_context(const context *pSrc, context *pDst, HANDLE Handle, DWORD DesiredAccess, - unsigned Tag) + DWORD Tag) { bool result = false; HANDLE hSrcProcess; HANDLE hTarget; - size_t index; + DWORD index; hSrcProcess = GetCurrentProcess(); diff --git a/src/wufuc/context.h b/src/wufuc/context.h index 0de5d10..6bbdb5e 100644 --- a/src/wufuc/context.h +++ b/src/wufuc/context.h @@ -4,7 +4,7 @@ typedef struct { CRITICAL_SECTION cs; - unsigned count; + DWORD count; union { struct @@ -18,54 +18,51 @@ typedef struct { struct { - unsigned mutex_tag; - unsigned uevent_tag; + DWORD mutex_tag; + DWORD uevent_tag; }; - unsigned tags[MAXIMUM_WAIT_OBJECTS]; + DWORD tags[MAXIMUM_WAIT_OBJECTS]; }; } context; #pragma pack(pop) bool ctx_create(context *ctx, const wchar_t *MutexName, - unsigned MutexTag, + DWORD MutexTag, const wchar_t *EventName, const wchar_t *EventStringSecurityDescriptor, - unsigned EventTag); - + DWORD EventTag); bool ctx_delete(context *ctx); - -unsigned ctx_add_handle(context *ctx, HANDLE Handle, unsigned Tag); - -bool ctx_get_tag(context *ctx, HANDLE Handle, unsigned *pTag); - -unsigned ctx_add_new_mutex(context *ctx, +DWORD ctx_add_handle(context *ctx, HANDLE Handle, DWORD Tag); +bool ctx_get_tag(context *ctx, HANDLE Handle, DWORD *pTag); +DWORD ctx_add_new_mutex(context *ctx, bool InitialOwner, const wchar_t *Name, - unsigned Tag, + DWORD Tag, HANDLE *pMutexHandle); - -unsigned ctx_add_new_mutex_fmt(context *ctx, +DWORD ctx_add_new_mutex_fmt(context *ctx, bool InitialOwner, - unsigned Tag, + DWORD Tag, HANDLE *pMutexHandle, const wchar_t *const NameFormat, ...); - -unsigned ctx_add_event(context *ctx, +DWORD ctx_add_event(context *ctx, const wchar_t *Name, const wchar_t *StringSecurityDescriptor, - unsigned Tag, + DWORD Tag, HANDLE *pEventHandle); - -bool ctx_wait(context *ctx, bool WaitAll, bool Alertable, DWORD *pResult); - -bool ctx_close_and_remove_handle(context *ctx, - HANDLE Handle); - +bool ctx_wait_all(context *ctx, + bool Alertable, + DWORD *pResult); +DWORD ctx_wait_any(context *ctx, + bool Alertable, + DWORD *pResult, + HANDLE *pHandle, + DWORD *pTag); +bool ctx_close_and_remove_handle(context *ctx, HANDLE Handle); bool ctx_duplicate_context(const context *pSrc, HANDLE hProcess, context *pDst, HANDLE Handle, DWORD DesiredAccess, - unsigned Tag); + DWORD Tag); diff --git a/src/wufuc/rundll32.c b/src/wufuc/rundll32.c index f180bf8..722c789 100644 --- a/src/wufuc/rundll32.c +++ b/src/wufuc/rundll32.c @@ -17,6 +17,10 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in SC_HANDLE hSCM; SC_HANDLE hService; SERVICE_NOTIFYW NotifyBuffer; + DWORD count; + DWORD ret; + HANDLE handle; + DWORD tag; if ( !ctx_create(&ctx, L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645", 0, @@ -48,7 +52,30 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING, &NotifyBuffer) ) { case ERROR_SUCCESS: - Unloading = WaitForSingleObjectEx(ctx.uevent, INFINITE, TRUE) == WAIT_OBJECT_0; + count = ctx_wait_any(&ctx, true, &ret, &handle, &tag); + if ( count == -1 ) { + // Wait function failed while making static copy of handles/tags, wtf! + Unloading = true; + break; + } else if ( ret == WAIT_OBJECT_0 + 1 ) { + trace(L"Unload event was set!"); + Unloading = true; + break; + } else if ( (ret >= ERROR_ABANDONED_WAIT_0 || ret < WAIT_ABANDONED_0 + count) ) { + g_ServiceHostCrashCount++; + trace(L"A process that wufuc injected into has crashed %Iu times!!! PID=%lu ", + g_ServiceHostCrashCount, tag); + + if ( g_ServiceHostCrashCount >= WUFUC_CRASH_THRESHOLD ) { + trace(L"Crash threshold has been reached, disabling wufuc until next reboot!"); + Unloading = true; + } + + Unloading = true; + } else if ( ret == WAIT_FAILED ) { + trace(L"Wait failed! GLE=%lu", GetLastError()); + Unloading = true; + } break; case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: trace(L"Client lagging!"); @@ -60,7 +87,7 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in } } CloseServiceHandle(hService); -close_scm: +close_scm: CloseServiceHandle(hSCM); } while ( Lagging ); delete_ctx: diff --git a/src/wufuc/wufuc.c b/src/wufuc/wufuc.c index d720085..3f0f952 100644 --- a/src/wufuc/wufuc.c +++ b/src/wufuc/wufuc.c @@ -9,6 +9,8 @@ #include +size_t g_ServiceHostCrashCount; + bool wufuc_inject(DWORD dwProcessId, LPTHREAD_START_ROUTINE pfnStart, context *pContext) diff --git a/src/wufuc/wufuc.h b/src/wufuc/wufuc.h index d78a396..88cd5f6 100644 --- a/src/wufuc/wufuc.h +++ b/src/wufuc/wufuc.h @@ -6,6 +6,10 @@ typedef struct WORD wCodePage; } LANGANDCODEPAGE, *PLANGANDCODEPAGE; +#define WUFUC_CRASH_THRESHOLD 3 + +extern size_t g_ServiceHostCrashCount; + bool wufuc_inject(DWORD dwProcessId, LPTHREAD_START_ROUTINE pfnStart, context *pContext);