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
**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)
@@ -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 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
[![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.
## 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
@@ -96,12 +96,19 @@ There was a fundamental issue with the method I tried using in this version that
## 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).
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
- 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).
[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:
only:
- master

View File

@@ -1,17 +1,14 @@
#include "stdafx.h"
#include "callbacks.h"
#include "hooks.h"
#include "helpers.h"
#include <Psapi.h>
VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
{
HMODULE hModule;
switch ( pNotifyBuffer->dwNotificationStatus ) {
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;
case ERROR_SERVICE_MARKED_FOR_DELETE:
SetEvent((HANDLE)pNotifyBuffer->pContext);
@@ -20,3 +17,68 @@ VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
if ( 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
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 ) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
case DLL_PROCESS_DETACH:
break;

View File

@@ -1,8 +1,9 @@
#include "stdafx.h"
#include "helpers.h"
#include "hooks.h"
#include <sddl.h>
bool create_exclusive_mutex(const wchar_t *name, HANDLE *pmutex)
bool CreateExclusiveMutex(const wchar_t *name, HANDLE *pmutex)
{
HANDLE mutex;
@@ -18,7 +19,7 @@ bool create_exclusive_mutex(const wchar_t *name, HANDLE *pmutex)
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 };
HANDLE event;
@@ -33,109 +34,29 @@ bool create_event_with_security_descriptor(const wchar_t *descriptor, bool manua
return false;
}
bool inject_self_into_process(DWORD dwProcessId, HMODULE *phModule)
{
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)
bool FileExists(const wchar_t *path)
{
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
}
bool path_expand_file_exists(const wchar_t *path)
bool FileExistsExpandEnvironmentStrings(const wchar_t *path)
{
bool result;
wchar_t *dst;
LPWSTR dst;
DWORD buffersize;
DWORD size;
dst = NULL;
size = 0;
do {
if ( size ) {
if ( dst )
free(dst);
dst = calloc(size, sizeof *dst);
}
buffersize = size;
buffersize = ExpandEnvironmentStringsW(path, NULL, 0);
dst = calloc(buffersize, sizeof *dst);
size = ExpandEnvironmentStringsW(path, dst, buffersize);
} while ( buffersize < size );
result = path_file_exists(dst);
if ( !size || size > buffersize )
return false;
result = FileExists(dst);
free(dst);
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;
@@ -148,16 +69,361 @@ int ffi_ver_compare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuil
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++ ) {
if ( !_wcsicmp(argv[i], option) )
index = i;
}
if ( index == -1 )
return index;
dwLen = GetFileVersionInfoSizeW(pFilename, NULL);
if ( !dwLen ) return result;
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
bool create_exclusive_mutex(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 CreateExclusiveMutex(const wchar_t *name, HANDLE *pmutex);
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 inject_dll_into_process(DWORD dwProcessId, const wchar_t *pszFilename, size_t nLength, HMODULE *phModule);
bool FileExists(const wchar_t *path);
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 path_change_fname(const wchar_t *srcpath, const wchar_t *fname, wchar_t *dstpath, size_t size);
bool path_file_exists(const wchar_t *path);
bool path_expand_file_exists(const wchar_t *path);
int ffi_ver_compare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
bool FindIsDeviceServiceablePtr(const wchar_t *pFilename, HMODULE hModule, PVOID *ppfnIsDeviceServiceable);
bool GetRemoteHModuleFromTh32ModuleSnapshot(HANDLE hSnapshot, const wchar_t *pLibFileName, HMODULE *phRemoteModule);
bool InjectSelfAndCreateRemoteThread(DWORD dwProcessId, LPTHREAD_START_ROUTINE pStartAddress, HANDLE SourceHandle, DWORD dwDesiredAccess);
bool InjectLibraryByFileName(HANDLE hProcess, const wchar_t *pLibFileName, size_t nLength, HMODULE *phRemoteModule);
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 "hooks.h"
#include "patchwua.h"
#include "helpers.h"
#include <Psapi.h>
LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
{
PWCH pBuffer = NULL;
DWORD MaximumLength = 0;
LSTATUS result;
DWORD cbData;
NTSTATUS Status;
ULONG ResultLength;
PKEY_NAME_INFORMATION pkni;
size_t BufferCount;
size_t NameCount;
int current;
int pos;
wchar_t *tmp;
size_t MaxCount;
size_t cbLength;
LPWSTR fname;
const WCHAR realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
if ( (lpData && lpcbData)
&& (lpValueName && !_wcsicmp(lpValueName, L"ServiceDll")) ) {
trace(L"");
// store original lpData buffer size
cbData = *lpcbData;
// save original buffer size
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);
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 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);
if ( !result ) {
trace(L"Failed to load library: %ls (error code=%08X)", lpFileName, GetLastError());
goto L1;
}
if ( !result ) return result;
trace(L"Loaded library: %ls", lpFileName);
dwLen = GetFileVersionInfoSizeW(lpFileName, NULL);
if ( !dwLen )
goto L1;
pBlock = malloc(dwLen);
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);
if ( FindIsDeviceServiceablePtr(lpFileName, result, (PVOID *)&g_pfnIsDeviceServiceable) ) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID *)&g_pfnIsDeviceServiceable, IsDeviceServiceable_hook);
DetourTransactionCommit();
}
}
break;
}
}
L2: free(pBlock);
L1: return result;
return result;
}
BOOL WINAPI IsDeviceServiceable_hook(void)

View File

@@ -1,6 +1,6 @@
#pragma once
typedef struct tagLANGANDCODEPAGE
typedef struct
{
WORD wLanguage;
WORD wCodePage;
@@ -8,9 +8,12 @@ typedef struct tagLANGANDCODEPAGE
typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void);
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
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);
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);
}
__declspec(noinline)
size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
{
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;

View File

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

View File

@@ -6,19 +6,44 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
{
HANDLE hMutex;
HANDLE hEvent;
bool Unloading;
DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
wchar_t GroupName[256];
DWORD dwProcessId;
bool Unloading = false;
bool Lagging;
SC_HANDLE hSCM;
SC_HANDLE hService;
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;
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;
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 {
Lagging = false;
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)
{
HANDLE event;
HANDLE hEvent;
event = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( event ) {
SetEvent(event);
CloseHandle(event);
hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( hEvent ) {
SetEvent(hEvent);
CloseHandle(hEvent);
}
}

View File

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

View File

@@ -1,13 +1,20 @@
#include "stdafx.h"
#include "tracing.h"
static FILE *steam;
void trace_(const wchar_t *const format, ...)
{
va_list argptr;
int count;
wchar_t *buffer;
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);
va_end(argptr);
OutputDebugStringW(buffer);
free(buffer);

View File

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

View File

@@ -26,7 +26,6 @@
<ClInclude Include="targetver.h" />
<ClInclude Include="helpers.h" />
<ClInclude Include="tracing.h" />
<ClInclude Include="patchwua.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="callbacks.c" />
@@ -42,7 +41,6 @@
<ClCompile Include="helpers.c" />
<ClCompile Include="rundll32.c" />
<ClCompile Include="tracing.c" />
<ClCompile Include="patchwua.c" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />
@@ -157,7 +155,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<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>
<ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -179,7 +177,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<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>
<ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -209,7 +207,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<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>
</Link>
<ResourceCompile>
@@ -238,7 +236,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<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>
</Link>
<ResourceCompile>

View File

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

View File

@@ -61,7 +61,7 @@ set "wufuc_dll=wufuc64.dll"
:dll_exists
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.
@@ -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.
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
ver | findstr " 6\.1\." >nul && (
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
@@ -98,8 +111,7 @@ echo.
goto :die
:check_mode
set "regkey=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\svchost.exe"
set "wufuc_dll_target=%systemfolder%\%wufuc_dll%"
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
if "%UNINSTALL%"=="1" goto :confirm_uninstall
@@ -113,19 +125,24 @@ echo systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
echo.
echo Please be absolutely sure you really need wufuc before proceeding.
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%:
if /I "%CONTINUE_INSTALL%"=="Y" goto :install
goto :cancel
:install
call :uninstall
copy /Y "%wufuc_dll_fullpath%" "%wufuc_dll_target%" && (
reg add "%regkey%" /v VerifierDlls /t REG_SZ /d "%wufuc_dll%" /f
reg add "%regkey%" /v GlobalFlag /t REG_DWORD /d 0x00000100 /f
)
net start Schedule
schtasks /Create /XML "%wufuc_xml%" /TN "%wufuc_task%" /F
schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\System32\rundll32.exe' """%wufuc_dll_fullpath%""",RUNDLL32_Start"
schtasks /Change /TN "%wufuc_task%" /ENABLE
rundll32 "%wufuc_dll_fullpath%",RUNDLL32_Unload
net stop wuauserv
schtasks /Run /TN "%wufuc_task%"
timeout /nobreak /t 3 >nul
net start wuauserv
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
:: END INSTALL MODE ///////////////////////////////////////////////////////////
@@ -139,20 +156,21 @@ goto :cancel
:uninstall_stub
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
:uninstall
:: restore wuaueng.dll if it was modified by 0.1-0.5
sfc /SCANFILE="%systemfolder%\wuaueng.dll"
:: remove traces of wufuc 0.6-0.7
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
:: remove traces of wufuc 0.6-0.7, 0.9.999+
schtasks /Query /TN "%wufuc_task%" >nul 2>&1 && (
schtasks /Delete /TN "%wufuc_task%" /F )
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 delete "%regkey%" /f || goto :skip_delete
:delete_target

Binary file not shown.