#include <ntifs.h>
#include <ntddk.h>
#include <intrin.h>
#include "ptehook.h"
#define CR0_WP (1 << 16)
#define _WIN32_WINNT 0x0601
#define NTOS_MODE_USER
void HexDump(const void* data, size_t size);
typedef INT(*LDE_DISASM)(PVOID address, INT bits);
typedef unsigned long DWORD;
typedef unsigned __int64 ULONG64;
// 使用WDK标准类型
typedef unsigned char BYTE;
typedef LONG NTSTATUS;
// 修正的跳板指令结构
#pragma pack(push, 1)
typedef struct _JMP_ABS {
BYTE opcode[6]; // FF 25 00 00 00 00 = jmp [rip+0]
ULONG64 address; // 目标地址 (紧跟在指令后)
} JMP_ABS, * PJMP_ABS;
#pragma pack(pop)
static_assert(sizeof(JMP_ABS) == 14, "JMP_ABS size must be 14 bytes");
LDE_DISASM lde_disasm;
// 初始化引擎
VOID lde_init()
{
lde_disasm = (LDE_DISASM)ExAllocatePool(NonPagedPool, 12800);
memcpy(lde_disasm, szShellCode, 12800);
}
// 得到完整指令长度,避免截断
ULONG GetFullPatchSize(PUCHAR Address)
{
ULONG LenCount = 0, Len = 0;
// 至少需要14字节
while (LenCount <= 14)
{
Len = lde_disasm(Address, 64);
Address = Address + Len;
LenCount = LenCount + Len;
}
return LenCount;
}
#define PROCESS_NAME_LENGTH 16
#define DRIVER_TAG 'HKOB'
EXTERN_C char* PsGetProcessImageFileName(PEPROCESS process);
char target_process_name[] = "oxygen.exe";
typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)(
HANDLE Handle,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
ULONG Tag,
PVOID* Object,
POBJECT_HANDLE_INFORMATION HandleInformation
);
fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = NULL;
// PTE Hook Framework
#define MAX_G_BIT_RECORDS 128
#define MAX_HOOK_COUNT 64
#define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF))
#define PDPTE_PS_BIT (1 << 7)
#define PDE_PS_BIT (1 << 7)
#define PTE_NX_BIT (1ULL << 63)
#define CACHE_WB (6ULL << 3)
// 页表结构定义
typedef struct _PAGE_TABLE {
UINT64 LineAddress;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 pat : 1;
UINT64 global : 1;
UINT64 ignored_1 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_2 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*PteAddress;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 large_page : 1;
UINT64 global : 1;
UINT64 ignored_2 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_3 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*PdeAddress;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 ignored_1 : 1;
UINT64 page_size : 1;
UINT64 ignored_2 : 4;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_3 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*PdpteAddress;
UINT64* Pml4Address;
BOOLEAN IsLargePage;
BOOLEAN Is1GBPage;
UINT64 OriginalPte;
UINT64 OriginalPde;
UINT64 OriginalPdpte;
UINT64 OriginalPml4e;
HANDLE ProcessId;
} PAGE_TABLE, * PPAGE_TABLE;
// G位信息记录结构体
typedef struct _G_BIT_INFO {
void* AlignAddress;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 large_page : 1;
UINT64 global : 1;
UINT64 ignored_2 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_3 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*PdeAddress;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 pat : 1;
UINT64 global : 1;
UINT64 ignored_1 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_2 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*PteAddress;
BOOLEAN IsLargePage;
} G_BIT_INFO, * PG_BIT_INFO;
typedef struct _HOOK_INFO {
void* OriginalAddress;
void* HookAddress;
UINT8 OriginalBytes[20];
UINT8 HookBytes[20];
UINT32 HookLength;
BOOLEAN IsHooked;
HANDLE ProcessId;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 pat : 1;
UINT64 global : 1;
UINT64 ignored_1 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_2 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*HookedPte;
union {
struct {
UINT64 present : 1;
UINT64 write : 1;
UINT64 user : 1;
UINT64 write_through : 1;
UINT64 cache_disable : 1;
UINT64 accessed : 1;
UINT64 dirty : 1;
UINT64 large_page : 1;
UINT64 global : 1;
UINT64 ignored_2 : 3;
UINT64 page_frame_number : 36;
UINT64 reserved_1 : 4;
UINT64 ignored_3 : 7;
UINT64 protection_key : 4;
UINT64 execute_disable : 1;
} flags;
UINT64 value;
}*HookedPde;
} HOOK_INFO;
class PteHookManager {
public:
bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr);
bool fn_remove_hook(HANDLE process_id, void* hook_addr);
static PteHookManager* GetInstance();
HOOK_INFO* GetHookInfo() { return m_HookInfo; }
char* GetTrampLinePool() { return m_TrampLinePool; }
UINT32 GetHookCount() { return m_HookCount; }
bool fn_resume_global_bits(void* align_addr);
~PteHookManager(); // 添加析构函数声明
private:
bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd);
void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address);
bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde);
bool fn_isolation_pages(HANDLE process_id, void* ori_addr);
bool fn_split_large_pages(void* in_pde, void* out_pde);
NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table);
void* fn_pa_to_va(UINT64 pa);
UINT64 fn_va_to_pa(void* va);
__forceinline KIRQL DisableWriteProtection();
__forceinline void EnableWriteProtection(KIRQL oldIrql);
void logger(const char* info, bool is_err, LONG err_code = 0);
void PrintPageTableInfo(const PAGE_TABLE& table);
void PrintHookInfo(const HOOK_INFO& hookInfo);
void PrintGBitInfo(const G_BIT_INFO& gbitInfo);
static constexpr SIZE_T MAX_HOOKS = 256; // 根据需求调整
G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS];
UINT32 m_GbitCount = 0;
void* m_PteBase = 0;
HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 };
DWORD m_HookCount = 0;
char* m_TrampLinePool = nullptr; // 合并为一个声明
UINT32 m_PoolUsed = 0;
static PteHookManager* m_Instance;
};
PteHookManager* PteHookManager::m_Instance = nullptr;
// 实现部分
__forceinline KIRQL PteHookManager::DisableWriteProtection() {
KIRQL oldIrql = KeRaiseIrqlToDpcLevel();
UINT64 cr0 = __readcr0();
__writecr0(cr0 & ~0x10000); // 清除CR0.WP位
_mm_mfence();
return oldIrql;
}
__forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) {
_mm_mfence();
UINT64 cr0 = __readcr0();
__writecr0(cr0 | 0x10000); // 设置CR0.WP位
KeLowerIrql(oldIrql);
}
void PteHookManager::logger(const char* info, bool is_err, LONG err_code) {
if (is_err) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] ERROR: %s (0x%X)\n", info, err_code);
}
else {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] INFO: %s\n", info);
}
}
void PteHookManager::PrintPageTableInfo(const PAGE_TABLE& table) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] Page Table Info for VA: 0x%p\n", (void*)table.LineAddress);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PML4E: 0x%llx (Address: 0x%p)\n", table.OriginalPml4e, table.Pml4Address);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PDPTE: 0x%llx (Address: 0x%p), Is1GBPage: %d\n",
table.OriginalPdpte, table.PdpteAddress, table.Is1GBPage);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PDE: 0x%llx (Address: 0x%p), IsLargePage: %d\n",
table.OriginalPde, table.PdeAddress, table.IsLargePage);
if (!table.IsLargePage && !table.Is1GBPage) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PTE: 0x%llx (Address: 0x%p)\n", table.OriginalPte, table.PteAddress);
}
}
void PteHookManager::PrintHookInfo(const HOOK_INFO& hookInfo) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] Hook Info:\n");
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" Original Address: 0x%p\n", hookInfo.OriginalAddress);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" Hook Address: 0x%p\n", hookInfo.HookAddress);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" Hook Length: %d\n", hookInfo.HookLength);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" Is Hooked: %d\n", hookInfo.IsHooked);
// 打印原始字节
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Bytes: ");
for (UINT32 i = 0; i < sizeof(hookInfo.OriginalBytes); i++) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.OriginalBytes[i]);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n");
// 打印Hook字节
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Bytes: ");
for (UINT32 i = 0; i < sizeof(hookInfo.HookBytes); i++) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.HookBytes[i]);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n");
}
void PteHookManager::PrintGBitInfo(const G_BIT_INFO& gbitInfo) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] G-Bit Info:\n");
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" Align Address: 0x%p\n", gbitInfo.AlignAddress);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" IsLargePage: %d\n", gbitInfo.IsLargePage);
if (gbitInfo.PdeAddress) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PDE: 0x%llx (Address: 0x%p)\n", gbitInfo.PdeAddress->value, gbitInfo.PdeAddress);
}
if (gbitInfo.PteAddress) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
" PTE: 0x%llx (Address: 0x%p)\n", gbitInfo.PteAddress->value, gbitInfo.PteAddress);
}
}
void* PteHookManager::fn_pa_to_va(UINT64 pa) {
PHYSICAL_ADDRESS physAddr;
physAddr.QuadPart = pa;
return MmGetVirtualForPhysical(physAddr);
}
UINT64 PteHookManager::fn_va_to_pa(void* va) {
PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va);
return physAddr.QuadPart;
}
NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) {
UINT64 va = table.LineAddress;
UINT64 pml4e_index = (va >> 39) & 0x1FF;
UINT64 pdpte_index = (va >> 30) & 0x1FF;
UINT64 pde_index = (va >> 21) & 0x1FF;
UINT64 pte_index = (va >> 12) & 0x1FF;
// PML4
UINT64 pml4_pa = cr3_val & ~0xFFF;
UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa);
if (!pml4_va) return STATUS_INVALID_ADDRESS;
table.Pml4Address = &pml4_va[pml4e_index];
table.OriginalPml4e = *table.Pml4Address;
if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION;
// PDPTE
UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF;
UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa);
if (!pdpte_va) return STATUS_INVALID_ADDRESS;
table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index];
table.OriginalPdpte = table.PdpteAddress->value;
table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE;
if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION;
if (table.Is1GBPage) return STATUS_SUCCESS;
// PDE
UINT64 pde_pa = table.OriginalPdpte & ~0xFFF;
UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa);
if (!pde_va) return STATUS_INVALID_ADDRESS;
table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index];
table.OriginalPde = table.PdeAddress->value;
table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE;
if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION;
if (table.IsLargePage) return STATUS_SUCCESS;
// PTE
UINT64 pte_pa = table.OriginalPde & ~0xFFF;
UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa);
if (!pte_va) return STATUS_INVALID_ADDRESS;
table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index];
table.OriginalPte = table.PteAddress->value;
if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION;
// 打印页表信息
PrintPageTableInfo(table);
return STATUS_SUCCESS;
}
bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) {
auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr;
auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 正在拆分大页: 输入PDE=0x%llx, 输出PDE=0x%p\n",
in_pde->value, out_pde);
PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 };
HighAddr.QuadPart = MAXULONG64;
auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache(
PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached);
if (!pt) {
logger("分配连续内存失败 (用于拆分大页)", true);
return false;
}
UINT64 start_pfn = in_pde->flags.page_frame_number;
for (int i = 0; i < 512; i++) {
pt[i].value = 0;
pt[i].flags.present = 1;
pt[i].flags.write = in_pde->flags.write;
pt[i].flags.user = in_pde->flags.user;
pt[i].flags.write_through = in_pde->flags.write_through;
pt[i].flags.cache_disable = in_pde->flags.cache_disable;
pt[i].flags.accessed = in_pde->flags.accessed;
pt[i].flags.dirty = in_pde->flags.dirty;
pt[i].flags.global = 0;
pt[i].flags.page_frame_number = start_pfn + i;
}
out_pde->value = in_pde->value;
out_pde->flags.large_page = 0;
out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x%llx\n", fn_va_to_pa(pt));
return true;
}
bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) {
PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 };
HighAddr.QuadPart = MAXULONG64;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 开始隔离页表: CR3=0x%llx, 地址=0x%p\n",
cr3_val, replace_align_addr);
auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached);
auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached);
auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached);
auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached);
if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) {
if (VaPt) MmFreeContiguousMemory(VaPt);
if (Va4kb) MmFreeContiguousMemory(Va4kb);
if (VaPdt) MmFreeContiguousMemory(VaPdt);
if (VaPdpt) MmFreeContiguousMemory(VaPdpt);
logger("分配连续内存失败 (用于隔离页表)", true);
return false;
}
PAGE_TABLE Table = { 0 };
Table.LineAddress = (UINT64)replace_align_addr;
NTSTATUS status = get_page_table(cr3_val, Table);
if (!NT_SUCCESS(status)) {
MmFreeContiguousMemory(VaPt);
MmFreeContiguousMemory(Va4kb);
MmFreeContiguousMemory(VaPdt);
MmFreeContiguousMemory(VaPdpt);
logger("获取页表信息失败", true, status);
return false;
}
UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF;
UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF;
UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF;
UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF;
memcpy(Va4kb, replace_align_addr, PAGE_SIZE);
if (Table.IsLargePage && split_pde_ptr) {
auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr;
memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE);
}
else {
memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE);
}
memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE);
memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE);
auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt;
new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12;
auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt;
new_pde[pde_index].value = Table.OriginalPde;
new_pde[pde_index].flags.large_page = 0;
new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12;
auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt;
new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12;
auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF);
new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF);
__invlpg(replace_align_addr);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12);
return true;
}
bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) {
PEPROCESS Process;
if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) {
logger("查找进程失败", true);
return false;
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 开始隔离页面: PID=%d, 地址=0x%p\n",
(ULONG)(ULONG_PTR)process_id, ori_addr);
KAPC_STATE ApcState;
KeStackAttachProcess(Process, &ApcState);
void* AlignAddr = PAGE_ALIGN(ori_addr);
PAGE_TABLE Table = { 0 };
Table.LineAddress = (UINT64)AlignAddr;
UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28);
if (!NT_SUCCESS(get_page_table(target_cr3, Table))) {
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
logger("获取目标进程页表失败", true);
return false;
}
bool success = false;
decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr;
if (Table.IsLargePage) {
split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS');
if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) {
if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS');
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
logger("拆分大页失败", true);
return false;
}
if (Table.PdeAddress->flags.global) {
Table.PdeAddress->flags.global = 0;
fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 清除大页G位: PDE=0x%llx\n", Table.PdeAddress->value);
}
}
else if (Table.PteAddress && Table.PteAddress->flags.global) {
Table.PteAddress->flags.global = 0;
fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 清除PTE G位: PTE=0x%llx\n", Table.PteAddress->value);
success = fn_isolation_pagetable(__readcr3(), AlignAddr, split_pde);
if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS');
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 页表状态: IsLargePage=%d, Is1GBPage=%d\n",
Table.IsLargePage, Table.Is1GBPage);
if (Table.PteAddress) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] PTE 值: 0x%llx (G位=%d)\n",
Table.PteAddress->value, Table.PteAddress->flags.global);
}
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
if (success) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 页面隔离成功\n");
}
else {
logger("页面隔离失败", true);
}
return success;
}
KeUnstackDetachProcess(&ApcState);
ObDereferenceObject(Process);
return true;
}
bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd)
{
// 1. 确保8字节对齐
if (reinterpret_cast<ULONG_PTR>(trampoline) & 0x7) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 跳板地址未对齐 (0x%p)\n", trampoline);
return false;
}
// 2. 禁用写保护
KIRQL oldIrql = DisableWriteProtection();
// 3. 直接写入内存
RtlCopyMemory(trampoline, &jmpCmd, sizeof(JMP_ABS));
// 4. 刷新缓存
__invlpg(trampoline);
_mm_mfence();
// 5. 恢复写保护
EnableWriteProtection(oldIrql);
// 6. 验证写入
BYTE buffer[sizeof(JMP_ABS)];
RtlCopyMemory(buffer, trampoline, sizeof(buffer));
if (memcmp(buffer, &jmpCmd, sizeof(jmpCmd)) != 0) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 验证失败! 内存内容:\n");
HexDump(buffer, sizeof(buffer));
return false;
}
// 7. 反汇编验证
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 跳板指令: jmp [rip+0] -> 0x%016llX\n",
jmpCmd.address);
return true;
}
// 辅助函数:十六进制转储
void HexDump(const void* data, size_t size) {
const BYTE* bytes = static_cast<const BYTE*>(data);
for (size_t i = 0; i < size; ++i) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", bytes[i]);
if ((i + 1) % 16 == 0) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n");
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n");
}
bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr)
{
if (!ori_addr || !hk_addr || !*ori_addr) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 无效参数 (ori_addr=%p, hk_addr=%p)\n",
ori_addr, hk_addr);
return false;
}
// 分配跳板池(如果尚未分配)
if (!m_TrampLinePool) {
PHYSICAL_ADDRESS LowAddr = { LowAddr.QuadPart = 0x100000 };
PHYSICAL_ADDRESS HighAddr = { HighAddr.QuadPart = ~0ull };
m_TrampLinePool = (char*)MmAllocateContiguousMemorySpecifyCache(
PAGE_SIZE * 8, LowAddr, HighAddr, LowAddr, MmNonCached);
if (!m_TrampLinePool) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 无法分配跳板池内存\n");
return false;
}
// 设置内存保护属性
PMDL pMdl = IoAllocateMdl(m_TrampLinePool, PAGE_SIZE * 8, FALSE, FALSE, NULL);
if (pMdl) {
MmBuildMdlForNonPagedPool(pMdl);
MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
IoFreeMdl(pMdl);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 跳板池分配成功: 地址=0x%p, 大小=%d字节\n",
m_TrampLinePool, PAGE_SIZE * 8);
}
// 计算跳板位置(8字节对齐)
void* trampoline = (void*)((ULONG_PTR)(m_TrampLinePool + m_PoolUsed + 7) & ~7) ;
SIZE_T requiredSize = ((char*)trampoline - m_TrampLinePool) + sizeof(JMP_ABS);
// 构造正确的跳转指令
JMP_ABS jmpCmd = {};
memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // jmp [rip+0]
jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 构造跳转指令:\n"
" 目标地址: 0x%p\n"
" 跳板位置: 0x%p\n"
" 指令格式: FF 25 00 00 00 00 + 8字节地址\n",
hk_addr, trampoline);
// 写入跳板指令
if (!WriteTrampolineInstruction(trampoline, jmpCmd)) {
return false;
}
// 记录Hook信息
bool hookRecorded = false;
for (UINT32 i = 0; i < MAX_HOOK_COUNT; i++) {
if (!m_HookInfo[i].IsHooked) {
m_HookInfo[i].OriginalAddress = *ori_addr;
m_HookInfo[i].HookAddress = trampoline;
m_HookInfo[i].ProcessId = process_id;
m_HookInfo[i].IsHooked = TRUE;
RtlCopyMemory(m_HookInfo[i].HookBytes, &jmpCmd, sizeof(jmpCmd));
m_HookInfo[i].HookLength = sizeof(JMP_ABS);
m_HookCount++;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] Hook记录 #%d: 原始地址=0x%p, 跳板=0x%p\n",
i, *ori_addr, trampoline);
hookRecorded = true;
break;
}
}
if (!hookRecorded) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 超过最大Hook数量限制 (%d)\n", MAX_HOOK_COUNT);
return false;
}
// 更新原始地址为跳板地址
*ori_addr = trampoline;
m_PoolUsed = (UINT32)requiredSize;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] Hook安装成功! 跳板指令:\n"
" jmp [rip+0] -> 0x%p\n",
hk_addr);
return true;
}
// 析构函数清理资源
PteHookManager::~PteHookManager()
{
if (m_TrampLinePool) {
MmFreeContiguousMemory(m_TrampLinePool);
m_TrampLinePool = nullptr;
}
}
bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 尝试移除Hook: Hook地址=0x%p\n", hook_addr);
for (UINT32 i = 0; i < m_HookCount; i++) {
if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 找到匹配的Hook: 原始地址=0x%p\n", m_HookInfo[i].OriginalAddress);
KIRQL oldIrql = DisableWriteProtection();
memcpy(m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalBytes,
sizeof(m_HookInfo[i].OriginalBytes));
EnableWriteProtection(oldIrql);
m_HookInfo[i].IsHooked = FALSE;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] Hook已成功移除\n");
return true;
}
}
logger("未找到匹配的Hook", true);
return false;
}
void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) {
if (m_GbitCount >= MAX_G_BIT_RECORDS) {
logger("达到最大G位记录数量限制", true);
return;
}
PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++];
record->AlignAddress = align_addr;
record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address;
record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address;
record->IsLargePage = (pde_address && ((decltype(PAGE_TABLE::PdeAddress))pde_address)->flags.large_page);
// 打印G位信息
PrintGBitInfo(*record);
}
bool PteHookManager::fn_resume_global_bits(void* align_addr) {
KIRQL oldIrql = DisableWriteProtection();
bool found = false;
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 开始恢复G位: 对齐地址=0x%p\n", align_addr);
for (UINT32 i = 0; i < m_GbitCount; i++) {
PG_BIT_INFO record = &m_GbitRecords[i];
if (align_addr && record->AlignAddress != align_addr) continue;
if (record->PteAddress) {
record->PteAddress->flags.global = 1;
__invlpg(record->AlignAddress);
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL,
" 恢复PTE G位: PTE=0x%llx, 地址=0x%p\n",
record->PteAddress->value, record->AlignAddress);
}
if (record->PdeAddress) {
record->PdeAddress->flags.global = 1;
if (record->IsLargePage) {
__invlpg(record->AlignAddress);
}
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL,
" 恢复PDE G位: PDE=0x%llx, 地址=0x%p, 大页=%d\n",
record->PdeAddress->value, record->AlignAddress, record->IsLargePage);
}
found = true;
if (align_addr) break;
}
EnableWriteProtection(oldIrql);
if (found) {
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] G位恢复完成\n");
}
else {
logger("未找到匹配的G位记录", true);
}
return found;
}
PteHookManager* PteHookManager::GetInstance() {
if (!m_Instance) {
m_Instance = static_cast<PteHookManager*>(
ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk'));
if (m_Instance) {
RtlZeroMemory(m_Instance, sizeof(PteHookManager));
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] PTE Hook管理器实例已创建: 地址=0x%p\n", m_Instance);
}
else {
DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 创建PTE Hook管理器实例失败\n");
}
}
return m_Instance;
}
// 全局PTE Hook管理器实例
PteHookManager* g_PteHookManager = nullptr;
// 辅助函数:检查是否为目标进程
BOOLEAN IsTargetProcess(CHAR* imageName) {
CHAR currentName[16];
// 复制到本地缓冲区并确保 NULL 终止
RtlCopyMemory(currentName, imageName, 16);
currentName[15] = '\0'; // 确保终止
// 修剪尾部空格
for (int i = 15; i >= 0; i--) {
if (currentName[i] == ' ') currentName[i] = '\0';
else if (currentName[i] != '\0') break;
}
return (strcmp(currentName, target_process_name) == 0);
}
// Hook 函数
NTSTATUS MyObReferenceObjectByHandleWithTag(
HANDLE Handle,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
ULONG Tag,
PVOID* Object,
POBJECT_HANDLE_INFORMATION HandleInformation
) {
__debugbreak(); // 强制中断,确认是否执行到这里
PEPROCESS currentProcess = PsGetCurrentProcess();
CHAR* imageName = PsGetProcessImageFileName(currentProcess);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName);
if (IsTargetProcess(imageName)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[!] [HookFunction] 拒绝访问目标进程 PID=%d\n", HandleToULong(PsGetCurrentProcessId()));
return STATUS_ACCESS_DENIED;
}
return g_OriginalObReferenceObjectByHandleWithTag(
Handle,
DesiredAccess,
ObjectType,
AccessMode,
Tag,
Object,
HandleInformation
);
}
NTSTATUS InstallHook() {
UNICODE_STRING funcName;
RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag");
g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName);
if (!g_OriginalObReferenceObjectByHandleWithTag) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[-] [InstallHook] 找不到 ObReferenceObjectByHandleWithTag\n");
return STATUS_NOT_FOUND;
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag);
void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag;
void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag;
HANDLE currentProcessId = PsGetCurrentProcessId();
if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(currentProcessId, &targetFunc, hookFunc)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[-] [InstallHook] PTE Hook 安装失败\n");
return STATUS_UNSUCCESSFUL;
}
g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[+] [InstallHook] Hook 成功安装. 跳板地址: %p\n", targetFunc);
return STATUS_SUCCESS;
}
// 移除 Hook
VOID RemoveHook() {
if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) {
g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag);
}
}
// 工作线程函数
VOID InstallHookWorker(PVOID Context) {
UNREFERENCED_PARAMETER(Context);
DbgPrint("[+] Worker thread started for hook installation\n");
InstallHook();
PsTerminateSystemThread(STATUS_SUCCESS);
}
// 进程创建回调
VOID ProcessNotifyCallback(
_In_ HANDLE ParentId,
_In_ HANDLE ProcessId,
_In_ BOOLEAN Create
) {
UNREFERENCED_PARAMETER(ParentId);
if (Create) {
PEPROCESS process = NULL;
if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &process))) {
CHAR* imageName = PsGetProcessImageFileName(process);
CHAR currentName[16];
RtlCopyMemory(currentName, imageName, 16);
currentName[15] = '\0';
for (int i = 15; i >= 0; i--) {
if (currentName[i] == ' ') currentName[i] = '\0';
else if (currentName[i] != '\0') break;
}
if (strcmp(currentName, target_process_name) == 0) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[+] [ProcessNotifyCallback] 目标进程 %s 创建 (PID: %d)\n", currentName, HandleToULong(ProcessId));
HANDLE threadHandle;
NTSTATUS status = PsCreateSystemThread(
&threadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
InstallHookWorker,
NULL
);
if (NT_SUCCESS(status)) {
ZwClose(threadHandle);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[+] [ProcessNotifyCallback] 工作线程已创建\n");
}
else {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[-] [ProcessNotifyCallback] 创建线程失败: 0x%X\n", status);
}
}
ObDereferenceObject(process);
}
}
}
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("[+] Driver unloading...\n");
// 移除进程通知回调
PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, TRUE);
// 移除Hook
RemoveHook();
// 清理PTE Hook资源
if (g_PteHookManager) {
DbgPrint("[PTE_HOOK] Cleaning up PTE...\n");
// 恢复所有被修改的G位
g_PteHookManager->fn_resume_global_bits(nullptr);
// 移除所有活动的Hook
HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo();
UINT32 hookCount = g_PteHookManager->GetHookCount();
for (UINT32 i = 0; i < hookCount; i++) {
if (hookInfo[i].IsHooked) {
g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress);
}
}
// 释放跳板池内存
char* trampLinePool = g_PteHookManager->GetTrampLinePool();
if (trampLinePool) {
ExFreePoolWithTag(trampLinePool, 'JmpP');
}
// 释放管理器实例
ExFreePoolWithTag(g_PteHookManager, 'tpHk');
g_PteHookManager = nullptr;
}
DbgPrint("[+] Driver unloaded successfully\n");
}
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(RegistryPath);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载开始\n");
DriverObject->DriverUnload = DriverUnload;
g_PteHookManager = PteHookManager::GetInstance();
if (!g_PteHookManager) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 初始化 PteHookManager 失败\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, FALSE);
if (!NT_SUCCESS(status)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[-] [DriverEntry] 注册进程通知失败 (0x%X)\n", status);
return status;
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载成功\n");
return STATUS_SUCCESS;
}
将整个代码修改正确