many changes, see description [skip ci]
Note: currently only works via manual injection, Rundll32Entry has been removed - Fixed conflict with UpdatePack7R2 (and WuaCpuFix) by hooking `RegQueryValueExW` and fixing the path to `wuaueng.dll`. (fixes #100) - Eliminated lots of redundant and unnecessary code. - Other reliability improvements and bug fixes. - Removed the error message that displays in the installers when `wuaueng.dll` is below the minimum supported version, and added an internal check that will skip the patching procedure if the version of `wuaueng.dll` is too low. **This means you can now safely install wufuc prior to any updates, and it will automatically start working once it's needed, without any potential side effects.** (fixes #99) - Added `/UNATTENDED` flag to the batch installer and uninstaller. You can use this to bypass the confirmation for a fully automated installation/uninstallation. To use it, you invoke the batch script from an elevated command prompt, like so: `"wufuc_installer.bat" /UNATTENDED` - Improved logging framework to allow multiple processes to safely write to the same `.log` file.
This commit is contained in:
@@ -12,11 +12,11 @@ build:
|
|||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
set "BUILD_VERSION=%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%"
|
set "BUILD_COMMIT_VERSION=%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%"
|
||||||
|
|
||||||
set "BUILD_VERSION_COMMA_SEP=%APPVEYOR_BUILD_VERSION:.=,%"
|
set "BUILD_VERSION_COMMA=%APPVEYOR_BUILD_VERSION:.=,%"
|
||||||
|
|
||||||
set "BUILD_ZIPFILE=%APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%_v%BUILD_VERSION%_%PLATFORM%.zip"
|
set "BUILD_ZIPFILE=%APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%_v%BUILD_COMMIT_VERSION%_%PLATFORM%.zip"
|
||||||
after_build:
|
after_build:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
copy /Y "wufuc\bin\%CONFIGURATION%\%PLATFORM%\wufuc*.dll" "setup-batch\"
|
copy /Y "wufuc\bin\%CONFIGURATION%\%PLATFORM%\wufuc*.dll" "setup-batch\"
|
||||||
|
@@ -75,7 +75,7 @@ title wufuc installer - v%Version%
|
|||||||
set "wufuc_xml=%~dp0wufuc.xml"
|
set "wufuc_xml=%~dp0wufuc.xml"
|
||||||
|
|
||||||
if exist "%wufuc_xml%" (
|
if exist "%wufuc_xml%" (
|
||||||
goto :check_ver
|
goto :check_winver
|
||||||
)
|
)
|
||||||
echo ERROR - Could not find %wufuc_xml%!
|
echo ERROR - Could not find %wufuc_xml%!
|
||||||
echo.
|
echo.
|
||||||
@@ -85,18 +85,14 @@ echo Please extract all the files from wufuc_v%Version%.zip to a permanent
|
|||||||
echo location like C:\Program Files\wufuc and try again.
|
echo location like C:\Program Files\wufuc and try again.
|
||||||
goto :die
|
goto :die
|
||||||
|
|
||||||
:check_ver
|
:check_winver
|
||||||
ver | findstr " 6\.1\." >nul && (
|
ver | findstr " 6\.1\." >nul && (
|
||||||
set "WINDOWS_VER=6.1"
|
|
||||||
set "WUAUENG_DLL_MIN_VER=7.6.7601.23714"
|
|
||||||
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
|
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
|
||||||
goto :check_wuaueng_ver
|
goto :check_unattended
|
||||||
)
|
)
|
||||||
ver | findstr " 6\.3\." >nul && (
|
ver | findstr " 6\.3\." >nul && (
|
||||||
set "WINDOWS_VER=8.1"
|
|
||||||
set "WUAUENG_DLL_MIN_VER=7.9.9600.18621"
|
|
||||||
echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE%
|
echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE%
|
||||||
goto :check_wuaueng_ver
|
goto :check_unattended
|
||||||
)
|
)
|
||||||
|
|
||||||
:unsupported_os
|
:unsupported_os
|
||||||
@@ -117,19 +113,11 @@ echo and that this warning is a mistake, you may continue with the patching proc
|
|||||||
echo at your own peril.
|
echo at your own peril.
|
||||||
goto :confirmation
|
goto :confirmation
|
||||||
|
|
||||||
:check_wuaueng_ver
|
:check_unattended
|
||||||
call :get_filever "%systemroot%\System32\wuaueng.dll"
|
if [%1]==[] goto :confirmation
|
||||||
call :compareversion "%WUAUENG_DLL_MIN_VER%" "%Version%"
|
if /I "%1"=="/UNATTENDED" goto :uninstall
|
||||||
if errorlevel 1 (
|
shift
|
||||||
echo.
|
goto :check_unattended
|
||||||
echo ERROR - Detected that wuaueng.dll is below the minimum supported version.
|
|
||||||
echo.
|
|
||||||
echo You must first run Windows Update until the "Unsupported Hardware" window
|
|
||||||
echo pops up, then try again.
|
|
||||||
echo.
|
|
||||||
goto :die
|
|
||||||
)
|
|
||||||
echo Detected supported Windows Update agent version: %Version%
|
|
||||||
|
|
||||||
:confirmation
|
:confirmation
|
||||||
echo.
|
echo.
|
||||||
@@ -178,44 +166,5 @@ exit
|
|||||||
:get_filever file
|
:get_filever file
|
||||||
set "file=%~1"
|
set "file=%~1"
|
||||||
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%file:\=\\%'" get Version /value ^| find "="') do set "%%i"
|
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%file:\=\\%'" get Version /value ^| find "="') do set "%%i"
|
||||||
exit /b
|
|
||||||
|
|
||||||
:compareversion version1 version2
|
|
||||||
:: https://stackoverflow.com/a/15809139
|
|
||||||
:: Compares two version numbers and returns the result in the ERRORLEVEL
|
|
||||||
::
|
|
||||||
:: Returns 1 if version1 > version2
|
|
||||||
:: 0 if version1 = version2
|
|
||||||
:: -1 if version1 < version2
|
|
||||||
::
|
|
||||||
:: The nodes must be delimited by . or , or -
|
|
||||||
::
|
|
||||||
:: Nodes are normally strictly numeric, without a 0 prefix. A letter suffix
|
|
||||||
:: is treated as a separate node
|
|
||||||
setlocal enableDelayedExpansion
|
|
||||||
set "v1=%~1"
|
|
||||||
set "v2=%~2"
|
|
||||||
call :divideLetters v1
|
|
||||||
call :divideLetters v2
|
|
||||||
:loop
|
|
||||||
call :parseNode "%v1%" n1 v1
|
|
||||||
call :parseNode "%v2%" n2 v2
|
|
||||||
if %n1% gtr %n2% exit /b 1
|
|
||||||
if %n1% lss %n2% exit /b -1
|
|
||||||
if not defined v1 (
|
|
||||||
if not defined v2 ( exit /b 0 )
|
|
||||||
)
|
|
||||||
if not defined v1 ( exit /b -1 )
|
|
||||||
if not defined v2 ( exit /b 1 )
|
|
||||||
goto :loop
|
|
||||||
|
|
||||||
:parseNode version nodeVar remainderVar
|
|
||||||
for /f "tokens=1* delims=.,-" %%A in ("%~1") do (
|
|
||||||
set "%~2=%%A"
|
|
||||||
set "%~3=%%B"
|
|
||||||
)
|
|
||||||
exit /b
|
|
||||||
|
|
||||||
:divideLetters versionVar
|
|
||||||
for %%C in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set "%~1=!%~1:%%C=.%%C!"
|
|
||||||
exit /b
|
exit /b
|
||||||
|
@@ -40,23 +40,28 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
|
|||||||
goto :die
|
goto :die
|
||||||
|
|
||||||
:is_x86
|
:is_x86
|
||||||
set "WINDOWS_ARCHITECTURE=x86"
|
|
||||||
set "wufuc_dll=%~dp0wufuc32.dll"
|
set "wufuc_dll=%~dp0wufuc32.dll"
|
||||||
goto :get_ver
|
goto :get_ver
|
||||||
|
|
||||||
:is_x64
|
:is_x64
|
||||||
set "WINDOWS_ARCHITECTURE=x64"
|
|
||||||
set "wufuc_dll=%~dp0wufuc64.dll"
|
set "wufuc_dll=%~dp0wufuc64.dll"
|
||||||
|
|
||||||
:get_ver
|
:get_ver
|
||||||
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i"
|
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i"
|
||||||
title wufuc uninstaller - v%Version%
|
title wufuc uninstaller - v%Version%
|
||||||
|
|
||||||
|
:loop
|
||||||
|
if [%1]==[] goto :confirmation
|
||||||
|
if /I "%1"=="/UNATTENDED" goto :uninstall
|
||||||
|
shift
|
||||||
|
goto :loop
|
||||||
|
|
||||||
:confirmation
|
:confirmation
|
||||||
set /p CONTINUE=Enter 'Y' if you want to uninstall wufuc:
|
set /p CONTINUE=Enter 'Y' if you want to uninstall wufuc:
|
||||||
if /I not "%CONTINUE%"=="Y" goto :cancel
|
if /I not "%CONTINUE%"=="Y" goto :cancel
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
|
:uninstall
|
||||||
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
||||||
rundll32 "%wufuc_dll%",Rundll32Unload
|
rundll32 "%wufuc_dll%",Rundll32Unload
|
||||||
net start Schedule
|
net start Schedule
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26430.14
|
VisualStudioVersion = 15.0.26730.15
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wufuc", "wufuc\wufuc.vcxproj", "{00F96695-CE41-4C2F-A344-6219DFB4F887}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wufuc", "wufuc\wufuc.vcxproj", "{00F96695-CE41-4C2F-A344-6219DFB4F887}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -44,4 +44,7 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {5070ABC4-3344-4D6E-B744-E3508B10A327}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@@ -1,106 +1,55 @@
|
|||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
|
|
||||||
#include "service.h"
|
|
||||||
#include "iathook.h"
|
#include "iathook.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "patchwua.h"
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "ntdllhelper.h"
|
#include "service.h"
|
||||||
#include "logging.h"
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define WIN32_NO_STATUS
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WIN32_NO_STATUS
|
|
||||||
|
|
||||||
#include <winternl.h>
|
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <Psapi.h>
|
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
|
|
||||||
DWORD WINAPI ThreadProcCallback(LPVOID lpParam) {
|
DWORD WINAPI ThreadProcCallback(LPVOID *lpParam) {
|
||||||
|
OSVERSIONINFO osvi = { 0 };
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||||
|
#pragma warning(suppress : 4996)
|
||||||
|
if ( GetVersionEx(&osvi) )
|
||||||
|
trace(_T("Windows version: %d.%d.%d (%zu-bit)"), osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, sizeof(uintptr_t) * 8);
|
||||||
|
else trace(_T("Failed to get Windows version (error code=%08X)"), GetLastError());
|
||||||
|
|
||||||
|
char brand[0x31];
|
||||||
|
trace(_T("Processor: %hs"), get_cpuid_brand(brand, _countof(brand)));
|
||||||
|
|
||||||
|
LPTSTR lpCommandLine = GetCommandLine();
|
||||||
TCHAR lpServiceCommandLine[0x8000];
|
TCHAR lpServiceCommandLine[0x8000];
|
||||||
GetServiceCommandLine(NULL, _T("wuauserv"), lpServiceCommandLine, _countof(lpServiceCommandLine));
|
if ( GetServiceCommandLine(NULL, _T("wuauserv"), lpServiceCommandLine, _countof(lpServiceCommandLine))
|
||||||
if ( _tcsicmp(GetCommandLine(), lpServiceCommandLine) )
|
&& !_tcsicmp(lpCommandLine, lpServiceCommandLine) ) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa = { 0 };
|
SECURITY_ATTRIBUTES sa = { 0 };
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
sa.bInheritHandle = FALSE;
|
sa.bInheritHandle = FALSE;
|
||||||
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:(A;;0x001F0003;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL) ) {
|
if ( ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:(A;;0x001F0003;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL) ) {
|
||||||
trace(_T("Failed to convert string security descriptor to security descriptor (error code=%08X)"), GetLastError());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||||
if ( hEvent ) {
|
if ( hEvent ) {
|
||||||
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", (LPVOID)&fpLoadLibraryExW, LoadLibraryExW_hook);
|
HANDLE threads[0x1000];
|
||||||
|
|
||||||
PVOID cookie;
|
size_t count = suspend_other_threads(threads, _countof(threads));
|
||||||
NTSTATUS status;
|
iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", (LPVOID)&pfnRegQueryValueExW, RegQueryValueExW_hook);
|
||||||
if ( TryLdrRegisterDllNotification(0, (PLDR_DLL_NOTIFICATION_FUNCTION)LdrDllNotificationCallback, NULL, &cookie, &status) ) {
|
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", (LPVOID)&pfnLoadLibraryExW, LoadLibraryExW_hook);
|
||||||
if ( NT_SUCCESS(status) ) {
|
resume_and_close_threads(threads, count);
|
||||||
trace(_T("Registered LdrDllNotificationCallback (status code=%d)"), status);
|
|
||||||
HMODULE hm = GetModuleHandleW(GetWindowsUpdateServiceDllW());
|
|
||||||
if ( hm ) {
|
|
||||||
MODULEINFO modinfo;
|
|
||||||
if ( GetModuleInformation(GetCurrentProcess(), hm, &modinfo, sizeof(MODULEINFO)) )
|
|
||||||
PatchWUA((void *)modinfo.lpBaseOfDll, (size_t)modinfo.SizeOfImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(hEvent, INFINITE);
|
WaitForSingleObject(hEvent, INFINITE);
|
||||||
trace(_T("Unload event was set"));
|
trace(_T("Unload event was set, removing hooks and unloading..."));
|
||||||
|
|
||||||
if ( cookie ) {
|
count = suspend_other_threads(threads, _countof(threads));
|
||||||
if ( TryLdrUnregisterDllNotification(cookie, &status) ) {
|
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", NULL, pfnLoadLibraryExW);
|
||||||
if ( NT_SUCCESS(status) )
|
iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", NULL, pfnRegQueryValueExW);
|
||||||
trace(_T("Unregistered LdrDllNotificationCallback (status code=%d)"), status);
|
resume_and_close_threads(threads, count);
|
||||||
else
|
|
||||||
trace(_T("Failed to unregister LdrDllNotificationCallback (status code=%d)"), status);
|
|
||||||
} else
|
|
||||||
trace(_T("Failed to get LdrUnregisterDllNotification proc address"));
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
trace(_T("Failed to register LdrDllNotificationCallback (status code=%d)"), status);
|
|
||||||
} else
|
|
||||||
trace(_T("Failed to get LdrRegisterDllNotification proc address"));
|
|
||||||
|
|
||||||
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", NULL, fpLoadLibraryExW);
|
|
||||||
CloseHandle(hEvent);
|
CloseHandle(hEvent);
|
||||||
} else {
|
} else trace(_T("Failed to create unload event (error code=%08X)"), GetLastError());
|
||||||
trace(_T("Failed to create unload event (error code=%08X)"), GetLastError());
|
} else trace(_T("Failed to convert string security descriptor to security descriptor (error code=%08X)"), GetLastError());
|
||||||
return 0;
|
} else trace(_T("Current process command line is incorrect: %s != %s"), lpCommandLine, lpServiceCommandLine);
|
||||||
}
|
|
||||||
trace(_T("Bye bye!"));
|
trace(_T("Bye bye!"));
|
||||||
FreeLibraryAndExitThread((HMODULE)lpParam, 0);
|
FreeLibraryAndExitThread((HMODULE)lpParam, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID CALLBACK LdrDllNotificationCallback(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) {
|
|
||||||
switch ( NotificationReason ) {
|
|
||||||
case LDR_DLL_NOTIFICATION_REASON_LOADED:
|
|
||||||
{
|
|
||||||
LDR_DLL_LOADED_NOTIFICATION_DATA data = NotificationData->Loaded;
|
|
||||||
|
|
||||||
trace(_T("Loaded library: %wZ"), data.FullDllName);
|
|
||||||
|
|
||||||
wchar_t buffer[MAX_PATH];
|
|
||||||
wcscpy_s(buffer, _countof(buffer), (wchar_t *)GetWindowsUpdateServiceDllW());
|
|
||||||
ApplyUpdatePack7R2ShimIfNeeded(buffer, _countof(buffer), buffer, _countof(buffer));
|
|
||||||
|
|
||||||
if ( !_wcsnicmp((wchar_t *)data.FullDllName->Buffer, buffer, (size_t)data.FullDllName->Length) )
|
|
||||||
PatchWUA(data.DllBase, data.SizeOfImage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LDR_DLL_NOTIFICATION_REASON_UNLOADED:
|
|
||||||
{
|
|
||||||
LDR_DLL_UNLOADED_NOTIFICATION_DATA data = NotificationData->Unloaded;
|
|
||||||
|
|
||||||
trace(_T("Unloaded library: %wZ"), data.FullDllName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@@ -1,11 +1,8 @@
|
|||||||
#ifndef CALLBACKS_H
|
#ifndef CALLBACKS_H_INCLUDED
|
||||||
#define CALLBACKS_H
|
#define CALLBACKS_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ntdllhelper.h"
|
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
DWORD WINAPI ThreadProcCallback(LPVOID lpParam);
|
DWORD WINAPI ThreadProcCallback(LPVOID *lpParam);
|
||||||
VOID CALLBACK LdrDllNotificationCallback(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context);
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "logging.h"
|
#include "ntdllhelper.h"
|
||||||
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
@@ -8,21 +9,21 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||||||
switch ( ul_reason_for_call ) {
|
switch ( ul_reason_for_call ) {
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
{
|
{
|
||||||
if ( !IsOperatingSystemSupported() || IsWow64() )
|
if ( !IsOperatingSystemSupported() /*|| IsWow64()*/ )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
DisableThreadLibraryCalls(hModule);
|
|
||||||
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcCallback, (LPVOID)hModule, 0, NULL);
|
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcCallback, (LPVOID)hModule, 0, NULL);
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
if ( !lpReserved )
|
DeinitTracing();
|
||||||
FreeNTDLL();
|
|
||||||
FreeLogging();
|
|
||||||
break;
|
break;
|
||||||
default:
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
102
wufuc/helpers.c
102
wufuc/helpers.c
@@ -1,12 +1,11 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
#include "logging.h"
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <Psapi.h>
|
|
||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
|
|
||||||
static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
|
static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
|
||||||
@@ -27,25 +26,23 @@ static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwM
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsWindows7(void) {
|
BOOL IsWindows7(void) {
|
||||||
static BOOL m_checkedIsWindows7 = FALSE;
|
static BOOL checked = FALSE, isWindows7 = FALSE;
|
||||||
static BOOL m_isWindows7 = FALSE;
|
|
||||||
|
|
||||||
if ( !m_checkedIsWindows7 ) {
|
if ( !checked ) {
|
||||||
m_isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
||||||
m_checkedIsWindows7 = TRUE;
|
checked = TRUE;
|
||||||
}
|
}
|
||||||
return m_isWindows7;
|
return isWindows7;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsWindows8Point1(void) {
|
BOOL IsWindows8Point1(void) {
|
||||||
static BOOL m_checkedIsWindows8Point1 = FALSE;
|
static BOOL checked = FALSE, isWindows8Point1 = FALSE;
|
||||||
static BOOL m_isWindows8Point1 = FALSE;
|
|
||||||
|
|
||||||
if ( !m_checkedIsWindows8Point1 ) {
|
if ( !checked ) {
|
||||||
m_isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
||||||
m_checkedIsWindows8Point1 = TRUE;
|
checked = TRUE;
|
||||||
}
|
}
|
||||||
return m_isWindows8Point1;
|
return isWindows8Point1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsOperatingSystemSupported(void) {
|
BOOL IsOperatingSystemSupported(void) {
|
||||||
@@ -57,30 +54,28 @@ BOOL IsOperatingSystemSupported(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsWow64(void) {
|
BOOL IsWow64(void) {
|
||||||
static BOOL m_checkedIsWow64 = FALSE;
|
static BOOL checked = FALSE, isWow64 = FALSE;
|
||||||
static BOOL m_isWow64 = FALSE;
|
static ISWOW64PROCESS pfnIsWow64Process = NULL;
|
||||||
static ISWOW64PROCESS fpIsWow64Process = NULL;
|
|
||||||
|
|
||||||
if ( !m_checkedIsWow64 ) {
|
if ( !checked ) {
|
||||||
if ( !fpIsWow64Process )
|
if ( !pfnIsWow64Process )
|
||||||
fpIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
|
pfnIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
|
||||||
|
|
||||||
if ( fpIsWow64Process && fpIsWow64Process(GetCurrentProcess(), &m_isWow64) )
|
if ( pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &isWow64) )
|
||||||
m_checkedIsWow64 = TRUE;
|
checked = TRUE;
|
||||||
}
|
}
|
||||||
return m_isWow64;
|
return isWow64;
|
||||||
}
|
}
|
||||||
|
|
||||||
void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb) {
|
size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount) {
|
||||||
DWORD dwProcessId = GetCurrentProcessId();
|
|
||||||
DWORD dwThreadId = GetCurrentThreadId();
|
|
||||||
|
|
||||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
THREADENTRY32 te = { 0 };
|
THREADENTRY32 te = { 0 };
|
||||||
te.dwSize = sizeof(te);
|
te.dwSize = sizeof(te);
|
||||||
Thread32First(hSnap, &te);
|
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
if ( Thread32First(hSnap, &te) ) {
|
||||||
|
DWORD dwProcessId = GetCurrentProcessId();
|
||||||
|
DWORD dwThreadId = GetCurrentThreadId();
|
||||||
|
WaitForTracingMutex(); // make sure we don't dead lock
|
||||||
do {
|
do {
|
||||||
if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId )
|
if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId )
|
||||||
continue;
|
continue;
|
||||||
@@ -88,33 +83,58 @@ void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb) {
|
|||||||
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
|
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
|
||||||
SuspendThread(lphThreads[count]);
|
SuspendThread(lphThreads[count]);
|
||||||
count++;
|
count++;
|
||||||
} while ( count < *lpcb && Thread32Next(hSnap, &te) );
|
} while ( count < nMaxCount && Thread32Next(hSnap, &te) );
|
||||||
|
ReleaseTracingMutex();
|
||||||
|
}
|
||||||
CloseHandle(hSnap);
|
CloseHandle(hSnap);
|
||||||
*lpcb = count;
|
trace(_T("Suspended %zu other threads"), count);
|
||||||
trace(_T("Suspended %d other threads"), count);
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resume_and_close_threads(LPHANDLE lphThreads, size_t cb) {
|
void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount) {
|
||||||
for ( size_t i = 0; i < cb; i++ ) {
|
for ( size_t i = 0; i < nCount; i++ ) {
|
||||||
ResumeThread(lphThreads[i]);
|
ResumeThread(lphThreads[i]);
|
||||||
CloseHandle(lphThreads[i]);
|
CloseHandle(lphThreads[i]);
|
||||||
}
|
}
|
||||||
trace(_T("Resumed %d threads"), cb);
|
trace(_T("Resumed %zu threads"), nCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_cpuid_brand(char *brand) {
|
char *get_cpuid_brand(char *brand, size_t nMaxCount) {
|
||||||
int info[4];
|
int info[4];
|
||||||
__cpuidex(info, 0x80000000, 0);
|
__cpuidex(info, 0x80000000, 0);
|
||||||
if ( info[0] < 0x80000004 ) {
|
if ( info[0] < 0x80000004 ) {
|
||||||
brand[0] = '\0';
|
brand[0] = '\0';
|
||||||
return;
|
return brand;
|
||||||
}
|
}
|
||||||
uint32_t *char_as_int = (uint32_t *)brand;
|
uint32_t *char_as_int = (uint32_t *)brand;
|
||||||
for ( int op = 0x80000002; op <= 0x80000004; op++ ) {
|
for ( int op = 0x80000002; op <= 0x80000004; op++ ) {
|
||||||
__cpuidex(info, op, 0);
|
__cpuidex(info, op, 0);
|
||||||
*(char_as_int++) = info[0];
|
for ( int i = 0; i < 4; i++ )
|
||||||
*(char_as_int++) = info[1];
|
*(char_as_int++) = info[i];
|
||||||
*(char_as_int++) = info[2];
|
|
||||||
*(char_as_int++) = info[3];
|
|
||||||
}
|
}
|
||||||
|
size_t i = 0;
|
||||||
|
while ( i < nMaxCount && isspace(brand[i]) )
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return brand + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *find_fname(wchar_t *pPath) {
|
||||||
|
wchar_t *pwc = wcsrchr(pPath, L'\\');
|
||||||
|
if ( pwc && *(++pwc) )
|
||||||
|
return pwc;
|
||||||
|
|
||||||
|
return pPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2) {
|
||||||
|
if ( ma1 < ma2 ) return -1;
|
||||||
|
if ( ma1 > ma2 ) return 1;
|
||||||
|
if ( mi1 < mi2 ) return -1;
|
||||||
|
if ( mi1 > mi2 ) return 1;
|
||||||
|
if ( b1 < b2 ) return -1;
|
||||||
|
if ( b1 > b2 ) return 1;
|
||||||
|
if ( r1 < r2 ) return -1;
|
||||||
|
if ( r1 > r2 ) return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef HELPERS_H
|
#ifndef HELPERS_H_INCLUDED
|
||||||
#define HELPERS_H
|
#define HELPERS_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@@ -11,11 +11,10 @@ BOOL IsWindows8Point1(void);
|
|||||||
BOOL IsOperatingSystemSupported(void);
|
BOOL IsOperatingSystemSupported(void);
|
||||||
BOOL IsWow64(void);
|
BOOL IsWow64(void);
|
||||||
|
|
||||||
void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb);
|
size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount);
|
||||||
void resume_and_close_threads(LPHANDLE lphThreads, size_t cb);
|
void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount);
|
||||||
|
|
||||||
void get_cpuid_brand(char *brand);
|
char *get_cpuid_brand(char *brand, size_t nMaxCount);
|
||||||
|
wchar_t *find_fname(wchar_t *pPath);
|
||||||
#define STRINGIZE_(x) #x
|
int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2);
|
||||||
#define STRINGIZE(x) STRINGIZE_(x)
|
|
||||||
#endif
|
#endif
|
||||||
|
152
wufuc/hooks.c
152
wufuc/hooks.c
@@ -1,67 +1,121 @@
|
|||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
|
|
||||||
#include "service.h"
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
//#include "ntdllhelper.h"
|
#include "patchwua.h"
|
||||||
#include "logging.h"
|
#include "ntdllhelper.h"
|
||||||
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
//#define WIN32_NO_STATUS
|
#define WIN32_NO_STATUS
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
//#undef WIN32_NO_STATUS
|
#undef WIN32_NO_STATUS
|
||||||
|
|
||||||
//#include <winternl.h>
|
#include <ntstatus.h>
|
||||||
//#include <ntstatus.h>
|
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
//REGQUERYVALUEEXW fpRegQueryValueExW = NULL;
|
REGQUERYVALUEEXW pfnRegQueryValueExW = NULL;
|
||||||
LOADLIBRARYEXW fpLoadLibraryExW = NULL;
|
LOADLIBRARYEXW pfnLoadLibraryExW = NULL;
|
||||||
|
|
||||||
//LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
|
LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
|
||||||
// static NTQUERYKEY fpNtQueryKey = NULL;
|
size_t nMaxCount = *lpcbData / sizeof(wchar_t);
|
||||||
//
|
|
||||||
// DWORD cbData = *lpcbData;
|
LRESULT result = pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||||
//
|
|
||||||
// LRESULT result = fpRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
NTSTATUS status;
|
||||||
// if ( !result && lpData && !_wcsicmp((const wchar_t *)lpValueName, L"ServiceDll") ) {
|
ULONG ResultLength;
|
||||||
// if ( InitNTDLL() ) {
|
if ( !_wcsicmp(lpValueName, L"ServiceDll")
|
||||||
// if ( !fpNtQueryKey )
|
&& TryNtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength, &status)
|
||||||
// fpNtQueryKey = (NTQUERYKEY)GetProcAddress(g_hNTDLL, "NtQueryKey");
|
&& (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL) ) {
|
||||||
//
|
|
||||||
// if ( fpNtQueryKey ) {
|
PKEY_NAME_INFORMATION pkni = malloc(ResultLength);
|
||||||
// ULONG ResultLength;
|
if ( TryNtQueryKey((HANDLE)hKey, KeyNameInformation, (PVOID)pkni, ResultLength, &ResultLength, &status)
|
||||||
// NTSTATUS status = fpNtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength);
|
&& NT_SUCCESS(status) ) {
|
||||||
// if ( status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL ) {
|
|
||||||
// PVOID buffer = malloc(ResultLength);
|
size_t nBufferCount = pkni->NameLength / sizeof(wchar_t);
|
||||||
// if ( NT_SUCCESS(fpNtQueryKey((HANDLE)hKey, KeyNameInformation, buffer, ResultLength, &ResultLength))
|
int current, pos;
|
||||||
// && !_wcsnicmp(buffer, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\services\\wuauserv", (size_t)ResultLength) ) {
|
if ( _snwscanf_s(pkni->Name, nBufferCount, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet%03d\\services\\wuauserv\\Parameters%n", ¤t, &pos) == 1
|
||||||
//
|
&& pos == nBufferCount ) {
|
||||||
// wchar_t path[MAX_PATH], newpath[MAX_PATH];
|
|
||||||
// wcsncpy_s(path, _countof(path), (wchar_t *)lpData, (rsize_t)*lpcbData);
|
size_t nCount = nMaxCount + 1;
|
||||||
//
|
wchar_t *path = calloc(nCount, sizeof(wchar_t));
|
||||||
// if ( ApplyUpdatePack7R2ShimIfNeeded(path, _countof(path), newpath, _countof(newpath)) ) {
|
wcsncpy_s(path, nCount, (wchar_t *)lpData, *lpcbData / sizeof(wchar_t));
|
||||||
// trace(_T("UpdatePack7R2 shim: \"%ls\" -> \"%ls\""), path, newpath);
|
|
||||||
// wcscpy_s((wchar_t *)lpData, (rsize_t)cbData, newpath);
|
wchar_t *fname = find_fname(path);
|
||||||
// }
|
if ( !_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
|
||||||
// }
|
|| !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix
|
||||||
// free(buffer);
|
|| !_wcsicmp(fname, L"WuaCpuFix.dll") ) {
|
||||||
// }
|
|
||||||
// }
|
wcscpy_s(fname, nMaxCount - (fname - path), L"wuaueng.dll");
|
||||||
// }
|
|
||||||
// }
|
DWORD nSize = ExpandEnvironmentStringsW(path, NULL, 0);
|
||||||
// return result;
|
wchar_t *lpDst = calloc(nSize, sizeof(wchar_t));
|
||||||
//}
|
ExpandEnvironmentStringsW(path, lpDst, nSize);
|
||||||
|
if ( GetFileAttributesW(lpDst) != INVALID_FILE_ATTRIBUTES ) {
|
||||||
|
trace(_T("Compatibility fix: %.*ls -> %ls"), *lpcbData / sizeof(wchar_t), (wchar_t *)lpData, path);
|
||||||
|
size_t nLength = wcsnlen_s(path, nMaxCount);
|
||||||
|
wcsncpy_s((wchar_t *)lpData, nMaxCount, path, nLength);
|
||||||
|
*lpcbData = (DWORD)(nLength * sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
free(lpDst);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pkni);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) {
|
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) {
|
||||||
wchar_t buffer[MAX_PATH];
|
HMODULE result = pfnLoadLibraryExW(lpFileName, hFile, dwFlags);
|
||||||
wcscpy_s(buffer, _countof(buffer), lpFileName);
|
trace(_T("Loaded library: %ls"), lpFileName);
|
||||||
|
|
||||||
if ( !_wcsicmp(buffer, GetWindowsUpdateServiceDllW())
|
DWORD dwLen = GetFileVersionInfoSizeW(lpFileName, NULL);
|
||||||
&& ApplyUpdatePack7R2ShimIfNeeded(buffer, _countof(buffer), buffer, _countof(buffer)) ) {
|
if ( dwLen ) {
|
||||||
trace(_T("UpdatePack7R2 shim: %ls -> %ls"), lpFileName, buffer);
|
LPVOID pBlock = malloc(dwLen);
|
||||||
|
if ( GetFileVersionInfoW(lpFileName, 0, dwLen, pBlock) ) {
|
||||||
|
PLANGANDCODEPAGE ptl;
|
||||||
|
UINT cb;
|
||||||
|
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) ) {
|
||||||
|
wchar_t lpSubBlock[38];
|
||||||
|
for ( size_t i = 0; i < (cb / sizeof(LANGANDCODEPAGE)); i++ ) {
|
||||||
|
swprintf_s(lpSubBlock, _countof(lpSubBlock), L"\\StringFileInfo\\%04x%04x\\InternalName", ptl[i].wLanguage, ptl[i].wCodePage);
|
||||||
|
wchar_t *lpszInternalName;
|
||||||
|
UINT uLen;
|
||||||
|
if ( VerQueryValueW(pBlock, lpSubBlock, (LPVOID *)&lpszInternalName, &uLen)
|
||||||
|
&& !_wcsicmp(lpszInternalName, L"wuaueng.dll") ) {
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO *pffi;
|
||||||
|
VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen);
|
||||||
|
WORD wMajor = HIWORD(pffi->dwProductVersionMS);
|
||||||
|
WORD wMinor = LOWORD(pffi->dwProductVersionMS);
|
||||||
|
WORD wBuild = HIWORD(pffi->dwProductVersionLS);
|
||||||
|
WORD wRevision = LOWORD(pffi->dwProductVersionLS);
|
||||||
|
|
||||||
|
TCHAR fname[MAX_PATH];
|
||||||
|
GetModuleBaseName(GetCurrentProcess(), result, fname, _countof(fname));
|
||||||
|
|
||||||
|
if ( (IsWindows7() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 6, 7601, 23714) != -1)
|
||||||
|
|| (IsWindows8Point1() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 9, 9600, 18621) != -1) ) {
|
||||||
|
|
||||||
|
trace(_T("%s version: %d.%d.%d.%d"), fname, wMajor, wMinor, wBuild, wRevision);
|
||||||
|
MODULEINFO modinfo;
|
||||||
|
if ( GetModuleInformation(GetCurrentProcess(), result, &modinfo, sizeof(MODULEINFO)) ) {
|
||||||
|
if ( PatchWUA(modinfo.lpBaseOfDll, modinfo.SizeOfImage) )
|
||||||
|
trace(_T("Successfully patched %s!"), fname);
|
||||||
|
else trace(_T("Failed to patch %s!"), fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fpLoadLibraryExW((LPWSTR)buffer, hFile, dwFlags);
|
else trace(_T("Failed to get module information for %s (%p) (couldn't patch)"), fname, result);
|
||||||
|
} else trace(_T("Unsupported version of %s: %d.%d.%d.%d (patching skipped)"), fname, wMajor, wMinor, wBuild, wRevision);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pBlock);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -1,33 +1,23 @@
|
|||||||
#ifndef HOOKS_H
|
#ifndef HOOKS_H_INCLUDED
|
||||||
#define HOOKS_H
|
#define HOOKS_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//#define WIN32_NO_STATUS
|
#define WIN32_NO_STATUS
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
//#undef WIN32_NO_STATUS
|
#undef WIN32_NO_STATUS
|
||||||
|
|
||||||
//typedef enum _KEY_INFORMATION_CLASS {
|
typedef struct tagLANGANDCODEPAGE {
|
||||||
// KeyBasicInformation = 0,
|
WORD wLanguage;
|
||||||
// KeyNodeInformation = 1,
|
WORD wCodePage;
|
||||||
// KeyFullInformation = 2,
|
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
||||||
// KeyNameInformation = 3,
|
|
||||||
// KeyCachedInformation = 4,
|
typedef LRESULT(WINAPI *REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
||||||
// KeyFlagsInformation = 5,
|
|
||||||
// KeyVirtualizationInformation = 6,
|
|
||||||
// KeyHandleTagsInformation = 7,
|
|
||||||
// MaxKeyInfoClass = 8
|
|
||||||
//} KEY_INFORMATION_CLASS;
|
|
||||||
//
|
|
||||||
//typedef NTSTATUS(NTAPI *NTQUERYKEY)(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
|
||||||
//
|
|
||||||
//typedef LRESULT(WINAPI *REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
|
||||||
typedef HMODULE(WINAPI *LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
|
typedef HMODULE(WINAPI *LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
|
||||||
|
|
||||||
//extern REGQUERYVALUEEXW fpRegQueryValueExW;
|
extern REGQUERYVALUEEXW pfnRegQueryValueExW;
|
||||||
extern LOADLIBRARYEXW fpLoadLibraryExW;
|
extern LOADLIBRARYEXW pfnLoadLibraryExW;
|
||||||
|
|
||||||
LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
|
|
||||||
|
|
||||||
|
LRESULT 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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#include "iathook.h"
|
#include "iathook.h"
|
||||||
|
|
||||||
#include "logging.h"
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
@@ -32,10 +32,11 @@ void iat_hook(HMODULE hModule, LPCSTR lpFuncName, LPVOID *lpOldAddress, LPVOID l
|
|||||||
trace(_T("Modified IAT: hModule=%p, Name=%hs, OldAddress=%p, NewAddress=%p"), hModule, lpFuncName, *lpAddress, lpNewAddress);
|
trace(_T("Modified IAT: hModule=%p, Name=%hs, OldAddress=%p, NewAddress=%p"), hModule, lpFuncName, *lpAddress, lpNewAddress);
|
||||||
|
|
||||||
DWORD flOldProtect;
|
DWORD flOldProtect;
|
||||||
DWORD flNewProtect = PAGE_READWRITE;
|
if ( VirtualProtect(lpAddress, sizeof(LPVOID), PAGE_READWRITE, &flOldProtect) ) {
|
||||||
VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect);
|
|
||||||
if ( lpOldAddress )
|
if ( lpOldAddress )
|
||||||
*lpOldAddress = *lpAddress;
|
*lpOldAddress = *lpAddress;
|
||||||
*lpAddress = lpNewAddress;
|
*lpAddress = lpNewAddress;
|
||||||
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
|
if ( !VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flOldProtect) )
|
||||||
|
trace(_T("Failed to restore memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError());
|
||||||
|
} else trace(_T("Failed to change memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError());
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef IATHOOK_H
|
#ifndef IATHOOK_H_INCLUDED
|
||||||
#define IATHOOK_H
|
#define IATHOOK_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
@@ -1,59 +0,0 @@
|
|||||||
#include "logging.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
#include <Psapi.h>
|
|
||||||
|
|
||||||
static FILE *fp;
|
|
||||||
static BOOL logging_enabled = FALSE;
|
|
||||||
|
|
||||||
BOOL InitLogging(void) {
|
|
||||||
if ( fp )
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
TCHAR filename[MAX_PATH];
|
|
||||||
GetModuleFileName(HINST_THISCOMPONENT, filename, _countof(filename));
|
|
||||||
|
|
||||||
TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME];
|
|
||||||
_tsplitpath_s(filename, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), NULL, 0);
|
|
||||||
|
|
||||||
TCHAR basename[MAX_PATH];
|
|
||||||
GetModuleBaseNameW(GetCurrentProcess(), NULL, basename, _countof(basename));
|
|
||||||
_tcscat_s(fname, _countof(fname), _T("."));
|
|
||||||
_tcscat_s(fname, _countof(fname), basename);
|
|
||||||
_tmakepath_s(filename, _countof(filename), drive, dir, fname, _T(".log"));
|
|
||||||
|
|
||||||
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
LARGE_INTEGER size;
|
|
||||||
GetFileSizeEx(hFile, &size);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
fp = _tfsopen(filename, size.QuadPart < (1 << 20) ? _T("at") : _T("wt"), _SH_DENYWR);
|
|
||||||
return (fp != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void trace_(LPCTSTR format, ...) {
|
|
||||||
static DWORD dwProcessId = 0;
|
|
||||||
|
|
||||||
if ( InitLogging() ) {
|
|
||||||
if ( !dwProcessId )
|
|
||||||
dwProcessId = GetCurrentProcessId();
|
|
||||||
|
|
||||||
TCHAR datebuf[9], timebuf[9];
|
|
||||||
_tstrdate_s(datebuf, _countof(datebuf));
|
|
||||||
_tstrtime_s(timebuf, _countof(timebuf));
|
|
||||||
_ftprintf_s(fp, _T("%s %s [%d] "), datebuf, timebuf, dwProcessId);
|
|
||||||
|
|
||||||
va_list argptr;
|
|
||||||
va_start(argptr, format);
|
|
||||||
_vftprintf_s(fp, format, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
fflush(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL FreeLogging(void) {
|
|
||||||
return fp && !fclose(fp);
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
#ifndef LOGGING_H
|
|
||||||
#define LOGGING_H
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
|
|
||||||
extern IMAGE_DOS_HEADER __ImageBase;
|
|
||||||
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
|
||||||
|
|
||||||
BOOL InitLogging(void);
|
|
||||||
void trace_(LPCTSTR format, ...);
|
|
||||||
BOOL FreeLogging(void);
|
|
||||||
|
|
||||||
#define STRINGIZE_(x) #x
|
|
||||||
#define STRINGIZE(x) STRINGIZE_(x)
|
|
||||||
|
|
||||||
#define __LINESTR__ STRINGIZE(__LINE__)
|
|
||||||
#define trace(format, ...) trace_(_T(__FILE__) _T(":") _T(__LINESTR__) _T("(") _T(__FUNCTION__) _T("): ") format _T("\n"), ##__VA_ARGS__)
|
|
||||||
#endif
|
|
@@ -7,48 +7,23 @@
|
|||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
HMODULE g_hNTDLL = NULL;
|
static HMODULE g_hNTDLL = NULL;
|
||||||
|
|
||||||
BOOL InitNTDLL(void) {
|
static BOOL InitNTDLL(void) {
|
||||||
if ( !g_hNTDLL )
|
if ( !g_hNTDLL )
|
||||||
g_hNTDLL = LoadLibrary(_T("ntdll"));
|
g_hNTDLL = GetModuleHandle(_T("ntdll"));
|
||||||
return (g_hNTDLL != NULL);
|
return !!g_hNTDLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL FreeNTDLL(void) {
|
BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status) {
|
||||||
if ( g_hNTDLL ) {
|
static NTQUERYKEY pfnNtQueryKey = NULL;
|
||||||
BOOL result = FreeLibrary(g_hNTDLL);
|
|
||||||
if ( result )
|
|
||||||
g_hNTDLL = NULL;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL TryLdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID *Cookie, NTSTATUS *result) {
|
|
||||||
static LDRREGISTERDLLNOTIFICATION fpLdrRegisterDllNotification = NULL;
|
|
||||||
|
|
||||||
if ( InitNTDLL() ) {
|
if ( InitNTDLL() ) {
|
||||||
if ( !fpLdrRegisterDllNotification )
|
if ( !pfnNtQueryKey )
|
||||||
fpLdrRegisterDllNotification = (LDRREGISTERDLLNOTIFICATION)GetProcAddress(g_hNTDLL, "LdrRegisterDllNotification");
|
pfnNtQueryKey = (NTQUERYKEY)GetProcAddress(g_hNTDLL, "NtQueryKey");
|
||||||
|
|
||||||
if ( fpLdrRegisterDllNotification ) {
|
if ( pfnNtQueryKey ) {
|
||||||
*result = fpLdrRegisterDllNotification(Flags, NotificationFunction, Context, Cookie);
|
*status = pfnNtQueryKey(KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL TryLdrUnregisterDllNotification(PVOID Cookie, NTSTATUS *result) {
|
|
||||||
static LDRUNREGISTERDLLNOTIFICATION fpLdrUnregisterDllNotification = NULL;
|
|
||||||
|
|
||||||
if ( InitNTDLL() ) {
|
|
||||||
if ( !fpLdrUnregisterDllNotification )
|
|
||||||
fpLdrUnregisterDllNotification = (LDRUNREGISTERDLLNOTIFICATION)GetProcAddress(g_hNTDLL, "LdrUnregisterDllNotification");
|
|
||||||
|
|
||||||
if ( fpLdrUnregisterDllNotification ) {
|
|
||||||
*result = fpLdrUnregisterDllNotification(Cookie);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef NTDLLHELPER_H
|
#ifndef NTDLLHELPER_H_INCLUDED
|
||||||
#define NTDLLHELPER_H
|
#define NTDLLHELPER_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define WIN32_NO_STATUS
|
#define WIN32_NO_STATUS
|
||||||
@@ -8,42 +8,24 @@
|
|||||||
|
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
|
typedef enum tagKEY_INFORMATION_CLASS {
|
||||||
ULONG Flags;
|
KeyBasicInformation = 0,
|
||||||
PUNICODE_STRING FullDllName;
|
KeyNodeInformation = 1,
|
||||||
PUNICODE_STRING BaseDllName;
|
KeyFullInformation = 2,
|
||||||
PVOID DllBase;
|
KeyNameInformation = 3,
|
||||||
ULONG SizeOfImage;
|
KeyCachedInformation = 4,
|
||||||
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
|
KeyFlagsInformation = 5,
|
||||||
|
KeyVirtualizationInformation = 6,
|
||||||
|
KeyHandleTagsInformation = 7,
|
||||||
|
MaxKeyInfoClass = 8
|
||||||
|
} KEY_INFORMATION_CLASS;
|
||||||
|
|
||||||
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
|
typedef struct tagKEY_NAME_INFORMATION {
|
||||||
ULONG Flags;
|
ULONG NameLength;
|
||||||
PCUNICODE_STRING FullDllName;
|
WCHAR Name[1];
|
||||||
PCUNICODE_STRING BaseDllName;
|
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
|
||||||
PVOID DllBase;
|
|
||||||
ULONG SizeOfImage;
|
|
||||||
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
|
|
||||||
|
|
||||||
typedef union _LDR_DLL_NOTIFICATION_DATA {
|
typedef NTSTATUS(NTAPI *NTQUERYKEY)(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||||
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
|
|
||||||
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
|
|
||||||
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
|
|
||||||
typedef const LDR_DLL_NOTIFICATION_DATA *PCLDR_DLL_NOTIFICATION_DATA;
|
|
||||||
|
|
||||||
typedef VOID(CALLBACK *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG, PCLDR_DLL_NOTIFICATION_DATA, PVOID);
|
BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status);
|
||||||
|
|
||||||
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
|
|
||||||
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
|
|
||||||
|
|
||||||
typedef NTSTATUS(NTAPI *LDRREGISTERDLLNOTIFICATION)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, PVOID, PVOID *);
|
|
||||||
typedef NTSTATUS(NTAPI *LDRUNREGISTERDLLNOTIFICATION)(PVOID);
|
|
||||||
|
|
||||||
extern HMODULE g_hNTDLL;
|
|
||||||
|
|
||||||
BOOL InitNTDLL(void);
|
|
||||||
|
|
||||||
BOOL FreeNTDLL(void);
|
|
||||||
|
|
||||||
BOOL TryLdrRegisterDllNotification(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, PVOID Context, PVOID *Cookie, NTSTATUS *result);
|
|
||||||
BOOL TryLdrUnregisterDllNotification(PVOID Cookie, NTSTATUS *result);
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "patternfind.h"
|
#include "patternfind.h"
|
||||||
#include "logging.h"
|
#include "tracing.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -10,60 +10,61 @@
|
|||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
|
|
||||||
BOOL PatchWUA(void *lpBaseOfDll, size_t SizeOfImage) {
|
BOOL PatchWUA(void *lpBaseOfDll, size_t SizeOfImage) {
|
||||||
char *pattern;
|
char *pattern;
|
||||||
size_t offset00, offset01;
|
size_t offset1, offset2;
|
||||||
#ifdef _AMD64_
|
#ifdef _AMD64_
|
||||||
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
|
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
|
||||||
offset00 = 10;
|
offset1 = 10;
|
||||||
offset01 = 18;
|
offset2 = 18;
|
||||||
#elif defined(_X86_)
|
#elif defined(_X86_)
|
||||||
if ( IsWindows7() ) {
|
if ( IsWindows7() ) {
|
||||||
pattern = "833D????????00 743E E8???????? A3????????";
|
pattern = "833D????????00 743E E8???????? A3????????";
|
||||||
offset00 = 2;
|
offset1 = 2;
|
||||||
offset01 = 15;
|
offset2 = 15;
|
||||||
} else if ( IsWindows8Point1() ) {
|
} else if ( IsWindows8Point1() ) {
|
||||||
pattern = "8BFF 51 833D????????00 7507 A1????????";
|
pattern = "8BFF 51 833D????????00 7507 A1????????";
|
||||||
offset00 = 5;
|
offset1 = 5;
|
||||||
offset01 = 13;
|
offset2 = 13;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, 0, pattern);
|
unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, 0, pattern);
|
||||||
if ( !ptr ) {
|
if ( !ptr ) {
|
||||||
trace(_T("No pattern match!"));
|
trace(_T("No pattern match! (couldn't patch)"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
trace(_T("wuaueng!IsDeviceServiceable VA: %p"), ptr);
|
TCHAR fname[MAX_PATH];
|
||||||
BOOL result = FALSE;
|
GetModuleBaseName(GetCurrentProcess(), (HMODULE)lpBaseOfDll, fname, _countof(fname));
|
||||||
LPBOOL lpbFirstRun, lpbIsCPUSupportedResult;
|
trace(_T("Matched pattern for IsDeviceServiceable at %s+0x%zx"), fname,
|
||||||
|
(size_t)((uintptr_t)ptr - (uintptr_t)lpBaseOfDll));
|
||||||
|
LPBOOL lpb1, lpb2;
|
||||||
#ifdef _AMD64_
|
#ifdef _AMD64_
|
||||||
lpbFirstRun = (LPBOOL)(ptr + offset00 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset00));
|
lpb1 = (LPBOOL)(ptr + offset1 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset1));
|
||||||
lpbIsCPUSupportedResult = (LPBOOL)(ptr + offset01 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset01));
|
lpb2 = (LPBOOL)(ptr + offset2 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset2));
|
||||||
#elif defined(_X86_)
|
#elif defined(_X86_)
|
||||||
lpbFirstRun = (LPBOOL)(*(uintptr_t *)(ptr + offset00));
|
lpb1 = (LPBOOL)(*(uintptr_t *)(ptr + offset1));
|
||||||
lpbIsCPUSupportedResult = (LPBOOL)(*(uintptr_t *)(ptr + offset01));
|
lpb2 = (LPBOOL)(*(uintptr_t *)(ptr + offset2));
|
||||||
#endif
|
#endif
|
||||||
|
offset1 = (size_t)((uintptr_t)lpb1 - (uintptr_t)lpBaseOfDll);
|
||||||
|
offset2 = (size_t)((uintptr_t)lpb2 - (uintptr_t)lpBaseOfDll);
|
||||||
|
|
||||||
DWORD flNewProtect = PAGE_READWRITE;
|
|
||||||
DWORD flOldProtect;
|
DWORD flOldProtect;
|
||||||
if ( *lpbFirstRun ) {
|
if ( *lpb1 ) {
|
||||||
VirtualProtect(lpbFirstRun, sizeof(BOOL), flNewProtect, &flOldProtect);
|
if ( VirtualProtect(lpb1, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||||
*lpbFirstRun = FALSE;
|
*lpb1 = FALSE;
|
||||||
VirtualProtect(lpbFirstRun, sizeof(BOOL), flOldProtect, &flNewProtect);
|
trace(_T("Patched value #1 at %s+0x%zx: %08x"), fname, offset1, *lpb1);
|
||||||
trace(_T("Patched boolean value #1: %p = %s"), lpbFirstRun, *lpbFirstRun ? L"TRUE" : L"FALSE");
|
if ( !VirtualProtect(lpb1, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||||
result = TRUE;
|
trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError());
|
||||||
|
} else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError());
|
||||||
}
|
}
|
||||||
if ( !*lpbIsCPUSupportedResult ) {
|
if ( !*lpb2 ) {
|
||||||
VirtualProtect(lpbIsCPUSupportedResult, sizeof(BOOL), flNewProtect, &flOldProtect);
|
if ( VirtualProtect(lpb2, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||||
*lpbIsCPUSupportedResult = TRUE;
|
*lpb2 = TRUE;
|
||||||
VirtualProtect(lpbIsCPUSupportedResult, sizeof(BOOL), flOldProtect, &flNewProtect);
|
trace(_T("Patched value #2 at %s+0x%zx: %08x"), fname, offset2, *lpb2);
|
||||||
trace(_T("Patched boolean value #2: %p = %s"), lpbIsCPUSupportedResult, *lpbIsCPUSupportedResult ? L"TRUE" : L"FALSE");
|
if ( !VirtualProtect(lpb2, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||||
result = TRUE;
|
trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError());
|
||||||
|
} else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError());
|
||||||
}
|
}
|
||||||
if ( result )
|
return !*lpb1 && *lpb2;
|
||||||
trace(_T("Successfully patched WUA module!"));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef PATCHWUA_H
|
#ifndef PATCHWUA_H_INCLUDED
|
||||||
#define PATCHWUA_H
|
#define PATCHWUA_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
/* Ported to C from x64dbg's patternfind.cpp:
|
/* Ported to Win32 C from x64dbg's patternfind.cpp:
|
||||||
* https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp
|
* https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp
|
||||||
|
*
|
||||||
* x64dbg license (GPL-3.0):
|
* x64dbg license (GPL-3.0):
|
||||||
* https://github.com/x64dbg/x64dbg/blob/development/LICENSE
|
* https://github.com/x64dbg/x64dbg/blob/development/LICENSE
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +35,7 @@ static size_t formathexpattern(const char *patterntext, char *formattext, size_t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL patterntransform(const char *patterntext, LPPATTERNBYTE pattern, size_t *patternsize) {
|
static BOOL patterntransform(const char *patterntext, PPATTERNBYTE pattern, size_t *patternsize) {
|
||||||
size_t cb = formathexpattern(patterntext, NULL, 0);
|
size_t cb = formathexpattern(patterntext, NULL, 0);
|
||||||
if ( !cb || cb > *patternsize )
|
if ( !cb || cb > *patternsize )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -60,7 +61,7 @@ static BOOL patterntransform(const char *patterntext, LPPATTERNBYTE pattern, siz
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void patternwritebyte(unsigned char *byte, LPPATTERNBYTE pbyte) {
|
static void patternwritebyte(unsigned char *byte, PPATTERNBYTE pbyte) {
|
||||||
unsigned char n1 = (*byte >> 4) & 0xf;
|
unsigned char n1 = (*byte >> 4) & 0xf;
|
||||||
unsigned char n2 = *byte & 0xf;
|
unsigned char n2 = *byte & 0xf;
|
||||||
if ( !pbyte->nibble[0].wildcard )
|
if ( !pbyte->nibble[0].wildcard )
|
||||||
@@ -77,12 +78,10 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte
|
|||||||
writepatternsize = datasize;
|
writepatternsize = datasize;
|
||||||
|
|
||||||
BOOL result = FALSE;
|
BOOL result = FALSE;
|
||||||
LPPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE));
|
PPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE));
|
||||||
if ( patterntransform(pattern, writepattern, &writepatternsize) ) {
|
if ( patterntransform(pattern, writepattern, &writepatternsize) ) {
|
||||||
DWORD flNewProtect = PAGE_READWRITE;
|
|
||||||
DWORD flOldProtect;
|
DWORD flOldProtect;
|
||||||
|
if ( result = VirtualProtect(data, writepatternsize, PAGE_READWRITE, &flOldProtect) ) {
|
||||||
if ( result = VirtualProtect(data, writepatternsize, flNewProtect, &flOldProtect) ) {
|
|
||||||
for ( size_t i = 0; i < writepatternsize; i++ ) {
|
for ( size_t i = 0; i < writepatternsize; i++ ) {
|
||||||
BYTE n1 = (data[i] >> 4) & 0xf;
|
BYTE n1 = (data[i] >> 4) & 0xf;
|
||||||
BYTE n2 = data[i] & 0xf;
|
BYTE n2 = data[i] & 0xf;
|
||||||
@@ -92,7 +91,7 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte
|
|||||||
if ( !writepattern[i].nibble[1].wildcard )
|
if ( !writepattern[i].nibble[1].wildcard )
|
||||||
n2 = writepattern[i].nibble[1].data;
|
n2 = writepattern[i].nibble[1].data;
|
||||||
data[i] = ((n1 << 4) & 0xf0) | (n2 & 0xf);
|
data[i] = ((n1 << 4) & 0xf0) | (n2 & 0xf);
|
||||||
result = VirtualProtect(data, writepatternsize, flOldProtect, &flNewProtect);
|
result = VirtualProtect(data, writepatternsize, flOldProtect, &flOldProtect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +102,7 @@ static BOOL patternwrite(unsigned char *data, size_t datasize, const char *patte
|
|||||||
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern) {
|
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern) {
|
||||||
unsigned char *result = NULL;
|
unsigned char *result = NULL;
|
||||||
size_t searchpatternsize = strlen(pattern);
|
size_t searchpatternsize = strlen(pattern);
|
||||||
LPPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE));
|
PPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE));
|
||||||
|
|
||||||
if ( patterntransform(pattern, searchpattern, &searchpatternsize) ) {
|
if ( patterntransform(pattern, searchpattern, &searchpatternsize) ) {
|
||||||
for ( size_t i = startindex, j = 0; i < datasize; i++ ) { //search for the pattern
|
for ( size_t i = startindex, j = 0; i < datasize; i++ ) { //search for the pattern
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
#ifndef PATTERNFIND_H
|
#ifndef PATTERNFIND_H_INCLUDED
|
||||||
#define PATTERNFIND_H
|
#define PATTERNFIND_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
typedef struct _PATTERNBYTE {
|
typedef struct tagPATTERNBYTE {
|
||||||
struct _PATTERNNIBBLE {
|
struct tagPATTERNNIBBLE {
|
||||||
unsigned char data;
|
unsigned char data;
|
||||||
BOOL wildcard;
|
BOOL wildcard;
|
||||||
} nibble[2];
|
} nibble[2];
|
||||||
} PATTERNBYTE, *PPATTERNBYTE, *LPPATTERNBYTE;
|
} PATTERNBYTE, *PPATTERNBYTE;
|
||||||
|
|
||||||
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern);
|
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern);
|
||||||
unsigned char *patternsnr(unsigned char *data, size_t datasize, size_t startindex, const char *searchpattern, const char *replacepattern);
|
unsigned char *patternsnr(unsigned char *data, size_t datasize, size_t startindex, const char *searchpattern, const char *replacepattern);
|
||||||
|
@@ -1,77 +1,8 @@
|
|||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "helpers.h"
|
#include "tracing.h"
|
||||||
#include "logging.h"
|
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <TlHelp32.h>
|
|
||||||
#include <VersionHelpers.h>
|
|
||||||
|
|
||||||
void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
|
||||||
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
|
||||||
if ( hEvent ) {
|
|
||||||
CloseHandle(hEvent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t *osname;
|
|
||||||
if ( IsWindows7() ) {
|
|
||||||
if ( IsWindowsServer() )
|
|
||||||
osname = _T("Windows Server 2008 R2");
|
|
||||||
else
|
|
||||||
osname = _T("Windows 7");
|
|
||||||
} else if ( IsWindows8Point1() ) {
|
|
||||||
if ( IsWindowsServer() )
|
|
||||||
osname = _T("Windows Server 2012 R2");
|
|
||||||
else
|
|
||||||
osname = _T("Windows 8.1");
|
|
||||||
}
|
|
||||||
trace(_T("Operating System: %s %d-bit"), osname, sizeof(uintptr_t) * 8);
|
|
||||||
|
|
||||||
char brand[0x31];
|
|
||||||
get_cpuid_brand(brand);
|
|
||||||
size_t i = 0;
|
|
||||||
while ( i < _countof(brand) && isspace(brand[i]) )
|
|
||||||
i++;
|
|
||||||
|
|
||||||
trace(_T("Processor: %hs"), brand + i);
|
|
||||||
|
|
||||||
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
|
|
||||||
if ( !hSCManager )
|
|
||||||
return;
|
|
||||||
|
|
||||||
TCHAR lpGroupName[256];
|
|
||||||
DWORD dwProcessId;
|
|
||||||
BOOL result = GetServiceProcessId(hSCManager, _T("wuauserv"), &dwProcessId);
|
|
||||||
if ( !result && GetServiceGroupName(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName)) )
|
|
||||||
result = GetServiceGroupProcessId(hSCManager, lpGroupName, &dwProcessId);
|
|
||||||
|
|
||||||
CloseServiceHandle(hSCManager);
|
|
||||||
if ( !result )
|
|
||||||
return;
|
|
||||||
|
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
|
|
||||||
if ( !hProcess )
|
|
||||||
return;
|
|
||||||
|
|
||||||
TCHAR lpLibFileName[MAX_PATH];
|
|
||||||
GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName));
|
|
||||||
SIZE_T size = (SIZE_T)((_tcslen(lpLibFileName) + 1) * sizeof(TCHAR));
|
|
||||||
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
|
|
||||||
if ( lpBaseAddress && WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, size, NULL) ) {
|
|
||||||
HANDLE hThread = CreateRemoteThread(
|
|
||||||
hProcess, NULL, 0,
|
|
||||||
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), STRINGIZE(LoadLibrary)),
|
|
||||||
lpBaseAddress, 0, NULL
|
|
||||||
);
|
|
||||||
WaitForSingleObject(hThread, INFINITE);
|
|
||||||
trace(_T("Injected into process: %d"), dwProcessId);
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
|
|
||||||
CloseHandle(hProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
||||||
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||||
|
153
wufuc/service.c
153
wufuc/service.c
@@ -1,128 +1,9 @@
|
|||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpCommandLine, SIZE_T dwSize) {
|
||||||
#include "shellapihelper.h"
|
|
||||||
#include "logging.h"
|
|
||||||
|
|
||||||
static BOOL OpenServiceParametersKey(LPCWSTR lpSubKey, PHKEY phkResult) {
|
|
||||||
BOOL result = FALSE;
|
|
||||||
HKEY hKey, hSubKey;
|
|
||||||
if ( !RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services", 0, KEY_READ, &hKey)
|
|
||||||
&& !RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, &hSubKey)
|
|
||||||
&& !RegOpenKeyExW(hSubKey, L"Parameters", 0, KEY_READ, phkResult) ) {
|
|
||||||
|
|
||||||
result = TRUE;
|
|
||||||
}
|
|
||||||
if ( hKey )
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
|
|
||||||
if ( hSubKey )
|
|
||||||
RegCloseKey(hSubKey);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL FindServiceDllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize) {
|
|
||||||
BOOL result = FALSE;
|
|
||||||
HKEY hKey;
|
|
||||||
if ( OpenServiceParametersKey(lpServiceName, &hKey) ) {
|
|
||||||
DWORD cb = dwSize;
|
|
||||||
if ( !RegGetValueW(hKey, NULL, L"ServiceDll", RRF_RT_REG_SZ, NULL, lpServiceDll, &cb) ) {
|
|
||||||
trace(_T("Service \"%s\" DLL path: %ls"), lpServiceName, lpServiceDll);
|
|
||||||
result = TRUE;
|
|
||||||
}
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPWSTR GetWindowsUpdateServiceDllW(void) {
|
|
||||||
static WCHAR path[MAX_PATH];
|
|
||||||
|
|
||||||
if ( !path[0] ) {
|
|
||||||
if ( !FindServiceDllW(L"wuauserv", path, _countof(path)) )
|
|
||||||
path[0] = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ApplyUpdatePack7R2ShimIfNeeded(const wchar_t *path, size_t pathsize, wchar_t *newpath, size_t newpathsize) {
|
|
||||||
wchar_t drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
|
|
||||||
_wsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), ext, _countof(ext));
|
|
||||||
if ( !_wcsicmp(fname, L"wuaueng2") ) {
|
|
||||||
_wmakepath_s(newpath, newpathsize, drive, dir, L"wuaueng", ext);
|
|
||||||
return GetFileAttributesW(newpath) != INVALID_FILE_ATTRIBUTES;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL GetServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPDWORD lpdwProcessId) {
|
|
||||||
BOOL result = FALSE;
|
|
||||||
BOOL selfclose = !hSCManager;
|
|
||||||
if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
|
|
||||||
|
|
||||||
if ( selfclose )
|
|
||||||
CloseServiceHandle(hSCManager);
|
|
||||||
|
|
||||||
if ( !hService )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
SERVICE_STATUS_PROCESS buffer;
|
|
||||||
DWORD cb;
|
|
||||||
if ( QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&buffer, sizeof(buffer), &cb)
|
|
||||||
&& buffer.dwProcessId ) {
|
|
||||||
|
|
||||||
*lpdwProcessId = buffer.dwProcessId;
|
|
||||||
trace(_T("Service \"%s\" process ID: %d"), lpServiceName, *lpdwProcessId);
|
|
||||||
result = TRUE;
|
|
||||||
}
|
|
||||||
CloseServiceHandle(hService);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
|
|
||||||
BOOL result = FALSE;
|
|
||||||
BOOL selfclose = !hSCManager;
|
|
||||||
if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
TCHAR lpBinaryPathName[0x8000];
|
|
||||||
if ( !GetServiceCommandLine(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName)) )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if ( selfclose )
|
|
||||||
CloseServiceHandle(hSCManager);
|
|
||||||
|
|
||||||
int numArgs;
|
|
||||||
LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs);
|
|
||||||
if ( numArgs < 3 )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
TCHAR fname[_MAX_FNAME];
|
|
||||||
_tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0);
|
|
||||||
|
|
||||||
if ( !_tcsicmp(fname, _T("svchost")) ) {
|
|
||||||
LPWSTR *p = argv;
|
|
||||||
for ( int i = 1; i < numArgs; i++ ) {
|
|
||||||
if ( !_tcsicmp(*(p++), _T("-k")) && !_tcscpy_s(lpGroupName, dwSize, *p) ) {
|
|
||||||
result = TRUE;
|
|
||||||
trace(_T("Service \"%s\" group name: %s"), lpServiceName, lpGroupName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
|
|
||||||
BOOL result = FALSE;
|
BOOL result = FALSE;
|
||||||
if ( !hSCManager && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
if ( !hSCManager && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
||||||
return result;
|
return result;
|
||||||
@@ -137,40 +18,10 @@ BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR l
|
|||||||
|
|
||||||
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
|
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
|
||||||
if ( QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded)
|
if ( QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded)
|
||||||
&& !_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName) )
|
&& !_tcscpy_s(lpCommandLine, dwSize, sc->lpBinaryPathName) )
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
free(sc);
|
free(sc);
|
||||||
}
|
}
|
||||||
CloseServiceHandle(hService);
|
CloseServiceHandle(hService);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL GetServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, LPDWORD lpdwProcessId) {
|
|
||||||
BOOL result = FALSE;
|
|
||||||
BOOL selfclose = !hSCManager;
|
|
||||||
if ( selfclose && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
|
||||||
return result;
|
|
||||||
|
|
||||||
DWORD uBytes = 1 << 20;
|
|
||||||
LPBYTE pvData = malloc(uBytes);
|
|
||||||
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"),
|
|
||||||
lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
|
|
||||||
|
|
||||||
for ( LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1 ) {
|
|
||||||
DWORD dwProcessId;
|
|
||||||
TCHAR group[256];
|
|
||||||
if ( GetServiceProcessId(hSCManager, p, &dwProcessId)
|
|
||||||
&& (GetServiceGroupName(hSCManager, p, group, _countof(group))
|
|
||||||
&& !_tcsicmp(group, lpServiceGroupName)) ) {
|
|
||||||
|
|
||||||
*lpdwProcessId = dwProcessId;
|
|
||||||
result = TRUE;
|
|
||||||
trace(_T("Service group \"%s\" process ID: %d"), lpServiceGroupName, *lpdwProcessId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(pvData);
|
|
||||||
if ( selfclose )
|
|
||||||
CloseServiceHandle(hSCManager);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
@@ -1,14 +1,8 @@
|
|||||||
#ifndef SERVICE_H
|
#ifndef SERVICE_H_INCLUDED
|
||||||
#define SERVICE_H
|
#define SERVICE_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
BOOL FindServiceDllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD nCount);
|
|
||||||
LPWSTR GetWindowsUpdateServiceDllW(void);
|
|
||||||
BOOL ApplyUpdatePack7R2ShimIfNeeded(const wchar_t *path, size_t pathsize, wchar_t *newpath, size_t newpathsize);
|
|
||||||
BOOL GetServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPDWORD lpdwProcessId);
|
|
||||||
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
|
|
||||||
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
|
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
|
||||||
BOOL GetServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, LPDWORD lpdwProcessId);
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
#ifndef SHELLAPIHELPER_H
|
|
||||||
#define SHELLAPIHELPER_H
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
#define CommandLineToArgv CommandLineToArgvW
|
|
||||||
#else
|
|
||||||
#define CommandLineToArgv CommandLineToArgvA
|
|
||||||
#endif
|
|
||||||
#endif
|
|
72
wufuc/tracing.c
Normal file
72
wufuc/tracing.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include "tracing.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
static FILE *m_pStream;
|
||||||
|
static HANDLE m_hMutex;
|
||||||
|
static BOOL m_bDeinitializing;
|
||||||
|
|
||||||
|
BOOL InitTracing(void) {
|
||||||
|
if ( m_bDeinitializing )
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ( !m_hMutex )
|
||||||
|
m_hMutex = CreateMutex(NULL, FALSE, _T("Global\\wufuc_TracingMutex"));
|
||||||
|
|
||||||
|
if ( m_hMutex && !m_pStream ) {
|
||||||
|
TCHAR path[MAX_PATH];
|
||||||
|
GetModuleFileName(HINST_THISCOMPONENT, path, _countof(path));
|
||||||
|
|
||||||
|
TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME];
|
||||||
|
_tsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), NULL, 0);
|
||||||
|
_tmakepath_s(path, _countof(path), drive, dir, fname, _T(".log"));
|
||||||
|
|
||||||
|
m_pStream = _tfsopen(path, _T("at"), _SH_DENYNO);
|
||||||
|
}
|
||||||
|
return m_pStream && m_hMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WaitForTracingMutex(void) {
|
||||||
|
return WaitForSingleObject(m_hMutex, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ReleaseTracingMutex(void) {
|
||||||
|
return ReleaseMutex(m_hMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace_(LPCTSTR format, ...) {
|
||||||
|
if ( InitTracing() ) {
|
||||||
|
TCHAR datebuf[9], timebuf[9];
|
||||||
|
_tstrdate_s(datebuf, _countof(datebuf));
|
||||||
|
_tstrtime_s(timebuf, _countof(timebuf));
|
||||||
|
if ( !WaitForTracingMutex() ) {
|
||||||
|
_ftprintf_s(m_pStream, _T("%s %s [PID: %d TID: %d] "), datebuf, timebuf, GetCurrentProcessId(), GetCurrentThreadId());
|
||||||
|
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, format);
|
||||||
|
_vftprintf_s(m_pStream, format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
fflush(m_pStream);
|
||||||
|
}
|
||||||
|
ReleaseTracingMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL DeinitTracing(void) {
|
||||||
|
m_bDeinitializing = TRUE;
|
||||||
|
|
||||||
|
BOOL result = TRUE;
|
||||||
|
if ( m_hMutex ) {
|
||||||
|
result = CloseHandle(m_hMutex);
|
||||||
|
m_hMutex = NULL;
|
||||||
|
}
|
||||||
|
if ( m_pStream ) {
|
||||||
|
result = result && !fclose(m_pStream);
|
||||||
|
m_pStream = NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
22
wufuc/tracing.h
Normal file
22
wufuc/tracing.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef LOGGING_H_INCLUDED
|
||||||
|
#define LOGGING_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
extern IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
||||||
|
|
||||||
|
BOOL InitTracing(void);
|
||||||
|
DWORD WaitForTracingMutex(void);
|
||||||
|
BOOL ReleaseTracingMutex(void);
|
||||||
|
void trace_(LPCTSTR format, ...);
|
||||||
|
BOOL DeinitTracing(void);
|
||||||
|
|
||||||
|
#define STRINGIZE_(x) #x
|
||||||
|
#define STRINGIZE(x) STRINGIZE_(x)
|
||||||
|
|
||||||
|
#define LINESTR STRINGIZE(__LINE__)
|
||||||
|
#define trace(format, ...) trace_(_T(__FILE__) _T(":") _T(LINESTR) _T("(") _T(__FUNCTION__) _T("): ") format _T("\n"), ##__VA_ARGS__)
|
||||||
|
#endif
|
@@ -1,3 +1,2 @@
|
|||||||
EXPORTS
|
EXPORTS
|
||||||
Rundll32Entry
|
|
||||||
Rundll32Unload
|
Rundll32Unload
|
||||||
|
BIN
wufuc/wufuc.rc
BIN
wufuc/wufuc.rc
Binary file not shown.
17
wufuc/wufuc.rch
Normal file
17
wufuc/wufuc.rch
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef WUFUC_RCH_INCLUDED
|
||||||
|
#define WUFUC_RCH_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
#ifndef BUILD_COMMIT_VERSION
|
||||||
|
#define BUILD_COMMIT_VERSION 0.8.0.0
|
||||||
|
#endif
|
||||||
|
#ifndef BUILD_VERSION_COMMA
|
||||||
|
#define BUILD_VERSION_COMMA 0,8.0,0
|
||||||
|
#endif
|
||||||
|
#define STRINGIZE_(x) #x
|
||||||
|
#define STRINGIZE(x) STRINGIZE_(x)
|
||||||
|
#ifdef X64
|
||||||
|
#define WUFUC_DLL "wufuc64.dll"
|
||||||
|
#elif defined(X86)
|
||||||
|
#define WUFUC_DLL "wufuc32.dll"
|
||||||
|
#endif
|
||||||
|
#endif
|
@@ -18,6 +18,44 @@
|
|||||||
<Platform>x64</Platform>
|
<Platform>x64</Platform>
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="callbacks.h" />
|
||||||
|
<ClInclude Include="helpers.h" />
|
||||||
|
<ClInclude Include="hooks.h" />
|
||||||
|
<ClInclude Include="iathook.h" />
|
||||||
|
<ClInclude Include="tracing.h" />
|
||||||
|
<ClInclude Include="ntdllhelper.h" />
|
||||||
|
<ClInclude Include="patchwua.h" />
|
||||||
|
<ClInclude Include="patternfind.h" />
|
||||||
|
<ClInclude Include="service.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="callbacks.c" />
|
||||||
|
<ClCompile Include="dllmain.c" />
|
||||||
|
<ClCompile Include="helpers.c" />
|
||||||
|
<ClCompile Include="hooks.c" />
|
||||||
|
<ClCompile Include="iathook.c" />
|
||||||
|
<ClCompile Include="tracing.c" />
|
||||||
|
<ClCompile Include="ntdllhelper.c" />
|
||||||
|
<ClCompile Include="patchwua.c" />
|
||||||
|
<ClCompile Include="patternfind.c" />
|
||||||
|
<ClCompile Include="rundll32.c" />
|
||||||
|
<ClCompile Include="service.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="wufuc.def" />
|
||||||
|
<ClInclude Include="wufuc.rch">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="wufuc.rc">
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{00F96695-CE41-4C2F-A344-6219DFB4F887}</ProjectGuid>
|
<ProjectGuid>{00F96695-CE41-4C2F-A344-6219DFB4F887}</ProjectGuid>
|
||||||
@@ -108,7 +146,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@@ -122,29 +160,30 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>Full</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
||||||
<PreprocessorDefinitions>BUILD_VERSION=$(BUILD_VERSION);BUILD_VERSION_COMMA_SEP=$(BUILD_VERSION_COMMA_SEP);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
@@ -155,22 +194,23 @@
|
|||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>Full</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<CompileAs>CompileAsC</CompileAs>
|
<CompileAs>CompileAsC</CompileAs>
|
||||||
|
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
||||||
<PreprocessorDefinitions>BUILD_VERSION=$(BUILD_VERSION);BUILD_VERSION_COMMA_SEP=$(BUILD_VERSION_COMMA_SEP);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
@@ -178,37 +218,6 @@
|
|||||||
</Command>
|
</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="callbacks.c" />
|
|
||||||
<ClCompile Include="hooks.c" />
|
|
||||||
<ClCompile Include="dllmain.c" />
|
|
||||||
<ClCompile Include="iathook.c" />
|
|
||||||
<ClCompile Include="logging.c" />
|
|
||||||
<ClCompile Include="ntdllhelper.c" />
|
|
||||||
<ClCompile Include="patchwua.c" />
|
|
||||||
<ClCompile Include="patternfind.c" />
|
|
||||||
<ClCompile Include="rundll32.c" />
|
|
||||||
<ClCompile Include="service.c" />
|
|
||||||
<ClCompile Include="helpers.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="callbacks.h" />
|
|
||||||
<ClInclude Include="hooks.h" />
|
|
||||||
<ClInclude Include="iathook.h" />
|
|
||||||
<ClInclude Include="logging.h" />
|
|
||||||
<ClInclude Include="ntdllhelper.h" />
|
|
||||||
<ClInclude Include="patchwua.h" />
|
|
||||||
<ClInclude Include="patternfind.h" />
|
|
||||||
<ClInclude Include="service.h" />
|
|
||||||
<ClInclude Include="shellapihelper.h" />
|
|
||||||
<ClInclude Include="helpers.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="wufuc.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="wufuc.def" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@@ -1,34 +1,94 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="hooks.c" />
|
<Filter Include="Header Files">
|
||||||
<ClCompile Include="dllmain.c" />
|
<UniqueIdentifier>{629a1242-73f5-4282-a218-7b8d7d761cc6}</UniqueIdentifier>
|
||||||
<ClCompile Include="iathook.c" />
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
<ClCompile Include="logging.c" />
|
</Filter>
|
||||||
<ClCompile Include="patternfind.c" />
|
<Filter Include="Resource Files">
|
||||||
<ClCompile Include="rundll32.c" />
|
<UniqueIdentifier>{e54f7242-67a6-4c85-bf48-0f7a6095b613}</UniqueIdentifier>
|
||||||
<ClCompile Include="service.c" />
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
<ClCompile Include="helpers.c" />
|
</Filter>
|
||||||
<ClCompile Include="callbacks.c" />
|
<Filter Include="Source Files">
|
||||||
<ClCompile Include="patchwua.c" />
|
<UniqueIdentifier>{acf0da3d-e3e4-4fc8-aaf8-8d0558e6414c}</UniqueIdentifier>
|
||||||
<ClCompile Include="ntdllhelper.c" />
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="hooks.h" />
|
<ClInclude Include="ntdllhelper.h">
|
||||||
<ClInclude Include="iathook.h" />
|
<Filter>Header Files</Filter>
|
||||||
<ClInclude Include="logging.h" />
|
</ClInclude>
|
||||||
<ClInclude Include="patternfind.h" />
|
<ClInclude Include="patchwua.h">
|
||||||
<ClInclude Include="service.h" />
|
<Filter>Header Files</Filter>
|
||||||
<ClInclude Include="shellapihelper.h" />
|
</ClInclude>
|
||||||
<ClInclude Include="helpers.h" />
|
<ClInclude Include="patternfind.h">
|
||||||
<ClInclude Include="callbacks.h" />
|
<Filter>Header Files</Filter>
|
||||||
<ClInclude Include="patchwua.h" />
|
</ClInclude>
|
||||||
<ClInclude Include="ntdllhelper.h" />
|
<ClInclude Include="service.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="callbacks.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="helpers.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="hooks.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="iathook.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="tracing.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="wufuc.rch">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="wufuc.rc" />
|
<ClCompile Include="ntdllhelper.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="patchwua.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="patternfind.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="rundll32.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="service.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="callbacks.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dllmain.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="helpers.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="hooks.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="iathook.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="tracing.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="wufuc.def" />
|
<None Include="wufuc.def">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="wufuc.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Reference in New Issue
Block a user