diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e4c47b..389f48c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,17 @@ # Contributing guidelines -This document is also available in [简体中文], [繁体中文], [русский], [Español] and [more...](https://github.com/zeffy/wufuc/wiki) +[:de:] [:es:] [:fr:] [:it:] [:hungary:] [:brazil:] [:ru:] [:cn:] [:taiwan:] ## Reporting an issue [![](https://isitmaintained.com/badge/resolution/zeffy/wufuc.svg)](https://isitmaintained.com/project/zeffy/wufuc) -#### Before you create an issue, please make sure of the following: +### Before you create an issue, please make sure of the following: - Are you using at least the [latest stable version](https://github.com/zeffy/wufuc/releases/latest)? - Have you tried restarting your computer? -#### After you've confirmed those things, please create an issue and include the following information: +### After you've confirmed those things, please create an issue and include the following information: -- Navigate to where you installed wufuc, and attach all the `*.log` files to your issue. -- What build are you using? Stable release or unstable AppVeyor builds? +- Navigate to where you installed wufuc, and attach `wufuc.log` to your issue. - What is the file version and/or SHA-1 hash of `C:\Windows\System32\wuaueng.dll`? - Any other information you feel is relevant to your issue. @@ -21,7 +20,12 @@ This document is also available in [简体中文], [繁体中文], [русски - Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the contributing guidelines. - Issues that go a week without a response from original poster are subject to closure at my discretion. -[简体中文]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) -[繁体中文]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%E7%B9%81%E9%AB%94%E4%B8%AD%E6%96%87) -[русский]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9) -[Español]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Espa%C3%B1ol) +[:de:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Deutsch) +[:es:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Espa%C3%B1ol) +[:fr:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Fran%C3%A7ais) +[:it:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Italiano) +[:hungary:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Magyar) +[:brazil:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(Portugu%C3%AAs%20Brasileiro) +[:ru:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9) +[:cn:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) +[:taiwan:]: https://github.com/zeffy/wufuc/wiki/CONTRIBUTING-(%E7%B9%81%E9%AB%94%E4%B8%AD%E6%96%87) diff --git a/src/wufuc/callbacks.c b/src/wufuc/callbacks.c index b448868..fa8eefd 100644 --- a/src/wufuc/callbacks.c +++ b/src/wufuc/callbacks.c @@ -1,15 +1,12 @@ #include "stdafx.h" #include "callbacks.h" -#include "hooks.h" -#include "hlpmisc.h" #include "hlpmem.h" +#include "hlpmisc.h" #include "hlpsvc.h" +#include "hooks.h" VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer) { - trace(L"Enter service notify callback. (NotifyStatus=%ld ServiceStatus=%ld)", - pNotifyBuffer->dwNotificationStatus, pNotifyBuffer->ServiceStatus); - switch ( pNotifyBuffer->dwNotificationStatus ) { case ERROR_SUCCESS: if ( pNotifyBuffer->ServiceStatus.dwProcessId ) @@ -25,7 +22,29 @@ VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer) LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames); } -DWORD WINAPI ThreadStartCallback(LPVOID pParam) +DWORD WINAPI PipeLoopThreadCallback(LPVOID pParam) +{ + HANDLE hPipe = (HANDLE)pParam; + BOOL fSuccess; + wchar_t chBuf[512]; + while (true) { + // Read from the pipe. + + fSuccess = ReadFile( + hPipe, // pipe handle + chBuf, // buffer to receive reply + BUFSIZE * sizeof(wchar_t), // size of buffer + &cbRead, // number of bytes read + NULL); // not overlapped + + if ( !fSuccess && GetLastError() != ERROR_MORE_DATA ) + break;; + + _tprintf(TEXT("\"%s\"\n"), chBuf); + } +} + +DWORD WINAPI StartThreadCallback(LPVOID pParam) { ContextHandles ctx; SC_HANDLE hSCM; @@ -33,8 +52,9 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) DWORD dwProcessId; LPQUERY_SERVICE_CONFIGW pServiceConfig; DWORD dwServiceType; - LPWSTR str; + wchar_t *str; HMODULE hModule; + wchar_t Filename[MAX_PATH]; DWORD result; // get mutex and unload event handles from virtual memory @@ -55,7 +75,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); if ( !hSCM ) { - trace(L"Failed to open SCM. (GetLastError=%ul)", GetLastError()); + trace(L"Failed to open SCM. (GetLastError=%lu)", GetLastError()); goto release; } @@ -91,7 +111,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) // query the ServiceDll path after applying our compat hook so that it // is correct - str = (LPWSTR)RegQueryValueExAlloc(HKEY_LOCAL_MACHINE, + str = (wchar_t *)RegQueryValueExAlloc(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters", L"ServiceDll", NULL, NULL); g_pszWUServiceDll = ExpandEnvironmentStringsAlloc(str, NULL); @@ -105,9 +125,8 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) DetourAttach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook); if ( g_pszWUServiceDll ) { - hModule = GetModuleHandleW(g_pszWUServiceDll); - if ( hModule ) { - if ( FindIDSFunctionPointer(hModule, &(PVOID)g_pfnIsDeviceServiceable) ) { + if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule) ) { + if ( FindIDSFunctionAddress(hModule, &(PVOID)g_pfnIsDeviceServiceable) ) { trace(L"Matched pattern for %ls!IsDeviceServiceable. (%p)", PathFindFileNameW(g_pszWUServiceDll), g_pfnIsDeviceServiceable); @@ -115,6 +134,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) } else { trace(L"No pattern matched!"); } + FreeLibrary(hModule); } } @@ -125,7 +145,6 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) // intentionally leave parent mutex open until this thread ends, at // which point it becomes abandoned again. result = WaitForMultipleObjects(_countof(ctx.handles), ctx.handles, FALSE, INFINITE); - trace(L"Unload condition has been met."); // unhook @@ -137,9 +156,19 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam) if ( g_pfnLoadLibraryExW ) DetourDetach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook); - if ( g_pfnIsDeviceServiceable ) - DetourDetach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook); + // check to see if the last known address of IsDeviceServiceable + // is still in the address space of wuaueng.dll before + // attempting to unhook the function. + if ( g_pfnIsDeviceServiceable + && GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPWSTR)g_pfnIsDeviceServiceableLastKnown, &hModule) ) { + if ( GetModuleFileNameW(hModule, Filename, _countof(Filename)) + && (!_wcsicmp(Filename, g_pszWUServiceDll) + || !_wcsicmp(Filename, PathFindFileNameW(g_pszWUServiceDll))) ) + DetourDetach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook); + FreeLibrary(hModule); + } if ( g_pfnRegQueryValueExW ) DetourDetach(&(PVOID)g_pfnRegQueryValueExW, RegQueryValueExW_hook); @@ -151,8 +180,10 @@ release: ReleaseMutex(ctx.hChildMutex); close_handles: CloseHandle(ctx.hChildMutex); - CloseHandle(ctx.hParentMutex); CloseHandle(ctx.hUnloadEvent); + CloseHandle(ctx.hParentMutex); + if ( g_hTracingMutex ) + CloseHandle(g_hTracingMutex); unload: trace(L"Freeing library and exiting main thread."); FreeLibraryAndExitThread(PIMAGEBASE, 0); diff --git a/src/wufuc/hlpmem.c b/src/wufuc/hlpmem.c index d28a0d1..2b028d4 100644 --- a/src/wufuc/hlpmem.c +++ b/src/wufuc/hlpmem.c @@ -1,11 +1,11 @@ #include "stdafx.h" -#include "hlpmisc.h" +#include "callbacks.h" #include "hlpmem.h" +#include "hlpmisc.h" #include "hlpver.h" #include "hooks.h" -#include "callbacks.h" -bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable) +bool FindIDSFunctionAddress(HMODULE hModule, PVOID *ppfnIsDeviceServiceable) { bool result = false; bool is_win7 = false; @@ -61,23 +61,26 @@ bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable) pffi = GetVersionInfoFromHModuleAlloc(hModule, L"\\", &cbffi); if ( !pffi ) { trace(L"Failed to allocate version information from hmodule."); - continue; + break; } + trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu", + HIWORD(pffi->dwProductVersionMS), + LOWORD(pffi->dwProductVersionMS), + HIWORD(pffi->dwProductVersionLS), + LOWORD(pffi->dwProductVersionLS)); // assure wuaueng.dll is at least the minimum supported version tmp = ((is_win7 && ProductVersionCompare(pffi, 7, 6, 7601, 23714) != -1) || (is_win81 && ProductVersionCompare(pffi, 7, 9, 9600, 18621) != -1)); free(pffi); if ( !tmp ) { - trace(L"Module does not meet the minimum supported version."); - continue; + trace(L"Windows Update Agent does not meet the minimum supported version."); + break; } - if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) break; - offset = patternfind(modinfo.lpBaseOfDll, - modinfo.SizeOfImage, + offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, #ifdef _WIN64 "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????" #else @@ -87,7 +90,8 @@ bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable) #endif ); if ( offset != -1 ) { - *ppfnIsDeviceServiceable = (PVOID)((uint8_t *)modinfo.lpBaseOfDll + offset); + g_pfnIsDeviceServiceableLastKnown = (PVOID)((uint8_t *)modinfo.lpBaseOfDll + offset); + *ppfnIsDeviceServiceable = g_pfnIsDeviceServiceableLastKnown; result = true; } break; @@ -254,7 +258,7 @@ bool wufuc_InjectLibrary(DWORD dwProcessId, ContextHandles *pContext) HANDLE hSrcProcess; ContextHandles param = { 0 }; - if ( swprintf_s(MutexName, _countof(MutexName), + if ( swprintf_s(MutexName, _countof(MutexName), L"Global\\%08x-7132-44a8-be15-56698979d2f3", dwProcessId) == -1 ) { trace(L"Failed to print mutex name to string! (%lu)", dwProcessId); diff --git a/src/wufuc/hlpmem.h b/src/wufuc/hlpmem.h index a7a3a9a..4734d43 100644 --- a/src/wufuc/hlpmem.h +++ b/src/wufuc/hlpmem.h @@ -27,7 +27,7 @@ typedef struct WORD wCodePage; } LANGANDCODEPAGE, *PLANGANDCODEPAGE; -bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable); +bool FindIDSFunctionAddress(HMODULE hModule, PVOID *ppfnIsDeviceServiceable); HANDLE GetRemoteHModuleFromTh32ModuleSnapshot(HANDLE hSnapshot, const wchar_t *pLibFileName); bool InjectLibraryAndCreateRemoteThread( HANDLE hProcess, diff --git a/src/wufuc/hlpmisc.c b/src/wufuc/hlpmisc.c index ed1e0ad..3a2a903 100644 --- a/src/wufuc/hlpmisc.c +++ b/src/wufuc/hlpmisc.c @@ -2,7 +2,7 @@ #include "hlpmisc.h" #include -bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex) +bool InitializeMutex(bool InitialOwner, const wchar_t *pMutexName, HANDLE *phMutex) { HANDLE hMutex; @@ -22,10 +22,10 @@ bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex) } bool CreateEventWithStringSecurityDescriptor( - LPCWSTR pStringSecurityDescriptor, + const wchar_t *pStringSecurityDescriptor, bool ManualReset, bool InitialState, - LPCWSTR pName, + const wchar_t *pName, HANDLE *phEvent) { SECURITY_ATTRIBUTES sa = { sizeof sa }; @@ -48,8 +48,8 @@ bool CreateEventWithStringSecurityDescriptor( PVOID RegGetValueAlloc( HKEY hkey, - LPCWSTR pSubKey, - LPCWSTR pValue, + const wchar_t *pSubKey, + const wchar_t *pValue, DWORD dwFlags, LPDWORD pdwType, LPDWORD pcbData) @@ -75,8 +75,8 @@ PVOID RegGetValueAlloc( LPBYTE RegQueryValueExAlloc( HKEY hKey, - LPCWSTR pSubKey, - LPCWSTR pValueName, + const wchar_t *pSubKey, + const wchar_t *pValueName, LPDWORD pType, LPDWORD pcbData) { @@ -136,9 +136,9 @@ PVOID NtQueryKeyAlloc( return result; } -LPWSTR ExpandEnvironmentStringsAlloc(LPCWSTR src, LPDWORD pcchLength) +wchar_t *ExpandEnvironmentStringsAlloc(const wchar_t *src, LPDWORD pcchLength) { - LPWSTR result; + wchar_t *result; DWORD buffersize; DWORD size; diff --git a/src/wufuc/hlpmisc.h b/src/wufuc/hlpmisc.h index 42e71ad..37629d9 100644 --- a/src/wufuc/hlpmisc.h +++ b/src/wufuc/hlpmisc.h @@ -1,27 +1,27 @@ #pragma once -bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex); +bool InitializeMutex(bool InitialOwner, const wchar_t *pMutexName, HANDLE *phMutex); bool CreateEventWithStringSecurityDescriptor( - LPCWSTR pStringSecurityDescriptor, + const wchar_t *pStringSecurityDescriptor, bool ManualReset, bool InitialState, - LPCWSTR pName, + const wchar_t *pName, HANDLE *phEvent); PVOID RegGetValueAlloc( HKEY hkey, - LPCWSTR pSubKey, - LPCWSTR pValue, + const wchar_t *pSubKey, + const wchar_t *pValue, DWORD dwFlags, LPDWORD pdwType, LPDWORD pcbData); LPBYTE RegQueryValueExAlloc( HKEY hKey, - LPCWSTR pSubKey, - LPCWSTR pValueName, + const wchar_t *pSubKey, + const wchar_t *pValueName, LPDWORD pType, LPDWORD pcbData); PVOID NtQueryKeyAlloc( HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PULONG pResultLength); -LPWSTR ExpandEnvironmentStringsAlloc(LPCWSTR src, LPDWORD pcchLength); +wchar_t *ExpandEnvironmentStringsAlloc(const wchar_t *src, LPDWORD pcchLength); diff --git a/src/wufuc/hlpsvc.c b/src/wufuc/hlpsvc.c index 1e4e803..cfa7761 100644 --- a/src/wufuc/hlpsvc.c +++ b/src/wufuc/hlpsvc.c @@ -68,12 +68,12 @@ bool QueryServiceStatusProcessInfoByName( bool QueryServiceGroupName( const LPQUERY_SERVICE_CONFIGW pServiceConfig, - LPWSTR *pGroupName, + wchar_t **pGroupName, HLOCAL *hMem) { bool result = false; int NumArgs; - LPWSTR *argv; + wchar_t **argv; argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs); if ( argv ) { @@ -126,7 +126,7 @@ DWORD HeuristicServiceGroupProcessId(SC_HANDLE hSCM, const wchar_t *pGroupNameSe DWORD cbBufSize; LPQUERY_SERVICE_CONFIGW pServiceConfig; bool success = false; - LPWSTR pGroupName; + wchar_t *pGroupName; HLOCAL hMem; pData = RegGetValueAlloc(HKEY_LOCAL_MACHINE, @@ -165,7 +165,7 @@ DWORD HeuristicServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService) { DWORD result = 0; LPQUERY_SERVICE_CONFIGW pServiceConfig; - LPWSTR pGroupName; + wchar_t *pGroupName; HLOCAL hMem; result = QueryServiceProcessId(hSCM, hService); diff --git a/src/wufuc/hlpsvc.h b/src/wufuc/hlpsvc.h index c13e031..6ab70fe 100644 --- a/src/wufuc/hlpsvc.h +++ b/src/wufuc/hlpsvc.h @@ -14,7 +14,7 @@ bool QueryServiceStatusProcessInfoByName( LPSERVICE_STATUS_PROCESS pServiceStatus); bool QueryServiceGroupName( const LPQUERY_SERVICE_CONFIGW pServiceConfig, - LPWSTR *pGroupName, + wchar_t **pGroupName, HLOCAL *hMem); DWORD QueryServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService); DWORD QueryServiceProcessIdByName(SC_HANDLE hSCM, const wchar_t *pServiceName); diff --git a/src/wufuc/hlpver.c b/src/wufuc/hlpver.c index b6fea42..dfa0fbb 100644 --- a/src/wufuc/hlpver.c +++ b/src/wufuc/hlpver.c @@ -14,7 +14,7 @@ int ProductVersionCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD return 0; } -bool GetVersionInfoFromHModule(HMODULE hModule, LPCWSTR pszSubBlock, LPVOID pData, PUINT pcbData) +bool GetVersionInfoFromHModule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData) { bool result = false; UINT cbData; @@ -68,7 +68,7 @@ cleanup: return result; } -LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, LPCWSTR pszSubBlock, PUINT pcbData) +LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData) { UINT cbData = 0; LPVOID result = NULL; diff --git a/src/wufuc/hlpver.h b/src/wufuc/hlpver.h index ae0905e..240c605 100644 --- a/src/wufuc/hlpver.h +++ b/src/wufuc/hlpver.h @@ -1,6 +1,6 @@ #pragma once int ProductVersionCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev); -bool GetVersionInfoFromHModule(HMODULE hModule, LPCWSTR pszSubBlock, LPVOID pData, PUINT pcbData); -LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, LPCWSTR pszSubBlock, PUINT pcbData); +bool GetVersionInfoFromHModule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData); +LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData); bool IsWindowsVersion(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor); diff --git a/src/wufuc/hooks.c b/src/wufuc/hooks.c index 37d0f29..6f83cc1 100644 --- a/src/wufuc/hooks.c +++ b/src/wufuc/hooks.c @@ -1,17 +1,18 @@ #include "stdafx.h" -#include "hooks.h" -#include "hlpmisc.h" #include "hlpmem.h" +#include "hlpmisc.h" +#include "hooks.h" -LPWSTR g_pszWUServiceDll; +wchar_t *g_pszWUServiceDll; LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW; LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW; LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable; +LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceableLastKnown; LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { - PWCH pBuffer; + wchar_t *pBuffer; DWORD MaximumLength = 0; LSTATUS result; ULONG ResultLength; @@ -19,8 +20,8 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR size_t NameCount; int current; int pos; - LPWSTR fname; - const WCHAR realpath[] = L"%systemroot%\\system32\\wuaueng.dll"; + wchar_t *fname; + const wchar_t realpath[] = L"%systemroot%\\system32\\wuaueng.dll"; wchar_t *expandedpath; DWORD cchLength; @@ -30,8 +31,8 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); - if ( result != ERROR_SUCCESS - || !MaximumLength + if ( result != ERROR_SUCCESS + || !MaximumLength || !lpValueName || (lpType && *lpType != REG_EXPAND_SZ) || _wcsicmp(lpValueName, L"ServiceDll") ) @@ -59,11 +60,15 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR || !_wcsicmp(fname, L"WuaCpuFix.dll")) ) { expandedpath = ExpandEnvironmentStringsAlloc(realpath, &cchLength); - - trace(L"Fixed path to wuauserv ServiceDll: %ls -> %ls", fname, PathFindFileNameW(expandedpath)); - if ( SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) - *lpcbData = cchLength * (sizeof *expandedpath); - free(expandedpath); + if ( expandedpath ) { + if ( PathFileExistsW(expandedpath) + && SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) { + + *lpcbData = cchLength * (sizeof *expandedpath); + trace(L"Fixed path to Windows Update service library."); + } + free(expandedpath); + } } } free(pkni); @@ -79,9 +84,10 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla trace(L"Loaded library: %ls (%p)", lpFileName, result); if ( g_pszWUServiceDll - && !_wcsicmp(lpFileName, g_pszWUServiceDll) ) { + && (!_wcsicmp(lpFileName, g_pszWUServiceDll) + || !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) { - if ( FindIDSFunctionPointer(result, &(PVOID)g_pfnIsDeviceServiceable) ) { + if ( FindIDSFunctionAddress(result, &(PVOID)g_pfnIsDeviceServiceable) ) { trace(L"Matched pattern for %ls!IsDeviceServiceable. (%p)", PathFindFileNameW(lpFileName), g_pfnIsDeviceServiceable); diff --git a/src/wufuc/hooks.h b/src/wufuc/hooks.h index ef80057..e752d34 100644 --- a/src/wufuc/hooks.h +++ b/src/wufuc/hooks.h @@ -5,11 +5,12 @@ typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void); -extern LPWSTR g_pszWUServiceDll; +extern wchar_t *g_pszWUServiceDll; extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW; extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW; extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable; +extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceableLastKnown; LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags); diff --git a/src/wufuc/rundll32.c b/src/wufuc/rundll32.c index bb51a20..8e68f4b 100644 --- a/src/wufuc/rundll32.c +++ b/src/wufuc/rundll32.c @@ -1,7 +1,7 @@ #include "stdafx.h" #include "callbacks.h" -#include "hlpmisc.h" #include "hlpmem.h" +#include "hlpmisc.h" #include "hlpsvc.h" void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) @@ -17,18 +17,20 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in if ( !InitializeMutex(true, L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645", - &ctx.hParentMutex) ) { - - trace(L"Failed to initialize main mutex. (GetLastError=%ul)", GetLastError()); + &ctx.hParentMutex) ) return; - }; + + if ( !start_traing() ) + itrace(L"Could not create tracing pipe!"); + return; + if ( !CreateEventWithStringSecurityDescriptor(L"D:(A;;0x001F0003;;;BA)", true, false, L"Global\\wufuc_UnloadEvent", &ctx.hUnloadEvent) ) { - trace(L"Failed to create unload event. (GetLastError=%ul)", GetLastError()); + trace(L"Failed to create unload event. (GetLastError=%lu)", GetLastError()); goto close_mutex; } dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG; @@ -36,13 +38,13 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in Lagging = false; hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if ( !hSCM ) { - trace(L"Failed to open SCM. (GetLastError=%ul)", GetLastError()); + trace(L"Failed to open SCM. (GetLastError=%lu)", GetLastError()); goto close_event; } hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess); if ( !hService ) { - trace(L"Failed to open service. (GetLastError=%ul)", GetLastError()); + trace(L"Failed to open service. (GetLastError=%lu)", GetLastError()); goto close_scm; } if ( (dwDesiredAccess & SERVICE_QUERY_CONFIG) == SERVICE_QUERY_CONFIG ) { @@ -79,6 +81,8 @@ close_event: CloseHandle(ctx.hUnloadEvent); close_mutex: ReleaseMutex(ctx.hParentMutex); + if ( g_hTracingMutex ) + CloseHandle(g_hTracingMutex); CloseHandle(ctx.hParentMutex); } @@ -100,7 +104,7 @@ void CALLBACK RUNDLL32_DeleteFileW( int nCmdShow) { int argc; - LPWSTR *argv; + wchar_t **argv; argv = CommandLineToArgvW(lpszCmdLine, &argc); if ( argv ) { diff --git a/src/wufuc/stdafx.h b/src/wufuc/stdafx.h index 24a9b16..8664869 100644 --- a/src/wufuc/stdafx.h +++ b/src/wufuc/stdafx.h @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/wufuc/tracing.c b/src/wufuc/tracing.c index 0a9bf67..667d0e2 100644 --- a/src/wufuc/tracing.c +++ b/src/wufuc/tracing.c @@ -1,7 +1,8 @@ #include "stdafx.h" #include "tracing.h" +#include -void trace_(const wchar_t *const format, ...) +void itrace_(const wchar_t *const format, ...) { va_list argptr; int count; @@ -17,3 +18,217 @@ void trace_(const wchar_t *const format, ...) OutputDebugStringW(buffer); free(buffer); } + +HANDLE g_hTracingMutex; +wchar_t path[MAX_PATH]; +wchar_t exepath[MAX_PATH]; + +DWORD WINAPI tracing_thread(LPVOID pParam) +{ + wchar_t *folder; + HANDLE file; + DWORD dwProcessId; + wchar_t *exename; + int count; + + if ( !*path ) { + SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &folder); + wcscpy_s(path, _countof(path), folder); + CoTaskMemFree(folder); + PathAppendW(path, L"wufuc"); + CreateDirectoryW(path, NULL); + PathAppendW(path, L"wufuc.log"); + } + if ( !*exepath ) + GetModuleFileNameW(NULL, exepath, _countof(exepath)); + + file = CreateFileW(path, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + itrace(L"CreateFileW=%p", file); + dwProcessId = GetCurrentProcessId(); + exename = PathFindFileNameW(exepath); + + va_start(argptr, format); + count = _vscwprintf(format, argptr) + 1; + buf1 = calloc(count, sizeof *buf1); + vswprintf_s(buf1, count, format, argptr); + va_end(argptr); + + count = _scwprintf(fmt, datebuf, timebuf, dwProcessId, exename, buf1); + buf2 = calloc(count + 1, sizeof *buf2); + swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, dwProcessId, exename, buf1); + free(buf1); + itrace(L"WriteFile=%d", WriteFile(file, buf2, count * (sizeof *buf2), &written, NULL)); + free(buf2); + itrace(L"FlushFileBuffers=%d", FlushFileBuffers(file)); + itrace(L"CloseHandle=%d", CloseHandle(file)); + itrace(L"ReleaseMutex=%d", ReleaseMutex(g_hTracingMutex)); + + + HANDLE hHeap = GetProcessHeap(); + TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, 512 * sizeof(TCHAR)); + + DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; + BOOL fSuccess = FALSE; + HANDLE hPipe = NULL; + + // Do some extra error checking since the app will keep running even if this + // thread fails. + + if ( pParam == NULL ) { + itrace(L"\nERROR - Pipe Server Failure:"); + itrace(L" InstanceThread got an unexpected NULL value in lpvParam."); + itrace(L" InstanceThread exitting."); + if ( pchRequest != NULL ) HeapFree(hHeap, 0, pchRequest); + return -1; + } + + // Print verbose messages. In production code, this should be for debugging only. + printf("InstanceThread created, receiving and processing messages.\n"); + + // The thread's parameter is a handle to a pipe object instance. + + hPipe = (HANDLE)pParam; + + // Loop until done reading + while ( true ) { + // Read client requests from the pipe. This simplistic code only allows messages + // up to BUFSIZE characters in length. + fSuccess = ReadFile( + hPipe, // handle to pipe + pchRequest, // buffer to receive data + 512 * sizeof(TCHAR), // size of buffer + &cbBytesRead, // number of bytes read + NULL); // not overlapped I/O + + if ( !fSuccess || cbBytesRead == 0 ) { + if ( GetLastError() == ERROR_BROKEN_PIPE ) { + itrace(L"InstanceThread: client disconnected."); + } else { + itrace(L"InstanceThread ReadFile failed, GLE=%d.", GetLastError()); + } + break; + } + + _wstrdate_s(datebuf, _countof(datebuf)); + _wstrtime_s(timebuf, _countof(timebuf)); + + if ( !fSuccess ) { + itrace(L"InstanceThread WriteFile failed, GLE=%d.", GetLastError()); + break; + } + } + + // Flush the pipe to allow the client to read the pipe's contents + // before disconnecting. Then disconnect the pipe, and close the + // handle to this pipe instance. + + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); + + HeapFree(hHeap, 0, pchRequest); + + printf("InstanceThread exitting.\n"); + return 1; +} + +bool start_tracing(const wchar_t *pipename) +{ + HANDLE hPipe; + HANDLE hPipe = INVALID_HANDLE_VALUE; + HANDLE hThread = NULL; + + while ( true ) { + hPipe = CreateNamedPipeW(pipename, + PIPE_ACCESS_INBOUND, 0, PIPE_UNLIMITED_INSTANCES, 512, 0, 512, NULL); + if ( hPipe == INVALID_HANDLE_VALUE ) { + itrace(L"CreateNamedPipe failed, GLE=%d.\n"), GetLastError(); + return false; + } + + if ( ConnectNamedPipe(hPipe, NULL) || + GetLastError() == ERROR_PIPE_CONNECTED ) { + itrace(L"Client connected, creating a processing thread."); + + // Create a thread for this client. + hThread = CreateThread( + NULL, // no security attribute + 0, // default stack size + tracing_thread, // thread proc + (LPVOID)hPipe, // thread parameter + 0, // not suspended + NULL); // returns thread ID + + if ( hThread == NULL ) { + itrace(L"CreateThread failed, GLE=%d.\n"), GetLastError(); + return false; + } else { + CloseHandle(hThread); + } + } else { + // The client could not connect, so close the pipe. + CloseHandle(hPipe); + } + } + return true; +} + +void trace_(const wchar_t *const format, ...) +{ + va_list argptr; + wchar_t *folder; + wchar_t datebuf[9]; + wchar_t timebuf[9]; + HANDLE file; + DWORD dwProcessId; + wchar_t *exename; + int count; + DWORD written; + const wchar_t fmt[] = L"%ls %ls [%lu] Exe(%ls) %ls"; + wchar_t *buf1; + wchar_t *buf2; + + va_start(argptr, format); + itrace_(format); + va_end(argptr); + + if ( !*path ) { + SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &folder); + wcscpy_s(path, _countof(path), folder); + CoTaskMemFree(folder); + PathAppendW(path, L"wufuc"); + CreateDirectoryW(path, NULL); + PathAppendW(path, L"wufuc.log"); + } + if ( !*exepath ) + GetModuleFileNameW(NULL, exepath, _countof(exepath)); + + if ( !g_hTracingMutex ) + g_hTracingMutex = CreateMutexW(NULL, FALSE, L"Global\\6b2f5740-7435-47f7-865c-dbd825292f32"); + + itrace(L"WaitForSingleObject=%lu", WaitForSingleObject(g_hTracingMutex, INFINITE)); + + _wstrdate_s(datebuf, _countof(datebuf)); + _wstrtime_s(timebuf, _countof(timebuf)); + + file = CreateFileW(path, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + itrace(L"CreateFileW=%p", file); + dwProcessId = GetCurrentProcessId(); + exename = PathFindFileNameW(exepath); + + va_start(argptr, format); + count = _vscwprintf(format, argptr) + 1; + buf1 = calloc(count, sizeof *buf1); + vswprintf_s(buf1, count, format, argptr); + va_end(argptr); + + count = _scwprintf(fmt, datebuf, timebuf, dwProcessId, exename, buf1); + buf2 = calloc(count + 1, sizeof *buf2); + swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, dwProcessId, exename, buf1); + free(buf1); + itrace(L"WriteFile=%d", WriteFile(file, buf2, count * (sizeof *buf2), &written, NULL)); + free(buf2); + itrace(L"FlushFileBuffers=%d", FlushFileBuffers(file)); + itrace(L"CloseHandle=%d", CloseHandle(file)); + itrace(L"ReleaseMutex=%d", ReleaseMutex(g_hTracingMutex)); +} diff --git a/src/wufuc/tracing.h b/src/wufuc/tracing.h index b058e44..8069508 100644 --- a/src/wufuc/tracing.h +++ b/src/wufuc/tracing.h @@ -2,13 +2,14 @@ #include -extern IMAGE_DOS_HEADER __ImageBase; -#define HMODULE_THISCOMPONENT ((HMODULE)&__ImageBase); +extern HANDLE g_hTracingMutex; +void itrace_(const wchar_t *const format, ...); void trace_(const wchar_t *const format, ...); #define STRINGIZEW_(x) L#x #define STRINGIZEW(x) STRINGIZEW_(x) #define LINEWSTR STRINGIZEW(__LINE__) -#define trace(format, ...) trace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\n", ##__VA_ARGS__) +#define itrace(format, ...) itrace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\r\n", ##__VA_ARGS__) +#define trace(format, ...) trace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\r\n", ##__VA_ARGS__) diff --git a/src/wufuc_setup/wufuc_setup.aip b/src/wufuc_setup/wufuc_setup.aip index e328759..ca9089d 100644 --- a/src/wufuc_setup/wufuc_setup.aip +++ b/src/wufuc_setup/wufuc_setup.aip @@ -8,6 +8,7 @@ + @@ -24,16 +25,16 @@ - + - - - + + + @@ -61,12 +62,15 @@ + + + - - + + @@ -114,6 +118,7 @@ + @@ -154,6 +159,7 @@ + @@ -187,10 +193,12 @@ + + @@ -201,9 +209,11 @@ + + @@ -221,13 +231,16 @@ - + - - - - + + + + + + + @@ -235,19 +248,22 @@ - + + - - + + + + - - + + @@ -259,6 +275,9 @@ + + + diff --git a/src/wufuc_setup_bat/.gitignore b/src/wufuc_setup_bat/.gitignore index b404162..c9602de 100644 --- a/src/wufuc_setup_bat/.gitignore +++ b/src/wufuc_setup_bat/.gitignore @@ -1,3 +1,4 @@ # Other *.dll +*.exe *.zip