nt!DbgBreakPointWithStatus:
fffff805`7affd0b0 cc int 3
kd> ed nt!Kd_DEFAULT_Mask 0xFFFFFFFF
kd> ed nt!Kd_IHVDRIVER_Mask 0xFFFFFFFF
kd> g
[+] [DriverEntry] 驱动加载开始
[+] [DriverEntry] 驱动加载成功
[+] [ProcessNotifyCallback] 目标进程 oxygen.exe 创建 (PID: 8772)
[+] [ProcessNotifyCallback] 工作线程已创建
[+] Worker thread started for hook installation on PID: 8772
Break instruction exception - code 80000003 (first chance)
obpcallback!InstallHook+0x50:
fffff805`802d13a0 cc int 3
kd> g
[+] [InstallHook] 找到目标函数地址: FFFFF8057B2EFB60
[PTE_HOOK] 开始隔离页面: PID=8772, 地址=0xFFFFF8057B2EFB60
[PTE_HOOK] 正在拆分大页: 输入PDE=0xa00000002a001a1, 输出PDE=0xFFFFBD0464F73BB0
[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x239de6000
[PTE_HOOK] G-Bit Info:
Align Address: 0xFFFFF8057B2EF000
IsLargePage: 1
PDE: 0xa00000002a000a1 (Address: 0xFFFFE2713E015EC8)
[PTE_HOOK] 清除大页G位: PDE=0xa00000002a000a1
[PTE_HOOK] 开始隔离页表: CR3=0x19dc62000, 地址=0xFFFFF8057B2EF000
[PTE_HOOK] 大页模式: 源PFN=0x239de6, 源VA=FFFFCF812EB37000
KDTARGET: Refreshing KD connection
*** Fatal System Error: 0x00000050
(0xFFFFE271389C5F00,0x0000000000000000,0xFFFFF805802D24B6,0x0000000000000002)
Driver at fault:
*** obpcallback.sys - Address FFFFF805802D24B6 base at FFFFF805802D0000, DateStamp 686e6499
.
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
For analysis of this file, run !analyze -v
nt!DbgBreakPointWithStatus:
fffff805`7affd0b0 cc int 3
kd> !analyze -v
Connected to Windows 10 19041 x64 target at (Wed Jul 9 20:47:45.168 2025 (UTC + 8:00)), ptr64 TRUE
Loading Kernel Symbols
...................................
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.
............................
................................................................
.....................................................
Loading User Symbols
PEB is paged out (Peb.Ldr = 00000000`0034a018). Type ".hh dbgerr001" for details
Loading unloaded module list
.......
ERROR: FindPlugIns 8007007b
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: ffffe271389c5f00, memory referenced.
Arg2: 0000000000000000, X64: bit 0 set if the fault was due to a not-present PTE.
bit 1 is set if the fault was due to a write, clear if a read.
bit 3 is set if the processor decided the fault was due to a corrupted PTE.
bit 4 is set if the fault was due to attempted execute of a no-execute PTE.
- ARM64: bit 1 is set if the fault was due to a write, clear if a read.
bit 3 is set if the fault was due to attempted execute of a no-execute PTE.
Arg3: fffff805802d24b6, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 0000000000000002, (reserved)
Debugging Details:
------------------
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.
KEY_VALUES_STRING: 1
Key : AV.Type
Value: Read
Key : Analysis.CPU.mSec
Value: 4859
Key : Analysis.Elapsed.mSec
Value: 43355
Key : Analysis.IO.Other.Mb
Value: 0
Key : Analysis.IO.Read.Mb
Value: 3
Key : Analysis.IO.Write.Mb
Value: 1
Key : Analysis.Init.CPU.mSec
Value: 3375
Key : Analysis.Init.Elapsed.mSec
Value: 62367
Key : Analysis.Memory.CommitPeak.Mb
Value: 66
Key : Analysis.Version.DbgEng
Value: 10.0.27829.1001
Key : Analysis.Version.Description
Value: 10.2503.24.01 amd64fre
Key : Analysis.Version.Ext
Value: 1.2503.24.1
Key : Bugcheck.Code.KiBugCheckData
Value: 0x50
Key : Bugcheck.Code.LegacyAPI
Value: 0x50
Key : Bugcheck.Code.TargetModel
Value: 0x50
Key : Failure.Bucket
Value: AV_R_(null)_obpcallback!PteHookManager::fn_isolation_pagetable
Key : Failure.Exception.IP.Address
Value: 0xfffff805802d24b6
Key : Failure.Exception.IP.Module
Value: obpcallback
Key : Failure.Exception.IP.Offset
Value: 0x24b6
Key : Failure.Hash
Value: {66662972-75f7-8164-ff3f-97f1d0653246}
Key : Hypervisor.Enlightenments.Value
Value: 12576
Key : Hypervisor.Enlightenments.ValueHex
Value: 0x3120
Key : Hypervisor.Flags.AnyHypervisorPresent
Value: 1
Key : Hypervisor.Flags.ApicEnlightened
Value: 0
Key : Hypervisor.Flags.ApicVirtualizationAvailable
Value: 0
Key : Hypervisor.Flags.AsyncMemoryHint
Value: 0
Key : Hypervisor.Flags.CoreSchedulerRequested
Value: 0
Key : Hypervisor.Flags.CpuManager
Value: 0
Key : Hypervisor.Flags.DeprecateAutoEoi
Value: 1
Key : Hypervisor.Flags.DynamicCpuDisabled
Value: 0
Key : Hypervisor.Flags.Epf
Value: 0
Key : Hypervisor.Flags.ExtendedProcessorMasks
Value: 0
Key : Hypervisor.Flags.HardwareMbecAvailable
Value: 0
Key : Hypervisor.Flags.MaxBankNumber
Value: 0
Key : Hypervisor.Flags.MemoryZeroingControl
Value: 0
Key : Hypervisor.Flags.NoExtendedRangeFlush
Value: 1
Key : Hypervisor.Flags.NoNonArchCoreSharing
Value: 0
Key : Hypervisor.Flags.Phase0InitDone
Value: 1
Key : Hypervisor.Flags.PowerSchedulerQos
Value: 0
Key : Hypervisor.Flags.RootScheduler
Value: 0
Key : Hypervisor.Flags.SynicAvailable
Value: 1
Key : Hypervisor.Flags.UseQpcBias
Value: 0
Key : Hypervisor.Flags.Value
Value: 536632
Key : Hypervisor.Flags.ValueHex
Value: 0x83038
Key : Hypervisor.Flags.VpAssistPage
Value: 1
Key : Hypervisor.Flags.VsmAvailable
Value: 0
Key : Hypervisor.RootFlags.AccessStats
Value: 0
Key : Hypervisor.RootFlags.CrashdumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.CreateVirtualProcessor
Value: 0
Key : Hypervisor.RootFlags.DisableHyperthreading
Value: 0
Key : Hypervisor.RootFlags.HostTimelineSync
Value: 0
Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled
Value: 0
Key : Hypervisor.RootFlags.IsHyperV
Value: 0
Key : Hypervisor.RootFlags.LivedumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.MapDeviceInterrupt
Value: 0
Key : Hypervisor.RootFlags.MceEnlightened
Value: 0
Key : Hypervisor.RootFlags.Nested
Value: 0
Key : Hypervisor.RootFlags.StartLogicalProcessor
Value: 0
Key : Hypervisor.RootFlags.Value
Value: 0
Key : Hypervisor.RootFlags.ValueHex
Value: 0x0
Key : SecureKernel.HalpHvciEnabled
Value: 0
Key : WER.OS.Branch
Value: vb_release
Key : WER.OS.Version
Value: 10.0.19041.1
BUGCHECK_CODE: 50
BUGCHECK_P1: ffffe271389c5f00
BUGCHECK_P2: 0
BUGCHECK_P3: fffff805802d24b6
BUGCHECK_P4: 2
FAULTING_THREAD: ffffbd046b292080
READ_ADDRESS: unable to get nt!PspSessionIdBitmap
ffffe271389c5f00
MM_INTERNAL_CODE: 2
PROCESS_NAME: oxygen.exe
STACK_TEXT:
fffffc89`cd0dac48 fffff805`7b111882 : fffffc89`cd0dadb0 fffff805`7af7c940 fffff805`802d0000 00000000`00000000 : nt!DbgBreakPointWithStatus
fffffc89`cd0dac50 fffff805`7b110e66 : fffff805`00000003 fffffc89`cd0dadb0 fffff805`7b00a110 fffffc89`cd0db300 : nt!KiBugCheckDebugBreak+0x12
fffffc89`cd0dacb0 fffff805`7aff5317 : 00000000`00000000 00000000`00000000 ffffe2f8`00000000 00000000`00000000 : nt!KeBugCheck2+0x946
fffffc89`cd0db3c0 fffff805`7b07a665 : 00000000`00000050 ffffe271`389c5f00 00000000`00000000 fffffc89`cd0db6a0 : nt!KeBugCheckEx+0x107
fffffc89`cd0db400 fffff805`7aeea4a0 : 00000000`00000000 00000000`00000000 fffffc89`cd0db720 00000000`00000000 : nt!MiSystemFault+0x172315
fffffc89`cd0db500 fffff805`7b00335e : 00000000`00000000 fffff805`7affd0d5 00000000`00000010 00000000`00040295 : nt!MmAccessFault+0x400
fffffc89`cd0db6a0 fffff805`802d24b6 : fffffc89`cd0db8b8 00000000`0000470a fffff805`802d41e0 00000000`00239de6 : nt!KiPageFault+0x35e
fffffc89`cd0db830 fffff805`802d1e51 : ffffbd04`64f74000 00000001`9dc62000 fffff805`7b2ef000 ffffbd04`64f73bb0 : obpcallback!PteHookManager::fn_isolation_pagetable+0x4b6 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 566]
fffffc89`cd0db9c0 fffff805`802d28bf : ffffbd04`64f74000 00000000`00002244 fffff805`7b2efb60 00000000`00000035 : obpcallback!PteHookManager::fn_isolation_pages+0x261 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 659]
fffffc89`cd0dbad0 fffff805`802d13f4 : ffffbd04`64f74000 00000000`00002244 fffffc89`cd0dbbb0 fffff805`802d15b0 : obpcallback!PteHookManager::fn_pte_inline_hook_bp_pg+0x4f [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 780]
fffffc89`cd0dbb90 fffff805`802d1484 : fffff805`802d4890 00000000`00002244 00000000`00000000 fffff805`75eaf180 : obpcallback!InstallHook+0xa4 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1039]
fffffc89`cd0dbbe0 fffff805`7aea29a5 : 00000000`00002244 fffff805`802d1450 00000000`00002244 00000000`00000001 : obpcallback!InstallHookWorker+0x34 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1067]
fffffc89`cd0dbc10 fffff805`7affc868 : fffff805`75eaf180 ffffbd04`6b292080 fffff805`7aea2950 00000000`00000246 : nt!PspSystemThreadStartup+0x55
fffffc89`cd0dbc60 00000000`00000000 : fffffc89`cd0dc000 fffffc89`cd0d6000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x28
FAULTING_SOURCE_LINE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp
FAULTING_SOURCE_FILE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp
FAULTING_SOURCE_LINE_NUMBER: 566
FAULTING_SOURCE_CODE:
562: }
563: memcpy(VaPdt, pdt_source_va, PAGE_SIZE);
564:
565: // ??????3: ¡ã???????PDPT?????¡¤
> 566: UINT64 pdpt_pfn = (Table.Pml4Address[pml4e_index] & ~0xFFF) >> 12;
567: void* pdpt_source_va = get_va_from_pfn(pdpt_pfn);
568: if (!pdpt_source_va) {
569: logger("??¡¤¡§????PDPT???¨¦?????¡¤", true);
570: return false;
571: }
SYMBOL_NAME: obpcallback!PteHookManager::fn_isolation_pagetable+4b6
MODULE_NAME: obpcallback
IMAGE_NAME: obpcallback.sys
STACK_COMMAND: .process /r /p 0xffffbd046545f1c0; .thread 0xffffbd046b292080 ; kb
BUCKET_ID_FUNC_OFFSET: 4b6
FAILURE_BUCKET_ID: AV_R_(null)_obpcallback!PteHookManager::fn_isolation_pagetable
OS_VERSION: 10.0.19041.1
BUILDLAB_STR: vb_release
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {66662972-75f7-8164-ff3f-97f1d0653246}
Followup: MachineOwner什么原因导致的错误,代码如下:#include <ntifs.h>
#include <ntddk.h>
#include <intrin.h>
#include "ptehook.h"
#define CR0_WP (1 << 16)
HANDLE targetProcessId = NULL;
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
ULONG64 address; // 8字节绝对地址
} JMP_ABS, * PJMP_ABS;
#pragma pack(pop)
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);
// 物理地址转虚拟地址的辅助函数
auto get_va_from_pfn = [this](UINT64 pfn) -> void* {
if (pfn == 0) return nullptr;
PHYSICAL_ADDRESS physAddr;
physAddr.QuadPart = pfn << 12;
return fn_pa_to_va(physAddr.QuadPart);
};
// 修复点1: 安全获取PT源地址
void* pt_source_va = nullptr;
if (Table.IsLargePage && split_pde_ptr) {
auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr;
pt_source_va = get_va_from_pfn(split_pde->flags.page_frame_number);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 大页模式: 源PFN=0x%llx, 源VA=%p\n",
split_pde->flags.page_frame_number, pt_source_va);
}
else {
pt_source_va = get_va_from_pfn(Table.PdeAddress->flags.page_frame_number);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 常规模式: 源PFN=0x%llx, 源VA=%p\n",
Table.PdeAddress->flags.page_frame_number, pt_source_va);
}
if (!pt_source_va) {
logger("无法获取PT源虚拟地址", true);
return false;
}
memcpy(VaPt, pt_source_va, PAGE_SIZE);
// 修复点2: 安全获取PDT源地址
void* pdt_source_va = get_va_from_pfn(Table.PdpteAddress->flags.page_frame_number);
if (!pdt_source_va) {
logger("无法获取PDT源虚拟地址", true);
return false;
}
memcpy(VaPdt, pdt_source_va, PAGE_SIZE);
// 修复点3: 安全获取PDPT源地址
UINT64 pdpt_pfn = (Table.Pml4Address[pml4e_index] & ~0xFFF) >> 12;
void* pdpt_source_va = get_va_from_pfn(pdpt_pfn);
if (!pdpt_source_va) {
logger("无法获取PDPT源虚拟地址", true);
return false;
}
memcpy(VaPdpt, pdpt_source_va, PAGE_SIZE);
// 设置新PTE
auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt;
new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12;
// 设置新PDE
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;
// 设置新PDPTE
auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt;
new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12;
// 设置新PML4E
auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF);
if (!new_pml4) {
logger("无法获取PML4虚拟地址", true);
return false;
}
// 保存原始PML4E值
UINT64 original_pml4e = new_pml4[pml4e_index];
new_pml4[pml4e_index] = (original_pml4e & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF);
// 刷新TLB (多核安全)
KeIpiGenericCall([](ULONG_PTR Context) -> ULONG_PTR {
__invlpg((void*)Context);
return 0;
}, (ULONG_PTR)replace_align_addr);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] PML4E更新: 0x%llx -> 0x%llx\n", original_pml4e, new_pml4[pml4e_index]);
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);
}
success = fn_isolation_pagetable(target_cr3, AlignAddr, split_pde);
}
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(target_cr3, 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)
{
if (!MmIsAddressValid(trampoline)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 内存地址无效 (VA=%p)\n", trampoline);
return false;
}
PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(trampoline);
if (physAddr.QuadPart == 0) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 错误: 无法获取物理地址 (VA=%p)\n", trampoline);
return false;
}
KIRQL oldIrql = KeRaiseIrqlToDpcLevel();
BOOLEAN wpEnabled = (__readcr0() & CR0_WP);
if (wpEnabled) {
__writecr0(__readcr0() & ~CR0_WP);
_mm_mfence();
}
PMDL pMdl = IoAllocateMdl(trampoline, sizeof(JMP_ABS), FALSE, FALSE, NULL);
if (!pMdl) {
if (wpEnabled) __writecr0(__readcr0() | CR0_WP);
KeLowerIrql(oldIrql);
return false;
}
NTSTATUS status = STATUS_SUCCESS;
__try {
MmBuildMdlForNonPagedPool(pMdl);
MmProtectMdlSystemAddress(pMdl, PAGE_READWRITE);
// 正确写入 FF25 00000000 和 8字节地址
memcpy(trampoline, jmpCmd.opcode, 6); // FF25 00000000
*(ULONG64*)((BYTE*)trampoline + 6) = jmpCmd.address; // 地址写入 RIP+0 的位置
_mm_sfence();
_mm_clflush(trampoline);
_mm_clflush((BYTE*)trampoline + 8);
__invlpg(trampoline);
_mm_mfence();
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 异常: 写入跳板失败 (代码: 0x%X)\n", status);
}
IoFreeMdl(pMdl);
if (wpEnabled) {
__writecr0(__readcr0() | CR0_WP);
_mm_mfence();
}
KeLowerIrql(oldIrql);
if (!NT_SUCCESS(status)) return false;
// 验证写入结果
if (*(USHORT*)trampoline != 0x25FF ||
*(ULONG64*)((BYTE*)trampoline + 6) != jmpCmd.address)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 验证失败: 跳板内容不匹配\n"
" 预期: FF25 [%p]\n"
" 实际: %02X%02X %02X%02X%02X%02X [%p]\n",
jmpCmd.address,
((BYTE*)trampoline)[0], ((BYTE*)trampoline)[1],
((BYTE*)trampoline)[2], ((BYTE*)trampoline)[3],
((BYTE*)trampoline)[4], ((BYTE*)trampoline)[5],
*(ULONG64*)((BYTE*)trampoline + 6));
return false;
}
return true;
}
bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr)
{
// [1] 页表隔离
if (!fn_isolation_pages(process_id, *ori_addr)) {
return false;
}
// [2] 获取目标进程上下文
PEPROCESS targetProcess;
if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &targetProcess))) {
return false;
}
KAPC_STATE apcState;
KeStackAttachProcess(targetProcess, &apcState);
// [3] 构造跳转指令
JMP_ABS jmpCmd = {};
memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // FF25 00000000
jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr);
// [4] 直接写入被隔离页
void* targetFunc = *ori_addr;
bool success = false;
// 禁用写保护
KIRQL oldIrql = DisableWriteProtection();
__try {
// 保存原始指令 (用于卸载)
RtlCopyMemory(m_HookInfo[m_HookCount].OriginalBytes, targetFunc, sizeof(jmpCmd));
// 写入跳转指令到隔离页
memcpy(targetFunc, &jmpCmd, 6);
*(ULONG64*)((BYTE*)targetFunc + 6) = jmpCmd.address;
// 刷新缓存
_mm_sfence();
_mm_clflush(targetFunc);
__invlpg(targetFunc);
_mm_mfence();
success = true;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[PTE_HOOK] 直接写入隔离页成功: VA=%p -> Hook=%p\n",
targetFunc, hk_addr);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"[PTE_HOOK] 写入隔离页异常: 0x%X\n", GetExceptionCode());
}
// 恢复写保护
EnableWriteProtection(oldIrql);
// [5] 记录Hook信息
if (success) {
m_HookInfo[m_HookCount].OriginalAddress = targetFunc;
m_HookInfo[m_HookCount].HookAddress = hk_addr;
m_HookInfo[m_HookCount].ProcessId = process_id;
m_HookInfo[m_HookCount].IsHooked = TRUE;
m_HookCount++;
}
// [6] 清理
KeUnstackDetachProcess(&apcState);
ObDereferenceObject(targetProcess);
return success;
}
// 析构函数清理资源
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
) {
PEPROCESS currentProcess = PsGetCurrentProcess();
CHAR* imageName = PsGetProcessImageFileName(currentProcess);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName);
__debugbreak(); // 强制中断,确认是否执行到这里
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;
}
__debugbreak();
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag);
void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag;
void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag;
if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(targetProcessId, &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);
__debugbreak(); // 强制中断,验证是否执行到这里
return STATUS_SUCCESS;
}
// 移除 Hook
VOID RemoveHook() {
if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) {
g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag);
}
}
// 工作线程函数
VOID InstallHookWorker(PVOID Context) {
targetProcessId = (HANDLE)Context;
DbgPrint("[+] Worker thread started for hook installation on PID: %d\n", HandleToULong(targetProcessId));
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,
(PVOID)ProcessId // 关键:传递目标进程ID
);
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;
}
最新发布