remove detours
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
#include "stdafx.h"
|
||||
#include "callbacks.h"
|
||||
#include "hooks.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpmem.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpsvc.h"
|
||||
#include "hooks.h"
|
||||
|
||||
VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
|
||||
{
|
||||
trace(L"Enter service notify callback. (NotifyStatus=%ld ServiceStatus=%ld)",
|
||||
pNotifyBuffer->dwNotificationStatus, pNotifyBuffer->ServiceStatus);
|
||||
|
||||
switch ( pNotifyBuffer->dwNotificationStatus ) {
|
||||
case ERROR_SUCCESS:
|
||||
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
|
||||
@@ -25,7 +22,29 @@ VOID CALLBACK ServiceNotifyCallback(PSERVICE_NOTIFYW pNotifyBuffer)
|
||||
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
|
||||
}
|
||||
|
||||
DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
DWORD WINAPI PipeLoopThreadCallback(LPVOID pParam)
|
||||
{
|
||||
HANDLE hPipe = (HANDLE)pParam;
|
||||
BOOL fSuccess;
|
||||
wchar_t chBuf[512];
|
||||
while (true) {
|
||||
// Read from the pipe.
|
||||
|
||||
fSuccess = ReadFile(
|
||||
hPipe, // pipe handle
|
||||
chBuf, // buffer to receive reply
|
||||
BUFSIZE * sizeof(wchar_t), // size of buffer
|
||||
&cbRead, // number of bytes read
|
||||
NULL); // not overlapped
|
||||
|
||||
if ( !fSuccess && GetLastError() != ERROR_MORE_DATA )
|
||||
break;;
|
||||
|
||||
_tprintf(TEXT("\"%s\"\n"), chBuf);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WINAPI StartThreadCallback(LPVOID pParam)
|
||||
{
|
||||
ContextHandles ctx;
|
||||
SC_HANDLE hSCM;
|
||||
@@ -33,8 +52,9 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
DWORD dwProcessId;
|
||||
LPQUERY_SERVICE_CONFIGW pServiceConfig;
|
||||
DWORD dwServiceType;
|
||||
LPWSTR str;
|
||||
wchar_t *str;
|
||||
HMODULE hModule;
|
||||
wchar_t Filename[MAX_PATH];
|
||||
DWORD result;
|
||||
|
||||
// get mutex and unload event handles from virtual memory
|
||||
@@ -55,7 +75,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
|
||||
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
if ( !hSCM ) {
|
||||
trace(L"Failed to open SCM. (GetLastError=%ul)", GetLastError());
|
||||
trace(L"Failed to open SCM. (GetLastError=%lu)", GetLastError());
|
||||
goto release;
|
||||
}
|
||||
|
||||
@@ -91,7 +111,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
|
||||
// query the ServiceDll path after applying our compat hook so that it
|
||||
// is correct
|
||||
str = (LPWSTR)RegQueryValueExAlloc(HKEY_LOCAL_MACHINE,
|
||||
str = (wchar_t *)RegQueryValueExAlloc(HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\CurrentControlSet\\services\\wuauserv\\Parameters",
|
||||
L"ServiceDll", NULL, NULL);
|
||||
g_pszWUServiceDll = ExpandEnvironmentStringsAlloc(str, NULL);
|
||||
@@ -105,9 +125,8 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
DetourAttach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook);
|
||||
|
||||
if ( g_pszWUServiceDll ) {
|
||||
hModule = GetModuleHandleW(g_pszWUServiceDll);
|
||||
if ( hModule ) {
|
||||
if ( FindIDSFunctionPointer(hModule, &(PVOID)g_pfnIsDeviceServiceable) ) {
|
||||
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule) ) {
|
||||
if ( FindIDSFunctionAddress(hModule, &(PVOID)g_pfnIsDeviceServiceable) ) {
|
||||
trace(L"Matched pattern for %ls!IsDeviceServiceable. (%p)",
|
||||
PathFindFileNameW(g_pszWUServiceDll),
|
||||
g_pfnIsDeviceServiceable);
|
||||
@@ -115,6 +134,7 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
} else {
|
||||
trace(L"No pattern matched!");
|
||||
}
|
||||
FreeLibrary(hModule);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -125,7 +145,6 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
// intentionally leave parent mutex open until this thread ends, at
|
||||
// which point it becomes abandoned again.
|
||||
result = WaitForMultipleObjects(_countof(ctx.handles), ctx.handles, FALSE, INFINITE);
|
||||
|
||||
trace(L"Unload condition has been met.");
|
||||
|
||||
// unhook
|
||||
@@ -137,9 +156,19 @@ DWORD WINAPI ThreadStartCallback(LPVOID pParam)
|
||||
if ( g_pfnLoadLibraryExW )
|
||||
DetourDetach(&(PVOID)g_pfnLoadLibraryExW, LoadLibraryExW_hook);
|
||||
|
||||
if ( g_pfnIsDeviceServiceable )
|
||||
DetourDetach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook);
|
||||
// check to see if the last known address of IsDeviceServiceable
|
||||
// is still in the address space of wuaueng.dll before
|
||||
// attempting to unhook the function.
|
||||
if ( g_pfnIsDeviceServiceable
|
||||
&& GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(LPWSTR)g_pfnIsDeviceServiceableLastKnown, &hModule) ) {
|
||||
|
||||
if ( GetModuleFileNameW(hModule, Filename, _countof(Filename))
|
||||
&& (!_wcsicmp(Filename, g_pszWUServiceDll)
|
||||
|| !_wcsicmp(Filename, PathFindFileNameW(g_pszWUServiceDll))) )
|
||||
DetourDetach(&(PVOID)g_pfnIsDeviceServiceable, IsDeviceServiceable_hook);
|
||||
FreeLibrary(hModule);
|
||||
}
|
||||
if ( g_pfnRegQueryValueExW )
|
||||
DetourDetach(&(PVOID)g_pfnRegQueryValueExW, RegQueryValueExW_hook);
|
||||
|
||||
@@ -151,8 +180,10 @@ release:
|
||||
ReleaseMutex(ctx.hChildMutex);
|
||||
close_handles:
|
||||
CloseHandle(ctx.hChildMutex);
|
||||
CloseHandle(ctx.hParentMutex);
|
||||
CloseHandle(ctx.hUnloadEvent);
|
||||
CloseHandle(ctx.hParentMutex);
|
||||
if ( g_hTracingMutex )
|
||||
CloseHandle(g_hTracingMutex);
|
||||
unload:
|
||||
trace(L"Freeing library and exiting main thread.");
|
||||
FreeLibraryAndExitThread(PIMAGEBASE, 0);
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "callbacks.h"
|
||||
#include "hlpmem.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpver.h"
|
||||
#include "hooks.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable)
|
||||
bool FindIDSFunctionAddress(HMODULE hModule, PVOID *ppfnIsDeviceServiceable)
|
||||
{
|
||||
bool result = false;
|
||||
bool is_win7 = false;
|
||||
@@ -61,23 +61,26 @@ bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable)
|
||||
pffi = GetVersionInfoFromHModuleAlloc(hModule, L"\\", &cbffi);
|
||||
if ( !pffi ) {
|
||||
trace(L"Failed to allocate version information from hmodule.");
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu",
|
||||
HIWORD(pffi->dwProductVersionMS),
|
||||
LOWORD(pffi->dwProductVersionMS),
|
||||
HIWORD(pffi->dwProductVersionLS),
|
||||
LOWORD(pffi->dwProductVersionLS));
|
||||
|
||||
// assure wuaueng.dll is at least the minimum supported version
|
||||
tmp = ((is_win7 && ProductVersionCompare(pffi, 7, 6, 7601, 23714) != -1)
|
||||
|| (is_win81 && ProductVersionCompare(pffi, 7, 9, 9600, 18621) != -1));
|
||||
free(pffi);
|
||||
if ( !tmp ) {
|
||||
trace(L"Module does not meet the minimum supported version.");
|
||||
continue;
|
||||
trace(L"Windows Update Agent does not meet the minimum supported version.");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !GetModuleInformation(hProcess, hModule, &modinfo, sizeof modinfo) )
|
||||
break;
|
||||
|
||||
offset = patternfind(modinfo.lpBaseOfDll,
|
||||
modinfo.SizeOfImage,
|
||||
offset = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage,
|
||||
#ifdef _WIN64
|
||||
"FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"
|
||||
#else
|
||||
@@ -87,7 +90,8 @@ bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable)
|
||||
#endif
|
||||
);
|
||||
if ( offset != -1 ) {
|
||||
*ppfnIsDeviceServiceable = (PVOID)((uint8_t *)modinfo.lpBaseOfDll + offset);
|
||||
g_pfnIsDeviceServiceableLastKnown = (PVOID)((uint8_t *)modinfo.lpBaseOfDll + offset);
|
||||
*ppfnIsDeviceServiceable = g_pfnIsDeviceServiceableLastKnown;
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
@@ -254,7 +258,7 @@ bool wufuc_InjectLibrary(DWORD dwProcessId, ContextHandles *pContext)
|
||||
HANDLE hSrcProcess;
|
||||
ContextHandles param = { 0 };
|
||||
|
||||
if ( swprintf_s(MutexName, _countof(MutexName),
|
||||
if ( swprintf_s(MutexName, _countof(MutexName),
|
||||
L"Global\\%08x-7132-44a8-be15-56698979d2f3", dwProcessId) == -1 ) {
|
||||
|
||||
trace(L"Failed to print mutex name to string! (%lu)", dwProcessId);
|
||||
|
@@ -27,7 +27,7 @@ typedef struct
|
||||
WORD wCodePage;
|
||||
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
||||
|
||||
bool FindIDSFunctionPointer(HMODULE hModule, PVOID *ppfnIsDeviceServiceable);
|
||||
bool FindIDSFunctionAddress(HMODULE hModule, PVOID *ppfnIsDeviceServiceable);
|
||||
HANDLE GetRemoteHModuleFromTh32ModuleSnapshot(HANDLE hSnapshot, const wchar_t *pLibFileName);
|
||||
bool InjectLibraryAndCreateRemoteThread(
|
||||
HANDLE hProcess,
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#include "hlpmisc.h"
|
||||
#include <sddl.h>
|
||||
|
||||
bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex)
|
||||
bool InitializeMutex(bool InitialOwner, const wchar_t *pMutexName, HANDLE *phMutex)
|
||||
{
|
||||
HANDLE hMutex;
|
||||
|
||||
@@ -22,10 +22,10 @@ bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex)
|
||||
}
|
||||
|
||||
bool CreateEventWithStringSecurityDescriptor(
|
||||
LPCWSTR pStringSecurityDescriptor,
|
||||
const wchar_t *pStringSecurityDescriptor,
|
||||
bool ManualReset,
|
||||
bool InitialState,
|
||||
LPCWSTR pName,
|
||||
const wchar_t *pName,
|
||||
HANDLE *phEvent)
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa = { sizeof sa };
|
||||
@@ -48,8 +48,8 @@ bool CreateEventWithStringSecurityDescriptor(
|
||||
|
||||
PVOID RegGetValueAlloc(
|
||||
HKEY hkey,
|
||||
LPCWSTR pSubKey,
|
||||
LPCWSTR pValue,
|
||||
const wchar_t *pSubKey,
|
||||
const wchar_t *pValue,
|
||||
DWORD dwFlags,
|
||||
LPDWORD pdwType,
|
||||
LPDWORD pcbData)
|
||||
@@ -75,8 +75,8 @@ PVOID RegGetValueAlloc(
|
||||
|
||||
LPBYTE RegQueryValueExAlloc(
|
||||
HKEY hKey,
|
||||
LPCWSTR pSubKey,
|
||||
LPCWSTR pValueName,
|
||||
const wchar_t *pSubKey,
|
||||
const wchar_t *pValueName,
|
||||
LPDWORD pType,
|
||||
LPDWORD pcbData)
|
||||
{
|
||||
@@ -136,9 +136,9 @@ PVOID NtQueryKeyAlloc(
|
||||
return result;
|
||||
}
|
||||
|
||||
LPWSTR ExpandEnvironmentStringsAlloc(LPCWSTR src, LPDWORD pcchLength)
|
||||
wchar_t *ExpandEnvironmentStringsAlloc(const wchar_t *src, LPDWORD pcchLength)
|
||||
{
|
||||
LPWSTR result;
|
||||
wchar_t *result;
|
||||
DWORD buffersize;
|
||||
DWORD size;
|
||||
|
||||
|
@@ -1,27 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
bool InitializeMutex(bool InitialOwner, LPCWSTR pMutexName, HANDLE *phMutex);
|
||||
bool InitializeMutex(bool InitialOwner, const wchar_t *pMutexName, HANDLE *phMutex);
|
||||
bool CreateEventWithStringSecurityDescriptor(
|
||||
LPCWSTR pStringSecurityDescriptor,
|
||||
const wchar_t *pStringSecurityDescriptor,
|
||||
bool ManualReset,
|
||||
bool InitialState,
|
||||
LPCWSTR pName,
|
||||
const wchar_t *pName,
|
||||
HANDLE *phEvent);
|
||||
PVOID RegGetValueAlloc(
|
||||
HKEY hkey,
|
||||
LPCWSTR pSubKey,
|
||||
LPCWSTR pValue,
|
||||
const wchar_t *pSubKey,
|
||||
const wchar_t *pValue,
|
||||
DWORD dwFlags,
|
||||
LPDWORD pdwType,
|
||||
LPDWORD pcbData);
|
||||
LPBYTE RegQueryValueExAlloc(
|
||||
HKEY hKey,
|
||||
LPCWSTR pSubKey,
|
||||
LPCWSTR pValueName,
|
||||
const wchar_t *pSubKey,
|
||||
const wchar_t *pValueName,
|
||||
LPDWORD pType,
|
||||
LPDWORD pcbData);
|
||||
PVOID NtQueryKeyAlloc(
|
||||
HANDLE KeyHandle,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PULONG pResultLength);
|
||||
LPWSTR ExpandEnvironmentStringsAlloc(LPCWSTR src, LPDWORD pcchLength);
|
||||
wchar_t *ExpandEnvironmentStringsAlloc(const wchar_t *src, LPDWORD pcchLength);
|
||||
|
@@ -68,12 +68,12 @@ bool QueryServiceStatusProcessInfoByName(
|
||||
|
||||
bool QueryServiceGroupName(
|
||||
const LPQUERY_SERVICE_CONFIGW pServiceConfig,
|
||||
LPWSTR *pGroupName,
|
||||
wchar_t **pGroupName,
|
||||
HLOCAL *hMem)
|
||||
{
|
||||
bool result = false;
|
||||
int NumArgs;
|
||||
LPWSTR *argv;
|
||||
wchar_t **argv;
|
||||
|
||||
argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs);
|
||||
if ( argv ) {
|
||||
@@ -126,7 +126,7 @@ DWORD HeuristicServiceGroupProcessId(SC_HANDLE hSCM, const wchar_t *pGroupNameSe
|
||||
DWORD cbBufSize;
|
||||
LPQUERY_SERVICE_CONFIGW pServiceConfig;
|
||||
bool success = false;
|
||||
LPWSTR pGroupName;
|
||||
wchar_t *pGroupName;
|
||||
HLOCAL hMem;
|
||||
|
||||
pData = RegGetValueAlloc(HKEY_LOCAL_MACHINE,
|
||||
@@ -165,7 +165,7 @@ DWORD HeuristicServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService)
|
||||
{
|
||||
DWORD result = 0;
|
||||
LPQUERY_SERVICE_CONFIGW pServiceConfig;
|
||||
LPWSTR pGroupName;
|
||||
wchar_t *pGroupName;
|
||||
HLOCAL hMem;
|
||||
|
||||
result = QueryServiceProcessId(hSCM, hService);
|
||||
|
@@ -14,7 +14,7 @@ bool QueryServiceStatusProcessInfoByName(
|
||||
LPSERVICE_STATUS_PROCESS pServiceStatus);
|
||||
bool QueryServiceGroupName(
|
||||
const LPQUERY_SERVICE_CONFIGW pServiceConfig,
|
||||
LPWSTR *pGroupName,
|
||||
wchar_t **pGroupName,
|
||||
HLOCAL *hMem);
|
||||
DWORD QueryServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService);
|
||||
DWORD QueryServiceProcessIdByName(SC_HANDLE hSCM, const wchar_t *pServiceName);
|
||||
|
@@ -14,7 +14,7 @@ int ProductVersionCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GetVersionInfoFromHModule(HMODULE hModule, LPCWSTR pszSubBlock, LPVOID pData, PUINT pcbData)
|
||||
bool GetVersionInfoFromHModule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData)
|
||||
{
|
||||
bool result = false;
|
||||
UINT cbData;
|
||||
@@ -68,7 +68,7 @@ cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, LPCWSTR pszSubBlock, PUINT pcbData)
|
||||
LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData)
|
||||
{
|
||||
UINT cbData = 0;
|
||||
LPVOID result = NULL;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
int ProductVersionCompare(VS_FIXEDFILEINFO *pffi, WORD wMajor, WORD wMinor, WORD wBuild, WORD wRev);
|
||||
bool GetVersionInfoFromHModule(HMODULE hModule, LPCWSTR pszSubBlock, LPVOID pData, PUINT pcbData);
|
||||
LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, LPCWSTR pszSubBlock, PUINT pcbData);
|
||||
bool GetVersionInfoFromHModule(HMODULE hModule, const wchar_t *pszSubBlock, LPVOID pData, PUINT pcbData);
|
||||
LPVOID GetVersionInfoFromHModuleAlloc(HMODULE hModule, const wchar_t *pszSubBlock, PUINT pcbData);
|
||||
bool IsWindowsVersion(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor);
|
||||
|
@@ -1,17 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
#include "hooks.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpmem.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hooks.h"
|
||||
|
||||
LPWSTR g_pszWUServiceDll;
|
||||
wchar_t *g_pszWUServiceDll;
|
||||
|
||||
LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
|
||||
LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
|
||||
LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
|
||||
LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceableLastKnown;
|
||||
|
||||
LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
||||
{
|
||||
PWCH pBuffer;
|
||||
wchar_t *pBuffer;
|
||||
DWORD MaximumLength = 0;
|
||||
LSTATUS result;
|
||||
ULONG ResultLength;
|
||||
@@ -19,8 +20,8 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR
|
||||
size_t NameCount;
|
||||
int current;
|
||||
int pos;
|
||||
LPWSTR fname;
|
||||
const WCHAR realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
|
||||
wchar_t *fname;
|
||||
const wchar_t realpath[] = L"%systemroot%\\system32\\wuaueng.dll";
|
||||
wchar_t *expandedpath;
|
||||
DWORD cchLength;
|
||||
|
||||
@@ -30,8 +31,8 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR
|
||||
result = g_pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
|
||||
|
||||
if ( result != ERROR_SUCCESS
|
||||
|| !MaximumLength
|
||||
if ( result != ERROR_SUCCESS
|
||||
|| !MaximumLength
|
||||
|| !lpValueName
|
||||
|| (lpType && *lpType != REG_EXPAND_SZ)
|
||||
|| _wcsicmp(lpValueName, L"ServiceDll") )
|
||||
@@ -59,11 +60,15 @@ LSTATUS WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpR
|
||||
|| !_wcsicmp(fname, L"WuaCpuFix.dll")) ) {
|
||||
|
||||
expandedpath = ExpandEnvironmentStringsAlloc(realpath, &cchLength);
|
||||
|
||||
trace(L"Fixed path to wuauserv ServiceDll: %ls -> %ls", fname, PathFindFileNameW(expandedpath));
|
||||
if ( SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) )
|
||||
*lpcbData = cchLength * (sizeof *expandedpath);
|
||||
free(expandedpath);
|
||||
if ( expandedpath ) {
|
||||
if ( PathFileExistsW(expandedpath)
|
||||
&& SUCCEEDED(StringCbCopyW(pBuffer, MaximumLength, expandedpath)) ) {
|
||||
|
||||
*lpcbData = cchLength * (sizeof *expandedpath);
|
||||
trace(L"Fixed path to Windows Update service library.");
|
||||
}
|
||||
free(expandedpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pkni);
|
||||
@@ -79,9 +84,10 @@ HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFla
|
||||
trace(L"Loaded library: %ls (%p)", lpFileName, result);
|
||||
|
||||
if ( g_pszWUServiceDll
|
||||
&& !_wcsicmp(lpFileName, g_pszWUServiceDll) ) {
|
||||
&& (!_wcsicmp(lpFileName, g_pszWUServiceDll)
|
||||
|| !_wcsicmp(lpFileName, PathFindFileNameW(g_pszWUServiceDll))) ) {
|
||||
|
||||
if ( FindIDSFunctionPointer(result, &(PVOID)g_pfnIsDeviceServiceable) ) {
|
||||
if ( FindIDSFunctionAddress(result, &(PVOID)g_pfnIsDeviceServiceable) ) {
|
||||
trace(L"Matched pattern for %ls!IsDeviceServiceable. (%p)",
|
||||
PathFindFileNameW(lpFileName),
|
||||
g_pfnIsDeviceServiceable);
|
||||
|
@@ -5,11 +5,12 @@ typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD,
|
||||
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
|
||||
typedef BOOL(WINAPI *LPFN_ISDEVICESERVICEABLE)(void);
|
||||
|
||||
extern LPWSTR g_pszWUServiceDll;
|
||||
extern wchar_t *g_pszWUServiceDll;
|
||||
|
||||
extern LPFN_REGQUERYVALUEEXW g_pfnRegQueryValueExW;
|
||||
extern LPFN_LOADLIBRARYEXW g_pfnLoadLibraryExW;
|
||||
extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceable;
|
||||
extern LPFN_ISDEVICESERVICEABLE g_pfnIsDeviceServiceableLastKnown;
|
||||
|
||||
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);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "callbacks.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpmem.h"
|
||||
#include "hlpmisc.h"
|
||||
#include "hlpsvc.h"
|
||||
|
||||
void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
|
||||
@@ -17,18 +17,20 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
|
||||
|
||||
if ( !InitializeMutex(true,
|
||||
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645",
|
||||
&ctx.hParentMutex) ) {
|
||||
|
||||
trace(L"Failed to initialize main mutex. (GetLastError=%ul)", GetLastError());
|
||||
&ctx.hParentMutex) )
|
||||
return;
|
||||
};
|
||||
|
||||
if ( !start_traing() )
|
||||
itrace(L"Could not create tracing pipe!");
|
||||
return;
|
||||
|
||||
if ( !CreateEventWithStringSecurityDescriptor(L"D:(A;;0x001F0003;;;BA)",
|
||||
true,
|
||||
false,
|
||||
L"Global\\wufuc_UnloadEvent",
|
||||
&ctx.hUnloadEvent) ) {
|
||||
|
||||
trace(L"Failed to create unload event. (GetLastError=%ul)", GetLastError());
|
||||
trace(L"Failed to create unload event. (GetLastError=%lu)", GetLastError());
|
||||
goto close_mutex;
|
||||
}
|
||||
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
|
||||
@@ -36,13 +38,13 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
|
||||
Lagging = false;
|
||||
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
|
||||
if ( !hSCM ) {
|
||||
trace(L"Failed to open SCM. (GetLastError=%ul)", GetLastError());
|
||||
trace(L"Failed to open SCM. (GetLastError=%lu)", GetLastError());
|
||||
goto close_event;
|
||||
}
|
||||
|
||||
hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess);
|
||||
if ( !hService ) {
|
||||
trace(L"Failed to open service. (GetLastError=%ul)", GetLastError());
|
||||
trace(L"Failed to open service. (GetLastError=%lu)", GetLastError());
|
||||
goto close_scm;
|
||||
}
|
||||
if ( (dwDesiredAccess & SERVICE_QUERY_CONFIG) == SERVICE_QUERY_CONFIG ) {
|
||||
@@ -79,6 +81,8 @@ close_event:
|
||||
CloseHandle(ctx.hUnloadEvent);
|
||||
close_mutex:
|
||||
ReleaseMutex(ctx.hParentMutex);
|
||||
if ( g_hTracingMutex )
|
||||
CloseHandle(g_hTracingMutex);
|
||||
CloseHandle(ctx.hParentMutex);
|
||||
}
|
||||
|
||||
@@ -100,7 +104,7 @@ void CALLBACK RUNDLL32_DeleteFileW(
|
||||
int nCmdShow)
|
||||
{
|
||||
int argc;
|
||||
LPWSTR *argv;
|
||||
wchar_t **argv;
|
||||
|
||||
argv = CommandLineToArgvW(lpszCmdLine, &argc);
|
||||
if ( argv ) {
|
||||
|
@@ -18,6 +18,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <share.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <shellapi.h>
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "tracing.h"
|
||||
#include <Shlobj.h>
|
||||
|
||||
void trace_(const wchar_t *const format, ...)
|
||||
void itrace_(const wchar_t *const format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
int count;
|
||||
@@ -17,3 +18,217 @@ void trace_(const wchar_t *const format, ...)
|
||||
OutputDebugStringW(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
HANDLE g_hTracingMutex;
|
||||
wchar_t path[MAX_PATH];
|
||||
wchar_t exepath[MAX_PATH];
|
||||
|
||||
DWORD WINAPI tracing_thread(LPVOID pParam)
|
||||
{
|
||||
wchar_t *folder;
|
||||
HANDLE file;
|
||||
DWORD dwProcessId;
|
||||
wchar_t *exename;
|
||||
int count;
|
||||
|
||||
if ( !*path ) {
|
||||
SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &folder);
|
||||
wcscpy_s(path, _countof(path), folder);
|
||||
CoTaskMemFree(folder);
|
||||
PathAppendW(path, L"wufuc");
|
||||
CreateDirectoryW(path, NULL);
|
||||
PathAppendW(path, L"wufuc.log");
|
||||
}
|
||||
if ( !*exepath )
|
||||
GetModuleFileNameW(NULL, exepath, _countof(exepath));
|
||||
|
||||
file = CreateFileW(path, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
itrace(L"CreateFileW=%p", file);
|
||||
dwProcessId = GetCurrentProcessId();
|
||||
exename = PathFindFileNameW(exepath);
|
||||
|
||||
va_start(argptr, format);
|
||||
count = _vscwprintf(format, argptr) + 1;
|
||||
buf1 = calloc(count, sizeof *buf1);
|
||||
vswprintf_s(buf1, count, format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
count = _scwprintf(fmt, datebuf, timebuf, dwProcessId, exename, buf1);
|
||||
buf2 = calloc(count + 1, sizeof *buf2);
|
||||
swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, dwProcessId, exename, buf1);
|
||||
free(buf1);
|
||||
itrace(L"WriteFile=%d", WriteFile(file, buf2, count * (sizeof *buf2), &written, NULL));
|
||||
free(buf2);
|
||||
itrace(L"FlushFileBuffers=%d", FlushFileBuffers(file));
|
||||
itrace(L"CloseHandle=%d", CloseHandle(file));
|
||||
itrace(L"ReleaseMutex=%d", ReleaseMutex(g_hTracingMutex));
|
||||
|
||||
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, 512 * sizeof(TCHAR));
|
||||
|
||||
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
|
||||
BOOL fSuccess = FALSE;
|
||||
HANDLE hPipe = NULL;
|
||||
|
||||
// Do some extra error checking since the app will keep running even if this
|
||||
// thread fails.
|
||||
|
||||
if ( pParam == NULL ) {
|
||||
itrace(L"\nERROR - Pipe Server Failure:");
|
||||
itrace(L" InstanceThread got an unexpected NULL value in lpvParam.");
|
||||
itrace(L" InstanceThread exitting.");
|
||||
if ( pchRequest != NULL ) HeapFree(hHeap, 0, pchRequest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Print verbose messages. In production code, this should be for debugging only.
|
||||
printf("InstanceThread created, receiving and processing messages.\n");
|
||||
|
||||
// The thread's parameter is a handle to a pipe object instance.
|
||||
|
||||
hPipe = (HANDLE)pParam;
|
||||
|
||||
// Loop until done reading
|
||||
while ( true ) {
|
||||
// Read client requests from the pipe. This simplistic code only allows messages
|
||||
// up to BUFSIZE characters in length.
|
||||
fSuccess = ReadFile(
|
||||
hPipe, // handle to pipe
|
||||
pchRequest, // buffer to receive data
|
||||
512 * sizeof(TCHAR), // size of buffer
|
||||
&cbBytesRead, // number of bytes read
|
||||
NULL); // not overlapped I/O
|
||||
|
||||
if ( !fSuccess || cbBytesRead == 0 ) {
|
||||
if ( GetLastError() == ERROR_BROKEN_PIPE ) {
|
||||
itrace(L"InstanceThread: client disconnected.");
|
||||
} else {
|
||||
itrace(L"InstanceThread ReadFile failed, GLE=%d.", GetLastError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_wstrdate_s(datebuf, _countof(datebuf));
|
||||
_wstrtime_s(timebuf, _countof(timebuf));
|
||||
|
||||
if ( !fSuccess ) {
|
||||
itrace(L"InstanceThread WriteFile failed, GLE=%d.", GetLastError());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the pipe to allow the client to read the pipe's contents
|
||||
// before disconnecting. Then disconnect the pipe, and close the
|
||||
// handle to this pipe instance.
|
||||
|
||||
FlushFileBuffers(hPipe);
|
||||
DisconnectNamedPipe(hPipe);
|
||||
CloseHandle(hPipe);
|
||||
|
||||
HeapFree(hHeap, 0, pchRequest);
|
||||
|
||||
printf("InstanceThread exitting.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool start_tracing(const wchar_t *pipename)
|
||||
{
|
||||
HANDLE hPipe;
|
||||
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
HANDLE hThread = NULL;
|
||||
|
||||
while ( true ) {
|
||||
hPipe = CreateNamedPipeW(pipename,
|
||||
PIPE_ACCESS_INBOUND, 0, PIPE_UNLIMITED_INSTANCES, 512, 0, 512, NULL);
|
||||
if ( hPipe == INVALID_HANDLE_VALUE ) {
|
||||
itrace(L"CreateNamedPipe failed, GLE=%d.\n"), GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ConnectNamedPipe(hPipe, NULL) ||
|
||||
GetLastError() == ERROR_PIPE_CONNECTED ) {
|
||||
itrace(L"Client connected, creating a processing thread.");
|
||||
|
||||
// Create a thread for this client.
|
||||
hThread = CreateThread(
|
||||
NULL, // no security attribute
|
||||
0, // default stack size
|
||||
tracing_thread, // thread proc
|
||||
(LPVOID)hPipe, // thread parameter
|
||||
0, // not suspended
|
||||
NULL); // returns thread ID
|
||||
|
||||
if ( hThread == NULL ) {
|
||||
itrace(L"CreateThread failed, GLE=%d.\n"), GetLastError();
|
||||
return false;
|
||||
} else {
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
} else {
|
||||
// The client could not connect, so close the pipe.
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void trace_(const wchar_t *const format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
wchar_t *folder;
|
||||
wchar_t datebuf[9];
|
||||
wchar_t timebuf[9];
|
||||
HANDLE file;
|
||||
DWORD dwProcessId;
|
||||
wchar_t *exename;
|
||||
int count;
|
||||
DWORD written;
|
||||
const wchar_t fmt[] = L"%ls %ls [%lu] Exe(%ls) %ls";
|
||||
wchar_t *buf1;
|
||||
wchar_t *buf2;
|
||||
|
||||
va_start(argptr, format);
|
||||
itrace_(format);
|
||||
va_end(argptr);
|
||||
|
||||
if ( !*path ) {
|
||||
SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &folder);
|
||||
wcscpy_s(path, _countof(path), folder);
|
||||
CoTaskMemFree(folder);
|
||||
PathAppendW(path, L"wufuc");
|
||||
CreateDirectoryW(path, NULL);
|
||||
PathAppendW(path, L"wufuc.log");
|
||||
}
|
||||
if ( !*exepath )
|
||||
GetModuleFileNameW(NULL, exepath, _countof(exepath));
|
||||
|
||||
if ( !g_hTracingMutex )
|
||||
g_hTracingMutex = CreateMutexW(NULL, FALSE, L"Global\\6b2f5740-7435-47f7-865c-dbd825292f32");
|
||||
|
||||
itrace(L"WaitForSingleObject=%lu", WaitForSingleObject(g_hTracingMutex, INFINITE));
|
||||
|
||||
_wstrdate_s(datebuf, _countof(datebuf));
|
||||
_wstrtime_s(timebuf, _countof(timebuf));
|
||||
|
||||
file = CreateFileW(path, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
itrace(L"CreateFileW=%p", file);
|
||||
dwProcessId = GetCurrentProcessId();
|
||||
exename = PathFindFileNameW(exepath);
|
||||
|
||||
va_start(argptr, format);
|
||||
count = _vscwprintf(format, argptr) + 1;
|
||||
buf1 = calloc(count, sizeof *buf1);
|
||||
vswprintf_s(buf1, count, format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
count = _scwprintf(fmt, datebuf, timebuf, dwProcessId, exename, buf1);
|
||||
buf2 = calloc(count + 1, sizeof *buf2);
|
||||
swprintf_s(buf2, count + 1, fmt, datebuf, timebuf, dwProcessId, exename, buf1);
|
||||
free(buf1);
|
||||
itrace(L"WriteFile=%d", WriteFile(file, buf2, count * (sizeof *buf2), &written, NULL));
|
||||
free(buf2);
|
||||
itrace(L"FlushFileBuffers=%d", FlushFileBuffers(file));
|
||||
itrace(L"CloseHandle=%d", CloseHandle(file));
|
||||
itrace(L"ReleaseMutex=%d", ReleaseMutex(g_hTracingMutex));
|
||||
}
|
||||
|
@@ -2,13 +2,14 @@
|
||||
|
||||
#include <phnt_windows.h>
|
||||
|
||||
extern IMAGE_DOS_HEADER __ImageBase;
|
||||
#define HMODULE_THISCOMPONENT ((HMODULE)&__ImageBase);
|
||||
extern HANDLE g_hTracingMutex;
|
||||
|
||||
void itrace_(const wchar_t *const format, ...);
|
||||
void trace_(const wchar_t *const format, ...);
|
||||
|
||||
#define STRINGIZEW_(x) L#x
|
||||
#define STRINGIZEW(x) STRINGIZEW_(x)
|
||||
|
||||
#define LINEWSTR STRINGIZEW(__LINE__)
|
||||
#define trace(format, ...) trace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\n", ##__VA_ARGS__)
|
||||
#define itrace(format, ...) itrace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\r\n", ##__VA_ARGS__)
|
||||
#define trace(format, ...) trace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\r\n", ##__VA_ARGS__)
|
||||
|
Reference in New Issue
Block a user