switch back from hooking IsDeviceServiceable to direct variable patching (fixes #146)

This commit is contained in:
zeffy
2018-04-02 13:23:43 -07:00
parent c7e94426a8
commit a8adfa3c08
16 changed files with 235 additions and 188 deletions

View File

@@ -12,14 +12,14 @@
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <minhook.h> #include <minhook.h>
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer) VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer)
{ {
switch ( pNotifyBuffer->dwNotificationStatus ) { switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS: case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId ) if ( pNotifyBuffer->ServiceStatus.dwProcessId )
wufuc_inject( wufuc_inject(
pNotifyBuffer->ServiceStatus.dwProcessId, pNotifyBuffer->ServiceStatus.dwProcessId,
(LPTHREAD_START_ROUTINE)cb_start, (LPTHREAD_START_ROUTINE)thread_start_callback,
(ptrlist_t *)pNotifyBuffer->pContext); (ptrlist_t *)pNotifyBuffer->pContext);
break; break;
case ERROR_SERVICE_MARKED_FOR_DELETE: case ERROR_SERVICE_MARKED_FOR_DELETE:
@@ -30,7 +30,7 @@ VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames); LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
} }
DWORD WINAPI cb_start(HANDLE *pParam) DWORD WINAPI thread_start_callback(HANDLE *pParam)
{ {
HANDLE handles[2]; HANDLE handles[2];
HANDLE hCrashMutex; HANDLE hCrashMutex;
@@ -41,7 +41,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
LPQUERY_SERVICE_CONFIGW pServiceConfig; LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType; DWORD dwServiceType;
const wchar_t szKernel32Dll[] = L"kernel32.dll"; const wchar_t szKernel32Dll[] = L"kernel32.dll";
const wchar_t szKernelBaseDll[] = L"KernelBase.dll"; const wchar_t szKernelBaseDll[] = L"kernelbase.dll";
const wchar_t *pszModule; const wchar_t *pszModule;
MH_STATUS status; MH_STATUS status;
int tmp; int tmp;
@@ -63,7 +63,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
// acquire child mutex, this should be immediate. // acquire child mutex, this should be immediate.
if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) { if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) {
log_error(L"Failed to acquire child mutex within five seconds. (%p)", hCrashMutex); log_error(L"Failed to acquire crash mutex within five seconds. (%p)", hCrashMutex);
goto close_handles; goto close_handles;
} }
SetEvent(hProceedEvent); SetEvent(hProceedEvent);
@@ -112,7 +112,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
} else log_error(L"Failed to create RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status)); } else log_error(L"Failed to create RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status));
} }
// query the ServiceDll path after applying our compat hook so that it // query the ServiceDll path after applying our compat hook so that it
// is correct // is consistent
str = (wchar_t *)reg_query_value_alloc(HKEY_LOCAL_MACHINE, str = (wchar_t *)reg_query_value_alloc(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters", L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
L"ServiceDll", NULL, NULL); L"ServiceDll", NULL, NULL);
@@ -142,7 +142,7 @@ abort_hook:
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) { || GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
// hook IsDeviceServiceable if wuaueng.dll is already loaded // hook IsDeviceServiceable if wuaueng.dll is already loaded
wufuc_hook(hModule); wufuc_patch(hModule);
FreeLibrary(hModule); FreeLibrary(hModule);
} }
// wait for unload event or the main mutex to be released or abandoned, // wait for unload event or the main mutex to be released or abandoned,

View File

@@ -1,4 +1,4 @@
#pragma once #pragma once
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer); VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer);
DWORD WINAPI cb_start(HANDLE *pParam); DWORD WINAPI thread_start_callback(HANDLE *pParam);

View File

@@ -9,7 +9,6 @@ wchar_t *g_pszWUServiceDll;
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)
{ {
@@ -88,13 +87,7 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla
&& (!_wcsicmp(lpFileName, g_pszWUServiceDll) && (!_wcsicmp(lpFileName, g_pszWUServiceDll)
|| !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) { || !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) {
wufuc_hook(result); wufuc_patch(result);
} }
return result; return result;
} }
BOOL WINAPI IsDeviceServiceable_hook(void)
{
log_debug(L"Entered stub function.");
return TRUE;
}

View File

@@ -3,18 +3,14 @@
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 wchar_t *g_pszWUServiceDll; extern wchar_t *g_pszWUServiceDll;
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;
extern PVOID g_ptRegQueryValueExW; extern PVOID g_ptRegQueryValueExW;
extern PVOID g_ptLoadLibraryExW; extern PVOID g_ptLoadLibraryExW;
extern PVOID g_ptIsDeviceServiceable;
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

@@ -49,7 +49,7 @@ bool mod_inject_and_begin_thread(
hThread = CreateRemoteThread(hProcess, hThread = CreateRemoteThread(hProcess,
NULL, NULL,
0, 0,
(LPTHREAD_START_ROUTINE)RtlOffsetToPointer(hRemoteModule, offset), OffsetToPointer(hRemoteModule, offset),
pBaseAddress, pBaseAddress,
0, 0,
NULL); NULL);

View File

@@ -46,7 +46,7 @@ bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity)
if ( tmp ) { if ( tmp ) {
ZeroMemory(tmp, vsize + tsize); ZeroMemory(tmp, vsize + tsize);
list->values = tmp; list->values = tmp;
list->tags = (uint32_t *)RtlOffsetToPointer(tmp, vsize); list->tags = OffsetToPointer(tmp, vsize);
list->capacity = c; list->capacity = c;
list->maxCapacity = maxCapacity; list->maxCapacity = maxCapacity;
list->count = 0; list->count = 0;
@@ -129,7 +129,7 @@ bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag)
ZeroMemory(tmp1, vsize); ZeroMemory(tmp1, vsize);
tmp2 = (uint32_t *)RtlOffsetToPointer(tmp1, vsize); tmp2 = OffsetToPointer(tmp1, vsize);
ZeroMemory(tmp2, tsize); ZeroMemory(tmp2, tsize);
if ( memmove_s(tmp1, vsize, list->values, list->count * (sizeof *list->values)) if ( memmove_s(tmp1, vsize, list->values, list->count * (sizeof *list->values))

View File

@@ -0,0 +1,84 @@
#include "stdafx.h"
#include "resourcehelper.h"
#include "log.h"
void *res_get_version_info(HMODULE hModule)
{
HRSRC hResInfo;
DWORD dwSize;
HGLOBAL hResData;
LPVOID pRes;
void *result;
hResInfo = FindResourceW(hModule,
MAKEINTRESOURCEW(VS_VERSION_INFO),
MAKEINTRESOURCEW(RT_VERSION));
if ( !hResInfo ) return NULL;
dwSize = SizeofResource(hModule, hResInfo);
if ( !dwSize ) return NULL;
hResData = LoadResource(hModule, hResInfo);
if ( !hResData ) return NULL;
pRes = LockResource(hResData);
if ( !pRes ) return NULL;
result = malloc(dwSize);
if ( !result ) return NULL;
if ( memcpy_s(result, dwSize, pRes, dwSize) ) {
free(result);
result = NULL;
}
return result;
}
wchar_t *res_query_string_file_info(const void *pBlock,
LANGANDCODEPAGE lcp,
const wchar_t *pszStringName,
size_t *pcchLength)
{
const wchar_t fmt[] = L"\\StringFileInfo\\%04x%04x\\%ls";
int ret;
int count;
wchar_t *pszSubBlock;
wchar_t *result = NULL;
UINT uLen;
ret = _scwprintf(fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
if ( ret == -1 ) return NULL;
count = ret + 1;
pszSubBlock = calloc(count, sizeof *pszSubBlock);
if ( !pszSubBlock ) return NULL;
ret = swprintf_s(pszSubBlock, count, fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
if ( ret != -1
&& VerQueryValueW(pBlock, pszSubBlock, &(LPVOID)result, &uLen)
&& pcchLength )
*pcchLength = uLen;
free(pszSubBlock);
return result;
}
PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pCount)
{
PLANGANDCODEPAGE result = NULL;
UINT uLen;
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", &(LPVOID)result, &uLen) )
*pCount = uLen / (sizeof *result);
return result;
}
VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock)
{
VS_FIXEDFILEINFO *result;
UINT uLen;
if ( VerQueryValueW(pBlock, L"\\", &(LPVOID)result, &uLen) )
return result;
return NULL;
}

View File

@@ -0,0 +1,18 @@
#pragma once
typedef struct
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
void *res_get_version_info(HMODULE hModule);
wchar_t *res_query_string_file_info(const void *pBlock,
LANGANDCODEPAGE lcp,
const wchar_t *pszStringName,
size_t *pcchLength);
PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pcbData);
VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock);

View File

@@ -59,11 +59,11 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd,
dwProcessId = svc_heuristic_process_id(hSCM, hService); dwProcessId = svc_heuristic_process_id(hSCM, hService);
if ( dwProcessId ) if ( dwProcessId )
wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)cb_start, &list); wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)thread_start_callback, &list);
} }
ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer); ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer);
NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)cb_service_notify; NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)service_notify_callback;
NotifyBuffer.pContext = (PVOID)&list; NotifyBuffer.pContext = (PVOID)&list;
while ( !Unloading && !Lagging ) { while ( !Unloading && !Lagging ) {
e = NotifyServiceStatusChangeW(hService, e = NotifyServiceStatusChangeW(hService,

View File

@@ -29,4 +29,4 @@
extern IMAGE_DOS_HEADER __ImageBase; extern IMAGE_DOS_HEADER __ImageBase;
#define PIMAGEBASE ((HMODULE)&__ImageBase) #define PIMAGEBASE ((HMODULE)&__ImageBase)
#define OffsetToPointer(Base, Offset) ((void *)(((uint8_t *)(Base)) + ((ptrdiff_t)(Offset))))

View File

@@ -14,81 +14,6 @@ int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor
return 0; return 0;
} }
bool ver_get_version_info_from_hmodule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData)
{
bool result = false;
UINT cbData;
HRSRC hResInfo;
DWORD dwSize;
HGLOBAL hResData;
LPVOID pRes;
LPVOID pCopy;
LPVOID pBuffer;
UINT uLen;
if ( !pcbData ) return result;
cbData = *pcbData;
hResInfo = FindResourceW(hModule,
MAKEINTRESOURCEW(VS_VERSION_INFO),
RT_VERSION);
if ( !hResInfo ) return result;
dwSize = SizeofResource(hModule, hResInfo);
if ( !dwSize ) return result;
hResData = LoadResource(hModule, hResInfo);
if ( !hResData ) return result;
pRes = LockResource(hResData);
if ( !pRes ) return result;
pCopy = malloc(dwSize);
if ( !pCopy ) return result;
if ( memcpy_s(pCopy, dwSize, pRes, dwSize)
|| !VerQueryValueW(pCopy, pszSubBlock, &pBuffer, &uLen) )
goto cleanup;
if ( !_wcsnicmp(pszSubBlock, L"\\StringFileInfo\\", 16) )
*pcbData = uLen * sizeof(wchar_t);
else
*pcbData = uLen;
if ( !pData ) {
result = true;
goto cleanup;
}
if ( cbData < *pcbData
|| memcpy_s(pData, cbData, pBuffer, *pcbData) )
goto cleanup;
result = true;
cleanup:
free(pCopy);
return result;
}
LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData)
{
UINT cbData = 0;
LPVOID result = NULL;
if ( !ver_get_version_info_from_hmodule(hModule, pszSubBlock, NULL, &cbData) )
return result;
result = malloc(cbData);
if ( !result ) return result;
if ( ver_get_version_info_from_hmodule(hModule, pszSubBlock, result, &cbData) ) {
*pcbData = cbData;
} else {
free(result);
result = NULL;
}
return result;
}
bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{ {
DWORDLONG dwlConditionMask = 0; DWORDLONG dwlConditionMask = 0;

View File

@@ -1,6 +1,4 @@
#pragma once #pragma once
int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev); int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
bool ver_get_version_info_from_hmodule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData);
LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData);
bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor); bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);

View File

@@ -6,13 +6,14 @@
#include "modulehelper.h" #include "modulehelper.h"
#include "mutexhelper.h" #include "mutexhelper.h"
#include "patternfind.h" #include "patternfind.h"
#include "resourcehelper.h"
#include "versionhelper.h" #include "versionhelper.h"
#include <minhook.h> #include <minhook.h>
HANDLE g_hMainMutex; HANDLE g_hMainMutex;
bool close_remote_handle(HANDLE hProcess, HANDLE hObject) static bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
{ {
bool result = false; bool result = false;
DWORD ExitCode; DWORD ExitCode;
@@ -99,96 +100,119 @@ close_mutex:
return result; return result;
} }
bool wufuc_hook(HMODULE hModule) static int wufuc_get_patch_info(VS_FIXEDFILEINFO *pffi, PATCHINFO *ppi)
{ {
bool result = false; #ifdef _WIN64
PLANGANDCODEPAGE ptl; if ( ver_verify_version_info(6, 1, 0) && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1
HANDLE hProcess; || ver_verify_version_info(6, 3, 0) && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
UINT cbtl;
wchar_t SubBlock[38]; ppi->pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
ppi->off1 = 0xa;
ppi->off2 = 0x12;
return 0;
}
#elif _WIN32
if ( ver_verify_version_info(6, 1, 0)
&& ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1 ) {
ppi->pattern = "833D????????00 743E E8???????? A3????????";
ppi->off1 = 0x2;
ppi->off2 = 0xf;
return 0;
} else if ( ver_verify_version_info(6, 3, 0)
&& ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
ppi->pattern = "8BFF 51 833D????????00 7507 A1????????";
ppi->off1 = 0x5;
ppi->off2 = 0xd;
return 0;
}
#endif
return 1;
}
static int wufuc_get_patch_ptrs(const PATCHINFO *ppi, uintptr_t pfn, PBOOL *ppval1, PBOOL *ppval2)
{
#ifdef _WIN64
*ppval1 = (PBOOL)(pfn + ppi->off1 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off1));
*ppval2 = (PBOOL)(pfn + ppi->off2 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off2));
return 0;
#elif _WIN32
*ppval1 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off1));
*ppval2 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off2));
return 0;
#else
return 1;
#endif
}
void wufuc_patch(HMODULE hModule)
{
void *pBlock;
PATCHINFO pi;
size_t count;
PLANGANDCODEPAGE plcp;
wchar_t *pInternalName; wchar_t *pInternalName;
UINT cbInternalName;
VS_FIXEDFILEINFO *pffi; VS_FIXEDFILEINFO *pffi;
UINT cbffi;
bool tmp;
MODULEINFO modinfo; MODULEINFO modinfo;
size_t offset; size_t offset;
LPVOID pTarget = NULL; void *pfn;
MH_STATUS status; DWORD fOldProtect;
PBOOL pval1;
PBOOL pval2;
ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl); pBlock = res_get_version_info(hModule);
if ( !ptl ) { if ( !pBlock ) goto free_pBlock;
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
return false; plcp = res_query_var_file_info(pBlock, &count);
if ( !plcp ) goto free_pBlock;
for ( size_t i = 0; i < count; i++ ) {
pInternalName = res_query_string_file_info(pBlock, plcp[i], L"InternalName", NULL);
if ( pInternalName && !_wcsicmp(pInternalName, L"wuaueng.dll") )
goto cont_patch;
} }
hProcess = GetCurrentProcess(); goto free_pBlock;
for ( size_t i = 0, count = (cbtl / sizeof *ptl); i < count; i++ ) { cont_patch:
if ( swprintf_s(SubBlock, pffi = res_query_fixed_file_info(pBlock);
_countof(SubBlock), if ( !pffi ) goto free_pBlock;
L"\\StringFileInfo\\%04x%04x\\InternalName",
ptl[i].wLanguage,
ptl[i].wCodePage) == -1 )
continue;
pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName); if ( wufuc_get_patch_info(pffi, &pi) ) {
if ( !pInternalName ) { log_warning(L"Unsupported Windows Update Agent version: %hu.%hu.%hu.%hu",
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
continue;
}
// identify wuaueng.dll by its resource data
if ( _wcsicmp(pInternalName, L"wuaueng.dll") ) {
log_error(L"Module internal name does not match! (InternalName=%ls)", pInternalName);
goto free_iname;
}
pffi = ver_get_version_info_from_hmodule_alloc(hModule, L"\\", &cbffi);
if ( !pffi ) {
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
break;
}
// assure wuaueng.dll version is supported
tmp = ((ver_verify_version_info(6, 1, 0) && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1)
|| (ver_verify_version_info(6, 3, 0) && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1));
log_info(L"%ls Windows Update Agent version: %hu.%hu.%hu.%hu",
tmp ? L"Supported" : L"Unsupported",
HIWORD(pffi->dwProductVersionMS), HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS), LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS), HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS)); LOWORD(pffi->dwProductVersionLS));
free(pffi); goto free_pBlock;
if ( !tmp ) break;
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)",
hModule, GetLastError());
break;
}
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage,
#ifdef _WIN64
"FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"
#else
ver_verify_version_info(6, 1, 0)
? "833D????????00 743E E8???????? A3????????"
: "8BFF 51 833D????????00 7507 A1????????"
#endif
);
if ( offset != -1 ) {
pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset);
log_info(L"Matched IsDeviceServiceable function! (Offset=%IX, Address=%p)", offset, pTarget);
status = MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL);
if ( status == MH_OK ) {
status = MH_EnableHook(pTarget);
if ( status == MH_OK )
log_info(L"Hooked IsDeviceServiceable! (Address=%p)", pTarget);
else log_error(L"Failed to enable IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status));
} else log_error(L"Failed to create IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status));
} else log_info(L"Couldn't match IsDeviceServiceable function! (Already patched?)");
free_iname:
free(pInternalName);
break;
} }
free(ptl); log_info(L"Supported Windows Update Agent version: %hu.%hu.%hu.%hu",
return result; HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
if ( GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pi.pattern);
if ( offset != -1 ) {
pfn = OffsetToPointer(modinfo.lpBaseOfDll, offset);
log_info(L"Matched %ls!IsDeviceServiceable function! (Offset=%IX, Address=%p)",
pInternalName, offset, pfn);
if ( !wufuc_get_patch_ptrs(&pi, (uintptr_t)pfn, &pval1, &pval2) ) {
if ( *pval1 && VirtualProtect(pval1, sizeof *pval1, PAGE_READWRITE, &fOldProtect) ) {
*pval1 = FALSE;
VirtualProtect(pval1, sizeof *pval1, fOldProtect, &fOldProtect);
log_info(L"Patched variable! (Address=%p)", pval1);
}
if ( !*pval2 && VirtualProtect(pval2, sizeof *pval2, PAGE_READWRITE, &fOldProtect) ) {
*pval2 = TRUE;
VirtualProtect(pval2, sizeof *pval2, fOldProtect, &fOldProtect);
log_info(L"Patched variable! (Address=%p)", pval2);
}
}
} else log_info(L"Couldn't match IsDeviceServiceable function!");
} else log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", hModule, GetLastError());
free_pBlock:
free(pBlock);
} }

View File

@@ -1,10 +1,11 @@
#pragma once #pragma once
typedef struct typedef struct _PATCHINFO
{ {
WORD wLanguage; const char *pattern;
WORD wCodePage; size_t off1;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE; size_t off2;
} PATCHINFO;
#define SVCHOST_CRASH_THRESHOLD 3 #define SVCHOST_CRASH_THRESHOLD 3
extern HANDLE g_hMainMutex; extern HANDLE g_hMainMutex;
@@ -12,4 +13,4 @@ extern HANDLE g_hMainMutex;
bool wufuc_inject(DWORD dwProcessId, bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pStartAddress, LPTHREAD_START_ROUTINE pStartAddress,
ptrlist_t *list); ptrlist_t *list);
bool wufuc_hook(HMODULE hModule); void wufuc_patch(HMODULE hModule);

View File

@@ -26,6 +26,7 @@
<ClInclude Include="log.h" /> <ClInclude Include="log.h" />
<ClInclude Include="modulehelper.h" /> <ClInclude Include="modulehelper.h" />
<ClInclude Include="registryhelper.h" /> <ClInclude Include="registryhelper.h" />
<ClInclude Include="resourcehelper.h" />
<ClInclude Include="servicehelper.h" /> <ClInclude Include="servicehelper.h" />
<ClInclude Include="versionhelper.h" /> <ClInclude Include="versionhelper.h" />
<ClInclude Include="hooks.h" /> <ClInclude Include="hooks.h" />
@@ -41,6 +42,7 @@
<ClCompile Include="ptrlist.c" /> <ClCompile Include="ptrlist.c" />
<ClCompile Include="modulehelper.c" /> <ClCompile Include="modulehelper.c" />
<ClCompile Include="registryhelper.c" /> <ClCompile Include="registryhelper.c" />
<ClCompile Include="resourcehelper.c" />
<ClCompile Include="servicehelper.c" /> <ClCompile Include="servicehelper.c" />
<ClCompile Include="mutexhelper.c" /> <ClCompile Include="mutexhelper.c" />
<ClCompile Include="versionhelper.c" /> <ClCompile Include="versionhelper.c" />

View File

@@ -57,6 +57,9 @@
<ClInclude Include="mutexhelper.h"> <ClInclude Include="mutexhelper.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="resourcehelper.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="callbacks.c"> <ClCompile Include="callbacks.c">
@@ -104,6 +107,9 @@
<ClCompile Include="eventhelper.c"> <ClCompile Include="eventhelper.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="resourcehelper.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="exports.def"> <None Include="exports.def">