24 Commits

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

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

View File

@@ -1,7 +1,13 @@
# wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![Downloads](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg) ![](https://img.shields.io/badge/downloads%20before%20v0.6-13k-brightgreen.svg)](../../releases)
# wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![Build status](https://ci.appveyor.com/api/projects/status/0s2unkpokttyslf0?svg=true)](https://ci.appveyor.com/project/zeffy/wufuc)
Disables the "Unsupported Hardware" message in Windows Update, and allows you to continue installing updates on Windows 7 and 8.1 systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
## Downloads [![Github All Releases](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg)](../../releases)
### You can get the latest stable version [here](../../releases/latest)!
If you are feeling brave, you can try the latest unstable builds [here](https://ci.appveyor.com/project/zeffy/wufuc). **Use these at your own risk!**
## Preface
The changelog for Windows updates KB4012218 and KB4012219 included the following:
@@ -34,7 +40,7 @@ My patch takes advantage of this result caching behavior by setting the "hasn't
- **No system files are modified!**
- Heuristic-based patching, which means it will usually keep working even after updates.
- C is best language.
- No external dependencies.
- No external dependencies.
### How to install/uninstall?
@@ -42,6 +48,16 @@ Just download the [latest release](../../releases/latest), and extract the `wufu
To uninstall run `uninstall_wufuc.bat` as administrator.
### How to update when a new version comes out?
Unless otherwise noted, you should only have to:
- Run `disable_wufuc.bat` as administrator.
- Copy the new files into the install folder, overwriting the old ones.
- Run the new `install_wufuc.bat` as administrator.
If you run into problems, try doing a full uninstall/reinstall.
### How do I remove your old patch and use this instead?
I've included a utility script called `repair_wuaueng.dll.bat`. When you run it, it will initiate an `sfc` scan and revert any changes made to `wuaueng.dll`.

28
appveyor.yml Normal file
View File

@@ -0,0 +1,28 @@
version: 0.6.1.{build}
skip_commits:
files:
- README.md
image: Visual Studio 2017
configuration: Release
platform:
- x86
- x64
build:
verbosity: minimal
after_build:
- cmd: >-
set "ZIP_NAME=..\%APPVEYOR_PROJECT_NAME%_v%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,8%_%PLATFORM%.zip"
cd "%APPVEYOR_BUILD_FOLDER%\install"
unix2dos "COPYING.txt"
for /R %%G in (*.bat) do unix2dos "%%G"
7z a "%ZIP_NAME%" "..\install"
7z rn "%ZIP_NAME%" "install" "wufuc"
artifacts:
- path: '*.zip'

View File

@@ -36,30 +36,34 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :check_ver
goto :is_x86
)
)
goto :unsupported_os
:is_x86
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :get_ver
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0wufuc64.dll"
:get_ver
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i"
title wufuc installer - v%Version%
:check_ver
wmic /output:stdout os get version | findstr "^6\.1\." >nul && (
set "WINDOWS_VER=6.1"
set "SUPPORTED_HOTFIXES=KB4019265 KB4019264 KB4015552 KB4015549 KB4015546 KB4012218"
set "SUPPORTED_HOTFIXES=KB4022722 KB4022719 KB4019265 KB4019264 KB4015552 KB4015549 KB4015546 KB4012218"
echo Detected supported operating system: Windows 7 %WINDOWS_ARCHITECTURE%
goto :check_hotfix
)
wmic /output:stdout os get version | findstr "^6\.3\." >nul && (
set "WINDOWS_VER=8.1"
set "SUPPORTED_HOTFIXES=KB4019217 KB4019215 KB4015553 KB4015550 KB4015547 KB4012219"
set "SUPPORTED_HOTFIXES=KB4022726 KB4022717 KB4019217 KB4019215 KB4015553 KB4015550 KB4015547 KB4012219"
echo Detected supported operating system: Windows 8.1 %WINDOWS_ARCHITECTURE%
goto :check_hotfix
)
@@ -83,22 +87,17 @@ for %%a in (%SUPPORTED_HOTFIXES%) do (
goto :confirmation
)
)
wmic /output:stdout qfe get /value 2>&1 | find "No Instance(s) Available" >nul && (
echo WARNING - wmic qfe is broken, can't check installed updates...
goto :confirmation
)
echo.
echo WARNING - Detected that no supported updates are installed!
echo WARNING - Detected that no supported updates are installed.
echo.
echo This can be a false warning, sometimes it is caused by the WMI
echo Win32_QuickFixEngineering class being broken. If you are certain
echo that you need wufuc, then you can continue ^(there should be no
echo side effects even if you don't need it^).
echo.
echo This warning could also mean that a new update came out and the
echo installer script's list of updates hasn't been updated yet. If
echo this is the case and you know which update it is, feel free to
echo create an issue. https://github.com/zeffy/wufuc/issues
set /p CONTINUE=Enter 'Y' if you still want to continue:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo This warning could also mean that a new update came out and the
echo wufuc installer script's list of updates hasn't been updated yet.
echo If this is definitely the case and you know which update it is,
echo feel free to create an issue. https://github.com/zeffy/wufuc/issues
:confirmation
echo.
@@ -106,13 +105,15 @@ echo wufuc disables the "Unsupported Hardware" message in Windows Update,
echo and allows you to continue installing updates on Windows 7 and 8.1
echo systems with Intel Kaby Lake, AMD Ryzen, or other unsupported processors.
echo.
echo Please be absolutely sure you really need wufuc before continuing.
echo.
set /p CONTINUE=Enter 'Y' if you want to install wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
:install
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
net start Schedule
schtasks /Create /XML "%~dp0wufuc.xml" /TN "%wufuc_task%" /F
schtasks /Change /TN "%wufuc_task%" /TR "'%systemroot%\system32\rundll32.exe' """%wufuc_dll%""",Rundll32Entry"
schtasks /Change /TN "%wufuc_task%" /ENABLE

View File

@@ -34,17 +34,21 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :confirmation
goto :is_x86
)
)
goto :die
:is_x86
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :get_ver
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0wufuc64.dll"
:get_ver
for /f "tokens=*" %%i in ('wmic /output:stdout datafile where "name='%wufuc_dll:\=\\%'" get Version /value ^| find "="') do set "%%i"
title wufuc uninstaller - v%Version%
@@ -55,6 +59,7 @@ echo.
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
rundll32 "%wufuc_dll%",Rundll32Unload
net start Schedule
schtasks /Delete /TN "%wufuc_task%" /F
echo.

View File

@@ -34,24 +34,22 @@ if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
goto :is_x64
)
if /I "%PROCESSOR_ARCHITECTURE%"=="x86" (
set "WINDOWS_ARCHITECTURE=x86"
set "wufuc_dll=%~dp0wufuc32.dll"
goto :confirmation
goto :is_x86
)
)
goto :die
:is_x86
set "wufuc_dll=%~dp0..\wufuc32.dll"
goto :disable
:is_x64
set "WINDOWS_ARCHITECTURE=x64"
set "wufuc_dll=%~dp0..\wufuc64.dll"
:confirmation
set /p CONTINUE=Enter 'Y' if you want to disable wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
:disable
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
rundll32 "%wufuc_dll%",Rundll32Unload
net start Schedule
schtasks /Change /TN "%wufuc_task%" /DISABLE
echo.
@@ -59,12 +57,5 @@ echo Disabled wufuc! You will still be able to check for updates until you resta
:die
echo.
echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...
pause >nul
pause
exit

View File

@@ -27,11 +27,8 @@ fltmc >nul 2>&1 || (
goto :die
)
set /p CONTINUE=Enter 'Y' if you want to enable wufuc:
if /I not "%CONTINUE%"=="Y" goto :cancel
echo.
set "wufuc_task=wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}"
net start Schedule
schtasks /Change /TN "%wufuc_task%" /ENABLE
schtasks /Run /TN "%wufuc_task%"
@@ -40,12 +37,5 @@ echo Enabled and started wufuc!
:die
echo.
echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...
pause >nul
pause
exit

View File

@@ -8,26 +8,23 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C2147FF-2B83-479B-813E-5ACB86F43042}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|Any CPU.ActiveCfg = Debug|Win32
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.ActiveCfg = Debug|x64
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x64.Build.0 = Debug|x64
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.ActiveCfg = Debug|Win32
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Debug|x86.Build.0 = Debug|Win32
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|Any CPU.ActiveCfg = Release|Win32
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.ActiveCfg = Release|x64
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x64.Build.0 = Release|x64
{00F96695-CE41-4C2F-A344-6219DFB4F887}.Release|x86.ActiveCfg = Release|Win32

View File

@@ -1,13 +1,13 @@
#include <stdint.h>
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <aclapi.h>
#include <sddl.h>
#include "core.h"
#include "process.h"
#include "service.h"
#include "util.h"
#include "patternfind.h"
#include "core.h"
DWORD WINAPI NewThreadProc(LPVOID lpParam) {
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
@@ -44,95 +44,81 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) {
DETOUR_IAT(hm, LoadLibraryExA);
DETOUR_IAT(hm, LoadLibraryExW);
HMODULE hwu = GetModuleHandle(_T("wuaueng.dll"));
if (hwu) {
PatchWUModule(hwu);
TCHAR lpServiceDll[MAX_PATH + 1];
get_svcdll(_T("wuauserv"), lpServiceDll, _countof(lpServiceDll));
HMODULE hwu = GetModuleHandle(lpServiceDll);
if (hwu && PatchWUAgentHMODULE(hwu)) {
_tdbgprintf(_T("Patched previously loaded Windows Update module!"));
}
ResumeAndCloseThreads(lphThreads, cb);
WaitForSingleObject(hEvent, INFINITE);
_tdbgprintf(_T("Received wufuc_UnloadEvent, removing hooks."));
_tdbgprintf(_T("Unload event was set."));
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
RESTORE_IAT(hm, LoadLibraryExA);
RESTORE_IAT(hm, LoadLibraryExW);
ResumeAndCloseThreads(lphThreads, cb);
_tdbgprintf(_T("Unloading library. Cya!"));
CloseHandle(hEvent);
_tdbgprintf(_T("See ya!"));
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
return 0;
}
BOOL IsWUModule(HMODULE hModule) {
TCHAR lpBaseName[MAX_PATH + 1];
GetModuleBaseName(GetCurrentProcess(), hModule, lpBaseName, _countof(lpBaseName));
return !_tcsicmp(lpBaseName, _T("wuaueng.dll"));
}
BOOL PatchWUModule(HMODULE hModule) {
if (!IsWindows7Or8Point1()) {
BOOL PatchWUAgentHMODULE(HMODULE hModule) {
LPSTR pattern;
SIZE_T offset00, offset01;
if (Is64BitWindows()) {
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
offset00 = 10;
offset01 = 18;
} else if (WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
pattern = "833D????????00 743E E8???????? A3????????";
offset00 = 2;
offset01 = 15;
} else if (WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
pattern = "8BFF 51 833D????????00 7507 A1????????";
offset00 = 5;
offset01 = 13;
} else {
return FALSE;
}
LPSTR lpszPattern;
SIZE_T n1, n2;
#ifdef _WIN64
lpszPattern =
"FFF3" // push rbx
"4883EC??" // sub rsp,??
"33DB" // xor ebx,ebx
"391D????????" // cmp dword ptr ds:[???????????],ebx
"7508" // jnz $+8
"8B05????????"; // mov eax,dword ptr ds:[???????????]
n1 = 10;
n2 = 18;
#elif defined(_WIN32)
if (IsWindows8Point1()) {
lpszPattern =
"8BFF" // mov edi,edi
"51" // push ecx
"833D????????00" // cmp dword ptr ds:[????????],0
"7507" // jnz $+7
"A1????????"; // mov eax,dword ptr ds:[????????]
n1 = 5;
n2 = 13;
} else if (IsWindows7()) {
lpszPattern =
"833D????????00" // cmp dword ptr ds:[????????],0
"743E" // je $+3E
"E8????????" // call <wuaueng.IsCPUSupported>
"A3????????"; // mov dword ptr ds:[????????],eax
n1 = 2;
n2 = 15;
}
#else
return FALSE;
#endif
MODULEINFO modinfo;
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO));
SIZE_T rva;
if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &rva)) {
SIZE_T rva = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, 0, pattern);
if (rva == -1) {
_tdbgprintf(_T("No pattern match!"));
return FALSE;
}
SIZE_T fpIsDeviceServiceable = (SIZE_T)modinfo.lpBaseOfDll + rva;
_tdbgprintf(_T("IsDeviceServiceable(void) matched at %p"), fpIsDeviceServiceable);
BOOL *lpbNotRunOnce = (BOOL *)(fpIsDeviceServiceable + n1 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n1));
if (*lpbNotRunOnce) {
*lpbNotRunOnce = FALSE;
_tdbgprintf(_T("Patched %p=%d"), lpbNotRunOnce, *lpbNotRunOnce);
uintptr_t baseAddress = (uintptr_t)modinfo.lpBaseOfDll;
uintptr_t fpIsDeviceServiceable = baseAddress + rva;
_tdbgprintf(_T("Found address of IsDeviceServiceable. (%p)"), fpIsDeviceServiceable);
BOOL result = FALSE;
LPBOOL lpbFirstRun, lpbIsCPUSupportedResult;
if (Is64BitWindows()) {
lpbFirstRun = (LPBOOL)(fpIsDeviceServiceable + offset00 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset00));
lpbIsCPUSupportedResult = (LPBOOL)(fpIsDeviceServiceable + offset01 + sizeof(uint32_t) + *(uint32_t *)(fpIsDeviceServiceable + offset01));
} else {
lpbFirstRun = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset00));
lpbIsCPUSupportedResult = (LPBOOL)(*(uintptr_t *)(fpIsDeviceServiceable + offset01));
}
BOOL *lpbCachedResult = (BOOL *)(fpIsDeviceServiceable + n2 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n2));
if (!*lpbCachedResult) {
*lpbCachedResult = TRUE;
_tdbgprintf(_T("Patched %p=%d"), lpbCachedResult, *lpbCachedResult);
if (*lpbFirstRun) {
*lpbFirstRun = FALSE;
_tdbgprintf(_T("Changed first run to FALSE. (%p=%08x)"), lpbFirstRun, *lpbFirstRun);
result = TRUE;
}
return TRUE;
if (!*lpbIsCPUSupportedResult) {
*lpbIsCPUSupportedResult = TRUE;
_tdbgprintf(_T("Changed cached result to TRUE. (%p=%08x)."),
lpbIsCPUSupportedResult, *lpbIsCPUSupportedResult);
result = TRUE;
}
return result;
}
HMODULE WINAPI _LoadLibraryExA(
@@ -141,8 +127,16 @@ HMODULE WINAPI _LoadLibraryExA(
_In_ DWORD dwFlags
) {
HMODULE result = LoadLibraryExA(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) {
PatchWUModule(result);
if (result) {
_dbgprintf("Loaded %s.", lpFileName);
CHAR path[MAX_PATH + 1];
if (!get_svcdllA("wuauserv", path, _countof(path))) {
return result;
}
if (!_stricmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
_dbgprintf("Patched Windows Update module!");
}
}
return result;
}
@@ -153,8 +147,16 @@ HMODULE WINAPI _LoadLibraryExW(
_In_ DWORD dwFlags
) {
HMODULE result = LoadLibraryExW(lpFileName, hFile, dwFlags);
if (IsWUModule(result)) {
PatchWUModule(result);
if (result) {
_wdbgprintf(L"Loaded library: %s.", lpFileName);
WCHAR path[MAX_PATH + 1];
if (!get_svcdllW(L"wuauserv", path, _countof(path))) {
return result;
}
if (!_wcsicmp(lpFileName, path) && PatchWUAgentHMODULE(result)) {
_wdbgprintf(L"Patched Windows Update module!");
}
}
return result;
};

View File

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

View File

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

117
wufuc/patternfind.c Normal file
View File

@@ -0,0 +1,117 @@
#include <Windows.h>
#include "patternfind.h"
/* Work in progress. Ported to C from x64dbg's patternfind.cpp:
<https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp>
x64dbg license (GPL-3.0):
<https://github.com/x64dbg/x64dbg/blob/development/LICENSE> */
int hexchtoint(CHAR c) {
int result = -1;
if (c >= '0' && c <= '9') {
result = c - '0';
} else if (c >= 'A' && c <= 'F') {
result = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
result = c - 'a' + 10;
}
return result;
}
SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize) {
SIZE_T len = strlen(patterntext);
SIZE_T result = 0;
for (SIZE_T i = 0; i < len && (!formattext || result < formattextsize); i++) {
if (patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1) {
if (formattext) {
formattext[result] = patterntext[i];
}
result++;
}
}
return result;
}
BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize) {
SIZE_T cb = formathexpattern(patterntext, NULL, 0);
if (!cb || cb > *patternsize) {
return FALSE;
}
LPSTR formattext = calloc(cb, sizeof(CHAR));
cb = formathexpattern(patterntext, formattext, cb);
if (cb % 2) {
formattext[cb++] = '?';
}
formattext[cb] = '\0';
for (SIZE_T i = 0, j = 0, k = 0; i < cb; i++, j ^= 1, k = (i - j) >> 1) {
if (formattext[i] == '?') {
pattern[k].nibble[j].wildcard = TRUE;
} else {
pattern[k].nibble[j].wildcard = FALSE;
pattern[k].nibble[j].data = hexchtoint(formattext[i]) & 0xf;
}
}
free(formattext);
*patternsize = cb >> 1;
return TRUE;
}
SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern) {
SIZE_T result = -1;
SIZE_T searchpatternsize = strlen(pattern);
LPPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE));
if (patterntransform(pattern, searchpattern, &searchpatternsize)) {
for (SIZE_T i = startindex, j = 0; i < datasize; i++) //search for the pattern
{
if ((searchpattern[j].nibble[0].wildcard || searchpattern[j].nibble[0].data == ((data[i] >> 4) & 0xf))
&& (searchpattern[j].nibble[1].wildcard || searchpattern[j].nibble[1].data == (data[i] & 0xf))) { //check if our pattern matches the current byte
if (++j == searchpatternsize) { //everything matched
result = i - searchpatternsize + 1;
break;
}
} else if (j > 0) { //fix by Computer_Angel
i -= j;
j = 0; //reset current pattern position
}
}
}
return result;
}
//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte) {
// BYTE n1 = (*byte >> 4) & 0xf;
// BYTE n2 = *byte & 0xf;
// if (!pbyte->nibble[0].wildcard) {
// n1 = pbyte->nibble[0].data;
// }
// if (!pbyte->nibble[1].wildcard) {
// n2 = pbyte->nibble[1].data;
// }
// *byte = ((n1 << 4) & 0xf0) | (n2 & 0xf);
//}
//
//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern) {
// SIZE_T writepatternsize = strlen(pattern);
// if (writepatternsize > datasize) {
// writepatternsize = datasize;
// }
// LPPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE));
// if (!patterntransform(pattern, writepattern, &writepatternsize)) {
// return;
// }
// for (size_t i = 0; i < writepatternsize; i++) {
// patternwritebyte(&data[i], &writepattern[i]);
// }
//}
//
//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern) {
// SIZE_T result = patternfind(data, datasize, startindex, searchpattern, NULL, 0);
// if (result == -1)
// return result;
// patternwrite(data + result, datasize - result, replacepattern);
// return result;
//}

16
wufuc/patternfind.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
typedef struct _PATTERNBYTE {
struct _PATTERNNIBBLE {
BYTE data;
BOOL wildcard;
} nibble[2];
} PATTERNBYTE, *PPATTERNBYTE, *LPPATTERNBYTE;
int hexchtoint(CHAR ch);
SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize);
BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize);
SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern);
//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte);
//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern)
//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern);

View File

@@ -2,16 +2,24 @@
#include <TlHelp32.h>
#include <tchar.h>
#include "service.h"
#include "process.h"
#include "util.h"
void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
if (!WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)
&& !WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) {
return;
}
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (hEvent) {
CloseHandle(hEvent);
return;
}
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
if (!hSCManager) {
return;
}
TCHAR lpGroupName[256];
DWORD dwProcessId;
BOOL result = get_svcpid(hSCManager, _T("wuauserv"), &dwProcessId);
@@ -26,15 +34,37 @@ void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int n
GetModuleFileName(HINST_THISCOMPONENT, lpLibFileName, _countof(lpLibFileName));
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (!hProcess) {
return;
}
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, _countof(lpLibFileName) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (lpBaseAddress && WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, _countof(lpLibFileName), NULL)) {
InjectLibrary(hProcess, lpLibFileName, _countof(lpLibFileName));
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (hSnap) {
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if (Module32First(hSnap, &me)) {
do {
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
break;
}
} while (Module32Next(hSnap, &me));
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
CloseHandle(hThread);
}
CloseHandle(hSnap);
}
}
CloseHandle(hProcess);
}
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (hEvent) {
_tdbgprintf(_T("Setting wufuc_UnloadEvent..."));
_tdbgprintf(_T("Setting unload event..."));
SetEvent(hEvent);
CloseHandle(hEvent);
}

View File

@@ -1,25 +1,33 @@
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "util.h"
#include "service.h"
#include "shellapihelper.h"
#include "service.h"
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
if (!hService) {
return FALSE;
}
BOOL get_svcdllA(LPCSTR lpServiceName, LPSTR lpServiceDll, DWORD dwSize) {
CHAR lpSubKey[MAX_PATH + 1];
sprintf_s(lpSubKey, _countof(lpSubKey), "SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
DWORD cbBytesNeeded;
QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded);
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded);
CloseServiceHandle(hService);
if (result) {
_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName);
}
free(sc);
return result;
DWORD uBytes = _MAX_PATH + 1;
LPBYTE pvData = malloc(uBytes);
RegGetValueA(HKEY_LOCAL_MACHINE, lpSubKey, "ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
ExpandEnvironmentStringsA((LPSTR)pvData, lpServiceDll, dwSize);
return TRUE;
}
BOOL get_svcdllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize) {
WCHAR lpSubKey[MAX_PATH + 1];
swprintf_s(lpSubKey, _countof(lpSubKey), L"SYSTEM\\CurrentControlSet\\services\\%s\\Parameters", lpServiceName);
DWORD uBytes = _MAX_PATH + 1;
LPBYTE pvData = malloc(uBytes);
RegGetValueW(HKEY_LOCAL_MACHINE, lpSubKey, L"ServiceDll", RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, NULL, pvData, &uBytes);
ExpandEnvironmentStringsW((LPWSTR)pvData, lpServiceDll, dwSize);
return TRUE;
}
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
@@ -31,8 +39,11 @@ BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessI
SERVICE_STATUS_PROCESS lpBuffer;
DWORD cbBytesNeeded;
BOOL result = FALSE;
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded) && lpBuffer.dwProcessId) {
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded)
&& lpBuffer.dwProcessId) {
*lpdwProcessId = lpBuffer.dwProcessId;
_tdbgprintf(_T("Got pid for service %s: %d."), lpServiceName, *lpdwProcessId);
result = TRUE;
}
CloseServiceHandle(hService);
@@ -57,9 +68,9 @@ BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupNam
if (!_tcsicmp(fname, _T("svchost"))) {
LPWSTR *p = argv;
for (int i = 1; i < numArgs; i++) {
if (!_tcsicmp(*(p++), _T("-k"))) {
_tcscpy_s(lpGroupName, dwSize, *p);
if (!_tcsicmp(*(p++), _T("-k")) && !_tcscpy_s(lpGroupName, dwSize, *p)) {
result = TRUE;
_tdbgprintf(_T("Got group name of service %s: %s."), lpServiceName, lpGroupName);
break;
}
}
@@ -67,22 +78,40 @@ BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupNam
return result;
}
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
if (!hService) {
return FALSE;
}
DWORD cbBytesNeeded;
BOOL result = FALSE;
if (!QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
if (QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded) && !_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName)) {
result = TRUE;
}
free(sc);
}
CloseServiceHandle(hService);
return result;
}
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
DWORD uBytes = 0x100000;
LPBYTE pvData = malloc(uBytes);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"),
lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
BOOL result = FALSE;
for (LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1) {
DWORD dwProcessId;
TCHAR group[256];
if (get_svcpid(hSCManager, p, &dwProcessId)) {
get_svcgname(hSCManager, p, group, _countof(group));
result = !_tcsicmp(group, lpServiceGroupName);
}
if (result) {
if (get_svcpid(hSCManager, p, &dwProcessId)
&& (get_svcgname(hSCManager, p, group, _countof(group)) && !_tcsicmp(group, lpServiceGroupName))) {
*lpdwProcessId = dwProcessId;
result = TRUE;
_tdbgprintf(_T("Got pid for service group %s: %d."), lpServiceGroupName, *lpdwProcessId);
break;
}
}

View File

@@ -1,9 +1,20 @@
#pragma once
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
BOOL get_svcdllA(LPCSTR lpServiceName, LPSTR lpServiceDll, DWORD dwSize);
BOOL get_svcdllW(LPCWSTR lpServiceName, LPWSTR lpServiceDll, DWORD dwSize);
#ifdef UNICODE
#define get_svcdll get_svcdllW
#else
#define get_svcdll get_svcdllA
#endif
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);

View File

@@ -1,6 +1,5 @@
#include <Windows.h>
#include <stdio.h>
#include <VersionHelpers.h>
#include <TlHelp32.h>
#include <tchar.h>
#include "util.h"
@@ -17,13 +16,13 @@ VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID l
if (lpOldAddress) {
*lpOldAddress = *lpAddress;
}
_dbgprintf("%s %p => %p", lpFuncName, *lpAddress, lpNewAddress);
_dbgprintf("Detoured %s from %p to %p.", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
SIZE_T hm = (SIZE_T)hModule;
uintptr_t hm = (uintptr_t)hModule;
for (PIMAGE_IMPORT_DESCRIPTOR iid = (PIMAGE_IMPORT_DESCRIPTOR)(hm + ((PIMAGE_NT_HEADERS)(hm + ((PIMAGE_DOS_HEADER)hm)->e_lfanew))
->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); iid->Name; iid++) {
@@ -39,70 +38,6 @@ LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
return NULL;
}
BOOL FindPattern(LPCBYTE pvData, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset) {
SIZE_T length = strlen(lpszPattern);
SIZE_T nBytes;
if (length % 2 || (nBytes = length / 2) > nNumberOfBytes) {
return FALSE;
}
LPBYTE lpBytes = malloc(nBytes * sizeof(BYTE));
BOOL *lpbwc = malloc(nBytes * sizeof(BOOL));
LPSTR p = lpszPattern;
BOOL valid = TRUE;
for (SIZE_T i = 0; i < nBytes; i++) {
if ((lpbwc[i] = strncmp(p, "??", 2)) && sscanf_s(p, "%2hhx", &lpBytes[i]) != 1) {
valid = FALSE;
break;
}
p += 2;
}
BOOL result = FALSE;
if (valid) {
for (SIZE_T i = nStart; i < nNumberOfBytes - nStart - (nBytes - 1); i++) {
BOOL found = TRUE;
for (SIZE_T j = 0; j < nBytes; j++) {
if (lpbwc[j] && pvData[i + j] != lpBytes[j]) {
found = FALSE;
break;
}
}
if (found) {
*lpOffset = i;
result = TRUE;
break;
}
}
}
free(lpBytes);
free(lpbwc);
return result;
}
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb) {
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, cb, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, cb, NULL)) {
return FALSE;
}
DWORD dwProcessId = GetProcessId(hProcess);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
MODULEENTRY32 me;
me.dwSize = sizeof(me);
Module32First(hSnap, &me);
do {
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
break;
}
} while (Module32Next(hSnap, &me));
CloseHandle(hSnap);
_tdbgprintf(_T("Injecting %s into process %d"), lpLibFileName, dwProcessId);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
CloseHandle(hThread);
return TRUE;
}
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te;
@@ -122,7 +57,7 @@ VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThrea
CloseHandle(hSnap);
*lpcb = count;
_tdbgprintf(_T("Suspended other threads."));
_tdbgprintf(_T("Suspended %d other threads."), count);
}
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
@@ -130,19 +65,38 @@ VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
_tdbgprintf(_T("Resumed threads."));
_tdbgprintf(_T("Resumed %d other threads."), cb);
}
BOOL IsWindows7Or8Point1(void) {
return IsWindows7() || IsWindows8Point1();
BOOL WindowsVersionCompare(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = dwMajorVersion;
osvi.dwMinorVersion = dwMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
osvi.wServicePackMinor = wServicePackMinor;
DWORDLONG dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, Operator);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, Operator);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, Operator);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMINOR, Operator);
return VerifyVersionInfo(&osvi, dwTypeMask, dwlConditionMask);
}
BOOL IsWindows7(void) {
return IsWindows7OrGreater() && !IsWindows8OrGreater();
}
BOOL IsWindows8Point1(void) {
return IsWindows8Point1OrGreater() && !IsWindows10OrGreater();
BOOL Is64BitWindows(void) {
#if defined(_WIN64)
return TRUE; // 64-bit programs run only on Win64
#elif defined(_WIN32)
// 32-bit programs run on both 32-bit and 64-bit Windows
// so must sniff
BOOL f64 = FALSE;
return IsWow64Process(GetCurrentProcess(), &f64) && f64;
#else
return FALSE; // Win64 does not support Win16
#endif
}
VOID _wdbgprintf(LPCWSTR format, ...) {

View File

@@ -14,19 +14,13 @@ VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID l
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset);
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb);
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);
BOOL IsWindows7Or8Point1(void);
BOOL WindowsVersionCompare(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask);
BOOL IsWindows7(void);
BOOL IsWindows8Point1(void);
BOOL Is64BitWindows(void);
VOID _wdbgprintf(LPCWSTR format, ...);
VOID _dbgprintf(LPCSTR format, ...);

Binary file not shown.

View File

@@ -177,7 +177,8 @@
<ItemGroup>
<ClCompile Include="core.c" />
<ClCompile Include="dllmain.c" />
<ClCompile Include="entrypoint.c" />
<ClCompile Include="patternfind.c" />
<ClCompile Include="rundll32.c" />
<ClCompile Include="service.c" />
<ClCompile Include="util.c" />
</ItemGroup>
@@ -186,6 +187,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="core.h" />
<ClInclude Include="patternfind.h" />
<ClInclude Include="service.h" />
<ClInclude Include="shellapihelper.h" />
<ClInclude Include="util.h" />