UNREFERENCED_PARAMETER(arg);的作用

本文深入解析C程序中利用宏处理未引用参数的机制及其背后的好处,通过具体代码实例,解释如何避免编译器警告,同时保持代码的简洁性和功能性。此外,探讨了在特定场景下保留未使用参数的重要性,特别是当函数通过函数指针调用时。


代码中看到C程序里用到了这样的语句:


#define UNREFERENCED_PARAMETER(x)   do { x = x; } while(0)


int Function(void *arg) 

  UNREFERENCED_PARAMETER(arg); 

  ... /*arg参数在本函数中从未被使用*/

将上段代码宏展开后:

int Function(void *arg) 


  arg = arg; 
  ... 

查阅资料才发现,这样做的好处是避免了编译器关于未引用参数的警告。实际上这条语句不做任何事情,编译器不会为之产生任何代码,所以在空间和性能上不会有任何损失。 

那为什么不直接删了未使用的参数呢?

有一种情况:此函数的被调用是通过函数指针来回调的,调用者已经写好了函数指针接口。这时候这个参数就不能删掉,为了屏蔽编译器的警告,故加上这个宏。

另外,这个宏还有另一种形式:

#define UNREFERENCED_PARAMETER(x) (x)



kd> ed nt!Kd_DEFAULT_Mask 0xFFFFFFFF kd> ed nt!Kd_IHVDRIVER_Mask 0xFFFFFFFF kd> g [+] [DriverEntry] 驱动加载开始 [+] [DriverEntry] 驱动加载成功 [+] [ProcessNotifyCallback] 目标进程 oxygen.exe 创建 (PID: 8052) [+] [ProcessNotifyCallback] 工作线程已创建 [+] Worker thread started for hook installation on PID: 8052 Break instruction exception - code 80000003 (first chance) obpcallback!InstallHook+0x50: fffff803`0e2a12f0 cc int 3 kd> g [+] [InstallHook] 找到目标函数地址: FFFFF803062EFB60 [PTE_HOOK] 开始隔离页面: PID=8052, 地址=0xFFFFF803062EFB60 [PTE_HOOK] 正在拆分大页: 输入PDE=0xa00000002a001a1, 输出PDE=0xFFFFBB878EFA3F80 [PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x239dab000 [PTE_HOOK] G-Bit Info: Align Address: 0xFFFFF803062EF000 IsLargePage: 1 PDE: 0xa00000002a000a1 (Address: 0xFFFFFE7F3E00C188) [PTE_HOOK] 清除大页G位: PDE=0xa00000002a000a1 [PTE_HOOK] 开始隔离页表: CR3=0x12e16c000, 地址=0xFFFFF803062EF000 KDTARGET: Refreshing KD connection *** Fatal System Error: 0x0000007e (0xFFFFFFFFC0000005,0xFFFFF8030E2A2265,0xFFFF80031C95B638,0xFFFF80031C95AE70) 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: fffff803`05ffd0b0 cc int 3 kd> !analyze -v Connected to Windows 10 19041 x64 target at (Wed Jul 9 20:20:01.053 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`00259018). Type ".hh dbgerr001" for details Loading unloaded module list ...... ERROR: FindPlugIns 8007007b ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e) This is a very common BugCheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address. Arguments: Arg1: ffffffffc0000005, The exception code that was not handled Arg2: fffff8030e2a2265, The address that the exception occurred at Arg3: ffff80031c95b638, Exception Record Address Arg4: ffff80031c95ae70, Context Record Address 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. PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details KEY_VALUES_STRING: 1 Key : AV.Type Value: Read Key : Analysis.CPU.mSec Value: 4234 Key : Analysis.Elapsed.mSec Value: 39170 Key : Analysis.IO.Other.Mb Value: 0 Key : Analysis.IO.Read.Mb Value: 2 Key : Analysis.IO.Write.Mb Value: 0 Key : Analysis.Init.CPU.mSec Value: 3250 Key : Analysis.Init.Elapsed.mSec Value: 59417 Key : Analysis.Memory.CommitPeak.Mb Value: 72 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: 0x7e Key : Bugcheck.Code.LegacyAPI Value: 0x7e Key : Bugcheck.Code.TargetModel Value: 0x7e Key : Failure.Bucket Value: AV_obpcallback!PteHookManager::fn_isolation_pagetable Key : Failure.Exception.Code Value: 0xc0000005 Key : Failure.Exception.IP.Address Value: 0xfffff8030e2a2265 Key : Failure.Exception.IP.Module Value: obpcallback Key : Failure.Exception.IP.Offset Value: 0x2265 Key : Failure.Exception.Record Value: 0xffff80031c95b638 Key : Failure.Hash Value: {03bbd39e-299b-91b8-212d-d002a6bff650} 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: 7e BUGCHECK_P1: ffffffffc0000005 BUGCHECK_P2: fffff8030e2a2265 BUGCHECK_P3: ffff80031c95b638 BUGCHECK_P4: ffff80031c95ae70 FAULTING_THREAD: ffffbb8793f90080 EXCEPTION_RECORD: ffff80031c95b638 -- (.exr 0xffff80031c95b638) ExceptionAddress: fffff8030e2a2265 (obpcallback!PteHookManager::fn_isolation_pagetable+0x0000000000000315) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000000 Parameter[1]: 0000000239dab000 Attempt to read from address 0000000239dab000 CONTEXT: ffff80031c95ae70 -- (.cxr 0xffff80031c95ae70) rax=0000000239dab000 rbx=ffffbb8793f90080 rcx=0000000000001000 rdx=0000000000000000 rsi=0000000239dab000 rdi=ffff9181d99a7000 rip=fffff8030e2a2265 rsp=ffff80031c95b870 rbp=0000000000000080 r8=ffff80031c95b940 r9=8000000000000200 r10=0000000000000000 r11=ffffbb8790910000 r12=0000000000000280 r13=0000000000000000 r14=ffffbb878f4af040 r15=fffff8030c094000 iopl=0 nv up ei pl nz ac po nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050216 obpcallback!PteHookManager::fn_isolation_pagetable+0x315: fffff803`0e2a2265 f3a4 rep movs byte ptr [rdi],byte ptr [rsi] Resetting default scope PROCESS_NAME: oxygen.exe READ_ADDRESS: unable to get nt!PspSessionIdBitmap 0000000239dab000 ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s EXCEPTION_CODE_STR: c0000005 EXCEPTION_PARAMETER1: 0000000000000000 EXCEPTION_PARAMETER2: 0000000239dab000 EXCEPTION_STR: 0xc0000005 STACK_TEXT: ffff8003`1c95b870 fffff803`0e2a1da1 : ffffbb87`8efa7000 00000001`2e16c000 fffff803`062ef000 ffffbb87`8efa3f80 : obpcallback!PteHookManager::fn_isolation_pagetable+0x315 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 526] ffff8003`1c95b9c0 fffff803`0e2a25df : ffffbb87`8efa7000 00000000`00001f74 fffff803`062efb60 00000000`00000035 : obpcallback!PteHookManager::fn_isolation_pages+0x261 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 602] ffff8003`1c95bad0 fffff803`0e2a1344 : ffffbb87`8efa7000 00000000`00001f74 ffff8003`1c95bbb0 fffff803`0e2a1500 : obpcallback!PteHookManager::fn_pte_inline_hook_bp_pg+0x4f [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 723] ffff8003`1c95bb90 fffff803`0e2a13d4 : fffff803`0e2a44a0 00000000`00001f74 00000000`00000000 fffff803`040ef180 : obpcallback!InstallHook+0xa4 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 982] ffff8003`1c95bbe0 fffff803`05ea29a5 : 00000000`00001f74 fffff803`0e2a13a0 00000000`00001f74 fffff803`00000001 : obpcallback!InstallHookWorker+0x34 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1010] ffff8003`1c95bc10 fffff803`05ffc868 : fffff803`040ef180 ffffbb87`93f90080 fffff803`05ea2950 ffff8003`1c95bc80 : nt!PspSystemThreadStartup+0x55 ffff8003`1c95bc60 00000000`00000000 : ffff8003`1c95c000 ffff8003`1c956000 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: 526 FAULTING_SOURCE_CODE: 522: memcpy(Va4kb, replace_align_addr, PAGE_SIZE); 523: 524: if (Table.IsLargePage && split_pde_ptr) { 525: auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; > 526: memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); 527: } 528: else { 529: memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); 530: } 531: SYMBOL_NAME: obpcallback!PteHookManager::fn_isolation_pagetable+315 MODULE_NAME: obpcallback IMAGE_NAME: obpcallback.sys STACK_COMMAND: .cxr 0xffff80031c95ae70 ; kb BUCKET_ID_FUNC_OFFSET: 315 FAILURE_BUCKET_ID: AV_obpcallback!PteHookManager::fn_isolation_pagetable OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {03bbd39e-299b-91b8-212d-d002a6bff650} 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); 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); } 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; }
07-10
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; }
07-10
******************************************************************************* 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: 7424) [+] [ProcessNotifyCallback] 工作线程已创建 [+] Worker thread started for hook installation on PID: 7424 Break instruction exception - code 80000003 (first chance) obpcallback!InstallHook+0x50: fffff805`802b12f0 cc int 3 kd> g [+] [InstallHook] 找到目标函数地址: FFFFF8057B2EFB60 KDTARGET: Refreshing KD connection *** Fatal System Error: 0x0000001a (0x0000000000001240,0xFFFFBD046C12D640,0xFFFFE20000000000,0x0000000000000000) 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 22:53:25.414 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`003f2018). Type ".hh dbgerr001" for details Loading unloaded module list ...... ERROR: FindPlugIns 8007007b ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* MEMORY_MANAGEMENT (1a) # Any other values for parameter 1 must be individually examined. Arguments: Arg1: 0000000000001240, The subtype of the BugCheck. Arg2: ffffbd046c12d640 Arg3: ffffe20000000000 Arg4: 0000000000000000 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. PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`003f2018). Type ".hh dbgerr001" for details KEY_VALUES_STRING: 1 Key : Analysis.CPU.mSec Value: 4609 Key : Analysis.Elapsed.mSec Value: 41822 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: 52339 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: 0x1a Key : Bugcheck.Code.LegacyAPI Value: 0x1a Key : Bugcheck.Code.TargetModel Value: 0x1a Key : Failure.Bucket Value: 0x1a_1240_obpcallback!PteHookManager::fn_pa_to_va Key : Failure.Hash Value: {8b1bf815-3433-a8c2-3b59-c418f61f9c76} 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: 1a BUGCHECK_P1: 1240 BUGCHECK_P2: ffffbd046c12d640 BUGCHECK_P3: ffffe20000000000 BUGCHECK_P4: 0 FAULTING_THREAD: ffffbd046c162080 PROCESS_NAME: oxygen.exe STACK_TEXT: fffffc89`cd605028 fffff805`7b111882 : fffffc89`cd605190 fffff805`7af7c940 00000000`00000000 00000000`00000000 : nt!DbgBreakPointWithStatus fffffc89`cd605030 fffff805`7b110e66 : 00000000`00000003 fffffc89`cd605190 fffff805`7b00a0c0 00000000`0000001a : nt!KiBugCheckDebugBreak+0x12 fffffc89`cd605090 fffff805`7aff5317 : 00000000`00000000 00000000`00001000 00000000`00000000 00000000`00000000 : nt!KeBugCheck2+0x946 fffffc89`cd6057a0 fffff805`7b02e1b6 : 00000000`0000001a 00000000`00001240 ffffbd04`6c12d640 ffffe200`00000000 : nt!KeBugCheckEx+0x107 fffffc89`cd6057e0 fffff805`802b2048 : 00000000`00000000 ffffbd04`6545f1c0 00000000`00000000 ffffe200`00000008 : nt!MmBuildMdlForNonPagedPool+0x1e4d16 fffffc89`cd6058a0 fffff805`802b28ae : ffffbd04`64f74000 00000001`747f8000 00000000`00450000 fffff805`7b2ac96b : obpcallback!PteHookManager::fn_pa_to_va+0x138 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 486] fffffc89`cd605910 fffff805`802b1a6c : ffffbd04`64f74000 00000001`747f8000 fffffc89`cd605a20 fffff805`7de94000 : obpcallback!PteHookManager::get_page_table+0x9e [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 539] fffffc89`cd6059b0 fffff805`802b21ff : ffffbd04`64f74000 00000000`00001d00 fffff805`7b2efb60 00000000`00000035 : obpcallback!PteHookManager::fn_isolation_pages+0x10c [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 875] fffffc89`cd605ad0 fffff805`802b1344 : ffffbd04`64f74000 00000000`00001d00 fffffc89`cd605bb0 fffff805`802b1500 : obpcallback!PteHookManager::fn_pte_inline_hook_bp_pg+0x4f [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1015] fffffc89`cd605b90 fffff805`802b13d4 : fffff805`802b3d20 00000000`00001d00 00000000`00000000 fffff805`75eaf180 : obpcallback!InstallHook+0xa4 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1343] fffffc89`cd605be0 fffff805`7aea29a5 : 00000000`00001d00 fffff805`802b13a0 00000000`00001d00 ffffb90d`00000001 : obpcallback!InstallHookWorker+0x34 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1371] fffffc89`cd605c10 fffff805`7affc868 : fffff805`75eaf180 ffffbd04`6c162080 fffff805`7aea2950 fffff805`00000000 : nt!PspSystemThreadStartup+0x55 fffffc89`cd605c60 00000000`00000000 : fffffc89`cd606000 fffffc89`cd600000 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: 486 FAULTING_SOURCE_CODE: 482: 483: PVOID va = nullptr; 484: __try { 485: MmBuildMdlForNonPagedPool(pMdl); > 486: MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess); 487: va = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority); 488: 489: if (va) { 490: // ?¨ª????MDL???? 491: if (m_MdlCount < MAX_MDL_CACHE) { SYMBOL_NAME: obpcallback!PteHookManager::fn_pa_to_va+138 MODULE_NAME: obpcallback IMAGE_NAME: obpcallback.sys STACK_COMMAND: .process /r /p 0xffffbd046545f1c0; .thread 0xffffbd046c162080 ; kb BUCKET_ID_FUNC_OFFSET: 138 FAILURE_BUCKET_ID: 0x1a_1240_obpcallback!PteHookManager::fn_pa_to_va OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {8b1bf815-3433-a8c2-3b59-c418f61f9c76} Followup: MachineOwner --------- 改为又出问题了,你找找问题。一直是访问有问题。应该是代码有流程出问题了。代码如下:#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) // 在类定义前添加以下常量定义 #define DIRECT_MAPPING_BASE 0xFFFF000000000000ULL // 页表标志位 #define PTE_GLOBAL_FLAG (1ULL << 8) #define PDE_GLOBAL_FLAG (1ULL << 8) #define PDPTE_GLOBAL_FLAG (1ULL << 8) #define PTE_WRITABLE_FLAG (1ULL << 1) #define PTE_NOEXECUTE_FLAG (1ULL << 63) #define PDE_2MB_PAGE_FLAG (1ULL << 7) #define PDPTE_1GB_PAGE_FLAG (1ULL << 7) 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(); // 添加析构函数声明 bool fn_modify_pte_permission(HANDLE process_id, void* addr, bool make_writable); UINT64 get_process_cr3(PEPROCESS process); 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); UINT64 m_OriginalPermissions; struct MdlEntry { PVOID va; PMDL mdl; }; static constexpr UINT32 MAX_MDL_CACHE = 16; // 添加常量定义 MdlEntry m_MdlCache[MAX_MDL_CACHE]; // MDL 缓存数组 UINT32 m_MdlCount = 0; // 当前缓存数量 // 添加 fn_unmap_pa 声明 void fn_unmap_pa(PVOID va); 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; void PteHookManager::fn_unmap_pa(PVOID va) { if (!va) return; // 查找 MDL 映射 for (UINT32 i = 0; i < m_MdlCount; i++) { if (m_MdlCache[i].va == va) { MmUnmapLockedPages(va, m_MdlCache[i].mdl); IoFreeMdl(m_MdlCache[i].mdl); // 从缓存中移除 if (i < m_MdlCount - 1) { RtlMoveMemory(&m_MdlCache[i], &m_MdlCache[i + 1], (m_MdlCount - i - 1) * sizeof(MdlEntry)); } m_MdlCount--; return; } } // 尝试释放 MmMapIoSpace 映射 PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); if (physAddr.QuadPart != 0) { MmUnmapIoSpace(va, PAGE_SIZE); } } UINT64 PteHookManager::get_process_cr3(PEPROCESS process) { #if defined(_AMD64_) // Windows 10/11 的CR3偏移通常是0x28 return *(UINT64*)((PUCHAR)process + 0x28); #elif defined(_X86_) return *(UINT64*)((PUCHAR)process + 0x18); #endif } // 修改析构函数释放所有 MDL 资源 PteHookManager::~PteHookManager() { // 清理 MDL 缓存 for (UINT32 i = 0; i < m_MdlCount; i++) { if (m_MdlCache[i].va) { MmUnmapLockedPages(m_MdlCache[i].va, m_MdlCache[i].mdl); IoFreeMdl(m_MdlCache[i].mdl); } } m_MdlCount = 0; // 清理其他资源 if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = 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; PVOID mappedVa = MmMapIoSpace(physAddr, PAGE_SIZE, MmNonCached); if (mappedVa) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PA] MmMapIoSpace映射成功: PA=0x%llx -> VA=0x%p\n", pa, mappedVa); return mappedVa; } // 3. 低4GB直接映射 if (physAddr.QuadPart < 0x100000000) { PVOID directVa = (PVOID)(physAddr.QuadPart + DIRECT_MAPPING_BASE); if (MmIsAddressValid(directVa)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PA] 低4GB直接映射成功: PA=0x%llx -> VA=0x%p\n", pa, directVa); return directVa; } } // 4. 使用MDL映射 PMDL pMdl = IoAllocateMdl(nullptr, PAGE_SIZE, FALSE, FALSE, NULL); if (!pMdl) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PA] MDL分配失败: PA=0x%llx\n", pa); return nullptr; } PVOID va = nullptr; __try { MmBuildMdlForNonPagedPool(pMdl); MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess); va = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority); if (va) { // 添加到MDL缓存 if (m_MdlCount < MAX_MDL_CACHE) { m_MdlCache[m_MdlCount].va = va; m_MdlCache[m_MdlCount].mdl = pMdl; m_MdlCount++; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PA] MDL映射缓存成功: PA=0x%llx -> VA=0x%p (缓存索引: %d)\n", pa, va, m_MdlCount - 1); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL, "[PA] MDL缓存已满,临时映射: PA=0x%llx -> VA=0x%p\n", pa, va); return va; // 临时映射,调用者需负责释放 } } } __except (EXCEPTION_EXECUTE_HANDLER) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PA] 物理地址转换异常: PA=0x%llx, 代码: 0x%X\n", pa, GetExceptionCode()); IoFreeMdl(pMdl); return nullptr; } if (!va) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PA] MDL映射失败: PA=0x%llx\n", pa); IoFreeMdl(pMdl); } return va; } 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.OriginalPdpte & PDPTE_1GB_PAGE_FLAG) ? 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.OriginalPde & PDE_2MB_PAGE_FLAG) ? 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; // 优先使用 MmMapIoSpace PVOID mappedVa = MmMapIoSpace(physAddr, PAGE_SIZE, MmNonCached); if (mappedVa) { return mappedVa; } // 低4GB直接映射 if (physAddr.QuadPart < 0x100000000) { return (PVOID)(physAddr.QuadPart + 0xFFFF000000000000); } // 回退到MDL方式 PMDL pMdl = IoAllocateMdl(nullptr, PAGE_SIZE, FALSE, FALSE, NULL); if (!pMdl) return nullptr; MmBuildMdlForNonPagedPool(pMdl); PVOID va = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority); if (va) { // 添加到MDL缓存 if (m_MdlCount < MAX_MDL_CACHE) { m_MdlCache[m_MdlCount++] = { va, pMdl }; } return va; } IoFreeMdl(pMdl); return nullptr; }; // 安全获取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 { UINT64 pt_pfn = (Table.OriginalPde & ~0xFFF) >> 12; pt_source_va = get_va_from_pfn(pt_pfn); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 常规模式: 源PFN=0x%llx, 源VA=%p\n", pt_pfn, pt_source_va); } if (!pt_source_va) { logger("无法获取PT源虚拟地址", true); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); return false; } // 复制PT数据(带异常处理) __try { memcpy(VaPt, pt_source_va, PAGE_SIZE); } __except (EXCEPTION_EXECUTE_HANDLER) { logger("复制PT数据时发生异常", true, GetExceptionCode()); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); fn_unmap_pa(pt_source_va); return false; } fn_unmap_pa(pt_source_va); // 释放映射 // 安全获取PDT源地址 UINT64 pdt_pfn = (Table.OriginalPdpte & ~0xFFF) >> 12; void* pdt_source_va = get_va_from_pfn(pdt_pfn); if (!pdt_source_va) { logger("无法获取PDT源虚拟地址", true); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); return false; } __try { memcpy(VaPdt, pdt_source_va, PAGE_SIZE); } __except (EXCEPTION_EXECUTE_HANDLER) { logger("复制PDT数据时发生异常", true, GetExceptionCode()); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); fn_unmap_pa(pdt_source_va); return false; } fn_unmap_pa(pdt_source_va); // 安全获取PDPT源地址 UINT64 pdpt_pfn = (Table.OriginalPml4e & ~0xFFF) >> 12; void* pdpt_source_va = get_va_from_pfn(pdpt_pfn); if (!pdpt_source_va) { logger("无法获取PDPT源虚拟地址", true); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); return false; } __try { memcpy(VaPdpt, pdpt_source_va, PAGE_SIZE); } __except (EXCEPTION_EXECUTE_HANDLER) { logger("复制PDPT数据时发生异常", true, GetExceptionCode()); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); fn_unmap_pa(pdpt_source_va); return false; } fn_unmap_pa(pdpt_source_va); // 设置新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(安全方式) PHYSICAL_ADDRESS pml4_phys; pml4_phys.QuadPart = cr3_val & ~0xFFF; UINT64* new_pml4 = (UINT64*)fn_pa_to_va(pml4_phys.QuadPart); if (!new_pml4) { logger("无法获取PML4虚拟地址", true); MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); return false; } // 保存原始PML4E值 UINT64 original_pml4e = new_pml4[pml4e_index]; UINT64 new_pml4e = (original_pml4e & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); // 原子更新PML4E KIRQL oldIrql = DisableWriteProtection(); new_pml4[pml4e_index] = new_pml4e; EnableWriteProtection(oldIrql); // 刷新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_pml4e); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; NTSTATUS status = PsLookupProcessByProcessId(process_id, &Process); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ISOL] 查找进程失败: PID=%d\n", HandleToULong(process_id)); return false; } KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; // 获取目标进程CR3 UINT64 target_cr3 = get_process_cr3(Process); if (target_cr3 == 0) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return false; } // 获取页表项 status = get_page_table(target_cr3, Table); if (!NT_SUCCESS(status)) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ISOL] 获取页表失败: VA=0x%p\n", AlignAddr); return false; } // 检查是否已隔离(G位为0) UINT64* pteEntry = nullptr; UINT64 globalFlag = 0; if (Table.PteAddress) { pteEntry = &Table.PteAddress->value; globalFlag = PTE_GLOBAL_FLAG; } else if (Table.PdeAddress && Table.IsLargePage) { pteEntry = &Table.PdeAddress->value; globalFlag = PDE_GLOBAL_FLAG; } else if (Table.PdpteAddress && Table.Is1GBPage) { pteEntry = &Table.PdpteAddress->value; globalFlag = PDPTE_GLOBAL_FLAG; } else { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ISOL] 无法确定页表级别\n"); return false; } UINT64 currentValue = *pteEntry; if ((currentValue & globalFlag) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[ISOL] 页面已隔离: VA=0x%p\n", AlignAddr); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } // 清除G位(Global标志) UINT64 newValue = currentValue & ~globalFlag; InterlockedExchange64((LONG64*)pteEntry, newValue); // 刷新TLB __invlpg(AlignAddr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[ISOL] 页面隔离成功: VA=0x%p, 原始值=0x%llx, 新值=0x%llx\n", AlignAddr, currentValue, newValue); 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] 修改PTE权限为可写 if (!fn_modify_pte_permission(process_id, *ori_addr, true)) { return false; } // [3] 获取目标进程上下文 PEPROCESS targetProcess; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &targetProcess))) { return false; } KAPC_STATE apcState; KeStackAttachProcess(targetProcess, &apcState); // [4] 构造跳转指令 JMP_ABS jmpCmd = {}; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // FF25 00000000 jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); // [5] 直接写入被隔离页 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); // [6] 恢复原始权限 fn_modify_pte_permission(process_id, *ori_addr, false); // [7] 记录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++; } // [8] 清理 KeUnstackDetachProcess(&apcState); ObDereferenceObject(targetProcess); return success; } bool PteHookManager::fn_modify_pte_permission(HANDLE process_id, void* addr, bool make_writable) { PEPROCESS Process; NTSTATUS status = PsLookupProcessByProcessId(process_id, &Process); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PERM] 查找进程失败: PID=%d\n", HandleToULong(process_id)); return false; } KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; // 获取目标进程CR3 UINT64 target_cr3 = get_process_cr3(Process); if (target_cr3 == 0) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return false; } // 获取页表项 status = get_page_table(target_cr3, Table); if (!NT_SUCCESS(status) || !Table.PteAddress) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PERM] 获取页表失败: VA=0x%p\n", AlignAddr); return false; } UINT64 pteValue = Table.PteAddress->value; UINT64 newPte; UINT64 permMask = PTE_WRITABLE_FLAG | PTE_NOEXECUTE_FLAG; if (make_writable) { // 保存原始权限 m_OriginalPermissions = pteValue & permMask; // 设置可写位并清除NX位 newPte = (pteValue & ~permMask) | PTE_WRITABLE_FLAG; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PERM] 修改权限为可写: VA=0x%p, 原始PTE=0x%llx, 新PTE=0x%llx\n", addr, pteValue, newPte); } else { // 恢复原始权限 newPte = (pteValue & ~permMask) | (m_OriginalPermissions & permMask); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PERM] 恢复原始权限: VA=0x%p, 原始PTE=0x%llx, 新PTE=0x%llx\n", addr, pteValue, newPte); } // 原子修改PTE InterlockedExchange64((LONG64*)&Table.PteAddress->value, newPte); // 刷新TLB __invlpg(addr); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } 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; }
07-10
### `UNREFERENCED_PARAMETER` 的作用和使用场景 在驱动开发中,函数参数可能不会在函数体内被使用,但编译器会发出关于未使用参数的警告,尤其是在启用 `/W4` 级别警告的情况下。`UNREFERENCED_PARAMETER` 宏被用于抑制这些警告,确保代码在高警告级别下仍能顺利编译。 该宏定义在 `winnt.h` 头文件中,其展开形式为 `(P)`,其中 `P` 是传递的参数或表达式。它本质上是一个空操作,仅用于告知编译器该参数是故意未使用的,从而避免编译器报出无关警告[^1]。 例如,在 WDM 驱动中,`DriverEntry` 函数的两个参数 `DriverObject` 和 `RegistryPath` 在某些实现中可能未被使用,此时可以使用 `UNREFERENCED_PARAMETER` 来避免警告: ```cpp NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(RegistryPath); // 驱动初始化逻辑 return STATUS_SUCCESS; } ``` 在实际开发中,特别是在调试或重构代码阶段,开发者可能会临时移除某些参数的使用,此时该宏可以防止编译器发出不必要的警告,同时保留参数以便后续恢复使用。 ### 原理实现 `UNREFERENCED_PARAMETER(P)` 的实现本质上是一个强制类型转换表达式 `(void)(P)`,它将参数 `P` 转换为 `void` 类型,表示该变量被“使用”,但不执行任何操作。这种方式不会产生实际的运行时开销,仅用于满足编译器的语法检查。 其等效实现如下: ```cpp #define UNREFERENCED_PARAMETER(P) (void)(P) ``` 无论参数是基本类型还是指针类型,该宏都能安全地处理,避免了编译器对未使用变量的警告。 --- ### 示例代码 以下是一个使用 `UNREFERENCED_PARAMETER` 的完整驱动函数示例: ```cpp NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) { UNREFERENCED_PARAMETER(DeviceObject); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } ``` 在此函数中,`DeviceObject` 参数未被使用,因此使用 `UNREFERENCED_PARAMETER` 来避免编译器警告。 --- ### 总结 `UNREFERENCED_PARAMETER` 在驱动开发中是一个常见的宏,用于抑制编译器关于未使用参数的警告。它在 WDM 驱动和 KMDF 驱动中都适用,尤其适用于调试、重构或接口定义中暂时不需要使用某些参数的情况。其原理是通过将参数转换为 `void` 类型来模拟“使用”行为,从而避免编译器报错。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值