From 31cefc29a50cd564f6661adffb1fc686257a5647 Mon Sep 17 00:00:00 2001 From: zeffy Date: Fri, 16 Mar 2018 06:48:50 -0700 Subject: [PATCH] 1.0 --- FAQ.md | 14 ++ README.md | 2 + src/wufuc/callbacks.c | 67 +++++--- src/wufuc/dllmain.c | 1 + src/wufuc/hooks.c | 14 +- src/wufuc/log.c | 154 +++++++++++++++--- src/wufuc/log.h | 19 ++- src/wufuc/ptrlist.c | 20 ++- src/wufuc/resource.h | 18 ++ src/wufuc/{wufuc.rc => resource.rc} | Bin 2030 -> 1994 bytes src/wufuc/rundll32.c | 10 +- src/wufuc/versionhelper.c | 12 +- src/wufuc/versionhelper.h | 2 - src/wufuc/wufuc.c | 60 +++---- src/wufuc/wufuc.h | 3 +- src/wufuc/wufuc.rch | 17 -- src/wufuc/wufuc.vcxproj | 4 +- src/wufuc/wufuc.vcxproj.filters | 16 +- src/wufuc_setup/wufuc_setup.aip | 66 +++++++- .../Restore_wuauserv.reg | Bin src/wufuc_setup_bat/install_wufuc.bat | 5 +- src/wufuc_setup_bat/wufuc_ScheduledTask.xml | Bin 3660 -> 3662 bytes 22 files changed, 356 insertions(+), 148 deletions(-) create mode 100644 src/wufuc/resource.h rename src/wufuc/{wufuc.rc => resource.rc} (86%) delete mode 100644 src/wufuc/wufuc.rch rename src/wufuc_setup_bat/{ => Troubleshooting}/Restore_wuauserv.reg (100%) diff --git a/FAQ.md b/FAQ.md index 442dbd4..6c1d0cc 100644 --- a/FAQ.md +++ b/FAQ.md @@ -13,6 +13,20 @@ These must be used from an elevated command line prompt. +## How to restore Windows Update to its default configuration + +Windows Update by default is configured to run as `SERVICE_WIN32_SHARE_PROCESS`, which means it shares a single `svchost.exe` process with several other Windows services. +It can also be configured as `SERVICE_WIN32_OWN_PROCESS`, which means it runs in its own process, which doesn't start until Windows Update does. + +Normally, either of these configurations is supported. + +However, if you have used another third-party solution for the CPU fix (such as UpdatePack7R2 or WuaCpuFix) either knowingly or unknowingly, wufuc will not function correctly if Windows Update is configured as `SERVICE_WIN32_OWN_PROCESS`. + +You have two ways to work around this limitation, either: + +- You can remove the other third-party solution yourself. +- Alternatively, go to the directory that you installed wufuc to, open the `Troubleshooting` subdirectory, and merge the `Restore_wuauserv.reg` file with your registry by double-clicking it, and then restart your PC. + ## How to manually remove wufuc v0.8.0.143 when it is impossible to uninstall it normally This applies exclusively to a very buggy version of wufuc that was only available for download for a short period of time, other versions are unaffected. diff --git a/README.md b/README.md index 90e4915..93cda4c 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,9 @@ Some people with older Intel and AMD processors are also affected! I've received - [Intel Atom D525](https://github.com/zeffy/wufuc/issues/34) - [Intel Core i5-M 560](https://github.com/zeffy/wufuc/issues/23) - [Intel Core i5-4300M](https://github.com/zeffy/wufuc/issues/24) +- [Intel Core i7-4930K](https://github.com/zeffy/wufuc/issues/126) - [Intel Pentium B940](https://github.com/zeffy/wufuc/issues/63) +- [AMD FX-6300](https://github.com/zeffy/wufuc/issues/135#issuecomment-367054217) - [AMD FX-8350](https://github.com/zeffy/wufuc/issues/32) - [AMD Turion 64 Mobile Technology ML-34](https://github.com/zeffy/wufuc/issues/80) diff --git a/src/wufuc/callbacks.c b/src/wufuc/callbacks.c index c6c68ad..791d787 100644 --- a/src/wufuc/callbacks.c +++ b/src/wufuc/callbacks.c @@ -5,9 +5,11 @@ #include "modulehelper.h" #include "registryhelper.h" #include "servicehelper.h" +#include "versionhelper.h" #include "ptrlist.h" #include "wufuc.h" +#include #include VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer) @@ -38,25 +40,30 @@ DWORD WINAPI cb_start(HANDLE *pParam) DWORD dwProcessId; LPQUERY_SERVICE_CONFIGW pServiceConfig; DWORD dwServiceType; + const wchar_t szKernel32Dll[] = L"kernel32.dll"; + const wchar_t szKernelBaseDll[] = L"KernelBase.dll"; + const wchar_t *pszModule; + MH_STATUS status; int tmp; - LPVOID pTarget = NULL; + LPVOID pv1 = NULL; + LPVOID pv2 = NULL; wchar_t *str; HMODULE hModule; if ( !pParam ) { - trace(L"Parameter argument is null!"); + log_error(L"Parameter argument is null!"); goto unload; } - handles[0] = pParam[0]; // main mutex handles[1] = pParam[1]; // unload event hCrashMutex = pParam[2]; // crash mutex hProceedEvent = pParam[3]; // proceed event - VirtualFree(pParam, 0, MEM_RELEASE); + if ( !VirtualFree(pParam, 0, MEM_RELEASE) ) + log_warning(L"VirtualFree failed! (lpAddress=%p, GLE=%lu)", pParam, GetLastError()); // acquire child mutex, this should be immediate. if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) { - trace(L"Failed to acquire child mutex within five seconds. (%p)", hCrashMutex); + log_error(L"Failed to acquire child mutex within five seconds. (%p)", hCrashMutex); goto close_handles; } SetEvent(hProceedEvent); @@ -64,12 +71,10 @@ DWORD WINAPI cb_start(HANDLE *pParam) hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); if ( !hSCM ) { - trace(L"Failed to open SCM. (GetLastError=%lu)", GetLastError()); + log_error(L"Failed to open SCM. (GetLastError=%lu)", GetLastError()); goto release; } - - hService = OpenServiceW(hSCM, L"wuauserv", - SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); + hService = OpenServiceW(hSCM, L"wuauserv", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); dwProcessId = svc_heuristic_process_id(hSCM, hService); pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL); dwServiceType = pServiceConfig->dwServiceType; @@ -79,23 +84,33 @@ DWORD WINAPI cb_start(HANDLE *pParam) CloseServiceHandle(hSCM); if ( tmp || dwProcessId != GetCurrentProcessId() ) { - trace(L"Injected into wrong process!"); + log_error(L"Injected into wrong process!"); + goto release; + } + if ( !ver_verify_version_info(6, 1, 0) && !ver_verify_version_info(6, 3, 0) ) { + log_error(L"Unsupported operating system!"); goto release; } - if ( dwServiceType == SERVICE_WIN32_SHARE_PROCESS ) { // assume wuaueng.dll hasn't been loaded yet, apply // RegQueryValueExW hook to fix incompatibility with // UpdatePack7R2 and other patches that modify the // Windows Update ServiceDll path in the registry. - MH_CreateHookApiEx(L"kernel32.dll", + pszModule = IsWindows8OrGreater() + ? szKernelBaseDll + : szKernel32Dll; + status = MH_CreateHookApiEx(pszModule, "RegQueryValueExW", RegQueryValueExW_hook, &(PVOID)g_pfnRegQueryValueExW, - &pTarget); - MH_EnableHook(pTarget); + &pv1); + if ( status == MH_OK ) { + status = MH_EnableHook(pv1); + if ( status == MH_OK ) + log_info(L"Hooked RegQueryValueExW! (Module=%ls, Address=%p)", pszModule, pv1); + else log_error(L"Failed to enable RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status)); + } else log_error(L"Failed to create RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status)); } - // query the ServiceDll path after applying our compat hook so that it // is correct str = (wchar_t *)reg_query_value_alloc(HKEY_LOCAL_MACHINE, @@ -103,18 +118,25 @@ DWORD WINAPI cb_start(HANDLE *pParam) L"ServiceDll", NULL, NULL); if ( !str ) { abort_hook: - if ( pTarget ) - MH_RemoveHook(pTarget); + if ( pv1 ) + MH_RemoveHook(pv1); goto release; } g_pszWUServiceDll = env_expand_strings_alloc(str, NULL); free(str); if ( !g_pszWUServiceDll ) goto abort_hook; - MH_CreateHookApi(L"kernel32.dll", + status = MH_CreateHookApiEx(szKernelBaseDll, "LoadLibraryExW", LoadLibraryExW_hook, - &(PVOID)g_pfnLoadLibraryExW); + &(PVOID)g_pfnLoadLibraryExW, + &pv2); + if ( status == MH_OK ) { + status = MH_EnableHook(pv2); + if ( status == MH_OK ) + log_info(L"Hooked LoadLibraryExW! (Module=%ls, Address=%p)", szKernelBaseDll, pv2); + else log_error(L"Failed to enable LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status)); + } else log_error(L"Failed to create LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status)); if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule) || GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) { @@ -122,14 +144,11 @@ abort_hook: // hook IsDeviceServiceable if wuaueng.dll is already loaded wufuc_hook(hModule); FreeLibrary(hModule); - } - 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."); + log_info(L"Unload condition has been met."); MH_DisableHook(MH_ALL_HOOKS); free(g_pszWUServiceDll); @@ -140,7 +159,7 @@ close_handles: CloseHandle(handles[0]); CloseHandle(handles[1]); unload: - trace(L"Unloading wufuc and exiting thread."); + log_info(L"Unloading wufuc and exiting thread."); FreeLibraryAndExitThread(PIMAGEBASE, 0); } diff --git a/src/wufuc/dllmain.c b/src/wufuc/dllmain.c index a29d610..710c094 100644 --- a/src/wufuc/dllmain.c +++ b/src/wufuc/dllmain.c @@ -16,6 +16,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, break; case DLL_PROCESS_DETACH: MH_Uninitialize(); + log_close(); break; } return TRUE; diff --git a/src/wufuc/hooks.c b/src/wufuc/hooks.c index be24b82..8c3da22 100644 --- a/src/wufuc/hooks.c +++ b/src/wufuc/hooks.c @@ -19,7 +19,7 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR ULONG ResultLength; PKEY_NAME_INFORMATION pkni; size_t NameCount; - int current; + unsigned int current; int pos; wchar_t *fname; const wchar_t realpath[] = L"%systemroot%\\system32\\wuaueng.dll"; @@ -31,7 +31,6 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR MaximumLength = *lpcbData; result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); - if ( result != ERROR_SUCCESS || !MaximumLength || !lpValueName @@ -51,7 +50,7 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR for ( size_t i = 0; i < NameCount; i++ ) pkni->Name[i] = towlower(pkni->Name[i]); - if ( _snwscanf_s(pkni->Name, NameCount, L"\\registry\\machine\\system\\controlset%03d\\services\\wuauserv\\parameters%n", ¤t, &pos) == 1 + if ( _snwscanf_s(pkni->Name, NameCount, L"\\registry\\machine\\system\\controlset%03u\\services\\wuauserv\\parameters%n", ¤t, &pos) == 1 && pos == NameCount ) { fname = PathFindFileNameW(pBuffer); @@ -66,7 +65,7 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR && SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) { *lpcbData = cchLength * (sizeof *expandedpath); - trace(L"Fixed path to Windows Update service library."); + log_info(L"Fixed path to Windows Update service library."); } free(expandedpath); } @@ -82,9 +81,10 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla result = g_pfnLoadLibraryExW(lpFileName, hFile, dwFlags); if ( !result ) return result; - trace(L"Loaded library: %ls (%p)", lpFileName, result); + log_debug(L"Loaded library: %ls (%p)", lpFileName, result); - if ( g_pszWUServiceDll + if ( dwFlags == LOAD_WITH_ALTERED_SEARCH_PATH + && g_pszWUServiceDll && (!_wcsicmp(lpFileName, g_pszWUServiceDll) || !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) { @@ -95,6 +95,6 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla BOOL WINAPI IsDeviceServiceable_hook(void) { - trace(L"Entered stub function."); + log_debug(L"Entered stub function."); return TRUE; } diff --git a/src/wufuc/log.c b/src/wufuc/log.c index 54fcecf..a1b4083 100644 --- a/src/wufuc/log.c +++ b/src/wufuc/log.c @@ -1,39 +1,153 @@ #include "stdafx.h" #include "log.h" -void logp_debug_write(const wchar_t *const format, ...) +#include + +HANDLE m_hFile = INVALID_HANDLE_VALUE; + +BOOL CALLBACK init_file_handle( + PINIT_ONCE pInitOnce, + ParamData *pParam, + PVOID *ppContext) +{ + BOOL result = FALSE; + HANDLE hFile; + HRESULT hr; + wchar_t *pszPath; + wchar_t szFilePath[MAX_PATH]; + int ret; + + pParam->dwProcessId = GetCurrentProcessId(); + if ( !GetModuleFileNameW(NULL, pParam->szExeFilePath, _countof(pParam->szExeFilePath)) ) { + log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError()); + return result; + } + pParam->pszExeName = PathFindFileNameW(pParam->szExeFilePath); + + hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath); + if ( hr != S_OK ) { + log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr); + return result; + } + ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath); + CoTaskMemFree(pszPath); + if ( ret ) { + log_debug(L"wcscpy_s failed! (Return value=%d)", ret); + return result; + } + + if ( !PathAppendW(szFilePath, L"wufuc") ) { +append_fail: + log_debug(L"PathAppendW failed!"); + return result; + } + if ( !CreateDirectoryW(szFilePath, NULL) + && GetLastError() != ERROR_ALREADY_EXISTS ) { + + log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError()); + return result; + } + if ( !PathAppendW(szFilePath, L"wufuc.log") ) + goto append_fail; + + hFile = CreateFileW(szFilePath, + FILE_APPEND_DATA, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ( hFile != INVALID_HANDLE_VALUE ) { + *ppContext = (PVOID)hFile; + result = TRUE; + } else { + log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError()); + } + return result; +} + +void log_debug_(const wchar_t *const format, ...) { - DWORD pid; - wchar_t exepath[MAX_PATH]; - wchar_t *exename; va_list ap; + wchar_t *buf; + int ret; int count; - wchar_t *buffer1; - wchar_t *buffer2; + + va_start(ap, format); + count = _vscwprintf(format, ap); + va_end(ap); + if ( count == -1 ) return; + + buf = calloc(count + 1, sizeof *buf); + if ( !buf ) return; + + va_start(ap, format); + ret = vswprintf_s(buf, count + 1, format, ap); + va_end(ap); + if ( ret != -1 ) + OutputDebugStringW(buf); + free(buf); +} + +void log_trace_(const wchar_t *const format, ...) +{ + static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT; + static ParamData data; + BOOL bStatus; + errno_t e; wchar_t datebuf[9]; wchar_t timebuf[9]; + va_list ap; const wchar_t fmt[] = L"%ls %ls [%ls:%lu] %ls"; + int count; + wchar_t *buf1; + int ret; + wchar_t *buf2; + DWORD written; - pid = GetCurrentProcessId(); - GetModuleFileNameW(NULL, exepath, _countof(exepath)); - exename = PathFindFileNameW(exepath); + bStatus = InitOnceExecuteOnce(&InitOnce, + (PINIT_ONCE_FN)init_file_handle, + &data, + &(LPVOID)m_hFile); + + e = _wstrdate_s(datebuf, _countof(datebuf)); + if ( e ) return; + e = _wstrtime_s(timebuf, _countof(timebuf)); + if ( e ) return; va_start(ap, format); - count = _vscwprintf(format, ap) + 1; + count = _vscwprintf(format, ap); va_end(ap); - buffer1 = calloc(count, sizeof *buffer1); + if ( count == -1 ) return; + + buf1 = calloc(count + 1, sizeof *buf1); + if ( !buf1 ) return; + va_start(ap, format); - vswprintf_s(buffer1, count, format, ap); + ret = vswprintf_s(buf1, count + 1, format, ap); va_end(ap); + if ( ret == -1 ) goto free_buf1; - _wstrdate_s(datebuf, _countof(datebuf)); - _wstrtime_s(timebuf, _countof(timebuf)); - count = _scwprintf(fmt, datebuf, timebuf, exename, pid, buffer1) + 1; + count = _scwprintf(fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1); + if ( count == -1 ) goto free_buf1; - buffer2 = calloc(count, sizeof *buffer2); - swprintf_s(buffer2, count, fmt, datebuf, timebuf, exename, pid, buffer1); + buf2 = calloc(count + 1, sizeof *buf2); + if ( !buf2 ) goto free_buf1; - free(buffer1); - OutputDebugStringW(buffer2); - free(buffer2); + ret = swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1); + if ( ret == -1 ) goto free_buf2; + + if ( !bStatus || !WriteFile(m_hFile, buf2, count * (sizeof *buf2), &written, NULL) ) + OutputDebugStringW(buf2); +free_buf2: + free(buf2); +free_buf1: + free(buf1); +} + +void log_close(void) +{ + if ( m_hFile != INVALID_HANDLE_VALUE ) + CloseHandle(m_hFile); } diff --git a/src/wufuc/log.h b/src/wufuc/log.h index 5f1a3f4..b784b12 100644 --- a/src/wufuc/log.h +++ b/src/wufuc/log.h @@ -1,6 +1,17 @@ #pragma once -void logp_debug_write(const wchar_t *const format, ...); -#define log_debug_write(format, ...) \ - logp_debug_write(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__) -#define trace log_debug_write +typedef struct +{ + DWORD dwProcessId; + wchar_t szExeFilePath[MAX_PATH]; + wchar_t *pszExeName; +} ParamData; + +void log_debug_(const wchar_t *const format, ...); +void log_trace_(const wchar_t *const format, ...); +void log_close(void); + +#define log_debug(format, ...) log_debug_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [DEBUG] " format L"\r\n", ##__VA_ARGS__) +#define log_info(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [INFO] " format L"\r\n", ##__VA_ARGS__) +#define log_warning(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [WARNING] " format L"\r\n", ##__VA_ARGS__) +#define log_error(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [ERROR] " format L"\r\n", ##__VA_ARGS__) diff --git a/src/wufuc/ptrlist.c b/src/wufuc/ptrlist.c index b9db9b9..5ec739e 100644 --- a/src/wufuc/ptrlist.c +++ b/src/wufuc/ptrlist.c @@ -362,14 +362,20 @@ leave: void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *)) { + if ( !list || !f ) return; + ptrlist_lock(list); - for ( size_t i = index; i < count; i++ ) - f(list->values[i]); + if ( index + count <= list->count ) { + for ( size_t i = index; i < count; i++ ) + f(list->values[i]); + } ptrlist_unlock(list); } void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *)) { + if ( !list || !f ) return; + ptrlist_lock(list); ptrlist_for(list, 0, list->count, f); ptrlist_unlock(list); @@ -377,14 +383,20 @@ void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *)) void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *)) { + if ( !list || !f ) return; + ptrlist_lock(list); - for ( size_t i = index; i < count; i++ ) - f(list->values[i]); + if ( index + count <= list->count ) { + for ( size_t i = index; i < count; i++ ) + f(list->values[i]); + } ptrlist_unlock(list); } void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *)) { + if ( !list || !f ) return; + ptrlist_lock(list); ptrlist_for_stdcall(list, 0, list->count, f); ptrlist_unlock(list); diff --git a/src/wufuc/resource.h b/src/wufuc/resource.h new file mode 100644 index 0000000..704ba3b --- /dev/null +++ b/src/wufuc/resource.h @@ -0,0 +1,18 @@ +#pragma once + +#ifndef BUILD_COMMIT_VERSION +#define BUILD_COMMIT_VERSION 1.0.0.0 +#endif + +#ifndef BUILD_VERSION_COMMA +#define BUILD_VERSION_COMMA 1,0,0,0 +#endif + +#define S_(x) #x +#define S(x) S_(x) + +#ifdef X64 +#define FILENAME "wufuc64.dll" +#elif defined(X86) +#define FILENAME "wufuc32.dll" +#endif diff --git a/src/wufuc/wufuc.rc b/src/wufuc/resource.rc similarity index 86% rename from src/wufuc/wufuc.rc rename to src/wufuc/resource.rc index 0d805b699d7ee7f5342ca15c8bfed1107b87903c..3591d7cc59bfacaa562a1a64fbb2232fcecfd420 100644 GIT binary patch delta 105 zcmaFIe~N#Cm|zh@Dnl_tK0_%(5koSNt+!E?pJlQO%RYWL22Tbb23H0@21f>82G_~? aEZURpSmm&a&tO%<5I@iQb@LTADMkPW4H!lM delta 149 zcmX@b|Biox7=JlKDMK0%Co||V6fq=kROe^m4`B#m@MQ2~a0il646c*cvpG&KU=^F( y!;&Ew&JfDr2E@(`@eD2uJ`6sS6Irw;>#@q=kZEI8!y>br^((q9o7b~RGXen2kRXTv diff --git a/src/wufuc/rundll32.c b/src/wufuc/rundll32.c index 8e68635..b304ec3 100644 --- a/src/wufuc/rundll32.c +++ b/src/wufuc/rundll32.c @@ -101,16 +101,16 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, CloseHandle(values[index]); crashes++; - trace(L"A process wufuc injected into has crashed %Iu time%ls! (PID=%lu)", + log_warning(L"A process wufuc injected into has crashed %Iu time%ls! (ProcessId=%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!"); + log_error(L"Crash threshold has been reached, disabling wufuc until next reboot!"); Unloading = true; Suspending = true; } } else if ( r == WAIT_FAILED ) { - trace(L"Wait function failed!"); + log_error(L"Wait function failed!"); Unloading = true; } free(values); @@ -118,11 +118,11 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, } while ( r != WAIT_IO_COMPLETION && !Unloading ); break; case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: - trace(L"Client lagging!"); + log_warning(L"Client lagging!"); Lagging = true; break; default: - trace(L"NotifyServiceStatusChange failed, return value: %lu (%08X)", e); + log_error(L"NotifyServiceStatusChange failed! (Return value=%lu)", e); Unloading = true; break; } diff --git a/src/wufuc/versionhelper.c b/src/wufuc/versionhelper.c index b46c77d..4a2c2a8 100644 --- a/src/wufuc/versionhelper.c +++ b/src/wufuc/versionhelper.c @@ -91,9 +91,9 @@ LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *p bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) { + DWORDLONG dwlConditionMask = 0; OSVERSIONINFOEXW osvi = { sizeof osvi }; - DWORDLONG dwlConditionMask = 0; VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL); VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL); VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); @@ -106,13 +106,3 @@ bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServi VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; } - -bool ver_verify_windows_7_sp1(void) -{ - return ver_verify_version_info(6, 1, 1); -} - -bool ver_verify_windows_8_1(void) -{ - return ver_verify_version_info(6, 3, 0); -} diff --git a/src/wufuc/versionhelper.h b/src/wufuc/versionhelper.h index 7fc954e..c9a534a 100644 --- a/src/wufuc/versionhelper.h +++ b/src/wufuc/versionhelper.h @@ -4,5 +4,3 @@ int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor bool ver_get_version_info_from_hmodule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData); LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData); bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor); -bool ver_verify_windows_7_sp1(void); -bool ver_verify_windows_8_1(void); \ No newline at end of file diff --git a/src/wufuc/wufuc.c b/src/wufuc/wufuc.c index 423b383..1cdf2cd 100644 --- a/src/wufuc/wufuc.c +++ b/src/wufuc/wufuc.c @@ -93,7 +93,9 @@ close_mutex: CloseHandle(hCrashMutex); } if ( result ) - trace(L"Successfully injected into process: %lu", dwProcessId); + log_info(L"Successfully injected into process! (ProcessId=%lu)", dwProcessId); + else + log_warning(L"Failed to inject into process! (ProcessId=%lu)", dwProcessId); return result; } @@ -108,17 +110,15 @@ bool wufuc_hook(HMODULE hModule) UINT cbInternalName; VS_FIXEDFILEINFO *pffi; UINT cbffi; - int tmp; + bool tmp; MODULEINFO modinfo; size_t offset; - LPVOID pTarget; - - if ( !ver_verify_windows_7_sp1() && !ver_verify_windows_8_1() ) - return false; + LPVOID pTarget = NULL; + MH_STATUS status; ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl); if ( !ptl ) { - trace(L"Failed to get translation info from hModule."); + log_error(L"ver_get_version_info_from_hmodule_alloc failed!"); return false; } hProcess = GetCurrentProcess(); @@ -133,58 +133,58 @@ bool wufuc_hook(HMODULE hModule) pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName); if ( !pInternalName ) { - trace(L"Failed to get internal name from hModule."); + log_error(L"ver_get_version_info_from_hmodule_alloc failed!"); continue; } - // identify wuaueng.dll by its resource data if ( _wcsicmp(pInternalName, L"wuaueng.dll") ) { - trace(L"Module internal name does not match. (%ls)", pInternalName); + log_error(L"Module internal name does not match! (InternalName=%ls)", pInternalName); goto free_iname; } pffi = ver_get_version_info_from_hmodule_alloc(hModule, L"\\", &cbffi); if ( !pffi ) { - trace(L"Failed to get version info from hModule."); + log_error(L"ver_get_version_info_from_hmodule_alloc failed!"); break; } - trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu", + // assure wuaueng.dll version is supported + tmp = ((ver_verify_version_info(6, 1, 0) && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1) + || (ver_verify_version_info(6, 3, 0) && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1)); + + log_info(L"%ls Windows Update Agent version: %hu.%hu.%hu.%hu", + tmp ? L"Supported" : L"Unsupported", HIWORD(pffi->dwProductVersionMS), LOWORD(pffi->dwProductVersionMS), HIWORD(pffi->dwProductVersionLS), LOWORD(pffi->dwProductVersionLS)); - - // assure wuaueng.dll is at least the minimum supported version - tmp = ((ver_verify_windows_7_sp1() && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1) - || (ver_verify_windows_8_1() && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1)); free(pffi); - if ( !tmp ) { - trace(L"Windows Update Agent does not meet the minimum supported version."); - break; - } + if ( !tmp ) break; + if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) { - trace(L"Failed to get module info: %p, %p (GLE=%08x)", hProcess, hModule, GetLastError()); + log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", + hModule, GetLastError()); break; } offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, #ifdef _WIN64 "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????" #else - ver_verify_windows_7_sp1() + ver_verify_version_info(6, 1, 0) ? "833D????????00 743E E8???????? A3????????" : "8BFF 51 833D????????00 7507 A1????????" #endif ); if ( offset != -1 ) { pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset); - trace(L"Found IsDeviceServiceable function: %p", pTarget); + log_info(L"Matched IsDeviceServiceable function! (Offset=%IX, Address=%p)", offset, 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 find function offset!"); - } + status = MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL); + if ( status == MH_OK ) { + status = MH_EnableHook(pTarget); + if ( status == MH_OK ) + log_info(L"Hooked IsDeviceServiceable! (Address=%p)", pTarget); + else log_error(L"Failed to enable IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status)); + } else log_error(L"Failed to create IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status)); + } else log_info(L"Couldn't match IsDeviceServiceable function! (Already patched?)"); free_iname: free(pInternalName); break; diff --git a/src/wufuc/wufuc.h b/src/wufuc/wufuc.h index 3a4c91b..5ecfa76 100644 --- a/src/wufuc/wufuc.h +++ b/src/wufuc/wufuc.h @@ -7,10 +7,9 @@ typedef struct } LANGANDCODEPAGE, *PLANGANDCODEPAGE; #define SVCHOST_CRASH_THRESHOLD 3 - extern HANDLE g_hMainMutex; bool wufuc_inject(DWORD dwProcessId, LPTHREAD_START_ROUTINE pStartAddress, ptrlist_t *list); -bool wufuc_hook(HMODULE hModule); \ No newline at end of file +bool wufuc_hook(HMODULE hModule); diff --git a/src/wufuc/wufuc.rch b/src/wufuc/wufuc.rch deleted file mode 100644 index 5568d40..0000000 --- a/src/wufuc/wufuc.rch +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef WUFUC_RCH_INCLUDED -#define WUFUC_RCH_INCLUDED -#pragma once -#ifndef BUILD_COMMIT_VERSION -#define BUILD_COMMIT_VERSION 1.0.0.0 -#endif -#ifndef BUILD_VERSION_COMMA -#define BUILD_VERSION_COMMA 1.0.0.0 -#endif -#define STRINGIZE_(x) #x -#define STRINGIZE(x) STRINGIZE_(x) -#ifdef X64 -#define WUFUC_DLL "wufuc64.dll" -#elif defined(X86) -#define WUFUC_DLL "wufuc32.dll" -#endif -#endif diff --git a/src/wufuc/wufuc.vcxproj b/src/wufuc/wufuc.vcxproj index dce5bff..8a3e685 100644 --- a/src/wufuc/wufuc.vcxproj +++ b/src/wufuc/wufuc.vcxproj @@ -58,12 +58,12 @@ - + Document - + 15.0 diff --git a/src/wufuc/wufuc.vcxproj.filters b/src/wufuc/wufuc.vcxproj.filters index 36bb57c..8d6feb2 100644 --- a/src/wufuc/wufuc.vcxproj.filters +++ b/src/wufuc/wufuc.vcxproj.filters @@ -106,16 +106,16 @@ - - Resource Files - - - - - Resource Files - Source Files + + Header Files + + + + + Resource Files + \ No newline at end of file diff --git a/src/wufuc_setup/wufuc_setup.aip b/src/wufuc_setup/wufuc_setup.aip index ca9089d..042ac59 100644 --- a/src/wufuc_setup/wufuc_setup.aip +++ b/src/wufuc_setup/wufuc_setup.aip @@ -5,12 +5,16 @@ + + + + - + - + @@ -39,31 +43,46 @@ + + + + + + + + - + + + - + + + + + + @@ -109,6 +128,11 @@ + + + + + @@ -119,13 +143,18 @@ + + + + + @@ -157,8 +186,15 @@ + + + + + + + @@ -175,6 +211,7 @@ + @@ -203,17 +240,19 @@ - + - - + + + - - + + + @@ -241,6 +280,9 @@ + + + @@ -265,7 +307,13 @@ + + + + + + diff --git a/src/wufuc_setup_bat/Restore_wuauserv.reg b/src/wufuc_setup_bat/Troubleshooting/Restore_wuauserv.reg similarity index 100% rename from src/wufuc_setup_bat/Restore_wuauserv.reg rename to src/wufuc_setup_bat/Troubleshooting/Restore_wuauserv.reg diff --git a/src/wufuc_setup_bat/install_wufuc.bat b/src/wufuc_setup_bat/install_wufuc.bat index 90ffc97..fc45326 100644 --- a/src/wufuc_setup_bat/install_wufuc.bat +++ b/src/wufuc_setup_bat/install_wufuc.bat @@ -134,7 +134,6 @@ goto :cancel :install call :uninstall -net start Schedule schtasks /Create /XML "%wufuc_xml%" /TN "%wufuc_task%" /F schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\System32\rundll32.exe' """%wufuc_dll_fullpath%""",RUNDLL32_Start" schtasks /Change /TN "%wufuc_task%" /ENABLE @@ -166,8 +165,8 @@ goto :confirm_restart sfc /SCANFILE="%systemfolder%\wuaueng.dll" :: remove traces of wufuc 0.6-0.7, 0.9.999+ - schtasks /Query /TN "%wufuc_task%" >nul 2>&1 && ( - schtasks /Delete /TN "%wufuc_task%" /F ) + net start Schedule + schtasks /Delete /TN "%wufuc_task%" /F rundll32 "%wufuc_dll_fullpath%",RUNDLL32_Unload :: remove traces of wufuc 0.8.x diff --git a/src/wufuc_setup_bat/wufuc_ScheduledTask.xml b/src/wufuc_setup_bat/wufuc_ScheduledTask.xml index 7770bd4ab13435af0d6f2fa8f7dde94b702829ad..f264c9058129d20f5b5a24b9136a1bfb2aa85fb2 100644 GIT binary patch delta 20 bcmX>jb53T%F;4b0hD3%OhT_eqIU893P*VpB delta 16 YcmX>nb4F&vG0w?q%vzg2amKI!06WeGMgRZ+