12 Commits

Author SHA1 Message Date
zeffy
a52637d493 Move misc files around, update FAQ.md 2018-05-17 09:53:06 -07:00
zeffy
5d20496f3a Update phnt headers 2018-05-17 09:46:18 -07:00
zeffy
cd5077ce82 Update appveyor.yml 2018-05-17 08:56:42 -07:00
zeffy
cc0428159f Update ISSUE_TEMPLATE.md 2018-05-17 08:55:25 -07:00
zeffy
e6da8ec18b 1.0.1.0 2018-05-17 08:52:53 -07:00
zeffy
35760a2546 Update wufuc.c 2018-04-04 16:23:41 -07:00
zeffy
a8adfa3c08 switch back from hooking IsDeviceServiceable to direct variable patching (fixes #146) 2018-04-02 13:23:43 -07:00
zeffy
c7e94426a8 Update phnt headers 2018-04-02 10:11:58 -07:00
zeffy
220b2eeaff update log.c, bump version number 2018-04-02 08:48:37 -07:00
zeffy
c2069e3c69 Fix log text encoding (UTF-16 w/o BOM -> UTF-8 w/o BOM) 2018-03-26 02:36:47 -07:00
zeffy
0523eb1b7b Update patternfind.c 2018-03-26 02:35:32 -07:00
zeffy
8ccdd2a50b add minhook license, rename phnt license, update aip [skip ci] 2018-03-16 08:04:57 -07:00
82 changed files with 1220 additions and 2399 deletions

View File

@@ -6,7 +6,7 @@ Then, make sure the following things are included in your issue:
- Operating system version and Service Pack (including 32- or 64-bit).
- Short description of the issue.
- Elaborate steps to reproduce the bug/issue being reported.
- Attach wufuc's log file (located at `C:\ProgramData\wufuc\wufuc.log`).
- Attach wufuc's log file (located at `C:\ProgramData\wufuc\wufuc.1.log`).
- Any supporting information that could help solve/understand the issue.
Any issues that do not include these, or go more than a week without a

9
FAQ.md
View File

@@ -15,17 +15,12 @@ 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:
- You can remove the other third-party solution yourself.
- Alternatively, go to the directory that you installed wufuc to, open the `Troubleshooting` subdirectory, and merge the `Restore_wuauserv.reg` file with your registry by double-clicking it, and then restart your PC.
- Alternatively, go to the directory that you installed wufuc to, and merge the `Restore_wuauserv.reg` file with your registry by double-clicking it, and then restart your PC.
## How to manually remove wufuc v0.8.0.143 when it is impossible to uninstall it normally

View File

@@ -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

View File

@@ -1,7 +1,7 @@
version: 1.0.0.{build}
version: 1.0.1.{build}
branches:
only:
- master
- micro
skip_commits:
files:
- '**/*.md'
@@ -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:

View File

@@ -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

View File

@@ -107,7 +107,8 @@ typedef struct _DBGUI_WAIT_STATE_CHANGE
typedef enum _DEBUGOBJECTINFOCLASS
{
DebugObjectFlags = 1,
DebugObjectUnusedInformation,
DebugObjectKillProcessOnExitInformation,
MaxDebugObjectInfoClass
} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;

View File

@@ -1394,13 +1394,13 @@ typedef enum _SYSTEM_INFORMATION_CLASS
SystemSecureDumpEncryptionInformation,
SystemWriteConstraintInformation, // SYSTEM_WRITE_CONSTRAINT_INFORMATION
SystemKernelVaShadowInformation, // SYSTEM_KERNEL_VA_SHADOW_INFORMATION
SystemHypervisorSharedPageInformation, // REDSTONE4
SystemHypervisorSharedPageInformation, // SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION // since REDSTONE4
SystemFirmwareBootPerformanceInformation,
SystemCodeIntegrityVerificationInformation,
SystemCodeIntegrityVerificationInformation, // SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION
SystemFirmwarePartitionInformation, // 200
SystemSpeculationControlInformation, // SYSTEM_SPECULATION_CONTROL_INFORMATION // (CVE-2017-5715) REDSTONE3 and above.
SystemDmaGuardPolicyInformation,
SystemEnclaveLaunchControlInformation,
SystemDmaGuardPolicyInformation, // SYSTEM_DMA_GUARD_POLICY_INFORMATION
SystemEnclaveLaunchControlInformation, // SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION
MaxSystemInfoClass
} SYSTEM_INFORMATION_CLASS;
@@ -1424,7 +1424,7 @@ typedef struct _SYSTEM_PROCESSOR_INFORMATION
USHORT ProcessorArchitecture;
USHORT ProcessorLevel;
USHORT ProcessorRevision;
USHORT ProcessorCount;
USHORT MaximumProcessors;
ULONG ProcessorFeatureBits;
} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION;
@@ -1845,6 +1845,11 @@ typedef enum _EVENT_TRACE_INFORMATION_CLASS
EventTraceSoftRestartInformation, // EVENT_TRACE_SOFT_RESTART_INFORMATION
EventTraceLastBranchConfigurationInformation, // REDSTONE3
EventTraceLastBranchEventListInformation,
EventTraceProfileSourceAddInformation, // EVENT_TRACE_PROFILE_ADD_INFORMATION // REDSTONE4
EventTraceProfileSourceRemoveInformation, // EVENT_TRACE_PROFILE_REMOVE_INFORMATION
EventTraceProcessorTraceConfigurationInformation,
EventTraceProcessorTraceEventListInformation,
EventTraceCoverageSamplerInformation, // EVENT_TRACE_COVERAGE_SAMPLER_INFORMATION
MaxEventTraceInfoClass
} EVENT_TRACE_INFORMATION_CLASS;
@@ -1955,6 +1960,36 @@ typedef struct _EVENT_TRACE_SOFT_RESTART_INFORMATION
WCHAR FileName[1];
} EVENT_TRACE_SOFT_RESTART_INFORMATION, *PEVENT_TRACE_SOFT_RESTART_INFORMATION;
typedef struct _EVENT_TRACE_PROFILE_ADD_INFORMATION
{
EVENT_TRACE_INFORMATION_CLASS EventTraceInformationClass;
BOOLEAN PerfEvtEventSelect;
BOOLEAN PerfEvtUnitSelect;
ULONG PerfEvtType;
ULONG CpuInfoHierarchy[0x3];
ULONG InitialInterval;
BOOLEAN AllowsHalt;
BOOLEAN Persist;
WCHAR ProfileSourceDescription[0x1];
} EVENT_TRACE_PROFILE_ADD_INFORMATION, *PEVENT_TRACE_PROFILE_ADD_INFORMATION;
typedef struct _EVENT_TRACE_PROFILE_REMOVE_INFORMATION
{
EVENT_TRACE_INFORMATION_CLASS EventTraceInformationClass;
KPROFILE_SOURCE ProfileSource;
ULONG CpuInfoHierarchy[0x3];
} EVENT_TRACE_PROFILE_REMOVE_INFORMATION, *PEVENT_TRACE_PROFILE_REMOVE_INFORMATION;
typedef struct _EVENT_TRACE_COVERAGE_SAMPLER_INFORMATION
{
EVENT_TRACE_INFORMATION_CLASS EventTraceInformationClass;
BOOLEAN CoverageSamplerInformationClass;
UCHAR MajorVersion;
UCHAR MinorVersion;
UCHAR Reserved;
HANDLE SamplerHandle;
} EVENT_TRACE_COVERAGE_SAMPLER_INFORMATION, *PEVENT_TRACE_COVERAGE_SAMPLER_INFORMATION;
typedef struct _SYSTEM_EXCEPTION_INFORMATION
{
ULONG AlignmentFixupCount;
@@ -2256,7 +2291,17 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
{
GUID BootIdentifier;
FIRMWARE_TYPE FirmwareType;
union
{
ULONGLONG BootFlags;
struct
{
ULONGLONG DbgMenuOsSelection : 1; // REDSTONE4
ULONGLONG DbgHiberBoot : 1;
ULONGLONG DbgSoftBoot : 1;
ULONGLONG DbgMeasuredLaunch : 1;
};
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION;
// private
@@ -2788,6 +2833,7 @@ typedef enum _SYSTEM_PROCESS_CLASSIFICATION
SystemProcessClassificationSystem,
SystemProcessClassificationSecureSystem,
SystemProcessClassificationMemCompression,
SystemProcessClassificationRegistry, // REDSTONE4
SystemProcessClassificationMaximum
} SYSTEM_PROCESS_CLASSIFICATION;
@@ -3007,6 +3053,7 @@ typedef struct _SYSTEM_MEMORY_USAGE_INFORMATION
typedef struct _SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION
{
HANDLE ImageFile;
ULONG Type; // REDSTONE4
} SYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION, *PSYSTEM_CODEINTEGRITY_CERTIFICATE_INFORMATION;
// private
@@ -3021,8 +3068,8 @@ typedef struct _SYSTEM_PHYSICAL_MEMORY_INFORMATION
typedef enum _SYSTEM_ACTIVITY_MODERATION_STATE
{
SystemActivityModerationStateSystemManaged,
SystemActivityModerationStateAlwaysThrottled,
SystemActivityModerationStateNeverThrottled,
SystemActivityModerationStateUserManagedAllowThrottling,
SystemActivityModerationStateUserManagedDisableThrottling,
MaxSystemActivityModerationState
} SYSTEM_ACTIVITY_MODERATION_STATE;
@@ -3065,9 +3112,11 @@ typedef struct _SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION
ULONG Locked : 1;
ULONG Unlockable : 1;
ULONG UnlockApplied : 1;
ULONG Reserved : 29;
ULONG UnlockIdValid : 1; // REDSTONE4
ULONG Reserved : 28;
};
};
UCHAR UnlockId[32]; // REDSTONE4
} SYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION, *PSYSTEM_CODEINTEGRITY_UNLOCK_INFORMATION;
// private
@@ -3098,11 +3147,27 @@ typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION
ULONG KvaShadowUserGlobal : 1;
ULONG KvaShadowPcid : 1;
ULONG KvaShadowInvpcid : 1;
ULONG Reserved : 28;
ULONG KvaShadowRequired : 1; // REDSTONE4
ULONG KvaShadowRequiredAvailable : 1;
ULONG Reserved : 26;
};
};
} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, *PSYSTEM_KERNEL_VA_SHADOW_INFORMATION;
// private
typedef struct _SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION
{
HANDLE FileHandle;
ULONG ImageSize;
PVOID Image;
} SYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION, *PSYSTEM_CODEINTEGRITYVERIFICATION_INFORMATION;
// private
typedef struct _SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION
{
PVOID HypervisorSharedUserVa;
} SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION, *PSYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION;
// private
typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION
{
@@ -3124,6 +3189,18 @@ typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION
};
} SYSTEM_SPECULATION_CONTROL_INFORMATION, *PSYSTEM_SPECULATION_CONTROL_INFORMATION;
// private
typedef struct _SYSTEM_DMA_GUARD_POLICY_INFORMATION
{
BOOLEAN DmaGuardPolicyEnabled;
} SYSTEM_DMA_GUARD_POLICY_INFORMATION, *PSYSTEM_DMA_GUARD_POLICY_INFORMATION;
// private
typedef struct _SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION
{
UCHAR EnclaveLaunchSigner[32];
} SYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION, *PSYSTEM_ENCLAVE_LAUNCH_CONTROL_INFORMATION;
#if (PHNT_MODE != PHNT_MODE_KERNEL)
NTSYSCALLAPI
@@ -3278,7 +3355,8 @@ typedef union _SYSDBG_LIVEDUMP_CONTROL_FLAGS
ULONG UseDumpStorageStack : 1;
ULONG CompressMemoryPagesData : 1;
ULONG IncludeUserSpaceMemoryPages : 1;
ULONG Reserved : 29;
ULONG AbortIfMemoryPressure : 1; // REDSTONE4
ULONG Reserved : 28;
};
ULONG AsUlong;
} SYSDBG_LIVEDUMP_CONTROL_FLAGS, *PSYSDBG_LIVEDUMP_CONTROL_FLAGS;
@@ -3974,12 +4052,15 @@ NtDisplayString(
_In_ PUNICODE_STRING String
);
// Boot graphics
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDrawText(
_In_ PUNICODE_STRING String
_In_ PUNICODE_STRING Text
);
#endif

View File

@@ -243,6 +243,8 @@ typedef enum _FILE_INFORMATION_CLASS
FileDesiredStorageClassInformation, // FILE_DESIRED_STORAGE_CLASS_INFORMATION // since REDSTONE2
FileStatInformation, // FILE_STAT_INFORMATION
FileMemoryPartitionInformation, // FILE_MEMORY_PARTITION_INFORMATION // since REDSTONE3
FileStatLxInformation, // FILE_STAT_LX_INFORMATION // since REDSTONE4
FileCaseSensitiveInformation, // FILE_CASE_SENSITIVE_INFORMATION
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
@@ -711,6 +713,34 @@ typedef struct _FILE_MEMORY_PARTITION_INFORMATION
} Flags;
} FILE_MEMORY_PARTITION_INFORMATION, *PFILE_MEMORY_PARTITION_INFORMATION;
// private
typedef struct _FILE_STAT_LX_INFORMATION
{
LARGE_INTEGER FileId;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG FileAttributes;
ULONG ReparseTag;
ULONG NumberOfLinks;
ULONG EffectiveAccess;
ULONG LxFlags;
ULONG LxUid;
ULONG LxGid;
ULONG LxMode;
ULONG LxDeviceIdMajor;
ULONG LxDeviceIdMinor;
} FILE_STAT_LX_INFORMATION, *PFILE_STAT_LX_INFORMATION;
// private
typedef struct _FILE_CASE_SENSITIVE_INFORMATION
{
ULONG Flags;
} FILE_CASE_SENSITIVE_INFORMATION, *PFILE_CASE_SENSITIVE_INFORMATION;
// NtQueryDirectoryFile types
typedef struct _FILE_DIRECTORY_INFORMATION

View File

@@ -720,6 +720,7 @@ LdrEnumerateLoadedModules(
_In_ PVOID Context
);
NTSYSAPI
NTSTATUS
NTAPI
LdrOpenImageFileOptionsKey(
@@ -728,6 +729,7 @@ LdrOpenImageFileOptionsKey(
_Out_ PHANDLE NewKeyHandle
);
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryImageFileKeyOption(
@@ -739,6 +741,7 @@ LdrQueryImageFileKeyOption(
_Out_opt_ PULONG ReturnedLength
);
NTSYSAPI
NTSTATUS
NTAPI
LdrQueryImageFileExecutionOptions(

View File

@@ -1,18 +1,6 @@
#ifndef _NTMISC_H
#define _NTMISC_H
// Boot graphics
#if (PHNT_VERSION >= PHNT_WIN7)
// rev
NTSYSCALLAPI
NTSTATUS
NTAPI
NtDrawText(
_In_ PUNICODE_STRING Text
);
#endif
// Filter manager
#define FLT_PORT_CONNECT 0x0001

View File

@@ -75,7 +75,7 @@ typedef enum _MEMORY_INFORMATION_CLASS
MemoryImageInformation, // MEMORY_IMAGE_INFORMATION
MemoryRegionInformationEx,
MemoryPrivilegedBasicInformation,
MemoryEnclaveImageInformation, // since REDSTONE3
MemoryEnclaveImageInformation, // MEMORY_ENCLAVE_IMAGE_INFORMATION // since REDSTONE3
MemoryBasicInformationCapped
} MEMORY_INFORMATION_CLASS;
#else
@@ -136,6 +136,15 @@ typedef struct _MEMORY_REGION_INFORMATION
SIZE_T CommitSize;
} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;
// private
typedef enum _MEMORY_WORKING_SET_EX_LOCATION
{
MemoryLocationInvalid,
MemoryLocationResident,
MemoryLocationPagefile,
MemoryLocationReserved
} MEMORY_WORKING_SET_EX_LOCATION;
// private
typedef struct _MEMORY_WORKING_SET_EX_BLOCK
{
@@ -207,12 +216,20 @@ typedef struct _MEMORY_IMAGE_INFORMATION
{
ULONG ImagePartialMap : 1;
ULONG ImageNotExecutable : 1;
ULONG ImageSigningLevel : 1; // REDSTONE3
ULONG Reserved : 30;
ULONG ImageSigningLevel : 4; // REDSTONE3
ULONG Reserved : 26;
};
};
} MEMORY_IMAGE_INFORMATION, *PMEMORY_IMAGE_INFORMATION;
// private
typedef struct _MEMORY_ENCLAVE_IMAGE_INFORMATION
{
MEMORY_IMAGE_INFORMATION ImageInfo;
UCHAR UniqueID[32];
UCHAR AuthorID[32];
} MEMORY_ENCLAVE_IMAGE_INFORMATION, *PMEMORY_ENCLAVE_IMAGE_INFORMATION;
#define MMPFNLIST_ZERO 0
#define MMPFNLIST_FREE 1
#define MMPFNLIST_STANDBY 2
@@ -654,7 +671,8 @@ typedef enum _MEMORY_PARTITION_INFORMATION_CLASS
SystemMemoryPartitionAddPagefile, // s: MEMORY_PARTITION_PAGEFILE_INFORMATION
SystemMemoryPartitionCombineMemory, // q; s: MEMORY_PARTITION_PAGE_COMBINE_INFORMATION
SystemMemoryPartitionInitialAddMemory, // q; s: MEMORY_PARTITION_INITIAL_ADD_INFORMATION
SystemMemoryPartitionGetMemoryEvents // MEMORY_PARTITION_MEMORY_EVENTS_INFORMATION // since REDSTONE2
SystemMemoryPartitionGetMemoryEvents, // MEMORY_PARTITION_MEMORY_EVENTS_INFORMATION // since REDSTONE2
SystemMemoryPartitionMax
} MEMORY_PARTITION_INFORMATION_CLASS;
// private

View File

@@ -84,8 +84,8 @@ typedef struct _PEB
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
PSLIST_HEADER AtlThunkSListPtr;
union
{
ULONG CrossProcessFlags;
@@ -193,19 +193,24 @@ typedef struct _PEB
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase;
PVOID TppWorkerpListLock;
PRTL_CRITICAL_SECTION TppWorkerpListLock;
LIST_ENTRY TppWorkerpList;
PVOID WaitOnAddressHashTable[128];
PVOID TelemetryCoverageHeader; // REDSTONE3
ULONG CloudFileFlags;
ULONG CloudFileDiagFlags; // REDSTONE4
CHAR PlaceholderCompatibilityMode;
CHAR PlaceholderCompatibilityModeReserved[7];
} PEB, *PPEB;
#ifdef _WIN64
C_ASSERT(FIELD_OFFSET(PEB, SessionId) == 0x2C0);
C_ASSERT(sizeof(PEB) == 0x7B0);
//C_ASSERT(sizeof(PEB) == 0x7B0); // REDSTONE3
C_ASSERT(sizeof(PEB) == 0x7B8); // REDSTONE4
#else
C_ASSERT(FIELD_OFFSET(PEB, SessionId) == 0x1D4);
C_ASSERT(sizeof(PEB) == 0x468);
//C_ASSERT(sizeof(PEB) == 0x468); // REDSTONE3
C_ASSERT(sizeof(PEB) == 0x470);
#endif
#define GDI_BATCH_BUFFER_SIZE 310

View File

@@ -105,7 +105,7 @@ typedef enum _PROCESSINFOCLASS
ProcessBasePriority, // s: KPRIORITY
ProcessRaisePriority, // s: ULONG
ProcessDebugPort, // q: HANDLE
ProcessExceptionPort, // s: HANDLE
ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT
ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10
ProcessLdtSize, // s: PROCESS_LDT_SIZE
@@ -132,12 +132,12 @@ typedef enum _PROCESSINFOCLASS
ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
ProcessIoPriority, // qs: IO_PRIORITY_HINT
ProcessExecuteFlags, // qs: ULONG
ProcessResourceManagement,
ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION
ProcessCookie, // q: ULONG
ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA
ProcessPagePriority, // q: ULONG
ProcessInstrumentationCallback, // 40
ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION
ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40
ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
ProcessImageFileNameWin32, // q: UNICODE_STRING
@@ -146,7 +146,7 @@ typedef enum _PROCESSINFOCLASS
ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
ProcessGroupInformation, // q: USHORT[]
ProcessTokenVirtualizationEnabled, // s: ULONG
ProcessConsoleHostProcess, // q: ULONG_PTR
ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation
ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50
ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
@@ -187,6 +187,9 @@ typedef enum _PROCESSINFOCLASS
ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION
ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION
ProcessImageSection,
ProcessDebugAuthInformation, // since REDSTONE4
ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT
ProcessSequenceNumber, // q: ULONGLONG
MaxProcessInfoClass
} PROCESSINFOCLASS;
#endif
@@ -353,6 +356,15 @@ typedef struct _POOLED_USAGE_AND_LIMITS
SIZE_T PagefileLimit;
} POOLED_USAGE_AND_LIMITS, *PPOOLED_USAGE_AND_LIMITS;
#define PROCESS_EXCEPTION_PORT_ALL_STATE_BITS 0x00000003
#define PROCESS_EXCEPTION_PORT_ALL_STATE_FLAGS ((ULONG_PTR)((1UL << PROCESS_EXCEPTION_PORT_ALL_STATE_BITS) - 1))
typedef struct _PROCESS_EXCEPTION_PORT
{
_In_ HANDLE ExceptionPortHandle; // Handle to the exception port. No particular access required.
_Inout_ ULONG StateFlags; // Miscellaneous state flags to be cached along with the exception port in the kernel.
} PROCESS_EXCEPTION_PORT, *PPROCESS_EXCEPTION_PORT;
typedef struct _PROCESS_ACCESS_TOKEN
{
HANDLE Token; // needs TOKEN_ASSIGN_PRIMARY access
@@ -448,6 +460,8 @@ typedef struct _PROCESS_SESSION_INFORMATION
ULONG SessionId;
} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
#define PROCESS_HANDLE_EXCEPTIONS_ENABLED 0x00000001
#define PROCESS_HANDLE_RAISE_EXCEPTION_ON_INVALID_HANDLE_CLOSE_DISABLED 0x00000000
#define PROCESS_HANDLE_RAISE_EXCEPTION_ON_INVALID_HANDLE_CLOSE_ENABLED 0x00000001
@@ -487,6 +501,42 @@ typedef struct _PROCESS_HANDLE_TRACING_QUERY
#endif
// private
typedef struct _THREAD_TLS_INFORMATION
{
ULONG Flags;
PVOID NewTlsData;
PVOID OldTlsData;
HANDLE ThreadId;
} THREAD_TLS_INFORMATION, *PTHREAD_TLS_INFORMATION;
// private
typedef enum _PROCESS_TLS_INFORMATION_TYPE
{
ProcessTlsReplaceIndex,
ProcessTlsReplaceVector,
MaxProcessTlsOperation
} PROCESS_TLS_INFORMATION_TYPE, *PPROCESS_TLS_INFORMATION_TYPE;
// private
typedef struct _PROCESS_TLS_INFORMATION
{
ULONG Flags;
ULONG OperationType;
ULONG ThreadDataCount;
ULONG TlsIndex;
ULONG PreviousCount;
THREAD_TLS_INFORMATION ThreadData[1];
} PROCESS_TLS_INFORMATION, *PPROCESS_TLS_INFORMATION;
// private
typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
ULONG Version;
ULONG Reserved;
PVOID Callback;
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;
// private
typedef struct _PROCESS_STACK_ALLOCATION_INFORMATION
{
@@ -757,17 +807,19 @@ typedef struct _MANAGE_WRITES_TO_EXECUTABLE_MEMORY
ULONG Spare : 22;
} MANAGE_WRITES_TO_EXECUTABLE_MEMORY, *PMANAGE_WRITES_TO_EXECUTABLE_MEMORY;
typedef struct _PROCESS_READWRITEVM_LOGGING_INFORMATION
#define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM 1
#define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM 2
#define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM_V 1UL
#define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM_V 2UL
typedef union _PROCESS_READWRITEVM_LOGGING_INFORMATION
{
union
{
BOOLEAN Flags;
UCHAR Flags;
struct
{
BOOLEAN EnableReadVmLogging : 1;
BOOLEAN EnableWriteVmLogging : 1;
BOOLEAN Unused : 6;
};
UCHAR EnableReadVmLogging : 1;
UCHAR EnableWriteVmLogging : 1;
UCHAR Unused : 6;
};
} PROCESS_READWRITEVM_LOGGING_INFORMATION, *PPROCESS_READWRITEVM_LOGGING_INFORMATION;
@@ -788,6 +840,16 @@ typedef struct _PROCESS_UPTIME_INFORMATION
};
} PROCESS_UPTIME_INFORMATION, *PPROCESS_UPTIME_INFORMATION;
typedef union _PROCESS_SYSTEM_RESOURCE_MANAGEMENT
{
ULONG Flags;
struct
{
ULONG Foreground : 1;
ULONG Reserved : 31;
};
} PROCESS_SYSTEM_RESOURCE_MANAGEMENT, *PPROCESS_SYSTEM_RESOURCE_MANAGEMENT;
// end_private
#endif
@@ -1008,6 +1070,7 @@ NtResumeProcess(
#define NtCurrentProcessToken() ((HANDLE)(LONG_PTR)-4)
#define NtCurrentThreadToken() ((HANDLE)(LONG_PTR)-5)
#define NtCurrentEffectiveToken() ((HANDLE)(LONG_PTR)-6)
#define NtCurrentSilo() ((HANDLE)(LONG_PTR)-1)
// Not NT, but useful.
#define NtCurrentProcessId() (NtCurrentTeb()->ClientId.UniqueProcess)
@@ -1471,7 +1534,8 @@ typedef enum _PS_MITIGATION_OPTION
PS_MITIGATION_OPTION_EXPORT_ADDRESS_FILTER_PLUS,
PS_MITIGATION_OPTION_RESTRICT_CHILD_PROCESS_CREATION,
PS_MITIGATION_OPTION_IMPORT_ADDRESS_FILTER,
PS_MITIGATION_OPTION_MODULE_TAMPERING_PROTECTION
PS_MITIGATION_OPTION_MODULE_TAMPERING_PROTECTION,
PS_MITIGATION_OPTION_RESTRICT_INDIRECT_BRANCH_PREDICTION
} PS_MITIGATION_OPTION;
// windows-internals-book:"Chapter 5"

View File

@@ -3236,6 +3236,15 @@ RtlDoesFileExists_U(
_In_ PWSTR FileName
);
#if (PHNT_VERSION >= PHNT_REDSTONE2)
NTSYSAPI
PCWSTR
NTAPI
RtlGetNtSystemRoot(
VOID
);
#endif
// Heaps
typedef struct _RTL_HEAP_ENTRY

View File

@@ -36,6 +36,7 @@
#define PHNT_REDSTONE 102
#define PHNT_REDSTONE2 103
#define PHNT_REDSTONE3 104
#define PHNT_REDSTONE4 105
#ifndef PHNT_MODE
#define PHNT_MODE PHNT_MODE_USER

View File

@@ -213,6 +213,8 @@ typedef const OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) { sizeof(OBJECT_ATTRIBUTES), NULL, n, a, NULL, NULL }
#define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\')
// Portability
typedef struct _OBJECT_ATTRIBUTES64

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -46,6 +46,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
<OutDir>$(ProjectDir)bin\$(Configuration)\$(PlatformShortName)\</OutDir>
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -93,7 +95,7 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
<Message>Copy release binaries to the setup staging directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>

View File

@@ -5,10 +5,7 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="AI_CLEAN_RESOURCES_DISABLE_UPGRADE" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_UNINSTALL" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_USER_PROMPT_BASIC_UI" Value="1"/>
<ROW Property="AI_CLEAN_RESOURCES_USER_PROMPT_FULL_UI" Value="1"/>
<ROW Property="AI_ThemeStyle" Value="aero" MsiKey="AI_ThemeStyle"/>
<ROW Property="ALLUSERS" Value="1"/>
<ROW Property="ARPCOMMENTS" Value="Enables Windows Update on PCs with unsupported processors." ValueLocId="*"/>
@@ -21,10 +18,10 @@
<ROW Property="AiPreventAutoPin" Value="System.AppUserModel.ExcludeFromShowInNewInstall"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="x64Build:6#x86Build:6"/>
<ROW Property="Manufacturer" Value="zeffy"/>
<ROW Property="ProductCode" Value="1027:{F4D292D2-CE8F-4908-80AF-CB48B3E560CF} 1028:{66D6B564-B289-4F83-98E0-4296CDE37CB9} 1031:{F4662CF2-7D9F-4370-B45F-ADB021733AF9} 1033:{0DAE2218-2FB5-4AD0-9558-FA2F1B1E5ABF} 1035:{7A1DE4CB-ED5F-4EA0-B262-137BB5CDF2BF} 1036:{B2D2636D-2170-457A-A876-051F227DEEA2} 1038:{9D2917A0-8F1E-4E0F-AE62-1938BD4CED0E} 1040:{3BD98571-9F20-44F8-9162-62D664860999} 1041:{64C167D2-432B-4B82-B5AF-AF795C78F4A1} 1042:{8EAAC0A1-89E3-46B8-B101-E149E87F04F4} 1043:{8AB22455-426B-4757-B640-30729411FD11} 1045:{1CC402B6-02FD-4E14-BE66-10A12FA99106} 1046:{9E7919D2-D6AF-4864-A6C3-028F759BF307} 1049:{8FA26981-B9FF-4505-B547-4EFA9B5241C8} 1060:{3992ECFB-F774-49FE-8B7A-9C2F7B52B271} 2052:{75CEB203-1CE4-4B6F-A9DF-18D8B902C6B8} 2070:{8B6326BE-B5FE-46F3-BD61-1AC95EB0C1CA} 3082:{D564C11C-4870-43C1-BD62-F71DFC45FBF2} " Type="16"/>
<ROW Property="ProductCode" Value="1027:{8788C792-140E-41E9-B875-685F557ACEE6} 1028:{C3A9DFE3-DBAB-47BA-ABAD-804D54F0FBF4} 1031:{85F838D1-6E19-4D99-BEE8-3A46A6D52813} 1033:{F011FFEE-01E3-495E-80CA-10A640C55031} 1035:{03787122-8FC5-4BF2-B447-372148E7E0CD} 1036:{C83296AB-0CC4-4954-A218-3F76BE31C530} 1038:{8D87BFD2-FE05-4506-A1D8-62EE821DB623} 1040:{C48A5EF8-8DB1-4D08-B468-683879C807E3} 1041:{5CCB0BE8-E87D-4D8C-BD5F-B5A6E1CDDB4A} 1042:{2AE0CA07-01C9-4B29-A880-E52CE19EB157} 1043:{28C34648-07BD-463C-A61E-AE47525AF2D2} 1045:{F7E7320E-9EBF-44C5-97E7-E8FEB7A47613} 1046:{393B1C36-514F-4722-A577-408055568261} 1049:{13DAE24C-D5C2-443E-8105-8B3FE24C9370} 1060:{836B7413-1503-4164-9D21-87C28468AD61} 2052:{880E51E8-4243-42F4-BAA3-B32785746291} 2070:{E76212D9-7C99-4C47-9004-3F32D658D6A6} 3082:{CFE6B8E7-9D52-488C-BEA6-A7EE3306B20C} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="wufuc"/>
<ROW Property="ProductVersion" Value="1.0.0.0" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="ProductVersion" Value="1.0.1.0" Type="32" TargetFile="wufuc64.dll"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{4C52972C-251E-4D1B-AD09-EAA765719DCC}"/>
<ROW Property="WindowsType9X" MultiBuildValue="x64Build:Windows 9x/ME#x86Build:Windows 9x/ME" ValueLocId="-"/>
@@ -43,36 +40,30 @@
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="CommonAppDataFolder" Directory_Parent="TARGETDIR" DefaultDir="COMMON~1|CommonAppDataFolder" IsPseudoRoot="1"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
<ROW Directory="Troubleshooting_1_Dir" Directory_Parent="APPDIR" DefaultDir="TROUBL~1|Troubleshooting"/>
<ROW Directory="Troubleshooting_Dir" Directory_Parent="SHORTCUTDIR" DefaultDir="TROUBL~1|Troubleshooting"/>
<ROW Directory="Troubleshooting_Dir" Directory_Parent="SHORTCUTDIR" DefaultDir="HELPAN~1|Help and Support"/>
<ROW Directory="X64FeatureItems_Dir" Directory_Parent="APPDIR" DefaultDir=".:X64FEA~1|X64FeatureItems"/>
<ROW Directory="X86FeatureItems_Dir" Directory_Parent="APPDIR" DefaultDir=".:X86FEA~1|X86FeatureItems"/>
<ROW Directory="wufuc_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="wufuc"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="COPYING" ComponentId="{6CA1ECA7-4C30-4BD0-A5E8-6B3E5BCBE31D}" Directory_="APPDIR" Attributes="0" KeyPath="COPYING" Type="0"/>
<ROW Component="ProductInformation" ComponentId="{75030EAB-5C17-4F84-B529-28003271CA3F}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
<ROW Component="Restore_wuauserv.reg" ComponentId="{5CE5C35B-6B0E-4EE4-B92C-7B1D9882DFC0}" Directory_="Troubleshooting_1_Dir" Attributes="0" KeyPath="Restore_wuauserv.reg" Type="0"/>
<ROW Component="SHORTCUTDIR" ComponentId="{910396A4-AFDD-4E57-BF00-2FDD4108AC61}" Directory_="SHORTCUTDIR" Attributes="0"/>
<ROW Component="Troubleshooting" ComponentId="{D4F7163C-0FD7-4862-BF97-F1693236500C}" Directory_="Troubleshooting_Dir" Attributes="0"/>
<ROW Component="X64FeatureItems" ComponentId="{0E189A37-1F40-4756-ACB9-6511067D5B47}" Directory_="X64FeatureItems_Dir" Attributes="0"/>
<ROW Component="X86FeatureItems" ComponentId="{CBB84726-9EC3-4570-9012-37BA98719022}" Directory_="X86FeatureItems_Dir" Attributes="0"/>
<ROW Component="wufuc" ComponentId="{331CB0F5-F6E7-4712-9F97-3609A0D5AFE6}" Directory_="wufuc_Dir" Attributes="0"/>
<ROW Component="wufuc32.dll" ComponentId="{7FBEF396-DCBC-4838-A4EB-336F74A836C7}" Directory_="APPDIR" Attributes="0" KeyPath="wufuc32.dll"/>
<ROW Component="wufuc64.dll" ComponentId="{0407D471-998A-4FD3-BC2D-72EE56FBEEF4}" Directory_="APPDIR" Attributes="256" KeyPath="wufuc64.dll"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="COPYING ProductInformation Restore_wuauserv.reg SHORTCUTDIR Troubleshooting wufuc"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="COPYING ProductInformation SHORTCUTDIR Troubleshooting"/>
<ROW Feature="X64Feature" Feature_Parent="MainFeature" Title="X64Feature" Display="0" Level="1" Directory_="APPDIR" Attributes="0" Components="X64FeatureItems wufuc64.dll" Builds="x64Build"/>
<ROW Feature="X86Feature" Feature_Parent="MainFeature" Title="X86Feature" Display="0" Level="1" Directory_="APPDIR" Attributes="0" Components="X86FeatureItems wufuc32.dll" Builds="x86Build"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="COPYING" Component_="COPYING" FileName="COPYING.txt" Attributes="0" SourcePath="..\..\COPYING" SelfReg="false" NextFile="Restore_wuauserv.reg"/>
<ROW File="Restore_wuauserv.reg" Component_="Restore_wuauserv.reg" FileName="RESTOR~1.REG|Restore_wuauserv.reg" Attributes="0" SourcePath="..\wufuc_setup_bat\Restore_wuauserv.reg" SelfReg="false"/>
<ROW File="COPYING" Component_="COPYING" FileName="COPYING.txt" Attributes="0" SourcePath="..\..\COPYING" SelfReg="false"/>
<ROW File="wufuc32.dll" Component_="wufuc32.dll" FileName="wufuc32.dll" Attributes="0" SourcePath="wufuc32.dll" SelfReg="false" NextFile="wufuc64.dll"/>
<ROW File="wufuc64.dll" Component_="wufuc64.dll" FileName="wufuc64.dll" Attributes="0" SourcePath="wufuc64.dll" SelfReg="false" NextFile="COPYING"/>
</COMPONENT>
@@ -80,10 +71,6 @@
<ROW MsiShortcutProperty="Uninstallwufuc1" Shortcut_="Uninstallwufuc" PropertyKey="[AiPreventAutoPin]" PropVariantValue="1"/>
<ROW MsiShortcutProperty="License1" Shortcut_="License" PropertyKey="[AiPreventAutoPin]" PropVariantValue="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.AiRemoveFileComponent">
<ROW RemoveFile="log" Condition="(AI_CLEAN_RESOURCES_UNINSTALL = &quot;1&quot;) AND (NOT UPGRADINGPRODUCTCODE)" Options="1"/>
<ROW RemoveFile="_" Condition="(AI_CLEAN_RESOURCES_UNINSTALL = &quot;1&quot;) AND (NOT UPGRADINGPRODUCTCODE)" Options="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
<ROW BootstrOptKey="GlobalOptions" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites" Options="2"/>
</COMPONENT>
@@ -128,11 +115,6 @@
<ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
<ROW Action="AI_AiRemoveFilesCommit" Description="Executing file removal operations" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesCommit" Template="Executing file removal: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesCommit"/>
<ROW Action="AI_AiRemoveFilesDeferred_Permanent" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesDeferred_Permanent" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesDeferred_Permanent"/>
<ROW Action="AI_AiRemoveFilesDeferred_Undoable" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesDeferred_Undoable" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesDeferred_Undoable"/>
<ROW Action="AI_AiRemoveFilesImmediate" Description="Preparing files for removal" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesImmediate" Template="Preparing file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesImmediate"/>
<ROW Action="AI_AiRemoveFilesRollback" Description="Restoring removed files" DescriptionLocId="ActionText.Description.AI_AiRemoveFilesRollback" Template="Restoring file: [1]" TemplateLocId="ActionText.Template.AI_AiRemoveFilesRollback"/>
<ROW Action="AI_XmlCommit" Description="Committing XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlCommit" Template="Committing XML file configurations." TemplateLocId="ActionText.Template.AI_XmlCommit"/>
<ROW Action="AI_XmlConfig" Description="Executing XML file configurations" DescriptionLocId="ActionText.Description.AI_XmlConfig" Template="Configuring XML file: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_XmlConfig"/>
<ROW Action="AI_XmlInstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlInstall"/>
@@ -143,7 +125,6 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="AdvancedInstallerHelper.dll" SourcePath="AdvancedInstallerHelper.dll"/>
<ROW Name="Prereq.dll" SourcePath="&lt;AI_CUSTACTS&gt;Prereq.dll"/>
<ROW Name="ResourceCleaner.dll" SourcePath="&lt;AI_CUSTACTS&gt;ResourceCleaner.dll"/>
<ROW Name="ShortcutFlags.dll" SourcePath="&lt;AI_CUSTACTS&gt;ShortcutFlags.dll"/>
<ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
<ROW Name="viewer.exe" SourcePath="&lt;AI_CUSTACTS&gt;viewer.exe"/>
@@ -187,14 +168,8 @@
<ROW Directory_="X86FeatureItems_Dir" Component_="X86FeatureItems" ManualDelete="false"/>
<ROW Directory_="X64FeatureItems_Dir" Component_="X64FeatureItems" ManualDelete="false"/>
<ROW Directory_="Troubleshooting_Dir" Component_="Troubleshooting" ManualDelete="false"/>
<ROW Directory_="wufuc_Dir" Component_="wufuc" ManualDelete="true"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_AiRemoveFilesCommit" Type="11777" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesCommit" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesDeferred_Permanent" Type="11265" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesPermanent" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesDeferred_Undoable" Type="11265" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesUndoable" WithoutSeq="true"/>
<ROW Action="AI_AiRemoveFilesImmediate" Type="1" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesImmediate"/>
<ROW Action="AI_AiRemoveFilesRollback" Type="11521" Source="ResourceCleaner.dll" Target="OnAiUndoRemoveFiles"/>
<ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
<ROW Action="AI_ApplyShortcutFlags" Type="3073" Source="ShortcutFlags.dll" Target="UpdateShortcutFlags" WithoutSeq="true"/>
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
@@ -211,7 +186,6 @@
<ROW Action="AI_PinToStartScreen" Type="1025" Source="ShortcutFlags.dll" Target="PinToStartScreen" WithoutSeq="true"/>
<ROW Action="AI_PinToTaskbar" Type="1025" Source="ShortcutFlags.dll" Target="PinToTaskbar" WithoutSeq="true"/>
<ROW Action="AI_PrepareShortcutFlags" Type="1" Source="ShortcutFlags.dll" Target="PrepareActionData"/>
<ROW Action="AI_PromptUserBasicUI" Type="1" Source="ResourceCleaner.dll" Target="OnPromptUserBasicUI"/>
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
@@ -235,24 +209,26 @@
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="x64Build:[ProgramFiles64Folder]\[ProductName]#x86Build:[ProgramFilesFolder]\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
<ROW Action="SetRebootProperty" Type="51" Source="REBOOT" Target="Force"/>
<ROW Action="StartWindowsUpdateService" Type="3073" Source="aicustact.dll" Target="StartWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_3"/>
<ROW Action="StopWindowsUpdateService" Type="3073" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_2"/>
<ROW Action="StopWindowsUpdateService" Type="3137" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="msiexec.exe" SourcePath="..\..\..\..\..\..\..\Windows\System32\msiexec.exe" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIniFileComponent">
<ROW IniFile="ServiceDll" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="&quot;ServiceDll&quot;" Value="hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,00,6f,\" Action="0" Component_="ProductInformation"/>
<ROW IniFile="URL" FileName="Donate.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/DONATE.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/README.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_6" FileName="LATEST~1.URL|Latest Release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/releases/latest" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_7" FileName="REPORT~1.URL|Report an Issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/issues" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_6" FileName="LATEST~1.URL|Latest release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/releases/latest" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_7" FileName="REPORT~1.URL|Report an issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/issues" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="URL_8" FileName="FAQ.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="URL" Value="https://github.com/zeffy/wufuc/blob/master/FAQ.md" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory" FileName="Donate.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_2" FileName="Readme.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_6" FileName="LATEST~1.URL|Latest Release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_7" FileName="REPORT~1.URL|Report an Issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_6" FileName="LATEST~1.URL|Latest release.url" DirProperty="SHORTCUTDIR" Section="InternetShortcut" Key="WorkingDirectory" Value="[SHORTCUTDIR]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_7" FileName="REPORT~1.URL|Report an issue.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="WorkingDirectory_8" FileName="FAQ.url" DirProperty="Troubleshooting_Dir" Section="InternetShortcut" Key="WorkingDirectory" Value="[Troubleshooting_Dir]" Action="0" Component_="SHORTCUTDIR"/>
<ROW IniFile="c00730079007300740065006d0033003200" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\" Value="00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\" Action="0" Component_="ProductInformation"/>
<ROW IniFile="e0067002e0064006c006c000000" FileName="RESTOR~1.REG|Restore_wuauserv.reg" DirProperty="APPDIR" Section="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv\Parameters" Key="77,00,75,00,61,00,75,00,65,00,6e,00,67,00,2e,00,64,00,6c,00,6c,00,00,00" Value="77,00,75,00,61,00,75,00,65,00,6e,00,67,00,2e,00,64,00,6c,00,6c,00,00,00" Action="0" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
<ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
@@ -277,12 +253,8 @@
<ROW Action="RunScheduledTask" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="5827"/>
<ROW Action="RunSFCScan" Sequence="3603"/>
<ROW Action="AI_AppSearchEx" Sequence="101"/>
<ROW Action="SetRebootProperty" Condition="NONDEFAULT_SERVICEDLL" Sequence="201"/>
<ROW Action="StartWindowsUpdateService" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="6402"/>
<ROW Action="AI_DATA_SETTER_3" Condition="( ( NOT Installed ) OR ( Installed AND REMOVE &lt;&gt; &quot;ALL&quot; AND AI_INSTALL_MODE &lt;&gt; &quot;Remove&quot; ) )" Sequence="6401"/>
<ROW Action="AI_AiRemoveFilesImmediate" Sequence="3499"/>
<ROW Action="AI_AiRemoveFilesRollback" Sequence="3099"/>
<ROW Action="AI_PromptUserBasicUI" Condition="((REMOVE = &quot;ALL&quot;) AND (NOT UPGRADINGPRODUCTCODE))" Sequence="2501"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
@@ -307,13 +279,9 @@
<ROW Registry="Path" Root="-1" Key="Software\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="Version" Root="-1" Key="Software\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRemoveFileComponent">
<ROW FileKey="_" Component_="ProductInformation" DirProperty="wufuc_Dir" InstallMode="2"/>
<ROW FileKey="log" Component_="ProductInformation" FileName="*.log" DirProperty="wufuc_Dir" InstallMode="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="License" Directory_="SHORTCUTDIR" Name="License" Component_="COPYING" Target="[#COPYING]" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="Restore_wuauserv.reg" Target="[CommonAppDataFolder]wufuc\wufuc.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Openwufuclogfile" Directory_="Troubleshooting_Dir" Name="OPENWU~1|Open wufuc log file" Component_="SHORTCUTDIR" Target="[CommonAppDataFolder]wufuc\wufuc.1.log" Hotkey="0" IconIndex="0" ShowCmd="1"/>
<ROW Shortcut="Uninstallwufuc" Directory_="SHORTCUTDIR" Name="UNINST~2|Uninstall [|ProductName]" Component_="ProductInformation" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Hotkey="0" Icon_="msiexec.exe" IconIndex="0" ShowCmd="1" CustomFlags="1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">

5
src/setup_bat/Donate.url Normal file
View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc/blob/master/DONATE.md
IDList=

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc/releases/latest
IDList=

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc/issues
IDList=

View File

@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://github.com/zeffy/wufuc
IDList=

View File

@@ -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}"

121
src/wufuc/asprintf.c Normal file
View File

@@ -0,0 +1,121 @@
#include "stdafx.h"
#include "asprintf.h"
#include <locale.h>
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;
}

17
src/wufuc/asprintf.h Normal file
View File

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

View File

@@ -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 <VersionHelpers.h>
#include <minhook.h>
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
{
switch ( pNotifyBuffer->dwNotificationStatus ) {
case ERROR_SUCCESS:
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
wufuc_inject(
pNotifyBuffer->ServiceStatus.dwProcessId,
(LPTHREAD_START_ROUTINE)cb_start,
(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 cb_start(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 child 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 correct
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_hook(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);
}

View File

@@ -1,4 +0,0 @@
#pragma once
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer);
DWORD WINAPI cb_start(HANDLE *pParam);

View File

@@ -1,7 +1,4 @@
#include "stdafx.h"
#include "log.h"
#include <minhook.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
@@ -9,13 +6,11 @@ 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();
if ( !lpReserved )
log_close();
break;
}

View File

@@ -1,23 +0,0 @@
#include "stdafx.h"
#include "eventhelper.h"
#include <sddl.h>
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;
}

View File

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

54
src/wufuc/helpers.c Normal file
View File

@@ -0,0 +1,54 @@
#include "stdafx.h"
#include "helpers.h"
#include <sddl.h>
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);
}

11
src/wufuc/helpers.h Normal file
View File

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

View File

@@ -1,100 +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;
LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
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", &current, &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_hook(result);
}
return result;
}
BOOL WINAPI IsDeviceServiceable_hook(void)
{
log_debug(L"Entered stub function.");
return TRUE;
}

View File

@@ -1,20 +0,0 @@
#pragma once
typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void);
extern wchar_t *g_pszWUServiceDll;
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
extern PVOID g_ptRegQueryValueExW;
extern PVOID g_ptLoadLibraryExW;
extern PVOID g_ptIsDeviceServiceable;
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);
BOOL WINAPI IsDeviceServiceable_hook(void);

View File

@@ -1,153 +0,0 @@
#include "stdafx.h"
#include "log.h"
#include <ShlObj.h>
HANDLE m_hFile = INVALID_HANDLE_VALUE;
BOOL CALLBACK init_file_handle(
PINIT_ONCE pInitOnce,
ParamData *pParam,
PVOID *ppContext)
{
BOOL result = FALSE;
HANDLE hFile;
HRESULT hr;
wchar_t *pszPath;
wchar_t szFilePath[MAX_PATH];
int ret;
pParam->dwProcessId = GetCurrentProcessId();
if ( !GetModuleFileNameW(NULL, pParam->szExeFilePath, _countof(pParam->szExeFilePath)) ) {
log_debug(L"GetModuleFileNameW failed! (GLE=%lu)", GetLastError());
return result;
}
pParam->pszExeName = PathFindFileNameW(pParam->szExeFilePath);
hr = SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pszPath);
if ( hr != S_OK ) {
log_debug(L"SHGetKnownFolderPath failed! (HRESULT=0x%08X)", hr);
return result;
}
ret = wcscpy_s(szFilePath, _countof(szFilePath), pszPath);
CoTaskMemFree(pszPath);
if ( ret ) {
log_debug(L"wcscpy_s failed! (Return value=%d)", ret);
return result;
}
if ( !PathAppendW(szFilePath, L"wufuc") ) {
append_fail:
log_debug(L"PathAppendW failed!");
return result;
}
if ( !CreateDirectoryW(szFilePath, NULL)
&& GetLastError() != ERROR_ALREADY_EXISTS ) {
log_debug(L"CreateDirectoryW failed! (GLE=%lu)", GetLastError());
return result;
}
if ( !PathAppendW(szFilePath, L"wufuc.log") )
goto append_fail;
hFile = CreateFileW(szFilePath,
FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( hFile != INVALID_HANDLE_VALUE ) {
*ppContext = (PVOID)hFile;
result = TRUE;
} else {
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;
static ParamData data;
BOOL bStatus;
errno_t e;
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;
DWORD written;
bStatus = InitOnceExecuteOnce(&InitOnce,
(PINIT_ONCE_FN)init_file_handle,
&data,
&(LPVOID)m_hFile);
e = _wstrdate_s(datebuf, _countof(datebuf));
if ( e ) return;
e = _wstrtime_s(timebuf, _countof(timebuf));
if ( e ) return;
va_start(ap, format);
count = _vscwprintf(format, ap);
va_end(ap);
if ( count == -1 ) return;
buf1 = calloc(count + 1, sizeof *buf1);
if ( !buf1 ) return;
va_start(ap, format);
ret = vswprintf_s(buf1, count + 1, format, ap);
va_end(ap);
if ( ret == -1 ) goto free_buf1;
count = _scwprintf(fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1);
if ( count == -1 ) goto free_buf1;
buf2 = calloc(count + 1, sizeof *buf2);
if ( !buf2 ) goto free_buf1;
ret = swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, data.pszExeName, data.dwProcessId, buf1);
if ( ret == -1 ) goto free_buf2;
if ( !bStatus || !WriteFile(m_hFile, buf2, count * (sizeof *buf2), &written, NULL) )
OutputDebugStringW(buf2);
free_buf2:
free(buf2);
free_buf1:
free(buf1);
}
void log_close(void)
{
if ( m_hFile != INVALID_HANDLE_VALUE )
CloseHandle(m_hFile);
}

View File

@@ -1,17 +0,0 @@
#pragma once
typedef struct
{
DWORD dwProcessId;
wchar_t szExeFilePath[MAX_PATH];
wchar_t *pszExeName;
} ParamData;
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__)

99
src/wufuc/logger.c Normal file
View File

@@ -0,0 +1,99 @@
#include "stdafx.h"
#include "logger.h"
#include "utf8.h"
#include <ShlObj.h>
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);
}

11
src/wufuc/logger.h Normal file
View File

@@ -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())

8
src/wufuc/memory.c Normal file
View File

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

3
src/wufuc/memory.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
BOOL WriteProcessMemoryBOOL(HANDLE hProcess, LPBOOL lpBaseAddress, BOOL bValue);

View File

@@ -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,
(LPTHREAD_START_ROUTINE)RtlOffsetToPointer(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;
}

View File

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

24
src/wufuc/modules.c Normal file
View File

@@ -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;
}

3
src/wufuc/modules.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
HMODULE Toolhelp32GetModuleHandle(DWORD th32ProcessID, LPCWSTR lpModuleName);

View File

@@ -1,41 +0,0 @@
#include "stdafx.h"
#include "mutexhelper.h"
#include <sddl.h>
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;
}

View File

@@ -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, ...);

View File

@@ -3,7 +3,9 @@
static inline bool isHex(char ch)
{
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
return (ch >= '0' && ch <= '9')
|| (ch >= 'A' && ch <= 'F')
|| (ch >= 'a' && ch <= 'f');
}
static inline int hexchtoint(char ch)
@@ -17,10 +19,14 @@ static inline int hexchtoint(char ch)
return -1;
}
static inline size_t formathexpattern(const char *patterntext, char *formattext, size_t formattextsize)
static inline size_t formathexpattern(const char *patterntext,
char *formattext,
size_t formattextsize)
{
size_t len = strlen(patterntext);
size_t len;
size_t result = 0;
len = strlen(patterntext);
for ( size_t i = 0; i < len; i++ ) {
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
if ( formattext && result + 1 < formattextsize )
@@ -44,18 +50,24 @@ static inline size_t formathexpattern(const char *patterntext, char *formattext,
return result;
}
bool patterntransform(const char *patterntext, PatternByte *pattern, size_t patternsize)
bool patterntransform(const char *patterntext,
PatternByte *pattern,
size_t patternsize)
{
size_t len;
size_t size;
char *formattext;
PatternByte newByte;
memset(pattern, 0, patternsize * (sizeof *pattern));
size_t len = formathexpattern(patterntext, NULL, 0);
len = formathexpattern(patterntext, NULL, 0);
if ( !len || len / 2 > patternsize )
return false;
size_t size = len + 1;
char *formattext = malloc(size);
size = len + 1;
formattext = malloc(size);
formathexpattern(patterntext, formattext, size);
PatternByte newByte;
for ( size_t i = 0, j = 0, k = 0; i < len && k <= patternsize; i++ ) {
if ( formattext[i] == '?' ) { //wildcard
@@ -78,14 +90,16 @@ bool patterntransform(const char *patterntext, PatternByte *pattern, size_t patt
static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
{
int matched = 0;
uint8_t n1;
uint8_t n2;
uint8_t n1 = (byte >> 4) & 0xF;
n1 = (byte >> 4) & 0xF;
if ( pbyte.nibble[0].wildcard )
matched++;
else if ( pbyte.nibble[0].data == n1 )
matched++;
uint8_t n2 = byte & 0xF;
n2 = byte & 0xF;
if ( pbyte.nibble[1].wildcard )
matched++;
else if ( pbyte.nibble[1].data == n2 )
@@ -96,10 +110,13 @@ static inline bool patternmatchbyte(uint8_t byte, const PatternByte pbyte)
size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
{
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
PatternByte *searchpattern = calloc(searchpatternsize, sizeof(PatternByte));
size_t searchpatternsize;
PatternByte *searchpattern;
size_t result = -1;
searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
searchpattern = calloc(searchpatternsize, sizeof *searchpattern);
if ( patterntransform(pattern, searchpattern, searchpatternsize) )
result = patternfind_pbyte(data, datasize, searchpattern, searchpatternsize);
@@ -108,7 +125,10 @@ size_t patternfind(uint8_t *data, size_t datasize, const char *pattern)
}
__declspec(noinline)
size_t patternfind_bytes(uint8_t *data, size_t datasize, const uint8_t *pattern, size_t patternsize)
size_t patternfind_bytes(uint8_t *data,
size_t datasize,
const uint8_t *pattern,
size_t patternsize)
{
if ( patternsize > datasize )
patternsize = datasize;
@@ -137,28 +157,38 @@ static inline void patternwritebyte(uint8_t *byte, const PatternByte pbyte)
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF);
}
void patternwrite(uint8_t *data, size_t datasize, const char *pattern)
void patternwrite(uint8_t *data,
size_t datasize,
const char *pattern)
{
size_t writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
PatternByte *writepattern = calloc(writepatternsize, sizeof(PatternByte));
size_t writepatternsize;
PatternByte *writepattern;
DWORD fOldProtect;
writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
writepattern = calloc(writepatternsize, sizeof *writepattern);
if ( patterntransform(pattern, writepattern, writepatternsize) ) {
DWORD OldProtect;
BOOL result = VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &OldProtect);
VirtualProtect(data, writepatternsize, PAGE_EXECUTE_READWRITE, &fOldProtect);
if ( writepatternsize > datasize )
writepatternsize = datasize;
for ( size_t i = 0; i < writepatternsize; i++ )
patternwritebyte(&data[i], writepattern[i]);
result = VirtualProtect(data, writepatternsize, OldProtect, &OldProtect);
VirtualProtect(data, writepatternsize, fOldProtect, &fOldProtect);
FlushInstructionCache(GetCurrentProcess(), data, datasize);
}
free(writepattern);
}
bool patternsnr(uint8_t *data, size_t datasize, const char *searchpattern, const char *replacepattern)
bool patternsnr(uint8_t *data,
size_t datasize,
const char *searchpattern,
const char *replacepattern)
{
size_t found = patternfind(data, datasize, searchpattern);
size_t found;
found = patternfind(data, datasize, searchpattern);
if ( found == -1 )
return false;
patternwrite(data + found, found - datasize, replacepattern);
@@ -166,7 +196,10 @@ bool patternsnr(uint8_t *data, size_t datasize, const char *searchpattern, const
}
__declspec(noinline)
size_t patternfind_pbyte(uint8_t *data, size_t datasize, const PatternByte *pattern, size_t searchpatternsize)
size_t patternfind_pbyte(uint8_t *data,
size_t datasize,
const PatternByte *pattern,
size_t searchpatternsize)
{
for ( size_t i = 0, pos = 0; i < datasize; i++ ) { //search for the pattern
if ( patternmatchbyte(data[i], pattern[pos]) ) { //check if our pattern matches the current byte

View File

@@ -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 = (uint32_t *)RtlOffsetToPointer(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 = (uint32_t *)RtlOffsetToPointer(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);
}

View File

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

22
src/wufuc/registry.c Normal file
View File

@@ -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;
}

3
src/wufuc/registry.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
DWORD RegGetValueAlloc(PVOID *ppvData, HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwFlags, LPDWORD pdwType);

View File

@@ -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;
}

View File

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

View File

@@ -1,18 +1,18 @@
#pragma once
#ifndef BUILD_COMMIT_VERSION
#define BUILD_COMMIT_VERSION 1.0.0.0
#define BUILD_COMMIT_VERSION 1.0.1.0
#endif
#ifndef BUILD_VERSION_COMMA
#define BUILD_VERSION_COMMA 1,0,0,0
#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

Binary file not shown.

View File

@@ -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)cb_start, &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)cb_service_notify;
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);

View File

@@ -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;
}

View File

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

View File

@@ -11,15 +11,12 @@
#include <phnt_windows.h>
#include <phnt.h>
// TODO: reference additional headers your program requires here
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <share.h>
#include <strsafe.h>
#include <shellapi.h>
@@ -27,6 +24,10 @@
#include <Psapi.h>
#include <TlHelp32.h>
#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))))

26
src/wufuc/utf8.c Normal file
View File

@@ -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;
}

3
src/wufuc/utf8.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
DWORD UTF8WriteFile(HANDLE hFile, LPCWSTR lpWideCharStr);

View File

@@ -1,108 +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_get_version_info_from_hmodule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData)
{
bool result = false;
UINT cbData;
HRSRC hResInfo;
DWORD dwSize;
HGLOBAL hResData;
LPVOID pRes;
LPVOID pCopy;
LPVOID pBuffer;
UINT uLen;
if ( !pcbData ) return result;
cbData = *pcbData;
hResInfo = FindResourceW(hModule,
MAKEINTRESOURCEW(VS_VERSION_INFO),
RT_VERSION);
if ( !hResInfo ) return result;
dwSize = SizeofResource(hModule, hResInfo);
if ( !dwSize ) return result;
hResData = LoadResource(hModule, hResInfo);
if ( !hResData ) return result;
pRes = LockResource(hResData);
if ( !pRes ) return result;
pCopy = malloc(dwSize);
if ( !pCopy ) return result;
if ( memcpy_s(pCopy, dwSize, pRes, dwSize)
|| !VerQueryValueW(pCopy, pszSubBlock, &pBuffer, &uLen) )
goto cleanup;
if ( !_wcsnicmp(pszSubBlock, L"\\StringFileInfo\\", 16) )
*pcbData = uLen * sizeof(wchar_t);
else
*pcbData = uLen;
if ( !pData ) {
result = true;
goto cleanup;
}
if ( cbData < *pcbData
|| memcpy_s(pData, cbData, pBuffer, *pcbData) )
goto cleanup;
result = true;
cleanup:
free(pCopy);
return result;
}
LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData)
{
UINT cbData = 0;
LPVOID result = NULL;
if ( !ver_get_version_info_from_hmodule(hModule, pszSubBlock, NULL, &cbData) )
return result;
result = malloc(cbData);
if ( !result ) return result;
if ( ver_get_version_info_from_hmodule(hModule, pszSubBlock, result, &cbData) ) {
*pcbData = cbData;
} else {
free(result);
result = NULL;
}
return result;
}
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;
}

View File

@@ -1,6 +0,0 @@
#pragma once
int ver_compare_product_version(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
bool ver_get_version_info_from_hmodule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData);
LPVOID ver_get_version_info_from_hmodule_alloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData);
bool ver_verify_version_info(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);

130
src/wufuc/versioninfo.c Normal file
View File

@@ -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;
}

19
src/wufuc/versioninfo.h Normal file
View File

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

View File

@@ -1,194 +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 "versionhelper.h"
#include <minhook.h>
HANDLE g_hMainMutex;
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;
}
bool wufuc_hook(HMODULE hModule)
{
bool result = false;
PLANGANDCODEPAGE ptl;
HANDLE hProcess;
UINT cbtl;
wchar_t SubBlock[38];
wchar_t *pInternalName;
UINT cbInternalName;
VS_FIXEDFILEINFO *pffi;
UINT cbffi;
bool tmp;
MODULEINFO modinfo;
size_t offset;
LPVOID pTarget = NULL;
MH_STATUS status;
ptl = ver_get_version_info_from_hmodule_alloc(hModule, L"\\VarFileInfo\\Translation", &cbtl);
if ( !ptl ) {
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
return false;
}
hProcess = GetCurrentProcess();
for ( size_t i = 0, count = (cbtl / sizeof *ptl); i < count; i++ ) {
if ( swprintf_s(SubBlock,
_countof(SubBlock),
L"\\StringFileInfo\\%04x%04x\\InternalName",
ptl[i].wLanguage,
ptl[i].wCodePage) == -1 )
continue;
pInternalName = ver_get_version_info_from_hmodule_alloc(hModule, SubBlock, &cbInternalName);
if ( !pInternalName ) {
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
continue;
}
// identify wuaueng.dll by its resource data
if ( _wcsicmp(pInternalName, L"wuaueng.dll") ) {
log_error(L"Module internal name does not match! (InternalName=%ls)", pInternalName);
goto free_iname;
}
pffi = ver_get_version_info_from_hmodule_alloc(hModule, L"\\", &cbffi);
if ( !pffi ) {
log_error(L"ver_get_version_info_from_hmodule_alloc failed!");
break;
}
// assure wuaueng.dll version is supported
tmp = ((ver_verify_version_info(6, 1, 0) && 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));
log_info(L"%ls Windows Update Agent version: %hu.%hu.%hu.%hu",
tmp ? L"Supported" : L"Unsupported",
HIWORD(pffi->dwProductVersionMS),
LOWORD(pffi->dwProductVersionMS),
HIWORD(pffi->dwProductVersionLS),
LOWORD(pffi->dwProductVersionLS));
free(pffi);
if ( !tmp ) break;
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) ) {
log_error(L"GetModuleInformation failed! (hModule=%p, GLE=%lu)",
hModule, GetLastError());
break;
}
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage,
#ifdef _WIN64
"FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"
#else
ver_verify_version_info(6, 1, 0)
? "833D????????00 743E E8???????? A3????????"
: "8BFF 51 833D????????00 7507 A1????????"
#endif
);
if ( offset != -1 ) {
pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset);
log_info(L"Matched IsDeviceServiceable function! (Offset=%IX, Address=%p)", offset, pTarget);
status = MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL);
if ( status == MH_OK ) {
status = MH_EnableHook(pTarget);
if ( status == MH_OK )
log_info(L"Hooked IsDeviceServiceable! (Address=%p)", pTarget);
else log_error(L"Failed to enable IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status));
} else log_error(L"Failed to create IsDeviceServiceable hook! (Status=%hs)", MH_StatusToString(status));
} else log_info(L"Couldn't match IsDeviceServiceable function! (Already patched?)");
free_iname:
free(pInternalName);
break;
}
free(ptl);
return result;
}

View File

@@ -1,15 +0,0 @@
#pragma once
typedef struct
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
#define SVCHOST_CRASH_THRESHOLD 3
extern HANDLE g_hMainMutex;
bool wufuc_inject(DWORD dwProcessId,
LPTHREAD_START_ROUTINE pStartAddress,
ptrlist_t *list);
bool wufuc_hook(HMODULE hModule);

View File

@@ -19,34 +19,27 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="callbacks.h" />
<ClInclude Include="eventhelper.h" />
<ClInclude Include="mutexhelper.h" />
<ClInclude Include="ptrlist.h" />
<ClInclude Include="log.h" />
<ClInclude Include="modulehelper.h" />
<ClInclude Include="registryhelper.h" />
<ClInclude Include="servicehelper.h" />
<ClInclude Include="versionhelper.h" />
<ClInclude Include="hooks.h" />
<ClInclude Include="asprintf.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="modules.h" />
<ClInclude Include="registry.h" />
<ClInclude Include="helpers.h" />
<ClInclude Include="utf8.h" />
<ClInclude Include="versioninfo.h" />
<ClInclude Include="verify.h" />
<ClInclude Include="patternfind.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="wufuc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="callbacks.c" />
<ClCompile Include="asprintf.c" />
<ClCompile Include="dllmain.c" />
<ClCompile Include="eventhelper.c" />
<ClCompile Include="ptrlist.c" />
<ClCompile Include="modulehelper.c" />
<ClCompile Include="registryhelper.c" />
<ClCompile Include="servicehelper.c" />
<ClCompile Include="mutexhelper.c" />
<ClCompile Include="versionhelper.c" />
<ClCompile Include="hooks.c" />
<ClCompile Include="log.c" />
<ClCompile Include="logger.c" />
<ClCompile Include="memory.c" />
<ClCompile Include="modules.c" />
<ClCompile Include="patternfind.c" />
<ClCompile Include="registry.c" />
<ClCompile Include="stdafx.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
@@ -54,7 +47,9 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rundll32.c" />
<ClCompile Include="wufuc.c" />
<ClCompile Include="helpers.c" />
<ClCompile Include="utf8.c" />
<ClCompile Include="versioninfo.c" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />
@@ -123,8 +118,8 @@
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
@@ -132,8 +127,8 @@
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -141,8 +136,8 @@
<IntDir>$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
@@ -150,8 +145,8 @@
<IntDir>$(ProjectDir)obj\$(Configuration)\$(PlatformShortName)\</IntDir>
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
<GenerateManifest>false</GenerateManifest>
<IncludePath>$(SolutionDir)..\inc\phnt;$(SolutionDir)..\inc\minhook;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\minhook;$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)..\inc\phnt;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -170,11 +165,9 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x86.MTd.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -193,11 +186,9 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x64.MTd.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -224,15 +215,13 @@
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<EntryPointSymbol>
</EntryPointSymbol>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x86.MT.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<SetChecksum>true</SetChecksum>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy release binaries to the setup staging directories</Message>
@@ -261,15 +250,13 @@ copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<AdditionalDependencies>version.lib;Shlwapi.lib;libMinHook.x64.MT.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<AdditionalDependencies>version.lib;Shlwapi.lib;%(AdditionalDependencies);ntdll.lib</AdditionalDependencies>
<SetChecksum>true</SetChecksum>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<ResourceCompile />
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)wufuc_setup\"</Command>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)setup_bat\"
copy /Y "$(TargetPath)" "$(SolutionDir)setup_ai\"</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Copy release binaries to the setup staging directories</Message>

View File

@@ -15,12 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="callbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -30,44 +24,38 @@
<ClInclude Include="patternfind.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="versionhelper.h">
<ClInclude Include="asprintf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="servicehelper.h">
<ClInclude Include="versioninfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="registryhelper.h">
<ClInclude Include="verify.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wufuc.h">
<ClInclude Include="registry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="modulehelper.h">
<ClInclude Include="modules.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="log.h">
<ClInclude Include="logger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ptrlist.h">
<ClInclude Include="utf8.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="eventhelper.h">
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mutexhelper.h">
<ClInclude Include="helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="callbacks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hooks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rundll32.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -77,31 +65,28 @@
<ClCompile Include="patternfind.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="servicehelper.c">
<ClCompile Include="asprintf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="versionhelper.c">
<ClCompile Include="versioninfo.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="registryhelper.c">
<ClCompile Include="modules.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wufuc.c">
<ClCompile Include="registry.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="log.c">
<ClCompile Include="logger.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="modulehelper.c">
<ClCompile Include="utf8.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ptrlist.c">
<ClCompile Include="memory.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mutexhelper.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="eventhelper.c">
<ClCompile Include="helpers.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -110,7 +95,7 @@
<Filter>Source Files</Filter>
</None>
<None Include="resource.h">
<Filter>Header Files</Filter>
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>