22 Commits

Author SHA1 Message Date
zeffy
af062f47d7 0.6.0.1 2017-06-05 16:27:35 -07:00
zeffy
7f0784424f spaces > tabs 2017-06-05 15:50:18 -07:00
zeffy
b02ad7a9d6 minor fixes, build events 2017-06-05 15:30:45 -07:00
zeffy
9d90abc0de refactoring 2017-06-05 15:17:39 -07:00
zeffy
2f4355e616 refactoring 2017-06-05 14:33:03 -07:00
zeffy
f74f30e3a9 rename debug print method and split to ansi/unicode 2017-06-05 07:44:06 -07:00
zeffy
712ef4e38b Update README.md 2017-06-04 18:16:05 -07:00
zeffy
a28e098cee current year 2017-06-04 18:01:48 -07:00
zeffy
66c10c4067 Update README.md 2017-06-04 17:59:35 -07:00
zeffy
1a69d35642 Update README.md 2017-06-04 17:59:22 -07:00
zeffy
0094d19358 add text about debugview 2017-06-04 17:44:24 -07:00
zeffy
3a3e195c6b minor changes 2017-06-04 17:28:30 -07:00
zeffy
2ff1e01cc8 Update README.md 2017-06-04 15:34:42 -07:00
zeffy
dfc7f82036 Update README.md 2017-06-04 15:11:20 -07:00
zeffy
490bc062b4 Update wufuc.sln 2017-06-04 15:04:03 -07:00
zeffy
3ce7f39269 Update README.md 2017-06-04 15:03:40 -07:00
zeffy
500eddf349 Update version.rc 2017-06-04 14:57:10 -07:00
zeffy
49d32db491 Update README.md 2017-06-04 14:57:01 -07:00
zeffy
fd984db033 Update README.md 2017-06-04 14:43:07 -07:00
zeffy
d1df067812 Update repair_wuaueng.dll.bat 2017-06-04 14:35:34 -07:00
zeffy
6e67f6de80 Update install_wufuc.bat 2017-06-04 14:34:11 -07:00
zeffy
45a2b915f9 Update README.md, delete stray wufuc.xml 2017-06-04 13:46:09 -07:00
21 changed files with 467 additions and 461 deletions

View File

@@ -1,4 +1,4 @@
# wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![download count](https://img.shields.io/github/downloads/zeffy/kb4012218-19/total.svg)](https://github.com/zeffy/kb4012218-19/releases/latest)
# wufuc [![a.k.a. kb4012218-19](https://img.shields.io/badge/a.k.a.-kb4012218--19-blue.svg)](../../tree/old-kb4012218-19) [![downloads](https://img.shields.io/github/downloads/zeffy/wufuc/total.svg) ![downloads before v0.6](https://img.shields.io/badge/downloads%20before%20v0.6-13k-brightgreen.svg)](https://github.com/zeffy/wufuc/releases/latest)
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.
@@ -24,25 +24,39 @@ My patch takes advantage of this result caching behavior by setting the "hasn't
## How it works
- On system boot the `wufuc` scheduled task runs under the `NT AUTHORITY\SYSTEM` user.
- `wufuc` determines what service host process the Windows Update service (`wuauserv`) runs in, and injects itself into it.
- At system boot the wufuc scheduled task runs as the `NT AUTHORITY\SYSTEM` user.
- `wufuc` determines what service host group process the Windows Update service runs in (typically `netsvcs`), and injects itself into it.
- Once injected, it applies a hook to `LoadLibraryEx` that automatically patches `wuaueng.dll` when it is loaded.
- Any previously loaded `wuaueng.dll` is also patched.
### Several improvements over my script-based approach:
- **No system files are modified!***
- Heuristic byte signature patching persists over new updates.
### Several improvements over my xdelta3/batch script method:
- **No system files are modified!**
- Heuristic-based patching, which means it will usually keep working even after updates.
- C is best language.
- No external dependencies except for Microsoft Visual C++ 2015 Redistributable.
- No external dependencies except for Microsoft Visual C++ 2017 Redistributable.
### How to install/uninstall?
Just run move the `wufuc` folder to wherever you want and run `install_wufuc.bat` as administrator.
Just download the [latest release](https://github.com/zeffy/wufuc/releases/latest), and extract the `wufuc` folder to a permanent location (like `C:\Program Files\wufuc`) and then run `install_wufuc.bat` as administrator.
To uninstall run `uninstall_wufuc.bat` as administrator.
To temporarily disable the patch, just go to the Task Scheduler and disable the `wufuc.{ ... }` task, then restart your computer.
To temporarily disable the patch, just go to the Task Scheduler and disable the `wufuc.{72EEE38B-9997-42BD-85D3-2DD96DA17307}` task, then restart your computer.
### How do I remove your old patch and use this instead?
I've included a utility script called `repair_wuaueng.dll.bat` that will initiate an sfc scan and attempt to automatically revert any changes made to `wuaueng.dll`.
I've included a utility script called `repair_wuaueng.dll.bat` that will initiate an sfc scan and revert any changes made to `wuaueng.dll`.
### How to see wufuc's debugging message output?
You will need to download [DebugView](https://technet.microsoft.com/en-us/sysinternals/debugview.aspx) to do this.
The best way to get a log of the entire life-cycle of wufuc is to do the following:
1. Disable wufuc in Task Scheduler.
2. Restart your computer.
3. Start `DebugView.exe` as administrator and check `Capture -> Capture Global Win32`.
4. Enable wufuc in Task Scheduler.
5. Run wufuc in Task Scheduler.
6. Output will be shown in DebugView.

View File

@@ -1,5 +1,5 @@
@echo off
title wufuc installer - v0.6
title wufuc installer - v0.6.0.1
:: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title wufuc installer - v0.6
:: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy
echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
@@ -76,7 +76,7 @@ goto :die
for %%a in (%SUPPORTED_HOTFIXES%) do (
wmic /output:stdout qfe get hotfixid | find "%%a" >nul && (
set "INSTALLED_HOTFIX=%%a"
echo Detected installed supported update: %%a
echo Detected supported installed update: %%a
goto :confirmation
)
)
@@ -84,8 +84,15 @@ for %%a in (%SUPPORTED_HOTFIXES%) do (
echo.
echo WARNING - Detected that no supported updates are installed!
echo.
echo This can be a false warning, if you are certain that need wufuc then you
echo can continue (there will be no side effects even if you don't need it)
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
@@ -123,7 +130,9 @@ rundll32 "%wufuc_dll%",Rundll32Unload
schtasks /Run /TN "%wufuc_task%"
echo.
echo Installed and started wufuc!
echo Installed and started wufuc, you can now continue installing updates! :^)
echo.
echo To uninstall, run uninstall_wufuc.bat as administrator.
goto :die
:die
@@ -132,7 +141,6 @@ echo Press any key to exit...
pause >nul
exit
:cancel
echo.
echo Canceled by user, press any key to exit...

View File

@@ -1,5 +1,5 @@
@echo off
title install wufuc (repair wuaueng.dll) - v0.6
title install wufuc ^(repair wuaueng.dll^) - v0.6.0.1
:: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title install wufuc (repair wuaueng.dll) - v0.6
:: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy
echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.

View File

@@ -1,5 +1,5 @@
@echo off
title wufuc uninstaller - v0.6
title wufuc uninstaller - v0.6.0.1
:: Copyright (C) 2017 zeffy
:: This program is free software: you can redistribute it and/or modify
@@ -15,7 +15,7 @@ title wufuc uninstaller - v0.6
:: You should have received a copy of the GNU General Public License
:: along with this program. If not, see <http://www.gnu.org/licenses/>.
echo Copyright (C) 2017 zeffy
echo Copyright ^(C^) 2017 zeffy
echo This program comes with ABSOLUTELY NO WARRANTY.
echo This is free software, and you are welcome to redistribute it
echo under certain conditions; see COPYING.txt for details.
@@ -56,7 +56,7 @@ rundll32 "%wufuc_dll%",Rundll32Unload
schtasks /Delete /TN "%wufuc_task%" /F
echo.
echo Unloaded and uninstalled wufuc!
echo Unloaded and uninstalled wufuc. :^(
:die
echo.

Binary file not shown.

View File

@@ -10,7 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitignore = .gitignore
LICENSE = LICENSE
README.md = README.md
wufuc.xml = wufuc.xml
EndProjectSection
EndProject
Global

BIN
wufuc.xml

Binary file not shown.

View File

@@ -13,7 +13,7 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) {
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
TCHAR lpBinaryPathName[0x8000];
QueryServiceBinaryPathName(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName));
get_svcpath(hSCManager, _T("wuauserv"), lpBinaryPathName, _countof(lpBinaryPathName));
BOOL result = _tcsicmp(GetCommandLine(), lpBinaryPathName);
CloseServiceHandle(hSCManager);
@@ -27,22 +27,23 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) {
ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:PAI(A;;FA;;;BA)"), SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL);
sa.bInheritHandle = FALSE;
HANDLE hEvent = CreateEvent(&sa, FALSE, FALSE, _T("Global\\wufuc_UnloadEvent"));
HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (!hEvent) {
return 0;
}
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
HANDLE lphThreads[0x1000];
SIZE_T cb;
SuspendProcess(lphThreads, _countof(lphThreads), &cb);
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
HMODULE hm = GetModuleHandle(NULL);
DETOUR_IAT(hm, LoadLibraryExA);
DETOUR_IAT(hm, LoadLibraryExW);
DbgPrint("Applied LoadLibraryEx hooks.");
HMODULE hwu = GetModuleHandle(_T("wuaueng.dll"));
if (hwu) {
PatchWUModule(hwu);
@@ -50,16 +51,16 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) {
ResumeAndCloseThreads(lphThreads, cb);
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
DbgPrint("Received wufuc_UnloadEvent, removing hooks.");
_tdbgprintf(_T("Received wufuc_UnloadEvent, removing hooks."));
SuspendProcess(lphThreads, _countof(lphThreads), &cb);
SuspendProcessThreads(dwProcessId, dwThreadId, lphThreads, _countof(lphThreads), &cb);
RESTORE_IAT(hm, LoadLibraryExA);
RESTORE_IAT(hm, LoadLibraryExW);
ResumeAndCloseThreads(lphThreads, cb);
DbgPrint("Unloading library. Cya!");
_tdbgprintf(_T("Unloading library. Cya!"));
CloseHandle(hEvent);
FreeLibraryAndExitThread(HINST_THISCOMPONENT, 0);
return 0;
}
@@ -97,8 +98,7 @@ BOOL PatchWUModule(HMODULE hModule) {
"A1????????"; // mov eax,dword ptr ds:[????????]
n1 = 5;
n2 = 13;
}
else if (IsWindows7()) {
} else if (IsWindows7()) {
lpszPattern =
"833D????????00" // cmp dword ptr ds:[????????],0
"743E" // je $+3E
@@ -118,20 +118,19 @@ BOOL PatchWUModule(HMODULE hModule) {
if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &offset)) {
return FALSE;
}
DbgPrint("IsDeviceServiceable(void) matched at %p", (UINT_PTR)modinfo.lpBaseOfDll + offset);
SIZE_T rva = (SIZE_T)modinfo.lpBaseOfDll + offset;
_tdbgprintf(_T("IsDeviceServiceable(void) matched at %p"), rva);
DWORD *lpdwResultIsNotCachedOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1);
BOOL *lpbResultIsNotCached = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n1 + sizeof(DWORD) + *lpdwResultIsNotCachedOffset);
if (*lpbResultIsNotCached) {
*lpbResultIsNotCached = FALSE;
DbgPrint("Patched %p=%d", lpbResultIsNotCached, *lpbResultIsNotCached);
BOOL *lpbNotRunOnce = (BOOL *)(rva + n1 + sizeof(DWORD) + *(DWORD *)(rva + n1));
if (*lpbNotRunOnce) {
*lpbNotRunOnce = FALSE;
_tdbgprintf(_T("Patched %p=%d"), lpbNotRunOnce, *lpbNotRunOnce);
}
DWORD *lpdwCachedResultOffset = (DWORD *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2);
BOOL *lpbCachedResult = (BOOL *)((UINT_PTR)modinfo.lpBaseOfDll + offset + n2 + sizeof(DWORD) + *lpdwCachedResultOffset);
BOOL *lpbCachedResult = (BOOL *)(rva + n2 + sizeof(DWORD) + *(DWORD *)(rva + n2));
if (!*lpbCachedResult) {
*lpbCachedResult = TRUE;
DbgPrint("Patched %p=%d", lpbCachedResult, *lpbCachedResult);
_tdbgprintf(_T("Patched %p=%d"), lpbCachedResult, *lpbCachedResult);
}
return TRUE;
}

View File

@@ -14,9 +14,9 @@ void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int n
SC_HANDLE hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
TCHAR lpGroupName[256];
DWORD dwProcessId;
BOOL result = QueryServiceProcessId(hSCManager, _T("wuauserv"), &dwProcessId);
if (!result && GetServiceGroupName(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) {
result = FindServiceGroupProcessId(hSCManager, lpGroupName, &dwProcessId);
BOOL result = get_svcpid(hSCManager, _T("wuauserv"), &dwProcessId);
if (!result && get_svcgname(hSCManager, _T("wuauserv"), lpGroupName, _countof(lpGroupName))) {
result = get_svcgpid(hSCManager, lpGroupName, &dwProcessId);
}
CloseServiceHandle(hSCManager);
if (!result) {
@@ -34,7 +34,7 @@ void CALLBACK Rundll32Entry(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int n
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
if (hEvent) {
DbgPrint("Setting wufuc_UnloadEvent...");
_tdbgprintf(_T("Setting wufuc_UnloadEvent..."));
SetEvent(hEvent);
CloseHandle(hEvent);
}

View File

@@ -1,139 +0,0 @@
#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>
#include <tchar.h>
#include "util.h"
#include "process.h"
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
LPVOID *lpAddress = FindIAT(hModule, lpFuncName);
if (!lpAddress || *lpAddress == lpNewAddress) {
return;
}
DWORD flOldProtect;
DWORD flNewProtect = PAGE_READWRITE;
VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect);
if (lpOldAddress) {
*lpOldAddress = *lpAddress;
}
DbgPrint("%S %p => %p", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName) {
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((LPBYTE)dos + dos->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR desc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)dos + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (PIMAGE_IMPORT_DESCRIPTOR iid = desc; iid->Name != 0; iid++) {
for (int i = 0; *(i + (LPVOID*)(iid->FirstThunk + (SIZE_T)hModule)) != NULL; i++) {
LPSTR name = (LPSTR)(*(i + (SIZE_T*)(iid->OriginalFirstThunk + (SIZE_T)hModule)) + (SIZE_T)hModule + 2);
const uintptr_t n = (uintptr_t)name;
if (!(n & (sizeof(n) == 4 ? 0x80000000 : 0x8000000000000000)) && !_stricmp(lpFuncName, name)) {
return i + (LPVOID*)(iid->FirstThunk + (SIZE_T)hModule);
}
}
}
return NULL;
}
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset) {
SIZE_T nPatternLength = strlen(lpszPattern);
SIZE_T nMaskLength = nPatternLength / 2;
if (nMaskLength > nNumberOfBytes || nPatternLength % 2) {
return FALSE;
}
LPBYTE lpPattern = malloc(nMaskLength * sizeof(BYTE));
BOOL *lpbMask = malloc(nMaskLength * sizeof(BOOL));
LPSTR p = lpszPattern;
BOOL valid = TRUE;
for (SIZE_T i = 0; i < nMaskLength; i++) {
if (lpbMask[i] = strncmp(p, "??", 2)) {
if (sscanf_s(p, "%2hhx", &lpPattern[i]) != 1) {
valid = FALSE;
break;
}
}
p += 2;
}
BOOL result = FALSE;
if (valid) {
for (SIZE_T i = nStart; i < nNumberOfBytes - nStart - (nMaskLength - 1); i++) {
BOOL found = TRUE;
for (SIZE_T j = 0; j < nMaskLength; j++) {
if (lpbMask[j] && lpBytes[i + j] != lpPattern[j]) {
found = FALSE;
break;
}
}
if (found) {
*lpOffset = i;
result = TRUE;
break;
}
}
}
free(lpPattern);
free(lpbMask);
return result;
}
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb) {
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, cb, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcess, lpBaseAddress, lpLibFileName, cb, NULL)) {
return FALSE;
}
DWORD dwProcessId = GetProcessId(hProcess);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
MODULEENTRY32 me;
me.dwSize = sizeof(me);
Module32First(hSnap, &me);
do {
if (!_tcsicmp(me.szModule, _T("kernel32.dll"))) {
break;
}
} while (Module32Next(hSnap, &me));
CloseHandle(hSnap);
DbgPrint("Injecting %s into process %d", lpLibFileName, dwProcessId);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(me.hModule, _CRT_STRINGIZE(LoadLibrary)), lpBaseAddress, 0, NULL);
CloseHandle(hThread);
return TRUE;
}
VOID SuspendProcess(HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te;
te.dwSize = sizeof(te);
Thread32First(hSnap, &te);
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
SIZE_T count = 0;
do {
if (te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId) {
continue;
}
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while (count < dwSize && Thread32Next(hSnap, &te));
CloseHandle(hSnap);
*lpcb = count;
DbgPrint("Suspended other threads.");
}
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
for (SIZE_T i = 0; i < cb; i++) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
DbgPrint("Resumed threads.");
}

View File

@@ -1,20 +0,0 @@
#pragma once
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
#define DETOUR_IAT(x, y) \
LPVOID __LPORIGINAL##y; \
DetourIAT(x, #y, &__LPORIGINAL##y, &_##y)
#define RESTORE_IAT(x, y) \
DetourIAT(x, #y, NULL, __LPORIGINAL##y)
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset);
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb);
VOID SuspendProcess(HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);

View File

@@ -1,15 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by version.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -2,8 +2,9 @@
#include <tchar.h>
#include "util.h"
#include "service.h"
#include "shellapihelper.h"
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize) {
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;
@@ -13,16 +14,15 @@ BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPT
QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded);
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
BOOL result = QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded);
int a = GetLastError();
CloseServiceHandle(hService);
if (result) {
_tcscpy_s(lpBinaryPathName, dwSize, sc->lpBinaryPathName);
}
LocalFree(sc);
free(sc);
return result;
}
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId) {
SC_HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
if (!hService) {
return FALSE;
@@ -34,15 +34,14 @@ BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *l
if (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&lpBuffer, sizeof(lpBuffer), &cbBytesNeeded) && lpBuffer.dwProcessId) {
*lpdwProcessId = lpBuffer.dwProcessId;
result = TRUE;
DbgPrint("Found %s pid %d", lpServiceName, *lpdwProcessId);
}
CloseServiceHandle(hService);
return result;
}
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize) {
TCHAR lpBinaryPathName[0x8000];
if (!QueryServiceBinaryPathName(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
if (!get_svcpath(hSCManager, lpServiceName, lpBinaryPathName, _countof(lpBinaryPathName))) {
return FALSE;
}
int numArgs;
@@ -57,11 +56,10 @@ BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpG
BOOL result = FALSE;
if (!_tcsicmp(fname, _T("svchost"))) {
LPWSTR *p = argv;
for (int i = 0; i + 1 < numArgs; i++) {
for (int i = 1; i < numArgs; i++) {
if (!_tcsicmp(*(p++), _T("-k"))) {
_tcscpy_s(lpGroupName, dwSize, *p);
result = TRUE;
DbgPrint("Found %s svc group: %s", lpServiceName, lpGroupName);
break;
}
}
@@ -69,29 +67,25 @@ BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpG
return result;
}
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId) {
DWORD uBytes = 0x100000;
LPBYTE pvData = malloc(uBytes);
RegGetValue(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"), lpServiceGroupName, RRF_RT_REG_MULTI_SZ, NULL, pvData, &uBytes);
LPTSTR ptr = (LPTSTR)pvData;
BOOL result = FALSE;
while (*ptr) {
for (LPTSTR p = (LPTSTR)pvData; *p; p += _tcslen(p) + 1) {
DWORD dwProcessId;
if (QueryServiceProcessId(hSCManager, ptr, &dwProcessId)) {
TCHAR group[256];
GetServiceGroupName(hSCManager, ptr, group, _countof(group));
if (get_svcpid(hSCManager, p, &dwProcessId)) {
get_svcgname(hSCManager, p, group, _countof(group));
result = !_tcsicmp(group, lpServiceGroupName);
}
if (result) {
DbgPrint("Found %s pid %d", lpServiceGroupName, dwProcessId);
*lpdwProcessId = dwProcessId;
break;
}
ptr += _tcslen(ptr) + 1;
}
LocalFree(pvData);
free(pvData);
return result;
}

View File

@@ -1,9 +1,9 @@
#pragma once
BOOL QueryServiceBinaryPathName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
BOOL get_svcpath(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
BOOL QueryServiceProcessId(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
BOOL get_svcpid(SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD *lpdwProcessId);
BOOL GetServiceGroupName(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
BOOL get_svcgname(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpGroupName, SIZE_T dwSize);
BOOL FindServiceGroupProcessId(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);
BOOL get_svcgpid(SC_HANDLE hSCManager, LPTSTR lpServiceGroupName, DWORD *lpdwProcessId);

7
wufuc/shellapihelper.h Normal file
View File

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

View File

@@ -1,5 +1,7 @@
#include <Windows.h>
#include <stdio.h>
#include <VersionHelpers.h>
#include <TlHelp32.h>
#include <tchar.h>
#include "util.h"
@@ -15,13 +17,148 @@ BOOL IsWindows8Point1(void) {
return IsWindows8Point1OrGreater() && !IsWindows10OrGreater();
}
//#ifdef _DEBUG
VOID _DbgPrint(LPCTSTR format, ...) {
TCHAR buffer[0x1000];
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
LPVOID *lpAddress = FindIAT(hModule, lpFuncName);
if (!lpAddress || *lpAddress == lpNewAddress) {
return;
}
DWORD flOldProtect;
DWORD flNewProtect = PAGE_READWRITE;
VirtualProtect(lpAddress, sizeof(LPVOID), flNewProtect, &flOldProtect);
if (lpOldAddress) {
*lpOldAddress = *lpAddress;
}
_dbgprintf("%s %p => %p", lpFuncName, *lpAddress, lpNewAddress);
*lpAddress = lpNewAddress;
VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flNewProtect);
}
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) {
SIZE_T hm = (SIZE_T)hModule;
for (PIMAGE_IMPORT_DESCRIPTOR iid = (PIMAGE_IMPORT_DESCRIPTOR)(hm + ((PIMAGE_NT_HEADERS)(hm + ((PIMAGE_DOS_HEADER)hm)->e_lfanew))
->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); iid->Name; iid++) {
LPVOID *p;
for (SIZE_T i = 0; *(p = i + (LPVOID *)(hm + iid->FirstThunk)); i++) {
LPSTR fn = (LPSTR)(hm + *(i + (SIZE_T *)(hm + iid->OriginalFirstThunk)) + 2);
if (!((uintptr_t)fn & IMAGE_ORDINAL_FLAG) && !_stricmp(lpFunctionName, fn)) {
return p;
}
}
}
return NULL;
}
BOOL 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;
te.dwSize = sizeof(te);
Thread32First(hSnap, &te);
SIZE_T count = 0;
do {
if (te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId) {
continue;
}
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while (count < dwSize && Thread32Next(hSnap, &te));
CloseHandle(hSnap);
*lpcb = count;
_tdbgprintf(_T("Suspended other threads."));
}
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T cb) {
for (SIZE_T i = 0; i < cb; i++) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
_tdbgprintf(_T("Resumed threads."));
}
VOID _wdbgprintf(LPCWSTR format, ...) {
WCHAR buffer[0x1000];
va_list argptr;
va_start(argptr, format);
_vstprintf_s(buffer, _countof(buffer), format, argptr);
vswprintf_s(buffer, _countof(buffer), format, argptr);
va_end(argptr);
OutputDebugString(buffer);
OutputDebugStringW(buffer);
}
VOID _dbgprintf(LPCSTR format, ...) {
CHAR buffer[0x1000];
va_list argptr;
va_start(argptr, format);
vsprintf_s(buffer, _countof(buffer), format, argptr);
va_end(argptr);
OutputDebugStringA(buffer);
}
//#endif

View File

@@ -9,16 +9,33 @@ BOOL IsWindows7(void);
BOOL IsWindows8Point1(void);
//#ifdef _DEBUG
VOID _DbgPrint(LPCTSTR format, ...);
#define DbgPrint(format, ...) \
_DbgPrint(_T(__FUNCTION__) _T(": ") _T(format), ##__VA_ARGS__)
//#else
//#define DbgPrint(format, ...)
//#endif
VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
#define DETOUR_IAT(x, y) \
LPVOID __LPORIGINAL##y; \
DetourIAT(x, #y, &__LPORIGINAL##y, &_##y)
#define RESTORE_IAT(x, y) \
DetourIAT(x, #y, NULL, __LPORIGINAL##y)
LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName);
BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset);
BOOL InjectLibrary(HANDLE hProcess, LPCTSTR lpLibFileName, DWORD cb);
VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb);
VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize);
VOID _wdbgprintf(LPCWSTR format, ...);
VOID _dbgprintf(LPCSTR format, ...);
//#ifdef _DEBUG
#ifdef UNICODE
#define CommandLineToArgv CommandLineToArgvW
#define _tdbgprintf _wdbgprintf
#else
#define CommandLineToArgv CommandLineToArgvA
#define _tdbgprintf _dbgprintf
#endif // !UNICODE
//#else
//#define _tdbgprintf(format, ...)
//#endif // !_DEBUG

Binary file not shown.

View File

@@ -144,6 +144,9 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)install\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -163,12 +166,14 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)install\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="core.c" />
<ClCompile Include="dllmain.c" />
<ClCompile Include="entrypoint.c" />
<ClCompile Include="process.c" />
<ClCompile Include="service.c" />
<ClCompile Include="util.c" />
</ItemGroup>
@@ -177,8 +182,8 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="core.h" />
<ClInclude Include="process.h" />
<ClInclude Include="service.h" />
<ClInclude Include="shellapihelper.h" />
<ClInclude Include="util.h" />
</ItemGroup>
<ItemGroup>