Compare commits
56 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2c31ea2fe4 | ||
![]() |
cda46fbc9f | ||
![]() |
c4a78a3e24 | ||
![]() |
3d0b322f1e | ||
![]() |
2be1785509 | ||
![]() |
c837bfec2f | ||
![]() |
4ad3642db6 | ||
![]() |
0b86b8e9ab | ||
![]() |
4b85cb18a6 | ||
![]() |
9badc6257e | ||
![]() |
7d30ebd048 | ||
![]() |
196f4465a9 | ||
![]() |
1d9b47e602 | ||
![]() |
ce7e6dd166 | ||
![]() |
080242cec9 | ||
![]() |
b7cff16081 | ||
![]() |
7e42fc54f3 | ||
![]() |
c8538b8ec3 | ||
![]() |
309981829e | ||
![]() |
8a5ef20488 | ||
![]() |
0f41968610 | ||
![]() |
c7a1e606ef | ||
![]() |
7d6baf8aac | ||
![]() |
50182997f2 | ||
![]() |
37c8bd8ae3 | ||
![]() |
a1a1fc0bd1 | ||
![]() |
0ce2cbfbc0 | ||
![]() |
be33bfb2d5 | ||
![]() |
549459ff58 | ||
![]() |
ae8d48d365 | ||
![]() |
a584e3a3a7 | ||
![]() |
07da645253 | ||
![]() |
642ed502d7 | ||
![]() |
fce0772996 | ||
![]() |
af062f47d7 | ||
![]() |
7f0784424f | ||
![]() |
b02ad7a9d6 | ||
![]() |
9d90abc0de | ||
![]() |
2f4355e616 | ||
![]() |
f74f30e3a9 | ||
![]() |
712ef4e38b | ||
![]() |
a28e098cee | ||
![]() |
66c10c4067 | ||
![]() |
1a69d35642 | ||
![]() |
0094d19358 | ||
![]() |
3a3e195c6b | ||
![]() |
2ff1e01cc8 | ||
![]() |
dfc7f82036 | ||
![]() |
490bc062b4 | ||
![]() |
3ce7f39269 | ||
![]() |
500eddf349 | ||
![]() |
49d32db491 | ||
![]() |
fd984db033 | ||
![]() |
d1df067812 | ||
![]() |
6e67f6de80 | ||
![]() |
45a2b915f9 |
46
README.md
46
README.md
@@ -1,7 +1,13 @@
|
|||||||
# wufuc [](../../tree/old-kb4012218-19) [](https://github.com/zeffy/kb4012218-19/releases/latest)
|
# wufuc [](../../tree/old-kb4012218-19) [](https://ci.appveyor.com/project/zeffy/wufuc)
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
## Downloads [](../../releases)
|
||||||
|
|
||||||
|
### You can get the latest stable version [here](../../releases/latest)!
|
||||||
|
|
||||||
|
If you are feeling brave, you can try the latest unstable builds [here](https://ci.appveyor.com/project/zeffy/wufuc). **Use these at your own risk!**
|
||||||
|
|
||||||
## Preface
|
## Preface
|
||||||
|
|
||||||
The changelog for Windows updates KB4012218 and KB4012219 included the following:
|
The changelog for Windows updates KB4012218 and KB4012219 included the following:
|
||||||
@@ -24,25 +30,45 @@ 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 to update when a new version comes out?
|
||||||
|
|
||||||
|
Unless otherwise noted, you should only have to:
|
||||||
|
|
||||||
|
- Run `disable_wufuc.bat` as administrator.
|
||||||
|
- Copy the new files into the install folder, overwriting the old ones.
|
||||||
|
- Run the new `install_wufuc.bat` as administrator.
|
||||||
|
|
||||||
|
If you run into problems, try doing a full uninstall/reinstall.
|
||||||
|
|
||||||
### 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.
|
||||||
|
28
appveyor.yml
Normal file
28
appveyor.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
version: 0.6.1.{build}
|
||||||
|
skip_commits:
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
image: Visual Studio 2017
|
||||||
|
configuration: Release
|
||||||
|
platform:
|
||||||
|
- x86
|
||||||
|
- x64
|
||||||
|
build:
|
||||||
|
verbosity: minimal
|
||||||
|
after_build:
|
||||||
|
- cmd: >-
|
||||||
|
|
||||||
|
set "ZIP_NAME=..\%APPVEYOR_PROJECT_NAME%_v%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%_%PLATFORM%.zip"
|
||||||
|
|
||||||
|
cd "%APPVEYOR_BUILD_FOLDER%\install"
|
||||||
|
|
||||||
|
unix2dos "COPYING.txt"
|
||||||
|
|
||||||
|
for /R %%G in (*.bat) do unix2dos "%%G"
|
||||||
|
|
||||||
|
7z a "%ZIP_NAME%" "..\install"
|
||||||
|
|
||||||
|
7z rn "%ZIP_NAME%" "install" "wufuc"
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: '*.zip'
|
@@ -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.
|
||||||
@@ -36,27 +36,34 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
|
|||||||
goto :is_x64
|
goto :is_x64
|
||||||
)
|
)
|
||||||
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
|
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
|
||||||
set "WINDOWS_ARCHITECTURE=x86"
|
goto :is_x86
|
||||||
set "wufuc_dll=%~dp0wufuc32.dll"
|
|
||||||
goto :check_ver
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
goto :unsupported_os
|
goto :unsupported_os
|
||||||
|
|
||||||
|
:is_x86
|
||||||
|
set "WINDOWS_ARCHITECTURE=x86"
|
||||||
|
set "wufuc_dll=%~dp0wufuc32.dll"
|
||||||
|
goto :get_ver
|
||||||
|
|
||||||
:is_x64
|
:is_x64
|
||||||
set "WINDOWS_ARCHITECTURE=x64"
|
set "WINDOWS_ARCHITECTURE=x64"
|
||||||
set "wufuc_dll=%~dp0wufuc64.dll"
|
set "wufuc_dll=%~dp0wufuc64.dll"
|
||||||
|
|
||||||
|
:get_ver
|
||||||
|
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"
|
||||||
set "SUPPORTED_HOTFIXES=KB4019265 KB4019264 KB4015552 KB4015549 KB4015546 KB4012218"
|
set "SUPPORTED_HOTFIXES=KB4022722 KB4022719 KB4019265 KB4019264 KB4015552 KB4015549 KB4015546 KB4012218"
|
||||||
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
|
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
|
||||||
goto :check_hotfix
|
goto :check_hotfix
|
||||||
)
|
)
|
||||||
wmic /output:stdout os get version | findstr "^6\.3\." >nul && (
|
wmic /output:stdout os get version | findstr "^6\.3\." >nul && (
|
||||||
set "WINDOWS_VER=8.1"
|
set "WINDOWS_VER=8.1"
|
||||||
set "SUPPORTED_HOTFIXES=KB4019217 KB4019215 KB4015553 KB4015550 KB4015547 KB4012219"
|
set "SUPPORTED_HOTFIXES=KB4022726 KB4022717 KB4019217 KB4019215 KB4015553 KB4015550 KB4015547 KB4012219"
|
||||||
echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE%
|
echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE%
|
||||||
goto :check_hotfix
|
goto :check_hotfix
|
||||||
)
|
)
|
||||||
@@ -76,19 +83,21 @@ 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
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
wmic /output:stdout qfe get /value 2>&1 | find "No Instance(s) Available" >nul && (
|
||||||
|
echo WARNING - wmic qfe is broken, can't check installed updates...
|
||||||
|
goto :confirmation
|
||||||
|
)
|
||||||
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 warning could also mean that a new update came out and the
|
||||||
echo can continue (there will be no side effects even if you don't need it)
|
echo wufuc installer script's list of updates hasn't been updated yet.
|
||||||
|
echo If this is definitely the case and you know which update it is,
|
||||||
set /p CONTINUE=Enter 'Y' if you still want to continue:
|
echo feel free to create an issue. https://github.com/zeffy/wufuc/issues
|
||||||
if /I not "%CONTINUE%"=="Y" goto :cancel
|
|
||||||
|
|
||||||
:confirmation
|
:confirmation
|
||||||
echo.
|
echo.
|
||||||
@@ -96,26 +105,15 @@ echo wufuc disables the "Unsupported Hardware" message in Windows Update,
|
|||||||
echo and allows you to continue installing updates on Windows 7 and 8.1
|
echo and allows you to continue installing updates on Windows 7 and 8.1
|
||||||
echo systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
|
echo systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
|
||||||
echo.
|
echo.
|
||||||
|
echo Please be absolutely sure you really need wufuc before continuing.
|
||||||
set /p CONTINUE=Enter 'Y' if you want to install wufuc:
|
|
||||||
if /I not "%CONTINUE%"=="Y" goto :cancel
|
|
||||||
echo.
|
echo.
|
||||||
|
set /p CONTINUE=Enter 'Y' if you want to install wufuc:
|
||||||
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
|
if /I not "%CONTINUE%"=="Y" goto :cancel
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
:install
|
:install
|
||||||
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
||||||
|
net start Schedule
|
||||||
schtasks /Create /XML "%~dp0wufuc.xml" /TN "%wufuc_task%" /F
|
schtasks /Create /XML "%~dp0wufuc.xml" /TN "%wufuc_task%" /F
|
||||||
schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\system32\rundll32.exe' """%wufuc_dll%""",Rundll32Entry"
|
schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\system32\rundll32.exe' """%wufuc_dll%""",Rundll32Entry"
|
||||||
schtasks /Change /TN "%wufuc_task%" /ENABLE
|
schtasks /Change /TN "%wufuc_task%" /ENABLE
|
||||||
@@ -123,7 +121,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 +132,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...
|
||||||
|
@@ -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.
|
||||||
@@ -34,29 +34,36 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
|
|||||||
goto :is_x64
|
goto :is_x64
|
||||||
)
|
)
|
||||||
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
|
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
|
||||||
set "WINDOWS_ARCHITECTURE=x86"
|
goto :is_x86
|
||||||
set "wufuc_dll=%~dp0wufuc32.dll"
|
|
||||||
goto :confirmation
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
goto :die
|
goto :die
|
||||||
|
|
||||||
|
:is_x86
|
||||||
|
set "WINDOWS_ARCHITECTURE=x86"
|
||||||
|
set "wufuc_dll=%~dp0wufuc32.dll"
|
||||||
|
goto :get_ver
|
||||||
|
|
||||||
:is_x64
|
:is_x64
|
||||||
set "WINDOWS_ARCHITECTURE=x64"
|
set "WINDOWS_ARCHITECTURE=x64"
|
||||||
set "wufuc_dll=%~dp0wufuc64.dll"
|
set "wufuc_dll=%~dp0wufuc64.dll"
|
||||||
|
|
||||||
|
:get_ver
|
||||||
|
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
|
||||||
|
net start Schedule
|
||||||
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.
|
||||||
|
61
install/utility scripts/disable_wufuc.bat
Normal file
61
install/utility scripts/disable_wufuc.bat
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
@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" (
|
||||||
|
goto :is_x86
|
||||||
|
)
|
||||||
|
)
|
||||||
|
goto :die
|
||||||
|
|
||||||
|
:is_x86
|
||||||
|
set "wufuc_dll=%~dp0..\wufuc32.dll"
|
||||||
|
goto :disable
|
||||||
|
|
||||||
|
:is_x64
|
||||||
|
set "wufuc_dll=%~dp0..\wufuc64.dll"
|
||||||
|
|
||||||
|
:disable
|
||||||
|
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
||||||
|
rundll32 "%wufuc_dll%",Rundll32Unload
|
||||||
|
net start Schedule
|
||||||
|
schtasks /Change /TN "%wufuc_task%" /DISABLE
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Disabled wufuc! You will still be able to check for updates until you restart.
|
||||||
|
|
||||||
|
:die
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
exit
|
41
install/utility scripts/enable_wufuc.bat
Normal file
41
install/utility scripts/enable_wufuc.bat
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
@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 "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
|
||||||
|
net start Schedule
|
||||||
|
schtasks /Change /TN "%wufuc_task%" /ENABLE
|
||||||
|
schtasks /Run /TN "%wufuc_task%"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Enabled and started wufuc!
|
||||||
|
|
||||||
|
:die
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
exit
|
@@ -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.
@@ -8,27 +8,23 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C2147FF-2B83-479B-813E-5ACB86F43042}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C2147FF-2B83-479B-813E-5ACB86F43042}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
|
appveyor.yml = appveyor.yml
|
||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
wufuc.xml = wufuc.xml
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.ActiveCfg = Debug|x64
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.Build.0 = Debug|x64
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.Build.0 = Debug|x64
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.ActiveCfg = Debug|Win32
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.Build.0 = Debug|Win32
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.Build.0 = Debug|Win32
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.ActiveCfg = Release|x64
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.ActiveCfg = Release|x64
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.Build.0 = Release|x64
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.Build.0 = Release|x64
|
||||||
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x86.ActiveCfg = Release|Win32
|
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
249
wufuc/core.c
249
wufuc/core.c
@@ -1,161 +1,162 @@
|
|||||||
|
#include <stdint.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <aclapi.h>
|
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
#include "core.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "patternfind.h"
|
||||||
|
#include "core.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"));
|
TCHAR lpServiceDll[MAX_PATH + 1];
|
||||||
if (hwu) {
|
get_svcdll(_T("wuauserv"), lpServiceDll, _countof(lpServiceDll));
|
||||||
PatchWUModule(hwu);
|
|
||||||
}
|
|
||||||
ResumeAndCloseThreads(lphThreads, cb);
|
|
||||||
|
|
||||||
WaitForSingleObject(hEvent, INFINITE);
|
HMODULE hwu = GetModuleHandle(lpServiceDll);
|
||||||
CloseHandle(hEvent);
|
if (hwu && PatchWUAgentHMODULE(hwu)) {
|
||||||
|
_tdbgprintf(_T("Patched previously loaded Windows Update module!"));
|
||||||
|
}
|
||||||
|
ResumeAndCloseThreads(lphThreads, cb);
|
||||||
|
|
||||||
DbgPrint("Received wufuc_UnloadEvent, removing hooks.");
|
WaitForSingleObject(hEvent, INFINITE);
|
||||||
|
|
||||||
SuspendProcess(lphThreads, _countof(lphThreads), &cb);
|
_tdbgprintf(_T("Unload event was set."));
|
||||||
RESTORE_IAT(hm, LoadLibraryExA);
|
|
||||||
RESTORE_IAT(hm, LoadLibraryExW);
|
|
||||||
ResumeAndCloseThreads(lphThreads, cb);
|
|
||||||
|
|
||||||
DbgPrint("Unloading library. Cya!");
|
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
|
||||||
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
|
RESTORE_IAT(hm, LoadLibraryExA);
|
||||||
return 0;
|
RESTORE_IAT(hm, LoadLibraryExW);
|
||||||
|
ResumeAndCloseThreads(lphThreads, cb);
|
||||||
|
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
_tdbgprintf(_T("See ya!"));
|
||||||
|
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsWUModule(HMODULE hModule) {
|
BOOL PatchWUAgentHMODULE(HMODULE hModule) {
|
||||||
TCHAR lpBaseName[MAX_PATH + 1];
|
LPSTR pattern;
|
||||||
GetModuleBaseName(GetCurrentProcess(), hModule, lpBaseName, _countof(lpBaseName));
|
SIZE_T offset00, offset01;
|
||||||
return !_tcsicmp(lpBaseName, _T("wuaueng.dll"));
|
if (Is64BitWindows()) {
|
||||||
}
|
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
|
||||||
|
offset00 = 10;
|
||||||
|
offset01 = 18;
|
||||||
|
} else if (WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
|
||||||
|
pattern = "833D????????00 743E E8???????? A3????????";
|
||||||
|
offset00 = 2;
|
||||||
|
offset01 = 15;
|
||||||
|
} else if (WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
|
||||||
|
pattern = "8BFF 51 833D????????00 7507 A1????????";
|
||||||
|
offset00 = 5;
|
||||||
|
offset01 = 13;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL PatchWUModule(HMODULE hModule) {
|
MODULEINFO modinfo;
|
||||||
if (!IsWindows7Or8Point1()) {
|
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPSTR lpszPattern;
|
SIZE_T rva = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, 0, pattern);
|
||||||
SIZE_T n1, n2;
|
if (rva == -1) {
|
||||||
#ifdef _WIN64
|
_tdbgprintf(_T("No pattern match!"));
|
||||||
lpszPattern =
|
return FALSE;
|
||||||
"FFF3" // push rbx
|
}
|
||||||
"4883EC??" // sub rsp,??
|
uintptr_t baseAddress = (uintptr_t)modinfo.lpBaseOfDll;
|
||||||
"33DB" // xor ebx,ebx
|
uintptr_t fpIsDeviceServiceable = baseAddress + rva;
|
||||||
"391D????????" // cmp dword ptr ds:[???????????],ebx
|
_tdbgprintf(_T("Found address of IsDeviceServiceable. (%p)"), fpIsDeviceServiceable);
|
||||||
"7508" // jnz $+8
|
BOOL result = FALSE;
|
||||||
"8B05????????"; // mov eax,dword ptr ds:[???????????]
|
LPBOOL lpbFirstRun, lpbIsCPUSupportedResult;
|
||||||
n1 = 10;
|
if (Is64BitWindows()) {
|
||||||
n2 = 18;
|
lpbFirstRun = (LPBOOL)(fpIsDeviceServiceable + offset00 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset00));
|
||||||
#elif defined(_WIN32)
|
lpbIsCPUSupportedResult = (LPBOOL)(fpIsDeviceServiceable + offset01 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset01));
|
||||||
if (IsWindows8Point1()) {
|
} else {
|
||||||
lpszPattern =
|
lpbFirstRun = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset00));
|
||||||
"8BFF" // mov edi,edi
|
lpbIsCPUSupportedResult = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset01));
|
||||||
"51" // push ecx
|
}
|
||||||
"833D????????00" // cmp dword ptr ds:[????????],0
|
|
||||||
"7507" // jnz $+7
|
|
||||||
"A1????????"; // mov eax,dword ptr ds:[????????]
|
|
||||||
n1 = 5;
|
|
||||||
n2 = 13;
|
|
||||||
}
|
|
||||||
else if (IsWindows7()) {
|
|
||||||
lpszPattern =
|
|
||||||
"833D????????00" // cmp dword ptr ds:[????????],0
|
|
||||||
"743E" // je $+3E
|
|
||||||
"E8????????" // call <wuaueng.IsCPUSupported>
|
|
||||||
"A3????????"; // mov dword ptr ds:[????????],eax
|
|
||||||
n1 = 2;
|
|
||||||
n2 = 15;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MODULEINFO modinfo;
|
if (*lpbFirstRun) {
|
||||||
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
|
*lpbFirstRun = FALSE;
|
||||||
|
_tdbgprintf(_T("Changed first run to FALSE. (%p=%08x)"), lpbFirstRun, *lpbFirstRun);
|
||||||
SIZE_T offset;
|
result = TRUE;
|
||||||
if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &offset)) {
|
}
|
||||||
return FALSE;
|
if (!*lpbIsCPUSupportedResult) {
|
||||||
}
|
*lpbIsCPUSupportedResult = TRUE;
|
||||||
DbgPrint("IsDeviceServiceable(void) matched at %p", (UINT_PTR)modinfo.lpBaseOfDll + offset);
|
_tdbgprintf(_T("Changed cached result to TRUE. (%p=%08x)."),
|
||||||
|
lpbIsCPUSupportedResult, *lpbIsCPUSupportedResult);
|
||||||
DWORD *lpdwResultIsNotCachedOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1);
|
result = TRUE;
|
||||||
BOOL *lpbResultIsNotCached = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1 + sizeof(DWORD) + *lpdwResultIsNotCachedOffset);
|
}
|
||||||
if (*lpbResultIsNotCached) {
|
return result;
|
||||||
*lpbResultIsNotCached = FALSE;
|
|
||||||
DbgPrint("Patched %p=%d", lpbResultIsNotCached, *lpbResultIsNotCached);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD *lpdwCachedResultOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2);
|
|
||||||
BOOL *lpbCachedResult = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2 + sizeof(DWORD) + *lpdwCachedResultOffset);
|
|
||||||
if (!*lpbCachedResult) {
|
|
||||||
*lpbCachedResult = TRUE;
|
|
||||||
DbgPrint("Patched %p=%d", lpbCachedResult, *lpbCachedResult);
|
|
||||||
}
|
|
||||||
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 (result) {
|
||||||
PatchWUModule(result);
|
_dbgprintf("Loaded %s.", lpFileName);
|
||||||
}
|
CHAR path[MAX_PATH + 1];
|
||||||
return result;
|
if (!get_svcdllA("wuauserv", path, _countof(path))) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_stricmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
|
||||||
|
_dbgprintf("Patched Windows Update module!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 (result) {
|
||||||
PatchWUModule(result);
|
_wdbgprintf(L"Loaded library: %s.", lpFileName);
|
||||||
}
|
WCHAR path[MAX_PATH + 1];
|
||||||
return result;
|
if (!get_svcdllW(L"wuauserv", path, _countof(path))) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_wcsicmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
|
||||||
|
_wdbgprintf(L"Patched Windows Update module!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
14
wufuc/core.h
14
wufuc/core.h
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
DWORD WINAPI NewThreadProc(LPVOID lpParam);
|
DWORD WINAPI NewThreadProc(LPVOID lpParam);
|
||||||
|
|
||||||
BOOL PatchWUModule(HMODULE hModule);
|
BOOL PatchWUAgentHMODULE(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
|
||||||
);
|
);
|
||||||
|
@@ -1,19 +1,24 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
#include "util.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);
|
if (WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)
|
||||||
CloseHandle(hThread);
|
|| WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
|
||||||
break;
|
|
||||||
}
|
HANDLE hThread = CreateThread(NULL, 0, NewThreadProc, NULL, 0, NULL);
|
||||||
case DLL_PROCESS_DETACH:
|
CloseHandle(hThread);
|
||||||
break;
|
}
|
||||||
default:
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case DLL_PROCESS_DETACH:
|
||||||
return TRUE;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@@ -1,41 +0,0 @@
|
|||||||
#include <Windows.h>
|
|
||||||
#include <TlHelp32.h>
|
|
||||||
#include <tchar.h>
|
|
||||||
#include "service.h"
|
|
||||||
#include "process.h"
|
|
||||||
#include "util.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;
|
|
||||||
}
|
|
||||||
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
|
|
||||||
TCHAR lpGroupName[256];
|
|
||||||
DWORD dwProcessId;
|
|
||||||
BOOL result = QueryServiceProcessId(hSCManager, _T("wuauserv"), &dwProcessId);
|
|
||||||
if (!result && GetServiceGroupName(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) {
|
|
||||||
result = FindServiceGroupProcessId(hSCManager, lpGroupName, &dwProcessId);
|
|
||||||
}
|
|
||||||
CloseServiceHandle(hSCManager);
|
|
||||||
if (!result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TCHAR lpLibFileName[MAX_PATH + 1];
|
|
||||||
GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName));
|
|
||||||
|
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
|
|
||||||
|
|
||||||
InjectLibrary(hProcess, lpLibFileName, _countof(lpLibFileName));
|
|
||||||
CloseHandle(hProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
|
||||||
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
|
||||||
if (hEvent) {
|
|
||||||
DbgPrint("Setting wufuc_UnloadEvent...");
|
|
||||||
SetEvent(hEvent);
|
|
||||||
CloseHandle(hEvent);
|
|
||||||
}
|
|
||||||
}
|
|
117
wufuc/patternfind.c
Normal file
117
wufuc/patternfind.c
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
#include "patternfind.h"
|
||||||
|
|
||||||
|
/* Work in progress. Ported to C from x64dbg's patternfind.cpp:
|
||||||
|
<https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp>
|
||||||
|
|
||||||
|
x64dbg license (GPL-3.0):
|
||||||
|
<https://github.com/x64dbg/x64dbg/blob/development/LICENSE> */
|
||||||
|
|
||||||
|
int hexchtoint(CHAR c) {
|
||||||
|
int result = -1;
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
result = c - '0';
|
||||||
|
} else if (c >= 'A' && c <= 'F') {
|
||||||
|
result = c - 'A' + 10;
|
||||||
|
} else if (c >= 'a' && c <= 'f') {
|
||||||
|
result = c - 'a' + 10;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize) {
|
||||||
|
SIZE_T len = strlen(patterntext);
|
||||||
|
SIZE_T result = 0;
|
||||||
|
for (SIZE_T i = 0; i < len && (!formattext || result < formattextsize); i++) {
|
||||||
|
if (patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1) {
|
||||||
|
if (formattext) {
|
||||||
|
formattext[result] = patterntext[i];
|
||||||
|
}
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize) {
|
||||||
|
SIZE_T cb = formathexpattern(patterntext, NULL, 0);
|
||||||
|
if (!cb || cb > *patternsize) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
LPSTR formattext = calloc(cb, sizeof(CHAR));
|
||||||
|
cb = formathexpattern(patterntext, formattext, cb);
|
||||||
|
|
||||||
|
if (cb % 2) {
|
||||||
|
formattext[cb++] = '?';
|
||||||
|
}
|
||||||
|
formattext[cb] = '\0';
|
||||||
|
|
||||||
|
for (SIZE_T i = 0, j = 0, k = 0; i < cb; i++, j ^= 1, k = (i - j) >> 1) {
|
||||||
|
if (formattext[i] == '?') {
|
||||||
|
pattern[k].nibble[j].wildcard = TRUE;
|
||||||
|
} else {
|
||||||
|
pattern[k].nibble[j].wildcard = FALSE;
|
||||||
|
pattern[k].nibble[j].data = hexchtoint(formattext[i]) & 0xf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(formattext);
|
||||||
|
*patternsize = cb >> 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern) {
|
||||||
|
SIZE_T result = -1;
|
||||||
|
SIZE_T searchpatternsize = strlen(pattern);
|
||||||
|
LPPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE));
|
||||||
|
if (patterntransform(pattern, searchpattern, &searchpatternsize)) {
|
||||||
|
for (SIZE_T i = startindex, j = 0; i < datasize; i++) //search for the pattern
|
||||||
|
{
|
||||||
|
if ((searchpattern[j].nibble[0].wildcard || searchpattern[j].nibble[0].data == ((data[i] >> 4) & 0xf))
|
||||||
|
&& (searchpattern[j].nibble[1].wildcard || searchpattern[j].nibble[1].data == (data[i] & 0xf))) { //check if our pattern matches the current byte
|
||||||
|
|
||||||
|
if (++j == searchpatternsize) { //everything matched
|
||||||
|
result = i - searchpatternsize + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (j > 0) { //fix by Computer_Angel
|
||||||
|
i -= j;
|
||||||
|
j = 0; //reset current pattern position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte) {
|
||||||
|
// BYTE n1 = (*byte >> 4) & 0xf;
|
||||||
|
// BYTE n2 = *byte & 0xf;
|
||||||
|
// if (!pbyte->nibble[0].wildcard) {
|
||||||
|
// n1 = pbyte->nibble[0].data;
|
||||||
|
// }
|
||||||
|
// if (!pbyte->nibble[1].wildcard) {
|
||||||
|
// n2 = pbyte->nibble[1].data;
|
||||||
|
// }
|
||||||
|
// *byte = ((n1 << 4) & 0xf0) | (n2 & 0xf);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern) {
|
||||||
|
// SIZE_T writepatternsize = strlen(pattern);
|
||||||
|
// if (writepatternsize > datasize) {
|
||||||
|
// writepatternsize = datasize;
|
||||||
|
// }
|
||||||
|
// LPPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE));
|
||||||
|
// if (!patterntransform(pattern, writepattern, &writepatternsize)) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// for (size_t i = 0; i < writepatternsize; i++) {
|
||||||
|
// patternwritebyte(&data[i], &writepattern[i]);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern) {
|
||||||
|
// SIZE_T result = patternfind(data, datasize, startindex, searchpattern, NULL, 0);
|
||||||
|
// if (result == -1)
|
||||||
|
// return result;
|
||||||
|
// patternwrite(data + result, datasize - result, replacepattern);
|
||||||
|
// return result;
|
||||||
|
//}
|
16
wufuc/patternfind.h
Normal file
16
wufuc/patternfind.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct _PATTERNBYTE {
|
||||||
|
struct _PATTERNNIBBLE {
|
||||||
|
BYTE data;
|
||||||
|
BOOL wildcard;
|
||||||
|
} nibble[2];
|
||||||
|
} PATTERNBYTE, *PPATTERNBYTE, *LPPATTERNBYTE;
|
||||||
|
|
||||||
|
int hexchtoint(CHAR ch);
|
||||||
|
SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize);
|
||||||
|
BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize);
|
||||||
|
SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern);
|
||||||
|
//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte);
|
||||||
|
//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern)
|
||||||
|
//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern);
|
139
wufuc/process.c
139
wufuc/process.c
@@ -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.");
|
|
||||||
}
|
|
@@ -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);
|
|
@@ -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
|
|
71
wufuc/rundll32.c
Normal file
71
wufuc/rundll32.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
#include <TlHelp32.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "service.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
||||||
|
if (!WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)
|
||||||
|
&& !WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||||
|
if (hEvent) {
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
|
||||||
|
if (!hSCManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TCHAR lpGroupName[256];
|
||||||
|
DWORD dwProcessId;
|
||||||
|
BOOL result = get_svcpid(hSCManager, _T("wuauserv"), &dwProcessId);
|
||||||
|
if (!result && get_svcgname(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) {
|
||||||
|
result = get_svcgpid(hSCManager, lpGroupName, &dwProcessId);
|
||||||
|
}
|
||||||
|
CloseServiceHandle(hSCManager);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TCHAR lpLibFileName[MAX_PATH + 1];
|
||||||
|
GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName));
|
||||||
|
|
||||||
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
|
||||||
|
if (!hProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, _countof(lpLibFileName) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
if (lpBaseAddress && WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, _countof(lpLibFileName), NULL)) {
|
||||||
|
|
||||||
|
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
|
||||||
|
if (hSnap) {
|
||||||
|
MODULEENTRY32 me;
|
||||||
|
me.dwSize = sizeof(me);
|
||||||
|
|
||||||
|
if (Module32First(hSnap, &me)) {
|
||||||
|
do {
|
||||||
|
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (Module32Next(hSnap, &me));
|
||||||
|
|
||||||
|
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
CloseHandle(hSnap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
||||||
|
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||||
|
if (hEvent) {
|
||||||
|
_tdbgprintf(_T("Setting unload event..."));
|
||||||
|
SetEvent(hEvent);
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
}
|
||||||
|
}
|
181
wufuc/service.c
181
wufuc/service.c
@@ -1,97 +1,120 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "shellapihelper.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
|
||||||
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
|
BOOL get_svcdllA(LPCSTR lpServiceName, LPSTR lpServiceDll, DWORD dwSize) {
|
||||||
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
|
CHAR lpSubKey[MAX_PATH + 1];
|
||||||
if (!hService) {
|
sprintf_s(lpSubKey, _countof(lpSubKey), "SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD cbBytesNeeded;
|
DWORD uBytes = _MAX_PATH + 1;
|
||||||
QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded);
|
LPBYTE pvData = malloc(uBytes);
|
||||||
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
|
|
||||||
BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded);
|
RegGetValueA(HKEY_LOCAL_MACHINE, lpSubKey, "ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
|
||||||
int a = GetLastError();
|
|
||||||
CloseServiceHandle(hService);
|
ExpandEnvironmentStringsA((LPSTR)pvData, lpServiceDll, dwSize);
|
||||||
if (result) {
|
return TRUE;
|
||||||
_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName);
|
|
||||||
}
|
|
||||||
LocalFree(sc);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
|
BOOL get_svcdllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize) {
|
||||||
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
|
WCHAR lpSubKey[MAX_PATH + 1];
|
||||||
if (!hService) {
|
swprintf_s(lpSubKey, _countof(lpSubKey), L"SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SERVICE_STATUS_PROCESS lpBuffer;
|
DWORD uBytes = _MAX_PATH + 1;
|
||||||
DWORD cbBytesNeeded;
|
LPBYTE pvData = malloc(uBytes);
|
||||||
BOOL result = FALSE;
|
RegGetValueW(HKEY_LOCAL_MACHINE, lpSubKey, L"ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
|
||||||
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded) && lpBuffer.dwProcessId) {
|
|
||||||
*lpdwProcessId = lpBuffer.dwProcessId;
|
ExpandEnvironmentStringsW((LPWSTR)pvData, lpServiceDll, dwSize);
|
||||||
result = TRUE;
|
return TRUE;
|
||||||
DbgPrint("Found %s pid %d", lpServiceName, *lpdwProcessId);
|
|
||||||
}
|
|
||||||
CloseServiceHandle(hService);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
|
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
|
||||||
TCHAR lpBinaryPathName[0x8000];
|
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
|
||||||
if (!QueryServiceBinaryPathName(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
|
if (!hService) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
int numArgs;
|
|
||||||
LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs);
|
|
||||||
if (numArgs < 3) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCHAR fname[_MAX_FNAME];
|
SERVICE_STATUS_PROCESS lpBuffer;
|
||||||
_tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0);
|
DWORD cbBytesNeeded;
|
||||||
|
BOOL result = FALSE;
|
||||||
|
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded)
|
||||||
|
&& lpBuffer.dwProcessId) {
|
||||||
|
|
||||||
BOOL result = FALSE;
|
*lpdwProcessId = lpBuffer.dwProcessId;
|
||||||
if (!_tcsicmp(fname, _T("svchost"))) {
|
_tdbgprintf(_T("Got pid for service %s: %d."), lpServiceName, *lpdwProcessId);
|
||||||
LPWSTR *p = argv;
|
result = TRUE;
|
||||||
for (int i = 0; i + 1 < numArgs; i++) {
|
}
|
||||||
if (!_tcsicmp(*(p++), _T("-k"))) {
|
CloseServiceHandle(hService);
|
||||||
_tcscpy_s(lpGroupName, dwSize, *p);
|
return result;
|
||||||
result = TRUE;
|
|
||||||
DbgPrint("Found %s svc group: %s", lpServiceName, lpGroupName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
|
BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
|
||||||
DWORD uBytes = 0x100000;
|
TCHAR lpBinaryPathName[0x8000];
|
||||||
LPBYTE pvData = malloc(uBytes);
|
if (!get_svcpath(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
int numArgs;
|
||||||
|
LPWSTR *argv = CommandLineToArgv(lpBinaryPathName, &numArgs);
|
||||||
|
if (numArgs < 3) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
|
TCHAR fname[_MAX_FNAME];
|
||||||
|
_tsplitpath_s(argv[0], NULL, 0, NULL, 0, fname, _countof(fname), NULL, 0);
|
||||||
|
|
||||||
LPTSTR ptr = (LPTSTR)pvData;
|
BOOL result = FALSE;
|
||||||
|
if (!_tcsicmp(fname, _T("svchost"))) {
|
||||||
BOOL result = FALSE;
|
LPWSTR *p = argv;
|
||||||
while (*ptr) {
|
for (int i = 1; i < numArgs; i++) {
|
||||||
DWORD dwProcessId;
|
if (!_tcsicmp(*(p++), _T("-k")) && !_tcscpy_s(lpGroupName, dwSize, *p)) {
|
||||||
if (QueryServiceProcessId(hSCManager, ptr, &dwProcessId)) {
|
result = TRUE;
|
||||||
TCHAR group[256];
|
_tdbgprintf(_T("Got group name of service %s: %s."), lpServiceName, lpGroupName);
|
||||||
GetServiceGroupName(hSCManager, ptr, group, _countof(group));
|
break;
|
||||||
result = !_tcsicmp(group, lpServiceGroupName);
|
}
|
||||||
}
|
}
|
||||||
if (result) {
|
}
|
||||||
DbgPrint("Found %s pid %d", lpServiceGroupName, dwProcessId);
|
return result;
|
||||||
*lpdwProcessId = dwProcessId;
|
}
|
||||||
break;
|
|
||||||
}
|
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
|
||||||
ptr += _tcslen(ptr) + 1;
|
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
|
||||||
}
|
if (!hService) {
|
||||||
LocalFree(pvData);
|
return FALSE;
|
||||||
return result;
|
}
|
||||||
|
DWORD cbBytesNeeded;
|
||||||
|
BOOL result = FALSE;
|
||||||
|
if (!QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
|
||||||
|
if (QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded) && !_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName)) {
|
||||||
|
result = TRUE;
|
||||||
|
}
|
||||||
|
free(sc);
|
||||||
|
}
|
||||||
|
CloseServiceHandle(hService);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
|
||||||
|
DWORD uBytes = 0x100000;
|
||||||
|
LPBYTE pvData = malloc(uBytes);
|
||||||
|
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"),
|
||||||
|
lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
|
||||||
|
|
||||||
|
BOOL result = FALSE;
|
||||||
|
for (LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1) {
|
||||||
|
DWORD dwProcessId;
|
||||||
|
TCHAR group[256];
|
||||||
|
if (get_svcpid(hSCManager, p, &dwProcessId)
|
||||||
|
&& (get_svcgname(hSCManager, p, group, _countof(group)) && !_tcsicmp(group, lpServiceGroupName))) {
|
||||||
|
|
||||||
|
*lpdwProcessId = dwProcessId;
|
||||||
|
result = TRUE;
|
||||||
|
_tdbgprintf(_T("Got pid for service group %s: %d."), lpServiceGroupName, *lpdwProcessId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pvData);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
|
|
||||||
|
|
||||||
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
|
BOOL get_svcdllA(LPCSTR lpServiceName, LPSTR lpServiceDll, DWORD dwSize);
|
||||||
|
|
||||||
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
|
BOOL get_svcdllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize);
|
||||||
|
|
||||||
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);
|
#ifdef UNICODE
|
||||||
|
#define get_svcdll get_svcdllW
|
||||||
|
#else
|
||||||
|
#define get_svcdll get_svcdllA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
|
||||||
|
|
||||||
|
BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
|
||||||
|
|
||||||
|
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
|
||||||
|
|
||||||
|
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);
|
||||||
|
7
wufuc/shellapihelper.h
Normal file
7
wufuc/shellapihelper.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define CommandLineToArgv CommandLineToArgvW
|
||||||
|
#else
|
||||||
|
#define CommandLineToArgv CommandLineToArgvA
|
||||||
|
#endif // !UNICODE
|
123
wufuc/util.c
123
wufuc/util.c
@@ -1,27 +1,118 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <VersionHelpers.h>
|
#include <stdio.h>
|
||||||
|
#include <TlHelp32.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
BOOL IsWindows7Or8Point1(void) {
|
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
|
||||||
return IsWindows7() || IsWindows8Point1();
|
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("Detoured %s from %p to %p.", lpFuncName, *lpAddress, lpNewAddress);
|
||||||
|
*lpAddress = lpNewAddress;
|
||||||
|
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL IsWindows7(void) {
|
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
|
||||||
return IsWindows7OrGreater() && !IsWindows8OrGreater();
|
uintptr_t hm = (uintptr_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 IsWindows8Point1(void) {
|
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) {
|
||||||
return IsWindows8Point1OrGreater() && !IsWindows10OrGreater();
|
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 %d other threads."), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef _DEBUG
|
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
|
||||||
VOID _DbgPrint(LPCTSTR format, ...) {
|
for (SIZE_T i = 0; i < cb; i++) {
|
||||||
TCHAR buffer[0x1000];
|
ResumeThread(lphThreads[i]);
|
||||||
va_list argptr;
|
CloseHandle(lphThreads[i]);
|
||||||
va_start(argptr, format);
|
}
|
||||||
_vstprintf_s(buffer, _countof(buffer), format, argptr);
|
_tdbgprintf(_T("Resumed %d other threads."), cb);
|
||||||
va_end(argptr);
|
}
|
||||||
OutputDebugString(buffer);
|
|
||||||
|
BOOL WindowsVersionCompare(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
|
||||||
|
OSVERSIONINFOEX osvi;
|
||||||
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||||
|
osvi.dwMajorVersion = dwMajorVersion;
|
||||||
|
osvi.dwMinorVersion = dwMinorVersion;
|
||||||
|
osvi.wServicePackMajor = wServicePackMajor;
|
||||||
|
osvi.wServicePackMinor = wServicePackMinor;
|
||||||
|
|
||||||
|
DWORDLONG dwlConditionMask = 0;
|
||||||
|
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, Operator);
|
||||||
|
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, Operator);
|
||||||
|
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, Operator);
|
||||||
|
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMINOR, Operator);
|
||||||
|
|
||||||
|
return VerifyVersionInfo(&osvi, dwTypeMask, dwlConditionMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Is64BitWindows(void) {
|
||||||
|
#if defined(_WIN64)
|
||||||
|
return TRUE; // 64-bit programs run only on Win64
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
// 32-bit programs run on both 32-bit and 64-bit Windows
|
||||||
|
// so must sniff
|
||||||
|
BOOL f64 = FALSE;
|
||||||
|
return IsWow64Process(GetCurrentProcess(), &f64) && f64;
|
||||||
|
#else
|
||||||
|
return FALSE; // Win64 does not support Win16
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID _wdbgprintf(LPCWSTR format, ...) {
|
||||||
|
WCHAR buffer[0x1000];
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, format);
|
||||||
|
vswprintf_s(buffer, _countof(buffer), format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
OutputDebugStringW(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
|
|
||||||
|
35
wufuc/util.h
35
wufuc/util.h
@@ -3,22 +3,33 @@
|
|||||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||||
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
||||||
|
|
||||||
BOOL IsWindows7Or8Point1(void);
|
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
|
||||||
|
|
||||||
BOOL IsWindows7(void);
|
#define DETOUR_IAT(x, y) \
|
||||||
|
LPVOID __LPORIGINAL##y; \
|
||||||
|
DetourIAT(x, #y, &__LPORIGINAL##y, &_##y)
|
||||||
|
|
||||||
BOOL IsWindows8Point1(void);
|
#define RESTORE_IAT(x, y) \
|
||||||
|
DetourIAT(x, #y, NULL, __LPORIGINAL##y)
|
||||||
|
|
||||||
|
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
|
||||||
|
|
||||||
|
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
|
||||||
|
|
||||||
|
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);
|
||||||
|
|
||||||
|
BOOL WindowsVersionCompare(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask);
|
||||||
|
|
||||||
|
BOOL Is64BitWindows(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
|
||||||
|
BIN
wufuc/version.rc
BIN
wufuc/version.rc
Binary file not shown.
@@ -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,15 @@
|
|||||||
<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="patternfind.c" />
|
||||||
<ClCompile Include="process.c" />
|
<ClCompile Include="rundll32.c" />
|
||||||
<ClCompile Include="service.c" />
|
<ClCompile Include="service.c" />
|
||||||
<ClCompile Include="util.c" />
|
<ClCompile Include="util.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -177,8 +187,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="core.h" />
|
<ClInclude Include="core.h" />
|
||||||
<ClInclude Include="process.h" />
|
<ClInclude Include="patternfind.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>
|
||||||
|
Reference in New Issue
Block a user