7 Commits

Author SHA1 Message Date
zeffy
35760a2546 Update wufuc.c 2018-04-04 16:23:41 -07:00
zeffy
a8adfa3c08 switch back from hooking IsDeviceServiceable to direct variable patching (fixes #146) 2018-04-02 13:23:43 -07:00
zeffy
c7e94426a8 Update phnt headers 2018-04-02 10:11:58 -07:00
zeffy
220b2eeaff update log.c, bump version number 2018-04-02 08:48:37 -07:00
zeffy
c2069e3c69 Fix log text encoding (UTF-16 w/o BOM -> UTF-8 w/o BOM) 2018-03-26 02:36:47 -07:00
zeffy
0523eb1b7b Update patternfind.c 2018-03-26 02:35:32 -07:00
zeffy
8ccdd2a50b add minhook license, rename phnt license, update aip [skip ci] 2018-03-16 08:04:57 -07:00
27 changed files with 532 additions and 269 deletions

View File

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

View File

@@ -0,0 +1,81 @@
MinHook - The Minimalistic API Hooking Library for x64/x86
Copyright (C) 2009-2017 Tsuda Kageyu.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
================================================================================
Hacker Disassembler Engine 32 C
Copyright (c) 2008-2009, Vyacheslav Patkov.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
Hacker Disassembler Engine 64 C
Copyright (c) 2008-2009, Vyacheslav Patkov.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1394,7 +1394,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemSecureDumpEncryptionInformation,
SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
SystemHypervisorSharedPageInformation, // REDSTONE4
SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // REDSTONE4
SystemFirmwareBootPerformanceInformation,
SystemCodeIntegrityVerificationInformation,
SystemFirmwarePartitionInformation, // 200
@@ -3103,6 +3103,12 @@ typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION
};
} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, *PSYSTEM_KERNEL_VA_SHADOW_INFORMATION;
// private
typedef struct _SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION
{
PVOID HypervisorSharedUserVa;
} SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION, *PSYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION;
// private
typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION
{

View File

@@ -136,6 +136,15 @@ typedef struct _MEMORY_REGION_INFORMATION
SIZE_T CommitSize;
} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;
// private
typedef enum _MEMORY_WORKING_SET_EX_LOCATION
{
MemoryLocationInvalid,
MemoryLocationResident,
MemoryLocationPagefile,
MemoryLocationReserved
} MEMORY_WORKING_SET_EX_LOCATION;
// private
typedef struct _MEMORY_WORKING_SET_EX_BLOCK
{

View File

@@ -0,0 +1,81 @@
MinHook - The Minimalistic API Hooking Library for x64/x86
Copyright (C) 2009-2017 Tsuda Kageyu.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
================================================================================
Hacker Disassembler Engine 32 C
Copyright (c) 2008-2009, Vyacheslav Patkov.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
Hacker Disassembler Engine 64 C
Copyright (c) 2008-2009, Vyacheslav Patkov.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -12,14 +12,14 @@
#include <VersionHelpers.h>
#include <minhook.h>
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer)
{
switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
wufuc_inject(
pNotifyBuffer->ServiceStatus.dwProcessId,
(LPTHREAD_START_ROUTINE)cb_start,
(LPTHREAD_START_ROUTINE)thread_start_callback,
(ptrlist_t *)pNotifyBuffer->pContext);
break;
case ERROR_SERVICE_MARKED_FOR_DELETE:
@@ -30,7 +30,7 @@ VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
}
DWORD WINAPI cb_start(HANDLE *pParam)
DWORD WINAPI thread_start_callback(HANDLE *pParam)
{
HANDLE handles[2];
HANDLE hCrashMutex;
@@ -41,7 +41,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
LPQUERY_SERVICE_CONFIGW pServiceConfig;
DWORD dwServiceType;
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;
MH_STATUS status;
int tmp;
@@ -63,7 +63,7 @@ DWORD WINAPI cb_start(HANDLE *pParam)
// acquire child mutex, this should be immediate.
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;
}
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));
}
// 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,
L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
L"ServiceDll", NULL, NULL);
@@ -142,7 +142,7 @@ abort_hook:
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
// hook IsDeviceServiceable if wuaueng.dll is already loaded
wufuc_hook(hModule);
wufuc_patch(hModule);
FreeLibrary(hModule);
}
// wait for unload event or the main mutex to be released or abandoned,

View File

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

View File

@@ -9,7 +9,6 @@ wchar_t *g_pszWUServiceDll;
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)
{
@@ -88,13 +87,7 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla
&& (!_wcsicmp(lpFileName, g_pszWUServiceDll)
|| !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) {
wufuc_hook(result);
wufuc_patch(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 HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void);
extern wchar_t *g_pszWUServiceDll;
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
extern PVOID g_ptRegQueryValueExW;
extern PVOID g_ptLoadLibraryExW;
extern PVOID g_ptIsDeviceServiceable;
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

@@ -3,54 +3,55 @@
#include <ShlObj.h>
HANDLE m_hFile = INVALID_HANDLE_VALUE;
static HANDLE m_hFile = INVALID_HANDLE_VALUE;
static DWORD m_dwProcessId;
static wchar_t m_szExeFilePath[MAX_PATH];
static wchar_t *m_pszExeName;
BOOL CALLBACK init_file_handle(
PINIT_ONCE pInitOnce,
ParamData *pParam,
PVOID *ppContext)
BOOL CALLBACK init_once_callback(
PINIT_ONCE InitOnce,
PVOID *Parameter,
PVOID *lpContext)
{
BOOL result = FALSE;
HANDLE hFile;
BOOL result;
HRESULT hr;
wchar_t *pszPath;
wchar_t szFilePath[MAX_PATH];
int ret;
pParam->dwProcessId = GetCurrentProcessId();
if ( !GetModuleFileNameW(NULL, pParam->szExeFilePath, _countof(pParam->szExeFilePath)) ) {
m_dwProcessId = GetCurrentProcessId();
if ( !GetModuleFileNameW(NULL, m_szExeFilePath, _countof(m_szExeFilePath)) ) {
log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError());
return result;
return FALSE;
}
pParam->pszExeName = PathFindFileNameW(pParam->szExeFilePath);
m_pszExeName = PathFindFileNameW(m_szExeFilePath);
hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath);
if ( hr != S_OK ) {
log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
return result;
return FALSE;
}
ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
CoTaskMemFree(pszPath);
if ( ret ) {
log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
return result;
return FALSE;
}
if ( !PathAppendW(szFilePath, L"wufuc") ) {
append_fail:
log_debug(L"PathAppendW failed!");
return result;
return FALSE;
}
if ( !CreateDirectoryW(szFilePath, NULL)
&& GetLastError() != ERROR_ALREADY_EXISTS ) {
log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError());
return result;
return FALSE;
}
if ( !PathAppendW(szFilePath, L"wufuc.log") )
if ( !PathAppendW(szFilePath, L"wufuc.1.log") )
goto append_fail;
hFile = CreateFileW(szFilePath,
m_hFile = CreateFileW(szFilePath,
FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@@ -58,12 +59,9 @@ append_fail:
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( hFile != INVALID_HANDLE_VALUE ) {
*ppContext = (PVOID)hFile;
result = TRUE;
} else {
result = m_hFile != INVALID_HANDLE_VALUE;
if ( !result )
log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError());
}
return result;
}
@@ -93,9 +91,7 @@ void log_debug_(const wchar_t *const format, ...)
void log_trace_(const wchar_t *const format, ...)
{
static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
static ParamData data;
BOOL bStatus;
errno_t e;
wchar_t datebuf[9];
wchar_t timebuf[9];
va_list ap;
@@ -104,42 +100,55 @@ void log_trace_(const wchar_t *const format, ...)
wchar_t *buf1;
int ret;
wchar_t *buf2;
int size;
char *buf3;
DWORD written;
bStatus = InitOnceExecuteOnce(&InitOnce,
(PINIT_ONCE_FN)init_file_handle,
&data,
&(LPVOID)m_hFile);
bStatus = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
e = _wstrdate_s(datebuf, _countof(datebuf));
if ( e ) return;
e = _wstrtime_s(timebuf, _countof(timebuf));
if ( e ) return;
if ( _wstrdate_s(datebuf, _countof(datebuf))
|| _wstrtime_s(timebuf, _countof(timebuf)) )
return;
va_start(ap, format);
count = _vscwprintf(format, ap);
ret = _vscwprintf(format, ap);
va_end(ap);
if ( count == -1 ) return;
if ( ret == -1 ) return;
count = ret + 1;
buf1 = calloc(count + 1, sizeof *buf1);
buf1 = calloc(count, sizeof *buf1);
if ( !buf1 ) return;
va_start(ap, format);
ret = vswprintf_s(buf1, count + 1, format, ap);
ret = vswprintf_s(buf1, count, format, ap);
va_end(ap);
if ( ret == -1 ) goto free_buf1;
count = _scwprintf(fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1);
if ( count == -1 ) goto free_buf1;
ret = _scwprintf(fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
if ( ret == -1 ) goto free_buf1;
count = ret + 1;
buf2 = calloc(count + 1, sizeof *buf2);
buf2 = calloc(count, sizeof *buf2);
if ( !buf2 ) goto free_buf1;
ret = swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1);
ret = swprintf_s(buf2, count, fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
if ( ret == -1 ) goto free_buf2;
if ( !bStatus || !WriteFile(m_hFile, buf2, count * (sizeof *buf2), &written, NULL) )
if ( bStatus ) {
size = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, NULL, 0, NULL, NULL);
if ( !size ) goto fallback;
buf3 = malloc(size);
if ( !buf3 ) goto fallback;
ret = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, buf3, size, NULL, NULL)
&& WriteFile(m_hFile, buf3, size, &written, NULL);
free(buf3);
if ( !ret ) goto fallback;
} else {
fallback:
OutputDebugStringW(buf2);
}
free_buf2:
free(buf2);
free_buf1:

View File

@@ -1,12 +1,5 @@
#pragma once
typedef struct
{
DWORD dwProcessId;
wchar_t szExeFilePath[MAX_PATH];
wchar_t *pszExeName;
} ParamData;
void log_debug_(const wchar_t *const format, ...);
void log_trace_(const wchar_t *const format, ...);
void log_close(void);

View File

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

View File

@@ -3,7 +3,9 @@
static inline bool isHex(char ch)
{
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
return (ch >= '0' && ch <= '9')
|| (ch >= 'A' && ch <= 'F')
|| (ch >= 'a' && ch <= 'f');
}
static inline int hexchtoint(char ch)
@@ -17,10 +19,14 @@ static inline int hexchtoint(char ch)
return -1;
}
static inline size_t formathexpattern(const char *patterntext, char *formattext, size_t formattextsize)
static inline size_t formathexpattern(const char *patterntext,
char *formattext,
size_t formattextsize)
{
size_t len = strlen(patterntext);
size_t len;
size_t result = 0;
len = strlen(patterntext);
for ( size_t i = 0; i < len; i++ ) {
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
if ( formattext && result + 1 < formattextsize )
@@ -44,18 +50,24 @@ static inline size_t formathexpattern(const char *patterntext, char *formattext,
return result;
}
bool patterntransform(const char *patterntext, PatternByte *pattern, size_t patternsize)
bool patterntransform(const char *patterntext,
PatternByte *pattern,
size_t patternsize)
{
size_t len;
size_t size;
char *formattext;
PatternByte newByte;
memset(pattern, 0, patternsize * (sizeof *pattern));
size_t len = formathexpattern(patterntext, NULL, 0);
len = formathexpattern(patterntext, NULL, 0);
if ( !len || len / 2 > patternsize )
return false;
size_t size = len + 1;
char *formattext = malloc(size);
size = len + 1;
formattext = malloc(size);
formathexpattern(patterntext, formattext, size);
PatternByte newByte;
for ( size_t i = 0, j = 0, k = 0; i < len && k <= patternsize; i++ ) {
if ( formattext[i] == '?' ) { //wildcard
@@ -78,14 +90,16 @@ bool patterntransform(const char *patterntext, PatternByte *pattern, size_t patt
static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
{
int matched = 0;
uint8_t n1;
uint8_t n2;
uint8_t n1 = (byte >> 4) & 0xF;
n1 = (byte >> 4) & 0xF;
if ( pbyte.nibble[0].wildcard )
matched++;
else if ( pbyte.nibble[0].data == n1 )
matched++;
uint8_t n2 = byte & 0xF;
n2 = byte & 0xF;
if ( pbyte.nibble[1].wildcard )
matched++;
else if ( pbyte.nibble[1].data == n2 )
@@ -96,10 +110,13 @@ static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
{
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
PatternByte *searchpattern = calloc(searchpatternsize, sizeof(PatternByte));
size_t searchpatternsize;
PatternByte *searchpattern;
size_t result = -1;
searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
searchpattern = calloc(searchpatternsize, sizeof *searchpattern);
if ( patterntransform(pattern, searchpattern, searchpatternsize) )
result = patternfind_pbyte(data, datasize, searchpattern, searchpatternsize);
@@ -108,7 +125,10 @@ size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
}
__declspec(noinline)
size_t patternfind_bytes(uint8_t *data, size_t datasize, const uint8_t *pattern, size_t patternsize)
size_t patternfind_bytes(uint8_t *data,
size_t datasize,
const uint8_t *pattern,
size_t patternsize)
{
if ( patternsize > datasize )
patternsize = datasize;
@@ -137,28 +157,38 @@ static inline void patternwritebyte(uint8_t *byte, const PatternByte pbyte)
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF);
}
void patternwrite(uint8_t *data, size_t datasize, const char *pattern)
void patternwrite(uint8_t *data,
size_t datasize,
const char *pattern)
{
size_t writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
PatternByte *writepattern = calloc(writepatternsize, sizeof(PatternByte));
size_t writepatternsize;
PatternByte *writepattern;
DWORD fOldProtect;
writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
writepattern = calloc(writepatternsize, sizeof *writepattern);
if ( patterntransform(pattern, writepattern, writepatternsize) ) {
DWORD OldProtect;
BOOL result = VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &OldProtect);
VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &fOldProtect);
if ( writepatternsize > datasize )
writepatternsize = datasize;
for ( size_t i = 0; i < writepatternsize; i++ )
patternwritebyte(&data[i], writepattern[i]);
result = VirtualProtect(data, writepatternsize, OldProtect, &OldProtect);
VirtualProtect(data, writepatternsize, fOldProtect, &fOldProtect);
FlushInstructionCache(GetCurrentProcess(), data, datasize);
}
free(writepattern);
}
bool patternsnr(uint8_t *data, size_t datasize, const char *searchpattern, const char *replacepattern)
bool patternsnr(uint8_t *data,
size_t datasize,
const char *searchpattern,
const char *replacepattern)
{
size_t found = patternfind(data, datasize, searchpattern);
size_t found;
found = patternfind(data, datasize, searchpattern);
if ( found == -1 )
return false;
patternwrite(data + found, found - datasize, replacepattern);
@@ -166,7 +196,10 @@ bool patternsnr(uint8_t *data, size_t datasize, const char *searchpattern, const
}
__declspec(noinline)
size_t patternfind_pbyte(uint8_t *data, size_t datasize, const PatternByte *pattern, size_t searchpatternsize)
size_t patternfind_pbyte(uint8_t *data,
size_t datasize,
const PatternByte *pattern,
size_t searchpatternsize)
{
for ( size_t i = 0, pos = 0; i < datasize; i++ ) { //search for the pattern
if ( patternmatchbyte(data[i], pattern[pos]) ) { //check if our pattern matches the current byte

View File

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

View File

@@ -1,11 +1,11 @@
#pragma once
#ifndef BUILD_COMMIT_VERSION
#define BUILD_COMMIT_VERSION 1.0.0.0
#define BUILD_COMMIT_VERSION 1.0.1.0
#endif
#ifndef BUILD_VERSION_COMMA
#define BUILD_VERSION_COMMA 1,0,0,0
#define BUILD_VERSION_COMMA 1,0,1,0
#endif
#define S_(x) #x

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);
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);
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;
while ( !Unloading && !Lagging ) {
e = NotifyServiceStatusChangeW(hService,

View File

@@ -29,4 +29,4 @@
extern IMAGE_DOS_HEADER __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;
}
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)
{
DWORDLONG dwlConditionMask = 0;

View File

@@ -1,6 +1,4 @@
#pragma once
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);

View File

@@ -6,13 +6,14 @@
#include "modulehelper.h"
#include "mutexhelper.h"
#include "patternfind.h"
#include "resourcehelper.h"
#include "versionhelper.h"
#include <minhook.h>
HANDLE g_hMainMutex;
bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
static bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
{
bool result = false;
DWORD ExitCode;
@@ -99,96 +100,123 @@ close_mutex:
return result;
}
bool wufuc_hook(HMODULE hModule)
static bool wufuc_get_patch_info(VS_FIXEDFILEINFO *pffi, PATCHINFO *ppi)
{
bool result = false;
PLANGANDCODEPAGE ptl;
HANDLE hProcess;
UINT cbtl;
wchar_t SubBlock[38];
wchar_t *pInternalName;
UINT cbInternalName;
VS_FIXEDFILEINFO *pffi;
UINT cbffi;
bool tmp;
MODULEINFO modinfo;
size_t offset;
LPVOID pTarget = NULL;
MH_STATUS status;
#ifdef _WIN64
if ( ver_verify_version_info(6, 1, 1) && 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 ) {
ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl);
if ( !ptl ) {
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
ppi->pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
ppi->off1 = 0xa;
ppi->off2 = 0x12;
return true;
}
#elif _WIN32
if ( ver_verify_version_info(6, 1, 1)
&& ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1 ) {
ppi->pattern = "833D????????00 743E E8???????? A3????????";
ppi->off1 = 0x2;
ppi->off2 = 0xf;
return true;
} 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 true;
}
#endif
return false;
}
hProcess = GetCurrentProcess();
for ( size_t i = 0, count = (cbtl / sizeof *ptl); i < count; i++ ) {
if ( swprintf_s(SubBlock,
_countof(SubBlock),
L"\\StringFileInfo\\%04x%04x\\InternalName",
ptl[i].wLanguage,
ptl[i].wCodePage) == -1 )
continue;
static bool 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 true;
#elif _WIN32
*ppval1 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off1));
*ppval2 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off2));
return true;
#else
return false;
#endif
}
pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName);
if ( !pInternalName ) {
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));
void wufuc_patch(HMODULE hModule)
{
void *pBlock;
PATCHINFO pi;
size_t count;
PLANGANDCODEPAGE plcp;
wchar_t *pInternalName;
VS_FIXEDFILEINFO *pffi;
MODULEINFO modinfo;
size_t offset;
void *pfn;
DWORD fOldProtect;
PBOOL pval1;
PBOOL pval2;
log_info(L"%ls Windows Update Agent version: %hu.%hu.%hu.%hu",
tmp ? L"Supported" : L"Unsupported",
pBlock = res_get_version_info(hModule);
if ( !pBlock ) return;
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;
}
goto free_pBlock;
cont_patch:
pffi = res_query_fixed_file_info(pBlock);
if ( !pffi ) goto free_pBlock;
if ( !wufuc_get_patch_info(pffi, &pi) ) {
log_warning(L"Unsupported Windows Update Agent version: %hu.%hu.%hu.%hu",
HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
goto free_pBlock;
}
log_info(L"Supported Windows Update Agent version: %hu.%hu.%hu.%hu",
HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
free(pffi);
if ( !tmp ) break;
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)",
hModule, GetLastError());
break;
if ( !GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", hModule, GetLastError());
goto free_pBlock;
}
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);
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pi.pattern);
if ( offset == -1 ) {
log_info(L"Couldn't match IsDeviceServiceable function!");
goto free_pBlock;
}
pfn = OffsetToPointer(modinfo.lpBaseOfDll, offset);
log_info(L"Matched %ls!IsDeviceServiceable function! (Offset=%IX, Address=%p)",
PathFindFileNameW(g_pszWUServiceDll), offset, pfn);
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;
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);
}
free(ptl);
return result;
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);
}
}
free_pBlock:
free(pBlock);
}

View File

@@ -1,10 +1,11 @@
#pragma once
typedef struct
typedef struct _PATCHINFO
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
const char *pattern;
size_t off1;
size_t off2;
} PATCHINFO;
#define SVCHOST_CRASH_THRESHOLD 3
extern HANDLE g_hMainMutex;
@@ -12,4 +13,4 @@ extern HANDLE g_hMainMutex;
bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pStartAddress,
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="modulehelper.h" />
<ClInclude Include="registryhelper.h" />
<ClInclude Include="resourcehelper.h" />
<ClInclude Include="servicehelper.h" />
<ClInclude Include="versionhelper.h" />
<ClInclude Include="hooks.h" />
@@ -41,6 +42,7 @@
<ClCompile Include="ptrlist.c" />
<ClCompile Include="modulehelper.c" />
<ClCompile Include="registryhelper.c" />
<ClCompile Include="resourcehelper.c" />
<ClCompile Include="servicehelper.c" />
<ClCompile Include="mutexhelper.c" />
<ClCompile Include="versionhelper.c" />

View File

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

View File

@@ -21,10 +21,10 @@
<ROW Property="AiPreventAutoPin" Value="System.AppUserModel.ExcludeFromShowInNewInstall"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="x64Build:6#x86Build:6"/>
<ROW Property="Manufacturer" Value="zeffy"/>
<ROW Property="ProductCode" Value="1027:{F4D292D2-CE8F-4908-80AF-CB48B3E560CF} 1028:{66D6B564-B289-4F83-98E0-4296CDE37CB9} 1031:{F4662CF2-7D9F-4370-B45F-ADB021733AF9} 1033:{0DAE2218-2FB5-4AD0-9558-FA2F1B1E5ABF} 1035:{7A1DE4CB-ED5F-4EA0-B262-137BB5CDF2BF} 1036:{B2D2636D-2170-457A-A876-051F227DEEA2} 1038:{9D2917A0-8F1E-4E0F-AE62-1938BD4CED0E} 1040:{3BD98571-9F20-44F8-9162-62D664860999} 1041:{64C167D2-432B-4B82-B5AF-AF795C78F4A1} 1042:{8EAAC0A1-89E3-46B8-B101-E149E87F04F4} 1043:{8AB22455-426B-4757-B640-30729411FD11} 1045:{1CC402B6-02FD-4E14-BE66-10A12FA99106} 1046:{9E7919D2-D6AF-4864-A6C3-028F759BF307} 1049:{8FA26981-B9FF-4505-B547-4EFA9B5241C8} 1060:{3992ECFB-F774-49FE-8B7A-9C2F7B52B271} 2052:{75CEB203-1CE4-4B6F-A9DF-18D8B902C6B8} 2070:{8B6326BE-B5FE-46F3-BD61-1AC95EB0C1CA} 3082:{D564C11C-4870-43C1-BD62-F71DFC45FBF2} " Type="16"/>
<ROW Property="ProductCode" Value="1027:{84169AC2-619B-4E39-ABAC-D97D0CCE52AA} 1028:{3242799A-EABC-4846-9FB2-9157464AC6B2} 1031:{15845A1D-9531-4B6B-B56E-93E56652876D} 1033:{02D77154-1789-4037-8157-4F9B400D184E} 1035:{2AB75127-0A1D-46C3-9939-7E1BEF4101F8} 1036:{E0275036-3F2B-44F3-BCDB-78C55071F41B} 1038:{66A9F4FC-8DB1-45AE-98A5-469F14DC2867} 1040:{A037A274-187E-4231-9857-17075F270D01} 1041:{8E027F22-470D-4800-B135-3661E11F1B2D} 1042:{0C7CB276-E4EB-4D99-BC4D-E362BD4AEA46} 1043:{DDD233EB-262F-42B5-BB37-61366CCB3AB7} 1045:{1008FE13-9C80-4061-BAF1-AFEFA3C322BE} 1046:{2C6C0A74-CDEE-4495-858D-EE570F1B14F0} 1049:{D86825C0-4294-441C-B200-3C7B1314FF10} 1060:{D475BE6D-DB4D-4783-8396-F96186694C6E} 2052:{BA2561A6-D217-400D-A2B0-A0AA07222A94} 2070:{3C2F9949-F866-45C9-BE0E-0D046934E2CF} 3082:{AB82F7D2-24EF-47C9-9978-A69CE1BE56B0} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="wufuc"/>
<ROW Property="ProductVersion" Value="1.0.0.0" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="ProductVersion" Value="1.0.0.191" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{4C52972C-251E-4D1B-AD09-EAA765719DCC}"/>
<ROW Property="WindowsType9X" MultiBuildValue="x64Build:Windows 9x/ME#x86Build:Windows 9x/ME" ValueLocId="-"/>
@@ -55,7 +55,7 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="COPYING" ComponentId="{6CA1ECA7-4C30-4BD0-A5E8-6B3E5BCBE31D}" Directory_="APPDIR" Attributes="0" KeyPath="COPYING" Type="0"/>
<ROW Component="ProductInformation" ComponentId="{75030EAB-5C17-4F84-B529-28003271CA3F}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
<ROW Component="Restore_wuauserv.reg" ComponentId="{5CE5C35B-6B0E-4EE4-B92C-7B1D9882DFC0}" Directory_="Troubleshooting_1_Dir" Attributes="0" KeyPath="Restore_wuauserv.reg" Type="0"/>
<ROW Component="Restore_wuauserv.reg" ComponentId="{ED9F90C5-1984-48DE-B109-4AF6F12A2E8F}" Directory_="Troubleshooting_1_Dir" Attributes="0" KeyPath="Restore_wuauserv.reg" Type="0"/>
<ROW Component="SHORTCUTDIR" ComponentId="{910396A4-AFDD-4E57-BF00-2FDD4108AC61}" Directory_="SHORTCUTDIR" Attributes="0"/>
<ROW Component="Troubleshooting" ComponentId="{D4F7163C-0FD7-4862-BF97-F1693236500C}" Directory_="Troubleshooting_Dir" Attributes="0"/>
<ROW Component="X64FeatureItems" ComponentId="{0E189A37-1F40-4756-ACB9-6511067D5B47}" Directory_="X64FeatureItems_Dir" Attributes="0"/>
@@ -72,7 +72,7 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="COPYING" Component_="COPYING" FileName="COPYING.txt" Attributes="0" SourcePath="..\..\COPYING" SelfReg="false" NextFile="Restore_wuauserv.reg"/>
<ROW File="Restore_wuauserv.reg" Component_="Restore_wuauserv.reg" FileName="RESTOR~1.REG|Restore_wuauserv.reg" Attributes="0" SourcePath="..\wufuc_setup_bat\Restore_wuauserv.reg" SelfReg="false"/>
<ROW File="Restore_wuauserv.reg" Component_="Restore_wuauserv.reg" FileName="RESTOR~1.REG|Restore_wuauserv.reg" Attributes="0" SourcePath="..\wufuc_setup_bat\Troubleshooting\Restore_wuauserv.reg" SelfReg="false"/>
<ROW File="wufuc32.dll" Component_="wufuc32.dll" FileName="wufuc32.dll" Attributes="0" SourcePath="wufuc32.dll" SelfReg="false" NextFile="wufuc64.dll"/>
<ROW File="wufuc64.dll" Component_="wufuc64.dll" FileName="wufuc64.dll" Attributes="0" SourcePath="wufuc64.dll" SelfReg="false" NextFile="COPYING"/>
</COMPONENT>
@@ -313,7 +313,7 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="License" Directory_="SHORTCUTDIR" Name="License" Component_="COPYING" Target="[#COPYING]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="Restore_wuauserv.reg" Target="[CommonAppDataFolder]wufuc\wufuc.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="SHORTCUTDIR" Target="[CommonAppDataFolder]wufuc\wufuc.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Uninstallwufuc" Directory_="SHORTCUTDIR" Name="UNINST~2|Uninstall [|ProductName]" Component_="ProductInformation" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="msiexec.exe" IconIndex="0" ShowCmd="1" CustomFlags="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">