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)
{
trace(L"enter");
switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
@@ -22,7 +21,7 @@ VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
(ptrlist_t *)pNotifyBuffer->pContext);
break;
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;
}
if ( pNotifyBuffer->pszServiceNames )
@@ -39,6 +38,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
DWORD dwProcessId;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType;
int tmp;
LPVOID pTarget = NULL;
wchar_t *str;
HMODULE hModule;
@@ -72,11 +72,12 @@ DWORD WINAPI cb_start(HANDLE *pParam)
dwProcessId = svc_heuristic_process_id(hSCM, hService);
pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
dwServiceType = pServiceConfig->dwServiceType;
tmp = _wcsicmp(pServiceConfig->lpBinaryPathName, GetCommandLineW());
free(pServiceConfig);
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
if ( dwProcessId != GetCurrentProcessId() ) {
if ( !tmp || dwProcessId != GetCurrentProcessId() ) {
trace(L"Injected into wrong process!");
goto release;
}
@@ -86,12 +87,12 @@ DWORD WINAPI cb_start(HANDLE *pParam)
// RegQueryValueExW hook to fix incompatibility with
// UpdatePack7R2 and other patches that modify the
// 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_hook,
&(PVOID)g_pfnRegQueryValueExW,
&pTarget)));
trace(L"MH_EnableHook RegQueryValueExW=%hs", MH_StatusToString(MH_EnableHook(pTarget)));
&pTarget);
MH_EnableHook(pTarget);
}
// query the ServiceDll path after applying our compat hook so that it
@@ -102,17 +103,17 @@ DWORD WINAPI cb_start(HANDLE *pParam)
if ( !str ) {
abort_hook:
if ( pTarget )
trace(L"MH_RemoveHook RegQueryValueExW=%hs", MH_StatusToString(MH_RemoveHook(pTarget)));
MH_RemoveHook(pTarget);
goto release;
}
g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
free(str);
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_hook,
&(PVOID)g_pfnLoadLibraryExW)));
&(PVOID)g_pfnLoadLibraryExW);
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
@@ -122,14 +123,14 @@ abort_hook:
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,
// for example if the user killed rundll32.exe with task manager.
WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
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);
release:
ReleaseMutex(hCrashMutex);

View File

@@ -19,29 +19,30 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
ptrlist_t list;
HANDLE hEvent;
DWORD dwDesiredAccess;
DWORD dwProcessId;
bool Unloading = false;
bool Lagging;
SC_HANDLE hSCM;
SC_HANDLE hService;
DWORD dwProcessId;
SERVICE_NOTIFYW NotifyBuffer;
bool Unloading = false;
DWORD e;
void **values;
uint32_t *tags;
size_t count;
DWORD e;
DWORD r;
size_t index;
size_t crashes = 0;
if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) return;
bool Suspending = false;
g_hMainMutex = mutex_create_new(true,
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(
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;
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
@@ -100,15 +101,16 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
CloseHandle(values[index]);
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]);
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
Unloading = true;
Suspending = true;
}
} else if ( r == WAIT_FAILED ) {
trace(L"WTF - Unexpected result from wait function!!!");
trace(L"Wait function failed!");
Unloading = true;
}
free(values);
@@ -132,11 +134,15 @@ close_scm:
set_event:
// signal event in case it is open in any other processes
SetEvent(hEvent);
release_mutex:
ReleaseMutex(g_hMainMutex);
destroy_list:
ptrlist_for_each_stdcall(&list, CloseHandle);
ptrlist_destroy(&list);
if ( Suspending )
NtSuspendProcess(GetCurrentProcess());
release_mutex:
ReleaseMutex(g_hMainMutex);
CloseHandle(g_hMainMutex);
}
void CALLBACK RUNDLL32_UnloadW(

View File

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