diff --git a/wufuc/appverifier.h b/wufuc/appverifier.h index c2c452b..51dbac2 100644 --- a/wufuc/appverifier.h +++ b/wufuc/appverifier.h @@ -38,7 +38,8 @@ typedef struct tagRTL_VERIFIER_PROVIDER_DESCRIPTOR RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback; } RTL_VERIFIER_PROVIDER_DESCRIPTOR, *PRTL_VERIFIER_PROVIDER_DESCRIPTOR; -extern RTL_VERIFIER_THUNK_DESCRIPTOR g_vfADVAPIThunkDescriptors[]; -extern RTL_VERIFIER_THUNK_DESCRIPTOR g_vfK32ThunkDescriptors[]; -extern RTL_VERIFIER_DLL_DESCRIPTOR g_vfDllDescriptors[]; -extern RTL_VERIFIER_PROVIDER_DESCRIPTOR g_vfProviderDescriptor; +typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); +typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); + +extern LPFN_REGQUERYVALUEEXW *g_plpfnRegQueryValueExW; +extern LPFN_LOADLIBRARYEXW *g_plpfnLoadLibraryExW; diff --git a/wufuc/dllmain.c b/wufuc/dllmain.c index 2cc2a5b..bdda410 100644 --- a/wufuc/dllmain.c +++ b/wufuc/dllmain.c @@ -8,20 +8,21 @@ #include #include -RTL_VERIFIER_THUNK_DESCRIPTOR g_vfK32ThunkDescriptors[] = { +RTL_VERIFIER_THUNK_DESCRIPTOR g_vfThunkDescriptors[] = { { "RegQueryValueExW", NULL, (PVOID)&RegQueryValueExW_Hook }, { "LoadLibraryExW", NULL, (PVOID)&LoadLibraryExW_Hook }, { 0 } }; -RTL_VERIFIER_DLL_DESCRIPTOR g_vfDllDescriptors[] = { - { L"kernel32.dll", 0, NULL, g_vfK32ThunkDescriptors }, - { 0 } }; -RTL_VERIFIER_DLL_DESCRIPTOR g_vfNullDllDescriptor = { 0 }; + +RTL_VERIFIER_DLL_DESCRIPTOR g_vfDllDescriptors[2]; + RTL_VERIFIER_PROVIDER_DESCRIPTOR g_vfProviderDescriptor = { sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR), - &g_vfNullDllDescriptor, - //(RTL_VERIFIER_DLL_LOAD_CALLBACK)&VerifierDllLoadCallback, - //(RTL_VERIFIER_DLL_UNLOAD_CALLBACK)&VerifierDllUnloadCallback -}; + g_vfDllDescriptors/*, + (RTL_VERIFIER_DLL_LOAD_CALLBACK)&VerifierDllLoadCallback, + (RTL_VERIFIER_DLL_UNLOAD_CALLBACK)&VerifierDllUnloadCallback*/ }; + +LPFN_REGQUERYVALUEEXW *g_plpfnRegQueryValueExW; +LPFN_LOADLIBRARYEXW *g_plpfnLoadLibraryExW; BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { @@ -31,27 +32,31 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv break; case DLL_PROCESS_DETACH: break; - case DLL_PROCESS_VERIFIER:; - if ( verify_winver(6, 1, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) - || verify_winver(6, 3, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) ) { + case DLL_PROCESS_VERIFIER: + if ( verify_win7() || verify_win81 ) { + UNICODE_STRING ImagePath; + RtlInitUnicodeString(&ImagePath, NULL); RTL_QUERY_REGISTRY_TABLE QueryTable[2]; RtlSecureZeroMemory(&QueryTable, sizeof(QueryTable)); QueryTable[0].Name = L"ImagePath"; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - UNICODE_STRING ImagePath; - RtlInitUnicodeString(&ImagePath, NULL); QueryTable[0].EntryContext = &ImagePath; - //TODO: check status and maybe fix implementation? idk... - NTSTATUS Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - L"wuauserv", - QueryTable, - NULL, - NULL); - - if ( !RtlCompareUnicodeString(&NtCurrentPeb()->ProcessParameters->CommandLine, &ImagePath, TRUE) ) - g_vfProviderDescriptor.ProviderDlls = g_vfDllDescriptors; + if ( RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, L"wuauserv", QueryTable, NULL, NULL) == STATUS_SUCCESS + && !RtlCompareUnicodeString(&NtCurrentPeb()->ProcessParameters->CommandLine, &ImagePath, TRUE) ) { + + if ( verify_win7() ) + g_vfDllDescriptors[0].DllName = L"kernel32.dll"; + else if ( verify_win81() ) + g_vfDllDescriptors[0].DllName = L"kernelbase.dll"; + + g_vfDllDescriptors[0].DllThunks = g_vfThunkDescriptors; + + g_plpfnRegQueryValueExW = (LPFN_REGQUERYVALUEEXW *)&g_vfThunkDescriptors[0].ThunkOldAddress; + g_plpfnLoadLibraryExW = (LPFN_LOADLIBRARYEXW *)&g_vfThunkDescriptors[1].ThunkOldAddress; + } + RtlFreeUnicodeString(&ImagePath); } *(PRTL_VERIFIER_PROVIDER_DESCRIPTOR *)lpReserved = &g_vfProviderDescriptor; break; diff --git a/wufuc/helpers.c b/wufuc/helpers.c index 3e4a675..3f2b74b 100644 --- a/wufuc/helpers.c +++ b/wufuc/helpers.c @@ -53,6 +53,26 @@ bool verify_winver( return RtlVerifyVersionInfo(&osvi, TypeMask, ConditionMask) == STATUS_SUCCESS; } +bool verify_win7(void) +{ + static bool a, b; + if ( !a ) { + b = verify_winver(6, 1, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0); + a = true; + } + return b; +} + +bool verify_win81(void) +{ + static bool a, b; + if ( !a ) { + b = verify_winver(6, 3, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0); + a = true; + } + return b; +} + wchar_t *find_fname(wchar_t *pPath) { wchar_t *pwc = wcsrchr(pPath, L'\\'); @@ -62,7 +82,7 @@ wchar_t *find_fname(wchar_t *pPath) return pPath; } -BOOL file_exists(const wchar_t *path) +bool file_exists(const wchar_t *path) { return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES; } diff --git a/wufuc/helpers.h b/wufuc/helpers.h index 3804e9d..43c4bfb 100644 --- a/wufuc/helpers.h +++ b/wufuc/helpers.h @@ -16,9 +16,11 @@ bool verify_winver( BYTE ServicePackMajorCondition, BYTE ServicePackMinorCondition ); +bool verify_win7(void); +bool verify_win81(void); wchar_t *find_fname(wchar_t *pPath); -BOOL file_exists(const wchar_t *path); +bool file_exists(const wchar_t *path); int compare_versions( WORD wMajorA, WORD wMinorA, WORD wBuildA, WORD wRevisionA, WORD wMajorB, WORD wMinorB, WORD wBuildB, WORD wRevisionB); diff --git a/wufuc/hooks.c b/wufuc/hooks.c index 408fae9..e04abbe 100644 --- a/wufuc/hooks.c +++ b/wufuc/hooks.c @@ -25,7 +25,7 @@ LSTATUS WINAPI RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR DWORD cbData = *lpcbData; size_t MaxCount = cbData / sizeof(wchar_t); - // this way the dll path is garunteed to be null terminated + // this way the dll path is guaranteed to be null-terminated result = RegGetValueW(hKey, NULL, lpValueName, RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, lpType, lpData, lpcbData); if ( result != ERROR_SUCCESS ) goto L_ret; @@ -39,8 +39,13 @@ LSTATUS WINAPI RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR Status = NtQueryKey((HANDLE)hKey, KeyNameInformation, (PVOID)pkni, ResultLength, &ResultLength); if ( Status == STATUS_SUCCESS ) { size_t BufferCount = pkni->NameLength / sizeof(wchar_t); + + // change key name to lower-case because there is no case-insensitive version of _snwscanf_s + for ( size_t i = 0; i < BufferCount; i++ ) + pkni->Name[i] = towlower(pkni->Name[i]); + int current, pos; - if ( _snwscanf_s(pkni->Name, BufferCount, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet%03d\\services\\wuauserv\\Parameters%n", ¤t, &pos) == 1 + if ( _snwscanf_s(pkni->Name, BufferCount, L"\\registry\\machine\\system\\controlset%03d\\services\\wuauserv\\parameters%n", ¤t, &pos) == 1 && pos == BufferCount ) { wchar_t drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; @@ -68,7 +73,7 @@ LSTATUS WINAPI RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR if ( file_exists(lpDst) ) { _wmakepath_s((wchar_t *)lpData, MaxCount, drive, dir, L"wuaueng", ext); *lpcbData = (DWORD)((wcslen((wchar_t *)lpData) + 1) * sizeof(wchar_t)); - trace(L"Fixed wuauserv ServiceDll path: %ls", lpDst); + trace(L"Fixed wuauserv %ls path: %ls", lpValueName, lpDst); } rtl_free(lpDst); } @@ -77,7 +82,7 @@ LSTATUS WINAPI RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR rtl_free(pkni); } else { // handle normally - result = ((LPFN_REGQUERYVALUEEXW)g_vfK32ThunkDescriptors[0].ThunkOldAddress)(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); + result = (*g_plpfnRegQueryValueExW)(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } L_ret: return result; @@ -85,17 +90,19 @@ L_ret: HMODULE WINAPI LoadLibraryExW_Hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) { - HMODULE result = ((LPFN_LOADLIBRARYEXW)g_vfK32ThunkDescriptors[1].ThunkOldAddress)(lpFileName, hFile, dwFlags); + HMODULE result = (*g_plpfnLoadLibraryExW)(lpFileName, hFile, dwFlags); if ( !result ) { trace(L"Failed to load library: %ls (error code=%08X)", lpFileName, GetLastError()); goto L_ret; } + trace(L"Loaded library: %ls", lpFileName); DWORD dwLen = GetFileVersionInfoSizeW(lpFileName, NULL); if ( !dwLen ) { trace(L"Failed to get file version info size for file %ls (error code=%08X)", lpFileName, GetLastError()); goto L_ret; } + LPVOID pBlock = rtl_malloc(dwLen); if ( GetFileVersionInfoW(lpFileName, 0, dwLen, pBlock) ) { PLANGANDCODEPAGE ptl; diff --git a/wufuc/hooks.h b/wufuc/hooks.h index e20ab23..2eddadd 100644 --- a/wufuc/hooks.h +++ b/wufuc/hooks.h @@ -8,8 +8,5 @@ typedef struct tagLANGANDCODEPAGE WORD wCodePage; } LANGANDCODEPAGE, *PLANGANDCODEPAGE; -typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); -typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); - 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/wufuc/patchwua.c b/wufuc/patchwua.c index 8a0187b..8ace70c 100644 --- a/wufuc/patchwua.c +++ b/wufuc/patchwua.c @@ -4,7 +4,6 @@ #include "patternfind.h" #include "tracing.h" -#include #include #include @@ -40,10 +39,12 @@ bool patch_wua(void *lpBaseOfDll, size_t SizeOfImage, wchar_t *fname) #ifdef _M_AMD64 pps = &X64PatchSet; #elif defined(_M_IX86) - if ( verify_winver(6, 1, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) ) + if ( verify_win7() ) pps = &Win7X86PatchSet; - else if ( verify_winver(6, 3, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) ) + else if ( verify_win81() ) pps = &Win81X86PatchSet; + else + goto L_ret; #endif unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, pps->Pattern); if ( !ptr ) {