PDE_PTE属性

该博客围绕修改0x8003F00C属性展开实验,拆分地址后,将线性地址8003f00c的PDE和PTE改为167,U/S改成1。实验得出应用程序不能访问高2G地址的原因是高2G的PDE的U/S被设为0,用户权限无法访问,还提及修改PDE PTE的U/S位为1。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

PDE 与PTE的P位同时为1,物理地址才有效。

在这里插入图片描述

实验 修改0x8003F00C属性

拆分地址:
8003f 00c
200 3f 00c
‭1000 0000 00 00 0011 1111 0000 0000 1100‬
在这里插入图片描述
实验修改了线性地址8003f00c的PDE 和PTE为167 把U/S改成了1

实验结论:为什么应用程序不能访问高2G地址?
因为高2G的PDE的U/S为设置成了0,用户权限不能访问。

修改PDE PTE的U/S位为1

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

[讨论][转帖][讨论][原创]windows Hook内核api,能过win10 22H2的pg 发表于: 2023-12-6 17:35 12258 举报 最近一直在思考如何hook内核函数而不触发pg,于是我在看雪找到一篇文章讲解如何hook内核函数不触发pg,链接:https://bbs.kanxue.com/thread-266781.htm。 文章并没有讲解思路,直接贴上代码,在看完他的代码后,我理解了其思路,发现代码有点冗长,存在一些多余的操作,不过这也给了我过pg的思路。 windows64位系统内核中内核函数线性地址对应的物理地址是pte里面的物理地址,是不是可以修改pte里面物理地址从而改变线性地址对应的物理地址,但是内核中的函数的pte里面的物理地址是全局的,只要一修改,其他进程也会受到影响。好在我们通过进程的Cr3找到进程的内核函数地址对应的PXE,这个PXE不是全局的,如果修改了PXE里面的值,该进程内核函数对应的物理地址也就变了,但是不会影响的其他进程。于是我们可以重构页表,通过修改PXE,PDPTEPDEPTE来修改该进程内核函数对应的物理地址,从而可以对该内核函数进行hook而不触发pg。大致做法如下图: 图片描述 图片描述 图片描述 我们可以通过映射物理内存到虚拟内存的方法来修改PXE,PDPTEPDEPTE。 这里一共两份源码,一份win7,一份win10,win10的源码针对2Mb大页的。 下面是源码: 支持win7 #include<ntifs.h> ULONG_PTR pPhyAddr[5] = { 0 }; typedef struct _HARDWARE_PTE { ULONG64 Valid : 1; ULONG64 Write : 1; ULONG64 Owner : 1; ULONG64 WriteThrough : 1; ULONG64 CacheDisable : 1; ULONG64 Accessed : 1; ULONG64 Dirty : 1; ULONG64 LargePage : 1; ULONG64 Global : 1; ULONG64 CopyOnWrite : 1; ULONG64 Prototype : 1; ULONG64 reserved0 : 1; ULONG64 PageFrameNumber : 36; ULONG64 reserved1 : 4; ULONG64 SoftwareWsIndex : 11; ULONG64 NoExecute : 1; } HARDWARE_PTE, *PHARDWARE_PTE; BOOLEAN InitHook(ULONG_PTR VirtualAddress_s, ULONG Pid, ULONG_PTR offset) { //1获取虚拟内存的PXE PDPTE pdepte的索引 ULONG PxeIndex = (VirtualAddress_s >> 0x27) & 0x1FF; UINT32 PPEIndex = (VirtualAddress_s >> 0x1E) & 0x1FF; //PPEIndex UINT32 PDEIndex = (VirtualAddress_s >> 0x15) & 0x1FF; //PDEIndex UINT32 PTEIndex = (VirtualAddress_s >> 0xC) & 0x1FF; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 //DbgBreakPoint(); //2 获取要hook进程的CR3 PEPROCESS pEprocess = NULL; NTSTATUS status = PsLookupProcessByProcessId(Pid, &pEprocess); if (!NT_SUCCESS(status)) { return 0; } ULONG_PTR Cr3PhyAddr = *(PULONG64)((ULONG64)pEprocess + KERNEL_CR3_OFFSET); PHYSICAL_ADDRESS Cr3 = { 0 }; Cr3.QuadPart = Cr3PhyAddr; ULONG_PTR VirtualAddresss = MmMapIoSpace(Cr3, PAGE_SIZE, MmNonCached);//由于Cr3是物理地址我们需要映射到虚拟内存中去 if (!VirtualAddresss) { return 0; } //3 构建页表 //*(PULONG64)(VirtualAddresss + PxeIndex * 8) |= 70; PHYSICAL_ADDRESS Low = { 0 }; PHYSICAL_ADDRESS High = { MAXULONG64 }; //ppe pPhyAddr[0] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); ULONG_PTR newPPEphy = MmGetPhysicalAddress(pPhyAddr[0]).QuadPart; ULONG_PTR PPEPhyAddr = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddresss + PxeIndex * 8))->PageFrameNumber) * 0x1000; PHYSICAL_ADDRESS temp = { 0 }; temp.QuadPart = PPEPhyAddr; ULONG_PTR VirtualAddress_PPE= MmMapIoSpace(temp, PAGE_SIZE, MmNonCached); memcpy(pPhyAddr[0], VirtualAddress_PPE, PAGE_SIZE); //pde pPhyAddr[1] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); ULONG_PTR newPDEphy= MmGetPhysicalAddress(pPhyAddr[1]).QuadPart; ULONG_PTR pdePhy= (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PPE + PPEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = pdePhy; ULONG_PTR VirtualAddress_PDE = MmMapIoSpace(temp,PAGE_SIZE, MmNonCached); memcpy(pPhyAddr[1], VirtualAddress_PDE, PAGE_SIZE); //pte pPhyAddr[2] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); ULONG_PTR newPTEphy = MmGetPhysicalAddress(pPhyAddr[2]).QuadPart; ULONG_PTR ptePhy = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PDE + PDEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = ptePhy; ULONG_PTR VirtualAddress_PTE = MmMapIoSpace(temp, PAGE_SIZE, MmNonCached); memcpy(pPhyAddr[2], VirtualAddress_PTE, PAGE_SIZE); //物理内存 pPhyAddr[3] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); ULONG_PTR newphy = MmGetPhysicalAddress(pPhyAddr[3]).QuadPart; ULONG_PTR Phy = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PTE + PTEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = Phy; ULONG_PTR VirtualAddress_PHY = MmMapIoSpace(temp, PAGE_SIZE, MmNonCached); memcpy(pPhyAddr[3], VirtualAddress_PHY, PAGE_SIZE); //ULONG_PTR ss3 = pPhyAddr[3]; //ULONG_PTR ss1 = pPhyAddr[1]; //ULONG_PTR ss2 = pPhyAddr[2]; //DbgBreakPoint(); //4 修改PXE PPE PDE PTE从而改变 ((PHARDWARE_PTE)(VirtualAddresss + PxeIndex * 8))->PageFrameNumber = newPPEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[0] + PPEIndex * 8))->PageFrameNumber = newPDEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[1] + PDEIndex * 8))->PageFrameNumber = newPTEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[2] + PTEIndex * 8))->PageFrameNumber = newphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[2] + PTEIndex * 8))->Write = 1; *(PUCHAR)(pPhyAddr[3] + offset + 0x27) = 0x90; *(PUCHAR)(pPhyAddr[3] + offset + 0x28) = 0x90; *(PUCHAR)(pPhyAddr[3] + offset + 0x29) = 0xc3; return TRUE; } VOID unstallHook() { 1 2 3 4 MmFreeContiguousMemory(pPhyAddr[0]); MmFreeContiguousMemory(pPhyAddr[1]); MmFreeContiguousMemory(pPhyAddr[2]); MmFreeContiguousMemory(pPhyAddr[3]); } VOID DriverUnload(PDRIVER_OBJECT pDriver) { unstallHook(); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRes) { pDriver->DriverUnload = DriverUnload; UNICODE_STRING ss = { 0 }; RtlInitUnicodeString(&ss, L"NtOpenProcess"); ULONG_PTR NtOpenAddr = MmGetSystemRoutineAddress(&ss); ULONG_PTR funcVir = NtOpenAddr & ~(0xfff); ULONG_PTR funcOffset = NtOpenAddr & 0xfff; InitHook(funcVir, 2280, funcOffset); //SetPTEHook(ssz); return STATUS_SUCCESS; } 当我附加到被我下钩子的进程,NtOpenProcess的结果在内存中是这样的: 图片描述 附加到我们没有HOOK的其他进程: 图片描述 在win7 64位系统中存在了5小时未发生pg。 我的这份源码纯粹是为了实验,封装的不太好,请谅解。 由于我刚学习64位系统内核没多久,可能文章会有一些错误,希望各位大佬能够指正。 对于win10,由于不能像win7用同样的方法映射页表的物理内存,我换了一种方式,且这次是2Mb的大页,细节有很多发生了变化,但思路还是一样的,我没有完善卸载函数,卸载的时候会蓝屏。 下面是源码: ULONG_PTR pPhyAddr[5] = { 0 }; ULONG IsPdeLager = 0; ULONG_PTR newPPEphy = 0; //ULONG_PTR pPhyAddr[5] = { 0 }; ULONG_PTR newPDEphy = 0; ULONG_PTR newPTEphy = 0; ULONG_PTR newphy = 0; typedef struct _HARDWARE_PTE { ULONG64 Valid : 1; ULONG64 Write : 1; ULONG64 Owner : 1; ULONG64 WriteThrough : 1; ULONG64 CacheDisable : 1; ULONG64 Accessed : 1; ULONG64 Dirty : 1; ULONG64 LargePage : 1; ULONG64 Global : 1; ULONG64 CopyOnWrite : 1; ULONG64 Prototype : 1; ULONG64 reserved0 : 1; ULONG64 PageFrameNumber : 36; ULONG64 reserved1 : 4; ULONG64 SoftwareWsIndex : 11; ULONG64 NoExecute : 1; } HARDWARE_PTE, *PHARDWARE_PTE; BOOLEAN InitHook(ULONG_PTR VirtualAddress_s, ULONG Pid, ULONG_PTR offset) { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 //1获取虚拟内存的PXE PDPTE pdepte的索引 ULONG PxeIndex = (VirtualAddress_s >> 0x27) & 0x1FF; UINT32 PPEIndex = (VirtualAddress_s >> 0x1E) & 0x1FF; //PPEIndex UINT32 PDEIndex = (VirtualAddress_s >> 0x15) & 0x1FF; //PDEIndex UINT32 PTEIndex = (VirtualAddress_s >> 0xC) & 0x1FF; //DbgBreakPoint(); //2 获取要hook进程的CR3 PEPROCESS pEprocess = NULL; NTSTATUS status = PsLookupProcessByProcessId(Pid, &pEprocess); if (!NT_SUCCESS(status)) { return 0; } HANDLE hMemory = NULL; UNICODE_STRING unName = { 0 }; RtlInitUnicodeString(&unName, L"\\Device\\PhysicalMemory"); OBJECT_ATTRIBUTES obj; InitializeObjectAttributes(&obj, &unName, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwOpenSection(&hMemory, SECTION_ALL_ACCESS, &obj); if (!NT_SUCCESS(status)) { return 0; } SIZE_T sizeView = PAGE_SIZE; PVOID sectionObj = NULL; status = ObReferenceObjectByHandle(hMemory, SECTION_ALL_ACCESS, NULL, KernelMode, &sectionObj, NULL); if (!NT_SUCCESS(status)) { return status; } ULONG_PTR Cr3PhyAddr = *(PULONG64)((ULONG64)pEprocess + KERNEL_CR3_OFFSET)&~(0xf); PHYSICAL_ADDRESS Cr3 = { 0 }; Cr3.QuadPart = Cr3PhyAddr; ULONG_PTR VirtualAddresss = NULL; status = ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddresss, 0, PAGE_SIZE, &Cr3, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); //ULONG_PTR VirtualAddresss = MmMapIoSpace(Cr3, PAGE_SIZE, MmNonCached);//由于Cr3是物理地址我们需要映射到虚拟内存中去 if (!NT_SUCCESS(status)) { return 0; } //3 构建页表 //*(PULONG64)(VirtualAddresss + PxeIndex * 8) |= 70; PHYSICAL_ADDRESS Low = { 0 }; PHYSICAL_ADDRESS High = { MAXULONG64 }; //ppe do { pPhyAddr[0] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); newPPEphy = MmGetPhysicalAddress(pPhyAddr[0]).QuadPart; ULONG_PTR PPEPhyAddr = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddresss + PxeIndex * 8))->PageFrameNumber) * 0x1000; PHYSICAL_ADDRESS temp = { 0 }; temp.QuadPart = PPEPhyAddr; ULONG_PTR VirtualAddress_PPE = NULL; ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddress_PPE, 0, PAGE_SIZE, &temp, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); memcpy(pPhyAddr[0], VirtualAddress_PPE, PAGE_SIZE); //pde pPhyAddr[1] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); newPDEphy = MmGetPhysicalAddress(pPhyAddr[1]).QuadPart; ULONG_PTR pdePhy = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PPE + PPEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = pdePhy; ULONG_PTR VirtualAddress_PDE = NULL; ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddress_PDE, 0, PAGE_SIZE, &temp, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); memcpy(pPhyAddr[1], VirtualAddress_PDE, PAGE_SIZE); //pte ULONG_PTR ptePhy = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PDE + PDEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = ptePhy; if (((PHARDWARE_PTE)(VirtualAddress_PDE + PDEIndex * 8))->LargePage == 1) { pPhyAddr[2] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE* 1024, Low, High, Low, MmCached); memset(pPhyAddr[2], 0, PAGE_SIZE * 1024); ULONG_PTR Real = MmGetPhysicalAddress(pPhyAddr[2]).QuadPart; ULONG_PTR Real1 = Real; ULONG_PTR Realtemp = 0; if (Real == 0) { MmFreeContiguousMemory(pPhyAddr[0]); MmFreeContiguousMemory(pPhyAddr[1]); MmFreeContiguousMemory(pPhyAddr[2]); return FALSE; } ULONG i = 0; for (i = 0; i < 1024; i++) { Real += PAGE_SIZE; //Real &= 0x1fffff; Realtemp = Real & 0x1fffff; if (!Realtemp) break; } DbgBreakPoint(); pPhyAddr[2] += PAGE_SIZE * (i+1); newPTEphy = MmGetPhysicalAddress(pPhyAddr[2]).QuadPart; ULONG_PTR VirtualAddress_PTE = NULL; sizeView = PAGE_SIZE * 0x200; ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddress_PTE, 0, PAGE_SIZE, &temp, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); memcpy(pPhyAddr[2], VirtualAddress_s &~(0x1fffff), PAGE_SIZE*0x200); ((PHARDWARE_PTE)(pPhyAddr[0] + PPEIndex * 8))->PageFrameNumber = newPDEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[1] + PDEIndex * 8))->PageFrameNumber = newPTEphy >> 12; //((PHARDWARE_PTE)(pPhyAddr[2] + PTEIndex * 8))->Write = 1; ULONG_PTR newOffset = (VirtualAddress_s & 0x1ff000) + offset; //((PHARDWARE_PTE)(pPhyAddr[1] + PTEIndex * 8))->Write = 1; *(PUCHAR)(pPhyAddr[2] + newOffset + 0x27) = 0x90; *(PUCHAR)(pPhyAddr[2] + newOffset + 0x28) = 0x90; *(PUCHAR)(pPhyAddr[2] + newOffset + 0x29) = 0xc3; ULONG_PTR ss = pPhyAddr[2]; ULONG_PTR ss2 = VirtualAddress_s & ~(0x1fffff); IsPdeLager = 1; break; } pPhyAddr[2] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); newPTEphy = MmGetPhysicalAddress(pPhyAddr[2]).QuadPart; ULONG_PTR VirtualAddress_PTE = NULL; ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddress_PTE, 0, PAGE_SIZE, &temp, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); memcpy(pPhyAddr[2], VirtualAddress_PTE, PAGE_SIZE); //物理内存 pPhyAddr[3] = (ULONG_PTR)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached); newphy = MmGetPhysicalAddress(pPhyAddr[3]).QuadPart; ULONG_PTR Phy = (ULONG_PTR)(((PHARDWARE_PTE)(VirtualAddress_PTE + PTEIndex * 8))->PageFrameNumber) * 0x1000; temp.QuadPart = Phy; ULONG_PTR VirtualAddress_PHY = NULL; ZwMapViewOfSection(hMemory, NtCurrentProcess(), &VirtualAddress_PHY, 0, PAGE_SIZE, &temp, &sizeView, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE); memcpy(pPhyAddr[3], VirtualAddress_PHY, PAGE_SIZE); } while (0); //ULONG_PTR ss3 = pPhyAddr[3]; //ULONG_PTR ss1 = pPhyAddr[1]; //ULONG_PTR ss2 = pPhyAddr[2]; //DbgBreakPoint(); //4 修改PXE PPE PDE PTE从而改变 if (IsPdeLager) { ((PHARDWARE_PTE)(VirtualAddresss + PxeIndex * 8))->PageFrameNumber = newPPEphy >> 12; return TRUE; } ((PHARDWARE_PTE)(VirtualAddresss + PxeIndex * 8))->PageFrameNumber = newPPEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[0] + PPEIndex * 8))->PageFrameNumber = newPDEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[1] + PDEIndex * 8))->PageFrameNumber = newPTEphy >> 12; ((PHARDWARE_PTE)(pPhyAddr[2] + PTEIndex * 8))->PageFrameNumber = newphy >> 12; return TRUE; }; VOID unstallHook() { if (IsPdeLager) { MmFreeContiguousMemory(pPhyAddr[0]); MmFreeContiguousMemory(pPhyAddr[1]); MmFreeContiguousMemory(pPhyAddr[2]); return; } 1 2 3 4 //MmFreeContiguousMemory(pPhyAddr[0]); //MmFreeContiguousMemory(pPhyAddr[1]); //MmFreeContiguousMemory(pPhyAddr[2]); //MmFreeContiguousMemory(pPhyAddr[3]); } VOID DriverUnload(PDRIVER_OBJECT pDriver) { unstallHook(); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRes) { pDriver->DriverUnload = DriverUnload; PKLDR_DATA_TABLE_ENTRY pKldr = (PKLDR_DATA_TABLE_ENTRY)pDriver->DriverSection; pKldr->Flags |= 0x20; //NTSTATUS status = PsSetCreateProcessNotifyRoutine(ProcessNotifyRoutine, FALSE); UNICODE_STRING ss = { 0 }; RtlInitUnicodeString(&ss, L"NtOpenProcess"); ULONG_PTR NtOpenAddr = MmGetSystemRoutineAddress(&ss); ULONG_PTR funcVir = NtOpenAddr & ~(0xfff); ULONG_PTR funcOffset = NtOpenAddr & 0xfff; InitHook(funcVir, 8568, funcOffset); //SetPTEHook(ssz); return STATUS_SUCCESS; } 附加到我们hook的进程: 图片描述 附加到其他进程: 图片描述 实验结果和win7是一样的,同样也没有出发PG。 根据上面的帖子,总结一个适用于win10 10240的页表hook
最新发布
07-16
#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) #define _WIN32_WINNT 0x0601 #define NTOS_MODE_USER void HexDump(const void* data, size_t size); typedef INT(*LDE_DISASM)(PVOID address, INT bits); typedef unsigned long DWORD; typedef unsigned __int64 ULONG64; // 使用WDK标准类型 typedef unsigned char BYTE; typedef LONG NTSTATUS; // 修正的跳板指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { BYTE opcode[6]; // FF 25 00 00 00 00 = jmp [rip+0] ULONG64 address; // 目标地址 (紧跟在指令后) } JMP_ABS, * PJMP_ABS; #pragma pack(pop) static_assert(sizeof(JMP_ABS) == 14, "JMP_ABS size must be 14 bytes"); LDE_DISASM lde_disasm; // 初始化引擎 VOID lde_init() { lde_disasm = (LDE_DISASM)ExAllocatePool(NonPagedPool, 12800); memcpy(lde_disasm, szShellCode, 12800); } // 得到完整指令长度,避免截断 ULONG GetFullPatchSize(PUCHAR Address) { ULONG LenCount = 0, Len = 0; // 至少需要14字节 while (LenCount <= 14) { Len = lde_disasm(Address, 64); Address = Address + Len; LenCount = LenCount + Len; } return LenCount; } #define PROCESS_NAME_LENGTH 16 #define DRIVER_TAG 'HKOB' EXTERN_C char* PsGetProcessImageFileName(PEPROCESS process); char target_process_name[] = "oxygen.exe"; typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = NULL; // PTE Hook Framework #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PDPTE_PS_BIT (1 << 7) #define PDE_PS_BIT (1 << 7) #define PTE_NX_BIT (1ULL << 63) #define CACHE_WB (6ULL << 3) // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPte; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPde; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); // 添加析构函数声明 private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void logger(const char* info, bool is_err, LONG err_code = 0); void PrintPageTableInfo(const PAGE_TABLE& table); void PrintHookInfo(const HOOK_INFO& hookInfo); void PrintGBitInfo(const G_BIT_INFO& gbitInfo); static constexpr SIZE_T MAX_HOOKS = 256; // 根据需求调整 G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; DWORD m_HookCount = 0; char* m_TrampLinePool = nullptr; // 合并为一个声明 UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL PteHookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~0x10000); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | 0x10000); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void PteHookManager::logger(const char* info, bool is_err, LONG err_code) { if (is_err) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: %s (0x%X)\n", info, err_code); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: %s\n", info); } } void PteHookManager::PrintPageTableInfo(const PAGE_TABLE& table) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Page Table Info for VA: 0x%p\n", (void*)table.LineAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PML4E: 0x%llx (Address: 0x%p)\n", table.OriginalPml4e, table.Pml4Address); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDPTE: 0x%llx (Address: 0x%p), Is1GBPage: %d\n", table.OriginalPdpte, table.PdpteAddress, table.Is1GBPage); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p), IsLargePage: %d\n", table.OriginalPde, table.PdeAddress, table.IsLargePage); if (!table.IsLargePage && !table.Is1GBPage) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", table.OriginalPte, table.PteAddress); } } void PteHookManager::PrintHookInfo(const HOOK_INFO& hookInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Address: 0x%p\n", hookInfo.OriginalAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Address: 0x%p\n", hookInfo.HookAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Length: %d\n", hookInfo.HookLength); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Is Hooked: %d\n", hookInfo.IsHooked); // 打印原始字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.OriginalBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.OriginalBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); // 打印Hook字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.HookBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.HookBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } void PteHookManager::PrintGBitInfo(const G_BIT_INFO& gbitInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G-Bit Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Align Address: 0x%p\n", gbitInfo.AlignAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " IsLargePage: %d\n", gbitInfo.IsLargePage); if (gbitInfo.PdeAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p)\n", gbitInfo.PdeAddress->value, gbitInfo.PdeAddress); } if (gbitInfo.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", gbitInfo.PteAddress->value, gbitInfo.PteAddress); } } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; // 打印页表信息 PrintPageTableInfo(table); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 正在拆分大页: 输入PDE=0x%llx, 输出PDE=0x%p\n", in_pde->value, out_pde); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { logger("分配连续内存失败 (用于拆分大页)", true); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x%llx\n", fn_va_to_pa(pt)); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页表: CR3=0x%llx, 地址=0x%p\n", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPdpt); logger("分配连续内存失败 (用于隔离页表)", true); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); logger("获取页表信息失败", true, status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { logger("查找进程失败", true); return false; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页面: PID=%d, 地址=0x%p\n", (ULONG)(ULONG_PTR)process_id, ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("获取目标进程页表失败", true); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("拆分大页失败", true); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除大页G位: PDE=0x%llx\n", Table.PdeAddress->value); } } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除PTE G位: PTE=0x%llx\n", Table.PteAddress->value); success = fn_isolation_pagetable(__readcr3(), AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表状态: IsLargePage=%d, Is1GBPage=%d\n", Table.IsLargePage, Table.Is1GBPage); if (Table.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE 值: 0x%llx (G位=%d)\n", Table.PteAddress->value, Table.PteAddress->flags.global); } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页面隔离成功\n"); } else { logger("页面隔离失败", true); } return success; } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { // 1. 确保8字节对齐 if (reinterpret_cast<ULONG_PTR>(trampoline) & 0x7) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 跳板地址未对齐 (0x%p)\n", trampoline); return false; } // 2. 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); // 3. 直接写入内存 RtlCopyMemory(trampoline, &jmpCmd, sizeof(JMP_ABS)); // 4. 刷新缓存 __invlpg(trampoline); _mm_mfence(); // 5. 恢复写保护 EnableWriteProtection(oldIrql); // 6. 验证写入 BYTE buffer[sizeof(JMP_ABS)]; RtlCopyMemory(buffer, trampoline, sizeof(buffer)); if (memcmp(buffer, &jmpCmd, sizeof(jmpCmd)) != 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 验证失败! 内存内容:\n"); HexDump(buffer, sizeof(buffer)); return false; } // 7. 反汇编验证 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 跳板指令: jmp [rip+0] -> 0x%016llX\n", jmpCmd.address); return true; } // 辅助函数:十六进制转储 void HexDump(const void* data, size_t size) { const BYTE* bytes = static_cast<const BYTE*>(data); for (size_t i = 0; i < size; ++i) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", bytes[i]); if ((i + 1) % 16 == 0) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { if (!ori_addr || !hk_addr || !*ori_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无效参数 (ori_addr=%p, hk_addr=%p)\n", ori_addr, hk_addr); return false; } // 分配跳板池(如果尚未分配) if (!m_TrampLinePool) { PHYSICAL_ADDRESS LowAddr = { LowAddr.QuadPart = 0x100000 }; PHYSICAL_ADDRESS HighAddr = { HighAddr.QuadPart = ~0ull }; m_TrampLinePool = (char*)MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE * 8, LowAddr, HighAddr, LowAddr, MmNonCached); if (!m_TrampLinePool) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无法分配跳板池内存\n"); return false; } // 设置内存保护属性 PMDL pMdl = IoAllocateMdl(m_TrampLinePool, PAGE_SIZE * 8, FALSE, FALSE, NULL); if (pMdl) { MmBuildMdlForNonPagedPool(pMdl); MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE); IoFreeMdl(pMdl); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 跳板池分配成功: 地址=0x%p, 大小=%d字节\n", m_TrampLinePool, PAGE_SIZE * 8); } // 计算跳板位置(8字节对齐) void* trampoline = (void*)((ULONG_PTR)(m_TrampLinePool + m_PoolUsed + 7) & ~7) ; SIZE_T requiredSize = ((char*)trampoline - m_TrampLinePool) + sizeof(JMP_ABS); // 构造正确的跳转指令 JMP_ABS jmpCmd = {}; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // jmp [rip+0] jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 构造跳转指令:\n" " 目标地址: 0x%p\n" " 跳板位置: 0x%p\n" " 指令格式: FF 25 00 00 00 00 + 8字节地址\n", hk_addr, trampoline); // 写入跳板指令 if (!WriteTrampolineInstruction(trampoline, jmpCmd)) { return false; } // 记录Hook信息 bool hookRecorded = false; for (UINT32 i = 0; i < MAX_HOOK_COUNT; i++) { if (!m_HookInfo[i].IsHooked) { m_HookInfo[i].OriginalAddress = *ori_addr; m_HookInfo[i].HookAddress = trampoline; m_HookInfo[i].ProcessId = process_id; m_HookInfo[i].IsHooked = TRUE; RtlCopyMemory(m_HookInfo[i].HookBytes, &jmpCmd, sizeof(jmpCmd)); m_HookInfo[i].HookLength = sizeof(JMP_ABS); m_HookCount++; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook记录 #%d: 原始地址=0x%p, 跳板=0x%p\n", i, *ori_addr, trampoline); hookRecorded = true; break; } } if (!hookRecorded) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 超过最大Hook数量限制 (%d)\n", MAX_HOOK_COUNT); return false; } // 更新原始地址为跳板地址 *ori_addr = trampoline; m_PoolUsed = (UINT32)requiredSize; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook安装成功! 跳板指令:\n" " jmp [rip+0] -> 0x%p\n", hk_addr); return true; } // 析构函数清理资源 PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; } } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 尝试移除Hook: Hook地址=0x%p\n", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 找到匹配的Hook: 原始地址=0x%p\n", m_HookInfo[i].OriginalAddress); KIRQL oldIrql = DisableWriteProtection(); memcpy(m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalBytes, sizeof(m_HookInfo[i].OriginalBytes)); EnableWriteProtection(oldIrql); m_HookInfo[i].IsHooked = FALSE; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook已成功移除\n"); return true; } } logger("未找到匹配的Hook", true); return false; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { logger("达到最大G位记录数量限制", true); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address && ((decltype(PAGE_TABLE::PdeAddress))pde_address)->flags.large_page); // 打印G位信息 PrintGBitInfo(*record); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始恢复G位: 对齐地址=0x%p\n", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PTE G位: PTE=0x%llx, 地址=0x%p\n", record->PteAddress->value, record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PDE G位: PDE=0x%llx, 地址=0x%p, 大页=%d\n", record->PdeAddress->value, record->AlignAddress, record->IsLargePage); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G位恢复完成\n"); } else { logger("未找到匹配的G位记录", true); } return found; } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE Hook管理器实例已创建: 地址=0x%p\n", m_Instance); } else { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 创建PTE Hook管理器实例失败\n"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; // 复制到本地缓冲区并确保 NULL 终止 RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } return (strcmp(currentName, target_process_name) == 0); } // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { __debugbreak(); // 强制中断,确认是否执行到这里 PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName); if (IsTargetProcess(imageName)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 拒绝访问目标进程 PID=%d\n", HandleToULong(PsGetCurrentProcessId())); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook() { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] 找不到 ObReferenceObjectByHandleWithTag\n"); return STATUS_NOT_FOUND; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; HANDLE currentProcessId = PsGetCurrentProcessId(); if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(currentProcessId, &targetFunc, hookFunc)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] PTE Hook 安装失败\n"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] Hook 成功安装. 跳板地址: %p\n", targetFunc); return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程函数 VOID InstallHookWorker(PVOID Context) { UNREFERENCED_PARAMETER(Context); DbgPrint("[+] Worker thread started for hook installation\n"); InstallHook(); PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 VOID ProcessNotifyCallback( _In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create ) { UNREFERENCED_PARAMETER(ParentId); if (Create) { PEPROCESS process = NULL; if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &process))) { CHAR* imageName = PsGetProcessImageFileName(process); CHAR currentName[16]; RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } if (strcmp(currentName, target_process_name) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 目标进程 %s 创建 (PID: %d)\n", currentName, HandleToULong(ProcessId)); HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, NULL ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 工作线程已创建\n"); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [ProcessNotifyCallback] 创建线程失败: 0x%X\n", status); } } ObDereferenceObject(process); } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("[+] Driver unloading...\n"); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { DbgPrint("[PTE_HOOK] Cleaning up PTE...\n"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放跳板池内存 char* trampLinePool = g_PteHookManager->GetTrampLinePool(); if (trampLinePool) { ExFreePoolWithTag(trampLinePool, 'JmpP'); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } DbgPrint("[+] Driver unloaded successfully\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载开始\n"); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 初始化 PteHookManager 失败\n"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 注册进程通知失败 (0x%X)\n", status); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载成功\n"); return STATUS_SUCCESS; } 将整个代码修改正确
06-25
kd> ed nt!Kd_DEFAULT_Mask 0xFFFFFFFF kd> ed nt!Kd_IHVDRIVER_Mask 0xFFFFFFFF kd> g [+] [DriverEntry] 驱动加载开始 [+] [DriverEntry] 驱动加载成功 [+] [ProcessNotifyCallback] 目标进程 oxygen.exe 创建 (PID: 8052) [+] [ProcessNotifyCallback] 工作线程已创建 [+] Worker thread started for hook installation on PID: 8052 Break instruction exception - code 80000003 (first chance) obpcallback!InstallHook+0x50: fffff803`0e2a12f0 cc int 3 kd> g [+] [InstallHook] 找到目标函数地址: FFFFF803062EFB60 [PTE_HOOK] 开始隔离页面: PID=8052, 地址=0xFFFFF803062EFB60 [PTE_HOOK] 正在拆分大页: 输入PDE=0xa00000002a001a1, 输出PDE=0xFFFFBB878EFA3F80 [PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x239dab000 [PTE_HOOK] G-Bit Info: Align Address: 0xFFFFF803062EF000 IsLargePage: 1 PDE: 0xa00000002a000a1 (Address: 0xFFFFFE7F3E00C188) [PTE_HOOK] 清除大页G位: PDE=0xa00000002a000a1 [PTE_HOOK] 开始隔离页表: CR3=0x12e16c000, 地址=0xFFFFF803062EF000 KDTARGET: Refreshing KD connection *** Fatal System Error: 0x0000007e (0xFFFFFFFFC0000005,0xFFFFF8030E2A2265,0xFFFF80031C95B638,0xFFFF80031C95AE70) Break instruction exception - code 80000003 (first chance) A fatal system error has occurred. Debugger entered on first try; Bugcheck callbacks have not been invoked. A fatal system error has occurred. For analysis of this file, run !analyze -v nt!DbgBreakPointWithStatus: fffff803`05ffd0b0 cc int 3 kd> !analyze -v Connected to Windows 10 19041 x64 target at (Wed Jul 9 20:20:01.053 2025 (UTC + 8:00)), ptr64 TRUE Loading Kernel Symbols ................................... Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long. Run !sym noisy before .reload to track down problems loading symbols. ............................ ................................................................ ..................................................... Loading User Symbols PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details Loading unloaded module list ...... ERROR: FindPlugIns 8007007b ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e) This is a very common BugCheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address. Arguments: Arg1: ffffffffc0000005, The exception code that was not handled Arg2: fffff8030e2a2265, The address that the exception occurred at Arg3: ffff80031c95b638, Exception Record Address Arg4: ffff80031c95ae70, Context Record Address Debugging Details: ------------------ Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long. Run !sym noisy before .reload to track down problems loading symbols. PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details KEY_VALUES_STRING: 1 Key : AV.Type Value: Read Key : Analysis.CPU.mSec Value: 4234 Key : Analysis.Elapsed.mSec Value: 39170 Key : Analysis.IO.Other.Mb Value: 0 Key : Analysis.IO.Read.Mb Value: 2 Key : Analysis.IO.Write.Mb Value: 0 Key : Analysis.Init.CPU.mSec Value: 3250 Key : Analysis.Init.Elapsed.mSec Value: 59417 Key : Analysis.Memory.CommitPeak.Mb Value: 72 Key : Analysis.Version.DbgEng Value: 10.0.27829.1001 Key : Analysis.Version.Description Value: 10.2503.24.01 amd64fre Key : Analysis.Version.Ext Value: 1.2503.24.1 Key : Bugcheck.Code.KiBugCheckData Value: 0x7e Key : Bugcheck.Code.LegacyAPI Value: 0x7e Key : Bugcheck.Code.TargetModel Value: 0x7e Key : Failure.Bucket Value: AV_obpcallback!PteHookManager::fn_isolation_pagetable Key : Failure.Exception.Code Value: 0xc0000005 Key : Failure.Exception.IP.Address Value: 0xfffff8030e2a2265 Key : Failure.Exception.IP.Module Value: obpcallback Key : Failure.Exception.IP.Offset Value: 0x2265 Key : Failure.Exception.Record Value: 0xffff80031c95b638 Key : Failure.Hash Value: {03bbd39e-299b-91b8-212d-d002a6bff650} Key : Hypervisor.Enlightenments.Value Value: 12576 Key : Hypervisor.Enlightenments.ValueHex Value: 0x3120 Key : Hypervisor.Flags.AnyHypervisorPresent Value: 1 Key : Hypervisor.Flags.ApicEnlightened Value: 0 Key : Hypervisor.Flags.ApicVirtualizationAvailable Value: 0 Key : Hypervisor.Flags.AsyncMemoryHint Value: 0 Key : Hypervisor.Flags.CoreSchedulerRequested Value: 0 Key : Hypervisor.Flags.CpuManager Value: 0 Key : Hypervisor.Flags.DeprecateAutoEoi Value: 1 Key : Hypervisor.Flags.DynamicCpuDisabled Value: 0 Key : Hypervisor.Flags.Epf Value: 0 Key : Hypervisor.Flags.ExtendedProcessorMasks Value: 0 Key : Hypervisor.Flags.HardwareMbecAvailable Value: 0 Key : Hypervisor.Flags.MaxBankNumber Value: 0 Key : Hypervisor.Flags.MemoryZeroingControl Value: 0 Key : Hypervisor.Flags.NoExtendedRangeFlush Value: 1 Key : Hypervisor.Flags.NoNonArchCoreSharing Value: 0 Key : Hypervisor.Flags.Phase0InitDone Value: 1 Key : Hypervisor.Flags.PowerSchedulerQos Value: 0 Key : Hypervisor.Flags.RootScheduler Value: 0 Key : Hypervisor.Flags.SynicAvailable Value: 1 Key : Hypervisor.Flags.UseQpcBias Value: 0 Key : Hypervisor.Flags.Value Value: 536632 Key : Hypervisor.Flags.ValueHex Value: 0x83038 Key : Hypervisor.Flags.VpAssistPage Value: 1 Key : Hypervisor.Flags.VsmAvailable Value: 0 Key : Hypervisor.RootFlags.AccessStats Value: 0 Key : Hypervisor.RootFlags.CrashdumpEnlightened Value: 0 Key : Hypervisor.RootFlags.CreateVirtualProcessor Value: 0 Key : Hypervisor.RootFlags.DisableHyperthreading Value: 0 Key : Hypervisor.RootFlags.HostTimelineSync Value: 0 Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled Value: 0 Key : Hypervisor.RootFlags.IsHyperV Value: 0 Key : Hypervisor.RootFlags.LivedumpEnlightened Value: 0 Key : Hypervisor.RootFlags.MapDeviceInterrupt Value: 0 Key : Hypervisor.RootFlags.MceEnlightened Value: 0 Key : Hypervisor.RootFlags.Nested Value: 0 Key : Hypervisor.RootFlags.StartLogicalProcessor Value: 0 Key : Hypervisor.RootFlags.Value Value: 0 Key : Hypervisor.RootFlags.ValueHex Value: 0x0 Key : SecureKernel.HalpHvciEnabled Value: 0 Key : WER.OS.Branch Value: vb_release Key : WER.OS.Version Value: 10.0.19041.1 BUGCHECK_CODE: 7e BUGCHECK_P1: ffffffffc0000005 BUGCHECK_P2: fffff8030e2a2265 BUGCHECK_P3: ffff80031c95b638 BUGCHECK_P4: ffff80031c95ae70 FAULTING_THREAD: ffffbb8793f90080 EXCEPTION_RECORD: ffff80031c95b638 -- (.exr 0xffff80031c95b638) ExceptionAddress: fffff8030e2a2265 (obpcallback!PteHookManager::fn_isolation_pagetable+0x0000000000000315) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000000 Parameter[1]: 0000000239dab000 Attempt to read from address 0000000239dab000 CONTEXT: ffff80031c95ae70 -- (.cxr 0xffff80031c95ae70) rax=0000000239dab000 rbx=ffffbb8793f90080 rcx=0000000000001000 rdx=0000000000000000 rsi=0000000239dab000 rdi=ffff9181d99a7000 rip=fffff8030e2a2265 rsp=ffff80031c95b870 rbp=0000000000000080 r8=ffff80031c95b940 r9=8000000000000200 r10=0000000000000000 r11=ffffbb8790910000 r12=0000000000000280 r13=0000000000000000 r14=ffffbb878f4af040 r15=fffff8030c094000 iopl=0 nv up ei pl nz ac po nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050216 obpcallback!PteHookManager::fn_isolation_pagetable+0x315: fffff803`0e2a2265 f3a4 rep movs byte ptr [rdi],byte ptr [rsi] Resetting default scope PROCESS_NAME: oxygen.exe READ_ADDRESS: unable to get nt!PspSessionIdBitmap 0000000239dab000 ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s EXCEPTION_CODE_STR: c0000005 EXCEPTION_PARAMETER1: 0000000000000000 EXCEPTION_PARAMETER2: 0000000239dab000 EXCEPTION_STR: 0xc0000005 STACK_TEXT: ffff8003`1c95b870 fffff803`0e2a1da1 : ffffbb87`8efa7000 00000001`2e16c000 fffff803`062ef000 ffffbb87`8efa3f80 : obpcallback!PteHookManager::fn_isolation_pagetable+0x315 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 526] ffff8003`1c95b9c0 fffff803`0e2a25df : ffffbb87`8efa7000 00000000`00001f74 fffff803`062efb60 00000000`00000035 : obpcallback!PteHookManager::fn_isolation_pages+0x261 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 602] ffff8003`1c95bad0 fffff803`0e2a1344 : ffffbb87`8efa7000 00000000`00001f74 ffff8003`1c95bbb0 fffff803`0e2a1500 : obpcallback!PteHookManager::fn_pte_inline_hook_bp_pg+0x4f [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 723] ffff8003`1c95bb90 fffff803`0e2a13d4 : fffff803`0e2a44a0 00000000`00001f74 00000000`00000000 fffff803`040ef180 : obpcallback!InstallHook+0xa4 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 982] ffff8003`1c95bbe0 fffff803`05ea29a5 : 00000000`00001f74 fffff803`0e2a13a0 00000000`00001f74 fffff803`00000001 : obpcallback!InstallHookWorker+0x34 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1010] ffff8003`1c95bc10 fffff803`05ffc868 : fffff803`040ef180 ffffbb87`93f90080 fffff803`05ea2950 ffff8003`1c95bc80 : nt!PspSystemThreadStartup+0x55 ffff8003`1c95bc60 00000000`00000000 : ffff8003`1c95c000 ffff8003`1c956000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x28 FAULTING_SOURCE_LINE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp FAULTING_SOURCE_FILE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp FAULTING_SOURCE_LINE_NUMBER: 526 FAULTING_SOURCE_CODE: 522: memcpy(Va4kb, replace_align_addr, PAGE_SIZE); 523: 524: if (Table.IsLargePage && split_pde_ptr) { 525: auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; > 526: memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); 527: } 528: else { 529: memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); 530: } 531: SYMBOL_NAME: obpcallback!PteHookManager::fn_isolation_pagetable+315 MODULE_NAME: obpcallback IMAGE_NAME: obpcallback.sys STACK_COMMAND: .cxr 0xffff80031c95ae70 ; kb BUCKET_ID_FUNC_OFFSET: 315 FAILURE_BUCKET_ID: AV_obpcallback!PteHookManager::fn_isolation_pagetable OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {03bbd39e-299b-91b8-212d-d002a6bff650} Followup: MachineOwner ---------按照你改的结果出错了。代码如下:#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) HANDLE targetProcessId = NULL; typedef INT(*LDE_DISASM)(PVOID address, INT bits); typedef unsigned long DWORD; typedef unsigned __int64 ULONG64; // 使用WDK标准类型 typedef unsigned char BYTE; typedef LONG NTSTATUS; // 修正后的跳转指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { BYTE opcode[6]; // FF 25 00 00 00 00 ULONG64 address; // 8字节绝对地址 } JMP_ABS, * PJMP_ABS; #pragma pack(pop) LDE_DISASM lde_disasm; // 初始化引擎 VOID lde_init() { lde_disasm = (LDE_DISASM)ExAllocatePool(NonPagedPool, 12800); memcpy(lde_disasm, szShellCode, 12800); } // 得到完整指令长度,避免截断 ULONG GetFullPatchSize(PUCHAR Address) { ULONG LenCount = 0, Len = 0; // 至少需要14字节 while (LenCount <= 14) { Len = lde_disasm(Address, 64); Address = Address + Len; LenCount = LenCount + Len; } return LenCount; } #define PROCESS_NAME_LENGTH 16 #define DRIVER_TAG 'HKOB' EXTERN_C char* PsGetProcessImageFileName(PEPROCESS process); char target_process_name[] = "oxygen.exe"; typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = NULL; // PTE Hook Framework #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PDPTE_PS_BIT (1 << 7) #define PDE_PS_BIT (1 << 7) #define PTE_NX_BIT (1ULL << 63) #define CACHE_WB (6ULL << 3) // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPte; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPde; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); // 添加析构函数声明 private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void logger(const char* info, bool is_err, LONG err_code = 0); void PrintPageTableInfo(const PAGE_TABLE& table); void PrintHookInfo(const HOOK_INFO& hookInfo); void PrintGBitInfo(const G_BIT_INFO& gbitInfo); static constexpr SIZE_T MAX_HOOKS = 256; // 根据需求调整 G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; DWORD m_HookCount = 0; char* m_TrampLinePool = nullptr; // 合并为一个声明 UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL PteHookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~0x10000); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | 0x10000); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void PteHookManager::logger(const char* info, bool is_err, LONG err_code) { if (is_err) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: %s (0x%X)\n", info, err_code); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: %s\n", info); } } void PteHookManager::PrintPageTableInfo(const PAGE_TABLE& table) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Page Table Info for VA: 0x%p\n", (void*)table.LineAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PML4E: 0x%llx (Address: 0x%p)\n", table.OriginalPml4e, table.Pml4Address); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDPTE: 0x%llx (Address: 0x%p), Is1GBPage: %d\n", table.OriginalPdpte, table.PdpteAddress, table.Is1GBPage); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p), IsLargePage: %d\n", table.OriginalPde, table.PdeAddress, table.IsLargePage); if (!table.IsLargePage && !table.Is1GBPage) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", table.OriginalPte, table.PteAddress); } } void PteHookManager::PrintHookInfo(const HOOK_INFO& hookInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Address: 0x%p\n", hookInfo.OriginalAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Address: 0x%p\n", hookInfo.HookAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Length: %d\n", hookInfo.HookLength); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Is Hooked: %d\n", hookInfo.IsHooked); // 打印原始字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.OriginalBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.OriginalBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); // 打印Hook字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.HookBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.HookBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } void PteHookManager::PrintGBitInfo(const G_BIT_INFO& gbitInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G-Bit Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Align Address: 0x%p\n", gbitInfo.AlignAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " IsLargePage: %d\n", gbitInfo.IsLargePage); if (gbitInfo.PdeAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p)\n", gbitInfo.PdeAddress->value, gbitInfo.PdeAddress); } if (gbitInfo.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", gbitInfo.PteAddress->value, gbitInfo.PteAddress); } } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; // 打印页表信息 PrintPageTableInfo(table); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 正在拆分大页: 输入PDE=0x%llx, 输出PDE=0x%p\n", in_pde->value, out_pde); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { logger("分配连续内存失败 (用于拆分大页)", true); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x%llx\n", fn_va_to_pa(pt)); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页表: CR3=0x%llx, 地址=0x%p\n", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPdpt); logger("分配连续内存失败 (用于隔离页表)", true); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); logger("获取页表信息失败", true, status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { logger("查找进程失败", true); return false; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页面: PID=%d, 地址=0x%p\n", (ULONG)(ULONG_PTR)process_id, ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("获取目标进程页表失败", true); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("拆分大页失败", true); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除大页G位: PDE=0x%llx\n", Table.PdeAddress->value); } success = fn_isolation_pagetable(target_cr3, AlignAddr, split_pde); } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除PTE G位: PTE=0x%llx\n", Table.PteAddress->value); success = fn_isolation_pagetable(target_cr3, AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表状态: IsLargePage=%d, Is1GBPage=%d\n", Table.IsLargePage, Table.Is1GBPage); if (Table.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE 值: 0x%llx (G位=%d)\n", Table.PteAddress->value, Table.PteAddress->flags.global); } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页面隔离成功\n"); } else { logger("页面隔离失败", true); } return success; } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { if (!MmIsAddressValid(trampoline)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 内存地址无效 (VA=%p)\n", trampoline); return false; } PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(trampoline); if (physAddr.QuadPart == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无法获取物理地址 (VA=%p)\n", trampoline); return false; } KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); BOOLEAN wpEnabled = (__readcr0() & CR0_WP); if (wpEnabled) { __writecr0(__readcr0() & ~CR0_WP); _mm_mfence(); } PMDL pMdl = IoAllocateMdl(trampoline, sizeof(JMP_ABS), FALSE, FALSE, NULL); if (!pMdl) { if (wpEnabled) __writecr0(__readcr0() | CR0_WP); KeLowerIrql(oldIrql); return false; } NTSTATUS status = STATUS_SUCCESS; __try { MmBuildMdlForNonPagedPool(pMdl); MmProtectMdlSystemAddress(pMdl, PAGE_READWRITE); // 正确写入 FF25 00000000 和 8字节地址 memcpy(trampoline, jmpCmd.opcode, 6); // FF25 00000000 *(ULONG64*)((BYTE*)trampoline + 6) = jmpCmd.address; // 地址写入 RIP+0 的位置 _mm_sfence(); _mm_clflush(trampoline); _mm_clflush((BYTE*)trampoline + 8); __invlpg(trampoline); _mm_mfence(); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 异常: 写入跳板失败 (代码: 0x%X)\n", status); } IoFreeMdl(pMdl); if (wpEnabled) { __writecr0(__readcr0() | CR0_WP); _mm_mfence(); } KeLowerIrql(oldIrql); if (!NT_SUCCESS(status)) return false; // 验证写入结果 if (*(USHORT*)trampoline != 0x25FF || *(ULONG64*)((BYTE*)trampoline + 6) != jmpCmd.address) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 验证失败: 跳板内容不匹配\n" " 预期: FF25 [%p]\n" " 实际: %02X%02X %02X%02X%02X%02X [%p]\n", jmpCmd.address, ((BYTE*)trampoline)[0], ((BYTE*)trampoline)[1], ((BYTE*)trampoline)[2], ((BYTE*)trampoline)[3], ((BYTE*)trampoline)[4], ((BYTE*)trampoline)[5], *(ULONG64*)((BYTE*)trampoline + 6)); return false; } return true; } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { // [1] 页表隔离 if (!fn_isolation_pages(process_id, *ori_addr)) { return false; } // [2] 获取目标进程上下文 PEPROCESS targetProcess; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &targetProcess))) { return false; } KAPC_STATE apcState; KeStackAttachProcess(targetProcess, &apcState); // [3] 构造跳转指令 JMP_ABS jmpCmd = {}; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // FF25 00000000 jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); // [4] 直接写入被隔离页 void* targetFunc = *ori_addr; bool success = false; // 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); __try { // 保存原始指令 (用于卸载) RtlCopyMemory(m_HookInfo[m_HookCount].OriginalBytes, targetFunc, sizeof(jmpCmd)); // 写入跳转指令到隔离页 memcpy(targetFunc, &jmpCmd, 6); *(ULONG64*)((BYTE*)targetFunc + 6) = jmpCmd.address; // 刷新缓存 _mm_sfence(); _mm_clflush(targetFunc); __invlpg(targetFunc); _mm_mfence(); success = true; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 直接写入隔离页成功: VA=%p -> Hook=%p\n", targetFunc, hk_addr); } __except (EXCEPTION_EXECUTE_HANDLER) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 写入隔离页异常: 0x%X\n", GetExceptionCode()); } // 恢复写保护 EnableWriteProtection(oldIrql); // [5] 记录Hook信息 if (success) { m_HookInfo[m_HookCount].OriginalAddress = targetFunc; m_HookInfo[m_HookCount].HookAddress = hk_addr; m_HookInfo[m_HookCount].ProcessId = process_id; m_HookInfo[m_HookCount].IsHooked = TRUE; m_HookCount++; } // [6] 清理 KeUnstackDetachProcess(&apcState); ObDereferenceObject(targetProcess); return success; } // 析构函数清理资源 PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; } } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 尝试移除Hook: Hook地址=0x%p\n", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 找到匹配的Hook: 原始地址=0x%p\n", m_HookInfo[i].OriginalAddress); KIRQL oldIrql = DisableWriteProtection(); memcpy(m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalBytes, sizeof(m_HookInfo[i].OriginalBytes)); EnableWriteProtection(oldIrql); m_HookInfo[i].IsHooked = FALSE; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook已成功移除\n"); return true; } } logger("未找到匹配的Hook", true); return false; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { logger("达到最大G位记录数量限制", true); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address && ((decltype(PAGE_TABLE::PdeAddress))pde_address)->flags.large_page); // 打印G位信息 PrintGBitInfo(*record); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始恢复G位: 对齐地址=0x%p\n", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PTE G位: PTE=0x%llx, 地址=0x%p\n", record->PteAddress->value, record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PDE G位: PDE=0x%llx, 地址=0x%p, 大页=%d\n", record->PdeAddress->value, record->AlignAddress, record->IsLargePage); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G位恢复完成\n"); } else { logger("未找到匹配的G位记录", true); } return found; } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE Hook管理器实例已创建: 地址=0x%p\n", m_Instance); } else { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 创建PTE Hook管理器实例失败\n"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; // 复制到本地缓冲区并确保 NULL 终止 RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } return (strcmp(currentName, target_process_name) == 0); } // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName); __debugbreak(); // 强制中断,确认是否执行到这里 if (IsTargetProcess(imageName)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 拒绝访问目标进程 PID=%d\n", HandleToULong(PsGetCurrentProcessId())); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook() { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] 找不到 ObReferenceObjectByHandleWithTag\n"); return STATUS_NOT_FOUND; } __debugbreak(); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(targetProcessId, &targetFunc, hookFunc)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] PTE Hook 安装失败\n"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] Hook 成功安装. 跳板地址: %p\n", targetFunc); __debugbreak(); // 强制中断,验证是否执行到这里 return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程函数 VOID InstallHookWorker(PVOID Context) { targetProcessId = (HANDLE)Context; DbgPrint("[+] Worker thread started for hook installation on PID: %d\n", HandleToULong(targetProcessId)); InstallHook(); PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 VOID ProcessNotifyCallback( _In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create ) { UNREFERENCED_PARAMETER(ParentId); if (Create) { PEPROCESS process = NULL; if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &process))) { CHAR* imageName = PsGetProcessImageFileName(process); CHAR currentName[16]; RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } if (strcmp(currentName, target_process_name) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 目标进程 %s 创建 (PID: %d)\n", currentName, HandleToULong(ProcessId)); HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, (PVOID)ProcessId // 关键:传递目标进程ID ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 工作线程已创建\n"); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [ProcessNotifyCallback] 创建线程失败: 0x%X\n", status); } } ObDereferenceObject(process); } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("[+] Driver unloading...\n"); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { DbgPrint("[PTE_HOOK] Cleaning up PTE...\n"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放跳板池内存 char* trampLinePool = g_PteHookManager->GetTrampLinePool(); if (trampLinePool) { ExFreePoolWithTag(trampLinePool, 'JmpP'); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } DbgPrint("[+] Driver unloaded successfully\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载开始\n"); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 初始化 PteHookManager 失败\n"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 注册进程通知失败 (0x%X)\n", status); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载成功\n"); return STATUS_SUCCESS; }
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值