32 Commits

Author SHA1 Message Date
zeffy
37c8bd8ae3 ok now 0.6.0.2 2017-06-06 16:12:00 -07:00
zeffy
a1a1fc0bd1 ??? logic 2017-06-06 15:46:16 -07:00
zeffy
0ce2cbfbc0 0.6.0.2 2017-06-06 15:21:10 -07:00
zeffy
be33bfb2d5 finish making msvc a static import 2017-06-06 14:12:03 -07:00
zeffy
549459ff58 Merge pull request #44 from navossoc/master
Remove MSVC run-time dependencies
2017-06-06 13:40:27 -07:00
Rafael Cossovan
ae8d48d365 Remove MSVC run-time dependencies (Microsoft Visual C++ 2017 Redistributable). 2017-06-06 15:52:07 -03:00
zeffy
a584e3a3a7 Update README.md 2017-06-05 19:51:12 -07:00
zeffy
07da645253 Update README.md 2017-06-05 18:21:53 -07:00
zeffy
642ed502d7 Update README.md 2017-06-05 18:11:07 -07:00
zeffy
fce0772996 fix comment spacing, variable names 2017-06-05 18:01:37 -07:00
zeffy
af062f47d7 0.6.0.1 2017-06-05 16:27:35 -07:00
zeffy
7f0784424f spaces > tabs 2017-06-05 15:50:18 -07:00
zeffy
b02ad7a9d6 minor fixes, build events 2017-06-05 15:30:45 -07:00
zeffy
9d90abc0de refactoring 2017-06-05 15:17:39 -07:00
zeffy
2f4355e616 refactoring 2017-06-05 14:33:03 -07:00
zeffy
f74f30e3a9 rename debug print method and split to ansi/unicode 2017-06-05 07:44:06 -07:00
zeffy
712ef4e38b Update README.md 2017-06-04 18:16:05 -07:00
zeffy
a28e098cee current year 2017-06-04 18:01:48 -07:00
zeffy
66c10c4067 Update README.md 2017-06-04 17:59:35 -07:00
zeffy
1a69d35642 Update README.md 2017-06-04 17:59:22 -07:00
zeffy
0094d19358 add text about debugview 2017-06-04 17:44:24 -07:00
zeffy
3a3e195c6b minor changes 2017-06-04 17:28:30 -07:00
zeffy
2ff1e01cc8 Update README.md 2017-06-04 15:34:42 -07:00
zeffy
dfc7f82036 Update README.md 2017-06-04 15:11:20 -07:00
zeffy
490bc062b4 Update wufuc.sln 2017-06-04 15:04:03 -07:00
zeffy
3ce7f39269 Update README.md 2017-06-04 15:03:40 -07:00
zeffy
500eddf349 Update version.rc 2017-06-04 14:57:10 -07:00
zeffy
49d32db491 Update README.md 2017-06-04 14:57:01 -07:00
zeffy
fd984db033 Update README.md 2017-06-04 14:43:07 -07:00
zeffy
d1df067812 Update repair_wuaueng.dll.bat 2017-06-04 14:35:34 -07:00
zeffy
6e67f6de80 Update install_wufuc.bat 2017-06-04 14:34:11 -07:00
zeffy
45a2b915f9 Update README.md, delete stray wufuc.xml 2017-06-04 13:46:09 -07:00
23 changed files with 596 additions and 478 deletions

View File

@@ -1,4 +1,4 @@
# wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![download count](https://img.shields.io/github/downloads/zeffy/kb4012218-19/total.svg)](https://github.com/zeffy/kb4012218-19/releases/latest) # wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![Downloads](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg) ![](https://img.shields.io/badge/downloads%20before%20v0.6-13k-brightgreen.svg)](../../releases)
Disables the "Unsupported Hardware" message in Windows Update, and allows you to continue installing updates on Windows 7 and 8.1 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors. Disables the "Unsupported Hardware" message in Windows Update, and allows you to continue installing updates on Windows 7 and 8.1 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
@@ -24,25 +24,35 @@ My patch takes advantage of this result caching behavior by setting the "hasn't
## How it works ## How it works
- On system boot the `wufuc` scheduled task runs under the `NT AUTHORITY\SYSTEM` user. - At system boot the wufuc scheduled task runs as the `NT AUTHORITY\SYSTEM` user.
- `wufuc` determines what service host process the Windows Update service (`wuauserv`) runs in, and injects itself into it. - `wufuc` determines what service host group process the Windows Update service runs in (typically `netsvcs`), and injects itself into it.
- Once injected, it applies a hook to `LoadLibraryEx` that automatically patches `wuaueng.dll` when it is loaded. - Once injected, it applies a hook to `LoadLibraryEx` that automatically patches `wuaueng.dll` when it is loaded.
- Any previously loaded `wuaueng.dll` is also patched. - Any previously loaded `wuaueng.dll` is also patched.
### Several improvements over my script-based approach: ### Several improvements over my xdelta3/batch script method:
- **No system files are modified!***
- Heuristic byte signature patching persists over new updates. - **No system files are modified!**
- Heuristic-based patching, which means it will usually keep working even after updates.
- C is best language. - C is best language.
- No external dependencies except for Microsoft Visual C++ 2015 Redistributable. - No external dependencies.
### How to install/uninstall? ### How to install/uninstall?
Just run move the `wufuc` folder to wherever you want and run `install_wufuc.bat` as administrator. Just download the [latest release](../../releases/latest), and extract the `wufuc` folder to a permanent location (like `C:\Program Files\wufuc`) and then run `install_wufuc.bat` as administrator.
To uninstall run `uninstall_wufuc.bat` as administrator. To uninstall run `uninstall_wufuc.bat` as administrator.
To temporarily disable the patch, just go to the Task Scheduler and disable the `wufuc.{ ... }` task, then restart your computer.
### How do I remove your old patch and use this instead? ### How do I remove your old patch and use this instead?
I've included a utility script called `repair_wuaueng.dll.bat` that will initiate an sfc scan and attempt to automatically revert any changes made to `wuaueng.dll`. I've included a utility script called `repair_wuaueng.dll.bat`. When you run it, it will initiate an `sfc` scan and revert any changes made to `wuaueng.dll`.
### How to see wufuc's debugging message output?
You will need to download [DebugView](https://technet.microsoft.com/en-us/sysinternals/debugview.aspx) to do this.
The best way to get a log of the entire life-cycle of wufuc is to do the following:
1. Disable wufuc by running `disable_wufuc.bat` as administrator.
2. Start `Dbgview.exe` as administrator and check `Capture -> Capture Global Win32`.
3. Enable wufuc by running `enable_wufuc.bat` as administrator.
4. Output will be shown in DebugView.

View File

@@ -1,5 +1,5 @@
@echo off @echo off
title wufuc installer - v0.6 title wufuc installer
:: Copyright (C) 2017 zeffy :: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify :: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title wufuc installer - v0.6
:: You should have received a copy of the GNU General Public License :: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>. :: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY. echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details. echo under certain conditions; see COPYING.txt for details.
@@ -47,6 +47,9 @@ goto :unsupported_os
set "WINDOWS_ARCHITECTURE=x64" set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0wufuc64.dll" set "wufuc_dll=%~dp0wufuc64.dll"
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i"
title wufuc installer - v%Version%
:check_ver :check_ver
wmic /output:stdout os get version | findstr "^6\.1\." >nul && ( wmic /output:stdout os get version | findstr "^6\.1\." >nul && (
set "WINDOWS_VER=6.1" set "WINDOWS_VER=6.1"
@@ -76,7 +79,7 @@ goto :die
for %%a in (%SUPPORTED_HOTFIXES%) do ( for %%a in (%SUPPORTED_HOTFIXES%) do (
wmic /output:stdout qfe get hotfixid | find "%%a" >nul && ( wmic /output:stdout qfe get hotfixid | find "%%a" >nul && (
set "INSTALLED_HOTFIX=%%a" set "INSTALLED_HOTFIX=%%a"
echo Detected installed supported update: %%a echo Detected supported installed update: %%a
goto :confirmation goto :confirmation
) )
) )
@@ -84,8 +87,15 @@ for %%a in (%SUPPORTED_HOTFIXES%) do (
echo. echo.
echo WARNING - Detected that no supported updates are installed! echo WARNING - Detected that no supported updates are installed!
echo. echo.
echo This can be a false warning, if you are certain that need wufuc then you echo This can be a false warning, sometimes it is caused by the WMI
echo can continue (there will be no side effects even if you don't need it) echo Win32_QuickFixEngineering class being broken. If you are certain
echo that you need wufuc, then you can continue ^(there should be no
echo side effects even if you don't need it^).
echo.
echo This warning could also mean that a new update came out and the
echo installer script's list of updates hasn't been updated yet. If
echo this is the case and you know which update it is, feel free to
echo create an issue. https://github.com/zeffy/wufuc/issues
set /p CONTINUE=Enter 'Y' if you still want to continue: set /p CONTINUE=Enter 'Y' if you still want to continue:
if /I not "%CONTINUE%"=="Y" goto :cancel if /I not "%CONTINUE%"=="Y" goto :cancel
@@ -101,19 +111,6 @@ set /p CONTINUE=Enter 'Y' if you want to install wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel if /I not "%CONTINUE%"=="Y" goto :cancel
echo. echo.
set "vcredist_path=%~dp0_Redist\vcredist_%WINDOWS_ARCHITECTURE%.exe"
if exist "%vcredist_path%" (
echo Installing Microsoft Visual C^+^+ 2017 Redistributable ^(%WINDOWS_ARCHITECTURE%^)...
"%vcredist_path%" /passive /norestart
goto :install
)
echo Couldn't locate and install Microsoft Visual C^+^+ 2017 Redistributable ^(%WINDOWS_ARCHITECTURE%^).
set /p CONTINUE=Enter 'Y' if you still want to continue:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
:install :install
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}" set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
schtasks /Create /XML "%~dp0wufuc.xml" /TN "%wufuc_task%" /F schtasks /Create /XML "%~dp0wufuc.xml" /TN "%wufuc_task%" /F
@@ -123,7 +120,9 @@ rundll32 "%wufuc_dll%",Rundll32Unload
schtasks /Run /TN "%wufuc_task%" schtasks /Run /TN "%wufuc_task%"
echo. echo.
echo Installed and started wufuc! echo Installed and started wufuc, you can now continue installing updates! :^)
echo.
echo To uninstall, run uninstall_wufuc.bat as administrator.
goto :die goto :die
:die :die
@@ -132,7 +131,6 @@ echo Press any key to exit...
pause >nul pause >nul
exit exit
:cancel :cancel
echo. echo.
echo Canceled by user, press any key to exit... echo Canceled by user, press any key to exit...

View File

@@ -1,5 +1,5 @@
@echo off @echo off
title wufuc uninstaller - v0.6 title wufuc uninstaller
:: Copyright (C) 2017 zeffy :: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify :: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title wufuc uninstaller - v0.6
:: You should have received a copy of the GNU General Public License :: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>. :: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY. echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details. echo under certain conditions; see COPYING.txt for details.
@@ -45,18 +45,20 @@ goto :die
set "WINDOWS_ARCHITECTURE=x64" set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0wufuc64.dll" set "wufuc_dll=%~dp0wufuc64.dll"
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%
: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
schtasks /Delete /TN "%wufuc_task%" /F schtasks /Delete /TN "%wufuc_task%" /F
echo. echo.
echo Unloaded and uninstalled wufuc! echo Unloaded and uninstalled wufuc. :^(
:die :die
echo. echo.

View File

@@ -0,0 +1,70 @@
@echo off
title wufuc utility - disable task
:: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify
:: it under the terms of the GNU General Public License as published by
:: the Free Software Foundation, either version 3 of the License, or
:: (at your option) any later version.
:: This program is distributed in the hope that it will be useful,
:: but WITHOUT ANY WARRANTY; without even the implied warranty of
:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
:: GNU General Public License for more details.
:: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
echo.
fltmc >nul 2>&1 || (
echo This batch script requires administrator privileges. Right-click on
echo %~nx0 and select "Run as administrator".
goto :die
)
if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
) else (
if /I "%PROCESSOR_ARCHITEW6432%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :confirmation
)
)
goto :die
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0..\wufuc64.dll"
:confirmation
set /p CONTINUE=Enter 'Y' if you want to disable wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
rundll32 "%wufuc_dll%",Rundll32Unload
schtasks /Change /TN "%wufuc_task%" /DISABLE
echo.
echo Disabled wufuc! You will still be able to check for updates until you restart.
:die
echo.
echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...
pause >nul
exit

View File

@@ -0,0 +1,51 @@
@echo off
title wufuc utility - enable task
:: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify
:: it under the terms of the GNU General Public License as published by
:: the Free Software Foundation, either version 3 of the License, or
:: (at your option) any later version.
:: This program is distributed in the hope that it will be useful,
:: but WITHOUT ANY WARRANTY; without even the implied warranty of
:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
:: GNU General Public License for more details.
:: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
echo.
fltmc >nul 2>&1 || (
echo This batch script requires administrator privileges. Right-click on
echo %~nx0 and select "Run as administrator".
goto :die
)
set /p CONTINUE=Enter 'Y' if you want to enable wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
schtasks /Change /TN "%wufuc_task%" /ENABLE
schtasks /Run /TN "%wufuc_task%"
echo.
echo Enabled and started wufuc!
:die
echo.
echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...
pause >nul
exit

View File

@@ -1,5 +1,5 @@
@echo off @echo off
title install wufuc (repair wuaueng.dll) - v0.6 title wufuc utility - repair wuaueng.dll
:: Copyright (C) 2017 zeffy :: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify :: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title install wufuc (repair wuaueng.dll) - v0.6
:: You should have received a copy of the GNU General Public License :: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>. :: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY. echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details. echo under certain conditions; see COPYING.txt for details.
@@ -27,7 +27,6 @@ fltmc >nul 2>&1 || (
goto :die goto :die
) )
:confirmation
echo You may want to use this script if you previously modified wuaueng.dll echo You may want to use this script if you previously modified wuaueng.dll
echo with "aio-wuaueng.dll-patch.bat" or by other means. echo with "aio-wuaueng.dll-patch.bat" or by other means.
echo. echo.

Binary file not shown.

View File

@@ -10,7 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitignore = .gitignore .gitignore = .gitignore
LICENSE = LICENSE LICENSE = LICENSE
README.md = README.md README.md = README.md
wufuc.xml = wufuc.xml
EndProjectSection EndProjectSection
EndProject EndProject
Global Global

BIN
wufuc.xml

Binary file not shown.

View File

@@ -10,152 +10,151 @@
#include "util.h" #include "util.h"
DWORD WINAPI NewThreadProc(LPVOID lpParam) { DWORD WINAPI NewThreadProc(LPVOID lpParam) {
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
TCHAR lpBinaryPathName[0x8000]; TCHAR lpBinaryPathName[0x8000];
QueryServiceBinaryPathName(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName)); get_svcpath(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName));
BOOL result = _tcsicmp(GetCommandLine(), lpBinaryPathName); BOOL result = _tcsicmp(GetCommandLine(), lpBinaryPathName);
CloseServiceHandle(hSCManager); CloseServiceHandle(hSCManager);
if (result) { if (result) {
return 0; return 0;
} }
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa); sa.nLength = sizeof(sa);
ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:PAI(A;;FA;;;BA)"), SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL); ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:PAI(A;;FA;;;BA)"), SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL);
sa.bInheritHandle = FALSE; sa.bInheritHandle = FALSE;
HANDLE hEvent = CreateEvent(&sa, FALSE, FALSE, _T("Global\\wufuc_UnloadEvent")); HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (!hEvent) { if (!hEvent) {
return 0; return 0;
} }
HANDLE lphThreads[0x1000]; DWORD dwProcessId = GetCurrentProcessId();
SIZE_T cb; DWORD dwThreadId = GetCurrentThreadId();
SuspendProcess(lphThreads, _countof(lphThreads), &cb); HANDLE lphThreads[0x1000];
SIZE_T cb;
HMODULE hm = GetModuleHandle(NULL); SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
DETOUR_IAT(hm, LoadLibraryExA);
DETOUR_IAT(hm, LoadLibraryExW);
DbgPrint("Applied LoadLibraryEx hooks."); HMODULE hm = GetModuleHandle(NULL);
DETOUR_IAT(hm, LoadLibraryExA);
DETOUR_IAT(hm, LoadLibraryExW);
HMODULE hwu = GetModuleHandle(_T("wuaueng.dll")); HMODULE hwu = GetModuleHandle(_T("wuaueng.dll"));
if (hwu) { if (hwu) {
PatchWUModule(hwu); PatchWUModule(hwu);
} }
ResumeAndCloseThreads(lphThreads, cb); ResumeAndCloseThreads(lphThreads, cb);
WaitForSingleObject(hEvent, INFINITE); WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
DbgPrint("Received wufuc_UnloadEvent, removing hooks."); _tdbgprintf(_T("Received wufuc_UnloadEvent, removing hooks."));
SuspendProcess(lphThreads, _countof(lphThreads), &cb); SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
RESTORE_IAT(hm, LoadLibraryExA); RESTORE_IAT(hm, LoadLibraryExA);
RESTORE_IAT(hm, LoadLibraryExW); RESTORE_IAT(hm, LoadLibraryExW);
ResumeAndCloseThreads(lphThreads, cb); ResumeAndCloseThreads(lphThreads, cb);
DbgPrint("Unloading library. Cya!"); _tdbgprintf(_T("Unloading library. Cya!"));
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0); CloseHandle(hEvent);
return 0; FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
return 0;
} }
BOOL IsWUModule(HMODULE hModule) { BOOL IsWUModule(HMODULE hModule) {
TCHAR lpBaseName[MAX_PATH + 1]; TCHAR lpBaseName[MAX_PATH + 1];
GetModuleBaseName(GetCurrentProcess(), hModule, lpBaseName, _countof(lpBaseName)); GetModuleBaseName(GetCurrentProcess(), hModule, lpBaseName, _countof(lpBaseName));
return !_tcsicmp(lpBaseName, _T("wuaueng.dll")); return !_tcsicmp(lpBaseName, _T("wuaueng.dll"));
} }
BOOL PatchWUModule(HMODULE hModule) { BOOL PatchWUModule(HMODULE hModule) {
if (!IsWindows7Or8Point1()) { if (!IsWindows7Or8Point1()) {
return FALSE; return FALSE;
} }
LPSTR lpszPattern; LPSTR lpszPattern;
SIZE_T n1, n2; SIZE_T n1, n2;
#ifdef _WIN64 #ifdef _WIN64
lpszPattern = lpszPattern =
"FFF3" // push rbx "FFF3" // push rbx
"4883EC??" // sub rsp,?? "4883EC??" // sub rsp,??
"33DB" // xor ebx,ebx "33DB" // xor ebx,ebx
"391D????????" // cmp dword ptr ds:[???????????],ebx "391D????????" // cmp dword ptr ds:[???????????],ebx
"7508" // jnz $+8 "7508" // jnz $+8
"8B05????????"; // mov eax,dword ptr ds:[???????????] "8B05????????"; // mov eax,dword ptr ds:[???????????]
n1 = 10; n1 = 10;
n2 = 18; n2 = 18;
#elif defined(_WIN32) #elif defined(_WIN32)
if (IsWindows8Point1()) { if (IsWindows8Point1()) {
lpszPattern = lpszPattern =
"8BFF" // mov edi,edi "8BFF" // mov edi,edi
"51" // push ecx "51" // push ecx
"833D????????00" // cmp dword ptr ds:[????????],0 "833D????????00" // cmp dword ptr ds:[????????],0
"7507" // jnz $+7 "7507" // jnz $+7
"A1????????"; // mov eax,dword ptr ds:[????????] "A1????????"; // mov eax,dword ptr ds:[????????]
n1 = 5; n1 = 5;
n2 = 13; n2 = 13;
} } else if (IsWindows7()) {
else if (IsWindows7()) { lpszPattern =
lpszPattern = "833D????????00" // cmp dword ptr ds:[????????],0
"833D????????00" // cmp dword ptr ds:[????????],0 "743E" // je $+3E
"743E" // je $+3E "E8????????" // call <wuaueng.IsCPUSupported>
"E8????????" // call <wuaueng.IsCPUSupported> "A3????????"; // mov dword ptr ds:[????????],eax
"A3????????"; // mov dword ptr ds:[????????],eax n1 = 2;
n1 = 2; n2 = 15;
n2 = 15; }
}
#else #else
return FALSE; return FALSE;
#endif #endif
MODULEINFO modinfo; MODULEINFO modinfo;
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO)); GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
SIZE_T offset; SIZE_T rva;
if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &offset)) { if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &rva)) {
return FALSE; return FALSE;
} }
DbgPrint("IsDeviceServiceable(void) matched at %p", (UINT_PTR)modinfo.lpBaseOfDll + offset); SIZE_T fpIsDeviceServiceable = (SIZE_T)modinfo.lpBaseOfDll + rva;
_tdbgprintf(_T("IsDeviceServiceable(void) matched at %p"), fpIsDeviceServiceable);
DWORD *lpdwResultIsNotCachedOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1); BOOL *lpbNotRunOnce = (BOOL *)(fpIsDeviceServiceable + n1 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n1));
BOOL *lpbResultIsNotCached = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1 + sizeof(DWORD) + *lpdwResultIsNotCachedOffset); if (*lpbNotRunOnce) {
if (*lpbResultIsNotCached) { *lpbNotRunOnce = FALSE;
*lpbResultIsNotCached = FALSE; _tdbgprintf(_T("Patched %p=%d"), lpbNotRunOnce, *lpbNotRunOnce);
DbgPrint("Patched %p=%d", lpbResultIsNotCached, *lpbResultIsNotCached); }
}
DWORD *lpdwCachedResultOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2); BOOL *lpbCachedResult = (BOOL *)(fpIsDeviceServiceable + n2 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n2));
BOOL *lpbCachedResult = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2 + sizeof(DWORD) + *lpdwCachedResultOffset); if (!*lpbCachedResult) {
if (!*lpbCachedResult) { *lpbCachedResult = TRUE;
*lpbCachedResult = TRUE; _tdbgprintf(_T("Patched %p=%d"), lpbCachedResult, *lpbCachedResult);
DbgPrint("Patched %p=%d", lpbCachedResult, *lpbCachedResult); }
} return TRUE;
return TRUE;
} }
HMODULE WINAPI _LoadLibraryExA( HMODULE WINAPI _LoadLibraryExA(
_In_ LPCSTR lpFileName, _In_ LPCSTR lpFileName,
_Reserved_ HANDLE hFile, _Reserved_ HANDLE hFile,
_In_ DWORD dwFlags _In_ DWORD dwFlags
) { ) {
HMODULE result = LoadLibraryExA(lpFileName, hFile, dwFlags); HMODULE result = LoadLibraryExA(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) { if (IsWUModule(result)) {
PatchWUModule(result); PatchWUModule(result);
} }
return result; return result;
} }
HMODULE WINAPI _LoadLibraryExW( HMODULE WINAPI _LoadLibraryExW(
_In_ LPCWSTR lpFileName, _In_ LPCWSTR lpFileName,
_Reserved_ HANDLE hFile, _Reserved_ HANDLE hFile,
_In_ DWORD dwFlags _In_ DWORD dwFlags
) { ) {
HMODULE result = LoadLibraryExW(lpFileName, hFile, dwFlags); HMODULE result = LoadLibraryExW(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) { if (IsWUModule(result)) {
PatchWUModule(result); PatchWUModule(result);
} }
return result; return result;
}; };

View File

@@ -5,13 +5,13 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam);
BOOL PatchWUModule(HMODULE hModule); BOOL PatchWUModule(HMODULE hModule);
HMODULE WINAPI _LoadLibraryExA( HMODULE WINAPI _LoadLibraryExA(
_In_ LPCSTR lpFileName, _In_ LPCSTR lpFileName,
_Reserved_ HANDLE hFile, _Reserved_ HANDLE hFile,
_In_ DWORD dwFlags _In_ DWORD dwFlags
); );
HMODULE WINAPI _LoadLibraryExW( HMODULE WINAPI _LoadLibraryExW(
_In_ LPCWSTR lpFileName, _In_ LPCWSTR lpFileName,
_Reserved_ HANDLE hFile, _Reserved_ HANDLE hFile,
_In_ DWORD dwFlags _In_ DWORD dwFlags
); );

View File

@@ -2,18 +2,18 @@
#include "core.h" #include "core.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) { switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
{ {
DisableThreadLibraryCalls(hModule); DisableThreadLibraryCalls(hModule);
HANDLE hThread = CreateThread(NULL, 0, NewThreadProc, NULL, 0, NULL); HANDLE hThread = CreateThread(NULL, 0, NewThreadProc, NULL, 0, NULL);
CloseHandle(hThread); CloseHandle(hThread);
break; break;
} }
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
break; break;
default: default:
break; break;
} }
return TRUE; return TRUE;
} }

View File

@@ -6,36 +6,36 @@
#include "util.h" #include "util.h"
void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent")); HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (hEvent) { if (hEvent) {
CloseHandle(hEvent); CloseHandle(hEvent);
return; return;
} }
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
TCHAR lpGroupName[256]; TCHAR lpGroupName[256];
DWORD dwProcessId; DWORD dwProcessId;
BOOL result = QueryServiceProcessId(hSCManager, _T("wuauserv"), &dwProcessId); BOOL result = get_svcpid(hSCManager, _T("wuauserv"), &dwProcessId);
if (!result && GetServiceGroupName(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) { if (!result && get_svcgname(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) {
result = FindServiceGroupProcessId(hSCManager, lpGroupName, &dwProcessId); result = get_svcgpid(hSCManager, lpGroupName, &dwProcessId);
} }
CloseServiceHandle(hSCManager); CloseServiceHandle(hSCManager);
if (!result) { if (!result) {
return; return;
} }
TCHAR lpLibFileName[MAX_PATH + 1]; TCHAR lpLibFileName[MAX_PATH + 1];
GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName)); GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName));
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
InjectLibrary(hProcess, lpLibFileName, _countof(lpLibFileName)); InjectLibrary(hProcess, lpLibFileName, _countof(lpLibFileName));
CloseHandle(hProcess); 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"));
if (hEvent) { if (hEvent) {
DbgPrint("Setting wufuc_UnloadEvent..."); _tdbgprintf(_T("Setting wufuc_UnloadEvent..."));
SetEvent(hEvent); SetEvent(hEvent);
CloseHandle(hEvent); CloseHandle(hEvent);
} }
} }

View File

@@ -1,139 +0,0 @@
#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>
#include <tchar.h>
#include "util.h"
#include "process.h"
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
LPVOID *lpAddress = FindIAT(hModule, lpFuncName);
if (!lpAddress || *lpAddress == lpNewAddress) {
return;
}
DWORD flOldProtect;
DWORD flNewProtect = PAGE_READWRITE;
VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect);
if (lpOldAddress) {
*lpOldAddress = *lpAddress;
}
DbgPrint("%S %p => %p", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName) {
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((LPBYTE)dos + dos->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR desc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)dos + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (PIMAGE_IMPORT_DESCRIPTOR iid = desc; iid->Name != 0; iid++) {
for (int i = 0; *(i + (LPVOID*)(iid->FirstThunk + (SIZE_T)hModule)) != NULL; i++) {
LPSTR name = (LPSTR)(*(i + (SIZE_T*)(iid->OriginalFirstThunk + (SIZE_T)hModule)) + (SIZE_T)hModule + 2);
const uintptr_t n = (uintptr_t)name;
if (!(n & (sizeof(n) == 4 ? 0x80000000 : 0x8000000000000000)) && !_stricmp(lpFuncName, name)) {
return i + (LPVOID*)(iid->FirstThunk + (SIZE_T)hModule);
}
}
}
return NULL;
}
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset) {
SIZE_T nPatternLength = strlen(lpszPattern);
SIZE_T nMaskLength = nPatternLength / 2;
if (nMaskLength > nNumberOfBytes || nPatternLength % 2) {
return FALSE;
}
LPBYTE lpPattern = malloc(nMaskLength * sizeof(BYTE));
BOOL *lpbMask = malloc(nMaskLength * sizeof(BOOL));
LPSTR p = lpszPattern;
BOOL valid = TRUE;
for (SIZE_T i = 0; i < nMaskLength; i++) {
if (lpbMask[i] = strncmp(p, "??", 2)) {
if (sscanf_s(p, "%2hhx", &lpPattern[i]) != 1) {
valid = FALSE;
break;
}
}
p += 2;
}
BOOL result = FALSE;
if (valid) {
for (SIZE_T i = nStart; i < nNumberOfBytes - nStart - (nMaskLength - 1); i++) {
BOOL found = TRUE;
for (SIZE_T j = 0; j < nMaskLength; j++) {
if (lpbMask[j] && lpBytes[i + j] != lpPattern[j]) {
found = FALSE;
break;
}
}
if (found) {
*lpOffset = i;
result = TRUE;
break;
}
}
}
free(lpPattern);
free(lpbMask);
return result;
}
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb) {
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, cb, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, cb, NULL)) {
return FALSE;
}
DWORD dwProcessId = GetProcessId(hProcess);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
MODULEENTRY32 me;
me.dwSize = sizeof(me);
Module32First(hSnap, &me);
do {
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
break;
}
} while (Module32Next(hSnap, &me));
CloseHandle(hSnap);
DbgPrint("Injecting %s into process %d", lpLibFileName, dwProcessId);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
CloseHandle(hThread);
return TRUE;
}
VOID SuspendProcess(HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te;
te.dwSize = sizeof(te);
Thread32First(hSnap, &te);
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
SIZE_T count = 0;
do {
if (te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId) {
continue;
}
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while (count < dwSize && Thread32Next(hSnap, &te));
CloseHandle(hSnap);
*lpcb = count;
DbgPrint("Suspended other threads.");
}
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
for (SIZE_T i = 0; i < cb; i++) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
DbgPrint("Resumed threads.");
}

View File

@@ -1,20 +0,0 @@
#pragma once
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
#define DETOUR_IAT(x, y) \
LPVOID __LPORIGINAL##y; \
DetourIAT(x, #y, &__LPORIGINAL##y, &_##y)
#define RESTORE_IAT(x, y) \
DetourIAT(x, #y, NULL, __LPORIGINAL##y)
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset);
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb);
VOID SuspendProcess(HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);

View File

@@ -1,15 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by version.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -2,96 +2,90 @@
#include <tchar.h> #include <tchar.h>
#include "util.h" #include "util.h"
#include "service.h" #include "service.h"
#include "shellapihelper.h"
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) { BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG); HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
if (!hService) { if (!hService) {
return FALSE; return FALSE;
} }
DWORD cbBytesNeeded; DWORD cbBytesNeeded;
QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded); QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded);
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded); LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded); BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded);
int a = GetLastError(); CloseServiceHandle(hService);
CloseServiceHandle(hService); if (result) {
if (result) { _tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName);
_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName); }
} free(sc);
LocalFree(sc); return result;
return result;
} }
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) { BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS); SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
if (!hService) { if (!hService) {
return FALSE; return FALSE;
} }
SERVICE_STATUS_PROCESS lpBuffer; SERVICE_STATUS_PROCESS lpBuffer;
DWORD cbBytesNeeded; DWORD cbBytesNeeded;
BOOL result = FALSE; BOOL result = FALSE;
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded) && lpBuffer.dwProcessId) { if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded) && lpBuffer.dwProcessId) {
*lpdwProcessId = lpBuffer.dwProcessId; *lpdwProcessId = lpBuffer.dwProcessId;
result = TRUE; result = TRUE;
DbgPrint("Found %s pid %d", lpServiceName, *lpdwProcessId); }
} CloseServiceHandle(hService);
CloseServiceHandle(hService); return result;
return result;
} }
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) { BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
TCHAR lpBinaryPathName[0x8000]; TCHAR lpBinaryPathName[0x8000];
if (!QueryServiceBinaryPathName(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) { if (!get_svcpath(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
return FALSE; return FALSE;
} }
int numArgs; int numArgs;
LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs); LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs);
if (numArgs < 3) { if (numArgs < 3) {
return FALSE; return FALSE;
} }
TCHAR fname[_MAX_FNAME]; TCHAR fname[_MAX_FNAME];
_tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0); _tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0);
BOOL result = FALSE; BOOL result = FALSE;
if (!_tcsicmp(fname, _T("svchost"))) { if (!_tcsicmp(fname, _T("svchost"))) {
LPWSTR *p = argv; LPWSTR *p = argv;
for (int i = 0; i + 1 < numArgs; i++) { for (int i = 1; i < numArgs; i++) {
if (!_tcsicmp(*(p++), _T("-k"))) { if (!_tcsicmp(*(p++), _T("-k"))) {
_tcscpy_s(lpGroupName, dwSize, *p); _tcscpy_s(lpGroupName, dwSize, *p);
result = TRUE; result = TRUE;
DbgPrint("Found %s svc group: %s", lpServiceName, lpGroupName); break;
break; }
} }
} }
} return result;
return result;
} }
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) { BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
DWORD uBytes = 0x100000; DWORD uBytes = 0x100000;
LPBYTE pvData = malloc(uBytes); LPBYTE pvData = malloc(uBytes);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes); RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
LPTSTR ptr = (LPTSTR)pvData; BOOL result = FALSE;
for (LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1) {
BOOL result = FALSE; DWORD dwProcessId;
while (*ptr) { TCHAR group[256];
DWORD dwProcessId; if (get_svcpid(hSCManager, p, &dwProcessId)) {
if (QueryServiceProcessId(hSCManager, ptr, &dwProcessId)) { get_svcgname(hSCManager, p, group, _countof(group));
TCHAR group[256]; result = !_tcsicmp(group, lpServiceGroupName);
GetServiceGroupName(hSCManager, ptr, group, _countof(group)); }
result = !_tcsicmp(group, lpServiceGroupName); if (result) {
} *lpdwProcessId = dwProcessId;
if (result) { break;
DbgPrint("Found %s pid %d", lpServiceGroupName, dwProcessId); }
*lpdwProcessId = dwProcessId; }
break; free(pvData);
} return result;
ptr += _tcslen(ptr) + 1;
}
LocalFree(pvData);
return result;
} }

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize); BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId); BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize); BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId); BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);

7
wufuc/shellapihelper.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#ifdef UNICODE
#define CommandLineToArgv CommandLineToArgvW
#else
#define CommandLineToArgv CommandLineToArgvA
#endif // !UNICODE

View File

@@ -1,27 +1,164 @@
#include <Windows.h> #include <Windows.h>
#include <stdio.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <TlHelp32.h>
#include <tchar.h> #include <tchar.h>
#include "util.h" #include "util.h"
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
LPVOID *lpAddress = FindIAT(hModule, lpFuncName);
if (!lpAddress || *lpAddress == lpNewAddress) {
return;
}
DWORD flOldProtect;
DWORD flNewProtect = PAGE_READWRITE;
VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect);
if (lpOldAddress) {
*lpOldAddress = *lpAddress;
}
_dbgprintf("%s %p => %p", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
SIZE_T hm = (SIZE_T)hModule;
for (PIMAGE_IMPORT_DESCRIPTOR iid = (PIMAGE_IMPORT_DESCRIPTOR)(hm + ((PIMAGE_NT_HEADERS)(hm + ((PIMAGE_DOS_HEADER)hm)->e_lfanew))
->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); iid->Name; iid++) {
LPVOID *p;
for (SIZE_T i = 0; *(p = i + (LPVOID *)(hm + iid->FirstThunk)); i++) {
LPSTR fn = (LPSTR)(hm + *(i + (SIZE_T *)(hm + iid->OriginalFirstThunk)) + 2);
if (!((uintptr_t)fn & IMAGE_ORDINAL_FLAG) && !_stricmp(lpFunctionName, fn)) {
return p;
}
}
}
return NULL;
}
BOOL FindPattern(LPCBYTE pvData, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset) {
SIZE_T length = strlen(lpszPattern);
SIZE_T nBytes;
if (length % 2 || (nBytes = length / 2) > nNumberOfBytes) {
return FALSE;
}
LPBYTE lpBytes = malloc(nBytes * sizeof(BYTE));
BOOL *lpbwc = malloc(nBytes * sizeof(BOOL));
LPSTR p = lpszPattern;
BOOL valid = TRUE;
for (SIZE_T i = 0; i < nBytes; i++) {
if ((lpbwc[i] = strncmp(p, "??", 2)) && sscanf_s(p, "%2hhx", &lpBytes[i]) != 1) {
valid = FALSE;
break;
}
p += 2;
}
BOOL result = FALSE;
if (valid) {
for (SIZE_T i = nStart; i < nNumberOfBytes - nStart - (nBytes - 1); i++) {
BOOL found = TRUE;
for (SIZE_T j = 0; j < nBytes; j++) {
if (lpbwc[j] && pvData[i + j] != lpBytes[j]) {
found = FALSE;
break;
}
}
if (found) {
*lpOffset = i;
result = TRUE;
break;
}
}
}
free(lpBytes);
free(lpbwc);
return result;
}
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb) {
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, cb, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, cb, NULL)) {
return FALSE;
}
DWORD dwProcessId = GetProcessId(hProcess);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
MODULEENTRY32 me;
me.dwSize = sizeof(me);
Module32First(hSnap, &me);
do {
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
break;
}
} while (Module32Next(hSnap, &me));
CloseHandle(hSnap);
_tdbgprintf(_T("Injecting %s into process %d"), lpLibFileName, dwProcessId);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
CloseHandle(hThread);
return TRUE;
}
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te;
te.dwSize = sizeof(te);
Thread32First(hSnap, &te);
SIZE_T count = 0;
do {
if (te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId) {
continue;
}
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while (count < dwSize && Thread32Next(hSnap, &te));
CloseHandle(hSnap);
*lpcb = count;
_tdbgprintf(_T("Suspended other threads."));
}
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
for (SIZE_T i = 0; i < cb; i++) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
_tdbgprintf(_T("Resumed threads."));
}
BOOL IsWindows7Or8Point1(void) { BOOL IsWindows7Or8Point1(void) {
return IsWindows7() || IsWindows8Point1(); return IsWindows7() || IsWindows8Point1();
} }
BOOL IsWindows7(void) { BOOL IsWindows7(void) {
return IsWindows7OrGreater() && !IsWindows8OrGreater(); return IsWindows7OrGreater() && !IsWindows8OrGreater();
} }
BOOL IsWindows8Point1(void) { BOOL IsWindows8Point1(void) {
return IsWindows8Point1OrGreater() && !IsWindows10OrGreater(); return IsWindows8Point1OrGreater() && !IsWindows10OrGreater();
} }
//#ifdef _DEBUG VOID _wdbgprintf(LPCWSTR format, ...) {
VOID _DbgPrint(LPCTSTR format, ...) { WCHAR buffer[0x1000];
TCHAR buffer[0x1000]; va_list argptr;
va_list argptr; va_start(argptr, format);
va_start(argptr, format); vswprintf_s(buffer, _countof(buffer), format, argptr);
_vstprintf_s(buffer, _countof(buffer), format, argptr); va_end(argptr);
va_end(argptr); OutputDebugStringW(buffer);
OutputDebugString(buffer); }
VOID _dbgprintf(LPCSTR format, ...) {
CHAR buffer[0x1000];
va_list argptr;
va_start(argptr, format);
vsprintf_s(buffer, _countof(buffer), format, argptr);
va_end(argptr);
OutputDebugStringA(buffer);
} }
//#endif

View File

@@ -3,22 +3,39 @@
EXTERN_C IMAGE_DOS_HEADER __ImageBase; EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
#define DETOUR_IAT(x, y) \
LPVOID __LPORIGINAL##y; \
DetourIAT(x, #y, &__LPORIGINAL##y, &_##y)
#define RESTORE_IAT(x, y) \
DetourIAT(x, #y, NULL, __LPORIGINAL##y)
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset);
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb);
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);
BOOL IsWindows7Or8Point1(void); BOOL IsWindows7Or8Point1(void);
BOOL IsWindows7(void); BOOL IsWindows7(void);
BOOL IsWindows8Point1(void); BOOL IsWindows8Point1(void);
VOID _wdbgprintf(LPCWSTR format, ...);
VOID _dbgprintf(LPCSTR format, ...);
//#ifdef _DEBUG //#ifdef _DEBUG
VOID _DbgPrint(LPCTSTR format, ...);
#define DbgPrint(format, ...) \
_DbgPrint(_T(__FUNCTION__) _T(": ") _T(format), ##__VA_ARGS__)
//#else
//#define DbgPrint(format, ...)
//#endif
#ifdef UNICODE #ifdef UNICODE
#define CommandLineToArgv CommandLineToArgvW #define _tdbgprintf _wdbgprintf
#else #else
#define CommandLineToArgv CommandLineToArgvA #define _tdbgprintf _dbgprintf
#endif // !UNICODE #endif // !UNICODE
//#else
//#define _tdbgprintf(format, ...)
//#endif // !_DEBUG

Binary file not shown.

View File

@@ -105,6 +105,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -119,6 +120,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -135,6 +137,7 @@
<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>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -144,6 +147,9 @@
<GenerateDebugInformation>false</GenerateDebugInformation> <GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)install\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
@@ -154,6 +160,7 @@
<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>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@@ -163,12 +170,14 @@
<GenerateDebugInformation>false</GenerateDebugInformation> <GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)install\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="core.c" /> <ClCompile Include="core.c" />
<ClCompile Include="dllmain.c" /> <ClCompile Include="dllmain.c" />
<ClCompile Include="entrypoint.c" /> <ClCompile Include="entrypoint.c" />
<ClCompile Include="process.c" />
<ClCompile Include="service.c" /> <ClCompile Include="service.c" />
<ClCompile Include="util.c" /> <ClCompile Include="util.c" />
</ItemGroup> </ItemGroup>
@@ -177,8 +186,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="core.h" /> <ClInclude Include="core.h" />
<ClInclude Include="process.h" />
<ClInclude Include="service.h" /> <ClInclude Include="service.h" />
<ClInclude Include="shellapihelper.h" />
<ClInclude Include="util.h" /> <ClInclude Include="util.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>