diff --git a/FAQ.md b/FAQ.md
index 6c1d0cc..5d7c703 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -15,12 +15,7 @@ These must be used from an elevated command line prompt.
## How to restore Windows Update to its default configuration
-Windows Update by default is configured to run as `SERVICE_WIN32_SHARE_PROCESS`, which means it shares a single `svchost.exe` process with several other Windows services.
-It can also be configured as `SERVICE_WIN32_OWN_PROCESS`, which means it runs in its own process, which doesn't start until Windows Update does.
-
-Normally, either of these configurations is supported.
-
-However, if you have used another third-party solution for the CPU fix (such as UpdatePack7R2 or WuaCpuFix) either knowingly or unknowingly, wufuc will not function correctly if Windows Update is configured as `SERVICE_WIN32_OWN_PROCESS`.
+If you have used another third-party solution for the CPU fix (such as UpdatePack7R2 or WuaCpuFix) either knowingly or unknowingly, wufuc may not function correctly.
You have two ways to work around this limitation, either:
diff --git a/README.md b/README.md
index 93cda4c..96be7b5 100644
--- a/README.md
+++ b/README.md
@@ -41,13 +41,6 @@ Some people with older Intel and AMD processors are also affected! I've received
- [AMD FX-8350](https://github.com/zeffy/wufuc/issues/32)
- [AMD Turion 64 Mobile Technology ML-34](https://github.com/zeffy/wufuc/issues/80)
-## Bad Microsoft!
-
-If you are interested, you can read my original write-up on discovering the CPU check [here](https://github.com/zeffy/wufuc/tree/old-kb4012218-19).
-
-The tl;dr version is basically, inside a system file named `wuaueng.dll`, there are two functions responsible for the CPU check: `IsDeviceServiceable(void)` and `IsCPUSupported(void)`.
-`IsDeviceServiceable` simply calls `IsCPUSupported` once, and then re-uses the result that it receives on subsequent calls.
-
## Features
- Enables Windows Update on PCs with unsupported processors.
@@ -57,34 +50,36 @@ The tl;dr version is basically, inside a system file named `wuaueng.dll`, there
- Byte pattern-based patching, which means it will usually keep working even after new updates come out.
- No dependencies.
-## Frequently Asked Questions
+## How wufuc works
-See [FAQ.md](https://github.com/zeffy/wufuc/blob/master/FAQ.md).
+The tl;dr version is basically:
-## How it works
+* Inside a system file called `wuaueng.dll`, there are two functions responsible for the CPU check: `IsDeviceServiceable` and `IsCPUSupported`.
+* `IsDeviceServiceable` simply calls `IsCPUSupported` once, and then saves the result and re-uses it on subsequent calls.
+* I take advantage of this behavior in wufuc by patching the saved result so that it is always `TRUE`, or supported.
-This is a basic run-down of what wufuc does when you install it:
+If you would like more information, you can read my original write-up on discovering the CPU check [here](https://github.com/zeffy/wufuc/tree/old-kb4012218-19).
-- The installer registers a scheduled task that automatically starts wufuc on system boot/user log on.
-- Depending on how the Windows Update service is configured to run, wufuc will:
- * **Shared process**: inject itself into the service host process that Windows Update will run in when it starts.
- * **Own process**: wait for the Windows Update service to start and then inject into it.
-- Once injected, wufuc will hook some functions where appropriate:
- * `LoadLibraryExW` hook will automatically hook the `IsDeviceServiceable()` function inside `wuaueng.dll` when it is loaded.
- * `RegQueryValueExW` hook is necessary to provide compatibility with [UpdatePack7R2](../../issues/100). This hook not applied when `wuauserv` is configured to run in its own process.
+
+## Building
+
+To build wufuc from source, you need to download and install the following:
+
+1. [Visual Studio 2017](https://www.visualstudio.com/).
+2. [Windows Driver Kit (WDK)](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk).
+3. (Optional, for MSI packages) [Advanced Installer](https://www.advancedinstaller.com/).
## Sponsors
### [Advanced Installer](https://www.advancedinstaller.com/)
-The installer packages are created with Advanced Installer using an [open source license](http://www.advancedinstaller.com/free-license.html).
+The installer packages are created with Advanced Installer using an [open source license](https://www.advancedinstaller.com/free-license.html).
Advanced Installer's intuitive and friendly user interface allowed me to quickly create a feature complete installer with minimal effort. Check it out!
## Special thanks
-- Wen Jia Liu ([@wj32](https://github.com/wj32)) for his awesome program [Process Hacker](https://github.com/processhacker2/processhacker), and also for his [phnt headers](https://github.com/processhacker2/processhacker/tree/master/phnt).
-- Duncan Ogilvie ([@mrexodia](https://github.com/mrexodia)) for [x64dbg](https://github.com/x64dbg/x64dbg), its [`patternfind.cpp`](https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp) algorithm, and its issue template which I adapted for this project.
-- Tsuda Kageyu ([@TsudaKageyu](https://github.com/TsudaKageyu)) for his excellent [minhook](https://github.com/TsudaKageyu/minhook) library.
+- [**@wj32**](https://github.com/wj32) for his awesome program [Process Hacker](https://github.com/processhacker2/processhacker), and also for his [phnt headers](https://github.com/processhacker2/processhacker/tree/master/phnt).
+- [**@mrexodia**](https://github.com/mrexodia) for [x64dbg](https://github.com/x64dbg/x64dbg), its [`patternfind.cpp`](https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp) algorithm, and its issue template which I adapted for this project.
[Latest]: https://github.com/zeffy/wufuc/releases/latest
[AppVeyor]: https://ci.appveyor.com/project/zeffy/wufuc
diff --git a/appveyor.yml b/appveyor.yml
index e4587c4..fc92120 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -22,9 +22,9 @@ before_build:
set "BUILD_ZIPFILE=%APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%_v%BUILD_COMMIT_VERSION%-%PLATFORM%.zip"
after_build:
- cmd: >-
- copy /Y "COPYING" "src\wufuc_setup_bat\COPYING.txt"
+ copy /Y "COPYING" "src\setup_bat\COPYING.txt"
- cd "%APPVEYOR_BUILD_FOLDER%\src\wufuc_setup_bat"
+ cd "%APPVEYOR_BUILD_FOLDER%\src\setup_bat"
echo v%BUILD_COMMIT_VERSION%>version.txt
@@ -32,9 +32,9 @@ after_build:
for /R %%i in (*.bat) do unix2dos "%%i"
- 7z a "%BUILD_ZIPFILE%" "..\wufuc_setup_bat"
+ 7z a "%BUILD_ZIPFILE%" "..\setup_bat"
- 7z rn "%BUILD_ZIPFILE%" "wufuc_setup_bat" "%APPVEYOR_PROJECT_NAME%"
+ 7z rn "%BUILD_ZIPFILE%" "setup_bat" "%APPVEYOR_PROJECT_NAME%"
7z d "%BUILD_ZIPFILE%" "%APPVEYOR_PROJECT_NAME%\.gitignore"
artifacts:
diff --git a/inc/minhook/minhook.LICENSE.txt b/inc/minhook/minhook.LICENSE.txt
deleted file mode 100644
index 74dea27..0000000
--- a/inc/minhook/minhook.LICENSE.txt
+++ /dev/null
@@ -1,81 +0,0 @@
-MinHook - The Minimalistic API Hooking Library for x64/x86
-Copyright (C) 2009-2017 Tsuda Kageyu.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-================================================================================
-Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
-================================================================================
-Hacker Disassembler Engine 32 C
-Copyright (c) 2008-2009, Vyacheslav Patkov.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------------------
-Hacker Disassembler Engine 64 C
-Copyright (c) 2008-2009, Vyacheslav Patkov.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/inc/minhook/minhook.h b/inc/minhook/minhook.h
deleted file mode 100644
index 9f62e33..0000000
--- a/inc/minhook/minhook.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * MinHook - The Minimalistic API Hooking Library for x64/x86
- * Copyright (C) 2009-2017 Tsuda Kageyu.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
- #error MinHook supports only x86 and x64 systems.
-#endif
-
-// MinHook Error Codes.
-typedef enum MH_STATUS
-{
- // Unknown error. Should not be returned.
- MH_UNKNOWN = -1,
-
- // Successful.
- MH_OK = 0,
-
- // MinHook is already initialized.
- MH_ERROR_ALREADY_INITIALIZED,
-
- // MinHook is not initialized yet, or already uninitialized.
- MH_ERROR_NOT_INITIALIZED,
-
- // The hook for the specified target function is already created.
- MH_ERROR_ALREADY_CREATED,
-
- // The hook for the specified target function is not created yet.
- MH_ERROR_NOT_CREATED,
-
- // The hook for the specified target function is already enabled.
- MH_ERROR_ENABLED,
-
- // The hook for the specified target function is not enabled yet, or already
- // disabled.
- MH_ERROR_DISABLED,
-
- // The specified pointer is invalid. It points the address of non-allocated
- // and/or non-executable region.
- MH_ERROR_NOT_EXECUTABLE,
-
- // The specified target function cannot be hooked.
- MH_ERROR_UNSUPPORTED_FUNCTION,
-
- // Failed to allocate memory.
- MH_ERROR_MEMORY_ALLOC,
-
- // Failed to change the memory protection.
- MH_ERROR_MEMORY_PROTECT,
-
- // The specified module is not loaded.
- MH_ERROR_MODULE_NOT_FOUND,
-
- // The specified function is not found.
- MH_ERROR_FUNCTION_NOT_FOUND
-}
-MH_STATUS;
-
-// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
-// MH_QueueEnableHook or MH_QueueDisableHook.
-#define MH_ALL_HOOKS NULL
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- // Initialize the MinHook library. You must call this function EXACTLY ONCE
- // at the beginning of your program.
- MH_STATUS WINAPI MH_Initialize(VOID);
-
- // Uninitialize the MinHook library. You must call this function EXACTLY
- // ONCE at the end of your program.
- MH_STATUS WINAPI MH_Uninitialize(VOID);
-
- // Creates a Hook for the specified target function, in disabled state.
- // Parameters:
- // pTarget [in] A pointer to the target function, which will be
- // overridden by the detour function.
- // pDetour [in] A pointer to the detour function, which will override
- // the target function.
- // ppOriginal [out] A pointer to the trampoline function, which will be
- // used to call the original target function.
- // This parameter can be NULL.
- MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
-
- // Creates a Hook for the specified API function, in disabled state.
- // Parameters:
- // pszModule [in] A pointer to the loaded module name which contains the
- // target function.
- // pszTarget [in] A pointer to the target function name, which will be
- // overridden by the detour function.
- // pDetour [in] A pointer to the detour function, which will override
- // the target function.
- // ppOriginal [out] A pointer to the trampoline function, which will be
- // used to call the original target function.
- // This parameter can be NULL.
- MH_STATUS WINAPI MH_CreateHookApi(
- LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
-
- // Creates a Hook for the specified API function, in disabled state.
- // Parameters:
- // pszModule [in] A pointer to the loaded module name which contains the
- // target function.
- // pszTarget [in] A pointer to the target function name, which will be
- // overridden by the detour function.
- // pDetour [in] A pointer to the detour function, which will override
- // the target function.
- // ppOriginal [out] A pointer to the trampoline function, which will be
- // used to call the original target function.
- // This parameter can be NULL.
- // ppTarget [out] A pointer to the target function, which will be used
- // with other functions.
- // This parameter can be NULL.
- MH_STATUS WINAPI MH_CreateHookApiEx(
- LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
-
- // Removes an already created hook.
- // Parameters:
- // pTarget [in] A pointer to the target function.
- MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
-
- // Enables an already created hook.
- // Parameters:
- // pTarget [in] A pointer to the target function.
- // If this parameter is MH_ALL_HOOKS, all created hooks are
- // enabled in one go.
- MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
-
- // Disables an already created hook.
- // Parameters:
- // pTarget [in] A pointer to the target function.
- // If this parameter is MH_ALL_HOOKS, all created hooks are
- // disabled in one go.
- MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
-
- // Queues to enable an already created hook.
- // Parameters:
- // pTarget [in] A pointer to the target function.
- // If this parameter is MH_ALL_HOOKS, all created hooks are
- // queued to be enabled.
- MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
-
- // Queues to disable an already created hook.
- // Parameters:
- // pTarget [in] A pointer to the target function.
- // If this parameter is MH_ALL_HOOKS, all created hooks are
- // queued to be disabled.
- MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
-
- // Applies all queued changes in one go.
- MH_STATUS WINAPI MH_ApplyQueued(VOID);
-
- // Translates the MH_STATUS to its name as a string.
- const char * WINAPI MH_StatusToString(MH_STATUS status);
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/lib/minhook/libMinHook.x64.MT.lib b/lib/minhook/libMinHook.x64.MT.lib
deleted file mode 100644
index 9bed8ad..0000000
Binary files a/lib/minhook/libMinHook.x64.MT.lib and /dev/null differ
diff --git a/lib/minhook/libMinHook.x64.MTd.lib b/lib/minhook/libMinHook.x64.MTd.lib
deleted file mode 100644
index 7ce78df..0000000
Binary files a/lib/minhook/libMinHook.x64.MTd.lib and /dev/null differ
diff --git a/lib/minhook/libMinHook.x86.MT.lib b/lib/minhook/libMinHook.x86.MT.lib
deleted file mode 100644
index 8a9d7f3..0000000
Binary files a/lib/minhook/libMinHook.x86.MT.lib and /dev/null differ
diff --git a/lib/minhook/libMinHook.x86.MTd.lib b/lib/minhook/libMinHook.x86.MTd.lib
deleted file mode 100644
index 36c32ba..0000000
Binary files a/lib/minhook/libMinHook.x86.MTd.lib and /dev/null differ
diff --git a/lib/minhook/minhook.LICENSE.txt b/lib/minhook/minhook.LICENSE.txt
deleted file mode 100644
index 74dea27..0000000
--- a/lib/minhook/minhook.LICENSE.txt
+++ /dev/null
@@ -1,81 +0,0 @@
-MinHook - The Minimalistic API Hooking Library for x64/x86
-Copyright (C) 2009-2017 Tsuda Kageyu.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-================================================================================
-Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
-================================================================================
-Hacker Disassembler Engine 32 C
-Copyright (c) 2008-2009, Vyacheslav Patkov.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------------------
-Hacker Disassembler Engine 64 C
-Copyright (c) 2008-2009, Vyacheslav Patkov.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/AdvancedInstallerHelper/AdvancedInstallerHelper.vcxproj b/src/AdvancedInstallerHelper/AdvancedInstallerHelper.vcxproj
index b49d9e0..31be887 100644
--- a/src/AdvancedInstallerHelper/AdvancedInstallerHelper.vcxproj
+++ b/src/AdvancedInstallerHelper/AdvancedInstallerHelper.vcxproj
@@ -46,6 +46,8 @@
true
false
+ $(ProjectDir)bin\$(Configuration)\$(PlatformShortName)\
+ $(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\
false
@@ -93,7 +95,7 @@
exports.def
- copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"
+ copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"
Copy release binaries to the setup staging directory
diff --git a/src/wufuc_setup/.gitignore b/src/setup_ai/.gitignore
similarity index 100%
rename from src/wufuc_setup/.gitignore
rename to src/setup_ai/.gitignore
diff --git a/src/wufuc_setup/LICENSE.rtf b/src/setup_ai/LICENSE.rtf
similarity index 100%
rename from src/wufuc_setup/LICENSE.rtf
rename to src/setup_ai/LICENSE.rtf
diff --git a/src/wufuc_setup/wufuc_setup.aip b/src/setup_ai/wufuc_setup.aip
similarity index 87%
rename from src/wufuc_setup/wufuc_setup.aip
rename to src/setup_ai/wufuc_setup.aip
index 54783b6..efa6a50 100644
--- a/src/wufuc_setup/wufuc_setup.aip
+++ b/src/setup_ai/wufuc_setup.aip
@@ -5,10 +5,7 @@
-
-
-
@@ -21,10 +18,10 @@
-
+
-
+
@@ -43,36 +40,30 @@
-
-
-
+
-
-
-
-
+
-
-
+
@@ -80,10 +71,6 @@
-
-
-
-
@@ -128,11 +115,6 @@
-
-
-
-
-
@@ -143,7 +125,6 @@
-
@@ -187,14 +168,8 @@
-
-
-
-
-
-
@@ -211,7 +186,6 @@
-
@@ -235,24 +209,26 @@
-
-
+
+
-
-
-
+
+
+
-
-
+
+
+
+
@@ -277,12 +253,8 @@
-
-
-
-
@@ -307,13 +279,9 @@
-
-
-
-
-
+
diff --git a/src/wufuc_setup_bat/.gitignore b/src/setup_bat/.gitignore
similarity index 100%
rename from src/wufuc_setup_bat/.gitignore
rename to src/setup_bat/.gitignore
diff --git a/src/wufuc_setup_bat/COPYING.txt b/src/setup_bat/COPYING.txt
similarity index 100%
rename from src/wufuc_setup_bat/COPYING.txt
rename to src/setup_bat/COPYING.txt
diff --git a/src/setup_bat/Help and Support/Donate.url b/src/setup_bat/Help and Support/Donate.url
new file mode 100644
index 0000000..2df8855
--- /dev/null
+++ b/src/setup_bat/Help and Support/Donate.url
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]
+Prop3=19,11
+[InternetShortcut]
+URL=https://github.com/zeffy/wufuc/blob/master/DONATE.md
+IDList=
diff --git a/src/setup_bat/Help and Support/Latest release.url b/src/setup_bat/Help and Support/Latest release.url
new file mode 100644
index 0000000..c33e468
--- /dev/null
+++ b/src/setup_bat/Help and Support/Latest release.url
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]
+Prop3=19,11
+[InternetShortcut]
+URL=https://github.com/zeffy/wufuc/releases/latest
+IDList=
diff --git a/src/wufuc_setup_bat/Troubleshooting/Restore_wuauserv.reg b/src/setup_bat/Help and Support/Restore_wuauserv.reg
similarity index 79%
rename from src/wufuc_setup_bat/Troubleshooting/Restore_wuauserv.reg
rename to src/setup_bat/Help and Support/Restore_wuauserv.reg
index 4a2cca4..eb1c973 100644
Binary files a/src/wufuc_setup_bat/Troubleshooting/Restore_wuauserv.reg and b/src/setup_bat/Help and Support/Restore_wuauserv.reg differ
diff --git a/src/setup_bat/Help and Support/wufuc on GitHub.url b/src/setup_bat/Help and Support/wufuc on GitHub.url
new file mode 100644
index 0000000..65a1ec9
--- /dev/null
+++ b/src/setup_bat/Help and Support/wufuc on GitHub.url
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]
+Prop3=19,11
+[InternetShortcut]
+URL=https://github.com/zeffy/wufuc
+IDList=
diff --git a/src/wufuc_setup_bat/install_wufuc.bat b/src/setup_bat/install_wufuc.bat
similarity index 100%
rename from src/wufuc_setup_bat/install_wufuc.bat
rename to src/setup_bat/install_wufuc.bat
diff --git a/src/wufuc_setup_bat/uninstall_wufuc.bat b/src/setup_bat/uninstall_wufuc.bat
similarity index 100%
rename from src/wufuc_setup_bat/uninstall_wufuc.bat
rename to src/setup_bat/uninstall_wufuc.bat
diff --git a/src/wufuc_setup_bat/wufuc_ScheduledTask.xml b/src/setup_bat/wufuc_ScheduledTask.xml
similarity index 100%
rename from src/wufuc_setup_bat/wufuc_ScheduledTask.xml
rename to src/setup_bat/wufuc_ScheduledTask.xml
diff --git a/src/wufuc.sln b/src/wufuc.sln
index 9c68b81..47a1e3c 100644
--- a/src/wufuc.sln
+++ b/src/wufuc.sln
@@ -5,12 +5,6 @@ VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wufuc", "wufuc\wufuc.vcxproj", "{00F96695-CE41-4C2F-A344-6219DFB4F887}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wufuc_setup_bat", "wufuc_setup_bat", "{97E33D3C-9AA1-4B84-803A-1A6AE2C6F361}"
- ProjectSection(SolutionItems) = preProject
- wufuc_setup_bat\install_wufuc.bat = wufuc_setup_bat\install_wufuc.bat
- wufuc_setup_bat\uninstall_wufuc.bat = wufuc_setup_bat\uninstall_wufuc.bat
- EndProjectSection
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedInstallerHelper", "AdvancedInstallerHelper\AdvancedInstallerHelper.vcxproj", "{12498D61-02AF-4C13-925D-E130EEDE2543}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repository Items", "Repository Items", "{E7EDB493-4D31-4646-8537-C515613689A6}"
diff --git a/src/wufuc/asprintf.c b/src/wufuc/asprintf.c
new file mode 100644
index 0000000..9d379c9
--- /dev/null
+++ b/src/wufuc/asprintf.c
@@ -0,0 +1,121 @@
+#include "stdafx.h"
+#include "asprintf.h"
+#include
+
+int asprintf(char **strp, char const *const fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = vasprintf(strp, fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vasprintf(char **strp, char const *const fmt, va_list ap)
+{
+ return vasprintf_l(strp, fmt, _get_current_locale(), ap);
+}
+
+int asprintf_l(char **strp, char const *const fmt, _locale_t locale, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, locale);
+ result = vasprintf_l(strp, fmt, locale, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vasprintf_l(char **strp, char const *const fmt, _locale_t locale, va_list ap)
+{
+ va_list copy;
+ int result;
+ char *str;
+ int ret;
+
+ va_copy(copy, ap);
+ result = _vscprintf(fmt, copy);
+ va_end(copy);
+
+ if ( result == -1 )
+ return result;
+
+ str = calloc(result + 1, sizeof *str);
+ if ( !str )
+ return -1;
+
+ va_copy(copy, ap);
+ ret = _vsprintf_s_l(str, result + 1, fmt, locale, copy);
+ va_end(copy);
+
+ if ( ret == -1 ) {
+ free(str);
+ return -1;
+ }
+ *strp = str;
+ return result;
+}
+
+int aswprintf(wchar_t **strp, wchar_t const *const fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = vaswprintf(strp, fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vaswprintf(wchar_t **strp, wchar_t const *const fmt, va_list ap)
+{
+ return vaswprintf_l(strp, fmt, _get_current_locale(), ap);
+}
+
+int aswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, locale);
+ result = vaswprintf_l(strp, fmt, locale, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int vaswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, va_list ap)
+{
+ va_list copy;
+ int result;
+ wchar_t *str;
+ int ret;
+
+ va_copy(copy, ap);
+ result = _vscwprintf_l(fmt, locale, copy);
+ va_end(copy);
+
+ if ( result == -1 )
+ return result;
+
+ str = calloc(result + 1, sizeof *str);
+ if ( !str )
+ return -1;
+
+ va_copy(copy, ap);
+ ret = _vswprintf_s_l(str, result + 1, fmt, locale, copy);
+ va_end(copy);
+
+ if ( ret == -1 ) {
+ free(str);
+ return -1;
+ }
+ *strp = str;
+ return result;
+}
diff --git a/src/wufuc/asprintf.h b/src/wufuc/asprintf.h
new file mode 100644
index 0000000..aee31d5
--- /dev/null
+++ b/src/wufuc/asprintf.h
@@ -0,0 +1,17 @@
+#pragma once
+
+int asprintf(char **strp, char const *const fmt, ...);
+
+int vasprintf(char **strp, char const *const fmt, va_list ap);
+
+int asprintf_l(char **strp, char const *const fmt, _locale_t locale, ...);
+
+int vasprintf_l(char **strp, char const *const fmt, _locale_t locale, va_list ap);
+
+int aswprintf(wchar_t **strp, wchar_t const *const fmt, ...);
+
+int vaswprintf(wchar_t **strp, wchar_t const *const fmt, va_list ap);
+
+int aswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, ...);
+
+int vaswprintf_l(wchar_t **strp, wchar_t const *const fmt, _locale_t locale, va_list ap);
diff --git a/src/wufuc/callbacks.c b/src/wufuc/callbacks.c
deleted file mode 100644
index 0230edc..0000000
--- a/src/wufuc/callbacks.c
+++ /dev/null
@@ -1,165 +0,0 @@
-#include "stdafx.h"
-#include "callbacks.h"
-#include "hooks.h"
-#include "log.h"
-#include "modulehelper.h"
-#include "registryhelper.h"
-#include "servicehelper.h"
-#include "versionhelper.h"
-#include "ptrlist.h"
-#include "wufuc.h"
-
-#include
-#include
-
-VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer)
-{
- switch ( pNotifyBuffer->dwNotificationStatus ) {
- case ERROR_SUCCESS:
- if ( pNotifyBuffer->ServiceStatus.dwProcessId )
- wufuc_inject(
- pNotifyBuffer->ServiceStatus.dwProcessId,
- (LPTHREAD_START_ROUTINE)thread_start_callback,
- (ptrlist_t *)pNotifyBuffer->pContext);
- break;
- case ERROR_SERVICE_MARKED_FOR_DELETE:
- SetEvent(ptrlist_at((ptrlist_t *)pNotifyBuffer->pContext, 0, NULL));
- break;
- }
- if ( pNotifyBuffer->pszServiceNames )
- LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
-}
-
-DWORD WINAPI thread_start_callback(HANDLE *pParam)
-{
- HANDLE handles[2];
- HANDLE hCrashMutex;
- HANDLE hProceedEvent;
- SC_HANDLE hSCM;
- SC_HANDLE hService;
- DWORD dwProcessId;
- LPQUERY_SERVICE_CONFIGW pServiceConfig;
- DWORD dwServiceType;
- const wchar_t szKernel32Dll[] = L"kernel32.dll";
- const wchar_t szKernelBaseDll[] = L"kernelbase.dll";
- const wchar_t *pszModule;
- MH_STATUS status;
- int tmp;
- LPVOID pv1 = NULL;
- LPVOID pv2 = NULL;
- wchar_t *str;
- HMODULE hModule;
-
- if ( !pParam ) {
- log_error(L"Parameter argument is null!");
- goto unload;
- }
- handles[0] = pParam[0]; // main mutex
- handles[1] = pParam[1]; // unload event
- hCrashMutex = pParam[2]; // crash mutex
- hProceedEvent = pParam[3]; // proceed event
- if ( !VirtualFree(pParam, 0, MEM_RELEASE) )
- log_warning(L"VirtualFree failed! (lpAddress=%p, GLE=%lu)", pParam, GetLastError());
-
- // acquire child mutex, this should be immediate.
- if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) {
- log_error(L"Failed to acquire crash mutex within five seconds. (%p)", hCrashMutex);
- goto close_handles;
- }
- SetEvent(hProceedEvent);
- CloseHandle(hProceedEvent);
-
- hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
- if ( !hSCM ) {
- log_error(L"Failed to open SCM. (GetLastError=%lu)", GetLastError());
- goto release;
- }
- hService = OpenServiceW(hSCM, L"wuauserv", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
- dwProcessId = svc_heuristic_process_id(hSCM, hService);
- pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
- dwServiceType = pServiceConfig->dwServiceType;
- tmp = _wcsicmp(pServiceConfig->lpBinaryPathName, GetCommandLineW());
- free(pServiceConfig);
- CloseServiceHandle(hService);
- CloseServiceHandle(hSCM);
-
- if ( tmp || dwProcessId != GetCurrentProcessId() ) {
- log_error(L"Injected into wrong process!");
- goto release;
- }
- if ( !ver_verify_version_info(6, 1, 0) && !ver_verify_version_info(6, 3, 0) ) {
- log_error(L"Unsupported operating system!");
- goto release;
- }
- if ( dwServiceType == SERVICE_WIN32_SHARE_PROCESS ) {
- // assume wuaueng.dll hasn't been loaded yet, apply
- // RegQueryValueExW hook to fix incompatibility with
- // UpdatePack7R2 and other patches that modify the
- // Windows Update ServiceDll path in the registry.
- pszModule = IsWindows8OrGreater()
- ? szKernelBaseDll
- : szKernel32Dll;
- status = MH_CreateHookApiEx(pszModule,
- "RegQueryValueExW",
- RegQueryValueExW_hook,
- &(PVOID)g_pfnRegQueryValueExW,
- &pv1);
- if ( status == MH_OK ) {
- status = MH_EnableHook(pv1);
- if ( status == MH_OK )
- log_info(L"Hooked RegQueryValueExW! (Module=%ls, Address=%p)", pszModule, pv1);
- else log_error(L"Failed to enable RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status));
- } else log_error(L"Failed to create RegQueryValueExW hook! (Status=%hs)", MH_StatusToString(status));
- }
- // query the ServiceDll path after applying our compat hook so that it
- // is consistent
- str = (wchar_t *)reg_query_value_alloc(HKEY_LOCAL_MACHINE,
- L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
- L"ServiceDll", NULL, NULL);
- if ( !str ) {
-abort_hook:
- if ( pv1 )
- MH_RemoveHook(pv1);
- goto release;
- }
- g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
- free(str);
- if ( !g_pszWUServiceDll ) goto abort_hook;
-
- status = MH_CreateHookApiEx(szKernelBaseDll,
- "LoadLibraryExW",
- LoadLibraryExW_hook,
- &(PVOID)g_pfnLoadLibraryExW,
- &pv2);
- if ( status == MH_OK ) {
- status = MH_EnableHook(pv2);
- if ( status == MH_OK )
- log_info(L"Hooked LoadLibraryExW! (Module=%ls, Address=%p)", szKernelBaseDll, pv2);
- else log_error(L"Failed to enable LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status));
- } else log_error(L"Failed to create LoadLibraryExW hook! (Status=%hs)", MH_StatusToString(status));
-
- if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
- || GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
-
- // hook IsDeviceServiceable if wuaueng.dll is already loaded
- wufuc_patch(hModule);
- FreeLibrary(hModule);
- }
- // wait for unload event or the main mutex to be released or abandoned,
- // for example if the user killed rundll32.exe with task manager.
- WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
- log_info(L"Unload condition has been met.");
-
- MH_DisableHook(MH_ALL_HOOKS);
- free(g_pszWUServiceDll);
-release:
- ReleaseMutex(hCrashMutex);
-close_handles:
- CloseHandle(hCrashMutex);
- CloseHandle(handles[0]);
- CloseHandle(handles[1]);
-unload:
- log_info(L"Unloading wufuc and exiting thread.");
- FreeLibraryAndExitThread(PIMAGEBASE, 0);
-}
-
diff --git a/src/wufuc/callbacks.h b/src/wufuc/callbacks.h
deleted file mode 100644
index 973f943..0000000
--- a/src/wufuc/callbacks.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-VOID CALLBACK service_notify_callback(PSERVICE_NOTIFYW pNotifyBuffer);
-DWORD WINAPI thread_start_callback(HANDLE *pParam);
diff --git a/src/wufuc/dllmain.c b/src/wufuc/dllmain.c
index 710c094..141b3a0 100644
--- a/src/wufuc/dllmain.c
+++ b/src/wufuc/dllmain.c
@@ -1,7 +1,4 @@
#include "stdafx.h"
-#include "log.h"
-
-#include
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
@@ -9,14 +6,12 @@ BOOL APIENTRY DllMain(HMODULE hModule,
{
switch ( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
- MH_Initialize();
- break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
- MH_Uninitialize();
- log_close();
+ if ( !lpReserved )
+ log_close();
break;
}
return TRUE;
diff --git a/src/wufuc/eventhelper.c b/src/wufuc/eventhelper.c
deleted file mode 100644
index 2c35460..0000000
--- a/src/wufuc/eventhelper.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "stdafx.h"
-#include "eventhelper.h"
-
-#include
-
-HANDLE event_create_with_string_security_descriptor(
- bool ManualReset,
- bool InitialState,
- const wchar_t *Name,
- const wchar_t *StringSecurityDescriptor)
-{
- SECURITY_ATTRIBUTES sa = { sizeof sa };
-
- if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
- StringSecurityDescriptor,
- SDDL_REVISION_1,
- &sa.lpSecurityDescriptor,
- NULL) ) {
-
- return CreateEventW(&sa, ManualReset, InitialState, Name);
- }
- return NULL;
-}
diff --git a/src/wufuc/eventhelper.h b/src/wufuc/eventhelper.h
deleted file mode 100644
index da7fbf8..0000000
--- a/src/wufuc/eventhelper.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-
-HANDLE event_create_with_string_security_descriptor(
- bool ManualReset,
- bool InitialState,
- const wchar_t *Name,
- const wchar_t *StringSecurityDescriptor);
diff --git a/src/wufuc/helpers.c b/src/wufuc/helpers.c
new file mode 100644
index 0000000..a464776
--- /dev/null
+++ b/src/wufuc/helpers.c
@@ -0,0 +1,54 @@
+#include "stdafx.h"
+#include "helpers.h"
+#include
+
+HANDLE CreateEventWithStringSecurityDescriptor(
+ LPCWSTR lpStringSecurityDescriptor,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName)
+{
+ SECURITY_ATTRIBUTES sa = { sizeof sa };
+
+ if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
+ lpStringSecurityDescriptor,
+ SDDL_REVISION_1,
+ &sa.lpSecurityDescriptor,
+ NULL) ) {
+ return CreateEventW(&sa, bManualReset, bInitialState, lpName);
+ }
+ return NULL;
+}
+
+HANDLE CreateNewMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName)
+{
+ HANDLE result;
+
+ result = CreateMutexW(lpMutexAttributes, bInitialOwner, lpName);
+ if ( result ) {
+ if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+ CloseHandle(result);
+ return NULL;
+ }
+ return result;
+ }
+ return NULL;
+}
+
+BOOL VerifyVersionInfoHelper(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
+{
+ DWORDLONG dwlConditionMask = 0;
+ OSVERSIONINFOEXW osvi = { sizeof osvi };
+
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+
+ osvi.dwMajorVersion = wMajorVersion;
+ osvi.dwMinorVersion = wMinorVersion;
+ osvi.wServicePackMajor = wServicePackMajor;
+
+ return VerifyVersionInfoW(&osvi,
+ VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
+ dwlConditionMask);
+}
diff --git a/src/wufuc/helpers.h b/src/wufuc/helpers.h
new file mode 100644
index 0000000..21ec83a
--- /dev/null
+++ b/src/wufuc/helpers.h
@@ -0,0 +1,11 @@
+#pragma once
+
+HANDLE CreateNewMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCWSTR lpName);
+
+HANDLE CreateEventWithStringSecurityDescriptor(
+ LPCWSTR lpStringSecurityDescriptor,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName);
+
+BOOL VerifyVersionInfoHelper(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);
diff --git a/src/wufuc/hooks.c b/src/wufuc/hooks.c
deleted file mode 100644
index b036b35..0000000
--- a/src/wufuc/hooks.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "stdafx.h"
-#include "hooks.h"
-#include "log.h"
-#include "registryhelper.h"
-#include "ptrlist.h"
-#include "wufuc.h"
-
-wchar_t *g_pszWUServiceDll;
-
-LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
-LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
-
-LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
-{
- wchar_t *pBuffer;
- DWORD MaximumLength = 0;
- LSTATUS result;
- ULONG ResultLength;
- PKEY_NAME_INFORMATION pkni;
- size_t NameCount;
- unsigned int current;
- int pos;
- wchar_t *fname;
- const wchar_t realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
- wchar_t *expandedpath;
- DWORD cchLength;
-
- // save original buffer size
- if ( lpData && lpcbData )
- MaximumLength = *lpcbData;
- result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
-
- if ( result != ERROR_SUCCESS
- || !MaximumLength
- || !lpValueName
- || (lpType && *lpType != REG_EXPAND_SZ)
- || _wcsicmp(lpValueName, L"ServiceDll") )
- return result;
-
- pBuffer = (wchar_t *)lpData;
-
- // get name of registry key being queried
- pkni = reg_query_key_alloc((HANDLE)hKey, KeyNameInformation, &ResultLength);
- if ( !pkni )
- return result;
- NameCount = pkni->NameLength / sizeof *pkni->Name;
-
- // change key name to lower-case because there is no case-insensitive version of _snwscanf_s
- for ( size_t i = 0; i < NameCount; i++ )
- pkni->Name[i] = towlower(pkni->Name[i]);
-
- if ( _snwscanf_s(pkni->Name, NameCount, L"\\registry\\machine\\system\\controlset%03u\\services\\wuauserv\\parameters%n", ¤t, &pos) == 1
- && pos == NameCount ) {
-
- fname = PathFindFileNameW(pBuffer);
-
- if ( (!_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
- || !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix
- || !_wcsicmp(fname, L"WuaCpuFix.dll")) ) {
-
- expandedpath = env_expand_strings_alloc(realpath, &cchLength);
- if ( expandedpath ) {
- if ( PathFileExistsW(expandedpath)
- && SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) {
-
- *lpcbData = cchLength * (sizeof *expandedpath);
- log_info(L"Fixed path to Windows Update service library.");
- }
- free(expandedpath);
- }
- }
- }
- free(pkni);
- return result;
-}
-
-HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags)
-{
- HMODULE result;
-
- result = g_pfnLoadLibraryExW(lpFileName, hFile, dwFlags);
- if ( !result ) return result;
- log_debug(L"Loaded library: %ls (%p)", lpFileName, result);
-
- if ( dwFlags == LOAD_WITH_ALTERED_SEARCH_PATH
- && g_pszWUServiceDll
- && (!_wcsicmp(lpFileName, g_pszWUServiceDll)
- || !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) {
-
- wufuc_patch(result);
- }
- return result;
-}
diff --git a/src/wufuc/hooks.h b/src/wufuc/hooks.h
deleted file mode 100644
index 7161e30..0000000
--- a/src/wufuc/hooks.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-
-typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
-typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
-
-extern wchar_t *g_pszWUServiceDll;
-
-extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
-extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
-
-extern PVOID g_ptRegQueryValueExW;
-extern PVOID g_ptLoadLibraryExW;
-
-LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
-HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags);
diff --git a/src/wufuc/log.c b/src/wufuc/log.c
deleted file mode 100644
index b397702..0000000
--- a/src/wufuc/log.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include "stdafx.h"
-#include "log.h"
-
-#include
-
-static HANDLE m_hFile = INVALID_HANDLE_VALUE;
-static DWORD m_dwProcessId;
-static wchar_t m_szExeFilePath[MAX_PATH];
-static wchar_t *m_pszExeName;
-
-BOOL CALLBACK init_once_callback(
- PINIT_ONCE InitOnce,
- PVOID *Parameter,
- PVOID *lpContext)
-{
- BOOL result;
- HRESULT hr;
- wchar_t *pszPath;
- wchar_t szFilePath[MAX_PATH];
- int ret;
-
- m_dwProcessId = GetCurrentProcessId();
- if ( !GetModuleFileNameW(NULL, m_szExeFilePath, _countof(m_szExeFilePath)) ) {
- log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError());
- return FALSE;
- }
- m_pszExeName = PathFindFileNameW(m_szExeFilePath);
-
- hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath);
- if ( hr != S_OK ) {
- log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
- return FALSE;
- }
- ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
- CoTaskMemFree(pszPath);
- if ( ret ) {
- log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
- return FALSE;
- }
- if ( !PathAppendW(szFilePath, L"wufuc") ) {
-append_fail:
- log_debug(L"PathAppendW failed!");
- return FALSE;
- }
- if ( !CreateDirectoryW(szFilePath, NULL)
- && GetLastError() != ERROR_ALREADY_EXISTS ) {
-
- log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError());
- return FALSE;
- }
- if ( !PathAppendW(szFilePath, L"wufuc.1.log") )
- goto append_fail;
-
- m_hFile = CreateFileW(szFilePath,
- FILE_APPEND_DATA,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- result = m_hFile != INVALID_HANDLE_VALUE;
- if ( !result )
- log_debug(L"CreateFileW failed! (GLE=%lu)", GetLastError());
- return result;
-}
-
-void log_debug_(const wchar_t *const format, ...)
-{
- va_list ap;
- wchar_t *buf;
- int ret;
- int count;
-
- va_start(ap, format);
- count = _vscwprintf(format, ap);
- va_end(ap);
- if ( count == -1 ) return;
-
- buf = calloc(count + 1, sizeof *buf);
- if ( !buf ) return;
-
- va_start(ap, format);
- ret = vswprintf_s(buf, count + 1, format, ap);
- va_end(ap);
- if ( ret != -1 )
- OutputDebugStringW(buf);
- free(buf);
-}
-
-void log_trace_(const wchar_t *const format, ...)
-{
- static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
- BOOL bStatus;
- wchar_t datebuf[9];
- wchar_t timebuf[9];
- va_list ap;
- const wchar_t fmt[] = L"%ls %ls [%ls:%lu] %ls";
- int count;
- wchar_t *buf1;
- int ret;
- wchar_t *buf2;
- int size;
- char *buf3;
- DWORD written;
-
- bStatus = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
-
- if ( _wstrdate_s(datebuf, _countof(datebuf))
- || _wstrtime_s(timebuf, _countof(timebuf)) )
- return;
-
- va_start(ap, format);
- ret = _vscwprintf(format, ap);
- va_end(ap);
- if ( ret == -1 ) return;
- count = ret + 1;
-
- buf1 = calloc(count, sizeof *buf1);
- if ( !buf1 ) return;
-
- va_start(ap, format);
- ret = vswprintf_s(buf1, count, format, ap);
- va_end(ap);
- if ( ret == -1 ) goto free_buf1;
-
- ret = _scwprintf(fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
- if ( ret == -1 ) goto free_buf1;
- count = ret + 1;
-
- buf2 = calloc(count, sizeof *buf2);
- if ( !buf2 ) goto free_buf1;
-
- ret = swprintf_s(buf2, count, fmt, datebuf, timebuf, m_pszExeName, m_dwProcessId, buf1);
- if ( ret == -1 ) goto free_buf2;
-
- if ( bStatus ) {
- size = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, NULL, 0, NULL, NULL);
- if ( !size ) goto fallback;
-
- buf3 = malloc(size);
- if ( !buf3 ) goto fallback;
-
- ret = WideCharToMultiByte(CP_UTF8, 0, buf2, ret, buf3, size, NULL, NULL)
- && WriteFile(m_hFile, buf3, size, &written, NULL);
- free(buf3);
- if ( !ret ) goto fallback;
- } else {
-fallback:
- OutputDebugStringW(buf2);
- }
-free_buf2:
- free(buf2);
-free_buf1:
- free(buf1);
-}
-
-void log_close(void)
-{
- if ( m_hFile != INVALID_HANDLE_VALUE )
- CloseHandle(m_hFile);
-}
diff --git a/src/wufuc/log.h b/src/wufuc/log.h
deleted file mode 100644
index f2f54c1..0000000
--- a/src/wufuc/log.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-void log_debug_(const wchar_t *const format, ...);
-void log_trace_(const wchar_t *const format, ...);
-void log_close(void);
-
-#define log_debug(format, ...) log_debug_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [DEBUG] " format L"\r\n", ##__VA_ARGS__)
-#define log_info(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [INFO] " format L"\r\n", ##__VA_ARGS__)
-#define log_warning(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [WARNING] " format L"\r\n", ##__VA_ARGS__)
-#define log_error(format, ...) log_trace_(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): [ERROR] " format L"\r\n", ##__VA_ARGS__)
diff --git a/src/wufuc/logger.c b/src/wufuc/logger.c
new file mode 100644
index 0000000..475550e
--- /dev/null
+++ b/src/wufuc/logger.c
@@ -0,0 +1,99 @@
+#include "stdafx.h"
+#include "logger.h"
+#include "utf8.h"
+#include
+
+static WCHAR s_szExeFilePath[MAX_PATH];
+static LPWSTR s_pszExeFileName;
+static HANDLE s_hFile = INVALID_HANDLE_VALUE;
+
+static BOOL CALLBACK init_once_callback(
+ PINIT_ONCE InitOnce,
+ PVOID *Parameter,
+ PVOID *lpContext)
+{
+ PWSTR pszPath;
+ LPWSTR folder;
+ int count;
+ LPWSTR file;
+
+ if ( !GetModuleFileNameW(NULL, s_szExeFilePath, _countof(s_szExeFilePath)) )
+ return FALSE;
+
+ s_pszExeFileName = PathFindFileNameW(s_szExeFilePath);
+
+ if ( FAILED(SHGetKnownFolderPath(&FOLDERID_ProgramData, KF_FLAG_DEFAULT, NULL, &pszPath)) )
+ return FALSE;
+
+ count = aswprintf(&folder, L"%ls\\wufuc", pszPath);
+ CoTaskMemFree(pszPath);
+
+ if ( count == -1 )
+ return FALSE;
+
+ if ( (CreateDirectoryW(folder, NULL) || GetLastError() == ERROR_ALREADY_EXISTS)
+ && aswprintf(&file, L"%ls\\wufuc.1.log", folder) != -1 ) {
+
+ s_hFile = CreateFileW(file,
+ FILE_APPEND_DATA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ free(file);
+ }
+ free(folder);
+ return s_hFile != INVALID_HANDLE_VALUE;
+}
+
+void log_debug_(const wchar_t *const format, ...)
+{
+ va_list ap;
+ int count;
+ wchar_t *buffer;
+
+ va_start(ap, format);
+ count = vaswprintf(&buffer, format, ap);
+ va_end(ap);
+ if ( count != -1 )
+ OutputDebugStringW(buffer);
+ free(buffer);
+}
+
+void log_trace_(const wchar_t *const format, ...)
+{
+ static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
+ BOOL status;
+ wchar_t datebuf[9];
+ wchar_t timebuf[9];
+ va_list ap;
+ int count;
+ wchar_t *buf1;
+ wchar_t *buf2;
+
+ status = InitOnceExecuteOnce(&InitOnce, init_once_callback, NULL, NULL);
+
+ if ( _wstrdate_s(datebuf, _countof(datebuf))
+ || _wstrtime_s(timebuf, _countof(timebuf)) )
+ return;
+
+ va_start(ap, format);
+ count = vaswprintf(&buf1, format, ap);
+ va_end(ap);
+ if ( count == -1 ) return;
+
+ count = aswprintf(&buf2, L"%ls %ls [%ls:%lu] %ls", datebuf, timebuf, s_pszExeFileName, GetCurrentProcessId(), buf1);
+ free(buf1);
+ if ( count == -1 ) return;
+
+ if ( !status || !UTF8WriteFile(s_hFile, buf2) )
+ OutputDebugStringW(buf2);
+ free(buf2);
+}
+
+void log_close(void)
+{
+ if ( s_hFile != INVALID_HANDLE_VALUE )
+ CloseHandle(s_hFile);
+}
diff --git a/src/wufuc/logger.h b/src/wufuc/logger.h
new file mode 100644
index 0000000..6c83297
--- /dev/null
+++ b/src/wufuc/logger.h
@@ -0,0 +1,11 @@
+#pragma once
+
+void log_debug_(const wchar_t *const format, ...);
+void log_trace_(const wchar_t *const format, ...);
+void log_close(void);
+
+#define log_debug(format, ...) log_debug_(L"[DEBUG] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
+#define log_info(format, ...) log_trace_(L"[INFO] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
+#define log_warning(format, ...) log_trace_(L"[WARNING] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
+#define log_error(format, ...) log_trace_(L"[ERROR] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
+#define log_gle(format, ...) log_trace_(L"[ERROR] " __FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L" (LastError=%lu)\r\n", ##__VA_ARGS__, GetLastError())
diff --git a/src/wufuc/memory.c b/src/wufuc/memory.c
new file mode 100644
index 0000000..2e69090
--- /dev/null
+++ b/src/wufuc/memory.c
@@ -0,0 +1,8 @@
+#include "stdafx.h"
+#include "stdafx.h"
+#include "memory.h"
+
+BOOL WriteProcessMemoryBOOL(HANDLE hProcess, LPBOOL lpBaseAddress, BOOL bValue)
+{
+ return WriteProcessMemory(hProcess, lpBaseAddress, &bValue, sizeof bValue, NULL);
+}
\ No newline at end of file
diff --git a/src/wufuc/memory.h b/src/wufuc/memory.h
new file mode 100644
index 0000000..4065250
--- /dev/null
+++ b/src/wufuc/memory.h
@@ -0,0 +1,3 @@
+#pragma once
+
+BOOL WriteProcessMemoryBOOL(HANDLE hProcess, LPBOOL lpBaseAddress, BOOL bValue);
diff --git a/src/wufuc/modulehelper.c b/src/wufuc/modulehelper.c
deleted file mode 100644
index c48df35..0000000
--- a/src/wufuc/modulehelper.c
+++ /dev/null
@@ -1,157 +0,0 @@
-#include "stdafx.h"
-#include "modulehelper.h"
-#include "log.h"
-
-HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName)
-{
- MODULEENTRY32W me = { sizeof me };
- if ( !Module32FirstW(hSnapshot, &me) )
- return NULL;
- do {
- if ( !_wcsicmp(me.szExePath, pLibFileName) )
- return me.hModule;
- } while ( Module32NextW(hSnapshot, &me) );
- return NULL;
-}
-
-bool mod_inject_and_begin_thread(
- HANDLE hProcess,
- HMODULE hModule,
- LPTHREAD_START_ROUTINE pStartAddress,
- const void *pParam,
- size_t cbParam)
-{
- bool result = false;
- NTSTATUS Status;
- LPVOID pBaseAddress = NULL;
- SIZE_T cb;
- HMODULE hRemoteModule = NULL;
- uintptr_t offset;
- HANDLE hThread;
-
- Status = NtSuspendProcess(hProcess);
- if ( !NT_SUCCESS(Status) ) return result;
-
- if ( pParam ) {
- // this will be VirtualFree()'d by the function at pStartAddress
- pBaseAddress = VirtualAllocEx(hProcess,
- NULL,
- cbParam,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if ( !pBaseAddress ) goto resume_process;
-
- if ( !WriteProcessMemory(hProcess, pBaseAddress, pParam, cbParam, &cb) )
- goto virt_free;
- }
- if ( mod_inject_by_hmodule(hProcess, hModule, &hRemoteModule) ) {
- offset = (uintptr_t)pStartAddress - (uintptr_t)hModule;
- hThread = CreateRemoteThread(hProcess,
- NULL,
- 0,
- OffsetToPointer(hRemoteModule, offset),
- pBaseAddress,
- 0,
- NULL);
-
- if ( hThread ) {
- CloseHandle(hThread);
- result = true;
- }
- }
-virt_free:
- if ( !result && pBaseAddress )
- VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
-resume_process:
- NtResumeProcess(hProcess);
- return result;
-}
-
-bool mod_inject_by_hmodule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule)
-{
- WCHAR Filename[MAX_PATH];
- DWORD nLength;
-
- nLength = GetModuleFileNameW(hModule, Filename, _countof(Filename));
- if ( nLength ) {
- return mod_inject(hProcess,
- Filename,
- nLength,
- phRemoteModule);
- }
- return false;
-}
-
-bool mod_inject(
- HANDLE hProcess,
- const wchar_t *pLibFilename,
- size_t cchLibFilename,
- HMODULE *phRemoteModule)
-{
- bool result = false;
- DWORD dwProcessId;
- NTSTATUS Status;
- HANDLE hSnapshot;
- SIZE_T nSize;
- LPVOID pBaseAddress;
- HANDLE hThread;
-
- Status = NtSuspendProcess(hProcess);
- if ( !NT_SUCCESS(Status) ) return result;
-
- dwProcessId = GetProcessId(hProcess);
-
- hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
- if ( !hSnapshot ) goto resume_process;
-
- *phRemoteModule = mod_get_from_th32_snapshot(hSnapshot,
- pLibFilename);
-
- CloseHandle(hSnapshot);
-
- // already injected... still sets *phRemoteModule
- if ( *phRemoteModule ) goto resume_process;
-
- nSize = (cchLibFilename + 1) * sizeof *pLibFilename;
- pBaseAddress = VirtualAllocEx(hProcess,
- NULL,
- nSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
-
- if ( !pBaseAddress ) goto resume_process;
-
- if ( !WriteProcessMemory(hProcess, pBaseAddress, pLibFilename, nSize, NULL) )
- goto virt_free;
-
- hThread = CreateRemoteThread(hProcess,
- NULL,
- 0,
- (LPTHREAD_START_ROUTINE)LoadLibraryW,
- pBaseAddress,
- 0,
- NULL);
- if ( !hThread ) goto virt_free;
-
- WaitForSingleObject(hThread, INFINITE);
-
- if ( sizeof *phRemoteModule > sizeof(DWORD) ) {
- hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
- if ( hSnapshot ) {
- *phRemoteModule = mod_get_from_th32_snapshot(
- hSnapshot,
- pLibFilename);
-
- CloseHandle(hSnapshot);
- result = *phRemoteModule != NULL;
- }
- } else {
- result = GetExitCodeThread(hThread, (LPDWORD)phRemoteModule) != FALSE;
- }
- CloseHandle(hThread);
-virt_free:
- VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
-resume_process:
- NtResumeProcess(hProcess);
- return result;
-}
diff --git a/src/wufuc/modulehelper.h b/src/wufuc/modulehelper.h
deleted file mode 100644
index 2e88a78..0000000
--- a/src/wufuc/modulehelper.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName);
-bool mod_inject_and_begin_thread(
- HANDLE hProcess,
- HMODULE hModule,
- LPTHREAD_START_ROUTINE pStartAddress,
- const void *pParam,
- size_t cbParam);
-bool mod_inject_by_hmodule(HANDLE hProcess, HMODULE hModule, HMODULE *phRemoteModule);
-bool mod_inject(
- HANDLE hProcess,
- const wchar_t *pLibFilename,
- size_t cchLibFilename,
- HMODULE *phRemoteModule);
diff --git a/src/wufuc/modules.c b/src/wufuc/modules.c
new file mode 100644
index 0000000..de97d31
--- /dev/null
+++ b/src/wufuc/modules.c
@@ -0,0 +1,24 @@
+#include "stdafx.h"
+#include "modules.h"
+
+HMODULE Toolhelp32GetModuleHandle(DWORD th32ProcessID, LPCWSTR lpModuleName)
+{
+ HANDLE Snapshot;
+ MODULEENTRY32W me = { sizeof me };
+ HMODULE result = NULL;
+
+ Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, th32ProcessID);
+ if ( !Snapshot ) return NULL;
+
+ if ( Module32FirstW(Snapshot, &me) ) {
+ do {
+ if ( !_wcsicmp(me.szExePath, lpModuleName) ) {
+ result = me.hModule;
+ break;
+ }
+ } while ( Module32NextW(Snapshot, &me) );
+ }
+ CloseHandle(Snapshot);
+
+ return result;
+}
diff --git a/src/wufuc/modules.h b/src/wufuc/modules.h
new file mode 100644
index 0000000..ff6e252
--- /dev/null
+++ b/src/wufuc/modules.h
@@ -0,0 +1,3 @@
+#pragma once
+
+HMODULE Toolhelp32GetModuleHandle(DWORD th32ProcessID, LPCWSTR lpModuleName);
diff --git a/src/wufuc/mutexhelper.c b/src/wufuc/mutexhelper.c
deleted file mode 100644
index 6b68b76..0000000
--- a/src/wufuc/mutexhelper.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "stdafx.h"
-#include "mutexhelper.h"
-
-#include
-
-HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName)
-{
- HANDLE hMutex;
-
- hMutex = CreateMutexW(NULL, InitialOwner, MutexName);
- if ( hMutex ) {
- if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
- CloseHandle(hMutex);
- return NULL;
- }
- return hMutex;
- }
- return NULL;
-}
-
-HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...)
-{
- HANDLE result = NULL;
- va_list ap;
- wchar_t *buffer;
- int ret;
-
- va_start(ap, NameFormat);
- ret = _vscwprintf(NameFormat, ap) + 1;
- va_end(ap);
- buffer = calloc(ret, sizeof *buffer);
- if ( buffer ) {
- va_start(ap, NameFormat);
- ret = vswprintf_s(buffer, ret, NameFormat, ap);
- va_end(ap);
- if (ret != -1)
- result = mutex_create_new(InitialOwner, buffer);
- free(buffer);
- }
- return result;
-}
diff --git a/src/wufuc/mutexhelper.h b/src/wufuc/mutexhelper.h
deleted file mode 100644
index 0ca26d4..0000000
--- a/src/wufuc/mutexhelper.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName);
-HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...);
diff --git a/src/wufuc/ptrlist.c b/src/wufuc/ptrlist.c
deleted file mode 100644
index 09bb85a..0000000
--- a/src/wufuc/ptrlist.c
+++ /dev/null
@@ -1,403 +0,0 @@
-#include "stdafx.h"
-#include "ptrlist.h"
-
-void ptrlist_lock(ptrlist_t *list)
-{
- EnterCriticalSection(&list->criticalSection);
-}
-
-void ptrlist_unlock(ptrlist_t *list)
-{
- LeaveCriticalSection(&list->criticalSection);
-}
-
-void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag)
-{
- void *result;
-
- ptrlist_lock(list);
- result = list->values[index];
- if ( pTag )
- *pTag = list->tags[index];
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity)
-{
- bool result = false;
- size_t c;
- size_t vsize;
- size_t tsize;
- void *tmp;
-
- if ( !list || capacity > maxCapacity )
- return result;
-
- c = capacity ? capacity :
- (maxCapacity ? min(maxCapacity, 16) : 16);
- vsize = c * (sizeof *list->values);
- tsize = c * (sizeof *list->tags);
-
- InitializeCriticalSection(&list->criticalSection);
- ptrlist_lock(list);
-
- tmp = malloc(vsize + tsize);
- if ( tmp ) {
- ZeroMemory(tmp, vsize + tsize);
- list->values = tmp;
- list->tags = OffsetToPointer(tmp, vsize);
- list->capacity = c;
- list->maxCapacity = maxCapacity;
- list->count = 0;
- result = true;
- }
- ptrlist_unlock(list);
- if ( !result )
- DeleteCriticalSection(&list->criticalSection);
- return result;
-}
-
-void ptrlist_destroy(ptrlist_t *list)
-{
- if ( !list ) return;
-
- ptrlist_lock(list);
-
- free(list->values);
- list->values = NULL;
- list->tags = NULL;
-
- list->count = 0;
- list->capacity = 0;
- list->maxCapacity = 0;
-
- ptrlist_unlock(list);
- DeleteCriticalSection(&list->criticalSection);
-}
-
-size_t ptrlist_index_of(ptrlist_t *list, void *value)
-{
- size_t result = -1;
-
- if ( !list || !value )
- return result;
-
- ptrlist_lock(list);
- for ( size_t i = 0; i < list->count; i++ ) {
- if ( list->values[i] == value ) {
- result = i;
- break;
- }
- }
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag)
-{
- bool result = false;
- size_t newCapacity;
- size_t diff;
- size_t vsize;
- size_t tsize;
- void **tmp1;
- uint32_t *tmp2;
-
- if ( !list || !value )
- return result;
-
- ptrlist_lock(list);
-
- if ( list->count >= list->capacity ) {
- newCapacity = list->count;
- if ( list->maxCapacity ) {
- diff = list->maxCapacity - list->capacity;
- if ( !diff )
- goto leave;
- newCapacity += min(diff, 16);
- } else {
- newCapacity += 16;
- }
- vsize = newCapacity * (sizeof *list->values);
- tsize = newCapacity * (sizeof *list->tags);
-
- tmp1 = malloc(vsize + tsize);
-
- if ( !tmp1 )
- goto leave;
-
- ZeroMemory(tmp1, vsize);
-
- tmp2 = OffsetToPointer(tmp1, vsize);
- ZeroMemory(tmp2, tsize);
-
- if ( memmove_s(tmp1, vsize, list->values, list->count * (sizeof *list->values))
- || memmove_s(tmp2, tsize, list->tags, list->count * (sizeof *list->tags)) ) {
-
- free(tmp1);
- goto leave;
- }
- list->values = tmp1;
- list->tags = tmp2;
- list->capacity = newCapacity;
- }
- list->values[list->count] = value;
- list->tags[list->count] = tag;
- list->count++;
- result = true;
-leave:
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count)
-{
- bool result = true;
-
- if ( !list || !values || !count )
- return false;
-
- ptrlist_lock(list);
- if ( list->count + count <= list->maxCapacity ) {
- for ( size_t i = 0; result && i < count; i++ )
- result = ptrlist_add(list, values[i], tags ? tags[i] : 0);
- } else {
- result = false;
- }
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_remove_at(ptrlist_t *list, size_t index)
-{
- bool result = false;
-
- if ( !list ) return result;
-
- ptrlist_lock(list);
- if ( index <= list->count - 1 ) {
- for ( size_t i = index; i < list->count - 1; i++ )
- list->values[i] = list->values[i + 1];
-
- list->values[list->count--] = NULL;
- result = true;
- }
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_remove(ptrlist_t *list, void *value)
-{
- size_t index;
- bool result = false;
-
- if ( !list || !value )
- return result;
-
- ptrlist_lock(list);
- index = ptrlist_index_of(list, value);
- if ( index != -1 )
- result = ptrlist_remove_at(list, index);
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count)
-{
- bool result = true;
-
- if ( !list || !count )
- return false;
-
- ptrlist_lock(list);
- if ( index <= list->count - 1
- && index + count <= list->count ) {
-
- for ( size_t i = 0; result && i < count; i++ )
- result = ptrlist_remove_at(list, index);
- } else {
- result = false;
- }
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_clear(ptrlist_t *list)
-{
- bool result = false;
-
- if ( !list ) return result;
-
- ptrlist_lock(list);
- result = ptrlist_remove_range(list, 0, list->count);
- ptrlist_unlock(list);
- return result;
-}
-
-size_t ptrlist_get_count(ptrlist_t *list)
-{
- size_t result = -1;
-
- if ( !list ) return result;
-
- ptrlist_lock(list);
- result = list->count;
- ptrlist_unlock(list);
- return result;
-}
-
-size_t ptrlist_get_capacity(ptrlist_t *list)
-{
- size_t result = -1;
-
- if ( !list ) return result;
-
- ptrlist_lock(list);
- result = list->capacity;
- ptrlist_unlock(list);
- return result;
-}
-
-size_t ptrlist_get_max_capacity(ptrlist_t *list)
-{
- size_t result = -1;
-
- if ( !list ) return result;
-
- ptrlist_lock(list);
- result = list->maxCapacity;
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_contains(ptrlist_t *list, void *value)
-{
- return ptrlist_index_of(list, value) != -1;
-}
-
-void **ptrlist_copy_values(ptrlist_t *list, size_t *count)
-{
- void **result = NULL;
- size_t size;
- size_t c;
-
- if ( !list || !count )
- return result;
-
- ptrlist_lock(list);
- c = list->count;
- if ( !c ) goto leave;
-
- size = c * (sizeof *list->values);
- result = malloc(c * (sizeof *list->values));
- if ( result ) {
- if ( !memcpy_s(result, size, list->values, size) ) {
- *count = c;
- } else {
- free(result);
- result = NULL;
- }
- }
-leave:
- ptrlist_unlock(list);
- return result;
-}
-
-uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count)
-{
- uint32_t *result = NULL;
- size_t size;
- size_t c;
-
- if ( !list || !count )
- return result;
-
- ptrlist_lock(list);
- c = list->count;
- if ( !c ) goto leave;
-
- size = c * (sizeof *list->tags);
- result = malloc(c * (sizeof *list->tags));
- if ( result ) {
- if ( !memcpy_s(result, size, list->tags, size) ) {
- *count = c;
- } else {
- free(result);
- result = NULL;
- }
- }
-leave:
- ptrlist_unlock(list);
- return result;
-}
-
-bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count)
-{
- bool result = false;
- void **v;
- uint32_t *t;
- size_t c;
-
- if ( !values || !tags || !count )
- return result;
-
- ptrlist_lock(list);
- v = ptrlist_copy_values(list, &c);
- if ( !v ) goto leave;
-
- t = ptrlist_copy_tags(list, &c);
- if ( !t ) {
- free(v);
- goto leave;
- }
- *values = v;
- *tags = t;
- *count = c;
- result = true;
-leave:
- ptrlist_unlock(list);
- return result;
-}
-
-void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *))
-{
- if ( !list || !f ) return;
-
- ptrlist_lock(list);
- if ( index + count <= list->count ) {
- for ( size_t i = index; i < count; i++ )
- f(list->values[i]);
- }
- ptrlist_unlock(list);
-}
-
-void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *))
-{
- if ( !list || !f ) return;
-
- ptrlist_lock(list);
- ptrlist_for(list, 0, list->count, f);
- ptrlist_unlock(list);
-}
-
-void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *))
-{
- if ( !list || !f ) return;
-
- ptrlist_lock(list);
- if ( index + count <= list->count ) {
- for ( size_t i = index; i < count; i++ )
- f(list->values[i]);
- }
- ptrlist_unlock(list);
-}
-
-void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *))
-{
- if ( !list || !f ) return;
-
- ptrlist_lock(list);
- ptrlist_for_stdcall(list, 0, list->count, f);
- ptrlist_unlock(list);
-}
diff --git a/src/wufuc/ptrlist.h b/src/wufuc/ptrlist.h
deleted file mode 100644
index e14034c..0000000
--- a/src/wufuc/ptrlist.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#pragma pack(push, 1)
-typedef struct ptrlist_t_
-{
- void **values;
- uint32_t *tags;
- size_t capacity;
- size_t maxCapacity;
- size_t count;
- CRITICAL_SECTION criticalSection;
-} ptrlist_t;
-#pragma pack(pop)
-
-void ptrlist_lock(ptrlist_t *list);
-void ptrlist_unlock(ptrlist_t *list);
-void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag);
-bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity);
-void ptrlist_destroy(ptrlist_t *list);
-size_t ptrlist_index_of(ptrlist_t *list, void *value);
-bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag);
-bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count);
-bool ptrlist_remove_at(ptrlist_t *list, size_t index);
-bool ptrlist_remove(ptrlist_t *list, void *value);
-bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count);
-bool ptrlist_clear(ptrlist_t *list);
-size_t ptrlist_get_count(ptrlist_t *list);
-size_t ptrlist_get_capacity(ptrlist_t *list);
-size_t ptrlist_get_max_capacity(ptrlist_t *list);
-bool ptrlist_contains(ptrlist_t *list, void *value);
-void **ptrlist_copy_values(ptrlist_t *list, size_t *count);
-uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count);
-bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count);
-void ptrlist_for(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *));
-void ptrlist_for_each(ptrlist_t *list, void(__cdecl *f)(void *));
-void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *));
-void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *));
diff --git a/src/wufuc/registry.c b/src/wufuc/registry.c
new file mode 100644
index 0000000..8113b0a
--- /dev/null
+++ b/src/wufuc/registry.c
@@ -0,0 +1,22 @@
+#include "stdafx.h"
+#include "registry.h"
+
+DWORD RegGetValueAlloc(PVOID *ppvData, HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwFlags, LPDWORD pdwType)
+{
+ DWORD result;
+ PVOID pvData;
+
+ if ( RegGetValueW(hKey, lpSubKey, lpValueName, dwFlags, pdwType, NULL, &result) != ERROR_SUCCESS )
+ return 0;
+
+ pvData = malloc(result);
+ if ( !pvData ) return 0;
+
+ if ( RegGetValueW(hKey, lpSubKey, lpValueName, dwFlags, pdwType, pvData, &result) == ERROR_SUCCESS ) {
+ *ppvData = pvData;
+ } else {
+ free(pvData);
+ return 0;
+ }
+ return result;
+}
diff --git a/src/wufuc/registry.h b/src/wufuc/registry.h
new file mode 100644
index 0000000..b2a4075
--- /dev/null
+++ b/src/wufuc/registry.h
@@ -0,0 +1,3 @@
+#pragma once
+
+DWORD RegGetValueAlloc(PVOID *ppvData, HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwFlags, LPDWORD pdwType);
diff --git a/src/wufuc/registryhelper.c b/src/wufuc/registryhelper.c
deleted file mode 100644
index 9975c18..0000000
--- a/src/wufuc/registryhelper.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "stdafx.h"
-#include "registryhelper.h"
-
-PVOID reg_get_value_alloc(
- HKEY hKey,
- LPCWSTR SubKey,
- LPCWSTR Value,
- DWORD dwFlags,
- LPDWORD pdwType,
- LPDWORD pcbData)
-{
- DWORD cbData = 0;
- PVOID result = NULL;
-
- if ( RegGetValueW(hKey, SubKey, Value, dwFlags, pdwType, NULL, &cbData) != ERROR_SUCCESS )
- return result;
-
- result = malloc(cbData);
- if ( !result ) return result;
-
- if ( RegGetValueW(hKey, SubKey, Value, dwFlags, pdwType, result, &cbData) == ERROR_SUCCESS ) {
- if ( pcbData )
- *pcbData = cbData;
- } else {
- free(result);
- result = NULL;
- }
- return result;
-}
-
-LPBYTE reg_query_value_alloc(
- HKEY hKey,
- LPCWSTR SubKey,
- LPCWSTR Value,
- LPDWORD pdwType,
- LPDWORD pcbData)
-{
- HKEY hSubKey;
- DWORD cbData = 0;
- DWORD dwType;
- LPBYTE result = NULL;
-
- if ( SubKey && *SubKey ) {
- if ( RegOpenKeyW(hKey, SubKey, &hSubKey) != ERROR_SUCCESS )
- return result;
- } else {
- hSubKey = hKey;
- }
- if ( RegQueryValueExW(hSubKey, Value, NULL, &dwType, result, &cbData) != ERROR_SUCCESS )
- return result;
-
- switch ( dwType ) {
- case REG_SZ:
- case REG_EXPAND_SZ:
- cbData += sizeof UNICODE_NULL;
- break;
- case REG_MULTI_SZ:
- cbData += (sizeof UNICODE_NULL) * 2;
- break;
- }
- result = malloc(cbData);
-
- if ( !result ) return result;
- ZeroMemory(result, cbData);
-
- if ( RegQueryValueExW(hSubKey, Value, NULL, pdwType, result, &cbData) == ERROR_SUCCESS ) {
- if ( pcbData )
- *pcbData = cbData;
- } else {
- free(result);
- result = NULL;
- }
- return result;
-}
-
-PVOID reg_query_key_alloc(
- HANDLE KeyHandle,
- KEY_INFORMATION_CLASS KeyInformationClass,
- PULONG pResultLength)
-{
- NTSTATUS Status;
- ULONG ResultLength;
- PVOID result = NULL;
-
- Status = NtQueryKey(KeyHandle, KeyInformationClass, NULL, 0, &ResultLength);
- if ( Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL )
- return result;
-
- result = malloc(ResultLength);
- if ( !result ) return result;
-
- Status = NtQueryKey(KeyHandle, KeyInformationClass, result, ResultLength, &ResultLength);
- if ( NT_SUCCESS(Status) ) {
- *pResultLength = ResultLength;
- } else {
- free(result);
- result = NULL;
- }
- return result;
-}
-
-LPWSTR env_expand_strings_alloc(LPCWSTR Src, LPDWORD pcchLength)
-{
- LPWSTR result;
- DWORD buffersize;
- DWORD size;
-
- buffersize = ExpandEnvironmentStringsW(Src, NULL, 0);
- result = calloc(buffersize, sizeof *result);
- size = ExpandEnvironmentStringsW(Src, result, buffersize);
- if ( !size || size > buffersize ) {
- free(result);
- result = NULL;
- } else if ( pcchLength ) {
- *pcchLength = buffersize;
- }
- return result;
-}
diff --git a/src/wufuc/registryhelper.h b/src/wufuc/registryhelper.h
deleted file mode 100644
index b452053..0000000
--- a/src/wufuc/registryhelper.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-PVOID reg_get_value_alloc(
- HKEY hkey,
- LPCWSTR pSubKey,
- LPCWSTR pValue,
- DWORD dwFlags,
- LPDWORD pdwType,
- LPDWORD pcbData);
-LPBYTE reg_query_value_alloc(
- HKEY hKey,
- LPCWSTR pSubKey,
- LPCWSTR pValueName,
- LPDWORD pType,
- LPDWORD pcbData);
-PVOID reg_query_key_alloc(
- HANDLE KeyHandle,
- KEY_INFORMATION_CLASS KeyInformationClass,
- PULONG pResultLength);
-LPWSTR env_expand_strings_alloc(LPCWSTR Src, LPDWORD pcchLength);
diff --git a/src/wufuc/resource.h b/src/wufuc/resource.h
index a8ce4af..f161183 100644
--- a/src/wufuc/resource.h
+++ b/src/wufuc/resource.h
@@ -8,11 +8,11 @@
#define BUILD_VERSION_COMMA 1,0,1,0
#endif
-#define S_(x) #x
-#define S(x) S_(x)
+#define STRINGIZE_(x) #x
+#define STRINGIZE(x) STRINGIZE_(x)
-#ifdef X64
+#ifdef _WIN64
#define FILENAME "wufuc64.dll"
-#elif defined(X86)
+#else
#define FILENAME "wufuc32.dll"
#endif
diff --git a/src/wufuc/resource.rc b/src/wufuc/resource.rc
index 3591d7c..172a828 100644
Binary files a/src/wufuc/resource.rc and b/src/wufuc/resource.rc differ
diff --git a/src/wufuc/resourcehelper.c b/src/wufuc/resourcehelper.c
deleted file mode 100644
index 537b733..0000000
--- a/src/wufuc/resourcehelper.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "stdafx.h"
-#include "resourcehelper.h"
-#include "log.h"
-
-void *res_get_version_info(HMODULE hModule)
-{
- HRSRC hResInfo;
- DWORD dwSize;
- HGLOBAL hResData;
- LPVOID pRes;
- void *result;
-
- hResInfo = FindResourceW(hModule,
- MAKEINTRESOURCEW(VS_VERSION_INFO),
- MAKEINTRESOURCEW(RT_VERSION));
- if ( !hResInfo ) return NULL;
-
- dwSize = SizeofResource(hModule, hResInfo);
- if ( !dwSize ) return NULL;
-
- hResData = LoadResource(hModule, hResInfo);
- if ( !hResData ) return NULL;
-
- pRes = LockResource(hResData);
- if ( !pRes ) return NULL;
-
- result = malloc(dwSize);
- if ( !result ) return NULL;
-
- if ( memcpy_s(result, dwSize, pRes, dwSize) ) {
- free(result);
- result = NULL;
- }
- return result;
-}
-
-wchar_t *res_query_string_file_info(const void *pBlock,
- LANGANDCODEPAGE lcp,
- const wchar_t *pszStringName,
- size_t *pcchLength)
-{
- const wchar_t fmt[] = L"\\StringFileInfo\\%04x%04x\\%ls";
- int ret;
- int count;
- wchar_t *pszSubBlock;
- wchar_t *result = NULL;
- UINT uLen;
-
- ret = _scwprintf(fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
- if ( ret == -1 ) return NULL;
-
- count = ret + 1;
- pszSubBlock = calloc(count, sizeof *pszSubBlock);
- if ( !pszSubBlock ) return NULL;
-
- ret = swprintf_s(pszSubBlock, count, fmt, lcp.wLanguage, lcp.wCodePage, pszStringName);
- if ( ret != -1
- && VerQueryValueW(pBlock, pszSubBlock, &(LPVOID)result, &uLen)
- && pcchLength )
- *pcchLength = uLen;
-
- free(pszSubBlock);
- return result;
-}
-
-PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pCount)
-{
- PLANGANDCODEPAGE result = NULL;
- UINT uLen;
-
- if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", &(LPVOID)result, &uLen) )
- *pCount = uLen / (sizeof *result);
- return result;
-}
-
-VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock)
-{
- VS_FIXEDFILEINFO *result;
- UINT uLen;
-
- if ( VerQueryValueW(pBlock, L"\\", &(LPVOID)result, &uLen) )
- return result;
- return NULL;
-}
diff --git a/src/wufuc/resourcehelper.h b/src/wufuc/resourcehelper.h
deleted file mode 100644
index 8710339..0000000
--- a/src/wufuc/resourcehelper.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-typedef struct
-{
- WORD wLanguage;
- WORD wCodePage;
-} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
-
-void *res_get_version_info(HMODULE hModule);
-
-wchar_t *res_query_string_file_info(const void *pBlock,
- LANGANDCODEPAGE lcp,
- const wchar_t *pszStringName,
- size_t *pcchLength);
-
-PLANGANDCODEPAGE res_query_var_file_info(const void *pBlock, size_t *pcbData);
-
-VS_FIXEDFILEINFO *res_query_fixed_file_info(const void *pBlock);
diff --git a/src/wufuc/rundll32.c b/src/wufuc/rundll32.c
index ebd7596..cf1c646 100644
--- a/src/wufuc/rundll32.c
+++ b/src/wufuc/rundll32.c
@@ -1,148 +1,261 @@
#include "stdafx.h"
-#include "callbacks.h"
-#include "eventhelper.h"
-#include "log.h"
-#include "modulehelper.h"
-#include "mutexhelper.h"
-#include "ptrlist.h"
-#include "registryhelper.h"
-#include "servicehelper.h"
-#include "wufuc.h"
+#include "memory.h"
+#include "modules.h"
+#include "patternfind.h"
+#include "registry.h"
+#include "helpers.h"
+#include "versioninfo.h"
-const wchar_t m_szUnloadEventName[] = L"Global\\wufuc_UnloadEvent";
+static BOOL s_bWindowsSevenSP1;
+static BOOL s_bWindowsEightPointOne;
-void CALLBACK RUNDLL32_StartW(HWND hwnd,
- HINSTANCE hinst,
- LPWSTR lpszCmdLine,
- int nCmdShow)
+static LPVOID ResolveAndTranslatePtr(LPVOID lpSrcImageBase, size_t Offset, LPVOID lpDstImageBase)
{
- ptrlist_t list;
- HANDLE hEvent;
- DWORD dwDesiredAccess;
+ LPVOID p = OffsetToPointer(lpSrcImageBase, Offset);
+
+#ifdef _WIN64
+ return OffsetToPointer(lpDstImageBase, PointerToOffset(lpSrcImageBase, OffsetToPointer(p, sizeof(uint32_t) + *(uint32_t *)p)));
+#else
+ return *(LPVOID *)p;
+#endif
+}
+
+static VOID CALLBACK ServiceNotifyCallback(PVOID pParameter)
+{
+ PSERVICE_NOTIFY pNotifyBuffer = pParameter;
+ DWORD dwProcessId = pNotifyBuffer->ServiceStatus.dwProcessId;
+ const DWORD dwDesiredAccess = PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE;
+ LPWSTR fname;
+ HANDLE hProcess;
+ NTSTATUS Status;
+ LPWSTR lpwstrFilename;
+ LPVOID lpData;
+ PLANGANDCODEPAGE lpTranslate;
+ LPWSTR lpInternalName;
+ VS_FIXEDFILEINFO *lpffi;
+ const char *pattern;
+ size_t off1;
+ size_t off2;
+ HMODULE hModule;
+ MODULEINFO modinfo;
+ LPVOID lpBuffer;
+ SIZE_T NumberOfBytesRead;
+ size_t offset;
+ LPVOID lpAddress;
+ BOOL bValue;
+
+ switch ( pNotifyBuffer->dwNotificationStatus ) {
+ case ERROR_SUCCESS:
+ if ( !RegGetValueAlloc(&lpwstrFilename,
+ HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
+ L"ServiceDll",
+ RRF_RT_REG_SZ,
+ NULL) ) {
+ log_gle(L"Failed to get wuauserv ServiceDll value!");
+ break;
+ }
+ if ( !GetFileVersionInfoExAlloc(FILE_VER_GET_NEUTRAL, TRUE, lpwstrFilename, &lpData) ) {
+ log_gle(L"Failed to get file version information: lpwstrFilename=%ls", lpwstrFilename);
+ goto free_lpwstrFilename;
+ }
+ if ( !VerQueryTranslations(lpData, &lpTranslate) ) {
+ log_gle(L"Failed to get resource translations: pBlock=%p", lpData);
+ goto free_lpData;
+ }
+ if ( !VerQueryString(lpData, lpTranslate[0], L"InternalName", &lpInternalName) ) {
+ log_gle(L"Failed to get InternalName resource string: wLanguage=%04x wCodePage=%04x pBlock=%p",
+ lpTranslate[0].wLanguage, lpTranslate[0].wCodePage, lpData);
+ goto free_lpData;
+ }
+ if ( _wcsicmp(lpInternalName, L"wuaueng.dll") ) {
+ log_error(L"InternalName mismatch: lpInternalName=%ls", lpInternalName);
+ goto free_lpData;
+ }
+ if ( !VerQueryFileInfo(lpData, &lpffi) ) {
+ log_gle(L"Failed to get resource file info: pBlock=%p", lpData);
+ goto free_lpData;
+ }
+#ifdef _WIN64
+ if ( (s_bWindowsSevenSP1 && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 6, 7601, 23714) != -1)
+ || (s_bWindowsEightPointOne && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 9, 9600, 18621) != -1) ) {
+ // all x64
+ pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
+ off1 = 0xa;
+ off2 = 0x12;
+ } else goto free_lpData;
+#else
+ if ( s_bWindowsSevenSP1 && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 6, 7601, 23714) != -1 ) {
+ // windows 7 x86
+ pattern = "833D????????00 743E E8???????? A3????????";
+ off1 = 0x2;
+ off2 = 0xf;
+ } else if ( s_bWindowsEightPointOne && vercmp(lpffi->dwProductVersionMS, lpffi->dwProductVersionLS, 7, 9, 9600, 18621) != -1 ) {
+ // windows 8.1 x86
+ pattern = "8BFF 51 833D????????00 7507 A1????????";
+ off1 = 0x5;
+ off2 = 0xd;
+ } else goto free_lpData;
+#endif
+ fname = PathFindFileNameW(lpwstrFilename);
+ log_info(L"Supported version of %ls: %hu.%hu.%hu.%hu",
+ fname,
+ HIWORD(lpffi->dwProductVersionMS), LOWORD(lpffi->dwProductVersionMS),
+ HIWORD(lpffi->dwProductVersionLS), LOWORD(lpffi->dwProductVersionLS));
+
+ hProcess = OpenProcess(dwDesiredAccess, FALSE, dwProcessId);
+ if ( !hProcess ) {
+ log_gle(L"Failed to open target process: dwProcessId=%lu", dwProcessId);
+ goto free_lpData;
+ }
+ Status = NtSuspendProcess(hProcess);
+ if ( Status != STATUS_SUCCESS ) {
+ log_error(L"Failed to suspend target process: hProcess=%p (Status=%ld)", hProcess, Status);
+ goto close_hProcess;
+ }
+ hModule = Toolhelp32GetModuleHandle(dwProcessId, lpwstrFilename);
+ if ( !hModule ) {
+ log_gle(L"Failed to find target module in Toolhelp32 snapshot: th32ProcessId=%lu lpModuleName=%ls",
+ dwProcessId, lpwstrFilename);
+ goto resume_hProcess;
+ }
+ if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
+ log_error(L"Failed to get target module information: hProcess=%p hModule=%p", hProcess, hModule);
+ goto resume_hProcess;
+ }
+ lpBuffer = malloc(modinfo.SizeOfImage);
+ if ( !lpBuffer ) {
+ log_error(L"Failed to allocate memory for lpBuffer!");
+ goto resume_hProcess;
+ }
+ if ( !ReadProcessMemory(hProcess, modinfo.lpBaseOfDll, lpBuffer, modinfo.SizeOfImage, &NumberOfBytesRead) ) {
+ log_gle(L"Failed to read target process memory: hProcess=%p lpBaseAddress=%p nSize=%lu",
+ hProcess, modinfo.lpBaseOfDll, modinfo.SizeOfImage);
+ goto free_lpBuffer;
+ }
+ offset = patternfind(lpBuffer, NumberOfBytesRead, pattern);
+ if ( offset == -1 ) {
+ log_error(L"Failed to find IsDeviceServiceable pattern!");
+ goto free_lpBuffer;
+ }
+ log_info(L"Found IsDeviceServiceable function offset: %ls+0x%Ix", fname, offset);
+
+ lpAddress = ResolveAndTranslatePtr(lpBuffer, offset + off1, modinfo.lpBaseOfDll);
+ bValue = FALSE;
+ if ( WriteProcessMemory(hProcess, lpAddress, &bValue, sizeof bValue, NULL) )
+ log_info(L"Successfully wrote value to target process: lpAddress=%p", lpAddress);
+ else
+ log_gle(L"Failed to write value to target process: lpAddress=%p!", lpAddress);
+
+ lpAddress = ResolveAndTranslatePtr(lpBuffer, offset + off2, modinfo.lpBaseOfDll);
+ bValue = TRUE;
+ if ( WriteProcessMemory(hProcess, lpAddress, &bValue, sizeof bValue, NULL) )
+ log_info(L"Successfully wrote value to target process: lpAddress=%p", lpAddress);
+ else
+ log_gle(L"Failed to patch flag in target process at address %p!", lpAddress);
+free_lpBuffer:
+ free(lpBuffer);
+resume_hProcess:
+ NtResumeProcess(hProcess);
+close_hProcess:
+ CloseHandle(hProcess);
+free_lpData:
+ free(lpData);
+free_lpwstrFilename:
+ free(lpwstrFilename);
+ break;
+ case ERROR_SERVICE_MARKED_FOR_DELETE:
+ *(bool *)pNotifyBuffer->pContext = true;
+ break;
+ }
+ if ( pNotifyBuffer->pszServiceNames )
+ LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
+}
+
+void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
+{
+ HANDLE hMutex;
+ HANDLE hUnloadEvent;
bool Lagging;
SC_HANDLE hSCM;
SC_HANDLE hService;
- DWORD dwProcessId;
SERVICE_NOTIFYW NotifyBuffer;
- bool Unloading = false;
- DWORD e;
- void **values;
- uint32_t *tags;
- size_t count;
- DWORD r;
- size_t index;
- size_t crashes = 0;
- bool Suspending = false;
+ DWORD Error;
- g_hMainMutex = mutex_create_new(true,
- L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
- if ( !g_hMainMutex ) return;
-
- if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) goto release_mutex;
-
- hEvent = event_create_with_string_security_descriptor(
- true, false, m_szUnloadEventName, L"D:(A;;0x001F0003;;;BA)");
- if ( !hEvent ) goto destroy_list;
- if ( !ptrlist_add(&list, hEvent, 0) ) goto set_event;
-
- dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
+ hMutex = CreateNewMutex(NULL, TRUE, L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
+ if ( !hMutex ) {
+ log_error(L"Failed to create instance mutex!");
+ return;
+ }
+ hUnloadEvent = CreateEventWithStringSecurityDescriptor(L"D:(A;;0x001F0003;;;BA)",
+ TRUE, FALSE, L"Global\\wufuc_UnloadEvent");
+ if ( !hUnloadEvent ) {
+ log_gle(L"Failed to create unload event!");
+ goto release_mutex;
+ }
+ s_bWindowsSevenSP1 = VerifyVersionInfoHelper(6, 1, 1);
+ if ( !s_bWindowsSevenSP1 ) {
+ s_bWindowsEightPointOne = VerifyVersionInfoHelper(6, 3, 0);
+ if ( !s_bWindowsEightPointOne ) {
+ log_error(L"Unsupported operating system!");
+ goto close_event;
+ }
+ }
do {
Lagging = false;
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
- if ( !hSCM ) goto set_event;
+ if ( !hSCM ) break;
- hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess);
- if ( !hService ) goto close_scm;
-
- if ( (dwDesiredAccess & SERVICE_QUERY_CONFIG) == SERVICE_QUERY_CONFIG ) {
- dwDesiredAccess &= ~SERVICE_QUERY_CONFIG;
-
- dwProcessId = svc_heuristic_process_id(hSCM, hService);
- if ( dwProcessId )
- wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)thread_start_callback, &list);
+ hService = OpenServiceW(hSCM, L"wuauserv", SERVICE_QUERY_STATUS);
+ if ( !hService ) {
+ CloseServiceHandle(hSCM);
+ break;
}
ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer);
NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
- NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)service_notify_callback;
- NotifyBuffer.pContext = (PVOID)&list;
- while ( !Unloading && !Lagging ) {
- e = NotifyServiceStatusChangeW(hService,
+ NotifyBuffer.pfnNotifyCallback = ServiceNotifyCallback;
+ NotifyBuffer.pContext = &Lagging;
+
+ while ( true ) {
+ Error = NotifyServiceStatusChangeW(hService,
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
&NotifyBuffer);
- switch ( e ) {
+ switch ( Error ) {
case ERROR_SUCCESS:
do {
- if ( !ptrlist_copy(&list, &values, &tags, &count) ) {
- Unloading = true;
- break;
+ Error = WaitForSingleObjectEx(hUnloadEvent, INFINITE, TRUE);
+ switch ( Error ) {
+ case WAIT_OBJECT_0:
+ log_info(L"Unload event signaled!");
+ goto exit_loop;
+ case WAIT_FAILED:
+ log_error(L"WaitForSingleObjectEx failed! Error=%lu", Error);
+ goto exit_loop;
}
- r = WaitForMultipleObjectsEx((DWORD)count,
- values, FALSE, INFINITE, TRUE);
-
- if ( r >= WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + count ) {
- // object signaled
- index = r - WAIT_OBJECT_0;
- if ( !index ) {
- // Unload event
- Unloading = true;
- } else {
- // crash mutex was released cleanly
- ptrlist_remove(&list, values[index]);
- ReleaseMutex(values[index]);
- CloseHandle(values[index]);
- }
- } else if ( r >= WAIT_ABANDONED_0 && r < WAIT_ABANDONED_0 + count ) {
- // object abandoned
- // crash mutex was abandoned, process has most likely crashed.
- index = r - WAIT_ABANDONED_0;
-
- ptrlist_remove(&list, values[index]);
- ReleaseMutex(values[index]);
- CloseHandle(values[index]);
-
- crashes++;
- log_warning(L"A process wufuc injected into has crashed %Iu time%ls! (ProcessId=%lu)",
- crashes, crashes != 1 ? L"s" : L"", tags[index]);
-
- if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
- log_error(L"Crash threshold has been reached, disabling wufuc until next reboot!");
- Unloading = true;
- Suspending = true;
- }
- } else if ( r == WAIT_FAILED ) {
- log_error(L"Wait function failed!");
- Unloading = true;
- }
- free(values);
- free(tags);
- } while ( r != WAIT_IO_COMPLETION && !Unloading );
+ } while ( Error != WAIT_IO_COMPLETION );
break;
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
- log_warning(L"Client lagging!");
+ log_warning(L"The service notification client is lagging too far behind the current state of services in the machine.");
Lagging = true;
- break;
+ goto exit_loop;
+ case ERROR_SERVICE_MARKED_FOR_DELETE:
+ log_warning(L"The specified service has been marked for deletion.");
+ Lagging = true;
+ goto exit_loop;
default:
- log_error(L"NotifyServiceStatusChange failed! (Return value=%lu)", e);
- Unloading = true;
- break;
+ log_error(L"NotifyServiceStatusChange failed! Error=%lu", Error);
+ goto exit_loop;
}
}
+exit_loop:
CloseServiceHandle(hService);
-close_scm:
CloseServiceHandle(hSCM);
} while ( Lagging );
-set_event:
- // signal event in case it is open in any other processes
- SetEvent(hEvent);
-destroy_list:
- ptrlist_for_each_stdcall(&list, CloseHandle);
- ptrlist_destroy(&list);
-
- if ( Suspending )
- NtSuspendProcess(NtCurrentProcess());
+close_event:
+ CloseHandle(hUnloadEvent);
release_mutex:
- ReleaseMutex(g_hMainMutex);
- CloseHandle(g_hMainMutex);
+ ReleaseMutex(hMutex);
+ CloseHandle(hMutex);
}
void CALLBACK RUNDLL32_UnloadW(
@@ -153,7 +266,7 @@ void CALLBACK RUNDLL32_UnloadW(
{
HANDLE hEvent;
- hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, m_szUnloadEventName);
+ hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
if ( hEvent ) {
SetEvent(hEvent);
CloseHandle(hEvent);
diff --git a/src/wufuc/servicehelper.c b/src/wufuc/servicehelper.c
deleted file mode 100644
index 0e94113..0000000
--- a/src/wufuc/servicehelper.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "stdafx.h"
-#include "servicehelper.h"
-#include "registryhelper.h"
-
-LPQUERY_SERVICE_CONFIGW svc_query_config_by_name_alloc(
- SC_HANDLE hSCM,
- const wchar_t *pServiceName,
- LPDWORD pcbBufSize)
-{
- SC_HANDLE hService;
- LPQUERY_SERVICE_CONFIGW result = NULL;
-
- hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_CONFIG);
- if ( !hService ) return result;
-
- result = svc_query_config_alloc(hSCM, hService, pcbBufSize);
-
- CloseServiceHandle(hService);
- return result;
-}
-
-LPQUERY_SERVICE_CONFIGW svc_query_config_alloc(
- SC_HANDLE hSCM,
- SC_HANDLE hService,
- LPDWORD pcbBufSize)
-{
- DWORD cbBytesNeeded;
- LPQUERY_SERVICE_CONFIGW result = NULL;
-
- if ( !QueryServiceConfigW(hService, NULL, 0, &cbBytesNeeded)
- && GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
-
- result = malloc(cbBytesNeeded);
- if ( result ) {
- if ( QueryServiceConfigW(hService, result, cbBytesNeeded, &cbBytesNeeded) ) {
- if ( pcbBufSize )
- *pcbBufSize = cbBytesNeeded;
- } else {
- free(result);
- result = NULL;
- }
- }
- }
- return result;
-}
-
-bool svc_query_process_info_by_name(
- SC_HANDLE hSCM,
- const wchar_t *pServiceName,
- LPSERVICE_STATUS_PROCESS pServiceStatus)
-{
- bool result = false;
- SC_HANDLE hService;
- DWORD cbBytesNeeded;
-
- hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS);
- if ( !hService )
- return result;
-
- result = !!QueryServiceStatusEx(hService,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE)pServiceStatus,
- sizeof *pServiceStatus,
- &cbBytesNeeded);
- CloseServiceHandle(hService);
- return result;
-}
-
-bool svc_query_group_name(
- const LPQUERY_SERVICE_CONFIGW pServiceConfig,
- wchar_t **pGroupName,
- HLOCAL *hMem)
-{
- bool result = false;
- int NumArgs;
- wchar_t **argv;
-
- argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs);
- if ( argv ) {
- if ( !_wcsicmp(PathFindFileNameW(argv[0]), L"svchost.exe") ) {
-
- for ( int i = 1; (i + 1) < NumArgs; i++ ) {
- if ( !_wcsicmp(argv[i], L"-k") ) {
- *pGroupName = argv[++i];
- *hMem = (HLOCAL)argv;
- return true;
- }
- }
- }
- LocalFree((HLOCAL)argv);
- }
- return false;
-}
-
-DWORD svc_query_process_id(SC_HANDLE hSCM, SC_HANDLE hService)
-{
- DWORD result = 0;
- SERVICE_STATUS_PROCESS ServiceStatus;
- DWORD cbBytesNeeded;
-
- if ( QueryServiceStatusEx(hService,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE)&ServiceStatus,
- sizeof ServiceStatus,
- &cbBytesNeeded) ) {
-
- result = ServiceStatus.dwProcessId;
- }
- return result;
-}
-
-DWORD svc_query_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName)
-{
- SERVICE_STATUS_PROCESS ServiceStatusProcess;
-
- if ( svc_query_process_info_by_name(hSCM, pServiceName, &ServiceStatusProcess) )
- return ServiceStatusProcess.dwProcessId;
- return 0;
-}
-
-DWORD svc_heuristic_group_process_id(SC_HANDLE hSCM, const wchar_t *pGroupNameSearch)
-{
- wchar_t *pData;
- DWORD result = 0;
- DWORD dwProcessId;
- DWORD cbBufSize;
- LPQUERY_SERVICE_CONFIGW pServiceConfig;
- bool success = false;
- wchar_t *pGroupName;
- HLOCAL hMem;
-
- pData = reg_get_value_alloc(HKEY_LOCAL_MACHINE,
- L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
- pGroupNameSearch,
- RRF_RT_REG_MULTI_SZ,
- NULL,
- NULL);
-
- if ( !pData ) return result;
-
- for ( wchar_t *pName = pData; *pName; pName += wcslen(pName) + 1 ) {
- dwProcessId = svc_query_process_id_by_name(hSCM, pName);
- if ( !dwProcessId ) continue;
-
- pServiceConfig = svc_query_config_by_name_alloc(hSCM, pName, &cbBufSize);
- if ( !pServiceConfig ) continue;
-
- if ( pServiceConfig->dwServiceType == SERVICE_WIN32_SHARE_PROCESS
- && svc_query_group_name(pServiceConfig, &pGroupName, &hMem) ) {
-
- success = !_wcsicmp(pGroupNameSearch, pGroupName);
- LocalFree(hMem);
- }
- free(pServiceConfig);
- if ( success ) {
- result = dwProcessId;
- break;
- }
- }
- free(pData);
- return result;
-}
-
-DWORD svc_heuristic_process_id(SC_HANDLE hSCM, SC_HANDLE hService)
-{
- DWORD result = 0;
- LPQUERY_SERVICE_CONFIGW pServiceConfig;
- wchar_t *pGroupName;
- HLOCAL hMem;
-
- result = svc_query_process_id(hSCM, hService);
- if ( result )
- return result;
-
- pServiceConfig = svc_query_config_alloc(hSCM, hService, NULL);
- if ( pServiceConfig ) {
- switch ( pServiceConfig->dwServiceType ) {
- case SERVICE_WIN32_OWN_PROCESS:
- // if the service isn't already running there's no
- // way to accurately guess the PID when it is set to
- // run in its own process. returns 0
- break;
- case SERVICE_WIN32_SHARE_PROCESS:
- // when the service is configured to run in a shared
- // process, it is possible to "guess" which svchost.exe
- // it will eventually be loaded into by finding other
- // services in the same group that are already running.
- if ( svc_query_group_name(pServiceConfig, &pGroupName, &hMem) ) {
- result = svc_heuristic_group_process_id(hSCM, pGroupName);
- LocalFree(hMem);
- }
- break;
- }
- free(pServiceConfig);
- }
- return result;
-}
-
-DWORD svc_heuristic_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName)
-{
- DWORD result = 0;
- SC_HANDLE hService;
-
- hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
- result = svc_heuristic_process_id(hSCM, hService);
- CloseServiceHandle(hService);
- return result;
-
-}
diff --git a/src/wufuc/servicehelper.h b/src/wufuc/servicehelper.h
deleted file mode 100644
index 7342705..0000000
--- a/src/wufuc/servicehelper.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-LPQUERY_SERVICE_CONFIGW svc_query_config_by_name_alloc(
- SC_HANDLE hSCM,
- const wchar_t *pServiceName,
- LPDWORD pcbBufSize);
-LPQUERY_SERVICE_CONFIGW svc_query_config_alloc(
- SC_HANDLE hSCM,
- SC_HANDLE hService,
- LPDWORD pcbBufSize);
-bool svc_query_process_info_by_name(
- SC_HANDLE hSCM,
- const wchar_t *pServiceName,
- LPSERVICE_STATUS_PROCESS pServiceStatus);
-bool svc_query_group_name(
- const LPQUERY_SERVICE_CONFIGW pServiceConfig,
- wchar_t **pGroupName,
- HLOCAL *hMem);
-DWORD svc_query_process_id(SC_HANDLE hSCM, SC_HANDLE hService);
-DWORD svc_query_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName);
-DWORD svc_heuristic_group_process_id(SC_HANDLE hSCM, const wchar_t *pGroupName);
-DWORD svc_heuristic_process_id(SC_HANDLE hSCM, SC_HANDLE hService);
-DWORD svc_heuristic_process_id_by_name(SC_HANDLE hSCM, const wchar_t *pServiceName);
diff --git a/src/wufuc/stdafx.h b/src/wufuc/stdafx.h
index 4052852..8ae9b6f 100644
--- a/src/wufuc/stdafx.h
+++ b/src/wufuc/stdafx.h
@@ -11,15 +11,12 @@
#include
#include
-
-
// TODO: reference additional headers your program requires here
#include
#include
#include
#include
#include
-#include
#include
#include
@@ -27,6 +24,10 @@
#include
#include
+#include "asprintf.h"
+#include "logger.h"
+
extern IMAGE_DOS_HEADER __ImageBase;
#define PIMAGEBASE ((HMODULE)&__ImageBase)
#define OffsetToPointer(Base, Offset) ((void *)(((uint8_t *)(Base)) + ((ptrdiff_t)(Offset))))
+#define PointerToOffset(Base, Pointer) ((ptrdiff_t)(((uint8_t *)(Pointer)) - ((uint8_t *)(Base))))
diff --git a/src/wufuc/utf8.c b/src/wufuc/utf8.c
new file mode 100644
index 0000000..26632c1
--- /dev/null
+++ b/src/wufuc/utf8.c
@@ -0,0 +1,26 @@
+#include "stdafx.h"
+#include "utf8.h"
+
+DWORD UTF8WriteFile(HANDLE hFile, LPCWSTR lpWideCharStr)
+{
+ int cchWideChar;
+ int size;
+ char *buffer;
+ DWORD NumberOfBytesWritten = 0;
+
+ cchWideChar = lstrlenW(lpWideCharStr);
+
+ size = WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL);
+ if ( !size )
+ return 0;
+
+ buffer = malloc(size);
+ if ( !buffer )
+ return 0;
+
+ if ( WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, cchWideChar, buffer, size, NULL, NULL) )
+ WriteFile(hFile, buffer, size, &NumberOfBytesWritten, NULL);
+
+ free(buffer);
+ return NumberOfBytesWritten;
+}
diff --git a/src/wufuc/utf8.h b/src/wufuc/utf8.h
new file mode 100644
index 0000000..415f47f
--- /dev/null
+++ b/src/wufuc/utf8.h
@@ -0,0 +1,3 @@
+#pragma once
+
+DWORD UTF8WriteFile(HANDLE hFile, LPCWSTR lpWideCharStr);
\ No newline at end of file
diff --git a/src/wufuc/versionhelper.c b/src/wufuc/versionhelper.c
deleted file mode 100644
index 86fe01e..0000000
--- a/src/wufuc/versionhelper.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "stdafx.h"
-#include "versionhelper.h"
-
-int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev)
-{
- if ( HIWORD(pffi->dwProductVersionMS) < wMajor ) return -1;
- if ( HIWORD(pffi->dwProductVersionMS) > wMajor ) return 1;
- if ( LOWORD(pffi->dwProductVersionMS) < wMinor ) return -1;
- if ( LOWORD(pffi->dwProductVersionMS) > wMinor ) return 1;
- if ( HIWORD(pffi->dwProductVersionLS) < wBuild ) return -1;
- if ( HIWORD(pffi->dwProductVersionLS) > wBuild ) return 1;
- if ( LOWORD(pffi->dwProductVersionLS) < wRev ) return -1;
- if ( LOWORD(pffi->dwProductVersionLS) > wRev ) return 1;
- return 0;
-}
-
-bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
-{
- DWORDLONG dwlConditionMask = 0;
- OSVERSIONINFOEXW osvi = { sizeof osvi };
-
- VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
-
- osvi.dwMajorVersion = wMajorVersion;
- osvi.dwMinorVersion = wMinorVersion;
- osvi.wServicePackMajor = wServicePackMajor;
-
- return VerifyVersionInfoW(&osvi,
- VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
- dwlConditionMask) != FALSE;
-}
diff --git a/src/wufuc/versionhelper.h b/src/wufuc/versionhelper.h
deleted file mode 100644
index 11b1226..0000000
--- a/src/wufuc/versionhelper.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
-bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);
diff --git a/src/wufuc/versioninfo.c b/src/wufuc/versioninfo.c
new file mode 100644
index 0000000..cda1cc5
--- /dev/null
+++ b/src/wufuc/versioninfo.c
@@ -0,0 +1,130 @@
+#include "stdafx.h"
+#include "versioninfo.h"
+
+DWORD GetModuleVersionInfo(HMODULE hModule, LPVOID *lplpData)
+{
+ HRSRC hResInfo;
+ DWORD result;
+ HGLOBAL hResData;
+ LPVOID pRes;
+ LPVOID lpData;
+
+ hResInfo = FindResourceW(hModule,
+ MAKEINTRESOURCEW(VS_VERSION_INFO),
+ MAKEINTRESOURCEW(RT_VERSION));
+ if ( !hResInfo ) return 0;
+
+ result = SizeofResource(hModule, hResInfo);
+ if ( !result ) return 0;
+
+ hResData = LoadResource(hModule, hResInfo);
+ if ( !hResData ) return 0;
+
+ pRes = LockResource(hResData);
+ if ( !pRes ) return 0;
+
+ lpData = malloc(result);
+ if ( !lpData ) return 0;
+
+ if ( !memcpy_s(lpData, result, pRes, result) ) {
+ *lplpData = lpData;
+ } else {
+ free(lpData);
+ return 0;
+ }
+ return result;
+}
+
+DWORD GetFileVersionInfoExAlloc(DWORD dwFlags, BOOL bPrefetched, LPCWSTR lpwstrFilename, LPVOID *lplpData)
+{
+ DWORD result;
+ DWORD dwHandle;
+ LPVOID lpData;
+
+ result = GetFileVersionInfoSizeExW(dwFlags,
+ lpwstrFilename,
+ &dwHandle);
+ if ( !result ) return 0;
+
+ lpData = malloc(result);
+ if ( !lpData ) return 0;
+
+ if ( GetFileVersionInfoExW(bPrefetched ? (dwFlags | FILE_VER_GET_PREFETCHED) : dwFlags,
+ lpwstrFilename,
+ dwHandle,
+ result,
+ lpData) ) {
+ *lplpData = lpData;
+ } else {
+ free(lpData);
+ return 0;
+ }
+ return result;
+}
+
+UINT VerQueryString(LPCVOID pBlock, LANGANDCODEPAGE LangCodePage, LPCWSTR lpName, LPWSTR *lplpString)
+{
+ LPWSTR pszSubBlock;
+ LPVOID lpBuffer;
+ UINT result = 0;
+
+ if ( aswprintf(&pszSubBlock,
+ L"\\StringFileInfo\\%04x%04x\\%ls",
+ LangCodePage.wLanguage,
+ LangCodePage.wCodePage,
+ lpName) == -1 )
+ return 0;
+
+ if ( VerQueryValueW(pBlock, pszSubBlock, &lpBuffer, &result) )
+ *lplpString = (LPWSTR)lpBuffer;
+
+ free(pszSubBlock);
+ return result;
+}
+
+UINT VerQueryTranslations(LPCVOID pBlock, PLANGANDCODEPAGE *lplpTranslate)
+{
+ PLANGANDCODEPAGE lpTranslate;
+ UINT uLen;
+
+ if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", &(LPVOID)lpTranslate, &uLen) ) {
+ *lplpTranslate = lpTranslate;
+ return uLen / (sizeof *lpTranslate);
+ }
+ return 0;
+}
+
+UINT VerQueryFileInfo(LPCVOID pBlock, VS_FIXEDFILEINFO **lplpffi)
+{
+ VS_FIXEDFILEINFO *lpffi;
+ UINT result;
+
+ if ( VerQueryValueW(pBlock, L"\\", &(LPVOID)lpffi, &result) ) {
+ *lplpffi = lpffi;
+ return result;
+ }
+ return 0;
+}
+
+int vercmp(DWORD dwMS, DWORD dwLS, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev)
+{
+ WORD w;
+
+ w = HIWORD(dwMS);
+ if ( w < wMajor ) return -1;
+ if ( w > wMajor ) return 1;
+
+ w = LOWORD(dwMS);
+ if ( w < wMinor ) return -1;
+ if ( w > wMinor ) return 1;
+
+ w = HIWORD(dwLS);
+ if ( w < wBuild ) return -1;
+ if ( w > wBuild ) return 1;
+
+ w = LOWORD(dwLS);
+ if ( w < wRev ) return -1;
+ if ( w > wRev ) return 1;
+
+ return 0;
+}
diff --git a/src/wufuc/versioninfo.h b/src/wufuc/versioninfo.h
new file mode 100644
index 0000000..b8105bf
--- /dev/null
+++ b/src/wufuc/versioninfo.h
@@ -0,0 +1,19 @@
+#pragma once
+
+typedef struct
+{
+ WORD wLanguage;
+ WORD wCodePage;
+} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
+
+DWORD GetModuleVersionInfo(HMODULE hModule, LPVOID *lplpData);
+
+DWORD GetFileVersionInfoExAlloc(DWORD dwFlags, BOOL bPrefetched, LPCWSTR lpwstrFilename, LPVOID *lplpData);
+
+UINT VerQueryString(LPCVOID pBlock, LANGANDCODEPAGE LangCodePage, LPCWSTR lpName, LPWSTR *lplpString);
+
+UINT VerQueryTranslations(LPCVOID pBlock, PLANGANDCODEPAGE *lplpTranslate);
+
+UINT VerQueryFileInfo(LPCVOID pBlock, VS_FIXEDFILEINFO **lplpffi);
+
+int vercmp(DWORD dwMS, DWORD dwLS, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
diff --git a/src/wufuc/wufuc.c b/src/wufuc/wufuc.c
deleted file mode 100644
index c28d3ab..0000000
--- a/src/wufuc/wufuc.c
+++ /dev/null
@@ -1,222 +0,0 @@
-#include "stdafx.h"
-#include "ptrlist.h"
-#include "wufuc.h"
-#include "hooks.h"
-#include "log.h"
-#include "modulehelper.h"
-#include "mutexhelper.h"
-#include "patternfind.h"
-#include "resourcehelper.h"
-#include "versionhelper.h"
-
-#include
-
-HANDLE g_hMainMutex;
-
-static bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
-{
- bool result = false;
- DWORD ExitCode;
- HANDLE hThread;
-
- hThread = CreateRemoteThread(hProcess,
- NULL,
- 0,
- (LPTHREAD_START_ROUTINE)CloseHandle,
- (LPVOID)hObject,
- 0,
- NULL);
- if ( hThread ) {
- if ( WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0
- && GetExitCodeThread(hThread, &ExitCode) ) {
-
- result = !!ExitCode;
- }
- CloseHandle(hThread);
- }
- return result;
-}
-
-bool wufuc_inject(DWORD dwProcessId,
- LPTHREAD_START_ROUTINE pStartAddress,
- ptrlist_t *list)
-{
- bool result = false;
- HANDLE hCrashMutex;
- HANDLE hProcess;
- HANDLE h;
- HANDLE hProceedEvent;
- HANDLE p[4];
-
- hCrashMutex = mutex_create_new_fmt(false, L"Global\\wufuc_CrashMutex*%08x", dwProcessId);
- if ( !hCrashMutex ) return result;
- if ( !ptrlist_add(list, hCrashMutex, dwProcessId) )
- goto close_mutex;
-
- hProceedEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
- if ( !hProceedEvent ) goto close_mutex;
-
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
- if ( !hProcess ) goto close_pevent;
-
- h = GetCurrentProcess();
- if ( !DuplicateHandle(h, g_hMainMutex, hProcess, &p[0], SYNCHRONIZE, FALSE, 0) )
- goto close_process;
- if ( !DuplicateHandle(h, ptrlist_at(list, 0, NULL), hProcess, &p[1], SYNCHRONIZE, FALSE, 0) )
- goto close_p0;
- if ( !DuplicateHandle(h, hCrashMutex, hProcess, &p[2], 0, FALSE, DUPLICATE_SAME_ACCESS) )
- goto close_p1;
- if ( !DuplicateHandle(h, hProceedEvent, hProcess, &p[3], EVENT_MODIFY_STATE, FALSE, 0) )
- goto close_p2;
-
- result = mod_inject_and_begin_thread(hProcess, PIMAGEBASE, pStartAddress, p, sizeof p);
-
- if ( result ) {
- // wait for injected thread to signal that it has taken
- // ownership of hCrashMutex before proceeding.
- result = WaitForSingleObject(hProceedEvent, 5000) != WAIT_TIMEOUT;
- } else {
- close_remote_handle(hProcess, p[3]);
-close_p2:
- close_remote_handle(hProcess, p[2]);
-close_p1:
- close_remote_handle(hProcess, p[1]);
-close_p0:
- close_remote_handle(hProcess, p[0]);
- }
-close_process:
- CloseHandle(hProcess);
-close_pevent:
- CloseHandle(hProceedEvent);
- if ( !result ) {
-close_mutex:
- ptrlist_remove(list, hCrashMutex);
- CloseHandle(hCrashMutex);
- }
- if ( result )
- log_info(L"Successfully injected into process! (ProcessId=%lu)", dwProcessId);
- else
- log_warning(L"Failed to inject into process! (ProcessId=%lu)", dwProcessId);
- return result;
-}
-
-static bool wufuc_get_patch_info(VS_FIXEDFILEINFO *pffi, PATCHINFO *ppi)
-{
-#ifdef _WIN64
- if ( ver_verify_version_info(6, 1, 1) && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1
- || ver_verify_version_info(6, 3, 0) && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
-
- ppi->pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
- ppi->off1 = 0xa;
- ppi->off2 = 0x12;
- return true;
- }
-#elif _WIN32
- if ( ver_verify_version_info(6, 1, 1)
- && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1 ) {
-
- ppi->pattern = "833D????????00 743E E8???????? A3????????";
- ppi->off1 = 0x2;
- ppi->off2 = 0xf;
- return true;
- } else if ( ver_verify_version_info(6, 3, 0)
- && ver_compare_product_version(pffi, 7, 9, 9600, 18621) != -1 ) {
-
- ppi->pattern = "8BFF 51 833D????????00 7507 A1????????";
- ppi->off1 = 0x5;
- ppi->off2 = 0xd;
- return true;
- }
-#endif
- return false;
-}
-
-static bool wufuc_get_patch_ptrs(const PATCHINFO *ppi, uintptr_t pfn, PBOOL *ppval1, PBOOL *ppval2)
-{
-#ifdef _WIN64
- *ppval1 = (PBOOL)(pfn + ppi->off1 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off1));
- *ppval2 = (PBOOL)(pfn + ppi->off2 + sizeof(uint32_t) + *(uint32_t *)(pfn + ppi->off2));
- return true;
-#elif _WIN32
- *ppval1 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off1));
- *ppval2 = (PBOOL)(*(uintptr_t *)(pfn + ppi->off2));
- return true;
-#else
- return false;
-#endif
-}
-
-void wufuc_patch(HMODULE hModule)
-{
- void *pBlock;
- PATCHINFO pi;
- size_t count;
- PLANGANDCODEPAGE plcp;
- wchar_t *pInternalName;
- VS_FIXEDFILEINFO *pffi;
- MODULEINFO modinfo;
- size_t offset;
- void *pfn;
- DWORD fOldProtect;
- PBOOL pval1;
- PBOOL pval2;
-
- pBlock = res_get_version_info(hModule);
- if ( !pBlock ) return;
-
- plcp = res_query_var_file_info(pBlock, &count);
- if ( !plcp ) goto free_pBlock;
-
- for ( size_t i = 0; i < count; i++ ) {
- pInternalName = res_query_string_file_info(pBlock, plcp[i], L"InternalName", NULL);
- if ( pInternalName && !_wcsicmp(pInternalName, L"wuaueng.dll") )
- goto cont_patch;
- }
- goto free_pBlock;
-
-cont_patch:
- pffi = res_query_fixed_file_info(pBlock);
- if ( !pffi ) goto free_pBlock;
-
- if ( !wufuc_get_patch_info(pffi, &pi) ) {
- log_warning(L"Unsupported Windows Update Agent version: %hu.%hu.%hu.%hu",
- HIWORD(pffi->dwProductVersionMS),
- LOWORD(pffi->dwProductVersionMS),
- HIWORD(pffi->dwProductVersionLS),
- LOWORD(pffi->dwProductVersionLS));
- goto free_pBlock;
- }
- log_info(L"Supported Windows Update Agent version: %hu.%hu.%hu.%hu",
- HIWORD(pffi->dwProductVersionMS),
- LOWORD(pffi->dwProductVersionMS),
- HIWORD(pffi->dwProductVersionLS),
- LOWORD(pffi->dwProductVersionLS));
-
- if ( !GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof modinfo) ) {
- log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)", hModule, GetLastError());
- goto free_pBlock;
- }
- offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, pi.pattern);
- if ( offset == -1 ) {
- log_info(L"Couldn't match IsDeviceServiceable function!");
- goto free_pBlock;
- }
- pfn = OffsetToPointer(modinfo.lpBaseOfDll, offset);
- log_info(L"Matched %ls!IsDeviceServiceable function! (Offset=%IX, Address=%p)",
- PathFindFileNameW(g_pszWUServiceDll), offset, pfn);
-
- if ( wufuc_get_patch_ptrs(&pi, (uintptr_t)pfn, &pval1, &pval2) ) {
- if ( *pval1 && VirtualProtect(pval1, sizeof *pval1, PAGE_READWRITE, &fOldProtect) ) {
- *pval1 = FALSE;
- VirtualProtect(pval1, sizeof *pval1, fOldProtect, &fOldProtect);
- log_info(L"Patched variable! (Address=%p)", pval1);
- }
- if ( !*pval2 && VirtualProtect(pval2, sizeof *pval2, PAGE_READWRITE, &fOldProtect) ) {
- *pval2 = TRUE;
- VirtualProtect(pval2, sizeof *pval2, fOldProtect, &fOldProtect);
- log_info(L"Patched variable! (Address=%p)", pval2);
- }
- }
-free_pBlock:
- free(pBlock);
-}
diff --git a/src/wufuc/wufuc.h b/src/wufuc/wufuc.h
deleted file mode 100644
index 8c51863..0000000
--- a/src/wufuc/wufuc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-typedef struct _PATCHINFO
-{
- const char *pattern;
- size_t off1;
- size_t off2;
-} PATCHINFO;
-
-#define SVCHOST_CRASH_THRESHOLD 3
-extern HANDLE g_hMainMutex;
-
-bool wufuc_inject(DWORD dwProcessId,
- LPTHREAD_START_ROUTINE pStartAddress,
- ptrlist_t *list);
-void wufuc_patch(HMODULE hModule);
diff --git a/src/wufuc/wufuc.vcxproj b/src/wufuc/wufuc.vcxproj
index 0b0095e..0327c27 100644
--- a/src/wufuc/wufuc.vcxproj
+++ b/src/wufuc/wufuc.vcxproj
@@ -19,36 +19,27 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
Create
Create
@@ -56,7 +47,9 @@
Create
-
+
+
+
@@ -125,8 +118,8 @@
$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\
$(ProjectName)$(PlatformArchitecture)
false
- $(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)
- $(SolutionDir)..\lib\minhook;$(LibraryPath)
+ $(SolutionDir)..\inc\phnt;$(IncludePath)
+ $(SolutionDir)..\lib\x86;$(LibraryPath)
true
@@ -134,8 +127,8 @@
$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\
$(ProjectName)$(PlatformArchitecture)
false
- $(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)
- $(SolutionDir)..\lib\minhook;$(LibraryPath)
+ $(SolutionDir)..\inc\phnt;$(IncludePath)
+ $(SolutionDir)..\lib\x64;$(LibraryPath)
false
@@ -143,8 +136,8 @@
$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\
$(ProjectName)$(PlatformArchitecture)
false
- $(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)
- $(SolutionDir)..\lib\minhook;$(LibraryPath)
+ $(SolutionDir)..\inc\phnt;$(IncludePath)
+ $(SolutionDir)..\lib\x86;$(LibraryPath)
false
@@ -152,8 +145,8 @@
$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\
$(ProjectName)$(PlatformArchitecture)
false
- $(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)
- $(SolutionDir)..\lib\minhook;$(LibraryPath)
+ $(SolutionDir)..\inc\phnt;$(IncludePath)
+ $(SolutionDir)..\lib\x64;$(LibraryPath)
@@ -172,11 +165,9 @@
exports.def
- version.lib;Shlwapi.lib;libMinHook.x86.MTd.lib;%(AdditionalDependencies);ntdll.lib
+ version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib
-
- X86;%(PreprocessorDefinitions)
-
+
@@ -195,11 +186,9 @@
exports.def
- version.lib;Shlwapi.lib;libMinHook.x64.MTd.lib;%(AdditionalDependencies);ntdll.lib
+ version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib
-
- X64;%(PreprocessorDefinitions)
-
+
@@ -226,15 +215,13 @@
exports.def
- version.lib;Shlwapi.lib;libMinHook.x86.MT.lib;%(AdditionalDependencies);ntdll.lib
+ version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib
true
-
- X86;%(PreprocessorDefinitions)
-
+
- copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
-copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"
+ copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
+copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"
Copy release binaries to the setup staging directories
@@ -263,15 +250,13 @@ copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"
true
false
exports.def
- version.lib;Shlwapi.lib;libMinHook.x64.MT.lib;%(AdditionalDependencies);ntdll.lib
+ version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib
true
-
- X64;%(PreprocessorDefinitions)
-
+
- copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
-copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"
+ copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
+copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"
Copy release binaries to the setup staging directories
diff --git a/src/wufuc/wufuc.vcxproj.filters b/src/wufuc/wufuc.vcxproj.filters
index 6e347bc..c468ff1 100644
--- a/src/wufuc/wufuc.vcxproj.filters
+++ b/src/wufuc/wufuc.vcxproj.filters
@@ -15,12 +15,6 @@
-
- Header Files
-
-
- Header Files
-
Header Files
@@ -30,47 +24,38 @@
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
+
Header Files
-
- Header Files
-
-
+
Header Files
-
- Source Files
-
Source Files
-
- Source Files
-
Source Files
@@ -80,34 +65,28 @@
Source Files
-
+
Source Files
-
+
Source Files
-
+
Source Files
-
+
Source Files
-
+
Source Files
-
+
Source Files
-
+
Source Files
-
- Source Files
-
-
- Source Files
-
-
+
Source Files
@@ -116,7 +95,7 @@
Source Files
- Header Files
+ Resource Files