suspend (not exit) when crash count is exceeded

This commit is contained in:
zeffy
2018-03-08 20:02:02 -08:00
parent a6a79e03dc
commit 872a3418db
3 changed files with 45 additions and 32 deletions

View File

@@ -12,7 +12,6 @@
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer) VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
{ {
trace(L"enter");
switch ( pNotifyBuffer->dwNotificationStatus ) { switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS: case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId ) if ( pNotifyBuffer->ServiceStatus.dwProcessId )
@@ -22,7 +21,7 @@ VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
(ptrlist_t *)pNotifyBuffer->pContext); (ptrlist_t *)pNotifyBuffer->pContext);
break; break;
case ERROR_SERVICE_MARKED_FOR_DELETE: case ERROR_SERVICE_MARKED_FOR_DELETE:
SetEvent(ptrlist_at((ptrlist_t *)pNotifyBuffer->pContext, 1, NULL)); SetEvent(ptrlist_at((ptrlist_t *)pNotifyBuffer->pContext, 0, NULL));
break; break;
} }
if ( pNotifyBuffer->pszServiceNames ) if ( pNotifyBuffer->pszServiceNames )
@@ -39,6 +38,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
DWORD dwProcessId; DWORD dwProcessId;
LPQUERY_SERVICE_CONFIGW pServiceConfig; LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType; DWORD dwServiceType;
int tmp;
LPVOID pTarget = NULL; LPVOID pTarget = NULL;
wchar_t *str; wchar_t *str;
HMODULE hModule; HMODULE hModule;
@@ -72,11 +72,12 @@ DWORD WINAPI cb_start(HANDLE *pParam)
dwProcessId = svc_heuristic_process_id(hSCM, hService); dwProcessId = svc_heuristic_process_id(hSCM, hService);
pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL); pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
dwServiceType = pServiceConfig->dwServiceType; dwServiceType = pServiceConfig->dwServiceType;
tmp = _wcsicmp(pServiceConfig->lpBinaryPathName, GetCommandLineW());
free(pServiceConfig); free(pServiceConfig);
CloseServiceHandle(hService); CloseServiceHandle(hService);
CloseServiceHandle(hSCM); CloseServiceHandle(hSCM);
if ( dwProcessId != GetCurrentProcessId() ) { if ( !tmp || dwProcessId != GetCurrentProcessId() ) {
trace(L"Injected into wrong process!"); trace(L"Injected into wrong process!");
goto release; goto release;
} }
@@ -86,12 +87,12 @@ DWORD WINAPI cb_start(HANDLE *pParam)
// RegQueryValueExW hook to fix incompatibility with // RegQueryValueExW hook to fix incompatibility with
// UpdatePack7R2 and other patches that modify the // UpdatePack7R2 and other patches that modify the
// Windows Update ServiceDll path in the registry. // Windows Update ServiceDll path in the registry.
trace(L"MH_CreateHookApi RegQueryValueExW=%hs", MH_StatusToString(MH_CreateHookApiEx(L"kernel32.dll", MH_CreateHookApiEx(L"kernel32.dll",
"RegQueryValueExW", "RegQueryValueExW",
RegQueryValueExW_hook, RegQueryValueExW_hook,
&(PVOID)g_pfnRegQueryValueExW, &(PVOID)g_pfnRegQueryValueExW,
&pTarget))); &pTarget);
trace(L"MH_EnableHook RegQueryValueExW=%hs", MH_StatusToString(MH_EnableHook(pTarget))); MH_EnableHook(pTarget);
} }
// query the ServiceDll path after applying our compat hook so that it // query the ServiceDll path after applying our compat hook so that it
@@ -102,17 +103,17 @@ DWORD WINAPI cb_start(HANDLE *pParam)
if ( !str ) { if ( !str ) {
abort_hook: abort_hook:
if ( pTarget ) if ( pTarget )
trace(L"MH_RemoveHook RegQueryValueExW=%hs", MH_StatusToString(MH_RemoveHook(pTarget))); MH_RemoveHook(pTarget);
goto release; goto release;
} }
g_pszWUServiceDll = env_expand_strings_alloc(str, NULL); g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
free(str); free(str);
if ( !g_pszWUServiceDll ) goto abort_hook; if ( !g_pszWUServiceDll ) goto abort_hook;
trace(L"MH_CreateHookApi LoadLibraryExW=%hs", MH_StatusToString(MH_CreateHookApi(L"kernel32.dll", MH_CreateHookApi(L"kernel32.dll",
"LoadLibraryExW", "LoadLibraryExW",
LoadLibraryExW_hook, LoadLibraryExW_hook,
&(PVOID)g_pfnLoadLibraryExW))); &(PVOID)g_pfnLoadLibraryExW);
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule) if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) { || GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
@@ -122,14 +123,14 @@ abort_hook:
FreeLibrary(hModule); FreeLibrary(hModule);
} }
trace(L"MH_EnableHook=%hs", MH_StatusToString(MH_EnableHook(MH_ALL_HOOKS))); MH_EnableHook(MH_ALL_HOOKS);
// wait for unload event or the main mutex to be released or abandoned, // wait for unload event or the main mutex to be released or abandoned,
// for example if the user killed rundll32.exe with task manager. // for example if the user killed rundll32.exe with task manager.
WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE); WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
trace(L"Unload condition has been met."); trace(L"Unload condition has been met.");
trace(L"MH_DisableHook(MH_ALL_HOOKS) LoadLibraryExW=%hs", MH_StatusToString(MH_DisableHook(MH_ALL_HOOKS))); MH_DisableHook(MH_ALL_HOOKS);
free(g_pszWUServiceDll); free(g_pszWUServiceDll);
release: release:
ReleaseMutex(hCrashMutex); ReleaseMutex(hCrashMutex);

View File

@@ -19,29 +19,30 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
ptrlist_t list; ptrlist_t list;
HANDLE hEvent; HANDLE hEvent;
DWORD dwDesiredAccess; DWORD dwDesiredAccess;
DWORD dwProcessId;
bool Unloading = false;
bool Lagging; bool Lagging;
SC_HANDLE hSCM; SC_HANDLE hSCM;
SC_HANDLE hService; SC_HANDLE hService;
DWORD dwProcessId;
SERVICE_NOTIFYW NotifyBuffer; SERVICE_NOTIFYW NotifyBuffer;
bool Unloading = false;
DWORD e;
void **values; void **values;
uint32_t *tags; uint32_t *tags;
size_t count; size_t count;
DWORD e;
DWORD r; DWORD r;
size_t index; size_t index;
size_t crashes = 0; size_t crashes = 0;
bool Suspending = false;
if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) return;
g_hMainMutex = mutex_create_new(true, g_hMainMutex = mutex_create_new(true,
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645"); L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
if ( !g_hMainMutex ) goto destroy_list; if ( !g_hMainMutex ) return;
if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) goto release_mutex;
hEvent = event_create_with_string_security_descriptor( hEvent = event_create_with_string_security_descriptor(
true, false, m_szUnloadEventName, L"D:(A;;0x001F0003;;;BA)"); true, false, m_szUnloadEventName, L"D:(A;;0x001F0003;;;BA)");
if ( !hEvent ) goto release_mutex; if ( !hEvent ) goto destroy_list;
if ( !ptrlist_add(&list, hEvent, 0) ) goto set_event; if ( !ptrlist_add(&list, hEvent, 0) ) goto set_event;
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG; dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
@@ -100,15 +101,16 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
CloseHandle(values[index]); CloseHandle(values[index]);
crashes++; crashes++;
trace(L"A process that wufuc injected into has crashed %Iu time%ls!!! (PID=%lu)", trace(L"A process wufuc injected into has crashed %Iu time%ls! (PID=%lu)",
crashes, crashes != 1 ? L"s" : L"", tags[index]); crashes, crashes != 1 ? L"s" : L"", tags[index]);
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) { if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!"); trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
Unloading = true; Unloading = true;
Suspending = true;
} }
} else if ( r == WAIT_FAILED ) { } else if ( r == WAIT_FAILED ) {
trace(L"WTF - Unexpected result from wait function!!!"); trace(L"Wait function failed!");
Unloading = true; Unloading = true;
} }
free(values); free(values);
@@ -132,11 +134,15 @@ close_scm:
set_event: set_event:
// signal event in case it is open in any other processes // signal event in case it is open in any other processes
SetEvent(hEvent); SetEvent(hEvent);
release_mutex:
ReleaseMutex(g_hMainMutex);
destroy_list: destroy_list:
ptrlist_for_each_stdcall(&list, CloseHandle); ptrlist_for_each_stdcall(&list, CloseHandle);
ptrlist_destroy(&list); ptrlist_destroy(&list);
if ( Suspending )
NtSuspendProcess(GetCurrentProcess());
release_mutex:
ReleaseMutex(g_hMainMutex);
CloseHandle(g_hMainMutex);
} }
void CALLBACK RUNDLL32_UnloadW( void CALLBACK RUNDLL32_UnloadW(

View File

@@ -92,6 +92,8 @@ close_mutex:
ptrlist_remove(list, hCrashMutex); ptrlist_remove(list, hCrashMutex);
CloseHandle(hCrashMutex); CloseHandle(hCrashMutex);
} }
if ( result )
trace(L"Successfully injected into process: %lu", dwProcessId);
return result; return result;
} }
@@ -100,13 +102,13 @@ bool wufuc_hook(HMODULE hModule)
bool result = false; bool result = false;
PLANGANDCODEPAGE ptl; PLANGANDCODEPAGE ptl;
HANDLE hProcess; HANDLE hProcess;
int tmp;
UINT cbtl; UINT cbtl;
wchar_t SubBlock[38]; wchar_t SubBlock[38];
UINT cbInternalName;
wchar_t *pInternalName; wchar_t *pInternalName;
UINT cbffi; UINT cbInternalName;
VS_FIXEDFILEINFO *pffi; VS_FIXEDFILEINFO *pffi;
UINT cbffi;
int tmp;
MODULEINFO modinfo; MODULEINFO modinfo;
size_t offset; size_t offset;
LPVOID pTarget; LPVOID pTarget;
@@ -116,7 +118,7 @@ bool wufuc_hook(HMODULE hModule)
ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl); ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl);
if ( !ptl ) { if ( !ptl ) {
trace(L"Failed to allocate version translation information from hmodule."); trace(L"Failed to get translation info from hModule.");
return false; return false;
} }
hProcess = GetCurrentProcess(); hProcess = GetCurrentProcess();
@@ -131,7 +133,7 @@ bool wufuc_hook(HMODULE hModule)
pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName); pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName);
if ( !pInternalName ) { if ( !pInternalName ) {
trace(L"Failed to allocate version internal name from hmodule."); trace(L"Failed to get internal name from hModule.");
continue; continue;
} }
@@ -142,7 +144,7 @@ bool wufuc_hook(HMODULE hModule)
} }
pffi = ver_get_version_info_from_hmodule_alloc(hModule, L"\\", &cbffi); pffi = ver_get_version_info_from_hmodule_alloc(hModule, L"\\", &cbffi);
if ( !pffi ) { if ( !pffi ) {
trace(L"Failed to allocate version information from hmodule."); trace(L"Failed to get version info from hModule.");
break; break;
} }
trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu", trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu",
@@ -160,7 +162,7 @@ bool wufuc_hook(HMODULE hModule)
break; break;
} }
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) { if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
trace(L"Failed to get module information (%p)", hModule); trace(L"Failed to get module info: %p, %p (GLE=%08x)", hProcess, hModule, GetLastError());
break; break;
} }
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage,
@@ -174,10 +176,14 @@ bool wufuc_hook(HMODULE hModule)
); );
if ( offset != -1 ) { if ( offset != -1 ) {
pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset); pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset);
MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL); trace(L"Found IsDeviceServiceable function: %p", pTarget);
result = (MH_EnableHook(pTarget) == MH_OK);
result = (MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL) == MH_OK)
&& (MH_EnableHook(pTarget) == MH_OK);
if ( result )
trace(L"Successfully hooked IsDeviceServiceable!");
} else { } else {
trace(L"Could not locate pattern offset!"); trace(L"Could not find function offset!");
} }
free_iname: free_iname:
free(pInternalName); free(pInternalName);