56 Commits

Author SHA1 Message Date
zeffy
2c31ea2fe4 Update appveyor.yml 2017-06-14 03:34:13 -07:00
zeffy
cda46fbc9f 0.6.1
- fixed x86 support
- added june updates to supported updates
- minor changes
2017-06-14 03:29:14 -07:00
zeffy
c4a78a3e24 improve batch script installers
- remove annoying confirmations on disable/enable scripts
- fix disable script on x86
- make sure Schedule service is running before trying do anything with
schtasks
2017-06-13 04:08:22 -07:00
zeffy
3d0b322f1e add is64bitwindows helper 2017-06-13 03:58:42 -07:00
zeffy
2be1785509 new byte pattern search alg
Ported to C from @x64dbg's patternfind.cpp.
https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp

This one is much better than my previous implementation because now I
can use wildcards on single nibbles!
2017-06-13 01:43:27 -07:00
zeffy
c837bfec2f better OS version detection 2017-06-10 14:25:46 -07:00
zeffy
4ad3642db6 more debug 2017-06-10 11:38:57 -07:00
zeffy
0b86b8e9ab more error checking 2017-06-10 11:30:25 -07:00
zeffy
4b85cb18a6 Update README.md 2017-06-10 02:40:47 -07:00
zeffy
9badc6257e ctrl s 2017-06-10 02:40:30 -07:00
zeffy
7d30ebd048 Rename entrypoint.c -> rundll32.c [skip ci] 2017-06-09 15:35:37 -07:00
zeffy
196f4465a9 Update README.md 2017-06-08 21:41:16 -07:00
zeffy
1d9b47e602 better installer 2017-06-08 14:54:38 -07:00
zeffy
ce7e6dd166 more error checking 2017-06-08 13:44:03 -07:00
zeffy
080242cec9 Update README.md 2017-06-07 14:04:27 -07:00
zeffy
b7cff16081 Update README.md 2017-06-07 14:00:15 -07:00
zeffy
7e42fc54f3 fix wrong debug message function 2017-06-07 07:31:43 -07:00
zeffy
c8538b8ec3 slightly more strict wu module detection 2017-06-07 07:18:41 -07:00
zeffy
309981829e better logging 2017-06-07 06:05:27 -07:00
zeffy
8a5ef20488 clean up 2017-06-07 05:34:00 -07:00
zeffy
0f41968610 Update README.md 2017-06-06 20:58:52 -07:00
zeffy
c7a1e606ef Update appveyor.yml 2017-06-06 20:50:27 -07:00
zeffy
7d6baf8aac Update appveyor.yml 2017-06-06 20:44:55 -07:00
zeffy
50182997f2 Add appveyor.yml 2017-06-06 20:39:42 -07:00
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
27 changed files with 838 additions and 532 deletions

View File

@@ -1,7 +1,13 @@
# 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) [![Build status](https://ci.appveyor.com/api/projects/status/0s2unkpokttyslf0?svg=true)](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.
## Downloads [![Github All Releases](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg)](../../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
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
- On system boot the `wufuc` scheduled task runs under the `NT AUTHORITY\SYSTEM` user.
- `wufuc` determines what service host process the Windows Update service (`wuauserv`) runs in, and injects itself into it.
- At system boot the wufuc scheduled task runs as the `NT AUTHORITY\SYSTEM` user.
- `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.
- Any previously loaded `wuaueng.dll` is also patched.
### Several improvements over my script-based approach:
- **No system files are modified!***
- Heuristic byte signature patching persists over new updates.
### Several improvements over my xdelta3/batch script method:
- **No system files are modified!**
- Heuristic-based patching, which means it will usually keep working even after updates.
- C is best language.
- No external dependencies except for Microsoft Visual C++ 2015 Redistributable.
- No external dependencies.
### 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 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?
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
View 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'

View File

@@ -1,5 +1,5 @@
@echo off
title wufuc installer - v0.6
title wufuc installer
:: Copyright (C) 2017 zeffy
:: 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
:: 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 is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
@@ -36,27 +36,34 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :check_ver
goto :is_x86
)
)
goto :unsupported_os
:is_x86
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :get_ver
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
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
wmic /output:stdout os get version | findstr "^6\.1\." >nul && (
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%
goto :check_hotfix
)
wmic /output:stdout os get version | findstr "^6\.3\." >nul && (
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%
goto :check_hotfix
)
@@ -76,19 +83,21 @@ goto :die
for %%a in (%SUPPORTED_HOTFIXES%) do (
wmic /output:stdout qfe get hotfixid | find "%%a" >nul && (
set "INSTALLED_HOTFIX=%%a"
echo Detected installed supported update: %%a
echo Detected supported installed update: %%a
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 WARNING - Detected that no supported updates are installed!
echo WARNING - Detected that no supported updates are installed.
echo.
echo This can be a false warning, if you are certain that need wufuc then you
echo can continue (there will be no side effects even if you don't need it)
set /p CONTINUE=Enter 'Y' if you still want to continue:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo This warning could also mean that a new update came out and the
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,
echo feel free to create an issue. https://github.com/zeffy/wufuc/issues
:confirmation
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 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
echo.
set /p CONTINUE=Enter 'Y' if you want to install wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo Please be absolutely sure you really need wufuc before continuing.
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:
set /p CONTINUE=Enter 'Y' if you want to install wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
:install
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
net start Schedule
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%" /ENABLE
@@ -123,7 +121,9 @@ rundll32 "%wufuc_dll%",Rundll32Unload
schtasks /Run /TN "%wufuc_task%"
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
:die
@@ -132,7 +132,6 @@ echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...

View File

@@ -1,5 +1,5 @@
@echo off
title wufuc uninstaller - v0.6
title wufuc uninstaller
:: Copyright (C) 2017 zeffy
:: 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
:: 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 is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
@@ -34,29 +34,36 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :confirmation
goto :is_x86
)
)
goto :die
:is_x86
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :get_ver
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
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
set /p CONTINUE=Enter 'Y' if you want to uninstall wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
:uninstall
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
rundll32 "%wufuc_dll%",Rundll32Unload
net start Schedule
schtasks /Delete /TN "%wufuc_task%" /F
echo.
echo Unloaded and uninstalled wufuc!
echo Unloaded and uninstalled wufuc. :^(
:die
echo.

View 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

View 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

View File

@@ -1,5 +1,5 @@
@echo off
title install wufuc (repair wuaueng.dll) - v0.6
title wufuc utility - repair wuaueng.dll
:: Copyright (C) 2017 zeffy
:: 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
:: 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 is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
@@ -27,7 +27,6 @@ fltmc >nul 2>&1 || (
goto :die
)
:confirmation
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.

Binary file not shown.

View File

@@ -8,27 +8,23 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C2147FF-2B83-479B-813E-5ACB86F43042}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
wufuc.xml = wufuc.xml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
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.Build.0 = Debug|x64
{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}.Release|Any CPU.ActiveCfg = Release|Win32
{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|x86.ActiveCfg = Release|Win32

BIN
wufuc.xml

Binary file not shown.

View File

@@ -1,19 +1,19 @@
#include <stdint.h>
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <aclapi.h>
#include <sddl.h>
#include "core.h"
#include "process.h"
#include "service.h"
#include "util.h"
#include "patternfind.h"
#include "core.h"
DWORD WINAPI NewThreadProc(LPVOID lpParam) {
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
TCHAR lpBinaryPathName[0x8000];
QueryServiceBinaryPathName(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName));
get_svcpath(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName));
BOOL result = _tcsicmp(GetCommandLine(), lpBinaryPathName);
CloseServiceHandle(hSCManager);
@@ -27,113 +27,98 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) {
ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:PAI(A;;FA;;;BA)"), SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL);
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) {
return 0;
}
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
HANDLE lphThreads[0x1000];
SIZE_T cb;
SuspendProcess(lphThreads, _countof(lphThreads), &cb);
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
HMODULE hm = GetModuleHandle(NULL);
DETOUR_IAT(hm, LoadLibraryExA);
DETOUR_IAT(hm, LoadLibraryExW);
DbgPrint("Applied LoadLibraryEx hooks.");
TCHAR lpServiceDll[MAX_PATH + 1];
get_svcdll(_T("wuauserv"), lpServiceDll, _countof(lpServiceDll));
HMODULE hwu = GetModuleHandle(_T("wuaueng.dll"));
if (hwu) {
PatchWUModule(hwu);
HMODULE hwu = GetModuleHandle(lpServiceDll);
if (hwu && PatchWUAgentHMODULE(hwu)) {
_tdbgprintf(_T("Patched previously loaded Windows Update module!"));
}
ResumeAndCloseThreads(lphThreads, cb);
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
DbgPrint("Received wufuc_UnloadEvent, removing hooks.");
_tdbgprintf(_T("Unload event was set."));
SuspendProcess(lphThreads, _countof(lphThreads), &cb);
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
RESTORE_IAT(hm, LoadLibraryExA);
RESTORE_IAT(hm, LoadLibraryExW);
ResumeAndCloseThreads(lphThreads, cb);
DbgPrint("Unloading library. Cya!");
CloseHandle(hEvent);
_tdbgprintf(_T("See ya!"));
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
return 0;
}
BOOL IsWUModule(HMODULE hModule) {
TCHAR lpBaseName[MAX_PATH + 1];
GetModuleBaseName(GetCurrentProcess(), hModule, lpBaseName, _countof(lpBaseName));
return !_tcsicmp(lpBaseName, _T("wuaueng.dll"));
}
BOOL PatchWUModule(HMODULE hModule) {
if (!IsWindows7Or8Point1()) {
BOOL PatchWUAgentHMODULE(HMODULE hModule) {
LPSTR pattern;
SIZE_T offset00, offset01;
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;
}
LPSTR lpszPattern;
SIZE_T n1, n2;
#ifdef _WIN64
lpszPattern =
"FFF3" // push rbx
"4883EC??" // sub rsp,??
"33DB" // xor ebx,ebx
"391D????????" // cmp dword ptr ds:[???????????],ebx
"7508" // jnz $+8
"8B05????????"; // mov eax,dword ptr ds:[???????????]
n1 = 10;
n2 = 18;
#elif defined(_WIN32)
if (IsWindows8Point1()) {
lpszPattern =
"8BFF" // mov edi,edi
"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;
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
SIZE_T offset;
if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &offset)) {
SIZE_T rva = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, 0, pattern);
if (rva == -1) {
_tdbgprintf(_T("No pattern match!"));
return FALSE;
}
DbgPrint("IsDeviceServiceable(void) matched at %p", (UINT_PTR)modinfo.lpBaseOfDll + offset);
DWORD *lpdwResultIsNotCachedOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1);
BOOL *lpbResultIsNotCached = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1 + sizeof(DWORD) + *lpdwResultIsNotCachedOffset);
if (*lpbResultIsNotCached) {
*lpbResultIsNotCached = FALSE;
DbgPrint("Patched %p=%d", lpbResultIsNotCached, *lpbResultIsNotCached);
uintptr_t baseAddress = (uintptr_t)modinfo.lpBaseOfDll;
uintptr_t fpIsDeviceServiceable = baseAddress + rva;
_tdbgprintf(_T("Found address of IsDeviceServiceable. (%p)"), fpIsDeviceServiceable);
BOOL result = FALSE;
LPBOOL lpbFirstRun, lpbIsCPUSupportedResult;
if (Is64BitWindows()) {
lpbFirstRun = (LPBOOL)(fpIsDeviceServiceable + offset00 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset00));
lpbIsCPUSupportedResult = (LPBOOL)(fpIsDeviceServiceable + offset01 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset01));
} else {
lpbFirstRun = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset00));
lpbIsCPUSupportedResult = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset01));
}
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);
if (*lpbFirstRun) {
*lpbFirstRun = FALSE;
_tdbgprintf(_T("Changed first run to FALSE. (%p=%08x)"), lpbFirstRun, *lpbFirstRun);
result = TRUE;
}
return TRUE;
if (!*lpbIsCPUSupportedResult) {
*lpbIsCPUSupportedResult = TRUE;
_tdbgprintf(_T("Changed cached result to TRUE. (%p=%08x)."),
lpbIsCPUSupportedResult, *lpbIsCPUSupportedResult);
result = TRUE;
}
return result;
}
HMODULE WINAPI _LoadLibraryExA(
@@ -142,8 +127,16 @@ HMODULE WINAPI _LoadLibraryExA(
_In_ DWORD dwFlags
) {
HMODULE result = LoadLibraryExA(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) {
PatchWUModule(result);
if (result) {
_dbgprintf("Loaded %s.", lpFileName);
CHAR path[MAX_PATH + 1];
if (!get_svcdllA("wuauserv", path, _countof(path))) {
return result;
}
if (!_stricmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
_dbgprintf("Patched Windows Update module!");
}
}
return result;
}
@@ -154,8 +147,16 @@ HMODULE WINAPI _LoadLibraryExW(
_In_ DWORD dwFlags
) {
HMODULE result = LoadLibraryExW(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) {
PatchWUModule(result);
if (result) {
_wdbgprintf(L"Loaded library: %s.", lpFileName);
WCHAR path[MAX_PATH + 1];
if (!get_svcdllW(L"wuauserv", path, _countof(path))) {
return result;
}
if (!_wcsicmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
_wdbgprintf(L"Patched Windows Update module!");
}
}
return result;
};

View File

@@ -2,7 +2,7 @@
DWORD WINAPI NewThreadProc(LPVOID lpParam);
BOOL PatchWUModule(HMODULE hModule);
BOOL PatchWUAgentHMODULE(HMODULE hModule);
HMODULE WINAPI _LoadLibraryExA(
_In_ LPCSTR lpFileName,

View File

@@ -1,13 +1,18 @@
#include <Windows.h>
#include "core.h"
#include "util.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hModule);
if (WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)
|| WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
HANDLE hThread = CreateThread(NULL, 0, NewThreadProc, NULL, 0, NULL);
CloseHandle(hThread);
}
break;
}
case DLL_PROCESS_DETACH:

View File

@@ -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
View 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
View 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);

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

71
wufuc/rundll32.c Normal file
View 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);
}
}

View File

@@ -1,28 +1,36 @@
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "util.h"
#include "shellapihelper.h"
#include "service.h"
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
if (!hService) {
return FALSE;
}
BOOL get_svcdllA(LPCSTR lpServiceName, LPSTR lpServiceDll, DWORD dwSize) {
CHAR lpSubKey[MAX_PATH + 1];
sprintf_s(lpSubKey, _countof(lpSubKey), "SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
DWORD cbBytesNeeded;
QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded);
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded);
int a = GetLastError();
CloseServiceHandle(hService);
if (result) {
_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName);
}
LocalFree(sc);
return result;
DWORD uBytes = _MAX_PATH + 1;
LPBYTE pvData = malloc(uBytes);
RegGetValueA(HKEY_LOCAL_MACHINE, lpSubKey, "ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
ExpandEnvironmentStringsA((LPSTR)pvData, lpServiceDll, dwSize);
return TRUE;
}
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
BOOL get_svcdllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize) {
WCHAR lpSubKey[MAX_PATH + 1];
swprintf_s(lpSubKey, _countof(lpSubKey), L"SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
DWORD uBytes = _MAX_PATH + 1;
LPBYTE pvData = malloc(uBytes);
RegGetValueW(HKEY_LOCAL_MACHINE, lpSubKey, L"ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
ExpandEnvironmentStringsW((LPWSTR)pvData, lpServiceDll, dwSize);
return TRUE;
}
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
if (!hService) {
return FALSE;
@@ -31,18 +39,20 @@ BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *l
SERVICE_STATUS_PROCESS lpBuffer;
DWORD cbBytesNeeded;
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;
_tdbgprintf(_T("Got pid for service %s: %d."), lpServiceName, *lpdwProcessId);
result = 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_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
TCHAR lpBinaryPathName[0x8000];
if (!QueryServiceBinaryPathName(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
if (!get_svcpath(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
return FALSE;
}
int numArgs;
@@ -57,11 +67,10 @@ BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpG
BOOL result = FALSE;
if (!_tcsicmp(fname, _T("svchost"))) {
LPWSTR *p = argv;
for (int i = 0; i + 1 < numArgs; i++) {
if (!_tcsicmp(*(p++), _T("-k"))) {
_tcscpy_s(lpGroupName, dwSize, *p);
for (int i = 1; i < numArgs; i++) {
if (!_tcsicmp(*(p++), _T("-k")) && !_tcscpy_s(lpGroupName, dwSize, *p)) {
result = TRUE;
DbgPrint("Found %s svc group: %s", lpServiceName, lpGroupName);
_tdbgprintf(_T("Got group name of service %s: %s."), lpServiceName, lpGroupName);
break;
}
}
@@ -69,29 +78,43 @@ BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpG
return result;
}
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
if (!hService) {
return FALSE;
}
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);
LPTSTR ptr = (LPTSTR)pvData;
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"),
lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
BOOL result = FALSE;
while (*ptr) {
for (LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1) {
DWORD dwProcessId;
if (QueryServiceProcessId(hSCManager, ptr, &dwProcessId)) {
TCHAR group[256];
GetServiceGroupName(hSCManager, ptr, group, _countof(group));
result = !_tcsicmp(group, lpServiceGroupName);
}
if (result) {
DbgPrint("Found %s pid %d", lpServiceGroupName, dwProcessId);
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;
}
ptr += _tcslen(ptr) + 1;
}
LocalFree(pvData);
free(pvData);
return result;
}

View File

@@ -1,9 +1,20 @@
#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
View File

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

View File

@@ -1,27 +1,118 @@
#include <Windows.h>
#include <VersionHelpers.h>
#include <stdio.h>
#include <TlHelp32.h>
#include <tchar.h>
#include "util.h"
BOOL IsWindows7Or8Point1(void) {
return IsWindows7() || IsWindows8Point1();
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("Detoured %s from %p to %p.", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
BOOL IsWindows7(void) {
return IsWindows7OrGreater() && !IsWindows8OrGreater();
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
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) {
return IsWindows8Point1OrGreater() && !IsWindows10OrGreater();
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 %d other threads."), count);
}
//#ifdef _DEBUG
VOID _DbgPrint(LPCTSTR format, ...) {
TCHAR buffer[0x1000];
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
for (SIZE_T i = 0; i < cb; i++) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
_tdbgprintf(_T("Resumed %d other threads."), cb);
}
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);
_vstprintf_s(buffer, _countof(buffer), format, argptr);
vswprintf_s(buffer, _countof(buffer), format, argptr);
va_end(argptr);
OutputDebugString(buffer);
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

View File

@@ -3,22 +3,33 @@
EXTERN_C IMAGE_DOS_HEADER __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
VOID _DbgPrint(LPCTSTR format, ...);
#define DbgPrint(format, ...) \
_DbgPrint(_T(__FUNCTION__) _T(": ") _T(format), ##__VA_ARGS__)
//#else
//#define DbgPrint(format, ...)
//#endif
#ifdef UNICODE
#define CommandLineToArgv CommandLineToArgvW
#define _tdbgprintf _wdbgprintf
#else
#define CommandLineToArgv CommandLineToArgvA
#define _tdbgprintf _dbgprintf
#endif // !UNICODE
//#else
//#define _tdbgprintf(format, ...)
//#endif // !_DEBUG

Binary file not shown.

View File

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