suspend (not exit) when crash count is exceeded
This commit is contained in:
@@ -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);
|
||||
|
@@ -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(
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user