diff --git a/src/wufuc/callbacks.c b/src/wufuc/callbacks.c index c0dba94..814fb95 100644 --- a/src/wufuc/callbacks.c +++ b/src/wufuc/callbacks.c @@ -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); diff --git a/src/wufuc/rundll32.c b/src/wufuc/rundll32.c index c7332b5..f36c224 100644 --- a/src/wufuc/rundll32.c +++ b/src/wufuc/rundll32.c @@ -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( diff --git a/src/wufuc/wufuc.c b/src/wufuc/wufuc.c index c194d9c..423b383 100644 --- a/src/wufuc/wufuc.c +++ b/src/wufuc/wufuc.c @@ -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);