finished implementing crash detection
This commit is contained in:
@@ -360,10 +360,18 @@ leave:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *))
|
void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *))
|
||||||
{
|
{
|
||||||
ptrlist_lock(list);
|
ptrlist_lock(list);
|
||||||
ptrlist_for_stdcall(list, 0, list->count, f);
|
for ( size_t i = index; i < count; i++ )
|
||||||
|
f(list->values[i]);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *))
|
||||||
|
{
|
||||||
|
ptrlist_lock(list);
|
||||||
|
ptrlist_for(list, 0, list->count, f);
|
||||||
ptrlist_unlock(list);
|
ptrlist_unlock(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,17 +383,9 @@ void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__std
|
|||||||
ptrlist_unlock(list);
|
ptrlist_unlock(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ptrlist_for_each_cdecl(ptrlist_t *list, void(__cdecl *f)(void *))
|
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *))
|
||||||
{
|
{
|
||||||
ptrlist_lock(list);
|
ptrlist_lock(list);
|
||||||
ptrlist_for_cdecl(list, 0, list->count, f);
|
ptrlist_for_stdcall(list, 0, list->count, f);
|
||||||
ptrlist_unlock(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ptrlist_for_cdecl(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *))
|
|
||||||
{
|
|
||||||
ptrlist_lock(list);
|
|
||||||
for ( size_t i = index; i < count; i++ )
|
|
||||||
f(list->values[i]);
|
|
||||||
ptrlist_unlock(list);
|
ptrlist_unlock(list);
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct ptrlist_t_ {
|
typedef struct ptrlist_t_
|
||||||
|
{
|
||||||
void **values;
|
void **values;
|
||||||
uint32_t *tags;
|
uint32_t *tags;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
@@ -13,10 +14,6 @@ typedef struct ptrlist_t_ {
|
|||||||
|
|
||||||
void ptrlist_lock(ptrlist_t *list);
|
void ptrlist_lock(ptrlist_t *list);
|
||||||
void ptrlist_unlock(ptrlist_t *list);
|
void ptrlist_unlock(ptrlist_t *list);
|
||||||
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *));
|
|
||||||
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *));
|
|
||||||
void ptrlist_for_each_cdecl(ptrlist_t *list, void(__cdecl *f)(void *));
|
|
||||||
void ptrlist_for_cdecl(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *));
|
|
||||||
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag);
|
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag);
|
||||||
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity);
|
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity);
|
||||||
void ptrlist_destroy(ptrlist_t *list);
|
void ptrlist_destroy(ptrlist_t *list);
|
||||||
@@ -34,3 +31,7 @@ bool ptrlist_contains(ptrlist_t *list, void *value);
|
|||||||
void **ptrlist_copy_values(ptrlist_t *list, size_t *count);
|
void **ptrlist_copy_values(ptrlist_t *list, size_t *count);
|
||||||
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count);
|
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count);
|
||||||
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count);
|
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count);
|
||||||
|
void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *));
|
||||||
|
void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *));
|
||||||
|
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *));
|
||||||
|
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *));
|
||||||
|
@@ -28,7 +28,8 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
|
|||||||
void **values;
|
void **values;
|
||||||
uint32_t *tags;
|
uint32_t *tags;
|
||||||
size_t count;
|
size_t count;
|
||||||
DWORD ret;
|
DWORD e;
|
||||||
|
DWORD r;
|
||||||
size_t index;
|
size_t index;
|
||||||
size_t crashes = 0;
|
size_t crashes = 0;
|
||||||
|
|
||||||
@@ -64,58 +65,62 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
|
|||||||
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)cb_service_notify;
|
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)cb_service_notify;
|
||||||
NotifyBuffer.pContext = (PVOID)&list;
|
NotifyBuffer.pContext = (PVOID)&list;
|
||||||
while ( !Unloading && !Lagging ) {
|
while ( !Unloading && !Lagging ) {
|
||||||
switch ( NotifyServiceStatusChangeW(hService,
|
e = NotifyServiceStatusChangeW(hService,
|
||||||
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
|
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
|
||||||
&NotifyBuffer) ) {
|
&NotifyBuffer);
|
||||||
|
switch ( e ) {
|
||||||
case ERROR_SUCCESS:
|
case ERROR_SUCCESS:
|
||||||
if ( !ptrlist_copy(&list, &values, &tags, &count) ) {
|
do {
|
||||||
Unloading = true;
|
if ( !ptrlist_copy(&list, &values, &tags, &count) ) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = WaitForMultipleObjectsEx((DWORD)count,
|
|
||||||
values, FALSE, INFINITE, TRUE);
|
|
||||||
|
|
||||||
if ( ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + count ) {
|
|
||||||
// object signaled
|
|
||||||
index = ret - WAIT_OBJECT_0;
|
|
||||||
|
|
||||||
if ( index == 0 ) { // Unload event
|
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
break;
|
break;
|
||||||
} else { // crash mutex was closed but the process didn't crash
|
}
|
||||||
|
r = WaitForMultipleObjectsEx((DWORD)count,
|
||||||
|
values, FALSE, INFINITE, TRUE);
|
||||||
|
|
||||||
|
if ( r >= WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + count ) {
|
||||||
|
// object signaled
|
||||||
|
index = r - WAIT_OBJECT_0;
|
||||||
|
if ( !index ) {
|
||||||
|
// Unload event
|
||||||
|
Unloading = true;
|
||||||
|
} else {
|
||||||
|
// crash mutex was released cleanly
|
||||||
|
ptrlist_remove(&list, values[index]);
|
||||||
|
ReleaseMutex(values[index]);
|
||||||
|
CloseHandle(values[index]);
|
||||||
|
}
|
||||||
|
} else if ( r >= WAIT_ABANDONED_0 && r < WAIT_ABANDONED_0 + count ) {
|
||||||
|
// object abandoned
|
||||||
|
// crash mutex was abandoned, process has most likely crashed.
|
||||||
|
index = r - WAIT_ABANDONED_0;
|
||||||
|
|
||||||
ptrlist_remove(&list, values[index]);
|
ptrlist_remove(&list, values[index]);
|
||||||
ReleaseMutex(values[index]);
|
ReleaseMutex(values[index]);
|
||||||
CloseHandle(values[index]);
|
CloseHandle(values[index]);
|
||||||
}
|
|
||||||
} else if ( ret >= WAIT_ABANDONED_0 && ret < WAIT_ABANDONED_0 + count ) {
|
|
||||||
// object abandoned
|
|
||||||
// crash mutex was abandoned, process has most likely crashed.
|
|
||||||
index = ret - WAIT_ABANDONED_0;
|
|
||||||
|
|
||||||
ptrlist_remove(&list, values[index]);
|
crashes++;
|
||||||
ReleaseMutex(values[index]);
|
trace(L"A process that wufuc injected into has crashed %Iu time%ls!!! (PID=%lu)",
|
||||||
CloseHandle(values[index]);
|
crashes, crashes != 1 ? L"s" : L"", tags[index]);
|
||||||
|
|
||||||
crashes++;
|
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
|
||||||
trace(L"A process that wufuc injected into has crashed %Iu time%ls!!! (PID=%lu)",
|
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
|
||||||
crashes, crashes != 1 ? L"s" : L"", tags[index]);
|
Unloading = true;
|
||||||
|
}
|
||||||
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
|
} else if ( r == WAIT_FAILED ) {
|
||||||
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
|
trace(L"WTF - Unexpected result from wait function!!!");
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
}
|
}
|
||||||
} else if ( ret == WAIT_FAILED ) {
|
free(values);
|
||||||
trace(L"WTF - Unexpected result from wait function!!!");
|
free(tags);
|
||||||
Unloading = true;
|
} while ( r != WAIT_IO_COMPLETION && !Unloading );
|
||||||
}
|
|
||||||
free(values);
|
|
||||||
free(tags);
|
|
||||||
break;
|
break;
|
||||||
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
|
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
|
||||||
trace(L"Client lagging!");
|
trace(L"Client lagging!");
|
||||||
Lagging = true;
|
Lagging = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
trace(L"NotifyServiceStatusChange failed, return value: %lu (%08X)", e);
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user