changed context member types, add crash detection (untested!)
This commit is contained in:
@@ -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,10 +103,10 @@ 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;
|
||||||
|
|
||||||
@@ -146,9 +146,9 @@ 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;
|
||||||
@@ -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 )
|
||||||
|
return false;
|
||||||
|
|
||||||
*pResult = WaitForMultipleObjectsEx(count,
|
*pResult = WaitForMultipleObjectsEx(count,
|
||||||
handles,
|
handles,
|
||||||
WaitAll,
|
TRUE,
|
||||||
INFINITE,
|
INFINITE,
|
||||||
Alertable);
|
Alertable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
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,
|
bool ctx_close_and_remove_handle(context *ctx, HANDLE Handle)
|
||||||
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();
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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!");
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user