Paging
32-Bit Paging
启用条件:CR0.PG = 1 and CR4.PAE = 0.
寻址范围:40-bit physical addresses, linear addresses are limited to 32 bits.
寻址方式:
PAE Paging
启用条件:CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 0.
寻址范围:52-bit physical addresses, linear addresses are limited to 32 bits.
寻址方式:
4-Level Paging
启用条件:CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1.
寻址范围:52-bit physical addresses, linear addresses are limited to 48 bits.
寻址方式:
其中,某些entry的bit7决定页面大小,PTE的bit9与copy-on-write技术有关。
代码测试(以x64 4-Level Paging为例)
1 |
|
Windows页表自映射
介绍
Windows为了方便自己管理内存于是采用了页表自映射(Self-mapping page tables)的方法以便于用VA操作。
以Win7 x64 7601为例子
已知定义
1 |
|
利用windbg先转换0x400000
1 | kd> !vtop 0 0x400000 |
将0x400000根据MiGetPteAddress
计算得到0xFFFFF68000002000,再次利用windbg转换
1 | kd> !vtop 0 0xFFFFF68000002000 |
实际上就是根据这个特定的PTE_BASE计算出pml4中的某一项的索引并让这一项再指向pml4(或者应该反过来说通过特定的索引计算出PTE_BASE)。在这里这个索引等于0x1ED,将这个索引左移39位(va中pml4e索引的位置),并将bit63:48填充为1即可得到PTE_BASE=0xFFFFF68000000000。
某种意义上来说就是让虚拟地址到物理地址的翻译过程中少了一次查表的过程。
PTE_BASE随机化
从Win10 14316开始,PTE_BASE不再是WRK中给出的0xFFFFF68000000000,而是随机初始化的。
引用大表哥hzqst逆向鹅厂定位PTE_BASE的例子。
1 | char __fastcall InitializePteBase(char a1) |
这段代码的意思就是在pml4中找到指向自己的那一项的索引,然后把这个索引左移39位再把bit63:48补上1就能得到PTE_BASE。而PDE_BASE就是把这个索引左移到VA中pdpte索引的位置再加上PTE_BASE就能得到,PPE_BASE、PXE_BASE同理,某种意义上相当于少了几次查表过程。
注:win10 1803之后MmMapIoSpace不再允许映射页表相关的物理地址,因此只能用MmGetVirtualForPhysical代替,或者自己实现映射物理地址。