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)
|
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);
|
||||||
|
@@ -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(
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user