push progress...
This commit is contained in:
@@ -1,54 +1,65 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "context.h"
|
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "modulehelper.h"
|
#include "modulehelper.h"
|
||||||
#include "registryhelper.h"
|
#include "registryhelper.h"
|
||||||
#include "servicehelper.h"
|
#include "servicehelper.h"
|
||||||
|
#include "ptrlist.h"
|
||||||
#include "wufuc.h"
|
#include "wufuc.h"
|
||||||
|
|
||||||
#include <minhook.h>
|
#include <minhook.h>
|
||||||
|
|
||||||
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
|
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer)
|
||||||
{
|
{
|
||||||
|
trace(L"enter");
|
||||||
switch ( pNotifyBuffer->dwNotificationStatus ) {
|
switch ( pNotifyBuffer->dwNotificationStatus ) {
|
||||||
case ERROR_SUCCESS:
|
case ERROR_SUCCESS:
|
||||||
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
|
if ( pNotifyBuffer->ServiceStatus.dwProcessId )
|
||||||
wufuc_inject(
|
wufuc_inject(
|
||||||
pNotifyBuffer->ServiceStatus.dwProcessId,
|
pNotifyBuffer->ServiceStatus.dwProcessId,
|
||||||
(LPTHREAD_START_ROUTINE)cb_start,
|
(LPTHREAD_START_ROUTINE)cb_start,
|
||||||
(context *)pNotifyBuffer->pContext);
|
(ptrlist_t *)pNotifyBuffer->pContext);
|
||||||
break;
|
break;
|
||||||
case ERROR_SERVICE_MARKED_FOR_DELETE:
|
case ERROR_SERVICE_MARKED_FOR_DELETE:
|
||||||
SetEvent(((context *)pNotifyBuffer->pContext)->uevent);
|
SetEvent(ptrlist_at((ptrlist_t *)pNotifyBuffer->pContext, 1, NULL));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( pNotifyBuffer->pszServiceNames )
|
if ( pNotifyBuffer->pszServiceNames )
|
||||||
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
|
LocalFree((HLOCAL)pNotifyBuffer->pszServiceNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI cb_start(context *ctx)
|
DWORD WINAPI cb_start(HANDLE *pParam)
|
||||||
{
|
{
|
||||||
|
HANDLE handles[2];
|
||||||
|
HANDLE hCrashMutex;
|
||||||
|
HANDLE hProceedEvent;
|
||||||
SC_HANDLE hSCM;
|
SC_HANDLE hSCM;
|
||||||
SC_HANDLE hService;
|
SC_HANDLE hService;
|
||||||
DWORD dwProcessId;
|
DWORD dwProcessId;
|
||||||
LPQUERY_SERVICE_CONFIGW pServiceConfig;
|
LPQUERY_SERVICE_CONFIGW pServiceConfig;
|
||||||
DWORD dwServiceType;
|
DWORD dwServiceType;
|
||||||
|
LPVOID pTarget = NULL;
|
||||||
wchar_t *str;
|
wchar_t *str;
|
||||||
HMODULE hModule;
|
HMODULE hModule;
|
||||||
|
|
||||||
// get mutex and unload event handles from virtual memory
|
if ( !pParam ) {
|
||||||
if ( !ctx ) {
|
trace(L"Parameter argument is null!");
|
||||||
trace(L"Context parameter is null!");
|
|
||||||
goto unload;
|
goto unload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handles[0] = pParam[0]; // main mutex
|
||||||
|
handles[1] = pParam[1]; // unload event
|
||||||
|
hCrashMutex = pParam[2]; // crash mutex
|
||||||
|
hProceedEvent = pParam[3]; // proceed event
|
||||||
|
VirtualFree(pParam, 0, MEM_RELEASE);
|
||||||
|
|
||||||
// acquire child mutex, this should be immediate.
|
// acquire child mutex, this should be immediate.
|
||||||
if ( WaitForSingleObject(ctx->handles[ctx->mutex_tag], 5000) != WAIT_OBJECT_0 ) {
|
if ( WaitForSingleObject(hCrashMutex, 5000) != WAIT_OBJECT_0 ) {
|
||||||
trace(L"Failed to acquire child mutex within five seconds. (%p)", ctx->handles[ctx->mutex_tag]);
|
trace(L"Failed to acquire child mutex within five seconds. (%p)", hCrashMutex);
|
||||||
goto close_handles;
|
goto close_handles;
|
||||||
}
|
}
|
||||||
|
SetEvent(hProceedEvent);
|
||||||
|
|
||||||
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
|
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
|
||||||
if ( !hSCM ) {
|
if ( !hSCM ) {
|
||||||
@@ -75,11 +86,12 @@ DWORD WINAPI cb_start(context *ctx)
|
|||||||
// RegQueryValueExW hook to fix incompatibility with
|
// RegQueryValueExW hook to fix incompatibility with
|
||||||
// UpdatePack7R2 and other patches that modify the
|
// UpdatePack7R2 and other patches that modify the
|
||||||
// Windows Update ServiceDll path in the registry.
|
// Windows Update ServiceDll path in the registry.
|
||||||
MH_CreateHookApi(L"kernel32.dll",
|
trace(L"MH_CreateHookApi RegQueryValueExW=%hs", MH_StatusToString(MH_CreateHookApiEx(L"kernel32.dll",
|
||||||
"RegQueryValueExW",
|
"RegQueryValueExW",
|
||||||
RegQueryValueExW_hook,
|
RegQueryValueExW_hook,
|
||||||
&(PVOID)g_pfnRegQueryValueExW);
|
&(PVOID)g_pfnRegQueryValueExW,
|
||||||
MH_EnableHook(g_pfnRegQueryValueExW);
|
&pTarget)));
|
||||||
|
trace(L"MH_EnableHook RegQueryValueExW=%hs", MH_StatusToString(MH_EnableHook(pTarget)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// query the ServiceDll path after applying our compat hook so that it
|
// query the ServiceDll path after applying our compat hook so that it
|
||||||
@@ -89,17 +101,18 @@ DWORD WINAPI cb_start(context *ctx)
|
|||||||
L"ServiceDll", NULL, NULL);
|
L"ServiceDll", NULL, NULL);
|
||||||
if ( !str ) {
|
if ( !str ) {
|
||||||
abort_hook:
|
abort_hook:
|
||||||
MH_RemoveHook(g_pfnRegQueryValueExW);
|
if ( pTarget )
|
||||||
|
trace(L"MH_RemoveHook RegQueryValueExW=%hs", MH_StatusToString(MH_RemoveHook(pTarget)));
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
|
g_pszWUServiceDll = env_expand_strings_alloc(str, NULL);
|
||||||
if ( !g_pszWUServiceDll ) goto abort_hook;
|
|
||||||
free(str);
|
free(str);
|
||||||
|
if ( !g_pszWUServiceDll ) goto abort_hook;
|
||||||
|
|
||||||
MH_CreateHookApi(L"kernel32.dll",
|
trace(L"MH_CreateHookApi LoadLibraryExW=%hs", MH_StatusToString(MH_CreateHookApi(L"kernel32.dll",
|
||||||
"LoadLibraryExW",
|
"LoadLibraryExW",
|
||||||
LoadLibraryExW_hook,
|
LoadLibraryExW_hook,
|
||||||
&(PVOID)g_pfnLoadLibraryExW);
|
&(PVOID)g_pfnLoadLibraryExW)));
|
||||||
|
|
||||||
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
|
if ( GetModuleHandleExW(0, g_pszWUServiceDll, &hModule)
|
||||||
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
|
|| GetModuleHandleExW(0, PathFindFileNameW(g_pszWUServiceDll), &hModule) ) {
|
||||||
@@ -109,27 +122,21 @@ abort_hook:
|
|||||||
FreeLibrary(hModule);
|
FreeLibrary(hModule);
|
||||||
|
|
||||||
}
|
}
|
||||||
MH_EnableHook(MH_ALL_HOOKS);
|
trace(L"MH_EnableHook=%hs", MH_StatusToString(MH_EnableHook(MH_ALL_HOOKS)));
|
||||||
|
|
||||||
// wait for unload event or the main mutex to be released or abandoned,
|
// wait for unload event or the main mutex to be released or abandoned,
|
||||||
// for example if the user killed rundll32.exe with task manager.
|
// for example if the user killed rundll32.exe with task manager.
|
||||||
|
WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
|
||||||
// we use ctx_wait_any_unsafe here because contexts created by
|
|
||||||
// ctx_duplicate_context are not initialized by ctx_create,
|
|
||||||
// and have no critical section to lock, so they are only used to
|
|
||||||
// hold static handles to send to another process.
|
|
||||||
ctx_wait_any_unsafe(ctx, false);
|
|
||||||
trace(L"Unload condition has been met.");
|
trace(L"Unload condition has been met.");
|
||||||
|
|
||||||
MH_DisableHook(MH_ALL_HOOKS);
|
trace(L"MH_DisableHook(MH_ALL_HOOKS) LoadLibraryExW=%hs", MH_StatusToString(MH_DisableHook(MH_ALL_HOOKS)));
|
||||||
free(g_pszWUServiceDll);
|
free(g_pszWUServiceDll);
|
||||||
release:
|
release:
|
||||||
ReleaseMutex(ctx->handles[ctx->mutex_tag]);
|
ReleaseMutex(hCrashMutex);
|
||||||
close_handles:
|
close_handles:
|
||||||
CloseHandle(ctx->handles[ctx->mutex_tag]);
|
CloseHandle(hCrashMutex);
|
||||||
CloseHandle(ctx->mutex);
|
CloseHandle(handles[0]);
|
||||||
CloseHandle(ctx->uevent);
|
CloseHandle(handles[1]);
|
||||||
VirtualFree(ctx, 0, MEM_RELEASE);
|
|
||||||
unload:
|
unload:
|
||||||
trace(L"Unloading wufuc and exiting thread.");
|
trace(L"Unloading wufuc and exiting thread.");
|
||||||
FreeLibraryAndExitThread(PIMAGEBASE, 0);
|
FreeLibraryAndExitThread(PIMAGEBASE, 0);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer);
|
VOID CALLBACK cb_service_notify(PSERVICE_NOTIFYW pNotifyBuffer);
|
||||||
DWORD WINAPI cb_start(context *ctx);
|
DWORD WINAPI cb_start(HANDLE *pParam);
|
||||||
|
@@ -1,404 +0,0 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#include "context.h"
|
|
||||||
|
|
||||||
#include <sddl.h>
|
|
||||||
|
|
||||||
static bool ctxp_remove_handle(context *ctx, DWORD Index)
|
|
||||||
{
|
|
||||||
if ( !ctx || Index > _countof(ctx->handles) || Index > ctx->count )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
for ( DWORD i = Index; i < ctx->count - 1; i++ ) {
|
|
||||||
ctx->handles[i] = ctx->handles[i + 1];
|
|
||||||
ctx->tags[i] = ctx->tags[i + 1];
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ctxp_create_new_mutex(bool InitialOwner,
|
|
||||||
const wchar_t *MutexName,
|
|
||||||
HANDLE *pMutexHandle)
|
|
||||||
{
|
|
||||||
HANDLE hMutex;
|
|
||||||
|
|
||||||
hMutex = CreateMutexW(NULL, InitialOwner, MutexName);
|
|
||||||
if ( hMutex ) {
|
|
||||||
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
|
|
||||||
CloseHandle(hMutex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*pMutexHandle = hMutex;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ctxp_create_new_mutex_vfmt(bool InitialOwner,
|
|
||||||
HANDLE *pMutexHandle,
|
|
||||||
const wchar_t *const NameFormat,
|
|
||||||
va_list ArgList)
|
|
||||||
{
|
|
||||||
wchar_t *buffer;
|
|
||||||
int ret;
|
|
||||||
bool result;
|
|
||||||
|
|
||||||
ret = _vscwprintf(NameFormat, ArgList) + 1;
|
|
||||||
buffer = calloc(ret, sizeof *buffer);
|
|
||||||
if ( !buffer )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ret = vswprintf_s(buffer, ret, NameFormat, ArgList);
|
|
||||||
if ( ret == -1 )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
result = ctxp_create_new_mutex(InitialOwner, buffer, pMutexHandle);
|
|
||||||
free(buffer);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ctxp_create_event_with_string_security_descriptor(
|
|
||||||
bool ManualReset,
|
|
||||||
bool InitialState,
|
|
||||||
const wchar_t *Name,
|
|
||||||
const wchar_t *StringSecurityDescriptor,
|
|
||||||
HANDLE *pEventHandle)
|
|
||||||
{
|
|
||||||
SECURITY_ATTRIBUTES sa = { sizeof sa };
|
|
||||||
HANDLE hEvent;
|
|
||||||
|
|
||||||
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
|
||||||
StringSecurityDescriptor,
|
|
||||||
SDDL_REVISION_1,
|
|
||||||
&sa.lpSecurityDescriptor,
|
|
||||||
NULL) ) {
|
|
||||||
|
|
||||||
hEvent = CreateEventW(&sa, ManualReset, InitialState, Name);
|
|
||||||
if ( hEvent ) {
|
|
||||||
*pEventHandle = hEvent;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD ctxp_find_handle_index(context *ctx, HANDLE Handle)
|
|
||||||
{
|
|
||||||
DWORD result = -1;
|
|
||||||
|
|
||||||
if ( !ctx || !Handle || Handle == INVALID_HANDLE_VALUE )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
for ( DWORD i = 0; i < ctx->count; i++ ) {
|
|
||||||
if ( ctx->handles[i] == Handle ) {
|
|
||||||
result = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_create(context *ctx,
|
|
||||||
const wchar_t *MutexName,
|
|
||||||
DWORD MutexTag,
|
|
||||||
const wchar_t *EventName,
|
|
||||||
const wchar_t *EventStringSecurityDescriptor,
|
|
||||||
DWORD EventTag)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if ( !ctx ) return false;
|
|
||||||
|
|
||||||
ZeroMemory(ctx, sizeof *ctx);
|
|
||||||
InitializeCriticalSection(&ctx->cs);
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
|
|
||||||
if ( ctxp_create_new_mutex(true, MutexName, &ctx->mutex) ) {
|
|
||||||
ctx->mutex_tag = MutexTag;
|
|
||||||
ctx->count++;
|
|
||||||
|
|
||||||
result = ctx_add_event(ctx, EventName, EventStringSecurityDescriptor, EventTag, NULL);
|
|
||||||
if ( !result ) {
|
|
||||||
ReleaseMutex(ctx->mutex);
|
|
||||||
ctx_close_and_remove_handle(ctx, ctx->mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_delete(context *ctx)
|
|
||||||
{
|
|
||||||
if ( !ctx || ctx->count > _countof(ctx->handles) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
while ( ctx->count-- ) {
|
|
||||||
CloseHandle(ctx->handles[ctx->count]);
|
|
||||||
ctx->handles[ctx->count] = INVALID_HANDLE_VALUE;
|
|
||||||
ctx->tags[ctx->count] = -1;
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
DeleteCriticalSection(&ctx->cs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_add_handle(context *ctx, HANDLE Handle, DWORD Tag)
|
|
||||||
{
|
|
||||||
DWORD result = -1;
|
|
||||||
|
|
||||||
if ( !ctx || !Handle )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
result = ctxp_find_handle_index(ctx, Handle);
|
|
||||||
if ( result != -1 ) {
|
|
||||||
ctx->tags[result] = Tag;
|
|
||||||
} else if ( ctx->count < _countof(ctx->handles) ) {
|
|
||||||
ctx->handles[ctx->count] = Handle;
|
|
||||||
ctx->tags[ctx->count] = Tag;
|
|
||||||
|
|
||||||
result = ctx->count++;
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_get_tag(context *ctx, HANDLE Handle, DWORD *pTag)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
if ( !ctx || !Handle || !pTag )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
index = ctxp_find_handle_index(ctx, Handle);
|
|
||||||
if ( index != -1 ) {
|
|
||||||
if ( pTag ) {
|
|
||||||
*pTag = ctx->tags[index];
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_add_new_mutex(context *ctx,
|
|
||||||
bool InitialOwner,
|
|
||||||
const wchar_t *Name,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pMutexHandle)
|
|
||||||
{
|
|
||||||
HANDLE hMutex;
|
|
||||||
DWORD result = -1;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
if ( ctxp_create_new_mutex(InitialOwner, Name, &hMutex) ) {
|
|
||||||
result = ctx_add_handle(ctx, hMutex, Tag);
|
|
||||||
if ( result != -1 ) {
|
|
||||||
if ( pMutexHandle )
|
|
||||||
*pMutexHandle = hMutex;
|
|
||||||
} else {
|
|
||||||
CloseHandle(hMutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_add_new_mutex_fmt(context *ctx,
|
|
||||||
bool InitialOwner,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pMutexHandle,
|
|
||||||
const wchar_t *const NameFormat,
|
|
||||||
...)
|
|
||||||
{
|
|
||||||
HANDLE hMutex;
|
|
||||||
DWORD result = -1;
|
|
||||||
va_list arglist;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
va_start(arglist, NameFormat);
|
|
||||||
if ( ctxp_create_new_mutex_vfmt(InitialOwner, &hMutex, NameFormat, arglist) ) {
|
|
||||||
result = ctx_add_handle(ctx, hMutex, Tag);
|
|
||||||
if ( result != -1 ) {
|
|
||||||
if ( pMutexHandle )
|
|
||||||
*pMutexHandle = hMutex;
|
|
||||||
} else {
|
|
||||||
CloseHandle(hMutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(arglist);
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_add_event(context *ctx,
|
|
||||||
const wchar_t *Name,
|
|
||||||
const wchar_t *StringSecurityDescriptor,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pEventHandle)
|
|
||||||
{
|
|
||||||
DWORD result = -1;
|
|
||||||
HANDLE hEvent;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
if ( ctxp_create_event_with_string_security_descriptor(
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
Name,
|
|
||||||
StringSecurityDescriptor,
|
|
||||||
&hEvent) ) {
|
|
||||||
result = ctx_add_handle(ctx, hEvent, Tag);
|
|
||||||
if ( result != -1 ) {
|
|
||||||
if ( pEventHandle )
|
|
||||||
*pEventHandle = hEvent;
|
|
||||||
} else {
|
|
||||||
CloseHandle(hEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_wait_all_unsafe(context *ctx,
|
|
||||||
bool Alertable)
|
|
||||||
{
|
|
||||||
return WaitForMultipleObjectsEx(ctx->count,
|
|
||||||
ctx->handles,
|
|
||||||
TRUE,
|
|
||||||
INFINITE,
|
|
||||||
Alertable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_wait_all(context *ctx,
|
|
||||||
bool Alertable,
|
|
||||||
DWORD *pResult)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
DWORD count;
|
|
||||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
count = ctx->count;
|
|
||||||
ret = memcpy_s(handles, sizeof(handles), ctx->handles, count * (sizeof *handles));
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
|
|
||||||
if ( ret )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*pResult = WaitForMultipleObjectsEx(count,
|
|
||||||
handles,
|
|
||||||
TRUE,
|
|
||||||
INFINITE,
|
|
||||||
Alertable);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_wait_any_unsafe(context *ctx,
|
|
||||||
bool Alertable)
|
|
||||||
{
|
|
||||||
return WaitForMultipleObjectsEx(ctx->count,
|
|
||||||
ctx->handles,
|
|
||||||
FALSE,
|
|
||||||
INFINITE,
|
|
||||||
Alertable);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD ctx_wait_any(context *ctx,
|
|
||||||
bool Alertable,
|
|
||||||
DWORD *pResult,
|
|
||||||
HANDLE *pHandle,
|
|
||||||
DWORD *pTag)
|
|
||||||
{
|
|
||||||
DWORD count;
|
|
||||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
|
||||||
DWORD tags[MAXIMUM_WAIT_OBJECTS];
|
|
||||||
int ret;
|
|
||||||
DWORD result;
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
// make copies of the struct members on the stack before waiting, because
|
|
||||||
// WaitForMultipleObjects(Ex) doesn't like it when you modify the contents of
|
|
||||||
// the array it is waiting on.
|
|
||||||
count = ctx->count;
|
|
||||||
ret = memcpy_s(handles, sizeof(handles), ctx->handles, count * (sizeof *handles));
|
|
||||||
if ( !ret )
|
|
||||||
ret = memcpy_s(tags, sizeof(tags), ctx->tags, count * (sizeof *tags));
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
|
|
||||||
if ( ret )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
result = WaitForMultipleObjectsEx(count, handles, FALSE, INFINITE, Alertable);
|
|
||||||
|
|
||||||
if ( result >= WAIT_OBJECT_0 || result < WAIT_OBJECT_0 + count )
|
|
||||||
index = result - WAIT_OBJECT_0;
|
|
||||||
else if ( result >= WAIT_ABANDONED_0 || result < WAIT_ABANDONED_0 + count )
|
|
||||||
index = result - WAIT_ABANDONED_0;
|
|
||||||
|
|
||||||
if ( pHandle )
|
|
||||||
*pHandle = handles[index];
|
|
||||||
if ( pTag )
|
|
||||||
*pTag = tags[index];
|
|
||||||
|
|
||||||
*pResult = result;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_close_and_remove_handle(context *ctx, HANDLE Handle)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
EnterCriticalSection(&ctx->cs);
|
|
||||||
index = ctxp_find_handle_index(ctx, Handle);
|
|
||||||
result = index != -1
|
|
||||||
&& CloseHandle(Handle)
|
|
||||||
&& ctxp_remove_handle(ctx, index);
|
|
||||||
LeaveCriticalSection(&ctx->cs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ctx_duplicate_context(const context *pSrc,
|
|
||||||
HANDLE hProcess,
|
|
||||||
context *pDst,
|
|
||||||
HANDLE Handle,
|
|
||||||
DWORD DesiredAccess,
|
|
||||||
DWORD Tag)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
HANDLE hSrcProcess;
|
|
||||||
HANDLE hTarget;
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
hSrcProcess = GetCurrentProcess();
|
|
||||||
|
|
||||||
if ( !DuplicateHandle(hSrcProcess, pSrc->mutex, hProcess, &pDst->mutex, SYNCHRONIZE, FALSE, 0) )
|
|
||||||
return false;
|
|
||||||
pDst->count++;
|
|
||||||
|
|
||||||
if ( !DuplicateHandle(hSrcProcess, pSrc->uevent, hProcess, &pDst->uevent, SYNCHRONIZE, FALSE, 0) ) {
|
|
||||||
close_mutex:
|
|
||||||
CloseHandle(pDst->mutex);
|
|
||||||
pDst->mutex = INVALID_HANDLE_VALUE;
|
|
||||||
pDst->count = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pDst->count++;
|
|
||||||
if ( !DuplicateHandle(hSrcProcess, Handle, hProcess, &hTarget, 0, FALSE, DesiredAccess)
|
|
||||||
|| (index = ctx_add_handle(pDst, hTarget, Tag)) == -1 ) {
|
|
||||||
|
|
||||||
CloseHandle(pDst->uevent);
|
|
||||||
pDst->uevent = INVALID_HANDLE_VALUE;
|
|
||||||
goto close_mutex;
|
|
||||||
|
|
||||||
}
|
|
||||||
pDst->mutex_tag = index;
|
|
||||||
return true;
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CRITICAL_SECTION cs;
|
|
||||||
DWORD count;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
HANDLE mutex;
|
|
||||||
HANDLE uevent;
|
|
||||||
};
|
|
||||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
DWORD mutex_tag;
|
|
||||||
DWORD uevent_tag;
|
|
||||||
};
|
|
||||||
DWORD tags[MAXIMUM_WAIT_OBJECTS];
|
|
||||||
};
|
|
||||||
} context;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
bool ctx_create(context *ctx,
|
|
||||||
const wchar_t *MutexName,
|
|
||||||
DWORD MutexTag,
|
|
||||||
const wchar_t *EventName,
|
|
||||||
const wchar_t *EventStringSecurityDescriptor,
|
|
||||||
DWORD EventTag);
|
|
||||||
bool ctx_delete(context *ctx);
|
|
||||||
DWORD ctx_add_handle(context *ctx, HANDLE Handle, DWORD Tag);
|
|
||||||
bool ctx_get_tag(context *ctx, HANDLE Handle, DWORD *pTag);
|
|
||||||
DWORD ctx_add_new_mutex(context *ctx,
|
|
||||||
bool InitialOwner,
|
|
||||||
const wchar_t *Name,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pMutexHandle);
|
|
||||||
DWORD ctx_add_new_mutex_fmt(context *ctx,
|
|
||||||
bool InitialOwner,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pMutexHandle,
|
|
||||||
const wchar_t *const NameFormat,
|
|
||||||
...);
|
|
||||||
DWORD ctx_add_event(context *ctx,
|
|
||||||
const wchar_t *Name,
|
|
||||||
const wchar_t *StringSecurityDescriptor,
|
|
||||||
DWORD Tag,
|
|
||||||
HANDLE *pEventHandle);
|
|
||||||
DWORD ctx_wait_all_unsafe(context *ctx,
|
|
||||||
bool Alertable);
|
|
||||||
bool ctx_wait_all(context *ctx,
|
|
||||||
bool Alertable,
|
|
||||||
DWORD *pResult);
|
|
||||||
DWORD ctx_wait_any_unsafe(context *ctx,
|
|
||||||
bool Alertable);
|
|
||||||
DWORD ctx_wait_any(context *ctx,
|
|
||||||
bool Alertable,
|
|
||||||
DWORD *pResult,
|
|
||||||
HANDLE *pHandle,
|
|
||||||
DWORD *pTag);
|
|
||||||
bool ctx_close_and_remove_handle(context *ctx, HANDLE Handle);
|
|
||||||
bool ctx_duplicate_context(const context *pSrc,
|
|
||||||
HANDLE hProcess,
|
|
||||||
context *pDst,
|
|
||||||
HANDLE Handle,
|
|
||||||
DWORD DesiredAccess,
|
|
||||||
DWORD Tag);
|
|
@@ -1,4 +1,5 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#include <minhook.h>
|
#include <minhook.h>
|
||||||
|
|
||||||
@@ -12,6 +13,7 @@ BOOL APIENTRY DllMain(HMODULE hModule,
|
|||||||
break;
|
break;
|
||||||
case DLL_THREAD_ATTACH:
|
case DLL_THREAD_ATTACH:
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
MH_Uninitialize();
|
MH_Uninitialize();
|
||||||
break;
|
break;
|
||||||
|
23
src/wufuc/eventhelper.c
Normal file
23
src/wufuc/eventhelper.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "eventhelper.h"
|
||||||
|
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
|
HANDLE event_create_with_string_security_descriptor(
|
||||||
|
bool ManualReset,
|
||||||
|
bool InitialState,
|
||||||
|
const wchar_t *Name,
|
||||||
|
const wchar_t *StringSecurityDescriptor)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof sa };
|
||||||
|
|
||||||
|
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||||
|
StringSecurityDescriptor,
|
||||||
|
SDDL_REVISION_1,
|
||||||
|
&sa.lpSecurityDescriptor,
|
||||||
|
NULL) ) {
|
||||||
|
|
||||||
|
return CreateEventW(&sa, ManualReset, InitialState, Name);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
7
src/wufuc/eventhelper.h
Normal file
7
src/wufuc/eventhelper.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
HANDLE event_create_with_string_security_descriptor(
|
||||||
|
bool ManualReset,
|
||||||
|
bool InitialState,
|
||||||
|
const wchar_t *Name,
|
||||||
|
const wchar_t *StringSecurityDescriptor);
|
@@ -1,8 +1,8 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "context.h"
|
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "registryhelper.h"
|
#include "registryhelper.h"
|
||||||
|
#include "ptrlist.h"
|
||||||
#include "wufuc.h"
|
#include "wufuc.h"
|
||||||
|
|
||||||
wchar_t *g_pszWUServiceDll;
|
wchar_t *g_pszWUServiceDll;
|
||||||
|
269
src/wufuc/log.c
269
src/wufuc/log.c
@@ -1,5 +1,4 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
void logp_debug_write(const wchar_t *const format, ...)
|
void logp_debug_write(const wchar_t *const format, ...)
|
||||||
@@ -7,7 +6,7 @@ void logp_debug_write(const wchar_t *const format, ...)
|
|||||||
DWORD pid;
|
DWORD pid;
|
||||||
wchar_t exepath[MAX_PATH];
|
wchar_t exepath[MAX_PATH];
|
||||||
wchar_t *exename;
|
wchar_t *exename;
|
||||||
va_list argptr;
|
va_list ap;
|
||||||
int count;
|
int count;
|
||||||
wchar_t *buffer1;
|
wchar_t *buffer1;
|
||||||
wchar_t *buffer2;
|
wchar_t *buffer2;
|
||||||
@@ -19,11 +18,13 @@ void logp_debug_write(const wchar_t *const format, ...)
|
|||||||
GetModuleFileNameW(NULL, exepath, _countof(exepath));
|
GetModuleFileNameW(NULL, exepath, _countof(exepath));
|
||||||
exename = PathFindFileNameW(exepath);
|
exename = PathFindFileNameW(exepath);
|
||||||
|
|
||||||
va_start(argptr, format);
|
va_start(ap, format);
|
||||||
count = _vscwprintf(format, argptr) + 1;
|
count = _vscwprintf(format, ap) + 1;
|
||||||
|
va_end(ap);
|
||||||
buffer1 = calloc(count, sizeof *buffer1);
|
buffer1 = calloc(count, sizeof *buffer1);
|
||||||
vswprintf_s(buffer1, count, format, argptr);
|
va_start(ap, format);
|
||||||
va_end(argptr);
|
vswprintf_s(buffer1, count, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
_wstrdate_s(datebuf, _countof(datebuf));
|
_wstrdate_s(datebuf, _countof(datebuf));
|
||||||
_wstrtime_s(timebuf, _countof(timebuf));
|
_wstrtime_s(timebuf, _countof(timebuf));
|
||||||
@@ -36,259 +37,3 @@ void logp_debug_write(const wchar_t *const format, ...)
|
|||||||
OutputDebugStringW(buffer2);
|
OutputDebugStringW(buffer2);
|
||||||
free(buffer2);
|
free(buffer2);
|
||||||
}
|
}
|
||||||
#define log_debug_write(format, ...) \
|
|
||||||
logp_debug_write(__FUNCTIONW__ L": " format L"\r\n", ##__VA_ARGS__)
|
|
||||||
#define trace log_debug_write
|
|
||||||
|
|
||||||
//#include "stdafx.h"
|
|
||||||
//#include "tracing.h"
|
|
||||||
//#include <Shlobj.h>
|
|
||||||
//
|
|
||||||
//wchar_t path[MAX_PATH];
|
|
||||||
//wchar_t exepath[MAX_PATH];
|
|
||||||
//
|
|
||||||
//bool tracec(bool condition, const wchar_t *const format, ...)
|
|
||||||
//{
|
|
||||||
// va_list argptr;
|
|
||||||
// int count;
|
|
||||||
// wchar_t *buffer;
|
|
||||||
//
|
|
||||||
// if ( condition ) {
|
|
||||||
// va_start(argptr, format);
|
|
||||||
//
|
|
||||||
// count = _vscwprintf(format, argptr) + 1;
|
|
||||||
// buffer = calloc(count, sizeof *buffer);
|
|
||||||
// vswprintf_s(buffer, count, format, argptr);
|
|
||||||
//
|
|
||||||
// va_end(argptr);
|
|
||||||
// OutputDebugStringW(buffer);
|
|
||||||
// free(buffer);
|
|
||||||
// }
|
|
||||||
// return condition;
|
|
||||||
//}
|
|
||||||
//void trace(const wchar_t *const format, ...)
|
|
||||||
//{
|
|
||||||
// va_list argptr;
|
|
||||||
// int count;
|
|
||||||
// wchar_t *buffer;
|
|
||||||
//
|
|
||||||
// va_start(argptr, format);
|
|
||||||
//
|
|
||||||
// count = _vscwprintf(format, argptr) + 1;
|
|
||||||
// buffer = calloc(count, sizeof *buffer);
|
|
||||||
// vswprintf_s(buffer, count, format, argptr);
|
|
||||||
//
|
|
||||||
// va_end(argptr);
|
|
||||||
// OutputDebugStringW(buffer);
|
|
||||||
// free(buffer);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//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,5 +2,5 @@
|
|||||||
|
|
||||||
void logp_debug_write(const wchar_t *const format, ...);
|
void logp_debug_write(const wchar_t *const format, ...);
|
||||||
#define log_debug_write(format, ...) \
|
#define log_debug_write(format, ...) \
|
||||||
logp_debug_write(__FUNCTIONW__ L": " format L"\r\n", ##__VA_ARGS__)
|
logp_debug_write(__FUNCTIONW__ L"(" _CRT_WIDE(_CRT_STRINGIZE(__LINE__)) L"): " format L"\r\n", ##__VA_ARGS__)
|
||||||
#define trace log_debug_write
|
#define trace log_debug_write
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "modulehelper.h"
|
#include "modulehelper.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName)
|
HMODULE mod_get_from_th32_snapshot(HANDLE hSnapshot, const wchar_t *pLibFileName)
|
||||||
{
|
{
|
||||||
@@ -61,7 +62,7 @@ bool mod_inject_and_begin_thread(
|
|||||||
virt_free:
|
virt_free:
|
||||||
if ( !result && pBaseAddress )
|
if ( !result && pBaseAddress )
|
||||||
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
|
||||||
resume_process:
|
resume_process:
|
||||||
NtResumeProcess(hProcess);
|
NtResumeProcess(hProcess);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -148,9 +149,9 @@ bool mod_inject(
|
|||||||
result = GetExitCodeThread(hThread, (LPDWORD)phRemoteModule) != FALSE;
|
result = GetExitCodeThread(hThread, (LPDWORD)phRemoteModule) != FALSE;
|
||||||
}
|
}
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
virt_free:
|
virt_free:
|
||||||
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pBaseAddress, 0, MEM_RELEASE);
|
||||||
resume_process:
|
resume_process:
|
||||||
NtResumeProcess(hProcess);
|
NtResumeProcess(hProcess);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
41
src/wufuc/mutexhelper.c
Normal file
41
src/wufuc/mutexhelper.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "mutexhelper.h"
|
||||||
|
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
|
HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName)
|
||||||
|
{
|
||||||
|
HANDLE hMutex;
|
||||||
|
|
||||||
|
hMutex = CreateMutexW(NULL, InitialOwner, MutexName);
|
||||||
|
if ( hMutex ) {
|
||||||
|
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
|
||||||
|
CloseHandle(hMutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return hMutex;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...)
|
||||||
|
{
|
||||||
|
HANDLE result = NULL;
|
||||||
|
va_list ap;
|
||||||
|
wchar_t *buffer;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, NameFormat);
|
||||||
|
ret = _vscwprintf(NameFormat, ap) + 1;
|
||||||
|
va_end(ap);
|
||||||
|
buffer = calloc(ret, sizeof *buffer);
|
||||||
|
if ( buffer ) {
|
||||||
|
va_start(ap, NameFormat);
|
||||||
|
ret = vswprintf_s(buffer, ret, NameFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (ret != -1)
|
||||||
|
result = mutex_create_new(InitialOwner, buffer);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
4
src/wufuc/mutexhelper.h
Normal file
4
src/wufuc/mutexhelper.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
HANDLE mutex_create_new(bool InitialOwner, const wchar_t *MutexName);
|
||||||
|
HANDLE mutex_create_new_fmt(bool InitialOwner, const wchar_t *const NameFormat, ...);
|
391
src/wufuc/ptrlist.c
Normal file
391
src/wufuc/ptrlist.c
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "ptrlist.h"
|
||||||
|
|
||||||
|
void ptrlist_lock(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&list->criticalSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_unlock(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&list->criticalSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag)
|
||||||
|
{
|
||||||
|
void *result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
result = list->values[index];
|
||||||
|
if ( pTag )
|
||||||
|
*pTag = list->tags[index];
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
size_t c;
|
||||||
|
size_t vsize;
|
||||||
|
size_t tsize;
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
if ( !list || capacity > maxCapacity )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
c = capacity ? capacity :
|
||||||
|
(maxCapacity ? min(maxCapacity, 16) : 16);
|
||||||
|
vsize = c * (sizeof *list->values);
|
||||||
|
tsize = c * (sizeof *list->tags);
|
||||||
|
|
||||||
|
InitializeCriticalSection(&list->criticalSection);
|
||||||
|
ptrlist_lock(list);
|
||||||
|
|
||||||
|
tmp = malloc(vsize + tsize);
|
||||||
|
if ( tmp ) {
|
||||||
|
ZeroMemory(tmp, vsize + tsize);
|
||||||
|
list->values = tmp;
|
||||||
|
list->tags = (uint32_t *)RtlOffsetToPointer(tmp, vsize);
|
||||||
|
list->capacity = c;
|
||||||
|
list->maxCapacity = maxCapacity;
|
||||||
|
list->count = 0;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
if ( !result )
|
||||||
|
DeleteCriticalSection(&list->criticalSection);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_destroy(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
if ( !list ) return;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
|
||||||
|
free(list->values);
|
||||||
|
list->values = NULL;
|
||||||
|
list->tags = NULL;
|
||||||
|
|
||||||
|
list->count = 0;
|
||||||
|
list->capacity = 0;
|
||||||
|
list->maxCapacity = 0;
|
||||||
|
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
DeleteCriticalSection(&list->criticalSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ptrlist_index_of(ptrlist_t *list, void *value)
|
||||||
|
{
|
||||||
|
size_t result = -1;
|
||||||
|
|
||||||
|
if ( !list || !value )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
for ( size_t i = 0; i < list->count; i++ ) {
|
||||||
|
if ( list->values[i] == value ) {
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
size_t newCapacity;
|
||||||
|
size_t diff;
|
||||||
|
size_t vsize;
|
||||||
|
size_t tsize;
|
||||||
|
void **tmp1;
|
||||||
|
uint32_t *tmp2;
|
||||||
|
|
||||||
|
if ( !list || !value )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
|
||||||
|
if ( list->count >= list->capacity ) {
|
||||||
|
newCapacity = list->count;
|
||||||
|
if ( list->maxCapacity ) {
|
||||||
|
diff = list->maxCapacity - list->capacity;
|
||||||
|
if ( !diff )
|
||||||
|
goto leave;
|
||||||
|
newCapacity += min(diff, 16);
|
||||||
|
} else {
|
||||||
|
newCapacity += 16;
|
||||||
|
}
|
||||||
|
vsize = newCapacity * (sizeof *list->values);
|
||||||
|
tsize = newCapacity * (sizeof *list->tags);
|
||||||
|
|
||||||
|
tmp1 = malloc(vsize + tsize);
|
||||||
|
|
||||||
|
if ( !tmp1 )
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
ZeroMemory(tmp1, vsize);
|
||||||
|
|
||||||
|
tmp2 = (uint32_t *)RtlOffsetToPointer(tmp1, vsize);
|
||||||
|
ZeroMemory(tmp2, tsize);
|
||||||
|
|
||||||
|
if ( memmove_s(tmp1, vsize, list->values, list->count * (sizeof *list->values))
|
||||||
|
|| memmove_s(tmp2, tsize, list->tags, list->count * (sizeof *list->tags)) ) {
|
||||||
|
|
||||||
|
free(tmp1);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
list->values = tmp1;
|
||||||
|
list->tags = tmp2;
|
||||||
|
list->capacity = newCapacity;
|
||||||
|
}
|
||||||
|
list->values[list->count] = value;
|
||||||
|
list->tags[list->count] = tag;
|
||||||
|
list->count++;
|
||||||
|
result = true;
|
||||||
|
leave:
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if ( !list || !values || !count )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
if ( list->count + count <= list->maxCapacity ) {
|
||||||
|
for ( size_t i = 0; result && i < count; i++ )
|
||||||
|
result = ptrlist_add(list, values[i], tags ? tags[i] : 0);
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_remove_at(ptrlist_t *list, size_t index)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if ( !list ) return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
if ( index <= list->count - 1 ) {
|
||||||
|
for ( size_t i = index; i < list->count - 1; i++ )
|
||||||
|
list->values[i] = list->values[i + 1];
|
||||||
|
|
||||||
|
list->values[list->count--] = NULL;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_remove(ptrlist_t *list, void *value)
|
||||||
|
{
|
||||||
|
size_t index;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if ( !list || !value )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
index = ptrlist_index_of(list, value);
|
||||||
|
if ( index != -1 )
|
||||||
|
result = ptrlist_remove_at(list, index);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if ( !list || !count )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
if ( index <= list->count - 1
|
||||||
|
&& index + count <= list->count ) {
|
||||||
|
|
||||||
|
for ( size_t i = 0; result && i < count; i++ )
|
||||||
|
result = ptrlist_remove_at(list, index);
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_clear(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if ( !list ) return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
result = ptrlist_remove_range(list, 0, list->count);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ptrlist_get_count(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
size_t result = -1;
|
||||||
|
|
||||||
|
if ( !list ) return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
result = list->count;
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ptrlist_get_capacity(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
size_t result = -1;
|
||||||
|
|
||||||
|
if ( !list ) return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
result = list->capacity;
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ptrlist_get_max_capacity(ptrlist_t *list)
|
||||||
|
{
|
||||||
|
size_t result = -1;
|
||||||
|
|
||||||
|
if ( !list ) return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
result = list->maxCapacity;
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_contains(ptrlist_t *list, void *value)
|
||||||
|
{
|
||||||
|
return ptrlist_index_of(list, value) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void **ptrlist_copy_values(ptrlist_t *list, size_t *count)
|
||||||
|
{
|
||||||
|
void **result = NULL;
|
||||||
|
size_t size;
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
if ( !list || !count )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
c = list->count;
|
||||||
|
if ( !c ) goto leave;
|
||||||
|
|
||||||
|
size = c * (sizeof *list->values);
|
||||||
|
result = malloc(c * (sizeof *list->values));
|
||||||
|
if ( result ) {
|
||||||
|
if ( !memcpy_s(result, size, list->values, size) ) {
|
||||||
|
*count = c;
|
||||||
|
} else {
|
||||||
|
free(result);
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count)
|
||||||
|
{
|
||||||
|
uint32_t *result = NULL;
|
||||||
|
size_t size;
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
if ( !list || !count )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
c = list->count;
|
||||||
|
if ( !c ) goto leave;
|
||||||
|
|
||||||
|
size = c * (sizeof *list->tags);
|
||||||
|
result = malloc(c * (sizeof *list->tags));
|
||||||
|
if ( result ) {
|
||||||
|
if ( !memcpy_s(result, size, list->tags, size) ) {
|
||||||
|
*count = c;
|
||||||
|
} else {
|
||||||
|
free(result);
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave:
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
void **v;
|
||||||
|
uint32_t *t;
|
||||||
|
size_t c;
|
||||||
|
|
||||||
|
if ( !values || !tags || !count )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
ptrlist_lock(list);
|
||||||
|
v = ptrlist_copy_values(list, &c);
|
||||||
|
if ( !v ) goto leave;
|
||||||
|
|
||||||
|
t = ptrlist_copy_tags(list, &c);
|
||||||
|
if ( !t ) {
|
||||||
|
free(v);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
*values = v;
|
||||||
|
*tags = t;
|
||||||
|
*count = c;
|
||||||
|
result = true;
|
||||||
|
leave:
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *))
|
||||||
|
{
|
||||||
|
ptrlist_lock(list);
|
||||||
|
ptrlist_for_stdcall(list, 0, list->count, f);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *))
|
||||||
|
{
|
||||||
|
ptrlist_lock(list);
|
||||||
|
for ( size_t i = index; i < count; i++ )
|
||||||
|
f(list->values[i]);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_for_each_cdecl(ptrlist_t *list, void(__cdecl *f)(void *))
|
||||||
|
{
|
||||||
|
ptrlist_lock(list);
|
||||||
|
ptrlist_for_cdecl(list, 0, list->count, f);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptrlist_for_cdecl(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *))
|
||||||
|
{
|
||||||
|
ptrlist_lock(list);
|
||||||
|
for ( size_t i = index; i < count; i++ )
|
||||||
|
f(list->values[i]);
|
||||||
|
ptrlist_unlock(list);
|
||||||
|
}
|
36
src/wufuc/ptrlist.h
Normal file
36
src/wufuc/ptrlist.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct ptrlist_t_ {
|
||||||
|
void **values;
|
||||||
|
uint32_t *tags;
|
||||||
|
size_t capacity;
|
||||||
|
size_t maxCapacity;
|
||||||
|
size_t count;
|
||||||
|
CRITICAL_SECTION criticalSection;
|
||||||
|
} ptrlist_t;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void ptrlist_lock(ptrlist_t *list);
|
||||||
|
void ptrlist_unlock(ptrlist_t *list);
|
||||||
|
void ptrlist_for_each_stdcall(ptrlist_t *list, void(__stdcall *f)(void *));
|
||||||
|
void ptrlist_for_stdcall(ptrlist_t *list, size_t index, size_t count, void(__stdcall *f)(void *));
|
||||||
|
void ptrlist_for_each_cdecl(ptrlist_t *list, void(__cdecl *f)(void *));
|
||||||
|
void ptrlist_for_cdecl(ptrlist_t *list, size_t index, size_t count, void(__cdecl *f)(void *));
|
||||||
|
void *ptrlist_at(ptrlist_t *list, size_t index, uint32_t *pTag);
|
||||||
|
bool ptrlist_create(ptrlist_t *list, size_t capacity, size_t maxCapacity);
|
||||||
|
void ptrlist_destroy(ptrlist_t *list);
|
||||||
|
size_t ptrlist_index_of(ptrlist_t *list, void *value);
|
||||||
|
bool ptrlist_add(ptrlist_t *list, void *value, uint32_t tag);
|
||||||
|
bool ptrlist_add_range(ptrlist_t *list, void **values, uint32_t *tags, size_t count);
|
||||||
|
bool ptrlist_remove_at(ptrlist_t *list, size_t index);
|
||||||
|
bool ptrlist_remove(ptrlist_t *list, void *value);
|
||||||
|
bool ptrlist_remove_range(ptrlist_t *list, size_t index, size_t count);
|
||||||
|
bool ptrlist_clear(ptrlist_t *list);
|
||||||
|
size_t ptrlist_get_count(ptrlist_t *list);
|
||||||
|
size_t ptrlist_get_capacity(ptrlist_t *list);
|
||||||
|
size_t ptrlist_get_max_capacity(ptrlist_t *list);
|
||||||
|
bool ptrlist_contains(ptrlist_t *list, void *value);
|
||||||
|
void **ptrlist_copy_values(ptrlist_t *list, size_t *count);
|
||||||
|
uint32_t *ptrlist_copy_tags(ptrlist_t *list, size_t *count);
|
||||||
|
bool ptrlist_copy(ptrlist_t *list, void ***values, uint32_t **tags, size_t *count);
|
@@ -1,15 +1,23 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "context.h"
|
|
||||||
#include "callbacks.h"
|
#include "callbacks.h"
|
||||||
|
#include "eventhelper.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "modulehelper.h"
|
#include "modulehelper.h"
|
||||||
|
#include "mutexhelper.h"
|
||||||
|
#include "ptrlist.h"
|
||||||
#include "registryhelper.h"
|
#include "registryhelper.h"
|
||||||
#include "servicehelper.h"
|
#include "servicehelper.h"
|
||||||
#include "wufuc.h"
|
#include "wufuc.h"
|
||||||
|
|
||||||
void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
|
const wchar_t m_szUnloadEventName[] = L"Global\\wufuc_UnloadEvent";
|
||||||
|
|
||||||
|
void CALLBACK RUNDLL32_StartW(HWND hwnd,
|
||||||
|
HINSTANCE hinst,
|
||||||
|
LPWSTR lpszCmdLine,
|
||||||
|
int nCmdShow)
|
||||||
{
|
{
|
||||||
context ctx;
|
ptrlist_t list;
|
||||||
|
HANDLE hEvent;
|
||||||
DWORD dwDesiredAccess;
|
DWORD dwDesiredAccess;
|
||||||
DWORD dwProcessId;
|
DWORD dwProcessId;
|
||||||
bool Unloading = false;
|
bool Unloading = false;
|
||||||
@@ -17,21 +25,29 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
|
|||||||
SC_HANDLE hSCM;
|
SC_HANDLE hSCM;
|
||||||
SC_HANDLE hService;
|
SC_HANDLE hService;
|
||||||
SERVICE_NOTIFYW NotifyBuffer;
|
SERVICE_NOTIFYW NotifyBuffer;
|
||||||
DWORD count;
|
void **values;
|
||||||
|
uint32_t *tags;
|
||||||
|
size_t count;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
HANDLE handle;
|
size_t index;
|
||||||
DWORD tag;
|
size_t crashes;
|
||||||
|
|
||||||
if ( !ctx_create(&ctx,
|
if ( !ptrlist_create(&list, 0, MAXIMUM_WAIT_OBJECTS) ) return;
|
||||||
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645", 0,
|
|
||||||
L"Global\\wufuc_UnloadEvent", L"D:(A;;0x001F0003;;;BA)", 0) )
|
g_hMainMutex = mutex_create_new(true,
|
||||||
return;
|
L"Global\\25020063-b5a7-4227-9fdf-25cb75e8c645");
|
||||||
|
if ( !g_hMainMutex ) goto destroy_list;
|
||||||
|
|
||||||
|
hEvent = event_create_with_string_security_descriptor(
|
||||||
|
true, false, m_szUnloadEventName, L"D:(A;;0x001F0003;;;BA)");
|
||||||
|
if ( !hEvent ) goto release_mutex;
|
||||||
|
if ( !ptrlist_add(&list, hEvent, 0) ) goto set_event;
|
||||||
|
|
||||||
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
|
dwDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG;
|
||||||
do {
|
do {
|
||||||
Lagging = false;
|
Lagging = false;
|
||||||
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
|
hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
|
||||||
if ( !hSCM ) goto delete_ctx;
|
if ( !hSCM ) goto set_event;
|
||||||
|
|
||||||
hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess);
|
hService = OpenServiceW(hSCM, L"wuauserv", dwDesiredAccess);
|
||||||
if ( !hService ) goto close_scm;
|
if ( !hService ) goto close_scm;
|
||||||
@@ -41,41 +57,59 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
|
|||||||
|
|
||||||
dwProcessId = svc_heuristic_process_id(hSCM, hService);
|
dwProcessId = svc_heuristic_process_id(hSCM, hService);
|
||||||
if ( dwProcessId )
|
if ( dwProcessId )
|
||||||
wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)cb_start, &ctx);
|
wufuc_inject(dwProcessId, (LPTHREAD_START_ROUTINE)cb_start, &list);
|
||||||
}
|
}
|
||||||
ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer);
|
ZeroMemory(&NotifyBuffer, sizeof NotifyBuffer);
|
||||||
NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
|
NotifyBuffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
|
||||||
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)cb_service_notify;
|
NotifyBuffer.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)cb_service_notify;
|
||||||
NotifyBuffer.pContext = (PVOID)&ctx;
|
NotifyBuffer.pContext = (PVOID)&list;
|
||||||
while ( !Unloading && !Lagging ) {
|
while ( !Unloading && !Lagging ) {
|
||||||
switch ( NotifyServiceStatusChangeW(hService,
|
switch ( NotifyServiceStatusChangeW(hService,
|
||||||
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
|
SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_RUNNING,
|
||||||
&NotifyBuffer) ) {
|
&NotifyBuffer) ) {
|
||||||
case ERROR_SUCCESS:
|
case ERROR_SUCCESS:
|
||||||
count = ctx_wait_any(&ctx, true, &ret, &handle, &tag);
|
if ( !ptrlist_copy(&list, &values, &tags, &count) ) {
|
||||||
if ( count == -1 ) {
|
|
||||||
// Wait function failed while making static copy of handles/tags, wtf!
|
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
break;
|
break;
|
||||||
} else if ( ret == WAIT_OBJECT_0 + 1 ) {
|
}
|
||||||
trace(L"Unload event was signaled!");
|
ret = WaitForMultipleObjectsEx((DWORD)count,
|
||||||
Unloading = true;
|
values, FALSE, INFINITE, TRUE);
|
||||||
break;
|
|
||||||
} else if ( (ret >= ERROR_ABANDONED_WAIT_0 || ret < WAIT_ABANDONED_0 + count) ) {
|
|
||||||
g_ServiceHostCrashCount++;
|
|
||||||
trace(L"A process that wufuc injected into has crashed %Iu times!!! PID=%lu",
|
|
||||||
g_ServiceHostCrashCount, tag);
|
|
||||||
|
|
||||||
ReleaseMutex(handle); // release the abandoned mutex
|
if ( ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + count ) {
|
||||||
ctx_close_and_remove_handle(&ctx, handle);
|
// object signaled
|
||||||
if ( g_ServiceHostCrashCount >= WUFUC_CRASH_THRESHOLD ) {
|
index = ret - WAIT_OBJECT_0;
|
||||||
|
|
||||||
|
if ( index == 0 ) { // Unload event
|
||||||
|
Unloading = true;
|
||||||
|
break;
|
||||||
|
} else { // crash mutex was closed but the process didn't crash
|
||||||
|
ptrlist_remove(&list, values[index]);
|
||||||
|
ReleaseMutex(values[index]);
|
||||||
|
CloseHandle(values[index]);
|
||||||
|
}
|
||||||
|
} else if ( ret >= WAIT_ABANDONED_0 && ret < WAIT_ABANDONED_0 + count ) {
|
||||||
|
// object abandoned
|
||||||
|
// crash mutex was abandoned, process has most likely crashed.
|
||||||
|
index = ret - WAIT_ABANDONED_0;
|
||||||
|
|
||||||
|
ptrlist_remove(&list, values[index]);
|
||||||
|
ReleaseMutex(values[index]);
|
||||||
|
CloseHandle(values[index]);
|
||||||
|
|
||||||
|
crashes++;
|
||||||
|
trace(L"A process that wufuc injected into has crashed %Iu time%ls!!! (PID=%lu)",
|
||||||
|
crashes, crashes != 1 ? L"s" : L"", tags[index]);
|
||||||
|
|
||||||
|
if ( crashes >= SVCHOST_CRASH_THRESHOLD ) {
|
||||||
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
|
trace(L"Crash threshold has been reached, disabling wufuc until next reboot!");
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
}
|
}
|
||||||
} else if ( ret == WAIT_FAILED ) {
|
} else if ( ret == WAIT_FAILED ) {
|
||||||
trace(L"Wait failed! GLE=%lu", GetLastError());
|
trace(L"WTF - Unexpected result from wait function!!!");
|
||||||
Unloading = true;
|
Unloading = true;
|
||||||
}
|
}
|
||||||
|
free(values);
|
||||||
|
free(tags);
|
||||||
break;
|
break;
|
||||||
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
|
case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING:
|
||||||
trace(L"Client lagging!");
|
trace(L"Client lagging!");
|
||||||
@@ -90,15 +124,25 @@ void CALLBACK RUNDLL32_StartW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in
|
|||||||
close_scm:
|
close_scm:
|
||||||
CloseServiceHandle(hSCM);
|
CloseServiceHandle(hSCM);
|
||||||
} while ( Lagging );
|
} while ( Lagging );
|
||||||
delete_ctx:
|
set_event:
|
||||||
ctx_delete(&ctx);
|
// signal event in case it is open in any other processes
|
||||||
|
SetEvent(hEvent);
|
||||||
|
release_mutex:
|
||||||
|
ReleaseMutex(g_hMainMutex);
|
||||||
|
destroy_list:
|
||||||
|
ptrlist_for_each_stdcall(&list, CloseHandle);
|
||||||
|
ptrlist_destroy(&list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK RUNDLL32_UnloadW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
|
void CALLBACK RUNDLL32_UnloadW(
|
||||||
|
HWND hwnd,
|
||||||
|
HINSTANCE hinst,
|
||||||
|
LPWSTR lpszCmdLine,
|
||||||
|
int nCmdShow)
|
||||||
{
|
{
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
|
|
||||||
hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\wufuc_UnloadEvent");
|
hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, m_szUnloadEventName);
|
||||||
if ( hEvent ) {
|
if ( hEvent ) {
|
||||||
SetEvent(hEvent);
|
SetEvent(hEvent);
|
||||||
CloseHandle(hEvent);
|
CloseHandle(hEvent);
|
||||||
|
@@ -1,38 +1,97 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "context.h"
|
#include "ptrlist.h"
|
||||||
#include "wufuc.h"
|
#include "wufuc.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "modulehelper.h"
|
#include "modulehelper.h"
|
||||||
|
#include "mutexhelper.h"
|
||||||
#include "patternfind.h"
|
#include "patternfind.h"
|
||||||
#include "versionhelper.h"
|
#include "versionhelper.h"
|
||||||
|
|
||||||
#include <minhook.h>
|
#include <minhook.h>
|
||||||
|
|
||||||
size_t g_ServiceHostCrashCount;
|
HANDLE g_hMainMutex;
|
||||||
|
|
||||||
bool wufuc_inject(DWORD dwProcessId,
|
bool close_remote_handle(HANDLE hProcess, HANDLE hObject)
|
||||||
LPTHREAD_START_ROUTINE pfnStart,
|
|
||||||
context *pContext)
|
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
HANDLE hProcess;
|
DWORD ExitCode;
|
||||||
HANDLE hMutex;
|
HANDLE hThread;
|
||||||
context ctx;
|
|
||||||
|
|
||||||
if ( !ctx_add_new_mutex_fmt(pContext,
|
hThread = CreateRemoteThread(hProcess,
|
||||||
false,
|
NULL,
|
||||||
dwProcessId,
|
0,
|
||||||
&hMutex,
|
(LPTHREAD_START_ROUTINE)CloseHandle,
|
||||||
L"Global\\%08x-7132-44a8-be15-56698979d2f3", dwProcessId) )
|
(LPVOID)hObject,
|
||||||
return false;
|
0,
|
||||||
|
NULL);
|
||||||
|
if ( hThread ) {
|
||||||
|
if ( WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0
|
||||||
|
&& GetExitCodeThread(hThread, &ExitCode) ) {
|
||||||
|
|
||||||
|
result = !!ExitCode;
|
||||||
|
}
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wufuc_inject(DWORD dwProcessId,
|
||||||
|
LPTHREAD_START_ROUTINE pStartAddress,
|
||||||
|
ptrlist_t *list)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
HANDLE hCrashMutex;
|
||||||
|
HANDLE hProcess;
|
||||||
|
HANDLE h;
|
||||||
|
HANDLE hProceedEvent;
|
||||||
|
HANDLE p[4];
|
||||||
|
|
||||||
|
hCrashMutex = mutex_create_new_fmt(false, L"Global\\wufuc_CrashMutex*%08x", dwProcessId);
|
||||||
|
if ( !hCrashMutex ) return result;
|
||||||
|
if ( !ptrlist_add(list, hCrashMutex, dwProcessId) )
|
||||||
|
goto close_mutex;
|
||||||
|
|
||||||
|
hProceedEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
|
if ( !hProceedEvent ) goto close_mutex;
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
|
||||||
if ( !hProcess ) return false;
|
if ( !hProcess ) goto close_pevent;
|
||||||
|
|
||||||
result = ctx_duplicate_context(pContext, hProcess, &ctx, hMutex, DUPLICATE_SAME_ACCESS, dwProcessId)
|
h = GetCurrentProcess();
|
||||||
&& mod_inject_and_begin_thread(hProcess, PIMAGEBASE, pfnStart, &ctx, sizeof ctx);
|
if ( !DuplicateHandle(h, g_hMainMutex, hProcess, &p[0], SYNCHRONIZE, FALSE, 0) )
|
||||||
|
goto close_process;
|
||||||
|
if ( !DuplicateHandle(h, ptrlist_at(list, 0, NULL), hProcess, &p[1], SYNCHRONIZE, FALSE, 0) )
|
||||||
|
goto close_p0;
|
||||||
|
if ( !DuplicateHandle(h, hCrashMutex, hProcess, &p[2], 0, FALSE, DUPLICATE_SAME_ACCESS) )
|
||||||
|
goto close_p1;
|
||||||
|
if ( !DuplicateHandle(h, hProceedEvent, hProcess, &p[3], EVENT_MODIFY_STATE, FALSE, 0) )
|
||||||
|
goto close_p2;
|
||||||
|
|
||||||
|
result = mod_inject_and_begin_thread(hProcess, PIMAGEBASE, pStartAddress, p, sizeof p);
|
||||||
|
|
||||||
|
if ( result ) {
|
||||||
|
// wait for injected thread to signal that it has taken
|
||||||
|
// ownership of hCrashMutex before proceeding.
|
||||||
|
result = WaitForSingleObject(hProceedEvent, 5000) != WAIT_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
close_remote_handle(hProcess, p[3]);
|
||||||
|
close_p2:
|
||||||
|
close_remote_handle(hProcess, p[2]);
|
||||||
|
close_p1:
|
||||||
|
close_remote_handle(hProcess, p[1]);
|
||||||
|
close_p0:
|
||||||
|
close_remote_handle(hProcess, p[0]);
|
||||||
|
}
|
||||||
|
close_process:
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
|
close_pevent:
|
||||||
|
CloseHandle(hProceedEvent);
|
||||||
|
if ( !result ) {
|
||||||
|
close_mutex:
|
||||||
|
ptrlist_remove(list, hCrashMutex);
|
||||||
|
CloseHandle(hCrashMutex);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +109,7 @@ bool wufuc_hook(HMODULE hModule)
|
|||||||
VS_FIXEDFILEINFO *pffi;
|
VS_FIXEDFILEINFO *pffi;
|
||||||
MODULEINFO modinfo;
|
MODULEINFO modinfo;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
LPVOID pTarget;
|
||||||
|
|
||||||
if ( !ver_verify_windows_7_sp1() && !ver_verify_windows_8_1() )
|
if ( !ver_verify_windows_7_sp1() && !ver_verify_windows_8_1() )
|
||||||
return false;
|
return false;
|
||||||
@@ -85,11 +145,11 @@ bool wufuc_hook(HMODULE hModule)
|
|||||||
trace(L"Failed to allocate version information from hmodule.");
|
trace(L"Failed to allocate version information from hmodule.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu"),
|
trace(L"Windows Update Agent version: %hu.%hu.%hu.%hu",
|
||||||
HIWORD(pffi->dwProductVersionMS),
|
HIWORD(pffi->dwProductVersionMS),
|
||||||
LOWORD(pffi->dwProductVersionMS),
|
LOWORD(pffi->dwProductVersionMS),
|
||||||
HIWORD(pffi->dwProductVersionLS),
|
HIWORD(pffi->dwProductVersionLS),
|
||||||
LOWORD(pffi->dwProductVersionLS);
|
LOWORD(pffi->dwProductVersionLS));
|
||||||
|
|
||||||
// assure wuaueng.dll is at least the minimum supported version
|
// assure wuaueng.dll is at least the minimum supported version
|
||||||
tmp = ((ver_verify_windows_7_sp1() && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1)
|
tmp = ((ver_verify_windows_7_sp1() && ver_compare_product_version(pffi, 7, 6, 7601, 23714) != -1)
|
||||||
@@ -113,10 +173,9 @@ bool wufuc_hook(HMODULE hModule)
|
|||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if ( offset != -1 ) {
|
if ( offset != -1 ) {
|
||||||
result = MH_CreateHook(
|
pTarget = (LPVOID)RtlOffsetToPointer(modinfo.lpBaseOfDll, offset);
|
||||||
RtlOffsetToPointer(modinfo.lpBaseOfDll, offset),
|
MH_CreateHook(pTarget, IsDeviceServiceable_hook, NULL);
|
||||||
IsDeviceServiceable_hook,
|
result = (MH_EnableHook(pTarget) == MH_OK);
|
||||||
NULL) == MH_OK;
|
|
||||||
} else {
|
} else {
|
||||||
trace(L"Could not locate pattern offset!");
|
trace(L"Could not locate pattern offset!");
|
||||||
}
|
}
|
||||||
|
@@ -6,11 +6,11 @@ typedef struct
|
|||||||
WORD wCodePage;
|
WORD wCodePage;
|
||||||
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
||||||
|
|
||||||
#define WUFUC_CRASH_THRESHOLD 3
|
#define SVCHOST_CRASH_THRESHOLD 3
|
||||||
|
|
||||||
extern size_t g_ServiceHostCrashCount;
|
extern HANDLE g_hMainMutex;
|
||||||
|
|
||||||
bool wufuc_inject(DWORD dwProcessId,
|
bool wufuc_inject(DWORD dwProcessId,
|
||||||
LPTHREAD_START_ROUTINE pfnStart,
|
LPTHREAD_START_ROUTINE pStartAddress,
|
||||||
context *pContext);
|
ptrlist_t *list);
|
||||||
bool wufuc_hook(HMODULE hModule);
|
bool wufuc_hook(HMODULE hModule);
|
@@ -20,7 +20,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="callbacks.h" />
|
<ClInclude Include="callbacks.h" />
|
||||||
<ClInclude Include="context.h" />
|
<ClInclude Include="eventhelper.h" />
|
||||||
|
<ClInclude Include="mutexhelper.h" />
|
||||||
|
<ClInclude Include="ptrlist.h" />
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
<ClInclude Include="modulehelper.h" />
|
<ClInclude Include="modulehelper.h" />
|
||||||
<ClInclude Include="registryhelper.h" />
|
<ClInclude Include="registryhelper.h" />
|
||||||
@@ -34,11 +36,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="callbacks.c" />
|
<ClCompile Include="callbacks.c" />
|
||||||
<ClCompile Include="context.c" />
|
|
||||||
<ClCompile Include="dllmain.c" />
|
<ClCompile Include="dllmain.c" />
|
||||||
|
<ClCompile Include="eventhelper.c" />
|
||||||
|
<ClCompile Include="ptrlist.c" />
|
||||||
<ClCompile Include="modulehelper.c" />
|
<ClCompile Include="modulehelper.c" />
|
||||||
<ClCompile Include="registryhelper.c" />
|
<ClCompile Include="registryhelper.c" />
|
||||||
<ClCompile Include="servicehelper.c" />
|
<ClCompile Include="servicehelper.c" />
|
||||||
|
<ClCompile Include="mutexhelper.c" />
|
||||||
<ClCompile Include="versionhelper.c" />
|
<ClCompile Include="versionhelper.c" />
|
||||||
<ClCompile Include="hooks.c" />
|
<ClCompile Include="hooks.c" />
|
||||||
<ClCompile Include="log.c" />
|
<ClCompile Include="log.c" />
|
||||||
|
@@ -30,9 +30,6 @@
|
|||||||
<ClInclude Include="patternfind.h">
|
<ClInclude Include="patternfind.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="context.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="versionhelper.h">
|
<ClInclude Include="versionhelper.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -51,6 +48,15 @@
|
|||||||
<ClInclude Include="log.h">
|
<ClInclude Include="log.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ptrlist.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="eventhelper.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="mutexhelper.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="callbacks.c">
|
<ClCompile Include="callbacks.c">
|
||||||
@@ -71,9 +77,6 @@
|
|||||||
<ClCompile Include="patternfind.c">
|
<ClCompile Include="patternfind.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="context.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="servicehelper.c">
|
<ClCompile Include="servicehelper.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -92,6 +95,15 @@
|
|||||||
<ClCompile Include="modulehelper.c">
|
<ClCompile Include="modulehelper.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ptrlist.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="mutexhelper.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="eventhelper.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="wufuc.rc">
|
<ResourceCompile Include="wufuc.rc">
|
||||||
|
Reference in New Issue
Block a user