NT内核的内存分配(PDE与PTE)

本文详细介绍了Windows内核中与内存管理相关的全局变量及其作用,包括最高用户地址、用户探测地址、系统范围开始地址等,并解释了虚拟地址到页表项地址的转换方法。

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

Nt Kernel Memory Allocation

Some important Globals concerning memory.

These globals are defined in ntos/mm/miglobal.c and set in ntos/mm/mminit.c and ntos/mm/i386/init386.c.


Global Example Value Notes

MmHighestUserAddress 0x7ffeffff
MmUserProbeAddress 0x7fff0000 One more than MmHighestUserAddress
MmSystemRangeStart 0x80000000 First 4Meg maps directly to [0,0x00400000) physical memory by a single PDE marked "Large Page".
MmNonPagedPoolStart 0x8051d000
MmPfnDatabase 0x83f9f000
MmWinStationSpaceBase 0xa3000000 Base Structure. Current MM_WINSTATION_SPACE struct always found here. This region is per session.
 0xa3010000 Winstation Space Driver Images Base
 0xa3c00000 Winstation Space Working Set
 0xa4000000 Winstation Space Paged Pool
 0xa5000000 Winstation Space Mapped Views
MmKStackPoolStart 0xa8000000 One byte above WinStation Space.
Also known as System PTE Expansion in NT5.0.
  0xc0000000 Page Table base
MmSystemPteBase 0xc0200000 PTE for VA 0x80000000
MmFirstPteForPagedPool 0xc0384000 PTE for VA 0xe1000000 (MmPagedPoolStart)
MmLastPteForPagedPool 0xc0390ffc
MmSystemPtesStart[0] 0xc03e3000 (enum _MMSYSTEM_PTE_POOL_TYPE).SystemPteSpace == 0
PTE for VA 0xf8c00000 (MmNonPagedSystemStart)
MmSystemPtesEnd[0] 0xc03f94a8
MmSystemPtesStart[1] 0xc03f94b0 (enum _MMSYSTEM_PTE_POOL_TYPE).NonPagedPoolExpansion == 1
PTE for VA 0xfe52c000 (MmNonPagedPoolExpansionStart)
MmSystemPtesEnd[1] 0xc03fef7c
  0xc0400000 Page table end + 1
MmPagedPoolStart 0xe1000000 Fixed Address
MmPagedPoolEnd 0xe43fffff
MmNonPagedSystemStart 0xf8c00000 The region known as "system PTE's".
MmNonPagedPoolExpansionStart 0xfe52c000
MmNonPagedPoolEnd 0xffbe0000

MmNumberOfSystemPtes 0x0000592b (MmSystemPtesEnd[0]-MmSystemPtesStart[0])/4+1
HKLM/System/.../Control/Session_Manager/Memory_Management (DWORD) System_Pages or default
MmNumberOfPhysicalPages 0x00003f6e 64M RAM
MmWinStationSpaceSize 0x05000000 Distance from MmWinStationSpaceBase to MmKStackPoolStart.

These are available in kd as follows:

kd> dd MmNumberOfSystemPtes
801565e0 0000592b 83f9f000 00003f6e 00000000

Converting Virtual Address to PTE's.

The page tables are based at 0xc0000000. 32 bits of address space must be represented by all PTE's. Each PTE represents 12 bits of address space (a 4K page) and itself consumes 2 bits (PTE = 4 bytes). So:

    32 - 12 + 2 = 22 bits

of address space is required. Therefore the top of the page table is at 0xc0400000-1.

The relationship between VA, a virtual address, and PTE, the address of the PTE for that address, is:

   VA = (( PTE - PTE_BASE )/ 4 ) * 4K
PTE = ( VA/4K ) * 4 + PTE_BASE

It is useful to note:

   PTE_BASE = 0xc0000000
4K = 0x1000

Because 4K is so nicely represented in hex, the only hard part for by-hand calculation is the division or multiplication by 4.

For example, the PTE for the base of the PTE table is:

   PTE = ( 0xc0000000 / 0x1000 ) * 4 + 0xc0000000
= 0xc0000 * 4 + 0xc0000000
= 0x300000 + 0xc0000000
= 0xc0300000

By clever coincidence, the page of PTE's starting at this addess is the PDE - a page of PTE's pointing to other pages of PTE's. The PTE of this VA is:

   PTE = ( 0xc0300000 / 0x1000 ) * 4 + PTE_BASE
= 0xc0300c00

This PTE contains the page frame number of the page holding the page directory. However, there must also be some PDE containing this page frame number. Since address translation will work even if each PTE/PDE references a different page frame, the PDE for this address must be the same as the PTE for this address.

The PTE for 0xc0300c00, since it is on the same page as the previously calculated PTE, is at 0xc0300c00. This PTE maps itself.

We check this, and that the page frame number in this PTE/PDE is loaded into CR3:

kd> !pte c0300c00
C0300000 - PDE at C0300C00 PTE at C0300C00
contains 00030067 contains 00030067
pfn 00030 --DA--UWV pfn 00030 --DA--UWV

kd> r
eax=00000001 ebx=00725d11 ecx=8014d25c edx=000002f8 esi=000000ae edi=c1979f90
eip=80135b18 esp=801509f4 ebp=80150a04 iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
cr0=8001003f cr2=01020004 cr3=00030000

kd>

Remarks on the PTE map.

The previous paragraph remarked that virtual address 0xc0300c00 is mapped by the PTE at the same virtual address. This is explained as the fixed point of the PTE map. Recall that the PTE map, PTE = h(VA), is linear:

    PTE = h( VA ) 
= ( VA / PAGE_SIZE ) * PTE_SIZE + PTE_BASE

So there is a solution to x = h(x). However, this solution need not be integral, so this explanation of the fixed point is faulty.

Note, however, that this special address, PTE_f = 0xc0300c00, can be calculated, for any PTE_BASE, as the third iterate of the map h:

    PTE_f = h( h( h( X ) ) ),  for any virtual address X.

The first iterate maps an arbitrary virtual address to a PTE-aligned virtual address in the page table; the second iterate maps this address to a PDE in the page directory; and the third iterate maps this address the map's fixed point.

This is all by virtue that h is a contracting map:

    X /superset h(X) /superset h(h(X)) /superset ... /superset Y

and the displayed descending chain of address subsets must stablized, since the sets are discrete. Although abstract, this paragraph is a complete proof of the fixed point and illustrates all the conditions necessary for its existence.

For instace, for h to be contracting, the page directory must land page aligned. Hence we find that PTE_BASE must be aligned on a 4M boundary, or 0x00400000. The length of the chain before stabilization is one more than the layers of page tables. The two level page tables of the i386 implies that 3 interations of h are necessary.

As an alternative but hypothetical example, consider 256 byte pages of 64 PTE's per page, PTE's still 4 bytes. This would give a four level page table where each level uses 6 bits, and the final offset is 8 bits. ( 4*6+8=32 ). The fixed point would be calculated by taking h(h(h(h(h(X))))) for any X in the address space.

WinStation space layout.

The following comment is from ntos/mm/citrix/ctxmi.h. Only MmWinstationSpaceBase is a global and can be included in the table of significant globals.

//
// Address Map when MmWinstationSpaceBase == 0xA3000000.
//
// When the system is booted in 2GB mode, these addresses
// change.
//
// MmWinStationSpaceBase+0
// Base structure
// 64K
//
// MmWinStationSpaceBase+0x10000
// Driver images
// 12M-64K (re)based drivers allocated from top down
// WIN32K.SYS based at 0xA3010000 always
//
// MmWinStationSpaceBase+0xC00000
// Working Set
// 4M
//
// MmWinStationSpaceBase+0x1000000
// Paged Pool
// 16M
//
// MmWinStationSpaceBase+0x2000000
// Mapped Views
// 16M
//
// Total
// 48M
//
// MmWinStationSpaceBase+0x3000000
// KSTACK POOL
//
// Total 416M
//
//

The WinstationSpace structures are in kernel space, but the active WinstaionSpace structure is mapped to MmWinStationSpaceBase. The first DWORD of this structure is the signature 0x0ccccccc, so this value should always appear at 0a3000000.

The MM_WINSTATIONSPACE structures are double-linked into a chain rooted at some global. Inside the structures are 20 PDE's which map up to 80M of Winstation space. Japanese has more.

[讨论][转帖][讨论][原创]windows Hook内核api,能过win10 22H2的pg 发表于: 2023-12-6 17:35 12257 最近一直在思考如何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; } 你看看这个代码,分析然后写一个win10 10240版本可行的页表hook代码
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值