0.8pre. installers are not finished [skip ci]
This commit is contained in:
44
wufuc/appverifier.h
Normal file
44
wufuc/appverifier.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <phnt_windows.h>
|
||||
|
||||
#define DLL_PROCESS_VERIFIER 4
|
||||
|
||||
typedef VOID(NTAPI *RTL_VERIFIER_DLL_LOAD_CALLBACK)(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
|
||||
typedef VOID(NTAPI *RTL_VERIFIER_DLL_UNLOAD_CALLBACK)(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
|
||||
typedef VOID(NTAPI *RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK)(PVOID AllocationBase, SIZE_T AllocationSize);
|
||||
|
||||
typedef struct tagRTL_VERIFIER_THUNK_DESCRIPTOR
|
||||
{
|
||||
PCHAR ThunkName;
|
||||
PVOID ThunkOldAddress;
|
||||
PVOID ThunkNewAddress;
|
||||
} RTL_VERIFIER_THUNK_DESCRIPTOR, *PRTL_VERIFIER_THUNK_DESCRIPTOR;
|
||||
|
||||
typedef struct tagRTL_VERIFIER_DLL_DESCRIPTOR
|
||||
{
|
||||
PWCHAR DllName;
|
||||
DWORD DllFlags;
|
||||
PVOID DllAddress;
|
||||
PRTL_VERIFIER_THUNK_DESCRIPTOR DllThunks;
|
||||
} RTL_VERIFIER_DLL_DESCRIPTOR, *PRTL_VERIFIER_DLL_DESCRIPTOR;
|
||||
|
||||
typedef struct tagRTL_VERIFIER_PROVIDER_DESCRIPTOR
|
||||
{
|
||||
DWORD Length;
|
||||
PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls;
|
||||
RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
|
||||
RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
|
||||
PWSTR VerifierImage;
|
||||
DWORD VerifierFlags;
|
||||
DWORD VerifierDebug;
|
||||
PVOID RtlpGetStackTraceAddress;
|
||||
PVOID RtlpDebugPageHeapCreate;
|
||||
PVOID RtlpDebugPageHeapDestroy;
|
||||
RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback;
|
||||
} RTL_VERIFIER_PROVIDER_DESCRIPTOR, *PRTL_VERIFIER_PROVIDER_DESCRIPTOR;
|
||||
|
||||
extern RTL_VERIFIER_THUNK_DESCRIPTOR g_vfADVAPIThunkDescriptors[];
|
||||
extern RTL_VERIFIER_THUNK_DESCRIPTOR g_vfK32ThunkDescriptors[];
|
||||
extern RTL_VERIFIER_DLL_DESCRIPTOR g_vfDllDescriptors[];
|
||||
extern RTL_VERIFIER_PROVIDER_DESCRIPTOR g_vfProviderDescriptor;
|
@@ -1,55 +1,15 @@
|
||||
#include "callbacks.h"
|
||||
|
||||
#include "iathook.h"
|
||||
#include "hooks.h"
|
||||
#include "helpers.h"
|
||||
#include "service.h"
|
||||
#include "tracing.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <sddl.h>
|
||||
#include <phnt_windows.h>
|
||||
|
||||
DWORD WINAPI ThreadProcCallback(LPVOID *lpParam) {
|
||||
OSVERSIONINFO osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
#pragma warning(suppress : 4996)
|
||||
if ( GetVersionEx(&osvi) )
|
||||
trace(_T("Windows version: %d.%d.%d (%zu-bit)"), osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, sizeof(uintptr_t) * 8);
|
||||
else trace(_T("Failed to get Windows version (error code=%08X)"), GetLastError());
|
||||
|
||||
char brand[0x31];
|
||||
trace(_T("Processor: %hs"), get_cpuid_brand(brand, _countof(brand)));
|
||||
|
||||
LPTSTR lpCommandLine = GetCommandLine();
|
||||
TCHAR lpServiceCommandLine[0x8000];
|
||||
if ( GetServiceCommandLine(NULL, _T("wuauserv"), lpServiceCommandLine, _countof(lpServiceCommandLine))
|
||||
&& !_tcsicmp(lpCommandLine, lpServiceCommandLine) ) {
|
||||
|
||||
SECURITY_ATTRIBUTES sa = { 0 };
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = FALSE;
|
||||
if ( ConvertStringSecurityDescriptorToSecurityDescriptor(_T("D:(A;;0x001F0003;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL) ) {
|
||||
HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||
if ( hEvent ) {
|
||||
HANDLE threads[0x1000];
|
||||
|
||||
size_t count = suspend_other_threads(threads, _countof(threads));
|
||||
iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", (LPVOID)&pfnRegQueryValueExW, RegQueryValueExW_hook);
|
||||
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", (LPVOID)&pfnLoadLibraryExW, LoadLibraryExW_hook);
|
||||
resume_and_close_threads(threads, count);
|
||||
|
||||
WaitForSingleObject(hEvent, INFINITE);
|
||||
trace(_T("Unload event was set, removing hooks and unloading..."));
|
||||
|
||||
count = suspend_other_threads(threads, _countof(threads));
|
||||
iat_hook(GetModuleHandle(NULL), "LoadLibraryExW", NULL, pfnLoadLibraryExW);
|
||||
iat_hook(GetModuleHandle(NULL), "RegQueryValueExW", NULL, pfnRegQueryValueExW);
|
||||
resume_and_close_threads(threads, count);
|
||||
CloseHandle(hEvent);
|
||||
} else trace(_T("Failed to create unload event (error code=%08X)"), GetLastError());
|
||||
} else trace(_T("Failed to convert string security descriptor to security descriptor (error code=%08X)"), GetLastError());
|
||||
} else trace(_T("Current process command line is incorrect: %s != %s"), lpCommandLine, lpServiceCommandLine);
|
||||
trace(_T("Bye bye!"));
|
||||
FreeLibraryAndExitThread((HMODULE)lpParam, 0);
|
||||
VOID NTAPI VerifierDllLoadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
|
||||
{
|
||||
trace(L"dll load %ls, DllBase=%p, DllSize=%Iu", DllName, DllBase, DllSize);
|
||||
}
|
||||
|
||||
VOID NTAPI VerifierDllUnloadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved)
|
||||
{
|
||||
trace(L"dll unload %ls, DllBase=%p, DllSize=%Iu", DllName, DllBase, DllSize);
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
#ifndef CALLBACKS_H_INCLUDED
|
||||
#define CALLBACKS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <phnt_windows.h>
|
||||
|
||||
DWORD WINAPI ThreadProcCallback(LPVOID *lpParam);
|
||||
#endif
|
||||
VOID NTAPI VerifierDllLoadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
|
||||
VOID NTAPI VerifierDllUnloadCallback(PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
|
||||
|
@@ -1,29 +1,63 @@
|
||||
#include "appverifier.h"
|
||||
#include "hooks.h"
|
||||
#include "callbacks.h"
|
||||
#include "helpers.h"
|
||||
#include "ntdllhelper.h"
|
||||
#include "tracing.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
switch ( ul_reason_for_call ) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
if ( !IsOperatingSystemSupported() /*|| IsWow64()*/ )
|
||||
return FALSE;
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcCallback, (LPVOID)hModule, 0, NULL);
|
||||
CloseHandle(hThread);
|
||||
break;
|
||||
}
|
||||
case DLL_PROCESS_DETACH:
|
||||
DeinitTracing();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
RTL_VERIFIER_THUNK_DESCRIPTOR g_vfK32ThunkDescriptors[] = {
|
||||
{ "RegQueryValueExW", NULL, (PVOID)&RegQueryValueExW_Hook },
|
||||
{ "LoadLibraryExW", NULL, (PVOID)&LoadLibraryExW_Hook },
|
||||
{ 0 } };
|
||||
RTL_VERIFIER_DLL_DESCRIPTOR g_vfDllDescriptors[] = {
|
||||
{ L"kernel32.dll", 0, NULL, g_vfK32ThunkDescriptors },
|
||||
{ 0 } };
|
||||
RTL_VERIFIER_DLL_DESCRIPTOR g_vfNullDllDescriptor[] = { { 0 } };
|
||||
RTL_VERIFIER_PROVIDER_DESCRIPTOR g_vfProviderDescriptor = {
|
||||
sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR),
|
||||
g_vfNullDllDescriptor,
|
||||
//(RTL_VERIFIER_DLL_LOAD_CALLBACK)&VerifierDllLoadCallback,
|
||||
//(RTL_VERIFIER_DLL_UNLOAD_CALLBACK)&VerifierDllUnloadCallback
|
||||
};
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch ( ul_reason_for_call ) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
LdrDisableThreadCalloutsForDll((PVOID)hModule);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_VERIFIER:;
|
||||
if ( verify_winver(6, 1, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0)
|
||||
|| verify_winver(6, 3, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) ) {
|
||||
|
||||
RTL_QUERY_REGISTRY_TABLE QueryTable[1];
|
||||
RtlSecureZeroMemory(&QueryTable, sizeof(QueryTable));
|
||||
QueryTable[0].Name = L"ImagePath";
|
||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||
UNICODE_STRING ImagePath;
|
||||
RtlInitUnicodeString(&ImagePath, NULL);
|
||||
QueryTable[0].EntryContext = &ImagePath;
|
||||
NTSTATUS Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
|
||||
L"wuauserv",
|
||||
QueryTable,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
// TODO: check status and maybe fix implementation? idk...
|
||||
if ( !RtlCompareUnicodeString(&NtCurrentPeb()->ProcessParameters->CommandLine, &ImagePath, TRUE) ) {
|
||||
g_vfProviderDescriptor.ProviderDlls = g_vfDllDescriptors;
|
||||
}
|
||||
}
|
||||
*(PRTL_VERIFIER_PROVIDER_DESCRIPTOR *)lpReserved = &g_vfProviderDescriptor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
194
wufuc/helpers.c
194
wufuc/helpers.c
@@ -1,140 +1,84 @@
|
||||
#include "helpers.h"
|
||||
|
||||
#include "tracing.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
|
||||
OSVERSIONINFOEX osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
osvi.dwMajorVersion = dwMajorVersion;
|
||||
osvi.dwMinorVersion = dwMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
osvi.wServicePackMinor = wServicePackMinor;
|
||||
bool verify_winver(
|
||||
DWORD dwMajorVersion,
|
||||
DWORD dwMinorVersion,
|
||||
DWORD dwBuildNumber,
|
||||
WORD wServicePackMajor,
|
||||
WORD wServicePackMinor,
|
||||
BYTE MajorVersionCondition,
|
||||
BYTE MinorVersionCondition,
|
||||
BYTE BuildNumberCondition,
|
||||
BYTE ServicePackMajorCondition,
|
||||
BYTE ServicePackMinorCondition
|
||||
)
|
||||
{
|
||||
RTL_OSVERSIONINFOEXW osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
||||
|
||||
DWORDLONG dwlConditionMask = 0;
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, Operator);
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, Operator);
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, Operator);
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMINOR, Operator);
|
||||
osvi.dwMajorVersion = dwMajorVersion;
|
||||
osvi.dwMinorVersion = dwMinorVersion;
|
||||
osvi.dwBuildNumber = dwBuildNumber;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
osvi.wServicePackMinor = wServicePackMinor;
|
||||
|
||||
return VerifyVersionInfo(&osvi, dwTypeMask, dwlConditionMask);
|
||||
ULONGLONG ConditionMask = 0;
|
||||
ULONG TypeMask = 0;
|
||||
if ( MajorVersionCondition ) {
|
||||
TypeMask |= VER_MAJORVERSION;
|
||||
VER_SET_CONDITION(ConditionMask, VER_MAJORVERSION, MajorVersionCondition);
|
||||
}
|
||||
if ( MinorVersionCondition ) {
|
||||
TypeMask |= VER_MINORVERSION;
|
||||
VER_SET_CONDITION(ConditionMask, VER_MINORVERSION, MinorVersionCondition);
|
||||
}
|
||||
if ( BuildNumberCondition ) {
|
||||
TypeMask |= VER_BUILDNUMBER;
|
||||
VER_SET_CONDITION(ConditionMask, VER_BUILDNUMBER, BuildNumberCondition);
|
||||
}
|
||||
if ( ServicePackMajorCondition ) {
|
||||
TypeMask |= VER_SERVICEPACKMAJOR;
|
||||
VER_SET_CONDITION(ConditionMask, VER_SERVICEPACKMAJOR, ServicePackMajorCondition);
|
||||
}
|
||||
if ( ServicePackMinorCondition ) {
|
||||
TypeMask |= VER_SERVICEPACKMINOR;
|
||||
VER_SET_CONDITION(ConditionMask, VER_SERVICEPACKMINOR, ServicePackMinorCondition);
|
||||
}
|
||||
return RtlVerifyVersionInfo(&osvi, TypeMask, ConditionMask) == STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL IsWindows7(void) {
|
||||
static BOOL checked = FALSE, isWindows7 = FALSE;
|
||||
wchar_t *find_fname(wchar_t *pPath)
|
||||
{
|
||||
wchar_t *pwc = wcsrchr(pPath, L'\\');
|
||||
if ( pwc && *(++pwc) )
|
||||
return pwc;
|
||||
|
||||
if ( !checked ) {
|
||||
isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
||||
checked = TRUE;
|
||||
}
|
||||
return isWindows7;
|
||||
return pPath;
|
||||
}
|
||||
|
||||
BOOL IsWindows8Point1(void) {
|
||||
static BOOL checked = FALSE, isWindows8Point1 = FALSE;
|
||||
|
||||
if ( !checked ) {
|
||||
isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
|
||||
checked = TRUE;
|
||||
}
|
||||
return isWindows8Point1;
|
||||
BOOL file_exists(const wchar_t *path)
|
||||
{
|
||||
return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
BOOL IsOperatingSystemSupported(void) {
|
||||
#if !defined(_AMD64_) && !defined(_X86_)
|
||||
return FALSE;
|
||||
#else
|
||||
return IsWindows7() || IsWindows8Point1();
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL IsWow64(void) {
|
||||
static BOOL checked = FALSE, isWow64 = FALSE;
|
||||
static ISWOW64PROCESS pfnIsWow64Process = NULL;
|
||||
|
||||
if ( !checked ) {
|
||||
if ( !pfnIsWow64Process )
|
||||
pfnIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
|
||||
|
||||
if ( pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &isWow64) )
|
||||
checked = TRUE;
|
||||
}
|
||||
return isWow64;
|
||||
}
|
||||
|
||||
size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount) {
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
THREADENTRY32 te = { 0 };
|
||||
te.dwSize = sizeof(te);
|
||||
size_t count = 0;
|
||||
if ( Thread32First(hSnap, &te) ) {
|
||||
DWORD dwProcessId = GetCurrentProcessId();
|
||||
DWORD dwThreadId = GetCurrentThreadId();
|
||||
WaitForTracingMutex(); // make sure we don't dead lock
|
||||
do {
|
||||
if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId )
|
||||
continue;
|
||||
|
||||
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
|
||||
SuspendThread(lphThreads[count]);
|
||||
count++;
|
||||
} while ( count < nMaxCount && Thread32Next(hSnap, &te) );
|
||||
ReleaseTracingMutex();
|
||||
}
|
||||
CloseHandle(hSnap);
|
||||
trace(_T("Suspended %zu other threads"), count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount) {
|
||||
for ( size_t i = 0; i < nCount; i++ ) {
|
||||
ResumeThread(lphThreads[i]);
|
||||
CloseHandle(lphThreads[i]);
|
||||
}
|
||||
trace(_T("Resumed %zu threads"), nCount);
|
||||
}
|
||||
|
||||
char *get_cpuid_brand(char *brand, size_t nMaxCount) {
|
||||
int info[4];
|
||||
__cpuidex(info, 0x80000000, 0);
|
||||
if ( info[0] < 0x80000004 ) {
|
||||
brand[0] = '\0';
|
||||
return brand;
|
||||
}
|
||||
uint32_t *char_as_int = (uint32_t *)brand;
|
||||
for ( int op = 0x80000002; op <= 0x80000004; op++ ) {
|
||||
__cpuidex(info, op, 0);
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
*(char_as_int++) = info[i];
|
||||
}
|
||||
size_t i = 0;
|
||||
while ( i < nMaxCount && isspace(brand[i]) )
|
||||
i++;
|
||||
|
||||
return brand + i;
|
||||
}
|
||||
|
||||
wchar_t *find_fname(wchar_t *pPath) {
|
||||
wchar_t *pwc = wcsrchr(pPath, L'\\');
|
||||
if ( pwc && *(++pwc) )
|
||||
return pwc;
|
||||
|
||||
return pPath;
|
||||
}
|
||||
|
||||
int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2) {
|
||||
if ( ma1 < ma2 ) return -1;
|
||||
if ( ma1 > ma2 ) return 1;
|
||||
if ( mi1 < mi2 ) return -1;
|
||||
if ( mi1 > mi2 ) return 1;
|
||||
if ( b1 < b2 ) return -1;
|
||||
if ( b1 > b2 ) return 1;
|
||||
if ( r1 < r2 ) return -1;
|
||||
if ( r1 > r2 ) return 1;
|
||||
return 0;
|
||||
int compare_versions(
|
||||
WORD wMajorA, WORD wMinorA, WORD wBuildA, WORD wRevisionA,
|
||||
WORD wMajorB, WORD wMinorB, WORD wBuildB, WORD wRevisionB
|
||||
)
|
||||
{
|
||||
if ( wMajorA < wMajorB ) return -1;
|
||||
if ( wMajorA > wMajorB ) return 1;
|
||||
if ( wMinorA < wMinorB ) return -1;
|
||||
if ( wMinorA > wMinorB ) return 1;
|
||||
if ( wBuildA < wBuildB ) return -1;
|
||||
if ( wBuildA > wBuildB ) return 1;
|
||||
if ( wRevisionA < wRevisionB ) return -1;
|
||||
if ( wRevisionA > wRevisionB ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,20 +1,25 @@
|
||||
#ifndef HELPERS_H_INCLUDED
|
||||
#define HELPERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef BOOL(WINAPI *ISWOW64PROCESS)(HANDLE, PBOOL);
|
||||
#include <phnt_windows.h>
|
||||
|
||||
BOOL IsWindows7(void);
|
||||
BOOL IsWindows8Point1(void);
|
||||
BOOL IsOperatingSystemSupported(void);
|
||||
BOOL IsWow64(void);
|
||||
bool verify_winver(
|
||||
DWORD dwMajorVersion,
|
||||
DWORD dwMinorVersion,
|
||||
DWORD dwBuildNumber,
|
||||
WORD wServicePackMajor,
|
||||
WORD wServicePackMinor,
|
||||
BYTE MajorVersionCondition,
|
||||
BYTE MinorVersionCondition,
|
||||
BYTE BuildNumberCondition,
|
||||
BYTE ServicePackMajorCondition,
|
||||
BYTE ServicePackMinorCondition
|
||||
);
|
||||
|
||||
size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount);
|
||||
void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount);
|
||||
|
||||
char *get_cpuid_brand(char *brand, size_t nMaxCount);
|
||||
wchar_t *find_fname(wchar_t *pPath);
|
||||
int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2);
|
||||
#endif
|
||||
BOOL file_exists(const wchar_t *path);
|
||||
int compare_versions(
|
||||
WORD wMajorA, WORD wMinorA, WORD wBuildA, WORD wRevisionA,
|
||||
WORD wMajorB, WORD wMinorB, WORD wBuildB, WORD wRevisionB);
|
||||
|
||||
|
204
wufuc/hooks.c
204
wufuc/hooks.c
@@ -1,121 +1,141 @@
|
||||
#include "hooks.h"
|
||||
|
||||
#include "helpers.h"
|
||||
#include "appverifier.h"
|
||||
#include "patchwua.h"
|
||||
#include "ntdllhelper.h"
|
||||
#include "helpers.h"
|
||||
#include "tracing.h"
|
||||
#include "rtl_malloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <ntstatus.h>
|
||||
#include <tchar.h>
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
#include <Psapi.h>
|
||||
|
||||
REGQUERYVALUEEXW pfnRegQueryValueExW = NULL;
|
||||
LOADLIBRARYEXW pfnLoadLibraryExW = NULL;
|
||||
|
||||
LRESULT WINAPI RegQueryValueExW_hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
|
||||
size_t nMaxCount = *lpcbData / sizeof(wchar_t);
|
||||
LSTATUS WINAPI RegQueryValueExW_Hook(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
||||
{
|
||||
LSTATUS result;
|
||||
|
||||
LRESULT result = pfnRegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
if ( (lpData && lpcbData)
|
||||
&& (lpValueName && !_wcsicmp(lpValueName, L"ServiceDll")) ) {
|
||||
|
||||
NTSTATUS status;
|
||||
ULONG ResultLength;
|
||||
if ( !_wcsicmp(lpValueName, L"ServiceDll")
|
||||
&& TryNtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength, &status)
|
||||
&& (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL) ) {
|
||||
DWORD cbData = *lpcbData;
|
||||
size_t MaxCount = cbData / sizeof(wchar_t);
|
||||
|
||||
PKEY_NAME_INFORMATION pkni = malloc(ResultLength);
|
||||
if ( TryNtQueryKey((HANDLE)hKey, KeyNameInformation, (PVOID)pkni, ResultLength, &ResultLength, &status)
|
||||
&& NT_SUCCESS(status) ) {
|
||||
// this way the dll path is garunteed to be null terminated
|
||||
result = RegGetValueW(hKey, NULL, lpValueName, RRF_RT_REG_EXPAND_SZ | RRF_NOEXPAND, lpType, lpData, lpcbData);
|
||||
if ( result != ERROR_SUCCESS )
|
||||
goto L_ret;
|
||||
|
||||
size_t nBufferCount = pkni->NameLength / sizeof(wchar_t);
|
||||
int current, pos;
|
||||
if ( _snwscanf_s(pkni->Name, nBufferCount, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet%03d\\services\\wuauserv\\Parameters%n", ¤t, &pos) == 1
|
||||
&& pos == nBufferCount ) {
|
||||
ULONG ResultLength;
|
||||
NTSTATUS Status = NtQueryKey((HANDLE)hKey, KeyNameInformation, NULL, 0, &ResultLength);
|
||||
if ( Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL )
|
||||
goto L_ret;
|
||||
|
||||
size_t nCount = nMaxCount + 1;
|
||||
wchar_t *path = calloc(nCount, sizeof(wchar_t));
|
||||
wcsncpy_s(path, nCount, (wchar_t *)lpData, *lpcbData / sizeof(wchar_t));
|
||||
PKEY_NAME_INFORMATION pkni = rtl_malloc(ResultLength);
|
||||
Status = NtQueryKey((HANDLE)hKey, KeyNameInformation, (PVOID)pkni, ResultLength, &ResultLength);
|
||||
if ( Status == STATUS_SUCCESS ) {
|
||||
size_t BufferCount = pkni->NameLength / sizeof(wchar_t);
|
||||
int current, pos;
|
||||
if ( _snwscanf_s(pkni->Name, BufferCount, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet%03d\\services\\wuauserv\\Parameters%n", ¤t, &pos) == 1
|
||||
&& pos == BufferCount ) {
|
||||
|
||||
wchar_t *fname = find_fname(path);
|
||||
if ( !_wcsicmp(fname, L"wuaueng2.dll") // UpdatePack7R2
|
||||
|| !_wcsicmp(fname, L"WuaCpuFix64.dll") // WuaCpuFix
|
||||
|| !_wcsicmp(fname, L"WuaCpuFix.dll") ) {
|
||||
wchar_t drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
|
||||
_wsplitpath_s((wchar_t *)lpData,
|
||||
drive, _countof(drive),
|
||||
dir, _countof(dir),
|
||||
fname, _countof(fname),
|
||||
ext, _countof(ext));
|
||||
|
||||
wcscpy_s(fname, nMaxCount - (fname - path), L"wuaueng.dll");
|
||||
if ( !_wcsicmp(ext, L".dll")
|
||||
&& (!_wcsicmp(fname, L"wuaueng2") // UpdatePack7R2
|
||||
|| !_wcsicmp(fname, L"WuaCpuFix64") // WuaCpuFix
|
||||
|| !_wcsicmp(fname, L"WuaCpuFix")) ) {
|
||||
|
||||
DWORD nSize = ExpandEnvironmentStringsW(path, NULL, 0);
|
||||
wchar_t *lpDst = calloc(nSize, sizeof(wchar_t));
|
||||
ExpandEnvironmentStringsW(path, lpDst, nSize);
|
||||
if ( GetFileAttributesW(lpDst) != INVALID_FILE_ATTRIBUTES ) {
|
||||
trace(_T("Compatibility fix: %.*ls -> %ls"), *lpcbData / sizeof(wchar_t), (wchar_t *)lpData, path);
|
||||
size_t nLength = wcsnlen_s(path, nMaxCount);
|
||||
wcsncpy_s((wchar_t *)lpData, nMaxCount, path, nLength);
|
||||
*lpcbData = (DWORD)(nLength * sizeof(wchar_t));
|
||||
}
|
||||
free(lpDst);
|
||||
wchar_t *tmp = rtl_malloc(cbData);
|
||||
|
||||
_wmakepath_s(tmp, MaxCount, drive, dir, L"wuaueng", ext);
|
||||
DWORD nSize = ExpandEnvironmentStringsW(tmp, NULL, 0);
|
||||
|
||||
wchar_t *lpDst = rtl_calloc(nSize, sizeof(wchar_t));
|
||||
ExpandEnvironmentStringsW(tmp, lpDst, nSize);
|
||||
|
||||
rtl_free(tmp);
|
||||
|
||||
if ( file_exists(lpDst) ) {
|
||||
_wmakepath_s((wchar_t *)lpData, MaxCount, drive, dir, L"wuaueng", ext);
|
||||
*lpcbData = (DWORD)((wcslen((wchar_t *)lpData) + 1) * sizeof(wchar_t));
|
||||
trace(L"Fixed wuauserv ServiceDll path: %ls", lpDst);
|
||||
}
|
||||
rtl_free(lpDst);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
rtl_free(pkni);
|
||||
} else {
|
||||
// handle normally
|
||||
result = ((LPFN_REGQUERYVALUEEXW)g_vfK32ThunkDescriptors[0].ThunkOldAddress)(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
}
|
||||
free(pkni);
|
||||
}
|
||||
return result;
|
||||
L_ret:
|
||||
return result;
|
||||
}
|
||||
|
||||
HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags) {
|
||||
HMODULE result = pfnLoadLibraryExW(lpFileName, hFile, dwFlags);
|
||||
trace(_T("Loaded library: %ls"), lpFileName);
|
||||
|
||||
DWORD dwLen = GetFileVersionInfoSizeW(lpFileName, NULL);
|
||||
if ( dwLen ) {
|
||||
LPVOID pBlock = malloc(dwLen);
|
||||
HMODULE WINAPI LoadLibraryExW_Hook(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags)
|
||||
{
|
||||
HMODULE result = ((LPFN_LOADLIBRARYEXW)g_vfK32ThunkDescriptors[1].ThunkOldAddress)(lpFileName, hFile, dwFlags);
|
||||
if ( !result ) {
|
||||
trace(L"Failed to load library: %ls (error code=%08X)", lpFileName, GetLastError());
|
||||
goto L_ret;
|
||||
}
|
||||
trace(L"Loaded library: %ls", lpFileName);
|
||||
DWORD dwLen = GetFileVersionInfoSizeW(lpFileName, NULL);
|
||||
if ( !dwLen ) {
|
||||
trace(L"Failed to get file version info size for file %ls (error code=%08X)", lpFileName, GetLastError());
|
||||
goto L_ret;
|
||||
}
|
||||
LPVOID pBlock = rtl_malloc(dwLen);
|
||||
if ( GetFileVersionInfoW(lpFileName, 0, dwLen, pBlock) ) {
|
||||
PLANGANDCODEPAGE ptl;
|
||||
UINT cb;
|
||||
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) ) {
|
||||
wchar_t lpSubBlock[38];
|
||||
for ( size_t i = 0; i < (cb / sizeof(LANGANDCODEPAGE)); i++ ) {
|
||||
swprintf_s(lpSubBlock, _countof(lpSubBlock), L"\\StringFileInfo\\%04x%04x\\InternalName", ptl[i].wLanguage, ptl[i].wCodePage);
|
||||
wchar_t *lpszInternalName;
|
||||
UINT uLen;
|
||||
if ( VerQueryValueW(pBlock, lpSubBlock, (LPVOID *)&lpszInternalName, &uLen)
|
||||
&& !_wcsicmp(lpszInternalName, L"wuaueng.dll") ) {
|
||||
PLANGANDCODEPAGE ptl;
|
||||
UINT cb;
|
||||
if ( VerQueryValueW(pBlock, L"\\VarFileInfo\\Translation", (LPVOID *)&ptl, &cb) ) {
|
||||
wchar_t lpSubBlock[38];
|
||||
for ( size_t i = 0; i < (cb / sizeof(LANGANDCODEPAGE)); i++ ) {
|
||||
swprintf_s(lpSubBlock, _countof(lpSubBlock), L"\\StringFileInfo\\%04x%04x\\InternalName", ptl[i].wLanguage, ptl[i].wCodePage);
|
||||
wchar_t *lpszInternalName;
|
||||
UINT uLen;
|
||||
if ( VerQueryValueW(pBlock, lpSubBlock, (LPVOID *)&lpszInternalName, &uLen)
|
||||
&& !_wcsicmp(lpszInternalName, L"wuaueng.dll") ) {
|
||||
|
||||
VS_FIXEDFILEINFO *pffi;
|
||||
VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen);
|
||||
WORD wMajor = HIWORD(pffi->dwProductVersionMS);
|
||||
WORD wMinor = LOWORD(pffi->dwProductVersionMS);
|
||||
WORD wBuild = HIWORD(pffi->dwProductVersionLS);
|
||||
WORD wRevision = LOWORD(pffi->dwProductVersionLS);
|
||||
VS_FIXEDFILEINFO *pffi;
|
||||
VerQueryValueW(pBlock, L"\\", (LPVOID *)&pffi, &uLen);
|
||||
WORD wMajor = HIWORD(pffi->dwProductVersionMS);
|
||||
WORD wMinor = LOWORD(pffi->dwProductVersionMS);
|
||||
WORD wBuild = HIWORD(pffi->dwProductVersionLS);
|
||||
WORD wRevision = LOWORD(pffi->dwProductVersionLS);
|
||||
|
||||
TCHAR fname[MAX_PATH];
|
||||
GetModuleBaseName(GetCurrentProcess(), result, fname, _countof(fname));
|
||||
|
||||
if ( (IsWindows7() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 6, 7601, 23714) != -1)
|
||||
|| (IsWindows8Point1() && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 9, 9600, 18621) != -1) ) {
|
||||
wchar_t path[MAX_PATH];
|
||||
GetModuleFileNameW(result, path, _countof(path));
|
||||
wchar_t *fname = find_fname(path);
|
||||
|
||||
trace(_T("%s version: %d.%d.%d.%d"), fname, wMajor, wMinor, wBuild, wRevision);
|
||||
MODULEINFO modinfo;
|
||||
if ( GetModuleInformation(GetCurrentProcess(), result, &modinfo, sizeof(MODULEINFO)) ) {
|
||||
if ( PatchWUA(modinfo.lpBaseOfDll, modinfo.SizeOfImage) )
|
||||
trace(_T("Successfully patched %s!"), fname);
|
||||
else trace(_T("Failed to patch %s!"), fname);
|
||||
}
|
||||
|
||||
else trace(_T("Failed to get module information for %s (%p) (couldn't patch)"), fname, result);
|
||||
} else trace(_T("Unsupported version of %s: %d.%d.%d.%d (patching skipped)"), fname, wMajor, wMinor, wBuild, wRevision);
|
||||
break;
|
||||
}
|
||||
if ( (verify_winver(6, 1, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 6, 7601, 23714) != -1)
|
||||
|| (verify_winver(6, 3, 0, 0, 0, VER_EQUAL, VER_EQUAL, 0, 0, 0) && compare_versions(wMajor, wMinor, wBuild, wRevision, 7, 9, 9600, 18621) != -1) ) {
|
||||
|
||||
trace(L"%ls version: %d.%d.%d.%d", fname, wMajor, wMinor, wBuild, wRevision);
|
||||
MODULEINFO modinfo;
|
||||
if ( GetModuleInformation(GetCurrentProcess(), result, &modinfo, sizeof(MODULEINFO)) ) {
|
||||
if ( !patch_wua(modinfo.lpBaseOfDll, modinfo.SizeOfImage) )
|
||||
trace(L"Failed to patch %ls!", fname);
|
||||
} else trace(L"Failed to get module information for %ls (%p) (couldn't patch)", fname, result);
|
||||
} else trace(L"Unsupported version of %ls: %d.%d.%d.%d (patching skipped)", fname, wMajor, wMinor, wBuild, wRevision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pBlock);
|
||||
}
|
||||
return result;
|
||||
rtl_free(pBlock);
|
||||
L_ret:
|
||||
return result;
|
||||
}
|
||||
|
@@ -1,23 +1,15 @@
|
||||
#ifndef HOOKS_H_INCLUDED
|
||||
#define HOOKS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#include <phnt_windows.h>
|
||||
|
||||
typedef struct tagLANGANDCODEPAGE {
|
||||
WORD wLanguage;
|
||||
WORD wCodePage;
|
||||
typedef struct tagLANGANDCODEPAGE
|
||||
{
|
||||
WORD wLanguage;
|
||||
WORD wCodePage;
|
||||
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
||||
|
||||
typedef LRESULT(WINAPI *REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
||||
typedef HMODULE(WINAPI *LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
|
||||
typedef LSTATUS(WINAPI *LPFN_REGQUERYVALUEEXW)(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
||||
typedef HMODULE(WINAPI *LPFN_LOADLIBRARYEXW)(LPCWSTR, HANDLE, DWORD);
|
||||
|
||||
extern REGQUERYVALUEEXW pfnRegQueryValueExW;
|
||||
extern LOADLIBRARYEXW pfnLoadLibraryExW;
|
||||
|
||||
LRESULT 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);
|
||||
|
||||
#endif
|
||||
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,42 +0,0 @@
|
||||
#include "iathook.h"
|
||||
|
||||
#include "tracing.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
static LPVOID *iat_find(HMODULE hModule, LPCSTR lpFunctionName) {
|
||||
uintptr_t hm = (uintptr_t)hModule;
|
||||
|
||||
for ( PIMAGE_IMPORT_DESCRIPTOR iid = (PIMAGE_IMPORT_DESCRIPTOR)(hm + ((PIMAGE_NT_HEADERS)(hm + ((PIMAGE_DOS_HEADER)hm)->e_lfanew))
|
||||
->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); iid->Name; iid++ ) {
|
||||
|
||||
LPVOID *pp;
|
||||
for ( size_t i = 0; *(pp = i + (LPVOID *)(hm + iid->FirstThunk)); i++ ) {
|
||||
LPSTR fn = (LPSTR)(hm + *(i + (PSIZE_T)(hm + iid->OriginalFirstThunk)) + 2);
|
||||
if ( !((uintptr_t)fn & IMAGE_ORDINAL_FLAG) && !_stricmp((const char *)lpFunctionName, (char *)fn) )
|
||||
return pp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void iat_hook(HMODULE hModule, LPCSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress) {
|
||||
LPVOID *lpAddress = iat_find(hModule, lpFuncName);
|
||||
if ( !lpAddress || *lpAddress == lpNewAddress )
|
||||
return;
|
||||
|
||||
if ( !hModule )
|
||||
hModule = GetModuleHandle(NULL);
|
||||
|
||||
trace(_T("Modified IAT: hModule=%p, Name=%hs, OldAddress=%p, NewAddress=%p"), hModule, lpFuncName, *lpAddress, lpNewAddress);
|
||||
|
||||
DWORD flOldProtect;
|
||||
if ( VirtualProtect(lpAddress, sizeof(LPVOID), PAGE_READWRITE, &flOldProtect) ) {
|
||||
if ( lpOldAddress )
|
||||
*lpOldAddress = *lpAddress;
|
||||
*lpAddress = lpNewAddress;
|
||||
if ( !VirtualProtect(lpAddress, sizeof(LPVOID), flOldProtect, &flOldProtect) )
|
||||
trace(_T("Failed to restore memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError());
|
||||
} else trace(_T("Failed to change memory region permissions at %p (error code=%08x)"), lpAddress, GetLastError());
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#ifndef IATHOOK_H_INCLUDED
|
||||
#define IATHOOK_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
void iat_hook(HMODULE hModule, LPCSTR lpFuncName, LPVOID *lpOldAddress, LPVOID lpNewAddress);
|
||||
#endif
|
20
wufuc/ntcstr.h
Normal file
20
wufuc/ntcstr.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <phnt_windows.h>
|
||||
|
||||
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
|
||||
#define _max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define _min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define _MAX_PATH 260 // max. length of full pathname
|
||||
#define _MAX_DRIVE 3 // max. length of drive component
|
||||
#define _MAX_DIR 256 // max. length of path component
|
||||
#define _MAX_FNAME 256 // max. length of file name component
|
||||
#define _MAX_EXT 256 // max. length of extension component
|
||||
|
||||
typedef int(__cdecl *LPFN__WCSICMP_NTDLL)(const wchar_t *string1, const wchar_t *string2);
|
||||
|
||||
int _wcsicmp_Ntdll(
|
||||
const wchar_t *string1,
|
||||
const wchar_t *string2
|
||||
);
|
@@ -1,31 +0,0 @@
|
||||
#include "ntdllhelper.h"
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <winternl.h>
|
||||
#include <tchar.h>
|
||||
|
||||
static HMODULE g_hNTDLL = NULL;
|
||||
|
||||
static BOOL InitNTDLL(void) {
|
||||
if ( !g_hNTDLL )
|
||||
g_hNTDLL = GetModuleHandle(_T("ntdll"));
|
||||
return !!g_hNTDLL;
|
||||
}
|
||||
|
||||
BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status) {
|
||||
static NTQUERYKEY pfnNtQueryKey = NULL;
|
||||
|
||||
if ( InitNTDLL() ) {
|
||||
if ( !pfnNtQueryKey )
|
||||
pfnNtQueryKey = (NTQUERYKEY)GetProcAddress(g_hNTDLL, "NtQueryKey");
|
||||
|
||||
if ( pfnNtQueryKey ) {
|
||||
*status = pfnNtQueryKey(KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
#ifndef NTDLLHELPER_H_INCLUDED
|
||||
#define NTDLLHELPER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
typedef enum tagKEY_INFORMATION_CLASS {
|
||||
KeyBasicInformation = 0,
|
||||
KeyNodeInformation = 1,
|
||||
KeyFullInformation = 2,
|
||||
KeyNameInformation = 3,
|
||||
KeyCachedInformation = 4,
|
||||
KeyFlagsInformation = 5,
|
||||
KeyVirtualizationInformation = 6,
|
||||
KeyHandleTagsInformation = 7,
|
||||
MaxKeyInfoClass = 8
|
||||
} KEY_INFORMATION_CLASS;
|
||||
|
||||
typedef struct tagKEY_NAME_INFORMATION {
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1];
|
||||
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
|
||||
|
||||
typedef NTSTATUS(NTAPI *NTQUERYKEY)(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
|
||||
BOOL TryNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength, PNTSTATUS status);
|
||||
#endif
|
119
wufuc/patchwua.c
119
wufuc/patchwua.c
@@ -4,67 +4,70 @@
|
||||
#include "patternfind.h"
|
||||
#include "tracing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <Psapi.h>
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
BOOL PatchWUA(void *lpBaseOfDll, size_t SizeOfImage) {
|
||||
char *pattern;
|
||||
size_t offset1, offset2;
|
||||
#ifdef _AMD64_
|
||||
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
|
||||
offset1 = 10;
|
||||
offset2 = 18;
|
||||
#elif defined(_X86_)
|
||||
if ( IsWindows7() ) {
|
||||
pattern = "833D????????00 743E E8???????? A3????????";
|
||||
offset1 = 2;
|
||||
offset2 = 15;
|
||||
} else if ( IsWindows8Point1() ) {
|
||||
pattern = "8BFF 51 833D????????00 7507 A1????????";
|
||||
offset1 = 5;
|
||||
offset2 = 13;
|
||||
}
|
||||
bool patch_wua(void *lpBaseOfDll, size_t SizeOfImage)
|
||||
{
|
||||
char *pattern;
|
||||
size_t offset1, offset2;
|
||||
#ifdef _M_AMD64
|
||||
pattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????";
|
||||
offset1 = 10;
|
||||
offset2 = 18;
|
||||
#elif defined(_M_IX86)
|
||||
if ( IsWindows7() ) {
|
||||
pattern = "833D????????00 743E E8???????? A3????????";
|
||||
offset1 = 2;
|
||||
offset2 = 15;
|
||||
} else if ( IsWindows8Point1() ) {
|
||||
pattern = "8BFF 51 833D????????00 7507 A1????????";
|
||||
offset1 = 5;
|
||||
offset2 = 13;
|
||||
}
|
||||
#endif
|
||||
unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, pattern);
|
||||
if ( !ptr ) {
|
||||
trace(L"No pattern match! (couldn't patch)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wchar_t path[MAX_PATH];
|
||||
GetModuleFileName((HMODULE)lpBaseOfDll, path, _countof(path));
|
||||
wchar_t *fname = find_fname(path);
|
||||
trace(L"Matched pattern at %ls!%p",
|
||||
fname,
|
||||
ptr);
|
||||
LPBOOL lpb1, lpb2;
|
||||
#ifdef _M_AMD64
|
||||
lpb1 = (LPBOOL)(ptr + offset1 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset1));
|
||||
lpb2 = (LPBOOL)(ptr + offset2 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset2));
|
||||
#elif defined(_M_IX86)
|
||||
lpb1 = (LPBOOL)(*(uintptr_t *)(ptr + offset1));
|
||||
lpb2 = (LPBOOL)(*(uintptr_t *)(ptr + offset2));
|
||||
#endif
|
||||
|
||||
unsigned char *ptr = patternfind(lpBaseOfDll, SizeOfImage, 0, pattern);
|
||||
if ( !ptr ) {
|
||||
trace(_T("No pattern match! (couldn't patch)"));
|
||||
return FALSE;
|
||||
}
|
||||
TCHAR fname[MAX_PATH];
|
||||
GetModuleBaseName(GetCurrentProcess(), (HMODULE)lpBaseOfDll, fname, _countof(fname));
|
||||
trace(_T("Matched pattern for IsDeviceServiceable at %s+0x%zx"), fname,
|
||||
(size_t)((uintptr_t)ptr - (uintptr_t)lpBaseOfDll));
|
||||
LPBOOL lpb1, lpb2;
|
||||
#ifdef _AMD64_
|
||||
lpb1 = (LPBOOL)(ptr + offset1 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset1));
|
||||
lpb2 = (LPBOOL)(ptr + offset2 + sizeof(uint32_t) + *(uint32_t *)(ptr + offset2));
|
||||
#elif defined(_X86_)
|
||||
lpb1 = (LPBOOL)(*(uintptr_t *)(ptr + offset1));
|
||||
lpb2 = (LPBOOL)(*(uintptr_t *)(ptr + offset2));
|
||||
#endif
|
||||
offset1 = (size_t)((uintptr_t)lpb1 - (uintptr_t)lpBaseOfDll);
|
||||
offset2 = (size_t)((uintptr_t)lpb2 - (uintptr_t)lpBaseOfDll);
|
||||
|
||||
DWORD flOldProtect;
|
||||
if ( *lpb1 ) {
|
||||
if ( VirtualProtect(lpb1, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||
*lpb1 = FALSE;
|
||||
trace(_T("Patched value #1 at %s+0x%zx: %08x"), fname, offset1, *lpb1);
|
||||
if ( !VirtualProtect(lpb1, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||
trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError());
|
||||
} else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset1, GetLastError());
|
||||
}
|
||||
if ( !*lpb2 ) {
|
||||
if ( VirtualProtect(lpb2, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||
*lpb2 = TRUE;
|
||||
trace(_T("Patched value #2 at %s+0x%zx: %08x"), fname, offset2, *lpb2);
|
||||
if ( !VirtualProtect(lpb2, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||
trace(_T("Failed to restore memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError());
|
||||
} else trace(_T("Failed to change memory region permissions at %s+0x%zx (error code=%08x)"), fname, offset2, GetLastError());
|
||||
}
|
||||
return !*lpb1 && *lpb2;
|
||||
DWORD flOldProtect;
|
||||
if ( *lpb1 == TRUE ) {
|
||||
if ( VirtualProtect(lpb1, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||
*lpb1 = FALSE;
|
||||
trace(L"Patched value #1 at %ls!%p: %08X", fname, lpb1, *lpb1);
|
||||
if ( !VirtualProtect(lpb1, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||
trace(L"Failed to restore memory region permissions at %ls!%p (error code=%08X)", fname, lpb1, GetLastError());
|
||||
} else trace(L"Failed to change memory region permissions at %ls!%p (error code=%08X)", fname, lpb1, GetLastError());
|
||||
}
|
||||
if ( *lpb2 == FALSE ) {
|
||||
if ( VirtualProtect(lpb2, sizeof(BOOL), PAGE_READWRITE, &flOldProtect) ) {
|
||||
*lpb2 = TRUE;
|
||||
trace(L"Patched value #2 at %ls!%p: %08X", fname, lpb2, *lpb2);
|
||||
if ( !VirtualProtect(lpb2, sizeof(BOOL), flOldProtect, &flOldProtect) )
|
||||
trace(L"Failed to restore memory region permissions at %ls!%p: (error code=%08X)", fname, lpb2, GetLastError());
|
||||
} else trace(L"Failed to change memory region permissions at %ls!%p (error code=%08X)", fname, lpb2, GetLastError());
|
||||
}
|
||||
return !*lpb1 && *lpb2;
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,7 @@
|
||||
#ifndef PATCHWUA_H_INCLUDED
|
||||
#define PATCHWUA_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
BOOL PatchWUA(void *lpBaseOfDll, size_t SizeOfImage);
|
||||
#endif
|
||||
#include <phnt_windows.h>
|
||||
|
||||
bool patch_wua(void *lpBaseOfDll, size_t SizeOfImage);
|
||||
|
@@ -1,133 +1,179 @@
|
||||
#include "patternfind.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include "rtl_malloc.h"
|
||||
|
||||
/* Ported to Win32 C from x64dbg's patternfind.cpp:
|
||||
* https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp
|
||||
*
|
||||
* x64dbg license (GPL-3.0):
|
||||
* https://github.com/x64dbg/x64dbg/blob/development/LICENSE
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
static int hexchtoint(char c) {
|
||||
int result = -1;
|
||||
if ( c >= '0' && c <= '9' )
|
||||
result = c - '0';
|
||||
else if ( c >= 'A' && c <= 'F' )
|
||||
result = c - 'A' + 10;
|
||||
else if ( c >= 'a' && c <= 'f' )
|
||||
result = c - 'a' + 10;
|
||||
|
||||
return result;
|
||||
static inline bool isHex(char ch)
|
||||
{
|
||||
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
|
||||
}
|
||||
|
||||
static size_t formathexpattern(const char *patterntext, char *formattext, size_t formattextsize) {
|
||||
size_t len = strlen(patterntext);
|
||||
size_t result = 0;
|
||||
for ( size_t i = 0; i < len && (!formattext || result < formattextsize); i++ ) {
|
||||
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
|
||||
if ( formattext )
|
||||
formattext[result] = patterntext[i];
|
||||
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
static inline int hexchtoint(char ch)
|
||||
{
|
||||
if ( ch >= '0' && ch <= '9' )
|
||||
return ch - '0';
|
||||
else if ( ch >= 'A' && ch <= 'F' )
|
||||
return ch - 'A' + 10;
|
||||
else if ( ch >= 'a' && ch <= 'f' )
|
||||
return ch - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static BOOL patterntransform(const char *patterntext, PPATTERNBYTE pattern, size_t *patternsize) {
|
||||
size_t cb = formathexpattern(patterntext, NULL, 0);
|
||||
if ( !cb || cb > *patternsize )
|
||||
return FALSE;
|
||||
static inline size_t formathexpattern(const char *patterntext, char *formattext, size_t formattextsize)
|
||||
{
|
||||
size_t len = strlen(patterntext);
|
||||
size_t result = 0;
|
||||
for ( size_t i = 0; i < len; i++ ) {
|
||||
if ( patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1 ) {
|
||||
if ( formattext && result + 1 < formattextsize )
|
||||
formattext[result] = patterntext[i];
|
||||
|
||||
char *formattext = calloc(cb, sizeof(char));
|
||||
cb = formathexpattern(patterntext, formattext, cb);
|
||||
|
||||
if ( cb % 2 )
|
||||
formattext[cb++] = '?';
|
||||
|
||||
formattext[cb] = '\0';
|
||||
|
||||
for ( size_t i = 0, j = 0, k = 0; i < cb; i++, j ^= 1, k = (i - j) >> 1 ) {
|
||||
if ( formattext[i] == '?' )
|
||||
pattern[k].nibble[j].wildcard = TRUE;
|
||||
else {
|
||||
pattern[k].nibble[j].wildcard = FALSE;
|
||||
pattern[k].nibble[j].data = hexchtoint(formattext[i]) & 0xf;
|
||||
}
|
||||
}
|
||||
free(formattext);
|
||||
*patternsize = cb >> 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void patternwritebyte(unsigned char *byte, PPATTERNBYTE pbyte) {
|
||||
unsigned char n1 = (*byte >> 4) & 0xf;
|
||||
unsigned char n2 = *byte & 0xf;
|
||||
if ( !pbyte->nibble[0].wildcard )
|
||||
n1 = pbyte->nibble[0].data;
|
||||
|
||||
if ( !pbyte->nibble[1].wildcard )
|
||||
n2 = pbyte->nibble[1].data;
|
||||
*byte = ((n1 << 4) & 0xf0) | (n2 & 0xf);
|
||||
}
|
||||
|
||||
static BOOL patternwrite(unsigned char *data, size_t datasize, const char *pattern) {
|
||||
size_t writepatternsize = strlen(pattern);
|
||||
if ( writepatternsize > datasize )
|
||||
writepatternsize = datasize;
|
||||
|
||||
BOOL result = FALSE;
|
||||
PPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE));
|
||||
if ( patterntransform(pattern, writepattern, &writepatternsize) ) {
|
||||
DWORD flOldProtect;
|
||||
if ( result = VirtualProtect(data, writepatternsize, PAGE_READWRITE, &flOldProtect) ) {
|
||||
for ( size_t i = 0; i < writepatternsize; i++ ) {
|
||||
BYTE n1 = (data[i] >> 4) & 0xf;
|
||||
BYTE n2 = data[i] & 0xf;
|
||||
if ( !writepattern[i].nibble[0].wildcard )
|
||||
n1 = writepattern[i].nibble[0].data;
|
||||
|
||||
if ( !writepattern[i].nibble[1].wildcard )
|
||||
n2 = writepattern[i].nibble[1].data;
|
||||
data[i] = ((n1 << 4) & 0xf0) | (n2 & 0xf);
|
||||
result = VirtualProtect(data, writepatternsize, flOldProtect, &flOldProtect);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(writepattern);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern) {
|
||||
unsigned char *result = NULL;
|
||||
size_t searchpatternsize = strlen(pattern);
|
||||
PPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE));
|
||||
|
||||
if ( patterntransform(pattern, searchpattern, &searchpatternsize) ) {
|
||||
for ( size_t i = startindex, j = 0; i < datasize; i++ ) { //search for the pattern
|
||||
if ( (searchpattern[j].nibble[0].wildcard || searchpattern[j].nibble[0].data == ((data[i] >> 4) & 0xf))
|
||||
&& (searchpattern[j].nibble[1].wildcard || searchpattern[j].nibble[1].data == (data[i] & 0xf)) ) { //check if our pattern matches the current byte
|
||||
|
||||
if ( ++j == searchpatternsize ) { //everything matched
|
||||
result = data + (i - searchpatternsize + 1);
|
||||
break;
|
||||
result++;
|
||||
}
|
||||
} else if ( j > 0 ) { //fix by Computer_Angel
|
||||
i -= j;
|
||||
j = 0; //reset current pattern position
|
||||
}
|
||||
}
|
||||
}
|
||||
free(searchpattern);
|
||||
return result;
|
||||
}
|
||||
if ( result % 2 ) { //not a multiple of 2
|
||||
if ( formattext && result + 1 < formattextsize )
|
||||
formattext[result] = '?';
|
||||
|
||||
unsigned char *patternsnr(unsigned char *data, size_t datasize, size_t startindex, const char *searchpattern, const char *replacepattern) {
|
||||
unsigned char *result = patternfind(data, datasize, startindex, searchpattern);
|
||||
if ( !result )
|
||||
result++;
|
||||
}
|
||||
if ( formattext ) {
|
||||
if ( result <= formattextsize )
|
||||
formattext[result] = '\0';
|
||||
else
|
||||
formattext[0] = '\0';
|
||||
}
|
||||
return result;
|
||||
|
||||
patternwrite(result, datasize, replacepattern);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool patterntransform(const char *patterntext, PatternByte *pattern, size_t patternsize)
|
||||
{
|
||||
memset(pattern, 0, patternsize * sizeof(PatternByte));
|
||||
size_t len = formathexpattern(patterntext, NULL, 0);
|
||||
|
||||
if ( !len || len / 2 > patternsize )
|
||||
return false;
|
||||
|
||||
size_t size = len + 1;
|
||||
char *formattext = rtl_malloc(size);
|
||||
formathexpattern(patterntext, formattext, size);
|
||||
PatternByte newByte;
|
||||
|
||||
for ( int i = 0, j = 0, k = 0; i < len && k <= patternsize; i++ ) {
|
||||
if ( formattext[i] == '?' ) { //wildcard
|
||||
newByte.nibble[j].wildcard = true; //match anything
|
||||
} else { //hex
|
||||
newByte.nibble[j].wildcard = false;
|
||||
newByte.nibble[j].data = hexchtoint(formattext[i]) & 0xF;
|
||||
}
|
||||
|
||||
j++;
|
||||
if ( j == 2 ) { //two nibbles = one byte
|
||||
j = 0;
|
||||
pattern[k++] = newByte;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool patternmatchbyte(unsigned char byte, const PatternByte pbyte)
|
||||
{
|
||||
int matched = 0;
|
||||
|
||||
unsigned char n1 = (byte >> 4) & 0xF;
|
||||
if ( pbyte.nibble[0].wildcard )
|
||||
matched++;
|
||||
else if ( pbyte.nibble[0].data == n1 )
|
||||
matched++;
|
||||
|
||||
unsigned char n2 = byte & 0xF;
|
||||
if ( pbyte.nibble[1].wildcard )
|
||||
matched++;
|
||||
else if ( pbyte.nibble[1].data == n2 )
|
||||
matched++;
|
||||
|
||||
return (matched == 2);
|
||||
}
|
||||
|
||||
unsigned char *patternfind(unsigned char *data, size_t datasize, const char *pattern)
|
||||
{
|
||||
size_t searchpatternsize = formathexpattern(pattern, NULL, 0) / 2;
|
||||
PatternByte *searchpattern = rtl_calloc(searchpatternsize, sizeof(PatternByte));
|
||||
|
||||
unsigned char *result = NULL;
|
||||
if ( patterntransform(pattern, searchpattern, searchpatternsize) )
|
||||
result = patternfind3(data, datasize, searchpattern, searchpatternsize);
|
||||
|
||||
rtl_free(searchpattern);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char *patternfind2(unsigned char *data, size_t datasize, unsigned char *pattern, size_t patternsize)
|
||||
{
|
||||
if ( patternsize > datasize )
|
||||
patternsize = datasize;
|
||||
for ( size_t i = 0, pos = 0; i < datasize; i++ ) {
|
||||
if ( data[i] == pattern[pos] ) {
|
||||
pos++;
|
||||
if ( pos == patternsize )
|
||||
return &data[i - patternsize + 1];
|
||||
} else if ( pos > 0 ) {
|
||||
i -= pos;
|
||||
pos = 0; //reset current pattern position
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void patternwritebyte(unsigned char *byte, const PatternByte pbyte)
|
||||
{
|
||||
unsigned char n1 = (*byte >> 4) & 0xF;
|
||||
unsigned char n2 = *byte & 0xF;
|
||||
if ( !pbyte.nibble[0].wildcard )
|
||||
n1 = pbyte.nibble[0].data;
|
||||
if ( !pbyte.nibble[1].wildcard )
|
||||
n2 = pbyte.nibble[1].data;
|
||||
*byte = ((n1 << 4) & 0xF0) | (n2 & 0xF);
|
||||
}
|
||||
|
||||
void patternwrite(unsigned char *data, size_t datasize, const char *pattern)
|
||||
{
|
||||
size_t writepatternsize = formathexpattern(pattern, NULL, 0) / 2;
|
||||
PatternByte *writepattern = rtl_calloc(writepatternsize, sizeof(PatternByte));
|
||||
|
||||
if ( patterntransform(pattern, writepattern, writepatternsize) ) {
|
||||
if ( writepatternsize > datasize )
|
||||
writepatternsize = datasize;
|
||||
for ( size_t i = 0; i < writepatternsize; i++ )
|
||||
patternwritebyte(&data[i], writepattern[i]);
|
||||
}
|
||||
|
||||
rtl_free(writepattern);
|
||||
}
|
||||
|
||||
bool patternsnr(unsigned char *data, size_t datasize, const char *searchpattern, const char *replacepattern)
|
||||
{
|
||||
unsigned char *found = patternfind(data, datasize, searchpattern);
|
||||
if ( !found )
|
||||
return false;
|
||||
patternwrite(found, datasize - (found - data), replacepattern);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char *patternfind3(unsigned char *data, size_t datasize, const PatternByte *pattern, size_t searchpatternsize)
|
||||
{
|
||||
for ( size_t i = 0, pos = 0; i < datasize; i++ ) { //search for the pattern
|
||||
if ( patternmatchbyte(data[i], pattern[pos]) ) { //check if our pattern matches the current byte
|
||||
pos++;
|
||||
if ( pos == searchpatternsize ) //everything matched
|
||||
return &data[i - searchpatternsize + 1];
|
||||
} else if ( pos > 0 ) { //fix by Computer_Angel
|
||||
i -= pos;
|
||||
pos = 0; //reset current pattern position
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
@@ -1,16 +1,57 @@
|
||||
#ifndef PATTERNFIND_H_INCLUDED
|
||||
#define PATTERNFIND_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct tagPATTERNBYTE {
|
||||
struct tagPATTERNNIBBLE {
|
||||
unsigned char data;
|
||||
BOOL wildcard;
|
||||
} nibble[2];
|
||||
} PATTERNBYTE, *PPATTERNBYTE;
|
||||
typedef struct tagPatternByte
|
||||
{
|
||||
struct PatternNibble
|
||||
{
|
||||
unsigned char data;
|
||||
bool wildcard;
|
||||
} nibble[2];
|
||||
} PatternByte;
|
||||
|
||||
unsigned char *patternfind(unsigned char *data, size_t datasize, size_t startindex, const char *pattern);
|
||||
unsigned char *patternsnr(unsigned char *data, size_t datasize, size_t startindex, const char *searchpattern, const char *replacepattern);
|
||||
#endif
|
||||
//returns: pointer to data when found, NULL when not found
|
||||
unsigned char *patternfind(
|
||||
unsigned char *data, //data
|
||||
size_t datasize, //size of data
|
||||
const char *pattern //pattern to search
|
||||
);
|
||||
|
||||
//returns: pointer to data when found, NULL when not found
|
||||
unsigned char *patternfind2(
|
||||
unsigned char *data, //data
|
||||
size_t datasize, //size of data
|
||||
unsigned char *pattern, //bytes to search
|
||||
size_t patternsize //size of bytes to search
|
||||
);
|
||||
|
||||
//returns: nothing
|
||||
void patternwrite(
|
||||
unsigned char *data, //data
|
||||
size_t datasize, //size of data
|
||||
const char *pattern //pattern to write
|
||||
);
|
||||
|
||||
//returns: true on success, false on failure
|
||||
bool patternsnr(
|
||||
unsigned char *data, //data
|
||||
size_t datasize, //size of data
|
||||
const char *searchpattern, //pattern to search
|
||||
const char *replacepattern //pattern to write
|
||||
);
|
||||
|
||||
//returns: true on success, false on failure
|
||||
bool patterntransform(
|
||||
const char *patterntext, //pattern string
|
||||
PatternByte *pattern, //pattern to feed to patternfind
|
||||
size_t patternsize //size of pattern
|
||||
);
|
||||
|
||||
//returns: pointer to data when found, NULL when not found
|
||||
unsigned char *patternfind3(
|
||||
unsigned char *data, //data
|
||||
size_t datasize, //size of data
|
||||
const PatternByte *pattern, //pattern to search
|
||||
size_t searchpatternsize //size of pattern to search
|
||||
);
|
||||
|
70
wufuc/rtl_malloc.c
Normal file
70
wufuc/rtl_malloc.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "rtl_malloc.h"
|
||||
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
void *rtl_malloc(size_t size)
|
||||
{
|
||||
return RtlAllocateHeap(RtlProcessHeap(), 0, size);
|
||||
}
|
||||
|
||||
void rtl_free(void *memblock)
|
||||
{
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, memblock);
|
||||
}
|
||||
|
||||
void *rtl_calloc(size_t num, size_t size)
|
||||
{
|
||||
return RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, num * size);
|
||||
}
|
||||
|
||||
void *rtl_realloc(void *memblock, size_t size)
|
||||
{
|
||||
if ( !memblock )
|
||||
return rtl_malloc(size);
|
||||
|
||||
if ( !size ) {
|
||||
rtl_free(memblock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RtlReAllocateHeap(RtlProcessHeap(), 0, memblock, size);
|
||||
}
|
||||
|
||||
void *_rtl_recalloc(void *memblock, size_t num, size_t size)
|
||||
{
|
||||
if ( !memblock )
|
||||
return rtl_calloc(num, size);
|
||||
|
||||
if ( !num || !size ) {
|
||||
rtl_free(memblock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RtlReAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, memblock, num * size);
|
||||
}
|
||||
|
||||
|
||||
void *_rtl_expand(void *memblock, size_t size)
|
||||
{
|
||||
return RtlReAllocateHeap(RtlProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, memblock, size);
|
||||
}
|
||||
|
||||
size_t _rtl_msize(void *memblock)
|
||||
{
|
||||
return RtlSizeHeap(RtlProcessHeap(), 0, memblock);
|
||||
}
|
||||
|
||||
int _rtl_heapchk(void)
|
||||
{
|
||||
if ( !RtlValidateHeap(RtlProcessHeap(), 0, NULL) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _rtl_heapmin(void)
|
||||
{
|
||||
if ( !RtlCompactHeap(RtlProcessHeap(), 0) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
19
wufuc/rtl_malloc.h
Normal file
19
wufuc/rtl_malloc.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
void *rtl_malloc(size_t size);
|
||||
|
||||
void rtl_free(void *memblock);
|
||||
|
||||
void *rtl_calloc(size_t num, size_t size);
|
||||
|
||||
void *rtl_realloc(void *memblock, size_t size);
|
||||
|
||||
void *_rtl_recalloc(void *memblock, size_t num, size_t size);
|
||||
|
||||
void *_rtl_expand(void *memblock, size_t size);
|
||||
|
||||
size_t _rtl_msize(void *memblock);
|
||||
|
||||
int _rtl_heapchk(void);
|
||||
|
||||
int _rtl_heapmin(void);
|
@@ -1,14 +0,0 @@
|
||||
#include "service.h"
|
||||
#include "tracing.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
void CALLBACK Rundll32Unload(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
||||
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("Global\\wufuc_UnloadEvent"));
|
||||
if ( hEvent ) {
|
||||
trace(_T("Setting unload event..."));
|
||||
SetEvent(hEvent);
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
#include "service.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpCommandLine, SIZE_T dwSize) {
|
||||
BOOL result = FALSE;
|
||||
if ( !hSCManager && !(hSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) )
|
||||
return result;
|
||||
|
||||
HANDLE hService = OpenService(hSCManager, lpServiceName, SERVICE_QUERY_CONFIG);
|
||||
if ( !hService )
|
||||
return result;
|
||||
|
||||
DWORD cbBytesNeeded;
|
||||
if ( !QueryServiceConfig(hService, NULL, 0, &cbBytesNeeded)
|
||||
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
|
||||
|
||||
LPQUERY_SERVICE_CONFIG sc = malloc(cbBytesNeeded);
|
||||
if ( QueryServiceConfig(hService, sc, cbBytesNeeded, &cbBytesNeeded)
|
||||
&& !_tcscpy_s(lpCommandLine, dwSize, sc->lpBinaryPathName) )
|
||||
result = TRUE;
|
||||
free(sc);
|
||||
}
|
||||
CloseServiceHandle(hService);
|
||||
return result;
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#ifndef SERVICE_H_INCLUDED
|
||||
#define SERVICE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
BOOL GetServiceCommandLine(SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPTSTR lpBinaryPathName, SIZE_T dwSize);
|
||||
#endif
|
35
wufuc/shimlib.c
Normal file
35
wufuc/shimlib.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "shimlib.h"
|
||||
#include "hooks.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
PHOOKAPI g_pHookApiArray;
|
||||
|
||||
PHOOKAPI WINAPI GetHookAPIs(LPCSTR szCommandLine, LPCWSTR wszShimName, PDWORD pdwHookCount) {
|
||||
g_pHookApiArray = calloc(2, sizeof(HOOKAPI));
|
||||
|
||||
if ( g_pHookApiArray ) {
|
||||
g_pHookApiArray[0].LibraryName = "advapi32.dll";
|
||||
g_pHookApiArray[0].FunctionName = "RegQueryValueExW";
|
||||
g_pHookApiArray[0].ReplacementFunction = RegQueryValueExW_hook;
|
||||
g_pHookApiArray[1].LibraryName = "kernel32.dll";
|
||||
g_pHookApiArray[1].FunctionName = "LoadLibraryExW";
|
||||
g_pHookApiArray[1].ReplacementFunction = LoadLibraryExW_hook;
|
||||
*pdwHookCount = 2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL WINAPI NotifyShims(DWORD fdwReason, PLDR_DATA_TABLE_ENTRY pLdrEntry) {
|
||||
switch ( fdwReason ) {
|
||||
case SHIM_NOTIFY_ATTACH:
|
||||
break;
|
||||
case SHIM_NOTIFY_DETACH:
|
||||
break;
|
||||
case SHIM_NOTIFY_DLL_LOAD:
|
||||
break;
|
||||
case SHIM_NOTIFY_DLL_UNLOAD:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
33
wufuc/shimlib.h
Normal file
33
wufuc/shimlib.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SHIM_H
|
||||
#define SHIM_H
|
||||
#pragma once
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
typedef struct tagHOOKAPI {
|
||||
PCSTR LibraryName;
|
||||
PCSTR FunctionName;
|
||||
PVOID ReplacementFunction;
|
||||
PVOID OriginalFunction;
|
||||
PVOID Reserved[2];
|
||||
} HOOKAPI, *PHOOKAPI;
|
||||
|
||||
#define SHIM_REASON_INIT 100
|
||||
#define SHIM_REASON_DEINIT 101
|
||||
#define SHIM_REASON_DLL_LOAD 102 /* Arg: PLDR_DATA_TABLE_ENTRY */
|
||||
#define SHIM_REASON_DLL_UNLOAD 103 /* Arg: PLDR_DATA_TABLE_ENTRY */
|
||||
|
||||
#define SHIM_NOTIFY_ATTACH 1
|
||||
#define SHIM_NOTIFY_DETACH 2
|
||||
#define SHIM_NOTIFY_DLL_LOAD 3 /* Arg: PLDR_DATA_TABLE_ENTRY */
|
||||
#define SHIM_NOTIFY_DLL_UNLOAD 4 /* Arg: PLDR_DATA_TABLE_ENTRY */
|
||||
|
||||
extern PHOOKAPI g_pHookApiArray;
|
||||
|
||||
PHOOKAPI WINAPI GetHookAPIs(LPCSTR szCommandLine, LPCWSTR wszShimName, PDWORD pdwHookCount);
|
||||
BOOL WINAPI NotifyShims(DWORD fdwReason, PLDR_DATA_TABLE_ENTRY pLdrEntry);
|
||||
#endif
|
117
wufuc/tracing.c
117
wufuc/tracing.c
@@ -1,72 +1,63 @@
|
||||
#include "tracing.h"
|
||||
|
||||
#include "helpers.h"
|
||||
#include "rtl_malloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
|
||||
static FILE *m_pStream;
|
||||
static HANDLE m_hMutex;
|
||||
static BOOL m_bDeinitializing;
|
||||
|
||||
BOOL InitTracing(void) {
|
||||
if ( m_bDeinitializing )
|
||||
return FALSE;
|
||||
|
||||
if ( !m_hMutex )
|
||||
m_hMutex = CreateMutex(NULL, FALSE, _T("Global\\wufuc_TracingMutex"));
|
||||
|
||||
if ( m_hMutex && !m_pStream ) {
|
||||
TCHAR path[MAX_PATH];
|
||||
GetModuleFileName(HINST_THISCOMPONENT, path, _countof(path));
|
||||
|
||||
TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME];
|
||||
_tsplitpath_s(path, drive, _countof(drive), dir, _countof(dir), fname, _countof(fname), NULL, 0);
|
||||
_tmakepath_s(path, _countof(path), drive, dir, fname, _T(".log"));
|
||||
|
||||
m_pStream = _tfsopen(path, _T("at"), _SH_DENYNO);
|
||||
}
|
||||
return m_pStream && m_hMutex;
|
||||
}
|
||||
|
||||
DWORD WaitForTracingMutex(void) {
|
||||
return WaitForSingleObject(m_hMutex, INFINITE);
|
||||
}
|
||||
|
||||
BOOL ReleaseTracingMutex(void) {
|
||||
return ReleaseMutex(m_hMutex);
|
||||
}
|
||||
|
||||
void trace_(LPCTSTR format, ...) {
|
||||
if ( InitTracing() ) {
|
||||
TCHAR datebuf[9], timebuf[9];
|
||||
_tstrdate_s(datebuf, _countof(datebuf));
|
||||
_tstrtime_s(timebuf, _countof(timebuf));
|
||||
if ( !WaitForTracingMutex() ) {
|
||||
_ftprintf_s(m_pStream, _T("%s %s [PID: %d TID: %d] "), datebuf, timebuf, GetCurrentProcessId(), GetCurrentThreadId());
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
_vftprintf_s(m_pStream, format, argptr);
|
||||
va_end(argptr);
|
||||
fflush(m_pStream);
|
||||
void trace_sysinfo(void)
|
||||
{
|
||||
RTL_OSVERSIONINFOW osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
|
||||
NTSTATUS status = RtlGetVersion(&osvi);
|
||||
if ( NT_SUCCESS(status) ) {
|
||||
trace(L"Windows version: %d.%d.%d (%Iu-bit)",
|
||||
osvi.dwMajorVersion,
|
||||
osvi.dwMinorVersion,
|
||||
osvi.dwBuildNumber,
|
||||
sizeof(uintptr_t) * 8);
|
||||
} else trace(L"Failed to get Windows version (status=%08X)", status);
|
||||
|
||||
int CPUInfo[4];
|
||||
__cpuidex(CPUInfo, 0x80000000, 0);
|
||||
if ( CPUInfo[0] < 0x80000004 ) {
|
||||
trace(L"This processor does not support the brand identification feature.");
|
||||
return;
|
||||
}
|
||||
ReleaseTracingMutex();
|
||||
}
|
||||
char brand[0x31];
|
||||
uint32_t *u32ptr = (uint32_t *)&brand;
|
||||
for ( int func = 0x80000002; func <= 0x80000004; func++ ) {
|
||||
__cpuidex(CPUInfo, func, 0);
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
*(u32ptr++) = CPUInfo[i];
|
||||
}
|
||||
size_t c = 0;
|
||||
do {
|
||||
if ( !isspace(brand[c]) )
|
||||
break;
|
||||
c++;
|
||||
} while ( c < _countof(brand) );
|
||||
trace(L"Processor: %hs", &brand[c]);
|
||||
}
|
||||
|
||||
BOOL DeinitTracing(void) {
|
||||
m_bDeinitializing = TRUE;
|
||||
|
||||
BOOL result = TRUE;
|
||||
if ( m_hMutex ) {
|
||||
result = CloseHandle(m_hMutex);
|
||||
m_hMutex = NULL;
|
||||
}
|
||||
if ( m_pStream ) {
|
||||
result = result && !fclose(m_pStream);
|
||||
m_pStream = NULL;
|
||||
}
|
||||
return result;
|
||||
void trace_(const wchar_t *const format, ...)
|
||||
{
|
||||
static int shown_sysinfo = 0;
|
||||
if ( !shown_sysinfo ) {
|
||||
shown_sysinfo = 1;
|
||||
trace_sysinfo();
|
||||
}
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
int count = _vscwprintf(format, argptr) + 1;
|
||||
wchar_t *buffer = rtl_calloc(count, sizeof(wchar_t));
|
||||
vswprintf_s(buffer, count, format, argptr);
|
||||
va_end(argptr);
|
||||
OutputDebugStringW(buffer);
|
||||
rtl_free(buffer);
|
||||
}
|
||||
|
@@ -1,22 +1,14 @@
|
||||
#ifndef LOGGING_H_INCLUDED
|
||||
#define LOGGING_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <phnt_windows.h>
|
||||
|
||||
extern IMAGE_DOS_HEADER __ImageBase;
|
||||
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
||||
#define HMODULE_THISCOMPONENT ((HMODULE)&__ImageBase);
|
||||
|
||||
BOOL InitTracing(void);
|
||||
DWORD WaitForTracingMutex(void);
|
||||
BOOL ReleaseTracingMutex(void);
|
||||
void trace_(LPCTSTR format, ...);
|
||||
BOOL DeinitTracing(void);
|
||||
void trace_(const wchar_t *const format, ...);
|
||||
|
||||
#define STRINGIZE_(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_(x)
|
||||
#define STRINGIZEW_(x) L#x
|
||||
#define STRINGIZEW(x) STRINGIZEW_(x)
|
||||
|
||||
#define LINESTR STRINGIZE(__LINE__)
|
||||
#define trace(format, ...) trace_(_T(__FILE__) _T(":") _T(LINESTR) _T("(") _T(__FUNCTION__) _T("): ") format _T("\n"), ##__VA_ARGS__)
|
||||
#endif
|
||||
#define LINEWSTR STRINGIZEW(__LINE__)
|
||||
#define trace(format, ...) trace_(__FILEW__ L":" LINEWSTR L"(" __FUNCTIONW__ L"): " format L"\n", ##__VA_ARGS__)
|
||||
|
@@ -1,2 +0,0 @@
|
||||
EXPORTS
|
||||
Rundll32Unload
|
BIN
wufuc/wufuc.rc
BIN
wufuc/wufuc.rc
Binary file not shown.
@@ -19,42 +19,32 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="appverifier.h" />
|
||||
<ClInclude Include="callbacks.h" />
|
||||
<ClInclude Include="helpers.h" />
|
||||
<ClInclude Include="hooks.h" />
|
||||
<ClInclude Include="iathook.h" />
|
||||
<ClInclude Include="rtl_malloc.h" />
|
||||
<ClInclude Include="tracing.h" />
|
||||
<ClInclude Include="ntdllhelper.h" />
|
||||
<ClInclude Include="patchwua.h" />
|
||||
<ClInclude Include="patternfind.h" />
|
||||
<ClInclude Include="service.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="callbacks.c" />
|
||||
<ClCompile Include="dllmain.c" />
|
||||
<ClCompile Include="helpers.c" />
|
||||
<ClCompile Include="hooks.c" />
|
||||
<ClCompile Include="iathook.c" />
|
||||
<ClCompile Include="rtl_malloc.c" />
|
||||
<ClCompile Include="tracing.c" />
|
||||
<ClCompile Include="ntdllhelper.c" />
|
||||
<ClCompile Include="patchwua.c" />
|
||||
<ClCompile Include="patternfind.c" />
|
||||
<ClCompile Include="rundll32.c" />
|
||||
<ClCompile Include="service.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="wufuc.def" />
|
||||
<None Include="wufuc.rch">
|
||||
<FileType>Document</FileType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="wufuc.rc">
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="wufuc.rc" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
@@ -114,6 +104,7 @@
|
||||
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IncludePath>$(SolutionDir)phnt\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
@@ -121,6 +112,7 @@
|
||||
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IncludePath>$(SolutionDir)phnt\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@@ -128,6 +120,7 @@
|
||||
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IncludePath>$(SolutionDir)phnt\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
@@ -135,34 +128,53 @@
|
||||
<IntDir>$(ProjectDir)$(BaseIntermediateOutputPath)$(Configuration)\$(PlatformShortName)\</IntDir>
|
||||
<TargetName>$(ProjectName)$(PlatformArchitecture)</TargetName>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IncludePath>$(SolutionDir)phnt\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||
<ModuleDefinitionFile>
|
||||
</ModuleDefinitionFile>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
<AdditionalDependencies>ntdll.lib;ntdllp.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
<PreBuildEvent />
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>ntdll.lib;ntdllp.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>
|
||||
</ModuleDefinitionFile>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
<PreBuildEvent />
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
@@ -170,10 +182,10 @@
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
||||
<PreprocessorDefinitions>BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
@@ -183,13 +195,22 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||
<ModuleDefinitionFile>
|
||||
</ModuleDefinitionFile>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
<AdditionalDependencies>ntdll.lib;ntdllp.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
<PreBuildEvent />
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>X86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@@ -197,10 +218,10 @@
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;WUFUC_EXPORTS;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<ResourceCompile Condition="'$(APPVEYOR)'=='True'">
|
||||
<PreprocessorDefinitions>BUILD_COMMIT_VERSION=$(BUILD_COMMIT_VERSION);BUILD_VERSION_COMMA=$(BUILD_VERSION_COMMA);$(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
@@ -210,13 +231,22 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>wufuc.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>ntdll.lib;ntdllp.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>
|
||||
</ModuleDefinitionFile>
|
||||
<EntryPointSymbol>DllMain</EntryPointSymbol>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
<PreBuildEvent />
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>X64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@@ -15,18 +15,12 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ntdllhelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="patchwua.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="patternfind.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="service.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="callbacks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -36,32 +30,23 @@
|
||||
<ClInclude Include="hooks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="iathook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tracing.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wufuc.rch">
|
||||
<Filter>Resource Files</Filter>
|
||||
<ClInclude Include="appverifier.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtl_malloc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ntdllhelper.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="patchwua.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="patternfind.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rundll32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="service.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="callbacks.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -74,17 +59,15 @@
|
||||
<ClCompile Include="hooks.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="iathook.c">
|
||||
<ClCompile Include="tracing.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tracing.c">
|
||||
<ClCompile Include="rtl_malloc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="wufuc.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="wufuc.rch" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="wufuc.rc">
|
||||
|
Reference in New Issue
Block a user