changed context member types, add crash detection (untested!)

This commit is contained in:
zeffy
2018-03-02 19:06:42 -08:00
parent 24c6029bdd
commit 2db985a55b
5 changed files with 141 additions and 68 deletions

View File

@@ -3,13 +3,13 @@
#include <sddl.h> #include <sddl.h>
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 ) if ( !ctx || Index > _countof(ctx->handles) || Index > ctx->count )
return false; return false;
EnterCriticalSection(&ctx->cs); 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->handles[i] = ctx->handles[i + 1];
ctx->tags[i] = ctx->tags[i + 1]; ctx->tags[i] = ctx->tags[i + 1];
} }
@@ -83,15 +83,15 @@ static bool ctxp_create_event_with_string_security_descriptor(
return false; 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 ) if ( !ctx || !Handle || Handle == INVALID_HANDLE_VALUE )
return -1; return -1;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
for ( unsigned i = 0; i < ctx->count; i++ ) { for ( DWORD i = 0; i < ctx->count; i++ ) {
if ( ctx->handles[i] == Handle ) { if ( ctx->handles[i] == Handle ) {
result = i; result = i;
break; break;
@@ -103,15 +103,15 @@ static unsigned ctxp_find_handle_index(context *ctx, HANDLE Handle)
bool ctx_create(context *ctx, bool ctx_create(context *ctx,
const wchar_t *MutexName, const wchar_t *MutexName,
unsigned MutexTag, DWORD MutexTag,
const wchar_t *EventName, const wchar_t *EventName,
const wchar_t *EventStringSecurityDescriptor, const wchar_t *EventStringSecurityDescriptor,
unsigned EventTag) DWORD EventTag)
{ {
bool result = false; bool result = false;
if ( !ctx ) return false; if ( !ctx ) return false;
ZeroMemory(ctx, sizeof *ctx); ZeroMemory(ctx, sizeof *ctx);
InitializeCriticalSection(&ctx->cs); InitializeCriticalSection(&ctx->cs);
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
@@ -146,16 +146,16 @@ bool ctx_delete(context *ctx)
return true; 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 ) if ( !ctx || !Handle )
return -1; return -1;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
result = ctxp_find_handle_index(ctx, Handle); result = ctxp_find_handle_index(ctx, Handle);
if ( result != -1) { if ( result != -1 ) {
ctx->tags[result] = Tag; ctx->tags[result] = Tag;
} else if ( ctx->count < _countof(ctx->handles) ) { } else if ( ctx->count < _countof(ctx->handles) ) {
ctx->handles[ctx->count] = Handle; ctx->handles[ctx->count] = Handle;
@@ -167,10 +167,10 @@ unsigned ctx_add_handle(context *ctx, HANDLE Handle, unsigned Tag)
return result; 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; bool result = false;
unsigned index; DWORD index;
if ( !ctx || !Handle || !pTag ) if ( !ctx || !Handle || !pTag )
return false; return false;
@@ -187,14 +187,14 @@ bool ctx_get_tag(context *ctx, HANDLE Handle, unsigned *pTag)
return result; return result;
} }
unsigned ctx_add_new_mutex(context *ctx, DWORD ctx_add_new_mutex(context *ctx,
bool InitialOwner, bool InitialOwner,
const wchar_t *Name, const wchar_t *Name,
unsigned Tag, DWORD Tag,
HANDLE *pMutexHandle) HANDLE *pMutexHandle)
{ {
HANDLE hMutex; HANDLE hMutex;
unsigned result = -1; DWORD result = -1;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
if ( ctxp_create_new_mutex(InitialOwner, Name, &hMutex) ) { if ( ctxp_create_new_mutex(InitialOwner, Name, &hMutex) ) {
@@ -210,15 +210,15 @@ unsigned ctx_add_new_mutex(context *ctx,
return result; return result;
} }
unsigned ctx_add_new_mutex_fmt(context *ctx, DWORD ctx_add_new_mutex_fmt(context *ctx,
bool InitialOwner, bool InitialOwner,
unsigned Tag, DWORD Tag,
HANDLE *pMutexHandle, HANDLE *pMutexHandle,
const wchar_t *const NameFormat, const wchar_t *const NameFormat,
...) ...)
{ {
HANDLE hMutex; HANDLE hMutex;
unsigned result = -1; DWORD result = -1;
va_list arglist; va_list arglist;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
@@ -237,13 +237,13 @@ unsigned ctx_add_new_mutex_fmt(context *ctx,
return result; return result;
} }
unsigned ctx_add_event(context *ctx, DWORD ctx_add_event(context *ctx,
const wchar_t *Name, const wchar_t *Name,
const wchar_t *StringSecurityDescriptor, const wchar_t *StringSecurityDescriptor,
unsigned Tag, DWORD Tag,
HANDLE *pEventHandle) HANDLE *pEventHandle)
{ {
unsigned result = -1; DWORD result = -1;
HANDLE hEvent; HANDLE hEvent;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
@@ -265,10 +265,12 @@ unsigned ctx_add_event(context *ctx,
return result; 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; int ret;
unsigned count; DWORD count;
HANDLE handles[MAXIMUM_WAIT_OBJECTS]; HANDLE handles[MAXIMUM_WAIT_OBJECTS];
EnterCriticalSection(&ctx->cs); 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)); ret = memcpy_s(handles, sizeof(handles), ctx->handles, count * (sizeof *handles));
LeaveCriticalSection(&ctx->cs); LeaveCriticalSection(&ctx->cs);
if ( !ret ) { if ( ret )
*pResult = WaitForMultipleObjectsEx(count, return false;
handles,
WaitAll, *pResult = WaitForMultipleObjectsEx(count,
INFINITE, handles,
Alertable); TRUE,
return true; INFINITE,
} Alertable);
return false; return true;
} }
bool ctx_close_and_remove_handle(context *ctx, DWORD ctx_wait_any(context *ctx,
HANDLE Handle) 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; bool result = false;
unsigned index; DWORD index;
EnterCriticalSection(&ctx->cs); EnterCriticalSection(&ctx->cs);
index = ctxp_find_handle_index(ctx, Handle); index = ctxp_find_handle_index(ctx, Handle);
@@ -307,12 +350,12 @@ bool ctx_duplicate_context(const context *pSrc,
context *pDst, context *pDst,
HANDLE Handle, HANDLE Handle,
DWORD DesiredAccess, DWORD DesiredAccess,
unsigned Tag) DWORD Tag)
{ {
bool result = false; bool result = false;
HANDLE hSrcProcess; HANDLE hSrcProcess;
HANDLE hTarget; HANDLE hTarget;
size_t index; DWORD index;
hSrcProcess = GetCurrentProcess(); hSrcProcess = GetCurrentProcess();

View File

@@ -4,7 +4,7 @@
typedef struct typedef struct
{ {
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
unsigned count; DWORD count;
union union
{ {
struct struct
@@ -18,54 +18,51 @@ typedef struct
{ {
struct struct
{ {
unsigned mutex_tag; DWORD mutex_tag;
unsigned uevent_tag; DWORD uevent_tag;
}; };
unsigned tags[MAXIMUM_WAIT_OBJECTS]; DWORD tags[MAXIMUM_WAIT_OBJECTS];
}; };
} context; } context;
#pragma pack(pop) #pragma pack(pop)
bool ctx_create(context *ctx, bool ctx_create(context *ctx,
const wchar_t *MutexName, const wchar_t *MutexName,
unsigned MutexTag, DWORD MutexTag,
const wchar_t *EventName, const wchar_t *EventName,
const wchar_t *EventStringSecurityDescriptor, const wchar_t *EventStringSecurityDescriptor,
unsigned EventTag); DWORD EventTag);
bool ctx_delete(context *ctx); bool ctx_delete(context *ctx);
DWORD ctx_add_handle(context *ctx, HANDLE Handle, DWORD Tag);
unsigned ctx_add_handle(context *ctx, HANDLE Handle, unsigned Tag); bool ctx_get_tag(context *ctx, HANDLE Handle, DWORD *pTag);
DWORD ctx_add_new_mutex(context *ctx,
bool ctx_get_tag(context *ctx, HANDLE Handle, unsigned *pTag);
unsigned ctx_add_new_mutex(context *ctx,
bool InitialOwner, bool InitialOwner,
const wchar_t *Name, const wchar_t *Name,
unsigned Tag, DWORD Tag,
HANDLE *pMutexHandle); HANDLE *pMutexHandle);
DWORD ctx_add_new_mutex_fmt(context *ctx,
unsigned ctx_add_new_mutex_fmt(context *ctx,
bool InitialOwner, bool InitialOwner,
unsigned Tag, DWORD Tag,
HANDLE *pMutexHandle, HANDLE *pMutexHandle,
const wchar_t *const NameFormat, const wchar_t *const NameFormat,
...); ...);
DWORD ctx_add_event(context *ctx,
unsigned ctx_add_event(context *ctx,
const wchar_t *Name, const wchar_t *Name,
const wchar_t *StringSecurityDescriptor, const wchar_t *StringSecurityDescriptor,
unsigned Tag, DWORD Tag,
HANDLE *pEventHandle); HANDLE *pEventHandle);
bool ctx_wait_all(context *ctx,
bool ctx_wait(context *ctx, bool WaitAll, bool Alertable, DWORD *pResult); bool Alertable,
DWORD *pResult);
bool ctx_close_and_remove_handle(context *ctx, DWORD ctx_wait_any(context *ctx,
HANDLE Handle); 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, bool ctx_duplicate_context(const context *pSrc,
HANDLE hProcess, HANDLE hProcess,
context *pDst, context *pDst,
HANDLE Handle, HANDLE Handle,
DWORD DesiredAccess, DWORD DesiredAccess,
unsigned Tag); DWORD Tag);

View File

@@ -17,6 +17,10 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
SC_HANDLE hSCM; SC_HANDLE hSCM;
SC_HANDLE hService; SC_HANDLE hService;
SERVICE_NOTIFYW NotifyBuffer; SERVICE_NOTIFYW NotifyBuffer;
DWORD count;
DWORD ret;
HANDLE handle;
DWORD tag;
if ( !ctx_create(&ctx, if ( !ctx_create(&ctx,
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645", 0, 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, SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
&NotifyBuffer) ) { &NotifyBuffer) ) {
case ERROR_SUCCESS: 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; break;
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
trace(L"Client lagging!"); trace(L"Client lagging!");
@@ -60,7 +87,7 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
} }
} }
CloseServiceHandle(hService); CloseServiceHandle(hService);
close_scm: close_scm:
CloseServiceHandle(hSCM); CloseServiceHandle(hSCM);
} while ( Lagging ); } while ( Lagging );
delete_ctx: delete_ctx:

View File

@@ -9,6 +9,8 @@
#include <minhook.h> #include <minhook.h>
size_t g_ServiceHostCrashCount;
bool wufuc_inject(DWORD dwProcessId, bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pfnStart, LPTHREAD_START_ROUTINE pfnStart,
context *pContext) context *pContext)

View File

@@ -6,6 +6,10 @@ typedef struct
WORD wCodePage; WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE; } LANGANDCODEPAGE, *PLANGANDCODEPAGE;
#define WUFUC_CRASH_THRESHOLD 3
extern size_t g_ServiceHostCrashCount;
bool wufuc_inject(DWORD dwProcessId, bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pfnStart, LPTHREAD_START_ROUTINE pfnStart,
context *pContext); context *pContext);