From ab40ad39a2423797da42bfc16a6b6ada45cb1bee Mon Sep 17 00:00:00 2001 From: zeffy Date: Thu, 21 Sep 2017 19:09:03 -0700 Subject: [PATCH] many changes, see description [skip ci] Note: currently only works via manual injection, Rundll32Entry has been removed - Fixed conflict with UpdatePack7R2 (and WuaCpuFix) by hooking `RegQueryValueExW` and fixing the path to `wuaueng.dll`. (fixes #100) - Eliminated lots of redundant and unnecessary code. - Other reliability improvements and bug fixes. - Removed the error message that displays in the installers when `wuaueng.dll` is below the minimum supported version, and added an internal check that will skip the patching procedure if the version of `wuaueng.dll` is too low. **This means you can now safely install wufuc prior to any updates, and it will automatically start working once it's needed, without any potential side effects.** (fixes #99) - Added `/UNATTENDED` flag to the batch installer and uninstaller. You can use this to bypass the confirmation for a fully automated installation/uninstallation. To use it, you invoke the batch script from an elevated command prompt, like so: `"wufuc_installer.bat" /UNATTENDED` - Improved logging framework to allow multiple processes to safely write to the same `.log` file. --- appveyor.yml | 6 +- setup-batch/install_wufuc.bat | 69 ++------------ setup-batch/uninstall_wufuc.bat | 9 +- wufuc.sln | 5 +- wufuc/callbacks.c | 123 ++++++++----------------- wufuc/callbacks.h | 9 +- wufuc/dllmain.c | 17 ++-- wufuc/helpers.c | 114 +++++++++++++---------- wufuc/helpers.h | 15 ++-- wufuc/hooks.c | 154 +++++++++++++++++++++----------- wufuc/hooks.h | 38 +++----- wufuc/iathook.c | 15 ++-- wufuc/iathook.h | 4 +- wufuc/logging.c | 59 ------------ wufuc/logging.h | 20 ----- wufuc/ntdllhelper.c | 47 +++------- wufuc/ntdllhelper.h | 56 ++++-------- wufuc/patchwua.c | 69 +++++++------- wufuc/patchwua.h | 4 +- wufuc/patternfind.c | 17 ++-- wufuc/patternfind.h | 10 +-- wufuc/rundll32.c | 71 +-------------- wufuc/service.c | 153 +------------------------------ wufuc/service.h | 10 +-- wufuc/shellapihelper.h | 10 --- wufuc/tracing.c | 72 +++++++++++++++ wufuc/tracing.h | 22 +++++ wufuc/wufuc.def | 1 - wufuc/wufuc.rc | Bin 2192 -> 2004 bytes wufuc/wufuc.rch | 17 ++++ wufuc/wufuc.vcxproj | 87 ++++++++++-------- wufuc/wufuc.vcxproj.filters | 106 +++++++++++++++++----- 32 files changed, 600 insertions(+), 809 deletions(-) delete mode 100644 wufuc/logging.c delete mode 100644 wufuc/logging.h delete mode 100644 wufuc/shellapihelper.h create mode 100644 wufuc/tracing.c create mode 100644 wufuc/tracing.h create mode 100644 wufuc/wufuc.rch diff --git a/appveyor.yml b/appveyor.yml index 4878844..e3d3907 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,11 +12,11 @@ build: verbosity: minimal before_build: - cmd: >- - set "BUILD_VERSION=%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%" + set "BUILD_COMMIT_VERSION=%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%" - set "BUILD_VERSION_COMMA_SEP=%APPVEYOR_BUILD_VERSION:.=,%" + set "BUILD_VERSION_COMMA=%APPVEYOR_BUILD_VERSION:.=,%" - set "BUILD_ZIPFILE=%APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%_v%BUILD_VERSION%_%PLATFORM%.zip" + set "BUILD_ZIPFILE=%APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%_v%BUILD_COMMIT_VERSION%_%PLATFORM%.zip" after_build: - cmd: >- copy /Y "wufuc\bin\%CONFIGURATION%\%PLATFORM%\wufuc*.dll" "setup-batch\" diff --git a/setup-batch/install_wufuc.bat b/setup-batch/install_wufuc.bat index 0d9babd..8ef75e3 100644 --- a/setup-batch/install_wufuc.bat +++ b/setup-batch/install_wufuc.bat @@ -75,7 +75,7 @@ title wufuc installer - v%Version% set "wufuc_xml=%~dp0wufuc.xml" if exist "%wufuc_xml%" ( - goto :check_ver + goto :check_winver ) echo ERROR - Could not find %wufuc_xml%! echo. @@ -85,18 +85,14 @@ echo Please extract all the files from wufuc_v%Version%.zip to a permanent echo location like C:\Program Files\wufuc and try again. goto :die -:check_ver +:check_winver ver | findstr " 6\.1\." >nul && ( - set "WINDOWS_VER=6.1" - set "WUAUENG_DLL_MIN_VER=7.6.7601.23714" echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE% - goto :check_wuaueng_ver + goto :check_unattended ) ver | findstr " 6\.3\." >nul && ( - set "WINDOWS_VER=8.1" - set "WUAUENG_DLL_MIN_VER=7.9.9600.18621" echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE% - goto :check_wuaueng_ver + goto :check_unattended ) :unsupported_os @@ -117,19 +113,11 @@ echo and that this warning is a mistake, you may continue with the patching proc echo at your own peril. goto :confirmation -:check_wuaueng_ver -call :get_filever "%systemroot%\System32\wuaueng.dll" -call :compareversion "%WUAUENG_DLL_MIN_VER%" "%Version%" -if errorlevel 1 ( - echo. - echo ERROR - Detected that wuaueng.dll is below the minimum supported version. - echo. - echo You must first run Windows Update until the "Unsupported Hardware" window - echo pops up, then try again. - echo. - goto :die -) -echo Detected supported Windows Update agent version: %Version% +:check_unattended +if [%1]==[] goto :confirmation +if /I "%1"=="/UNATTENDED" goto :uninstall +shift +goto :check_unattended :confirmation echo. @@ -178,44 +166,5 @@ exit :get_filever file set "file=%~1" for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%file:\=\\%'" get Version /value ^| find "="') do set "%%i" -exit /b -:compareversion version1 version2 -:: https://stackoverflow.com/a/15809139 -:: Compares two version numbers and returns the result in the ERRORLEVEL -:: -:: Returns 1 if version1 > version2 -:: 0 if version1 = version2 -:: -1 if version1 < version2 -:: -:: The nodes must be delimited by . or , or - -:: -:: Nodes are normally strictly numeric, without a 0 prefix. A letter suffix -:: is treated as a separate node -setlocal enableDelayedExpansion -set "v1=%~1" -set "v2=%~2" -call :divideLetters v1 -call :divideLetters v2 -:loop -call :parseNode "%v1%" n1 v1 -call :parseNode "%v2%" n2 v2 -if %n1% gtr %n2% exit /b 1 -if %n1% lss %n2% exit /b -1 -if not defined v1 ( - if not defined v2 ( exit /b 0 ) -) -if not defined v1 ( exit /b -1 ) -if not defined v2 ( exit /b 1 ) -goto :loop - -:parseNode version nodeVar remainderVar -for /f "tokens=1* delims=.,-" %%A in ("%~1") do ( - set "%~2=%%A" - set "%~3=%%B" -) -exit /b - -:divideLetters versionVar -for %%C in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set "%~1=!%~1:%%C=.%%C!" exit /b diff --git a/setup-batch/uninstall_wufuc.bat b/setup-batch/uninstall_wufuc.bat index 0ad0626..9fbf457 100644 --- a/setup-batch/uninstall_wufuc.bat +++ b/setup-batch/uninstall_wufuc.bat @@ -40,23 +40,28 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( goto :die :is_x86 -set "WINDOWS_ARCHITECTURE=x86" set "wufuc_dll=%~dp0wufuc32.dll" goto :get_ver :is_x64 -set "WINDOWS_ARCHITECTURE=x64" set "wufuc_dll=%~dp0wufuc64.dll" :get_ver for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i" title wufuc uninstaller - v%Version% +:loop +if [%1]==[] goto :confirmation +if /I "%1"=="/UNATTENDED" goto :uninstall +shift +goto :loop + :confirmation set /p CONTINUE=Enter 'Y' if you want to uninstall wufuc: if /I not "%CONTINUE%"=="Y" goto :cancel echo. +:uninstall set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}" rundll32 "%wufuc_dll%",Rundll32Unload net start Schedule diff --git a/wufuc.sln b/wufuc.sln index 7c5eaf5..5bf4d49 100644 --- a/wufuc.sln +++ b/wufuc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.14 +VisualStudioVersion = 15.0.26730.15 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wufuc", "wufuc\wufuc.vcxproj", "{00F96695-CE41-4C2F-A344-6219DFB4F887}" EndProject @@ -44,4 +44,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5070ABC4-3344-4D6E-B744-E3508B10A327} + EndGlobalSection EndGlobal diff --git a/wufuc/callbacks.c b/wufuc/callbacks.c index 949a815..1a59c57 100644 --- a/wufuc/callbacks.c +++ b/wufuc/callbacks.c @@ -1,106 +1,55 @@ #include "callbacks.h" -#include "service.h" #include "iathook.h" #include "hooks.h" -#include "patchwua.h" #include "helpers.h" -#include "ntdllhelper.h" -#include "logging.h" +#include "service.h" +#include "tracing.h" -#include - -#define WIN32_NO_STATUS #include -#undef WIN32_NO_STATUS - -#include #include -#include #include -DWORD WINAPI ThreadProcCallback(LPVOID lpParam) { +DWORD WINAPI ThreadProcCallback(LPVOID *lpParam) { + OSVERSIONINFO osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); +#pragma warning(suppress : 4996) + if ( GetVersionEx(&osvi) ) + trace(_T("Windows version: %d.%d.%d (%zu-bit)"), osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, sizeof(uintptr_t) * 8); + else trace(_T("Failed to get Windows version (error code=%08X)"), GetLastError()); + + char brand[0x31]; + trace(_T("Processor: %hs"), get_cpuid_brand(brand, _countof(brand))); + + LPTSTR lpCommandLine = GetCommandLine(); TCHAR lpServiceCommandLine[0x8000]; - GetServiceCommandLine(NULL, _T("wuauserv"), lpServiceCommandLine, _countof(lpServiceCommandLine)); - if ( _tcsicmp(GetCommandLine(), lpServiceCommandLine) ) - return 0; + if ( GetServiceCommandLine(NULL, _T("wuauserv"), lpServiceCommandLine, _countof(lpServiceCommandLine)) + && !_tcsicmp(lpCommandLine, lpServiceCommandLine) ) { - SECURITY_ATTRIBUTES sa = { 0 }; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = FALSE; - if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:(A;;0x001F0003;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL) ) { - trace(_T("Failed to convert string security descriptor to security descriptor (error code=%08X)"), GetLastError()); - return 0; - } + SECURITY_ATTRIBUTES sa = { 0 }; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = FALSE; + if ( ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:(A;;0x001F0003;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL) ) { + HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent")); + if ( hEvent ) { + HANDLE threads[0x1000]; - HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent")); - if ( hEvent ) { - iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", (LPVOID)&fpLoadLibraryExW, LoadLibraryExW_hook); - - PVOID cookie; - NTSTATUS status; - if ( TryLdrRegisterDllNotification(0, (PLDR_DLL_NOTIFICATION_FUNCTION)LdrDllNotificationCallback, NULL, &cookie, &status) ) { - if ( NT_SUCCESS(status) ) { - trace(_T("Registered LdrDllNotificationCallback (status code=%d)"), status); - HMODULE hm = GetModuleHandleW(GetWindowsUpdateServiceDllW()); - if ( hm ) { - MODULEINFO modinfo; - if ( GetModuleInformation(GetCurrentProcess(), hm, &modinfo, sizeof(MODULEINFO)) ) - PatchWUA((void *)modinfo.lpBaseOfDll, (size_t)modinfo.SizeOfImage); - } + size_t count = suspend_other_threads(threads, _countof(threads)); + iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", (LPVOID)&pfnRegQueryValueExW, RegQueryValueExW_hook); + iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", (LPVOID)&pfnLoadLibraryExW, LoadLibraryExW_hook); + resume_and_close_threads(threads, count); WaitForSingleObject(hEvent, INFINITE); - trace(_T("Unload event was set")); + trace(_T("Unload event was set, removing hooks and unloading...")); - if ( cookie ) { - if ( TryLdrUnregisterDllNotification(cookie, &status) ) { - if ( NT_SUCCESS(status) ) - trace(_T("Unregistered LdrDllNotificationCallback (status code=%d)"), status); - else - trace(_T("Failed to unregister LdrDllNotificationCallback (status code=%d)"), status); - } else - trace(_T("Failed to get LdrUnregisterDllNotification proc address")); - } - } else - trace(_T("Failed to register LdrDllNotificationCallback (status code=%d)"), status); - } else - trace(_T("Failed to get LdrRegisterDllNotification proc address")); - - iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", NULL, fpLoadLibraryExW); - CloseHandle(hEvent); - } else { - trace(_T("Failed to create unload event (error code=%08X)"), GetLastError()); - return 0; - } + count = suspend_other_threads(threads, _countof(threads)); + iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", NULL, pfnLoadLibraryExW); + iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", NULL, pfnRegQueryValueExW); + resume_and_close_threads(threads, count); + CloseHandle(hEvent); + } else trace(_T("Failed to create unload event (error code=%08X)"), GetLastError()); + } else trace(_T("Failed to convert string security descriptor to security descriptor (error code=%08X)"), GetLastError()); + } else trace(_T("Current process command line is incorrect: %s != %s"), lpCommandLine, lpServiceCommandLine); trace(_T("Bye bye!")); FreeLibraryAndExitThread((HMODULE)lpParam, 0); } - -VOID CALLBACK LdrDllNotificationCallback(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) { - switch ( NotificationReason ) { - case LDR_DLL_NOTIFICATION_REASON_LOADED: - { - LDR_DLL_LOADED_NOTIFICATION_DATA data = NotificationData->Loaded; - - trace(_T("Loaded library: %wZ"), data.FullDllName); - - wchar_t buffer[MAX_PATH]; - wcscpy_s(buffer, _countof(buffer), (wchar_t *)GetWindowsUpdateServiceDllW()); - ApplyUpdatePack7R2ShimIfNeeded(buffer, _countof(buffer), buffer, _countof(buffer)); - - if ( !_wcsnicmp((wchar_t *)data.FullDllName->Buffer, buffer, (size_t)data.FullDllName->Length) ) - PatchWUA(data.DllBase, data.SizeOfImage); - return; - } - case LDR_DLL_NOTIFICATION_REASON_UNLOADED: - { - LDR_DLL_UNLOADED_NOTIFICATION_DATA data = NotificationData->Unloaded; - - trace(_T("Unloaded library: %wZ"), data.FullDllName); - return; - } - default: - return; - } -} - diff --git a/wufuc/callbacks.h b/wufuc/callbacks.h index 1d0f2e8..6c4a87a 100644 --- a/wufuc/callbacks.h +++ b/wufuc/callbacks.h @@ -1,11 +1,8 @@ -#ifndef CALLBACKS_H -#define CALLBACKS_H +#ifndef CALLBACKS_H_INCLUDED +#define CALLBACKS_H_INCLUDED #pragma once -#include "ntdllhelper.h" - #include -DWORD WINAPI ThreadProcCallback(LPVOID lpParam); -VOID CALLBACK LdrDllNotificationCallback(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context); +DWORD WINAPI ThreadProcCallback(LPVOID *lpParam); #endif diff --git a/wufuc/dllmain.c b/wufuc/dllmain.c index 2c8117c..09a2a41 100644 --- a/wufuc/dllmain.c +++ b/wufuc/dllmain.c @@ -1,28 +1,29 @@ #include "callbacks.h" #include "helpers.h" -#include "logging.h" +#include "ntdllhelper.h" +#include "tracing.h" -#include +#include BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch ( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: { - if ( !IsOperatingSystemSupported() || IsWow64() ) + if ( !IsOperatingSystemSupported() /*|| IsWow64()*/ ) return FALSE; - DisableThreadLibraryCalls(hModule); HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcCallback, (LPVOID)hModule, 0, NULL); CloseHandle(hThread); break; } case DLL_PROCESS_DETACH: - if ( !lpReserved ) - FreeNTDLL(); - FreeLogging(); + DeinitTracing(); break; - default: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: break; } return TRUE; } + + diff --git a/wufuc/helpers.c b/wufuc/helpers.c index 9ee9bca..433be17 100644 --- a/wufuc/helpers.c +++ b/wufuc/helpers.c @@ -1,12 +1,11 @@ #include "helpers.h" -#include "logging.h" +#include "tracing.h" #include #include #include -#include #include static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) { @@ -27,25 +26,23 @@ static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwM } BOOL IsWindows7(void) { - static BOOL m_checkedIsWindows7 = FALSE; - static BOOL m_isWindows7 = FALSE; + static BOOL checked = FALSE, isWindows7 = FALSE; - if ( !m_checkedIsWindows7 ) { - m_isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION); - m_checkedIsWindows7 = TRUE; + if ( !checked ) { + isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION); + checked = TRUE; } - return m_isWindows7; + return isWindows7; } BOOL IsWindows8Point1(void) { - static BOOL m_checkedIsWindows8Point1 = FALSE; - static BOOL m_isWindows8Point1 = FALSE; + static BOOL checked = FALSE, isWindows8Point1 = FALSE; - if ( !m_checkedIsWindows8Point1 ) { - m_isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION); - m_checkedIsWindows8Point1 = TRUE; + if ( !checked ) { + isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION); + checked = TRUE; } - return m_isWindows8Point1; + return isWindows8Point1; } BOOL IsOperatingSystemSupported(void) { @@ -57,64 +54,87 @@ BOOL IsOperatingSystemSupported(void) { } BOOL IsWow64(void) { - static BOOL m_checkedIsWow64 = FALSE; - static BOOL m_isWow64 = FALSE; - static ISWOW64PROCESS fpIsWow64Process = NULL; + static BOOL checked = FALSE, isWow64 = FALSE; + static ISWOW64PROCESS pfnIsWow64Process = NULL; - if ( !m_checkedIsWow64 ) { - if ( !fpIsWow64Process ) - fpIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process"); + if ( !checked ) { + if ( !pfnIsWow64Process ) + pfnIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process"); - if ( fpIsWow64Process && fpIsWow64Process(GetCurrentProcess(), &m_isWow64) ) - m_checkedIsWow64 = TRUE; + if ( pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &isWow64) ) + checked = TRUE; } - return m_isWow64; + return isWow64; } -void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb) { - DWORD dwProcessId = GetCurrentProcessId(); - DWORD dwThreadId = GetCurrentThreadId(); - +size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount) { HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); THREADENTRY32 te = { 0 }; te.dwSize = sizeof(te); - Thread32First(hSnap, &te); - size_t count = 0; - do { - if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId ) - continue; + if ( Thread32First(hSnap, &te) ) { + DWORD dwProcessId = GetCurrentProcessId(); + DWORD dwThreadId = GetCurrentThreadId(); + WaitForTracingMutex(); // make sure we don't dead lock + do { + if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId ) + continue; - lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID); - SuspendThread(lphThreads[count]); - count++; - } while ( count < *lpcb && Thread32Next(hSnap, &te) ); + lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID); + SuspendThread(lphThreads[count]); + count++; + } while ( count < nMaxCount && Thread32Next(hSnap, &te) ); + ReleaseTracingMutex(); + } CloseHandle(hSnap); - *lpcb = count; - trace(_T("Suspended %d other threads"), count); + trace(_T("Suspended %zu other threads"), count); + return count; } -void resume_and_close_threads(LPHANDLE lphThreads, size_t cb) { - for ( size_t i = 0; i < cb; i++ ) { +void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount) { + for ( size_t i = 0; i < nCount; i++ ) { ResumeThread(lphThreads[i]); CloseHandle(lphThreads[i]); } - trace(_T("Resumed %d threads"), cb); + trace(_T("Resumed %zu threads"), nCount); } -void get_cpuid_brand(char *brand) { +char *get_cpuid_brand(char *brand, size_t nMaxCount) { int info[4]; __cpuidex(info, 0x80000000, 0); if ( info[0] < 0x80000004 ) { brand[0] = '\0'; - return; + return brand; } uint32_t *char_as_int = (uint32_t *)brand; for ( int op = 0x80000002; op <= 0x80000004; op++ ) { __cpuidex(info, op, 0); - *(char_as_int++) = info[0]; - *(char_as_int++) = info[1]; - *(char_as_int++) = info[2]; - *(char_as_int++) = info[3]; + for ( int i = 0; i < 4; i++ ) + *(char_as_int++) = info[i]; } + size_t i = 0; + while ( i < nMaxCount && isspace(brand[i]) ) + i++; + + return brand + i; +} + +wchar_t *find_fname(wchar_t *pPath) { + wchar_t *pwc = wcsrchr(pPath, L'\\'); + if ( pwc && *(++pwc) ) + return pwc; + + return pPath; +} + +int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2) { + if ( ma1 < ma2 ) return -1; + if ( ma1 > ma2 ) return 1; + if ( mi1 < mi2 ) return -1; + if ( mi1 > mi2 ) return 1; + if ( b1 < b2 ) return -1; + if ( b1 > b2 ) return 1; + if ( r1 < r2 ) return -1; + if ( r1 > r2 ) return 1; + return 0; } diff --git a/wufuc/helpers.h b/wufuc/helpers.h index 243952e..2a8d8d8 100644 --- a/wufuc/helpers.h +++ b/wufuc/helpers.h @@ -1,5 +1,5 @@ -#ifndef HELPERS_H -#define HELPERS_H +#ifndef HELPERS_H_INCLUDED +#define HELPERS_H_INCLUDED #pragma once #include @@ -11,11 +11,10 @@ BOOL IsWindows8Point1(void); BOOL IsOperatingSystemSupported(void); BOOL IsWow64(void); -void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb); -void resume_and_close_threads(LPHANDLE lphThreads, size_t cb); +size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount); +void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount); -void get_cpuid_brand(char *brand); - -#define STRINGIZE_(x) #x -#define STRINGIZE(x) STRINGIZE_(x) +char *get_cpuid_brand(char *brand, size_t nMaxCount); +wchar_t *find_fname(wchar_t *pPath); +int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2); #endif diff --git a/wufuc/hooks.c b/wufuc/hooks.c index bce0738..bb2f75d 100644 --- a/wufuc/hooks.c +++ b/wufuc/hooks.c @@ -1,67 +1,121 @@ #include "hooks.h" -#include "service.h" #include "helpers.h" -//#include "ntdllhelper.h" -#include "logging.h" +#include "patchwua.h" +#include "ntdllhelper.h" +#include "tracing.h" #include -//#define WIN32_NO_STATUS +#define WIN32_NO_STATUS #include -//#undef WIN32_NO_STATUS +#undef WIN32_NO_STATUS -//#include -//#include +#include #include #include -//REGQUERYVALUEEXW fpRegQueryValueExW = NULL; -LOADLIBRARYEXW fpLoadLibraryExW = NULL; +REGQUERYVALUEEXW pfnRegQueryValueExW = NULL; +LOADLIBRARYEXW pfnLoadLibraryExW = NULL; -//LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { -// static NTQUERYKEY fpNtQueryKey = NULL; -// -// DWORD cbData = *lpcbData; -// -// LRESULT result = fpRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); -// if ( !result && lpData && !_wcsicmp((const wchar_t *)lpValueName, L"ServiceDll") ) { -// if ( InitNTDLL() ) { -// if ( !fpNtQueryKey ) -// fpNtQueryKey = (NTQUERYKEY)GetProcAddress(g_hNTDLL, "NtQueryKey"); -// -// if ( fpNtQueryKey ) { -// ULONG ResultLength; -// NTSTATUS status = fpNtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength); -// if ( status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL ) { -// PVOID buffer = malloc(ResultLength); -// if ( NT_SUCCESS(fpNtQueryKey((HANDLE)hKey, KeyNameInformation, buffer, ResultLength, &ResultLength)) -// && !_wcsnicmp(buffer, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\services\\wuauserv", (size_t)ResultLength) ) { -// -// wchar_t path[MAX_PATH], newpath[MAX_PATH]; -// wcsncpy_s(path, _countof(path), (wchar_t *)lpData, (rsize_t)*lpcbData); -// -// if ( ApplyUpdatePack7R2ShimIfNeeded(path, _countof(path), newpath, _countof(newpath)) ) { -// trace(_T("UpdatePack7R2 shim: \"%ls\" -> \"%ls\""), path, newpath); -// wcscpy_s((wchar_t *)lpData, (rsize_t)cbData, newpath); -// } -// } -// free(buffer); -// } -// } -// } -// } -// return result; -//} +LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { + size_t nMaxCount = *lpcbData / sizeof(wchar_t); + + LRESULT result = pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); + + NTSTATUS status; + ULONG ResultLength; + if ( !_wcsicmp(lpValueName, L"ServiceDll") + && TryNtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength, &status) + && (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL) ) { + + PKEY_NAME_INFORMATION pkni = malloc(ResultLength); + if ( TryNtQueryKey((HANDLE)hKey, KeyNameInformation, (PVOID)pkni, ResultLength, &ResultLength, &status) + && NT_SUCCESS(status) ) { + + size_t nBufferCount = pkni->NameLength / sizeof(wchar_t); + int current, pos; + if ( _snwscanf_s(pkni->Name, nBufferCount, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet%03d\\services\\wuauserv\\Parameters%n", ¤t, &pos) == 1 + && pos == nBufferCount ) { + + size_t nCount = nMaxCount + 1; + wchar_t *path = calloc(nCount, sizeof(wchar_t)); + wcsncpy_s(path, nCount, (wchar_t *)lpData, *lpcbData / sizeof(wchar_t)); + + wchar_t *fname = find_fname(path); + if ( !_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2 + || !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix + || !_wcsicmp(fname, L"WuaCpuFix.dll") ) { + + wcscpy_s(fname, nMaxCount - (fname - path), L"wuaueng.dll"); + + DWORD nSize = ExpandEnvironmentStringsW(path, NULL, 0); + wchar_t *lpDst = calloc(nSize, sizeof(wchar_t)); + ExpandEnvironmentStringsW(path, lpDst, nSize); + if ( GetFileAttributesW(lpDst) != INVALID_FILE_ATTRIBUTES ) { + trace(_T("Compatibility fix: %.*ls -> %ls"), *lpcbData / sizeof(wchar_t), (wchar_t *)lpData, path); + size_t nLength = wcsnlen_s(path, nMaxCount); + wcsncpy_s((wchar_t *)lpData, nMaxCount, path, nLength); + *lpcbData = (DWORD)(nLength * sizeof(wchar_t)); + } + free(lpDst); + } + free(path); + } + } + free(pkni); + } + return result; +} HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) { - wchar_t buffer[MAX_PATH]; - wcscpy_s(buffer, _countof(buffer), lpFileName); + HMODULE result = pfnLoadLibraryExW(lpFileName, hFile, dwFlags); + trace(_T("Loaded library: %ls"), lpFileName); - if ( !_wcsicmp(buffer, GetWindowsUpdateServiceDllW()) - && ApplyUpdatePack7R2ShimIfNeeded(buffer, _countof(buffer), buffer, _countof(buffer)) ) { - trace(_T("UpdatePack7R2 shim: %ls -> %ls"), lpFileName, buffer); + DWORD dwLen = GetFileVersionInfoSizeW(lpFileName, NULL); + if ( dwLen ) { + LPVOID pBlock = malloc(dwLen); + if ( GetFileVersionInfoW(lpFileName, 0, dwLen, pBlock) ) { + PLANGANDCODEPAGE ptl; + UINT cb; + if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) ) { + wchar_t lpSubBlock[38]; + for ( size_t i = 0; i < (cb / sizeof(LANGANDCODEPAGE)); i++ ) { + swprintf_s(lpSubBlock, _countof(lpSubBlock), L"\\StringFileInfo\\%04x%04x\\InternalName", ptl[i].wLanguage, ptl[i].wCodePage); + wchar_t *lpszInternalName; + UINT uLen; + if ( VerQueryValueW(pBlock, lpSubBlock, (LPVOID *)&lpszInternalName, &uLen) + && !_wcsicmp(lpszInternalName, L"wuaueng.dll") ) { + + VS_FIXEDFILEINFO *pffi; + VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen); + WORD wMajor = HIWORD(pffi->dwProductVersionMS); + WORD wMinor = LOWORD(pffi->dwProductVersionMS); + WORD wBuild = HIWORD(pffi->dwProductVersionLS); + WORD wRevision = LOWORD(pffi->dwProductVersionLS); + + TCHAR fname[MAX_PATH]; + GetModuleBaseName(GetCurrentProcess(), result, fname, _countof(fname)); + + if ( (IsWindows7() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 6, 7601, 23714) != -1) + || (IsWindows8Point1() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 9, 9600, 18621) != -1) ) { + + trace(_T("%s version: %d.%d.%d.%d"), fname, wMajor, wMinor, wBuild, wRevision); + MODULEINFO modinfo; + if ( GetModuleInformation(GetCurrentProcess(), result, &modinfo, sizeof(MODULEINFO)) ) { + if ( PatchWUA(modinfo.lpBaseOfDll, modinfo.SizeOfImage) ) + trace(_T("Successfully patched %s!"), fname); + else trace(_T("Failed to patch %s!"), fname); + } + + else trace(_T("Failed to get module information for %s (%p) (couldn't patch)"), fname, result); + } else trace(_T("Unsupported version of %s: %d.%d.%d.%d (patching skipped)"), fname, wMajor, wMinor, wBuild, wRevision); + break; + } + } + } + } + free(pBlock); } - - return fpLoadLibraryExW((LPWSTR)buffer, hFile, dwFlags); + return result; } diff --git a/wufuc/hooks.h b/wufuc/hooks.h index 1dbc519..7ec294b 100644 --- a/wufuc/hooks.h +++ b/wufuc/hooks.h @@ -1,33 +1,23 @@ -#ifndef HOOKS_H -#define HOOKS_H +#ifndef HOOKS_H_INCLUDED +#define HOOKS_H_INCLUDED #pragma once -//#define WIN32_NO_STATUS +#define WIN32_NO_STATUS #include -//#undef WIN32_NO_STATUS +#undef WIN32_NO_STATUS -//typedef enum _KEY_INFORMATION_CLASS { -// KeyBasicInformation = 0, -// KeyNodeInformation = 1, -// KeyFullInformation = 2, -// KeyNameInformation = 3, -// KeyCachedInformation = 4, -// KeyFlagsInformation = 5, -// KeyVirtualizationInformation = 6, -// KeyHandleTagsInformation = 7, -// MaxKeyInfoClass = 8 -//} KEY_INFORMATION_CLASS; -// -//typedef NTSTATUS(NTAPI *NTQUERYKEY)(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG); -// -//typedef LRESULT(WINAPI *REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); +typedef struct tagLANGANDCODEPAGE { + WORD wLanguage; + WORD wCodePage; +} LANGANDCODEPAGE, *PLANGANDCODEPAGE; + +typedef LRESULT(WINAPI *REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); typedef HMODULE(WINAPI *LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); -//extern REGQUERYVALUEEXW fpRegQueryValueExW; -extern LOADLIBRARYEXW fpLoadLibraryExW; +extern REGQUERYVALUEEXW pfnRegQueryValueExW; +extern LOADLIBRARYEXW pfnLoadLibraryExW; -LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); - -HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags); +LRESULT 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); #endif diff --git a/wufuc/iathook.c b/wufuc/iathook.c index f99ad3e..6188bb0 100644 --- a/wufuc/iathook.c +++ b/wufuc/iathook.c @@ -1,6 +1,6 @@ #include "iathook.h" -#include "logging.h" +#include "tracing.h" #include #include @@ -32,10 +32,11 @@ void iat_hook(HMODULE hModule, LPCSTR lpFuncName, LPVOID *lpOldAddress, LPVOID l trace(_T("Modified IAT: hModule=%p, Name=%hs, OldAddress=%p, NewAddress=%p"), hModule, lpFuncName, *lpAddress, lpNewAddress); DWORD flOldProtect; - DWORD flNewProtect = PAGE_READWRITE; - VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect); - if ( lpOldAddress ) - *lpOldAddress = *lpAddress; - *lpAddress = lpNewAddress; - VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect); + if ( VirtualProtect(lpAddress, sizeof(LPVOID), PAGE_READWRITE, &flOldProtect) ) { + if ( lpOldAddress ) + *lpOldAddress = *lpAddress; + *lpAddress = lpNewAddress; + if ( !VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flOldProtect) ) + trace(_T("Failed to restore memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError()); + } else trace(_T("Failed to change memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError()); } diff --git a/wufuc/iathook.h b/wufuc/iathook.h index 3c564ed..0509d55 100644 --- a/wufuc/iathook.h +++ b/wufuc/iathook.h @@ -1,5 +1,5 @@ -#ifndef IATHOOK_H -#define IATHOOK_H +#ifndef IATHOOK_H_INCLUDED +#define IATHOOK_H_INCLUDED #pragma once #include diff --git a/wufuc/logging.c b/wufuc/logging.c deleted file mode 100644 index 7e65a6c..0000000 --- a/wufuc/logging.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "logging.h" - -#include -#include - -#include -#include -#include - -static FILE *fp; -static BOOL logging_enabled = FALSE; - -BOOL InitLogging(void) { - if ( fp ) - return TRUE; - - TCHAR filename[MAX_PATH]; - GetModuleFileName(HINST_THISCOMPONENT, filename, _countof(filename)); - - TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME]; - _tsplitpath_s(filename, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), NULL, 0); - - TCHAR basename[MAX_PATH]; - GetModuleBaseNameW(GetCurrentProcess(), NULL, basename, _countof(basename)); - _tcscat_s(fname, _countof(fname), _T(".")); - _tcscat_s(fname, _countof(fname), basename); - _tmakepath_s(filename, _countof(filename), drive, dir, fname, _T(".log")); - - HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - LARGE_INTEGER size; - GetFileSizeEx(hFile, &size); - CloseHandle(hFile); - fp = _tfsopen(filename, size.QuadPart < (1 << 20) ? _T("at") : _T("wt"), _SH_DENYWR); - return (fp != NULL); -} - -void trace_(LPCTSTR format, ...) { - static DWORD dwProcessId = 0; - - if ( InitLogging() ) { - if ( !dwProcessId ) - dwProcessId = GetCurrentProcessId(); - - TCHAR datebuf[9], timebuf[9]; - _tstrdate_s(datebuf, _countof(datebuf)); - _tstrtime_s(timebuf, _countof(timebuf)); - _ftprintf_s(fp, _T("%s %s [%d] "), datebuf, timebuf, dwProcessId); - - va_list argptr; - va_start(argptr, format); - _vftprintf_s(fp, format, argptr); - va_end(argptr); - fflush(fp); - } -} - -BOOL FreeLogging(void) { - return fp && !fclose(fp); -} diff --git a/wufuc/logging.h b/wufuc/logging.h deleted file mode 100644 index 0107e54..0000000 --- a/wufuc/logging.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LOGGING_H -#define LOGGING_H -#pragma once - -#include -#include - -extern IMAGE_DOS_HEADER __ImageBase; -#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) - -BOOL InitLogging(void); -void trace_(LPCTSTR format, ...); -BOOL FreeLogging(void); - -#define STRINGIZE_(x) #x -#define STRINGIZE(x) STRINGIZE_(x) - -#define __LINESTR__ STRINGIZE(__LINE__) -#define trace(format, ...) trace_(_T(__FILE__) _T(":") _T(__LINESTR__) _T("(") _T(__FUNCTION__) _T("): ") format _T("\n"), ##__VA_ARGS__) -#endif diff --git a/wufuc/ntdllhelper.c b/wufuc/ntdllhelper.c index ceb5357..1c03e37 100644 --- a/wufuc/ntdllhelper.c +++ b/wufuc/ntdllhelper.c @@ -7,48 +7,23 @@ #include #include -HMODULE g_hNTDLL = NULL; +static HMODULE g_hNTDLL = NULL; -BOOL InitNTDLL(void) { +static BOOL InitNTDLL(void) { if ( !g_hNTDLL ) - g_hNTDLL = LoadLibrary(_T("ntdll")); - return (g_hNTDLL != NULL); + g_hNTDLL = GetModuleHandle(_T("ntdll")); + return !!g_hNTDLL; } -BOOL FreeNTDLL(void) { - if ( g_hNTDLL ) { - BOOL result = FreeLibrary(g_hNTDLL); - if ( result ) - g_hNTDLL = NULL; - return result; - } - return FALSE; -} - -BOOL TryLdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID *Cookie, NTSTATUS *result) { - static LDRREGISTERDLLNOTIFICATION fpLdrRegisterDllNotification = NULL; +BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status) { + static NTQUERYKEY pfnNtQueryKey = NULL; if ( InitNTDLL() ) { - if ( !fpLdrRegisterDllNotification ) - fpLdrRegisterDllNotification = (LDRREGISTERDLLNOTIFICATION)GetProcAddress(g_hNTDLL, "LdrRegisterDllNotification"); - - if ( fpLdrRegisterDllNotification ) { - *result = fpLdrRegisterDllNotification(Flags, NotificationFunction, Context, Cookie); - return TRUE; - } - } - return FALSE; -} - -BOOL TryLdrUnregisterDllNotification(PVOID Cookie, NTSTATUS *result) { - static LDRUNREGISTERDLLNOTIFICATION fpLdrUnregisterDllNotification = NULL; - - if ( InitNTDLL() ) { - if ( !fpLdrUnregisterDllNotification ) - fpLdrUnregisterDllNotification = (LDRUNREGISTERDLLNOTIFICATION)GetProcAddress(g_hNTDLL, "LdrUnregisterDllNotification"); - - if ( fpLdrUnregisterDllNotification ) { - *result = fpLdrUnregisterDllNotification(Cookie); + if ( !pfnNtQueryKey ) + pfnNtQueryKey = (NTQUERYKEY)GetProcAddress(g_hNTDLL, "NtQueryKey"); + + if ( pfnNtQueryKey ) { + *status = pfnNtQueryKey(KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength); return TRUE; } } diff --git a/wufuc/ntdllhelper.h b/wufuc/ntdllhelper.h index cf76f43..e0a6a58 100644 --- a/wufuc/ntdllhelper.h +++ b/wufuc/ntdllhelper.h @@ -1,5 +1,5 @@ -#ifndef NTDLLHELPER_H -#define NTDLLHELPER_H +#ifndef NTDLLHELPER_H_INCLUDED +#define NTDLLHELPER_H_INCLUDED #pragma once #define WIN32_NO_STATUS @@ -8,42 +8,24 @@ #include -typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA { - ULONG Flags; - PUNICODE_STRING FullDllName; - PUNICODE_STRING BaseDllName; - PVOID DllBase; - ULONG SizeOfImage; -} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA; +typedef enum tagKEY_INFORMATION_CLASS { + KeyBasicInformation = 0, + KeyNodeInformation = 1, + KeyFullInformation = 2, + KeyNameInformation = 3, + KeyCachedInformation = 4, + KeyFlagsInformation = 5, + KeyVirtualizationInformation = 6, + KeyHandleTagsInformation = 7, + MaxKeyInfoClass = 8 +} KEY_INFORMATION_CLASS; -typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA { - ULONG Flags; - PCUNICODE_STRING FullDllName; - PCUNICODE_STRING BaseDllName; - PVOID DllBase; - ULONG SizeOfImage; -} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA; +typedef struct tagKEY_NAME_INFORMATION { + ULONG NameLength; + WCHAR Name[1]; +} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION; -typedef union _LDR_DLL_NOTIFICATION_DATA { - LDR_DLL_LOADED_NOTIFICATION_DATA Loaded; - LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded; -} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA; -typedef const LDR_DLL_NOTIFICATION_DATA *PCLDR_DLL_NOTIFICATION_DATA; +typedef NTSTATUS(NTAPI *NTQUERYKEY)(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG); -typedef VOID(CALLBACK *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG, PCLDR_DLL_NOTIFICATION_DATA, PVOID); - -#define LDR_DLL_NOTIFICATION_REASON_LOADED 1 -#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2 - -typedef NTSTATUS(NTAPI *LDRREGISTERDLLNOTIFICATION)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, PVOID, PVOID *); -typedef NTSTATUS(NTAPI *LDRUNREGISTERDLLNOTIFICATION)(PVOID); - -extern HMODULE g_hNTDLL; - -BOOL InitNTDLL(void); - -BOOL FreeNTDLL(void); - -BOOL TryLdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID *Cookie, NTSTATUS *result); -BOOL TryLdrUnregisterDllNotification(PVOID Cookie, NTSTATUS *result); +BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status); #endif diff --git a/wufuc/patchwua.c b/wufuc/patchwua.c index d8e3572..655b131 100644 --- a/wufuc/patchwua.c +++ b/wufuc/patchwua.c @@ -2,7 +2,7 @@ #include "helpers.h" #include "patternfind.h" -#include "logging.h" +#include "tracing.h" #include @@ -10,60 +10,61 @@ #include #include - BOOL PatchWUA(void *lpBaseOfDll, size_t SizeOfImage) { char *pattern; - size_t offset00, offset01; + size_t offset1, offset2; #ifdef _AMD64_ pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"; - offset00 = 10; - offset01 = 18; + offset1 = 10; + offset2 = 18; #elif defined(_X86_) if ( IsWindows7() ) { pattern = "833D????????00 743E E8???????? A3????????"; - offset00 = 2; - offset01 = 15; + offset1 = 2; + offset2 = 15; } else if ( IsWindows8Point1() ) { pattern = "8BFF 51 833D????????00 7507 A1????????"; - offset00 = 5; - offset01 = 13; + offset1 = 5; + offset2 = 13; } #endif unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, 0, pattern); if ( !ptr ) { - trace(_T("No pattern match!")); + trace(_T("No pattern match! (couldn't patch)")); return FALSE; } - trace(_T("wuaueng!IsDeviceServiceable VA: %p"), ptr); - BOOL result = FALSE; - LPBOOL lpbFirstRun, lpbIsCPUSupportedResult; + TCHAR fname[MAX_PATH]; + GetModuleBaseName(GetCurrentProcess(), (HMODULE)lpBaseOfDll, fname, _countof(fname)); + trace(_T("Matched pattern for IsDeviceServiceable at %s+0x%zx"), fname, + (size_t)((uintptr_t)ptr - (uintptr_t)lpBaseOfDll)); + LPBOOL lpb1, lpb2; #ifdef _AMD64_ - lpbFirstRun = (LPBOOL)(ptr + offset00 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset00)); - lpbIsCPUSupportedResult = (LPBOOL)(ptr + offset01 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset01)); + lpb1 = (LPBOOL)(ptr + offset1 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset1)); + lpb2 = (LPBOOL)(ptr + offset2 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset2)); #elif defined(_X86_) - lpbFirstRun = (LPBOOL)(*(uintptr_t *)(ptr + offset00)); - lpbIsCPUSupportedResult = (LPBOOL)(*(uintptr_t *)(ptr + offset01)); + lpb1 = (LPBOOL)(*(uintptr_t *)(ptr + offset1)); + lpb2 = (LPBOOL)(*(uintptr_t *)(ptr + offset2)); #endif + offset1 = (size_t)((uintptr_t)lpb1 - (uintptr_t)lpBaseOfDll); + offset2 = (size_t)((uintptr_t)lpb2 - (uintptr_t)lpBaseOfDll); - DWORD flNewProtect = PAGE_READWRITE; DWORD flOldProtect; - if ( *lpbFirstRun ) { - VirtualProtect(lpbFirstRun, sizeof(BOOL), flNewProtect, &flOldProtect); - *lpbFirstRun = FALSE; - VirtualProtect(lpbFirstRun, sizeof(BOOL), flOldProtect, &flNewProtect); - trace(_T("Patched boolean value #1: %p = %s"), lpbFirstRun, *lpbFirstRun ? L"TRUE" : L"FALSE"); - result = TRUE; + if ( *lpb1 ) { + if ( VirtualProtect(lpb1, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) { + *lpb1 = FALSE; + trace(_T("Patched value #1 at %s+0x%zx: %08x"), fname, offset1, *lpb1); + if ( !VirtualProtect(lpb1, sizeof(BOOL), flOldProtect, &flOldProtect) ) + trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError()); + } else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError()); } - if ( !*lpbIsCPUSupportedResult ) { - VirtualProtect(lpbIsCPUSupportedResult, sizeof(BOOL), flNewProtect, &flOldProtect); - *lpbIsCPUSupportedResult = TRUE; - VirtualProtect(lpbIsCPUSupportedResult, sizeof(BOOL), flOldProtect, &flNewProtect); - trace(_T("Patched boolean value #2: %p = %s"), lpbIsCPUSupportedResult, *lpbIsCPUSupportedResult ? L"TRUE" : L"FALSE"); - result = TRUE; + if ( !*lpb2 ) { + if ( VirtualProtect(lpb2, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) { + *lpb2 = TRUE; + trace(_T("Patched value #2 at %s+0x%zx: %08x"), fname, offset2, *lpb2); + if ( !VirtualProtect(lpb2, sizeof(BOOL), flOldProtect, &flOldProtect) ) + trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError()); + } else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError()); } - if ( result ) - trace(_T("Successfully patched WUA module!")); - - return result; + return !*lpb1 && *lpb2; } diff --git a/wufuc/patchwua.h b/wufuc/patchwua.h index 145182e..451b4f9 100644 --- a/wufuc/patchwua.h +++ b/wufuc/patchwua.h @@ -1,5 +1,5 @@ -#ifndef PATCHWUA_H -#define PATCHWUA_H +#ifndef PATCHWUA_H_INCLUDED +#define PATCHWUA_H_INCLUDED #pragma once #include diff --git a/wufuc/patternfind.c b/wufuc/patternfind.c index 6b3b558..32b2c2a 100644 --- a/wufuc/patternfind.c +++ b/wufuc/patternfind.c @@ -2,8 +2,9 @@ #include -/* Ported to C from x64dbg's patternfind.cpp: +/* Ported to Win32 C from x64dbg's patternfind.cpp: * https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp + * * x64dbg license (GPL-3.0): * https://github.com/x64dbg/x64dbg/blob/development/LICENSE */ @@ -34,7 +35,7 @@ static size_t formathexpattern(const char *patterntext, char *formattext, size_t return result; } -static BOOL patterntransform(const char *patterntext, LPPATTERNBYTE pattern, size_t *patternsize) { +static BOOL patterntransform(const char *patterntext, PPATTERNBYTE pattern, size_t *patternsize) { size_t cb = formathexpattern(patterntext, NULL, 0); if ( !cb || cb > *patternsize ) return FALSE; @@ -60,7 +61,7 @@ static BOOL patterntransform(const char *patterntext, LPPATTERNBYTE pattern, siz return TRUE; } -static void patternwritebyte(unsigned char *byte, LPPATTERNBYTE pbyte) { +static void patternwritebyte(unsigned char *byte, PPATTERNBYTE pbyte) { unsigned char n1 = (*byte >> 4) & 0xf; unsigned char n2 = *byte & 0xf; if ( !pbyte->nibble[0].wildcard ) @@ -77,12 +78,10 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte writepatternsize = datasize; BOOL result = FALSE; - LPPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE)); + PPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE)); if ( patterntransform(pattern, writepattern, &writepatternsize) ) { - DWORD flNewProtect = PAGE_READWRITE; DWORD flOldProtect; - - if ( result = VirtualProtect(data, writepatternsize, flNewProtect, &flOldProtect) ) { + if ( result = VirtualProtect(data, writepatternsize, PAGE_READWRITE, &flOldProtect) ) { for ( size_t i = 0; i < writepatternsize; i++ ) { BYTE n1 = (data[i] >> 4) & 0xf; BYTE n2 = data[i] & 0xf; @@ -92,7 +91,7 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte if ( !writepattern[i].nibble[1].wildcard ) n2 = writepattern[i].nibble[1].data; data[i] = ((n1 << 4) & 0xf0) | (n2 & 0xf); - result = VirtualProtect(data, writepatternsize, flOldProtect, &flNewProtect); + result = VirtualProtect(data, writepatternsize, flOldProtect, &flOldProtect); } } } @@ -103,7 +102,7 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern) { unsigned char *result = NULL; size_t searchpatternsize = strlen(pattern); - LPPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE)); + PPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE)); if ( patterntransform(pattern, searchpattern, &searchpatternsize) ) { for ( size_t i = startindex, j = 0; i < datasize; i++ ) { //search for the pattern diff --git a/wufuc/patternfind.h b/wufuc/patternfind.h index 6826b37..c6c4e70 100644 --- a/wufuc/patternfind.h +++ b/wufuc/patternfind.h @@ -1,15 +1,15 @@ -#ifndef PATTERNFIND_H -#define PATTERNFIND_H +#ifndef PATTERNFIND_H_INCLUDED +#define PATTERNFIND_H_INCLUDED #pragma once #include -typedef struct _PATTERNBYTE { - struct _PATTERNNIBBLE { +typedef struct tagPATTERNBYTE { + struct tagPATTERNNIBBLE { unsigned char data; BOOL wildcard; } nibble[2]; -} PATTERNBYTE, *PPATTERNBYTE, *LPPATTERNBYTE; +} PATTERNBYTE, *PPATTERNBYTE; unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern); unsigned char *patternsnr(unsigned char *data, size_t datasize, size_t startindex, const char *searchpattern, const char *replacepattern); diff --git a/wufuc/rundll32.c b/wufuc/rundll32.c index fb05de9..6a2ea8b 100644 --- a/wufuc/rundll32.c +++ b/wufuc/rundll32.c @@ -1,77 +1,8 @@ #include "service.h" -#include "helpers.h" -#include "logging.h" +#include "tracing.h" #include #include -#include -#include - -void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { - HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent")); - if ( hEvent ) { - CloseHandle(hEvent); - return; - } - - wchar_t *osname; - if ( IsWindows7() ) { - if ( IsWindowsServer() ) - osname = _T("Windows Server 2008 R2"); - else - osname = _T("Windows 7"); - } else if ( IsWindows8Point1() ) { - if ( IsWindowsServer() ) - osname = _T("Windows Server 2012 R2"); - else - osname = _T("Windows 8.1"); - } - trace(_T("Operating System: %s %d-bit"), osname, sizeof(uintptr_t) * 8); - - char brand[0x31]; - get_cpuid_brand(brand); - size_t i = 0; - while ( i < _countof(brand) && isspace(brand[i]) ) - i++; - - trace(_T("Processor: %hs"), brand + i); - - SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); - if ( !hSCManager ) - return; - - TCHAR lpGroupName[256]; - DWORD dwProcessId; - BOOL result = GetServiceProcessId(hSCManager, _T("wuauserv"), &dwProcessId); - if ( !result && GetServiceGroupName(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName)) ) - result = GetServiceGroupProcessId(hSCManager, lpGroupName, &dwProcessId); - - CloseServiceHandle(hSCManager); - if ( !result ) - return; - - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); - if ( !hProcess ) - return; - - TCHAR lpLibFileName[MAX_PATH]; - GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName)); - SIZE_T size = (SIZE_T)((_tcslen(lpLibFileName) + 1) * sizeof(TCHAR)); - LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - - if ( lpBaseAddress && WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, size, NULL) ) { - HANDLE hThread = CreateRemoteThread( - hProcess, NULL, 0, - (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), STRINGIZE(LoadLibrary)), - lpBaseAddress, 0, NULL - ); - WaitForSingleObject(hThread, INFINITE); - trace(_T("Injected into process: %d"), dwProcessId); - CloseHandle(hThread); - } - VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE); - CloseHandle(hProcess); -} void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent")); diff --git a/wufuc/service.c b/wufuc/service.c index 9b3e301..9244f54 100644 --- a/wufuc/service.c +++ b/wufuc/service.c @@ -1,128 +1,9 @@ #include "service.h" -#include - #include #include -#include "helpers.h" -#include "shellapihelper.h" -#include "logging.h" - -static BOOL OpenServiceParametersKey(LPCWSTR lpSubKey, PHKEY phkResult) { - BOOL result = FALSE; - HKEY hKey, hSubKey; - if ( !RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services", 0, KEY_READ, &hKey) - && !RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, &hSubKey) - && !RegOpenKeyExW(hSubKey, L"Parameters", 0, KEY_READ, phkResult) ) { - - result = TRUE; - } - if ( hKey ) - RegCloseKey(hKey); - - if ( hSubKey ) - RegCloseKey(hSubKey); - return result; -} - -BOOL FindServiceDllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize) { - BOOL result = FALSE; - HKEY hKey; - if ( OpenServiceParametersKey(lpServiceName, &hKey) ) { - DWORD cb = dwSize; - if ( !RegGetValueW(hKey, NULL, L"ServiceDll", RRF_RT_REG_SZ, NULL, lpServiceDll, &cb) ) { - trace(_T("Service \"%s\" DLL path: %ls"), lpServiceName, lpServiceDll); - result = TRUE; - } - RegCloseKey(hKey); - } - return result; -} - -LPWSTR GetWindowsUpdateServiceDllW(void) { - static WCHAR path[MAX_PATH]; - - if ( !path[0] ) { - if ( !FindServiceDllW(L"wuauserv", path, _countof(path)) ) - path[0] = L'\0'; - } - - return path; -} - -BOOL ApplyUpdatePack7R2ShimIfNeeded(const wchar_t *path, size_t pathsize, wchar_t *newpath, size_t newpathsize) { - wchar_t drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; - _wsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), ext, _countof(ext)); - if ( !_wcsicmp(fname, L"wuaueng2") ) { - _wmakepath_s(newpath, newpathsize, drive, dir, L"wuaueng", ext); - return GetFileAttributesW(newpath) != INVALID_FILE_ATTRIBUTES; - } - return FALSE; -} - -BOOL GetServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPDWORD lpdwProcessId) { - BOOL result = FALSE; - BOOL selfclose = !hSCManager; - if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) ) - return result; - - SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS); - - if ( selfclose ) - CloseServiceHandle(hSCManager); - - if ( !hService ) - return result; - - SERVICE_STATUS_PROCESS buffer; - DWORD cb; - if ( QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&buffer, sizeof(buffer), &cb) - && buffer.dwProcessId ) { - - *lpdwProcessId = buffer.dwProcessId; - trace(_T("Service \"%s\" process ID: %d"), lpServiceName, *lpdwProcessId); - result = TRUE; - } - CloseServiceHandle(hService); - return result; -} - -BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) { - BOOL result = FALSE; - BOOL selfclose = !hSCManager; - if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) ) - return result; - - TCHAR lpBinaryPathName[0x8000]; - if ( !GetServiceCommandLine(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName)) ) - return result; - - if ( selfclose ) - CloseServiceHandle(hSCManager); - - int numArgs; - LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs); - if ( numArgs < 3 ) - return result; - - TCHAR fname[_MAX_FNAME]; - _tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0); - - if ( !_tcsicmp(fname, _T("svchost")) ) { - LPWSTR *p = argv; - for ( int i = 1; i < numArgs; i++ ) { - if ( !_tcsicmp(*(p++), _T("-k")) && !_tcscpy_s(lpGroupName, dwSize, *p) ) { - result = TRUE; - trace(_T("Service \"%s\" group name: %s"), lpServiceName, lpGroupName); - break; - } - } - } - return result; -} - -BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) { +BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpCommandLine, SIZE_T dwSize) { BOOL result = FALSE; if ( !hSCManager && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) ) return result; @@ -137,40 +18,10 @@ BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR l LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded); if ( QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded) - && !_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName) ) + && !_tcscpy_s(lpCommandLine, dwSize, sc->lpBinaryPathName) ) result = TRUE; free(sc); } CloseServiceHandle(hService); return result; } - -BOOL GetServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, LPDWORD lpdwProcessId) { - BOOL result = FALSE; - BOOL selfclose = !hSCManager; - if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) ) - return result; - - DWORD uBytes = 1 << 20; - LPBYTE pvData = malloc(uBytes); - RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), - lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes); - - for ( LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1 ) { - DWORD dwProcessId; - TCHAR group[256]; - if ( GetServiceProcessId(hSCManager, p, &dwProcessId) - && (GetServiceGroupName(hSCManager, p, group, _countof(group)) - && !_tcsicmp(group, lpServiceGroupName)) ) { - - *lpdwProcessId = dwProcessId; - result = TRUE; - trace(_T("Service group \"%s\" process ID: %d"), lpServiceGroupName, *lpdwProcessId); - break; - } - } - free(pvData); - if ( selfclose ) - CloseServiceHandle(hSCManager); - return result; -} diff --git a/wufuc/service.h b/wufuc/service.h index 9a6f2c5..ad5c347 100644 --- a/wufuc/service.h +++ b/wufuc/service.h @@ -1,14 +1,8 @@ -#ifndef SERVICE_H -#define SERVICE_H +#ifndef SERVICE_H_INCLUDED +#define SERVICE_H_INCLUDED #pragma once #include -BOOL FindServiceDllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD nCount); -LPWSTR GetWindowsUpdateServiceDllW(void); -BOOL ApplyUpdatePack7R2ShimIfNeeded(const wchar_t *path, size_t pathsize, wchar_t *newpath, size_t newpathsize); -BOOL GetServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPDWORD lpdwProcessId); -BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize); BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize); -BOOL GetServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, LPDWORD lpdwProcessId); #endif diff --git a/wufuc/shellapihelper.h b/wufuc/shellapihelper.h deleted file mode 100644 index 2c1f7cd..0000000 --- a/wufuc/shellapihelper.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef SHELLAPIHELPER_H -#define SHELLAPIHELPER_H -#pragma once - -#ifdef UNICODE -#define CommandLineToArgv CommandLineToArgvW -#else -#define CommandLineToArgv CommandLineToArgvA -#endif -#endif diff --git a/wufuc/tracing.c b/wufuc/tracing.c new file mode 100644 index 0000000..08efaa2 --- /dev/null +++ b/wufuc/tracing.c @@ -0,0 +1,72 @@ +#include "tracing.h" + +#include +#include + +#include +#include + +static FILE *m_pStream; +static HANDLE m_hMutex; +static BOOL m_bDeinitializing; + +BOOL InitTracing(void) { + if ( m_bDeinitializing ) + return FALSE; + + if ( !m_hMutex ) + m_hMutex = CreateMutex(NULL, FALSE, _T("Global\\wufuc_TracingMutex")); + + if ( m_hMutex && !m_pStream ) { + TCHAR path[MAX_PATH]; + GetModuleFileName(HINST_THISCOMPONENT, path, _countof(path)); + + TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME]; + _tsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), NULL, 0); + _tmakepath_s(path, _countof(path), drive, dir, fname, _T(".log")); + + m_pStream = _tfsopen(path, _T("at"), _SH_DENYNO); + } + return m_pStream && m_hMutex; +} + +DWORD WaitForTracingMutex(void) { + return WaitForSingleObject(m_hMutex, INFINITE); +} + +BOOL ReleaseTracingMutex(void) { + return ReleaseMutex(m_hMutex); +} + +void trace_(LPCTSTR format, ...) { + if ( InitTracing() ) { + TCHAR datebuf[9], timebuf[9]; + _tstrdate_s(datebuf, _countof(datebuf)); + _tstrtime_s(timebuf, _countof(timebuf)); + if ( !WaitForTracingMutex() ) { + _ftprintf_s(m_pStream, _T("%s %s [PID: %d TID: %d] "), datebuf, timebuf, GetCurrentProcessId(), GetCurrentThreadId()); + + va_list argptr; + va_start(argptr, format); + _vftprintf_s(m_pStream, format, argptr); + va_end(argptr); + fflush(m_pStream); + } + ReleaseTracingMutex(); + } +} + +BOOL DeinitTracing(void) { + m_bDeinitializing = TRUE; + + BOOL result = TRUE; + if ( m_hMutex ) { + result = CloseHandle(m_hMutex); + m_hMutex = NULL; + } + if ( m_pStream ) { + result = result && !fclose(m_pStream); + m_pStream = NULL; + } + return result; +} diff --git a/wufuc/tracing.h b/wufuc/tracing.h new file mode 100644 index 0000000..4255e40 --- /dev/null +++ b/wufuc/tracing.h @@ -0,0 +1,22 @@ +#ifndef LOGGING_H_INCLUDED +#define LOGGING_H_INCLUDED +#pragma once + +#include +#include + +extern IMAGE_DOS_HEADER __ImageBase; +#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) + +BOOL InitTracing(void); +DWORD WaitForTracingMutex(void); +BOOL ReleaseTracingMutex(void); +void trace_(LPCTSTR format, ...); +BOOL DeinitTracing(void); + +#define STRINGIZE_(x) #x +#define STRINGIZE(x) STRINGIZE_(x) + +#define LINESTR STRINGIZE(__LINE__) +#define trace(format, ...) trace_(_T(__FILE__) _T(":") _T(LINESTR) _T("(") _T(__FUNCTION__) _T("): ") format _T("\n"), ##__VA_ARGS__) +#endif diff --git a/wufuc/wufuc.def b/wufuc/wufuc.def index 17c0f4f..7d9ac27 100644 --- a/wufuc/wufuc.def +++ b/wufuc/wufuc.def @@ -1,3 +1,2 @@ EXPORTS - Rundll32Entry Rundll32Unload diff --git a/wufuc/wufuc.rc b/wufuc/wufuc.rc index f51334b054c486b9405ed67ab9ec7b7350769f36..836f61e923a1ea4292ea0650d38ffb8f53c10ae0 100644 GIT binary patch delta 352 zcmbOrc!gi{|377hOolv$WQH7uQic?UR0ahGC5Cb!I}M1F8T1&6fMf=P(&UYd>5~Jo!DV?&JVg8*XO?e+FM5^kfK`+{tP?S%xi29^}+C zup`sJc7`&z0rfaD#51@s_%QfP{>Z95`53F5U^q||Ri=?u6zJ^~rnK7l|7%m@pVHSTg7UU17jb0mLQ@Nel*)53-AM Mxia_xT>~;100fIlrT_o{ delta 441 zcmcb@KS5CX|377hOolWD1qMZi6oynFE0ZA)NT)DpOw5#))&xqZ0U=gtb?JD9Ud3Zj_z8h)GP|fI*MJ9Egp8*Z`X{&3c$A3P1%qK*c&h#X4}ssX+In zfZd2;2hdr;3?U3b44w>r4DLWO3h0`61`UP^po|AI8ZSm`x@}Fl$YgV#}Evz|1k3g~eoI8Q>XLto;ew4t^70Kv)8U QLxI5%7%T>pH?k`O01XpaaR2}S diff --git a/wufuc/wufuc.rch b/wufuc/wufuc.rch new file mode 100644 index 0000000..3ea21ee --- /dev/null +++ b/wufuc/wufuc.rch @@ -0,0 +1,17 @@ +#ifndef WUFUC_RCH_INCLUDED +#define WUFUC_RCH_INCLUDED +#pragma once +#ifndef BUILD_COMMIT_VERSION +#define BUILD_COMMIT_VERSION 0.8.0.0 +#endif +#ifndef BUILD_VERSION_COMMA +#define BUILD_VERSION_COMMA 0,8.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/wufuc/wufuc.vcxproj b/wufuc/wufuc.vcxproj index 64b214f..6230aea 100644 --- a/wufuc/wufuc.vcxproj +++ b/wufuc/wufuc.vcxproj @@ -18,6 +18,44 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + + + X64;%(PreprocessorDefinitions) + X64;%(PreprocessorDefinitions) + X86;%(PreprocessorDefinitions) + X86;%(PreprocessorDefinitions) + + 15.0 {00F96695-CE41-4C2F-A344-6219DFB4F887} @@ -108,7 +146,7 @@ Windows - %(AdditionalDependencies) + version.lib;%(AdditionalDependencies) wufuc.def @@ -122,29 +160,30 @@ Windows - %(AdditionalDependencies) + version.lib;%(AdditionalDependencies) wufuc.def Level3 - MaxSpeed + Full true true WIN32;NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions) MultiThreaded CompileAsC + Size - BUILD_VERSION=$(BUILD_VERSION);BUILD_VERSION_COMMA_SEP=$(BUILD_VERSION_COMMA_SEP);$(PreprocessorDefinitions) + BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions) Windows true true false - %(AdditionalDependencies) + version.lib;%(AdditionalDependencies) wufuc.def @@ -155,22 +194,23 @@ Level3 - MaxSpeed + Full true true NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions) MultiThreaded CompileAsC + Size - BUILD_VERSION=$(BUILD_VERSION);BUILD_VERSION_COMMA_SEP=$(BUILD_VERSION_COMMA_SEP);$(PreprocessorDefinitions) + BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions) Windows true true false - %(AdditionalDependencies) + version.lib;%(AdditionalDependencies) wufuc.def @@ -178,37 +218,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wufuc/wufuc.vcxproj.filters b/wufuc/wufuc.vcxproj.filters index 08d9026..100c165 100644 --- a/wufuc/wufuc.vcxproj.filters +++ b/wufuc/wufuc.vcxproj.filters @@ -1,34 +1,94 @@  - - - - - - - - - - - + + {629a1242-73f5-4282-a218-7b8d7d761cc6} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {e54f7242-67a6-4c85-bf48-0f7a6095b613} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {acf0da3d-e3e4-4fc8-aaf8-8d0558e6414c} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + - - - - - - - - - - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Resource Files + - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + - + + Source Files + + + + + Resource Files + \ No newline at end of file