MmIsAddressValid

kd> u MmIsAddressValid

80511990 8bff            mov     edi,edi
80511992 55              push    ebp
80511993 8bec            mov     ebp,esp
80511995 51              push    ecx
80511996 51              push    ecx
80511997 8b4d08          mov     ecx,dword ptr [ebp+8]//传进来的参数,就是一个地址,假定为address
8051199a 56              push    esi
8051199b 8bc1            mov     eax,ecx//第几个参数?
8051199d c1e812          shr     eax,12h
805119a0 bef83f0000      mov     esi,3FF8h
805119a5 23c6            and     eax,esi
805119a7 2d0000a03f      sub     eax,3FA00000h
//  PDE==address'=address>>12h+3ff8h-3FA00000h
805119ac 8b10            mov     edx,dword ptr [eax]//取得计算后的address地址,address'应该是到达一个结构,去第一项给edx
805119ae 8b4004          mov     eax,dword ptr [eax+4]//去第二项给eax
//一系列的换算
805119b1 8945fc          mov     dword ptr [ebp-4],eax//将第二项送入一个局部变量,假定为param1=[address'+4];
805119b4 8bc2            mov     eax,edx
805119b6 57              push    edi
805119b7 83e001          and     eax,1//eax=[address]+1;,标志Present位
805119ba 33ff            xor     edi,edi
805119bc 0bc7            or      eax,edi//[address']+1为0的话就是无效的地址,;如果页面存在标志Present位 = 0,表示该页没有加载到对应的

805119be 7461            je      nt!MmIsAddressValid+0x91 (80511a21)//相等的话就跳到结尾处,置al为0,无效的地址

805119c0 bf80000000      mov     edi,80h
805119c5 23d7            and     edx,edi//edx=[address]+80h,取Page size位,Page size位 = 1,表示LargePage
805119c7 6a00            push    0
805119c9 8955f8          mov     dword ptr [ebp-8],edx//假定为param2=[address']+80h;
805119cc 58              pop     eax //eax=0;
805119cd 7404            je      nt!MmIsAddressValid+0x43 (805119d3)//跳805119d3,最高位 = 0 ,非LargePage
805119cf 85c0            test    eax,eax
805119d1 7452            je      nt!MmIsAddressValid+0x95 (80511a25)//地址有效的最高位 = 1 ,LargePage


805119d3 c1e909          shr     ecx,9  //ecx为我们传进来的参数address,。即地址中的高20位代表pte偏移,低12位表示属性
805119d6 81e1f8ff7f00    and     ecx,7FFFF8h 
805119dc 8b81040000c0    mov     eax,dword ptr [ecx-3FFFFFFCh]//
805119e2 81e900000040    sub     ecx,40000000h //PTE=address''=address>>9+7ffff8h-40000000h,减40000000h就是加0xC0000000
805119e8 8b11            mov     edx,dword ptr [ecx] //将address''的地址传给edx edx=[address''] ,PTE context
805119ea 8945fc          mov     dword ptr [ebp-4],eax //param1=[address>>9-3FFFFFFCh]
805119ed 53              push    ebx    
805119ee 8bc2            mov     eax,edx
805119f0 33db            xor     ebx,ebx
805119f2 83e001          and     eax,1  eax=[address'']+1;, pte 页面存在标志 Present位

805119f5 0bc3            or      eax,ebx
805119f7 5b              pop     ebx  // [address'']+1为0的话就无效 标志 Present位不存在无效
805119f8 7427            je      nt!MmIsAddressValid+0x91 (80511a21)//无效
805119fa 23d7            and     edx,edi   edx=[address'']+80h
805119fc 6a00            push    0
805119fe 8955f8          mov     dword ptr [ebp-8],edx //  param2=[address'']+80h
80511a01 58              pop     eax  // eax与edx相比较   
80511a02 7421            je      nt!MmIsAddressValid+0x95 (80511a25)//有效
80511a04 85c0            test    eax,eax //还是跳、、
80511a06 751d            jne     nt!MmIsAddressValid+0x95 (80511a25)//有效
80511a08 23ce            and     ecx,esi
805119fc 6a00            push    0
805119fe 8955f8          mov     dword ptr [ebp-8],edx
80511a01 58              pop     eax
80511a02 7421            je      nt!MmIsAddressValid+0x95 (80511a25)//有效
80511a04 85c0            test    eax,eax
80511a06 751d            jne     nt!MmIsAddressValid+0x95 (80511a25)//有效
80511a08 23ce            and     ecx,esi
80511a0a 8b89000060c0    mov     ecx,dword ptr [ecx-3FA00000h]
80511a10 b881000000      mov     eax,81h
80511a15 23c8            and     ecx,eax
80511a17 33d2            xor     edx,edx
80511a19 3bc8            cmp     ecx,eax
80511a1b 7508            jne     nt!MmIsAddressValid+0x95 (80511a25)//有效
80511a1d 85d2            test    edx,edx
80511a1f 7504            jne     nt!MmIsAddressValid+0x95 (80511a25)//有效


80511a21 32c0            xor     al,al
80511a23 eb02            jmp     nt!MmIsAddressValid+0x97 (80511a27)

80511a25 b001            mov     al,1
80511a27 5f              pop     edi
80511a28 5e              pop     esi
80511a29 c9              leave
80511a2a c20400          ret     4
80511a2d cc              int     3
80511a2e cc              int     3
80511a2f cc              int     3
80511a30 cc              int     3
80511a31 cc              int     3
PAE模式
int PDE = ((lVirtualAddress>>21)<<3) & 0x3FF8 + 0xC0600000;
int PTE = ((lVirtualAddress>>12)<<3) & 0x7FFFF8 + 0xC0000000;

//从网上找的一个C代码
BOOLEAN MmIsAddressValid ( PVOID VirtualAddress )
{
BYTE PresentSign = 0x1;
BYTE PageSizeSign = 0x80;
BYTE PresentAndPageSizeSign = 0x81;
PVOID lVirtualAddress;
ULONG PDE,PDEContext;
ULONG PTE,PTEContext;
lVirtualAddress = VirtualAddress;
PDE = (((ULONG)lVirtualAddress>>21)<<3) & 0x3FF8 + 0xC0600000;
PDEContext = (ULONG)*(PVOID)PDE;
if(!(PDEContext & PresentSign))
return FALSE;

if(PDEContext & PageSizeSign)
return TRUE;

PTE = (((ULONG)lVirtualAddress>>12)<<3) & 0x7FFFF8 + 0xC0000000;
PTEContext = (ULONG)*(PVOID)PTE;
if(!(PTEContext & PresentSign ))
return FALSE;

if(!(PTEContext & PageSizeSign))
return TRUE;
else
{
PDE = (ULONG)PTE & 0x3ff8 + 0xc0600000;
PDEContext = (ULONG)*(PVOID)PDE;
if(PDEContext & PresentAndPageSizeSign)
return TRUE;

}

return FALSE;
}

 

 

 

kd> !pte
               VA 00000000
PDE at 00000000C0600000    PTE at 00000000C0000000
contains 0000000002C80067  contains 0000000000000000
pfn 2c80       ---DA--UWEV   

******************************************************************************* 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 &#39;HKOB&#39; 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), &#39;tpHk&#39;)); 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] = &#39;\0&#39;; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == &#39; &#39;) currentName[i] = &#39;\0&#39;; else if (currentName[i] != &#39;\0&#39;) 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] = &#39;\0&#39;; for (int i = 15; i >= 0; i--) { if (currentName[i] == &#39; &#39;) currentName[i] = &#39;\0&#39;; else if (currentName[i] != &#39;\0&#39;) 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, &#39;JmpP&#39;); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, &#39;tpHk&#39;); 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
#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 &#39;HKOB&#39; 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; UINT64 m_OriginalPermissions; }; 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; } } 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 } // 尝试释放 MmMapIoSpace 映射 PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); if (physAddr.QuadPart != 0) { MmUnmapIoSpace(va, PAGE_SIZE); } } // 修改析构函数释放所有 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; // 1. 验证物理地址有效性 if (!MmIsPhysicalAddressValid(physAddr)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PA] 物理地址无效: 0x%llx\n", pa); return nullptr; } // 2. 尝试使用MmMapIoSpace 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), &#39;tpHk&#39;)); 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] = &#39;\0&#39;; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == &#39; &#39;) currentName[i] = &#39;\0&#39;; else if (currentName[i] != &#39;\0&#39;) 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] = &#39;\0&#39;; for (int i = 15; i >= 0; i--) { if (currentName[i] == &#39; &#39;) currentName[i] = &#39;\0&#39;; else if (currentName[i] != &#39;\0&#39;) 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, &#39;JmpP&#39;); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, &#39;tpHk&#39;); 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; } 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0392 不能在成员函数 "PteHookManager::get_process_cr3" 的类外部重新声明该函数 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 326 错误(活动) E0065 应输入“;” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 326 错误(活动) E0020 未定义标识符 "MmIsPhysicalAddressValid" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 458 错误(活动) E0020 未定义标识符 "physAddr" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 337 修改错误
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值