commit existing code before culling

This commit is contained in:
zeffy
2017-12-16 01:46:04 -08:00
parent 25ae43327b
commit c6d1def339
23 changed files with 621 additions and 354 deletions

View File

@@ -1,6 +1,6 @@
# Contributing guidelines # Contributing guidelines
**English** | [Community translations](https://github.com/zeffy/wufuc/wiki) This document is also available in [简体中文], [繁体中文], [русский], [Español] and [more...](https://github.com/zeffy/wufuc/wiki)
## Reporting an issue [![](https://isitmaintained.com/badge/resolution/zeffy/wufuc.svg)](https://isitmaintained.com/project/zeffy/wufuc) ## Reporting an issue [![](https://isitmaintained.com/badge/resolution/zeffy/wufuc.svg)](https://isitmaintained.com/project/zeffy/wufuc)
@@ -20,3 +20,8 @@
- 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 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. - 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)

View File

@@ -1,15 +1,15 @@
# wufuc # wufuc
[![Donate Bitcoin](https://cdn.rawgit.com/zeffy/wufuc/badges/bitcoin.svg)](https://admin.gear.mycelium.com/gateways/3554/orders/new) [![AppVeyor Builds](https://img.shields.io/appveyor/ci/zeffy/wufuc.svg?logo=appveyor&style=flat-square)](https://ci.appveyor.com/project/zeffy/wufuc) [![Chat on Telegram](https://cdn.rawgit.com/zeffy/wufuc/badges/telegram.svg)](https://t.me/joinchat/HEo6LUvV_83O92WzbYXLeQ) [![All Releases](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg?style=flat-square)](https://github.com/zeffy/wufuc/releases/latest) [![Donate Bitcoin](https://cdn.rawgit.com/zeffy/wufuc/badges/bitcoin.svg)](https://admin.gear.mycelium.com/gateways/3554/orders/new) [![AppVeyor Builds](https://img.shields.io/appveyor/ci/zeffy/wufuc.svg?logo=appveyor&style=flat-square)][AppVeyor] [![Chat on Telegram](https://cdn.rawgit.com/zeffy/wufuc/badges/telegram.svg)](https://t.me/joinchat/HEo6LUvV_83O92WzbYXLeQ) [![All Releases](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg?style=flat-square)][Latest]
**English** | [Community translations](https://github.com/zeffy/wufuc/wiki) This document is also available in [简体中文], [繁体中文], [русский], [Español] and [more...](https://github.com/zeffy/wufuc/wiki)
Disables the "Unsupported Hardware" message in Windows Update, and allows you to continue installing updates on Windows 7 and 8.1 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors. Disables the "Unsupported Hardware" message in Windows Update, and allows you to continue installing updates on Windows 7 and 8.1 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
## Downloads ## Downloads
**[Latest stable build](https://github.com/zeffy/wufuc/releases/latest) - Most people will want this version.** **[Latest stable build][Latest] - Most people will want this version.**
[Unstable builds](https://ci.appveyor.com/project/zeffy/wufuc) - Probably contains bugs; do not report issues with these builds. [Unstable builds][AppVeyor] - Probably contains bugs; do not report issues with these builds.
## Donate ## Donate
@@ -96,12 +96,19 @@ There was a fundamental issue with the method I tried using in this version that
## Sponsors ## Sponsors
### [Advanced Installer](http://www.advancedinstaller.com/) ### [Advanced Installer](https://www.advancedinstaller.com/)
The installer packages are created with Advanced Installer using an [open source license](http://www.advancedinstaller.com/free-license.html). The installer packages are created with Advanced Installer using an [open source license](http://www.advancedinstaller.com/free-license.html).
Advanced Installer's intuitive and friendly user interface allowed me to quickly create a feature complete installer with minimal effort. [Check it out!](http://www.advancedinstaller.com/) Advanced Installer's intuitive and friendly user interface allowed me to quickly create a feature complete installer with minimal effort. Check it out!
## Special thanks ## Special thanks
- Wen Jia Liu ([@wj32](https://github.com/wj32)) for his awesome program [Process Hacker](https://github.com/processhacker2/processhacker) which has been absolutely instrumental in the development of wufuc, and also for his [`phnt`](https://github.com/processhacker2/processhacker/tree/master/phnt) headers. - Wen Jia Liu ([@wj32](https://github.com/wj32)) for his awesome program [Process Hacker](https://github.com/processhacker2/processhacker) which has been absolutely instrumental in the development of wufuc, and also for his [`phnt`](https://github.com/processhacker2/processhacker/tree/master/phnt) headers.
- Duncan Ogilvie ([@mrexodia](https://github.com/mrexodia)) for his [`patternfind.cpp`](https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp) algorithm from [x64dbg](https://github.com/x64dbg/x64dbg). - Duncan Ogilvie ([@mrexodia](https://github.com/mrexodia)) for his [`patternfind.cpp`](https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp) algorithm from [x64dbg](https://github.com/x64dbg/x64dbg).
[Latest]: https://github.com/zeffy/wufuc/releases/latest
[AppVeyor]: https://ci.appveyor.com/project/zeffy/wufuc
[简体中文]: https://github.com/zeffy/wufuc/wiki/README-(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
[繁体中文]: https://github.com/zeffy/wufuc/wiki/README-(%E7%B9%81%E9%AB%94%E4%B8%AD%E6%96%87)
[русский]: https://github.com/zeffy/wufuc/wiki/README-(%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9)
[Español]: https://github.com/zeffy/wufuc/wiki/README-(Espa%C3%B1ol)

View File

@@ -1,4 +1,4 @@
version: 1.0.0.{build} version: 0.9.999.{build}
branches: branches:
only: only:
- master - master

View File

@@ -1,17 +1,14 @@
#include "stdafx.h" #include "stdafx.h"
#include "callbacks.h" #include "callbacks.h"
#include "hooks.h"
#include "helpers.h" #include "helpers.h"
#include <Psapi.h>
VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer) VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
{ {
HMODULE hModule;
switch ( pNotifyBuffer->dwNotificationStatus ) { switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS: case ERROR_SUCCESS:
if ( inject_self_into_process(pNotifyBuffer->ServiceStatus.dwProcessId, &hModule) ) { if ( pNotifyBuffer->ServiceStatus.dwProcessId )
InjectSelfAndCreateRemoteThread(pNotifyBuffer->ServiceStatus.dwProcessId, &StartAddress, (HANDLE)pNotifyBuffer->pContext, SYNCHRONIZE);
}
break; break;
case ERROR_SERVICE_MARKED_FOR_DELETE: case ERROR_SERVICE_MARKED_FOR_DELETE:
SetEvent((HANDLE)pNotifyBuffer->pContext); SetEvent((HANDLE)pNotifyBuffer->pContext);
@@ -20,3 +17,68 @@ VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
if ( pNotifyBuffer->pszServiceNames ) if ( pNotifyBuffer->pszServiceNames )
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames); LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
} }
DWORD WINAPI StartAddress(LPVOID pParam)
{
SC_HANDLE hSCM;
DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType;
int result;
DWORD cbData;
LPWSTR pServiceDll;
HMODULE hModule;
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
if ( !hSCM ) goto cleanup;
pServiceConfig = QueryServiceConfigByNameAlloc(hSCM, L"wuauserv", &cbBufSize);
CloseServiceHandle(hSCM);
if ( !pServiceConfig ) goto cleanup;
//dwServiceType = pServiceConfig->dwServiceType;
result = _wcsicmp(pServiceConfig->lpBinaryPathName, GetCommandLineW());
free(pServiceConfig);
if ( result ) goto cleanup;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// hook apis if configured as shared service
/* if ( dwServiceType == SERVICE_WIN32_SHARE_PROCESS ) {
g_pfnLoadLibraryExW = DetourFindFunction("kernel32.dll", "LoadLibraryExW");
DetourAttach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook);
g_pfnRegQueryValueExW = DetourFindFunction("kernel32.dll", "RegQueryValueExW");
DetourAttach(&(PVOID)g_pfnRegQueryValueExW, RegQueryValueExW_hook);
}*/
// hook IsDeviceServiceable if wuaueng.dll is already loaded
pServiceDll = RegGetValueAlloc(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters", L"ServiceDll", RRF_RT_REG_SZ, NULL, &cbData);
if ( pServiceDll ) {
hModule = GetModuleHandleW(pServiceDll);
if ( hModule && FindIsDeviceServiceablePtr(pServiceDll, hModule, &(PVOID)g_pfnIsDeviceServiceable) )
DetourAttach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook);
free(pServiceDll);
}
DetourTransactionCommit();
// wait for unload event
WaitForSingleObject((HANDLE)pParam, INFINITE);
// unhook functions
trace(L"DetourTransactionBegin result=%d", DetourTransactionBegin());
trace(L"DetourUpdateThread result=%d", DetourUpdateThread(GetCurrentThread()));
//if ( g_pfnLoadLibraryExW )
// trace(L"DetourDetach LoadLibraryExW_hook result=%d", DetourDetach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook));
//if ( g_pfnRegQueryValueExW )
// trace(L"DetourDetach RegQueryValueExW_hook result=%d", DetourDetach(&(PVOID)g_pfnRegQueryValueExW, RegQueryValueExW_hook));
if ( g_pfnIsDeviceServiceable )
trace(L"DetourDetach IsDeviceServiceable_hook result=%d", DetourDetach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook));
trace(L"DetourTransactionCommit result=%d", DetourTransactionCommit());
cleanup:
CloseHandle((HANDLE)pParam);
FreeLibraryAndExitThread(PIMAGEBASE, 0);
}

View File

@@ -1,3 +1,4 @@
#pragma once #pragma once
VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer); VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer);
DWORD WINAPI StartAddress(LPVOID pParam);

View File

@@ -4,7 +4,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
{ {
switch ( ul_reason_for_call ) { switch ( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
break; break;

View File

@@ -1,8 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#include "helpers.h" #include "helpers.h"
#include "hooks.h"
#include <sddl.h> #include <sddl.h>
bool create_exclusive_mutex(const wchar_t *name, HANDLE *pmutex) bool CreateExclusiveMutex(const wchar_t *name, HANDLE *pmutex)
{ {
HANDLE mutex; HANDLE mutex;
@@ -18,7 +19,7 @@ bool create_exclusive_mutex(const wchar_t *name, HANDLE *pmutex)
return false; return false;
} }
bool create_event_with_security_descriptor(const wchar_t *descriptor, bool manualreset, bool initialstate, const wchar_t *name, HANDLE *pevent) bool CreateEventWithStringSecurityDescriptor(const wchar_t *descriptor, bool manualreset, bool initialstate, const wchar_t *name, HANDLE *pevent)
{ {
SECURITY_ATTRIBUTES sa = { sizeof sa }; SECURITY_ATTRIBUTES sa = { sizeof sa };
HANDLE event; HANDLE event;
@@ -33,109 +34,29 @@ bool create_event_with_security_descriptor(const wchar_t *descriptor, bool manua
return false; return false;
} }
bool inject_self_into_process(DWORD dwProcessId, HMODULE *phModule) bool FileExists(const wchar_t *path)
{
wchar_t szFilename[MAX_PATH];
DWORD nLength;
nLength = GetModuleFileNameW(PIMAGEBASE, szFilename, _countof(szFilename));
if ( nLength )
return inject_dll_into_process(dwProcessId, szFilename, nLength, phModule);
return false;
}
bool inject_dll_into_process(DWORD dwProcessId, const wchar_t *pszFilename, size_t nLength, HMODULE *phModule)
{
bool result = false;
HANDLE hProcess;
NTSTATUS Status;
LPVOID pBaseAddress;
HANDLE hThread;
HANDLE hModule = NULL;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if ( !hProcess ) return result;
Status = NtSuspendProcess(hProcess);
if ( !NT_SUCCESS(Status) ) goto L1;
pBaseAddress = VirtualAllocEx(hProcess, NULL, nLength + (sizeof *pszFilename), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if ( !pBaseAddress ) goto L2;
if ( WriteProcessMemory(hProcess, pBaseAddress, pszFilename, nLength, NULL)
&& (hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, pBaseAddress, 0, NULL)) ) {
WaitForSingleObject(hThread, INFINITE);
if ( sizeof(DWORD) < sizeof hModule ) {
} else {
GetExitCodeThread(hThread, (LPDWORD)&hModule);
}
if ( hModule ) {
result = true;
*phModule = hModule;
}
CloseHandle(hThread);
}
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
L2: NtResumeProcess(hProcess);
L1: CloseHandle(hProcess);
return result;
}
const wchar_t *path_find_fname(const wchar_t *path)
{
const wchar_t *pwc = NULL;
if ( path )
pwc = (const wchar_t *)wcsrchr(path, L'\\');
return (pwc && *(++pwc)) ? pwc : path;
}
bool path_change_fname(const wchar_t *srcpath, const wchar_t *fname, wchar_t *dstpath, size_t size)
{
bool result;
wchar_t drive[_MAX_DRIVE];
wchar_t dir[_MAX_DIR];
result = !_wsplitpath_s(srcpath, drive, _countof(drive), dir, _countof(dir), NULL, 0, NULL, 0);
if ( result )
result = !_wmakepath_s(dstpath, size, drive, dir, fname, NULL);
return result;
}
bool path_file_exists(const wchar_t *path)
{ {
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES; return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
} }
bool path_expand_file_exists(const wchar_t *path) bool FileExistsExpandEnvironmentStrings(const wchar_t *path)
{ {
bool result; bool result;
wchar_t *dst; LPWSTR dst;
DWORD buffersize; DWORD buffersize;
DWORD size; DWORD size;
dst = NULL; buffersize = ExpandEnvironmentStringsW(path, NULL, 0);
size = 0; dst = calloc(buffersize, sizeof *dst);
do {
if ( size ) {
if ( dst )
free(dst);
dst = calloc(size, sizeof *dst);
}
buffersize = size;
size = ExpandEnvironmentStringsW(path, dst, buffersize); size = ExpandEnvironmentStringsW(path, dst, buffersize);
} while ( buffersize < size ); if ( !size || size > buffersize )
return false;
result = path_file_exists(dst); result = FileExists(dst);
free(dst); free(dst);
return result; return result;
} }
int ffi_ver_compare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev) int FileInfoVerCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev)
{ {
if ( HIWORD(pffi->dwProductVersionMS) < wMajor ) return -1; if ( HIWORD(pffi->dwProductVersionMS) < wMajor ) return -1;
if ( HIWORD(pffi->dwProductVersionMS) > wMajor ) return 1; if ( HIWORD(pffi->dwProductVersionMS) > wMajor ) return 1;
@@ -148,16 +69,361 @@ int ffi_ver_compare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuil
return 0; return 0;
} }
size_t find_argv_option(const wchar_t **argv, size_t argc, const wchar_t *option) bool FindIsDeviceServiceablePtr(const wchar_t *pFilename, HMODULE hModule, PVOID *ppfnIsDeviceServiceable)
{ {
size_t index = -1; bool result = false;
DWORD dwLen;
LPVOID pBlock;
PLANGANDCODEPAGE ptl;
UINT cb;
wchar_t SubBlock[38];
wchar_t *pInternalName;
UINT uLen;
VS_FIXEDFILEINFO *pffi;
bool is_win7 = false;
bool is_win81 = false;
size_t n;
char szModule[MAX_PATH];
LPFN_ISDEVICESERVICEABLE pfnIsDeviceServiceable = NULL;
MODULEINFO modinfo;
const char *pattern;
size_t offset;
for ( size_t i = 1; i < argc; i++ ) { dwLen = GetFileVersionInfoSizeW(pFilename, NULL);
if ( !_wcsicmp(argv[i], option) ) if ( !dwLen ) return result;
index = i;
}
if ( index == -1 )
return index;
return ++index < argc ? index : -1; pBlock = malloc(dwLen);
if ( !pBlock ) return result;
if ( !GetFileVersionInfoW(pFilename, 0, dwLen, pBlock)
|| !VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) )
goto cleanup;
is_win7 = IsWindowsVersion(6, 1, 1);
if ( !is_win7 )
is_win81 = IsWindowsVersion(6, 3, 0);
for ( size_t i = 0; i < (cb / sizeof *ptl); i++ ) {
swprintf_s(SubBlock, _countof(SubBlock), L"\\StringFileInfo\\%04x%04x\\InternalName",
ptl[i].wLanguage,
ptl[i].wCodePage);
// identify wuaueng.dll by its resource data
if ( !VerQueryValueW(pBlock, SubBlock, (LPVOID *)&pInternalName, &uLen)
|| _wcsicmp(pInternalName, L"wuaueng.dll")
|| !VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen) )
continue;
// assure wuaueng.dll is at least the minimum supported version
if ( (is_win7 && FileInfoVerCompare(pffi, 7, 6, 7601, 23714) != -1)
|| (is_win81 && FileInfoVerCompare(pffi, 7, 9, 9600, 18621) != -1) ) {
// convert pFilename to multibyte string because DetourFindFunction doesn't take wide string
// try resolving with detours helper function first (needs dbghelp.dll and an internet connection)
//if ( !wcstombs_s(&n, szModule, _countof(szModule), pFilename, _TRUNCATE) )
// pfnIsDeviceServiceable = DetourFindFunction(PathFindFileNameA(szModule), "IsDeviceServiceable");
// fall back to byte pattern search if the above method fails
if ( !pfnIsDeviceServiceable
&& K32GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
#ifdef _WIN64
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
#else
if ( is_win7 )
pattern = "833D????????00 743E E8???????? A3????????";
else // if we've reached this point we can assume win 8.1 without checking is_win81 again
pattern = "8BFF 51 833D????????00 7507 A1????????";
#endif
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pattern);
if ( offset != -1 )
pfnIsDeviceServiceable = (LPFN_ISDEVICESERVICEABLE)((uint8_t *)modinfo.lpBaseOfDll + offset);
}
if ( pfnIsDeviceServiceable ) {
trace(L"Found IsDeviceServiceable address: %p", pfnIsDeviceServiceable);
*ppfnIsDeviceServiceable = pfnIsDeviceServiceable;
result = true;
}
break;
}
}
cleanup:
free(pBlock);
return result;
}
bool GetRemoteHModuleFromTh32ModuleSnapshot(HANDLE hSnapshot, const wchar_t *pLibFileName, HMODULE *phRemoteModule)
{
MODULEENTRY32W me = { sizeof me };
if ( !Module32FirstW(hSnapshot, &me) )
return false;
do {
if ( !_wcsicmp(me.szExePath, pLibFileName) ) {
*phRemoteModule = me.hModule;
return true;
}
} while ( Module32NextW(hSnapshot, &me) );
return false;
}
bool InjectSelfAndCreateRemoteThread(DWORD dwProcessId, LPTHREAD_START_ROUTINE pStartAddress, HANDLE SourceHandle, DWORD dwDesiredAccess)
{
bool result = false;
HANDLE hProcess;
NTSTATUS Status;
HMODULE hRemoteModule;
LPTHREAD_START_ROUTINE pfnTargetStartAddress;
HANDLE TargetHandle = NULL;
HANDLE hThread;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if ( !hProcess ) return result;
Status = NtSuspendProcess(hProcess);
if ( !NT_SUCCESS(Status) ) goto cleanup;
if ( InjectLibraryByLocalHModule(hProcess, PIMAGEBASE, &hRemoteModule)
&& (!SourceHandle || DuplicateHandle(GetCurrentProcess(), SourceHandle, hProcess, &TargetHandle, dwDesiredAccess, FALSE, 0)) ) {
// get pointer to StartAddress in remote process
pfnTargetStartAddress = (LPTHREAD_START_ROUTINE)((uint8_t *)hRemoteModule + ((uint8_t *)pStartAddress - (uint8_t *)PIMAGEBASE));
hThread = CreateRemoteThread(hProcess, NULL, 0, pfnTargetStartAddress, (LPVOID)TargetHandle, 0, NULL);
if ( hThread ) {
CloseHandle(hThread);
result = true;
}
}
NtResumeProcess(hProcess);
cleanup:
CloseHandle(hProcess);
return result;
}
bool InjectLibraryByFileName(HANDLE hProcess, const wchar_t *pLibFileName, size_t cchLibFileName, HMODULE *phRemoteModule)
{
bool result = false;
DWORD dwProcessId;
NTSTATUS Status;
HANDLE hSnapshot;
SIZE_T nSize;
LPVOID pBaseAddress;
HANDLE hThread;
Status = NtSuspendProcess(hProcess);
if ( !NT_SUCCESS(Status) ) return result;
dwProcessId = GetProcessId(hProcess);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if ( !hSnapshot ) goto L1;
result = GetRemoteHModuleFromTh32ModuleSnapshot(hSnapshot, pLibFileName, phRemoteModule);
CloseHandle(hSnapshot);
// already injected... returns false but sets *phRemoteModule
if ( result ) goto L1;
nSize = (cchLibFileName + 1) * sizeof *pLibFileName;
pBaseAddress = VirtualAllocEx(hProcess, NULL, nSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if ( !pBaseAddress ) goto L1;
if ( !WriteProcessMemory(hProcess, pBaseAddress, pLibFileName, nSize, NULL) )
goto L2;
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, pBaseAddress, 0, NULL);
if ( !hThread ) goto L2;
WaitForSingleObject(hThread, INFINITE);
if ( sizeof *phRemoteModule > sizeof(DWORD) ) {
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if ( hSnapshot ) {
result = GetRemoteHModuleFromTh32ModuleSnapshot(hSnapshot, pLibFileName, phRemoteModule);
CloseHandle(hSnapshot);
}
} else {
result = !!GetExitCodeThread(hThread, (LPDWORD)phRemoteModule);
}
CloseHandle(hThread);
L2: VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
L1: NtResumeProcess(hProcess);
return result;
}
bool InjectLibraryByLocalHModule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule)
{
WCHAR Filename[MAX_PATH];
DWORD nLength;
nLength = GetModuleFileNameW(hModule, Filename, _countof(Filename));
if ( nLength )
return InjectLibraryByFileName(hProcess, Filename, nLength, phRemoteModule);
return false;
}
bool IsWindowsVersion(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
OSVERSIONINFOEXW osvi = { sizeof osvi };
DWORDLONG dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
PVOID NtQueryKeyAlloc(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PULONG pResultLength)
{
NTSTATUS Status;
ULONG ResultLength;
PVOID result = NULL;
Status = NtQueryKey(KeyHandle, KeyInformationClass, NULL, 0, &ResultLength);
if ( Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL )
return result;
result = malloc(ResultLength);
if ( !result ) return result;
Status = NtQueryKey(KeyHandle, KeyInformationClass, result, ResultLength, &ResultLength);
if ( NT_SUCCESS(Status) ) {
*pResultLength = ResultLength;
} else {
free(result);
result = NULL;
}
return result;
}
PVOID RegGetValueAlloc(HKEY hkey, const wchar_t *pSubKey, const wchar_t *pValue, DWORD dwFlags, LPDWORD pdwType, LPDWORD pcbData)
{
DWORD cbData = 0;
PVOID result = NULL;
if ( RegGetValueW(hkey, pSubKey, pValue, dwFlags, pdwType, NULL, &cbData) != ERROR_SUCCESS )
return result;
result = malloc(cbData);
if ( !result ) return result;
if ( RegGetValueW(hkey, pSubKey, pValue, dwFlags, pdwType, result, &cbData) == ERROR_SUCCESS ) {
*pcbData = cbData;
} else {
free(result);
result = NULL;
}
return result;
}
LPQUERY_SERVICE_CONFIGW QueryServiceConfigByNameAlloc(SC_HANDLE hSCM, const wchar_t *pServiceName, LPDWORD pcbBufSize)
{
SC_HANDLE hService;
DWORD cbBytesNeeded;
LPQUERY_SERVICE_CONFIGW result = NULL;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_CONFIG);
if ( !hService ) return result;
if ( !QueryServiceConfigW(hService, NULL, 0, &cbBytesNeeded)
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
result = malloc(cbBytesNeeded);
if ( result ) {
if ( QueryServiceConfigW(hService, result, cbBytesNeeded, &cbBytesNeeded) ) {
*pcbBufSize = cbBytesNeeded;
} else {
free(result);
result = NULL;
}
}
}
CloseServiceHandle(hService);
return result;
}
bool QueryServiceStatusProcessInfoByName(SC_HANDLE hSCM, const wchar_t *pServiceName, LPSERVICE_STATUS_PROCESS pServiceStatus)
{
bool result = false;
SC_HANDLE hService;
DWORD cbBytesNeeded;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS);
if ( !hService ) return result;
result = !!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)pServiceStatus, sizeof *pServiceStatus, &cbBytesNeeded);
CloseServiceHandle(hService);
return result;
}
bool QueryServiceGroupName(const LPQUERY_SERVICE_CONFIGW pServiceConfig, wchar_t *pGroupName, size_t nSize)
{
bool result = false;
int NumArgs;
LPWSTR *argv;
argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs);
if ( argv ) {
if ( !_wcsicmp(PathFindFileNameW(argv[0]), L"svchost.exe") ) {
for ( int i = 1; (i + 1) < NumArgs; i++ ) {
if ( !_wcsicmp(argv[i], L"-k") )
return !wcscpy_s(pGroupName, nSize, argv[++i]);
}
}
LocalFree((HLOCAL)argv);
}
return result;
}
DWORD QueryServiceProcessId(SC_HANDLE hSCM, const wchar_t *pServiceName)
{
SERVICE_STATUS_PROCESS ServiceStatusProcess;
if ( QueryServiceStatusProcessInfoByName(hSCM, pServiceName, &ServiceStatusProcess) )
return ServiceStatusProcess.dwProcessId;
return 0;
}
DWORD InferSvchostGroupProcessId(SC_HANDLE hSCM, const wchar_t *pGroupName)
{
DWORD result = 0;
DWORD cbData;
wchar_t *pData;
DWORD dwProcessId;
DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
bool success;
WCHAR GroupName[256];
pData = RegGetValueAlloc(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", pGroupName, RRF_RT_REG_MULTI_SZ, NULL, &cbData);
if ( !pData ) return result;
for ( wchar_t *pName = pData; *pName; pName += wcslen(pName) + 1 ) {
dwProcessId = QueryServiceProcessId(hSCM, pName);
trace(L"pName=%ls dwProcessId=%lu", pName, dwProcessId);
if ( !dwProcessId ) continue;
pServiceConfig = QueryServiceConfigByNameAlloc(hSCM, pName, &cbBufSize);
if ( !pServiceConfig ) continue;
success = QueryServiceGroupName(pServiceConfig, GroupName, _countof(GroupName));
free(pServiceConfig);
if ( success && !_wcsicmp(pGroupName, GroupName) ) {
trace(L"found PID for group %ls: %lu", pGroupName, dwProcessId);
result = dwProcessId;
break;
}
}
free(pData);
return result;
} }

View File

@@ -1,13 +1,25 @@
#pragma once #pragma once
bool create_exclusive_mutex(const wchar_t *name, HANDLE *pmutex); bool CreateExclusiveMutex(const wchar_t *name, HANDLE *pmutex);
bool create_event_with_security_descriptor(const wchar_t *descriptor, bool manualreset, bool initialstate, const wchar_t *name, HANDLE *pevent); bool CreateEventWithStringSecurityDescriptor(const wchar_t *descriptor, bool manualreset, bool initialstate, const wchar_t *name, HANDLE *pevent);
bool inject_self_into_process(DWORD dwProcessId, HMODULE *phModule); bool FileExists(const wchar_t *path);
bool inject_dll_into_process(DWORD dwProcessId, const wchar_t *pszFilename, size_t nLength, HMODULE *phModule); bool FileExistsExpandEnvironmentStrings(const wchar_t *path);
int FileInfoVerCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
size_t FindArgument(const wchar_t **argv, size_t argc, const wchar_t *val);
const wchar_t *path_find_fname(const wchar_t *path); bool FindIsDeviceServiceablePtr(const wchar_t *pFilename, HMODULE hModule, PVOID *ppfnIsDeviceServiceable);
bool path_change_fname(const wchar_t *srcpath, const wchar_t *fname, wchar_t *dstpath, size_t size); bool GetRemoteHModuleFromTh32ModuleSnapshot(HANDLE hSnapshot, const wchar_t *pLibFileName, HMODULE *phRemoteModule);
bool path_file_exists(const wchar_t *path); bool InjectSelfAndCreateRemoteThread(DWORD dwProcessId, LPTHREAD_START_ROUTINE pStartAddress, HANDLE SourceHandle, DWORD dwDesiredAccess);
bool path_expand_file_exists(const wchar_t *path); bool InjectLibraryByFileName(HANDLE hProcess, const wchar_t *pLibFileName, size_t nLength, HMODULE *phRemoteModule);
int ffi_ver_compare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev); bool InjectLibraryByLocalHModule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule);
bool IsWindowsVersion(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);
PVOID NtQueryKeyAlloc(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PULONG pResultLength);
PVOID RegGetValueAlloc(HKEY hkey, const wchar_t *pSubKey, const wchar_t *pValue, DWORD dwFlags, LPDWORD pdwType, LPDWORD pcbData);
LPQUERY_SERVICE_CONFIGW QueryServiceConfigByNameAlloc(SC_HANDLE hSCM, const wchar_t *pServiceName, LPDWORD pcbBufSize);
bool QueryServiceStatusProcessInfoByName(SC_HANDLE hSCM, const wchar_t *pServiceName, LPSERVICE_STATUS_PROCESS pServiceStatus);
bool QueryServiceGroupName(const LPQUERY_SERVICE_CONFIGW pServiceConfig, wchar_t *pGroupName, size_t nSize);
DWORD QueryServiceProcessId(SC_HANDLE hSCM, const wchar_t *pServiceName);
DWORD InferSvchostGroupProcessId(SC_HANDLE hSCM, const wchar_t *pGroupName);

View File

@@ -1,141 +1,88 @@
#include "stdafx.h" #include "stdafx.h"
#include "hooks.h" #include "hooks.h"
#include "patchwua.h"
#include "helpers.h" #include "helpers.h"
#include <Psapi.h>
LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW; LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW; LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
{ {
PWCH pBuffer = NULL;
DWORD MaximumLength = 0;
LSTATUS result; LSTATUS result;
DWORD cbData;
NTSTATUS Status;
ULONG ResultLength; ULONG ResultLength;
PKEY_NAME_INFORMATION pkni; PKEY_NAME_INFORMATION pkni;
size_t BufferCount; size_t NameCount;
int current; int current;
int pos; int pos;
wchar_t *tmp; LPWSTR fname;
size_t MaxCount; const WCHAR realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
size_t cbLength;
if ( (lpData && lpcbData) trace(L"");
&& (lpValueName && !_wcsicmp(lpValueName, L"ServiceDll")) ) {
// store original lpData buffer size // save original buffer size
cbData = *lpcbData; if ( lpData && lpcbData )
MaximumLength = *lpcbData;
trace(L"");
// 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 L1;
pkni = NULL;
ResultLength = 0;
do {
if ( ResultLength ) {
if ( pkni )
free(pkni);
pkni = malloc(ResultLength);
}
Status = NtQueryKey((HANDLE)hKey, KeyNameInformation, pkni, ResultLength, &ResultLength);
} while ( Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL );
if ( !NT_SUCCESS(Status) )
goto L2;
BufferCount = pkni->NameLength / sizeof(wchar_t);
// change key name to lower-case because there is no case-insensitive version of _snwscanf_s
if ( !_wcslwr_s(pkni->Name, BufferCount) && _snwscanf_s(pkni->Name, BufferCount,
L"\\registry\\machine\\system\\controlset%03d\\services\\wuauserv\\parameters%n", &current, &pos) == 1
&& pos == BufferCount ) {
const wchar_t *fname = path_find_fname((wchar_t *)lpData);
if ( !_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
|| !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix
|| !_wcsicmp(fname, L"WuaCpuFix.dll") ) {
MaxCount = cbData / sizeof(wchar_t);
tmp = malloc(cbData);
path_change_fname((wchar_t *)lpData, L"wuaueng.dll", tmp, MaxCount);
if ( path_expand_file_exists(tmp)
&& !wcscpy_s((wchar_t *)lpData, MaxCount, tmp)
&& SUCCEEDED(StringCbLengthW((PNZWCH)lpData, cbData, &cbLength)) ) {
*lpcbData = (DWORD)(cbLength + (sizeof UNICODE_NULL));
}
free(tmp);
}
}
L2: free(pkni);
} else {
// handle normally
result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
if ( result != ERROR_SUCCESS || !MaximumLength || !lpValueName || _wcsicmp(lpValueName, L"ServiceDll") )
return result;
trace(L"");
pBuffer = (wchar_t *)lpData;
trace(L"");
// get name of registry key being queried
pkni = NtQueryKeyAlloc((HANDLE)hKey, KeyNameInformation, &ResultLength);
trace(L"");
if ( !pkni )
return result;
trace(L"");
NameCount = pkni->NameLength / sizeof *pkni->Name;
// change key name to lower-case because there is no case-insensitive version of _snwscanf_s
if ( !_wcslwr_s(pkni->Name, NameCount)
&& _snwscanf_s(pkni->Name, NameCount, L"\\registry\\machine\\system\\controlset%03d\\services\\wuauserv\\parameters%n", &current, &pos) == 1
&& pos == NameCount ) {
trace(L"key=%.*ls", NameCount, pkni->Name);
fname = PathFindFileNameW(pBuffer);
trace(L"fname=%ls", fname);
if ( (!_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
|| !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix 64-bit
|| !_wcsicmp(fname, L"WuaCpuFix.dll"))
&& FileExistsExpandEnvironmentStrings(realpath)
&& SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, realpath)) ) {
trace(L"");
*lpcbData = sizeof realpath;
} }
L1: return result; }
free(pkni);
return result;
} }
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{ {
HMODULE result; HMODULE result;
DWORD dwLen;
LPVOID pBlock;
PLANGANDCODEPAGE ptl;
UINT cb;
wchar_t lpSubBlock[38];
wchar_t *lpszInternalName;
UINT uLen;
VS_FIXEDFILEINFO *pffi;
wchar_t path[MAX_PATH];
const wchar_t *fname;
MODULEINFO modinfo;
result = g_pfnLoadLibraryExW(lpFileName, hFile, dwFlags); result = g_pfnLoadLibraryExW(lpFileName, hFile, dwFlags);
if ( !result ) { if ( !result ) return result;
trace(L"Failed to load library: %ls (error code=%08X)", lpFileName, GetLastError());
goto L1;
}
trace(L"Loaded library: %ls", lpFileName); trace(L"Loaded library: %ls", lpFileName);
dwLen = GetFileVersionInfoSizeW(lpFileName, NULL); if ( FindIsDeviceServiceablePtr(lpFileName, result, (PVOID *)&g_pfnIsDeviceServiceable) ) {
if ( !dwLen ) DetourTransactionBegin();
goto L1; DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID *)&g_pfnIsDeviceServiceable, IsDeviceServiceable_hook);
pBlock = malloc(dwLen); DetourTransactionCommit();
if ( !GetFileVersionInfoW(lpFileName, 0, dwLen, pBlock)
|| !VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) )
goto L2;
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);
if ( VerQueryValueW(pBlock, lpSubBlock, (LPVOID *)&lpszInternalName, &uLen)
&& !_wcsicmp(lpszInternalName, L"wuaueng.dll") ) {
VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen);
GetModuleFileNameW(result, path, _countof(path));
fname = path_find_fname(path);
if ( (/*verify_win7() &&*/ ffi_ver_compare(pffi, 7, 6, 7601, 23714) != -1)
|| (/*verify_win81() &&*/ ffi_ver_compare(pffi, 7, 9, 9600, 18621) != -1) ) {
if ( GetModuleInformation(GetCurrentProcess(), result, &modinfo, sizeof(MODULEINFO)) ) {
if ( !patch_wua(modinfo.lpBaseOfDll, modinfo.SizeOfImage, fname) )
trace(L"Failed to patch %ls!", fname);
} }
} return result;
break;
}
}
L2: free(pBlock);
L1: return result;
} }
BOOL WINAPI IsDeviceServiceable_hook(void) BOOL WINAPI IsDeviceServiceable_hook(void)

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
typedef struct tagLANGANDCODEPAGE typedef struct
{ {
WORD wLanguage; WORD wLanguage;
WORD wCodePage; WORD wCodePage;
@@ -8,9 +8,12 @@ typedef struct tagLANGANDCODEPAGE
typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD); typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void);
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW; extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW; extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); 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); HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags);
BOOL WINAPI IsDeviceServiceable_hook(void);

View File

@@ -1,69 +0,0 @@
#include "stdafx.h"
#include "patchwua.h"
#ifdef _M_AMD64
static const PatchSet X64PatchSet = { "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????", 0xA, 0x12 };
#elif defined(_M_IX86)
static const PatchSet Win7X86PatchSet = { "833D????????00 743E E8???????? A3????????", 0x2, 0xF };
static const PatchSet Win81X86PatchSet = { "8BFF 51 833D????????00 7507 A1????????", 0x5, 0xD };
#endif
bool calculate_pointers(uintptr_t lpfn, const PatchSet *ps, LPBOOL *ppba, LPBOOL *ppbb)
{
#ifdef _M_AMD64
*ppba = (LPBOOL)(lpfn + ps->Offset1 + sizeof(uint32_t) + *(uint32_t *)(lpfn + ps->Offset1));
*ppbb = (LPBOOL)(lpfn + ps->Offset2 + sizeof(uint32_t) + *(uint32_t *)(lpfn + ps->Offset2));
return true;
#elif defined(_M_IX86)
*ppba = (LPBOOL)(*(uintptr_t *)(lpfn + ps->Offset1));
*ppbb = (LPBOOL)(*(uintptr_t *)(lpfn + ps->Offset2));
return true;
#endif
return false;
}
bool patch_wua(void *lpBaseOfDll, size_t SizeOfImage, const wchar_t *fname)
{
bool result = false;
const PatchSet *pps = NULL;
#ifdef _M_AMD64
pps = &X64PatchSet;
#elif defined(_M_IX86)
if ( 1/*verify_win7()*/ )
pps = &Win7X86PatchSet;
else if ( 1/*verify_win81()*/ )
pps = &Win81X86PatchSet;
else
goto L1;
#endif
size_t offset = patternfind(lpBaseOfDll, SizeOfImage, pps->Pattern);
if ( offset == -1 ) {
trace(L"No pattern match! (couldn't patch)");
goto L1;
}
uintptr_t ptr = (uintptr_t)lpBaseOfDll + offset;
LPBOOL pba, pbb;
if ( calculate_pointers((uintptr_t)ptr, pps, &pba, &pbb) ) {
DWORD flOldProtect;
if ( *pba == TRUE ) {
if ( VirtualProtect(pba, sizeof *pba, PAGE_READWRITE, &flOldProtect) ) {
*pba = FALSE;
trace(L"Patched value #1 at %ls!%p: %08X", fname, pba, *pba);
if ( !VirtualProtect(pba, sizeof *pba, flOldProtect, &flOldProtect) )
trace(L"Failed to restore memory region permissions at %ls!%p (error code=%08X)", fname, pba, GetLastError());
} else trace(L"Failed to change memory region permissions at %ls!%p (error code=%08X)", fname, pba, GetLastError());
}
if ( *pbb == FALSE ) {
if ( VirtualProtect(pbb, sizeof *pbb, PAGE_READWRITE, &flOldProtect) ) {
*pbb = TRUE;
trace(L"Patched value #2 at %ls!%p: %08X", fname, pbb, *pbb);
if ( !VirtualProtect(pbb, sizeof *pbb, flOldProtect, &flOldProtect) )
trace(L"Failed to restore memory region permissions at %ls!%p: (error code=%08X)", fname, pbb, GetLastError());
} else trace(L"Failed to change memory region permissions at %ls!%p (error code=%08X)", fname, pbb, GetLastError());
}
result = !*pba && *pbb;
}
L1: return result;
}

View File

@@ -1,11 +0,0 @@
#pragma once
typedef struct tagPatchSet
{
const char *Pattern;
const size_t Offset1;
const size_t Offset2;
} PatchSet;
bool calculate_pointers(uintptr_t lpfn, const PatchSet *ps, LPBOOL *ppba, LPBOOL *ppbb);
bool patch_wua(void *lpBaseOfDll, size_t SizeOfImage, const wchar_t *fname);

View File

@@ -94,7 +94,6 @@ static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
return (matched == 2); return (matched == 2);
} }
__declspec(noinline)
size_t patternfind(uint8_t *data, size_t datasize, const char *pattern) size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
{ {
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2; size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;

View File

@@ -2,7 +2,7 @@
typedef struct typedef struct
{ {
struct PatternNibble struct
{ {
uint8_t data; uint8_t data;
bool wildcard; bool wildcard;

View File

@@ -6,19 +6,44 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
{ {
HANDLE hMutex; HANDLE hMutex;
HANDLE hEvent; HANDLE hEvent;
bool Unloading; DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
wchar_t GroupName[256];
DWORD dwProcessId;
bool Unloading = false;
bool Lagging; bool Lagging;
SC_HANDLE hSCM; SC_HANDLE hSCM;
SC_HANDLE hService; SC_HANDLE hService;
SERVICE_NOTIFYW NotifyBuffer; SERVICE_NOTIFYW NotifyBuffer;
if ( !create_exclusive_mutex(L"Global\\{25020063-B5A7-4227-9FDF-25CB75E8C645}", &hMutex) ) if ( !CreateExclusiveMutex(L"Global\\{25020063-B5A7-4227-9FDF-25CB75E8C645}", &hMutex) )
return; return;
if ( !create_event_with_security_descriptor(L"D:(A;;0x001F0003;;;BA)", true, false, L"Global\\wufuc_UnloadEvent", &hEvent) ) if ( !CreateEventWithStringSecurityDescriptor(L"D:(A;;0x001F0003;;;BA)", true, false, L"Global\\wufuc_UnloadEvent", &hEvent) )
goto L1; goto L1;
Unloading = false; //hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
//if ( hSCM ) {
// trace(L"hSCM=%p", hSCM);
// pServiceConfig = QueryServiceConfigByNameAlloc(hSCM, L"wuauserv", &cbBufSize);
// trace(L"pServiceConfig=%p", pServiceConfig);
// if ( pServiceConfig ) {
// // inject into existing service host process if wuauserv is configured as shared process
// trace(L"pServiceConfig->dwServiceType=%lu", pServiceConfig->dwServiceType);
// if ( pServiceConfig->dwServiceType == SERVICE_WIN32_SHARE_PROCESS
// && QueryServiceGroupName(pServiceConfig, GroupName, _countof(GroupName)) ) {
// trace(L"GroupName=%ls", GroupName);
// dwProcessId = InferSvchostGroupProcessId(hSCM, GroupName);
// trace(L"dwProcessId=%lu", dwProcessId);
// if ( dwProcessId )
// InjectSelfAndCreateRemoteThread(dwProcessId, StartAddress, hEvent, SYNCHRONIZE);
// }
// free(pServiceConfig);
// }
// CloseServiceHandle(hSCM);
//}
do { do {
Lagging = false; Lagging = false;
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
@@ -57,12 +82,12 @@ L1: ReleaseMutex(hMutex);
void CALLBACK RUNDLL32_UnloadW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) void CALLBACK RUNDLL32_UnloadW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
{ {
HANDLE event; HANDLE hEvent;
event = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent"); hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( event ) { if ( hEvent ) {
SetEvent(event); SetEvent(hEvent);
CloseHandle(event); CloseHandle(hEvent);
} }
} }

View File

@@ -7,9 +7,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h>
#include <stdbool.h> #include <stdbool.h>
#include <strsafe.h> #include <strsafe.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <shellapi.h> #include <shellapi.h>
#include <Shlwapi.h>
#include <detours.h> #include <detours.h>
#include "patternfind.h" #include "patternfind.h"

View File

@@ -1,13 +1,20 @@
#include "stdafx.h" #include "stdafx.h"
#include "tracing.h" #include "tracing.h"
static FILE *steam;
void trace_(const wchar_t *const format, ...) void trace_(const wchar_t *const format, ...)
{ {
va_list argptr; va_list argptr;
int count;
wchar_t *buffer;
va_start(argptr, format); va_start(argptr, format);
int count = _vscwprintf(format, argptr) + 1;
wchar_t *buffer = calloc(count, sizeof(wchar_t)); count = _vscwprintf(format, argptr) + 1;
buffer = calloc(count, sizeof *buffer);
vswprintf_s(buffer, count, format, argptr); vswprintf_s(buffer, count, format, argptr);
va_end(argptr); va_end(argptr);
OutputDebugStringW(buffer); OutputDebugStringW(buffer);
free(buffer); free(buffer);

View File

@@ -2,10 +2,10 @@
#define WUFUC_RCH_INCLUDED #define WUFUC_RCH_INCLUDED
#pragma once #pragma once
#ifndef BUILD_COMMIT_VERSION #ifndef BUILD_COMMIT_VERSION
#define BUILD_COMMIT_VERSION 1.0.0.0 #define BUILD_COMMIT_VERSION 0.9.999.0
#endif #endif
#ifndef BUILD_VERSION_COMMA #ifndef BUILD_VERSION_COMMA
#define BUILD_VERSION_COMMA 1,0,0,0 #define BUILD_VERSION_COMMA 0,9,999,0
#endif #endif
#define STRINGIZE_(x) #x #define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x) #define STRINGIZE(x) STRINGIZE_(x)

View File

@@ -26,7 +26,6 @@
<ClInclude Include="targetver.h" /> <ClInclude Include="targetver.h" />
<ClInclude Include="helpers.h" /> <ClInclude Include="helpers.h" />
<ClInclude Include="tracing.h" /> <ClInclude Include="tracing.h" />
<ClInclude Include="patchwua.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="callbacks.c" /> <ClCompile Include="callbacks.c" />
@@ -42,7 +41,6 @@
<ClCompile Include="helpers.c" /> <ClCompile Include="helpers.c" />
<ClCompile Include="rundll32.c" /> <ClCompile Include="rundll32.c" />
<ClCompile Include="tracing.c" /> <ClCompile Include="tracing.c" />
<ClCompile Include="patchwua.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="exports.def" /> <None Include="exports.def" />
@@ -157,7 +155,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile> <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol> <EntryPointSymbol>
</EntryPointSymbol> </EntryPointSymbol>
<AdditionalDependencies>ntdll.lib;version.lib;detours.X86.MTd.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;version.lib;Shlwapi.lib;detours.X86.MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -179,7 +177,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile> <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol> <EntryPointSymbol>
</EntryPointSymbol> </EntryPointSymbol>
<AdditionalDependencies>ntdll.lib;version.lib;detours.X64.MTd.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;version.lib;Shlwapi.lib;detours.X64.MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<ResourceCompile> <ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -209,7 +207,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile> <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol> <EntryPointSymbol>
</EntryPointSymbol> </EntryPointSymbol>
<AdditionalDependencies>ntdll.lib;version.lib;detours.X86.MT.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;version.lib;Shlwapi.lib;detours.X86.MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SetChecksum>true</SetChecksum> <SetChecksum>true</SetChecksum>
</Link> </Link>
<ResourceCompile> <ResourceCompile>
@@ -238,7 +236,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation> <GenerateDebugInformation>false</GenerateDebugInformation>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile> <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<AdditionalDependencies>ntdll.lib;version.lib;detours.X64.MT.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ntdll.lib;version.lib;Shlwapi.lib;detours.X64.MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SetChecksum>true</SetChecksum> <SetChecksum>true</SetChecksum>
</Link> </Link>
<ResourceCompile> <ResourceCompile>

View File

@@ -15,9 +15,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="patchwua.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="callbacks.h"> <ClInclude Include="callbacks.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@@ -41,9 +38,6 @@
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="patchwua.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="callbacks.c"> <ClCompile Include="callbacks.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@@ -61,7 +61,7 @@ set "wufuc_dll=wufuc64.dll"
:dll_exists :dll_exists
set "wufuc_dll_fullpath=%~dp0%wufuc_dll%" set "wufuc_dll_fullpath=%~dp0%wufuc_dll%"
if exist "%wufuc_dll_fullpath%" goto :check_winver if exist "%wufuc_dll_fullpath%" goto :xml_exists
echo ERROR - Could not find %wufuc_dll_fullpath%! echo ERROR - Could not find %wufuc_dll_fullpath%!
echo. echo.
@@ -77,6 +77,19 @@ echo This error could also mean that your anti-virus deleted or quarantined %wuf
echo in which case, you will need to make an exception and restore it. echo in which case, you will need to make an exception and restore it.
goto :die goto :die
:xml_exists
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll_fullpath:\=\\%'" get Version /value ^| find "="') do set "%%i"
set "wufuc_xml=%~dp0wufuc_ScheduledTask.xml"
if exist "%wufuc_xml%" goto :check_winver
echo ERROR - Could not find %wufuc_xml%!
echo.
echo This most likely means you didn't extract all the files from the archive.
echo.
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_winver :check_winver
ver | findstr " 6\.1\." >nul && ( ver | findstr " 6\.1\." >nul && (
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE% echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
@@ -98,8 +111,7 @@ echo.
goto :die goto :die
:check_mode :check_mode
set "regkey=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\svchost.exe" set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
set "wufuc_dll_target=%systemfolder%\%wufuc_dll%"
if "%UNINSTALL%"=="1" goto :confirm_uninstall if "%UNINSTALL%"=="1" goto :confirm_uninstall
@@ -113,19 +125,24 @@ echo systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
echo. echo.
echo Please be absolutely sure you really need wufuc before proceeding. echo Please be absolutely sure you really need wufuc before proceeding.
echo. echo.
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll_fullpath:\=\\%'" get Version /value ^| find "="') do set "%%i"
set /p CONTINUE_INSTALL=Enter 'Y' if you want to install wufuc %Version%: set /p CONTINUE_INSTALL=Enter 'Y' if you want to install wufuc %Version%:
if /I "%CONTINUE_INSTALL%"=="Y" goto :install if /I "%CONTINUE_INSTALL%"=="Y" goto :install
goto :cancel goto :cancel
:install :install
call :uninstall call :uninstall
copy /Y "%wufuc_dll_fullpath%" "%wufuc_dll_target%" && ( net start Schedule
reg add "%regkey%" /v VerifierDlls /t REG_SZ /d "%wufuc_dll%" /f schtasks /Create /XML "%wufuc_xml%" /TN "%wufuc_task%" /F
reg add "%regkey%" /v GlobalFlag /t REG_DWORD /d 0x00000100 /f schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\System32\rundll32.exe' """%wufuc_dll_fullpath%""",RUNDLL32_Start"
) schtasks /Change /TN "%wufuc_task%" /ENABLE
rundll32 "%wufuc_dll_fullpath%",RUNDLL32_Unload
net stop wuauserv
schtasks /Run /TN "%wufuc_task%"
timeout /nobreak /t 3 >nul
net start wuauserv
echo. echo.
echo You will need to restart your PC to finish installing wufuc. echo You may need to restart your PC to finish installing wufuc.
goto :confirm_restart goto :confirm_restart
:: END INSTALL MODE /////////////////////////////////////////////////////////// :: END INSTALL MODE ///////////////////////////////////////////////////////////
@@ -139,20 +156,21 @@ goto :cancel
:uninstall_stub :uninstall_stub
call :uninstall call :uninstall
echo You will need to restart your PC to finish uninstalling wufuc. echo You may need to restart your PC to finish uninstalling wufuc.
goto :confirm_restart goto :confirm_restart
:uninstall :uninstall
:: restore wuaueng.dll if it was modified by 0.1-0.5 :: restore wuaueng.dll if it was modified by 0.1-0.5
sfc /SCANFILE="%systemfolder%\wuaueng.dll" sfc /SCANFILE="%systemfolder%\wuaueng.dll"
:: remove traces of wufuc 0.6-0.7 :: remove traces of wufuc 0.6-0.7, 0.9.999+
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
schtasks /Query /TN "%wufuc_task%" >nul 2>&1 && ( schtasks /Query /TN "%wufuc_task%" >nul 2>&1 && (
schtasks /Delete /TN "%wufuc_task%" /F ) schtasks /Delete /TN "%wufuc_task%" /F )
rundll32 "%wufuc_dll_fullpath%",RUNDLL32_LegacyUnload rundll32 "%wufuc_dll_fullpath%",RUNDLL32_Unload
:: remove traces of wufuc >=0.8 :: remove traces of wufuc 0.8.x
set "regkey=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\svchost.exe"
set "wufuc_dll_target=%systemfolder%\%wufuc_dll%"
reg query "%regkey%" >nul 2>&1 || goto :delete_target reg query "%regkey%" >nul 2>&1 || goto :delete_target
reg delete "%regkey%" /f || goto :skip_delete reg delete "%regkey%" /f || goto :skip_delete
:delete_target :delete_target

Binary file not shown.