You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
9.4 KiB
223 lines
9.4 KiB
#pragma once
|
|
#include "kutils.hpp"
|
|
|
|
#define WIN32K_SYSCALL_FILTER_MASK "xxxxxxxxxxxxxxxxxxxxxxx????xxx"
|
|
#define WIN32K_SYSCALL_FILTER_SIG "\x48\x89\x4C\x24\x20\x48\x89\x54\x24\x28\x4C\x89\x44\x24\x30\x4C\x89\x4C\x24\x38\x48\xC7\xC1\x00\x00\x00\x00\x48\xFF\x15"
|
|
static_assert(sizeof WIN32K_SYSCALL_FILTER_SIG == sizeof WIN32K_SYSCALL_FILTER_MASK, "signature and mask len invalid...");
|
|
|
|
typedef union _MISC_THREAD_VALUES
|
|
{
|
|
struct
|
|
{
|
|
ULONG ThreadFlagsSpare : 2; //0x78
|
|
ULONG AutoAlignment : 1; //0x78
|
|
ULONG DisableBoost : 1; //0x78
|
|
ULONG AlertedByThreadId : 1; //0x78
|
|
ULONG QuantumDonation : 1; //0x78
|
|
ULONG EnableStackSwap : 1; //0x78
|
|
ULONG GuiThread : 1; //0x78
|
|
ULONG DisableQuantum : 1; //0x78
|
|
ULONG ChargeOnlySchedulingGroup : 1; //0x78
|
|
ULONG DeferPreemption : 1; //0x78
|
|
ULONG QueueDeferPreemption : 1; //0x78
|
|
ULONG ForceDeferSchedule : 1; //0x78
|
|
ULONG SharedReadyQueueAffinity : 1; //0x78
|
|
ULONG FreezeCount : 1; //0x78
|
|
ULONG TerminationApcRequest : 1; //0x78
|
|
ULONG AutoBoostEntriesExhausted : 1; //0x78
|
|
ULONG KernelStackResident : 1; //0x78
|
|
ULONG TerminateRequestReason : 2; //0x78
|
|
ULONG ProcessStackCountDecremented : 1; //0x78
|
|
ULONG RestrictedGuiThread : 1; //0x78
|
|
ULONG VpBackingThread : 1; //0x78
|
|
ULONG ThreadFlagsSpare2 : 1; //0x78
|
|
ULONG EtwStackTraceApcInserted : 8; //0x78
|
|
};
|
|
volatile LONG ThreadFlags; //0x78
|
|
} MISC_THREAD_VALUES, * PMISC_THREAD_VALUES;
|
|
|
|
typedef struct _syscall_args_t
|
|
{
|
|
u64 rcx, rdx, r8, r9;
|
|
} syscall_args_t, *psyscall_args_t;
|
|
|
|
inline void* original_function = nullptr;
|
|
|
|
// handler is designed to get the arguments passed in registers...
|
|
extern "C" void asm_hook_handler_2004(unsigned syscall_number);
|
|
extern "C" void asm_hook_handler(unsigned syscall_number);
|
|
|
|
namespace nt
|
|
{
|
|
inline auto enable_filter(HANDLE tid) -> bool
|
|
{
|
|
PETHREAD thread;
|
|
if (PsLookupThreadByThreadId(tid, &thread) == STATUS_SUCCESS)
|
|
{
|
|
const auto thread_misc_values =
|
|
reinterpret_cast<PMISC_THREAD_VALUES>(
|
|
reinterpret_cast<unsigned char*>(thread) + 0x78);
|
|
|
|
// make the thread gui and restricted...
|
|
thread_misc_values->GuiThread = 1;
|
|
thread_misc_values->RestrictedGuiThread = 1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline auto enable_filter(PETHREAD thread) -> void
|
|
{
|
|
const auto thread_misc_values =
|
|
reinterpret_cast<PMISC_THREAD_VALUES>(
|
|
reinterpret_cast<unsigned char*>(thread) + 0x78);
|
|
|
|
// make the thread gui and restricted...
|
|
thread_misc_values->GuiThread = 1;
|
|
thread_misc_values->RestrictedGuiThread = 1;
|
|
}
|
|
|
|
namespace win32k
|
|
{
|
|
inline auto hook_filter(void* hook_func) -> void*
|
|
{
|
|
PEPROCESS peproc;
|
|
KAPC_STATE apc_state;
|
|
|
|
RTL_OSVERSIONINFOW version;
|
|
RtlGetVersion(&version);
|
|
|
|
const auto explorer_pid = kutils::process::get_pid(L"explorer.exe");
|
|
PsLookupProcessByProcessId((HANDLE)explorer_pid, &peproc);
|
|
|
|
// attach to an address space that contains win32k.sys
|
|
KeStackAttachProcess(peproc, &apc_state);
|
|
{
|
|
const auto win32k = kutils::driver::get_driver_base("win32k.sys");
|
|
if (version.dwBuildNumber >= 19041) // if 2004 and above...
|
|
{
|
|
/*
|
|
* .text:FFFFF97FFF0172E4 48 89 4C 24 20 mov [rsp+48h+var_28], rcx
|
|
* .text:FFFFF97FFF0172E9 48 89 54 24 28 mov [rsp+48h+var_20], rdx
|
|
* .text:FFFFF97FFF0172EE 4C 89 44 24 30 mov [rsp+48h+var_18], r8
|
|
* .text:FFFFF97FFF0172F3 4C 89 4C 24 38 mov [rsp+48h+var_10], r9
|
|
* .text:FFFFF97FFF0172F8 48 C7 C1 00 00 00 00 mov rcx, 0 ; _QWORD
|
|
* .text:FFFFF97FFF0172FF 48 FF 15 [B2 A4 03 00] call cs:__imp_IsWin32KSyscallFiltered <==== 30 bytes to this RVA...
|
|
*/
|
|
|
|
auto sig_result = reinterpret_cast<u64>(
|
|
kutils::signature::scan(win32k,
|
|
kutils::pe::get_nt_header(win32k)->OptionalHeader.SizeOfImage,
|
|
WIN32K_SYSCALL_FILTER_SIG, WIN32K_SYSCALL_FILTER_MASK));
|
|
|
|
const auto sig_rva = *reinterpret_cast<int*>(sig_result + 30); // + 30 from above...
|
|
sig_result = sig_result + sig_rva + 34; // 34 bytes to RIP...
|
|
|
|
if (sig_result)
|
|
{
|
|
/*
|
|
* .rdata:FFFFF97FFF0517B8 ; __int64 (__fastcall *IsWin32KSyscallFiltered)(_QWORD)
|
|
* .rdata:FFFFF97FFF0517B8 E4 05 01 FF 7F F9 FF FF __imp_IsWin32KSyscallFiltered dq offset IsWin32KSyscallFiltered <=== deference this....
|
|
*/
|
|
const auto win32k_filter_func =
|
|
reinterpret_cast<u64>(
|
|
*reinterpret_cast<void**>(sig_result));
|
|
|
|
/*
|
|
* .text:FFFFF97FFF0105E4 IsWin32KSyscallFiltered proc near
|
|
* .text:FFFFF97FFF0105E4 48 83 EC 28 sub rsp, 28h
|
|
* .text:FFFFF97FFF0105E8 48 8B 05 [A1 67 05 00] mov rax, cs:qword_FFFFF97FFF066D90 <======= + 7 bytes to this RVA....
|
|
* .text:FFFFF97FFF0105EF 48 85 C0 test rax, rax
|
|
* .text:FFFFF97FFF0105F2 74 06 jz short loc_FFFFF97FFF0105FA
|
|
* .text:FFFFF97FFF0105F4 FF 15 66 43 06 00 call cs:__guard_dispatch_icall_fptr
|
|
*/
|
|
const auto ptr_swap_rva = *reinterpret_cast<int*>(win32k_filter_func + 7); // + 7 from above^
|
|
const auto win32k_syscall_filter_ptr = reinterpret_cast<void**>(ptr_swap_rva + win32k_filter_func + 11); // + 7 because 11 bytes in is the next instruction after the mov rax, cs....
|
|
const auto result = *win32k_syscall_filter_ptr;
|
|
*win32k_syscall_filter_ptr = hook_func;
|
|
|
|
KeUnstackDetachProcess(&apc_state);
|
|
return result;
|
|
}
|
|
}
|
|
else // else 1909 and below (IAT hook)...
|
|
{
|
|
auto result = kutils::driver::iat_hook(
|
|
win32k, "IsWin32KSyscallFiltered", hook_func);
|
|
|
|
KeUnstackDetachProcess(&apc_state);
|
|
return result;
|
|
}
|
|
}
|
|
KeUnstackDetachProcess(&apc_state);
|
|
return nullptr;
|
|
}
|
|
|
|
inline auto unhook_filter(void* original_function) -> void
|
|
{
|
|
PEPROCESS peproc;
|
|
KAPC_STATE apc_state;
|
|
|
|
RTL_OSVERSIONINFOW version;
|
|
RtlGetVersion(&version);
|
|
|
|
const auto explorer_pid = kutils::process::get_pid(L"explorer.exe");
|
|
PsLookupProcessByProcessId((HANDLE)explorer_pid, &peproc);
|
|
|
|
// attach to an address space that contains win32k.sys
|
|
KeStackAttachProcess(peproc, &apc_state);
|
|
{
|
|
const auto win32k = kutils::driver::get_driver_base("win32k.sys");
|
|
if (version.dwBuildNumber >= 19041) // if 2004 and above...
|
|
{
|
|
/*
|
|
* .text:FFFFF97FFF0172E4 48 89 4C 24 20 mov [rsp+48h+var_28], rcx
|
|
* .text:FFFFF97FFF0172E9 48 89 54 24 28 mov [rsp+48h+var_20], rdx
|
|
* .text:FFFFF97FFF0172EE 4C 89 44 24 30 mov [rsp+48h+var_18], r8
|
|
* .text:FFFFF97FFF0172F3 4C 89 4C 24 38 mov [rsp+48h+var_10], r9
|
|
* .text:FFFFF97FFF0172F8 48 C7 C1 00 00 00 00 mov rcx, 0 ; _QWORD
|
|
* .text:FFFFF97FFF0172FF 48 FF 15 [B2 A4 03 00] call cs:__imp_IsWin32KSyscallFiltered <==== 30 bytes to this RVA...
|
|
*/
|
|
|
|
auto sig_result = reinterpret_cast<u64>(
|
|
kutils::signature::scan(win32k,
|
|
kutils::pe::get_nt_header(win32k)->OptionalHeader.SizeOfImage,
|
|
WIN32K_SYSCALL_FILTER_SIG, WIN32K_SYSCALL_FILTER_MASK));
|
|
|
|
const auto sig_rva = *reinterpret_cast<int*>(sig_result + 30); // + 30 from above...
|
|
sig_result = sig_result + sig_rva + 34; // 34 bytes to RIP...
|
|
|
|
if (sig_result)
|
|
{
|
|
/*
|
|
* .rdata:FFFFF97FFF0517B8 ; __int64 (__fastcall *IsWin32KSyscallFiltered)(_QWORD)
|
|
* .rdata:FFFFF97FFF0517B8 E4 05 01 FF 7F F9 FF FF __imp_IsWin32KSyscallFiltered dq offset IsWin32KSyscallFiltered <=== deference this....
|
|
*/
|
|
const auto win32k_filter_func =
|
|
reinterpret_cast<u64>(
|
|
*reinterpret_cast<void**>(sig_result));
|
|
|
|
/*
|
|
* .text:FFFFF97FFF0105E4 IsWin32KSyscallFiltered proc near
|
|
* .text:FFFFF97FFF0105E4 48 83 EC 28 sub rsp, 28h
|
|
* .text:FFFFF97FFF0105E8 48 8B 05 [A1 67 05 00] mov rax, cs:qword_FFFFF97FFF066D90 <======= + 7 bytes to this RVA....
|
|
* .text:FFFFF97FFF0105EF 48 85 C0 test rax, rax
|
|
* .text:FFFFF97FFF0105F2 74 06 jz short loc_FFFFF97FFF0105FA
|
|
* .text:FFFFF97FFF0105F4 FF 15 66 43 06 00 call cs:__guard_dispatch_icall_fptr
|
|
*/
|
|
const auto ptr_swap_rva = *reinterpret_cast<int*>(win32k_filter_func + 7); // + 7 from above^
|
|
const auto win32k_syscall_filter_ptr = reinterpret_cast<void**>(ptr_swap_rva + win32k_filter_func + 11); // + 7 because 11 bytes in is the next instruction after the mov rax, cs....
|
|
*win32k_syscall_filter_ptr = original_function;
|
|
}
|
|
}
|
|
else // else 1909 and below (IAT hook)...
|
|
{
|
|
// restore IAT...
|
|
kutils::driver::iat_hook(win32k,
|
|
"IsWin32KSyscallFiltered", original_function);
|
|
}
|
|
}
|
|
KeUnstackDetachProcess(&apc_state);
|
|
}
|
|
}
|
|
} |