Windows 10 x64:无法在Windbg上获取PXE
无法理解Windows内存管理器是如何工作的。 我查看附加的用户进程(Windows 10 x64:无法在Windbg上获取PXE,windows,debugging,winapi,memory-management,windbg,Windows,Debugging,Winapi,Memory Management,Windbg,无法理解Windows内存管理器是如何工作的。 我查看附加的用户进程(dbgview.exe)。 这是WOW64过程。在指定的地址(0x76560000)上有内核32.dll模块(也是WOW64)的.text部分。 为什么进程页表中没有指向这些虚拟地址的PTE和其他表 kd> db 76560000 00000000`76560000 8b ff 55 8b ec 51 56 57-33 f6 89 55 fc 56 68 80 ..U..QVW3..U.Vh. <...>
dbgview.exe
)。
这是WOW64过程。在指定的地址(0x76560000
)上有内核32.dll
模块(也是WOW64)的.text
部分。
为什么进程页表中没有指向这些虚拟地址的PTE和其他表
kd> db 76560000
00000000`76560000 8b ff 55 8b ec 51 56 57-33 f6 89 55 fc 56 68 80 ..U..QVW3..U.Vh.
<...>
kd> !pte 76560000
VA 0000000076560000
PXE at FFFFF6FB7DBED000 PPE at FFFFF6FB7DA00008 PDE at FFFFF6FB40001D90 PTE at FFFFF680003B2B00
Unable to get PXE FFFFF6FB7DBED000
kd> db FFFFF680003B2B00
fffff680`003b2b00 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????
<...>
kd>db 76560000
00000000`76560000 8b ff 55 8b ec 51 56 57-33 f6 89 55 fc 56 68 80..U..QVW3..U.Vh。
kd>!私人股本76560000
弗吉尼亚州00000000 76560000
FFFFF 6FB7DBED000处的PXE,FFFFF 6FB7DA00008处的PPE,FFFFF 6FB40001D90处的PDE,FFFFF 680003B2B00处的PTE
无法获取PXE FFFFF 6FB7DBED000
kd>db FFFFF 68003B2B00
FFFFF 680`003b2b00???????????????
我知道第一次访问(有页面错误)发生后会分配页面,但为什么也没有protype PTE?我发现,自从Windows 10周年更新(1607,10.0.14393)以来,PML4表被随机分配,以减少内核堆溢出。
这意味着页表可能未放置在
0xFFFFF6800000
首先,使用将任意虚拟地址转换为物理地址!vtop
在翻译过程中查看流程的dirbase
,或使用!process
查找进程的dirbase
:
lkd> .process /p fffffa8046a2e5f0
Implicit process is now fffffa80`46a2e5f0
lkd> .context 77fa90000
lkd> !vtop 0 13fe60000
Amd64VtoP: Virt 00000001`3fe60000, pagedir 7`7fa90000
Amd64VtoP: PML4E 7`7fa90000
Amd64VtoP: PDPE 1`c2e83020
Amd64VtoP: PDE 7`84e04ff8
Amd64VtoP: PTE 4`be585300
Amd64VtoP: Mapped phys 6`3efae000
Virtual address 13fe60000 translates to physical address 63efae000.
然后在PFN数据库中找到该物理帧(在本例中,PML4的物理页(cr3页又名.dirbase)为77fa90
,具有完整的物理地址77fa90000
:
lkd> !pfn 77fa90
PFN 0077FA90 at address FFFFFA80167EFB00
flink FFFFFA8046A2E5F0 blink / share count 00000005 pteaddress FFFFF6FB7DBEDF68
reference count 0001 used entry count 0000 Cached color 0 Priority 0
restore pte 00000080 containing page 77FA90 Active M
Modified
因此,地址FFFFF 6FB7DBED000
是PML4页面的虚拟地址,FFFFF 6FB7DBEDF68
是PML4E自参考条目的虚拟地址(1ed*8
=f68
)
fffff 6fb7dbed000
=111111111111111111111101101101000000000000
111111111111111111111101111101101111101101111101101111101101000000000000000000
PML4只能位于PML4E、PDTPE、PDE和PTE索引相同的虚拟地址,因此实际上有2^9
不同的组合,windows 7总是选择0x1ed
,即111101101
。这是因为PML4包含指向自身的PML4,即物理帧PML4的索引,所以它需要在层次结构的每个级别上保持对同一位置的索引
PML4是一个页表页,必须位于内核中,内核地址是高度规范的,即前缀为1111111111
,内核地址从00001
到11111
开始,即从08
到ff
因此,使用8TiB作为用户地址空间的64位操作系统可以放置的可能地址范围是31*(2^4)
=496个不同的可能位置,而实际上不是2^9
:
1111111111111 00001000010000000000000000000000000000
111111111111111111111111111111111111111111111111000000000000000000
即第一个是FFFF080402010000
,第二个是FF088442211000
,最后一个是FFFFFFFFFF000
:
在Windows10th2之前,自引用PML4条目的魔法索引是上文提到的0x1ed
。但是1607年的Windows10呢?微软升级了他们的游戏,作为提高Windows安全性的持续战斗,索引在引导时是随机的,因此0x1ed
现在是512个索引之一[sic.(496)]自引用条目索引可能具有的值(即9位索引)。此外,它还破坏了一些自己的工具,如!pte2va
WinDbg命令
0xFFF6800000000
是第一页表格页面中第一个PTE的地址,因此基本上MmPteBase
,除了因为在Windows 10 1607上PML4E可以是一个非0x1ed
的地址之外,因此基数并不总是0xFFF6800000000
,它使用变量nt!MmPteBase
来了解insta页表页分配的基址的起始位置。以前,此符号在ntoskrnl.exe
中不存在,因为它具有硬编码的基址0xFFFFF6800000000
。第一页和最后一页表页的地址将是:
first last
* pml4e_offset : 0x1ed 0x1ed
* pdpe_offset : 0x000 0x1ff
* pde_offset : 0x000 0x1ff
* pte_offset : 0x000 0x1ff
* offset : 0x000 0x000
当PML4E索引为0x1ed
时,第一页的表页为0xFFFFF6800000000
,最后一页的表页为0xFFFFFFF000
。PDEs+PDPTEs+PML4Es+PTEs分配在此范围内
因此,为了能够将虚拟地址转换为其PTE虚拟地址(而!pte2va
与此相反),您可以将111101101
附加到虚拟地址的开头,然后截断最后12位(页偏移量,不再有用),然后将其乘以8字节(PTE大小)(即,在末尾添加3个零,这将在包含PTE乘以PTE结构大小的页面中创建从最后一级索引到页面的新页面偏移量)。将PML4E索引连接到起始点只会使其循环一次,以便您实际获得PTE,而不是PTE指向的内容。将其连接到起始点与将其添加到MmPteBase
中是一样的
这里是简单的C++代码来做:
// pte.cpp
#include<iostream>
#include<string>
int main(int argc, char *argv[]) {
unsigned long long int input = std::stoull(argv[1], nullptr, 16);
long long int ptebase = 0xFFFFF68000000000;
long long int pteaddress = ptebase + ((input >> 12) << 3);
std::cout << "0x" << std::hex << pteaddress;
}
要获取PDE虚拟地址,必须将其粘贴两次,然后将最后21位截断,然后再乘以8。这就是!pte
的工作原理,与!pte2va
相反
类似地,PDE+PDPTE+PML4E的分配范围如下:
first last
* pml4e_offset : 0x1ed 0x1ed
* pdpe_offset : 0x1ed 0x1ed
* pde_offset : 0x000 0x1ff
* pte_offset : 0x000 0x1ff
* offset : 0x000 0x000
因为当您到达页面表页面范围内的pdpte偏移量的0x1ed
时,突然之间,您正在PML4 o中循环
first last
* pml4e_offset : 0x1ed 0x1ed
* pdpe_offset : 0x1ed 0x1ed
* pde_offset : 0x000 0x1ff
* pte_offset : 0x000 0x1ff
* offset : 0x000 0x000