Compare commits
7 Commits
v1.0.0.191
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
35760a2546 | ||
![]() |
a8adfa3c08 | ||
![]() |
c7e94426a8 | ||
![]() |
220b2eeaff | ||
![]() |
c2069e3c69 | ||
![]() |
0523eb1b7b | ||
![]() |
8ccdd2a50b |
@@ -1,4 +1,4 @@
|
|||||||
version: 1.0.0.{build}
|
version: 1.0.1.{build}
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
81
inc/minhook/minhook.LICENSE.txt
Normal file
81
inc/minhook/minhook.LICENSE.txt
Normal 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.
|
@@ -1394,7 +1394,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS
|
|||||||
SystemSecureDumpEncryptionInformation,
|
SystemSecureDumpEncryptionInformation,
|
||||||
SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
|
SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
|
||||||
SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
|
SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
|
||||||
SystemHypervisorSharedPageInformation, // REDSTONE4
|
SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // REDSTONE4
|
||||||
SystemFirmwareBootPerformanceInformation,
|
SystemFirmwareBootPerformanceInformation,
|
||||||
SystemCodeIntegrityVerificationInformation,
|
SystemCodeIntegrityVerificationInformation,
|
||||||
SystemFirmwarePartitionInformation, // 200
|
SystemFirmwarePartitionInformation, // 200
|
||||||
@@ -3103,6 +3103,12 @@ typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION
|
|||||||
};
|
};
|
||||||
} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, *PSYSTEM_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
|
// private
|
||||||
typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION
|
typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION
|
||||||
{
|
{
|
||||||
|
@@ -136,6 +136,15 @@ typedef struct _MEMORY_REGION_INFORMATION
|
|||||||
SIZE_T CommitSize;
|
SIZE_T CommitSize;
|
||||||
} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;
|
} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;
|
||||||
|
|
||||||
|
// private
|
||||||
|
typedef enum _MEMORY_WORKING_SET_EX_LOCATION
|
||||||
|
{
|
||||||
|
MemoryLocationInvalid,
|
||||||
|
MemoryLocationResident,
|
||||||
|
MemoryLocationPagefile,
|
||||||
|
MemoryLocationReserved
|
||||||
|
} MEMORY_WORKING_SET_EX_LOCATION;
|
||||||
|
|
||||||
// private
|
// private
|
||||||
typedef struct _MEMORY_WORKING_SET_EX_BLOCK
|
typedef struct _MEMORY_WORKING_SET_EX_BLOCK
|
||||||
{
|
{
|
||||||
|
81
lib/minhook/minhook.LICENSE.txt
Normal file
81
lib/minhook/minhook.LICENSE.txt
Normal 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.
|
@@ -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,
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
|
@@ -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);
|
|
||||||
|
@@ -3,54 +3,55 @@
|
|||||||
|
|
||||||
#include <ShlObj.h>
|
#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(
|
BOOL CALLBACK init_once_callback(
|
||||||
PINIT_ONCE pInitOnce,
|
PINIT_ONCE InitOnce,
|
||||||
ParamData *pParam,
|
PVOID *Parameter,
|
||||||
PVOID *ppContext)
|
PVOID *lpContext)
|
||||||
{
|
{
|
||||||
BOOL result = FALSE;
|
BOOL result;
|
||||||
HANDLE hFile;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
wchar_t *pszPath;
|
wchar_t *pszPath;
|
||||||
wchar_t szFilePath[MAX_PATH];
|
wchar_t szFilePath[MAX_PATH];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pParam->dwProcessId = GetCurrentProcessId();
|
m_dwProcessId = GetCurrentProcessId();
|
||||||
if ( !GetModuleFileNameW(NULL, pParam->szExeFilePath, _countof(pParam->szExeFilePath)) ) {
|
if ( !GetModuleFileNameW(NULL, m_szExeFilePath, _countof(m_szExeFilePath)) ) {
|
||||||
log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError());
|
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);
|
hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath);
|
||||||
if ( hr != S_OK ) {
|
if ( hr != S_OK ) {
|
||||||
log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
|
log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
|
||||||
return result;
|
return FALSE;
|
||||||
}
|
}
|
||||||
ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
|
ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
|
||||||
CoTaskMemFree(pszPath);
|
CoTaskMemFree(pszPath);
|
||||||
if ( ret ) {
|
if ( ret ) {
|
||||||
log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
|
log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
|
||||||
return result;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !PathAppendW(szFilePath, L"wufuc") ) {
|
if ( !PathAppendW(szFilePath, L"wufuc") ) {
|
||||||
append_fail:
|
append_fail:
|
||||||
log_debug(L"PathAppendW failed!");
|
log_debug(L"PathAppendW failed!");
|
||||||
return result;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if ( !CreateDirectoryW(szFilePath, NULL)
|
if ( !CreateDirectoryW(szFilePath, NULL)
|
||||||
&& GetLastError() != ERROR_ALREADY_EXISTS ) {
|
&& GetLastError() != ERROR_ALREADY_EXISTS ) {
|
||||||
|
|
||||||
log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError());
|
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;
|
goto append_fail;
|
||||||
|
|
||||||
hFile = CreateFileW(szFilePath,
|
m_hFile = CreateFileW(szFilePath,
|
||||||
FILE_APPEND_DATA,
|
FILE_APPEND_DATA,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -58,12 +59,9 @@ append_fail:
|
|||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if ( hFile != INVALID_HANDLE_VALUE ) {
|
result = m_hFile != INVALID_HANDLE_VALUE;
|
||||||
*ppContext = (PVOID)hFile;
|
if ( !result )
|
||||||
result = TRUE;
|
|
||||||
} else {
|
|
||||||
log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError());
|
log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError());
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +91,7 @@ void log_debug_(const wchar_t *const format, ...)
|
|||||||
void log_trace_(const wchar_t *const format, ...)
|
void log_trace_(const wchar_t *const format, ...)
|
||||||
{
|
{
|
||||||
static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
static ParamData data;
|
|
||||||
BOOL bStatus;
|
BOOL bStatus;
|
||||||
errno_t e;
|
|
||||||
wchar_t datebuf[9];
|
wchar_t datebuf[9];
|
||||||
wchar_t timebuf[9];
|
wchar_t timebuf[9];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -104,42 +100,55 @@ void log_trace_(const wchar_t *const format, ...)
|
|||||||
wchar_t *buf1;
|
wchar_t *buf1;
|
||||||
int ret;
|
int ret;
|
||||||
wchar_t *buf2;
|
wchar_t *buf2;
|
||||||
|
int size;
|
||||||
|
char *buf3;
|
||||||
DWORD written;
|
DWORD written;
|
||||||
|
|
||||||
bStatus = InitOnceExecuteOnce(&InitOnce,
|
bStatus = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
|
||||||
(PINIT_ONCE_FN)init_file_handle,
|
|
||||||
&data,
|
|
||||||
&(LPVOID)m_hFile);
|
|
||||||
|
|
||||||
e = _wstrdate_s(datebuf, _countof(datebuf));
|
if ( _wstrdate_s(datebuf, _countof(datebuf))
|
||||||
if ( e ) return;
|
|| _wstrtime_s(timebuf, _countof(timebuf)) )
|
||||||
e = _wstrtime_s(timebuf, _countof(timebuf));
|
return;
|
||||||
if ( e ) return;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
count = _vscwprintf(format, ap);
|
ret = _vscwprintf(format, ap);
|
||||||
va_end(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;
|
if ( !buf1 ) return;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
ret = vswprintf_s(buf1, count + 1, format, ap);
|
ret = vswprintf_s(buf1, count, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if ( ret == -1 ) goto free_buf1;
|
if ( ret == -1 ) goto free_buf1;
|
||||||
|
|
||||||
count = _scwprintf(fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1);
|
ret = _scwprintf(fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
|
||||||
if ( count == -1 ) goto free_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;
|
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 ( 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);
|
OutputDebugStringW(buf2);
|
||||||
|
}
|
||||||
free_buf2:
|
free_buf2:
|
||||||
free(buf2);
|
free(buf2);
|
||||||
free_buf1:
|
free_buf1:
|
||||||
|
@@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#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_debug_(const wchar_t *const format, ...);
|
||||||
void log_trace_(const wchar_t *const format, ...);
|
void log_trace_(const wchar_t *const format, ...);
|
||||||
void log_close(void);
|
void log_close(void);
|
||||||
|
@@ -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);
|
||||||
|
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
static inline bool isHex(char ch)
|
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)
|
static inline int hexchtoint(char ch)
|
||||||
@@ -17,10 +19,14 @@ static inline int hexchtoint(char ch)
|
|||||||
return -1;
|
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;
|
size_t result = 0;
|
||||||
|
|
||||||
|
len = strlen(patterntext);
|
||||||
for ( size_t i = 0; i < len; i++ ) {
|
for ( size_t i = 0; i < len; i++ ) {
|
||||||
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
|
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
|
||||||
if ( formattext && result + 1 < formattextsize )
|
if ( formattext && result + 1 < formattextsize )
|
||||||
@@ -44,18 +50,24 @@ static inline size_t formathexpattern(const char *patterntext, char *formattext,
|
|||||||
return result;
|
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));
|
memset(pattern, 0, patternsize * (sizeof *pattern));
|
||||||
size_t len = formathexpattern(patterntext, NULL, 0);
|
len = formathexpattern(patterntext, NULL, 0);
|
||||||
|
|
||||||
if ( !len || len / 2 > patternsize )
|
if ( !len || len / 2 > patternsize )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t size = len + 1;
|
size = len + 1;
|
||||||
char *formattext = malloc(size);
|
formattext = malloc(size);
|
||||||
formathexpattern(patterntext, formattext, size);
|
formathexpattern(patterntext, formattext, size);
|
||||||
PatternByte newByte;
|
|
||||||
|
|
||||||
for ( size_t i = 0, j = 0, k = 0; i < len && k <= patternsize; i++ ) {
|
for ( size_t i = 0, j = 0, k = 0; i < len && k <= patternsize; i++ ) {
|
||||||
if ( formattext[i] == '?' ) { //wildcard
|
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)
|
static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
|
||||||
{
|
{
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
|
uint8_t n1;
|
||||||
|
uint8_t n2;
|
||||||
|
|
||||||
uint8_t n1 = (byte >> 4) & 0xF;
|
n1 = (byte >> 4) & 0xF;
|
||||||
if ( pbyte.nibble[0].wildcard )
|
if ( pbyte.nibble[0].wildcard )
|
||||||
matched++;
|
matched++;
|
||||||
else if ( pbyte.nibble[0].data == n1 )
|
else if ( pbyte.nibble[0].data == n1 )
|
||||||
matched++;
|
matched++;
|
||||||
|
|
||||||
uint8_t n2 = byte & 0xF;
|
n2 = byte & 0xF;
|
||||||
if ( pbyte.nibble[1].wildcard )
|
if ( pbyte.nibble[1].wildcard )
|
||||||
matched++;
|
matched++;
|
||||||
else if ( pbyte.nibble[1].data == n2 )
|
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 patternfind(uint8_t *data, size_t datasize, const char *pattern)
|
||||||
{
|
{
|
||||||
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
|
size_t searchpatternsize;
|
||||||
PatternByte *searchpattern = calloc(searchpatternsize, sizeof(PatternByte));
|
PatternByte *searchpattern;
|
||||||
|
|
||||||
size_t result = -1;
|
size_t result = -1;
|
||||||
|
|
||||||
|
searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
|
||||||
|
searchpattern = calloc(searchpatternsize, sizeof *searchpattern);
|
||||||
|
|
||||||
if ( patterntransform(pattern, searchpattern, searchpatternsize) )
|
if ( patterntransform(pattern, searchpattern, searchpatternsize) )
|
||||||
result = patternfind_pbyte(data, datasize, 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)
|
__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 )
|
if ( patternsize > datasize )
|
||||||
patternsize = datasize;
|
patternsize = datasize;
|
||||||
@@ -137,28 +157,38 @@ static inline void patternwritebyte(uint8_t *byte, const PatternByte pbyte)
|
|||||||
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF);
|
*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;
|
size_t writepatternsize;
|
||||||
PatternByte *writepattern = calloc(writepatternsize, sizeof(PatternByte));
|
PatternByte *writepattern;
|
||||||
|
DWORD fOldProtect;
|
||||||
|
|
||||||
|
writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
|
||||||
|
writepattern = calloc(writepatternsize, sizeof *writepattern);
|
||||||
|
|
||||||
if ( patterntransform(pattern, writepattern, writepatternsize) ) {
|
if ( patterntransform(pattern, writepattern, writepatternsize) ) {
|
||||||
DWORD OldProtect;
|
VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &fOldProtect);
|
||||||
BOOL result = VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &OldProtect);
|
|
||||||
if ( writepatternsize > datasize )
|
if ( writepatternsize > datasize )
|
||||||
writepatternsize = datasize;
|
writepatternsize = datasize;
|
||||||
for ( size_t i = 0; i < writepatternsize; i++ )
|
for ( size_t i = 0; i < writepatternsize; i++ )
|
||||||
patternwritebyte(&data[i], writepattern[i]);
|
patternwritebyte(&data[i], writepattern[i]);
|
||||||
result = VirtualProtect(data, writepatternsize, OldProtect, &OldProtect);
|
VirtualProtect(data, writepatternsize, fOldProtect, &fOldProtect);
|
||||||
FlushInstructionCache(GetCurrentProcess(), data, datasize);
|
FlushInstructionCache(GetCurrentProcess(), data, datasize);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(writepattern);
|
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 )
|
if ( found == -1 )
|
||||||
return false;
|
return false;
|
||||||
patternwrite(data + found, found - datasize, replacepattern);
|
patternwrite(data + found, found - datasize, replacepattern);
|
||||||
@@ -166,7 +196,10 @@ bool patternsnr(uint8_t *data, size_t datasize, const char *searchpattern, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
__declspec(noinline)
|
__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
|
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
|
if ( patternmatchbyte(data[i], pattern[pos]) ) { //check if our pattern matches the current byte
|
||||||
|
@@ -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))
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef BUILD_COMMIT_VERSION
|
#ifndef BUILD_COMMIT_VERSION
|
||||||
#define BUILD_COMMIT_VERSION 1.0.0.0
|
#define BUILD_COMMIT_VERSION 1.0.1.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BUILD_VERSION_COMMA
|
#ifndef BUILD_VERSION_COMMA
|
||||||
#define BUILD_VERSION_COMMA 1,0,0,0
|
#define BUILD_VERSION_COMMA 1,0,1,0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define S_(x) #x
|
#define S_(x) #x
|
||||||
|
84
src/wufuc/resourcehelper.c
Normal file
84
src/wufuc/resourcehelper.c
Normal 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;
|
||||||
|
}
|
18
src/wufuc/resourcehelper.h
Normal file
18
src/wufuc/resourcehelper.h
Normal 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);
|
@@ -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,
|
||||||
|
@@ -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))))
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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,123 @@ close_mutex:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wufuc_hook(HMODULE hModule)
|
static bool wufuc_get_patch_info(VS_FIXEDFILEINFO *pffi, PATCHINFO *ppi)
|
||||||
{
|
{
|
||||||
bool result = false;
|
#ifdef _WIN64
|
||||||
PLANGANDCODEPAGE ptl;
|
if ( ver_verify_version_info(6, 1, 1) && 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ) return;
|
||||||
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
hProcess = GetCurrentProcess();
|
|
||||||
|
|
||||||
for ( size_t i = 0, count = (cbtl / sizeof *ptl); i < count; i++ ) {
|
plcp = res_query_var_file_info(pBlock, &count);
|
||||||
if ( swprintf_s(SubBlock,
|
if ( !plcp ) goto free_pBlock;
|
||||||
_countof(SubBlock),
|
|
||||||
L"\\StringFileInfo\\%04x%04x\\InternalName",
|
|
||||||
ptl[i].wLanguage,
|
|
||||||
ptl[i].wCodePage) == -1 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName);
|
for ( size_t i = 0; i < count; i++ ) {
|
||||||
if ( !pInternalName ) {
|
pInternalName = res_query_string_file_info(pBlock, plcp[i], L"InternalName", NULL);
|
||||||
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
|
if ( pInternalName && !_wcsicmp(pInternalName, L"wuaueng.dll") )
|
||||||
continue;
|
goto cont_patch;
|
||||||
}
|
}
|
||||||
// identify wuaueng.dll by its resource data
|
goto free_pBlock;
|
||||||
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",
|
cont_patch:
|
||||||
tmp ? L"Supported" : L"Unsupported",
|
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),
|
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,
|
log_info(L"Supported Windows Update Agent version: %hu.%hu.%hu.%hu",
|
||||||
#ifdef _WIN64
|
HIWORD(pffi->dwProductVersionMS),
|
||||||
"FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"
|
LOWORD(pffi->dwProductVersionMS),
|
||||||
#else
|
HIWORD(pffi->dwProductVersionLS),
|
||||||
ver_verify_version_info(6, 1, 0)
|
LOWORD(pffi->dwProductVersionLS));
|
||||||
? "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 ( !GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
|
||||||
if ( status == MH_OK ) {
|
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", hModule, GetLastError());
|
||||||
status = MH_EnableHook(pTarget);
|
goto free_pBlock;
|
||||||
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);
|
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pi.pattern);
|
||||||
return result;
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_pBlock:
|
||||||
|
free(pBlock);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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" />
|
||||||
|
@@ -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">
|
||||||
|
@@ -21,10 +21,10 @@
|
|||||||
<ROW Property="AiPreventAutoPin" Value="System.AppUserModel.ExcludeFromShowInNewInstall"/>
|
<ROW Property="AiPreventAutoPin" Value="System.AppUserModel.ExcludeFromShowInNewInstall"/>
|
||||||
<ROW Property="MSIFASTINSTALL" MultiBuildValue="x64Build:6#x86Build:6"/>
|
<ROW Property="MSIFASTINSTALL" MultiBuildValue="x64Build:6#x86Build:6"/>
|
||||||
<ROW Property="Manufacturer" Value="zeffy"/>
|
<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="ProductLanguage" Value="1033"/>
|
||||||
<ROW Property="ProductName" Value="wufuc"/>
|
<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="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
|
||||||
<ROW Property="UpgradeCode" Value="{4C52972C-251E-4D1B-AD09-EAA765719DCC}"/>
|
<ROW Property="UpgradeCode" Value="{4C52972C-251E-4D1B-AD09-EAA765719DCC}"/>
|
||||||
<ROW Property="WindowsType9X" MultiBuildValue="x64Build:Windows 9x/ME#x86Build:Windows 9x/ME" ValueLocId="-"/>
|
<ROW Property="WindowsType9X" MultiBuildValue="x64Build:Windows 9x/ME#x86Build:Windows 9x/ME" ValueLocId="-"/>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
<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="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="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="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="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"/>
|
<ROW Component="X64FeatureItems" ComponentId="{0E189A37-1F40-4756-ACB9-6511067D5B47}" Directory_="X64FeatureItems_Dir" Attributes="0"/>
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
<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="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="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"/>
|
<ROW File="wufuc64.dll" Component_="wufuc64.dll" FileName="wufuc64.dll" Attributes="0" SourcePath="wufuc64.dll" SelfReg="false" NextFile="COPYING"/>
|
||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
</COMPONENT>
|
</COMPONENT>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
|
<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="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"/>
|
<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>
|
||||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
|
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
|
||||||
|
Reference in New Issue
Block a user