Windows内核实验:PAE分页(PAE paging) multi(0 )disk(0 )rdisk(0 )partition(1 )\WINDOWS="Microsoft Windows XP Home Edition DEBUG" /noexecute=optin /fastdetect /debugport=COM1 /baudrate=115200
理论 时代发展,32位地址总线支持最大4g的物理内存越来越不够用来,就出现了36位地址总线的处理器,理论上支持最大64g的物理内存,为了寻址大于4G的物理内存,出现了PAE分页的方式
这是一种三级分页的的方式,比二级分页多了一级叫做**页目录指针表PDPT(Page Directory Pointer Table)**的第一级,为了寻址36位地址总线的物理内存,页目录表项(PDE),页表项(PTE),页目录指针(PDPTE)都变为了8字节(4字节只能描述232-12 *4kb=4G的物理内存,要描述64G至少需要36-12=24位来描述页基址,即需要36bit来做表项,干脆对齐8byte算了,所以从理论上是支持264-12 *4Kb大小物理内存),这样一个页只能存放4096/8=512个页表项,所以需要9个位来寻找,页目录项也是如此,就形成了2 9 9 12 分页
NOTES:
其中M是MAXPHYADDR的缩写(可以理解为地址总线位数),本例子M=36
CR3只有在intel-64架构有64位
保留位必须为0
XD位,如果 IA32_EFER.NXE标志位等于1,该位为1 则该页中的数据(或该项指向的页表中的所有页)不可执行(从该页中获取指令将被禁止;IA32_EFER.NXE等于0,该位位保留位,必须填0
PAE分页时每个进程虚拟内存还是22 *29 *29 *4KB=4G,不过系统可使用的总物理内存大了
PAE分页转换过程
调试 依旧是非pae的那个程序
g_cr3:0x8c902a0 local num address:004197B 0 请按任意键继续. . .
kd> .formats cr4 Evaluate expression: Hex: 000006f 9 Decimal: 1785 Decimal (unsigned ) : 1785 Octal: 00000003371 Binary: 00000000 00000000 00000110 11111001 Chars: .... Time: Thu Jan 1 08 :29 :45 1970 Float: low 2.50132e-042 high 0 Double: 8.81907e-321
cr4第五位pae标志位为1 开启pae
kd> !process 0 0 test.exe Failed to get VadRoot PROCESS 815b6020 SessionId: 0 Cid: 0154 Peb: 7ffd3000 ParentCid: 04b8 DirBase: 08c902a0 ObjectTable: e24c4a90 HandleCount: 17. Image: test.exe kd> .formats 004197B0 Evaluate expression: Hex: 004197b0 Decimal: 4298672 Decimal (unsigned) : 4298672 Octal: 00020313660 Binary: 00000000 01000001 10010111 10110000 Chars: .A.. Time: Fri Feb 20 02:04:32 1970 Float: low 6.02372e-039 high 0 Double: 2.12383e-317
虚拟地址按照2-9-9-12分页分开
00 000000010 000011001 011110110000
DirBase即为页目录指针表物理地址08c902a0
kd> !dq 08c902a0 + 0 # 8c902a0 00000000`0ca6c001 00000000`0ca6d001
得到页目录表物理地址0ca6c000
kd> !dq 0ca6c000 + 8 * 2 # ca6c010 00000000`0ca7c067 00000000`00000000
得到页表物理地址0ca7c000
kd> !dq 0ca7c000 + 8 * 0x19 # ca7c0c8 80000000`0cc1f067 80000000`0cb78067
得到页表项0cc1f000
kd> !db 0 cc1f000 + 0x7b0 # cc1f7b0 78 56 34 12 00 00 00 00 -00 00 00 00 00 00 00 00 xV4.............
!vtop验证
kd> !vtop 08c902a0 004197B0 X86VtoP: Virt 00000000004197b0, pagedir 0000000008c902a0 X86VtoP: PAE PDPE 0000000008c902a0 - 000000000ca6c001 X86VtoP: PAE PDE 000000000ca6c010 - 000000000ca7c067 X86VtoP: PAE PTE 000000000ca7c0c8 - 800000000cc1f067 X86VtoP: PAE Mapped phys 000000000cc1f7b0 Virtual address 4197b0 translates to physical address cc1f7b0.
页目录和页表在虚拟内存里的表现
总的大小变为2^2 * 2^9 * 2^9 * 8byte = 8Mb 所有页目录移到了0xc060 0000处
一个页目录指针表项描述4k * 2^9 * 2^9 = 1G内存
一个页目录项描述4k * 2^9 = 2M内存
一个页表项描述4k内存
页目录指针不放入虚拟内存(主要是页目录描述的内存太大了,没必要让这么到一块内存的属性放到进程空间里让进程去修改),其余表计算公式为
页表项地址=((address >> 12) << 3) + 0xc0000000
页目录项地址 = ((address >> 21) <<3) + 0xc0600000
kd> !process 0 0 test.exe Failed to get VadRoot PROCESS 815b6020 SessionId: 0 Cid: 0154 Peb: 7ffd3000 ParentCid: 04b8 DirBase: 08c902a0 ObjectTable: e24c4a90 HandleCount: 17. Image: test.exe kd> .process /i 815b6020 You need to continue execution (press 'g' <enter>) for the context to be switched. When the debugger breaks in again, you will be in the new process context. kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 80528bdc cc int 3 kd> r cr3 cr3=08c902a0 kd> !pte 004197B0 VA 004197b0 PDE at C0600010 PTE at C00020C8 contains 000000000CA7C067 contains 800000000CC1F067 pfn ca7c ---DA--UWEV pfn cc1f ---DA--UW-V kd> ?? ((0 x04197B0>> 12 ) << 3 ) + 0 xc0000000 unsigned int 0xc00020c8 kd> ?? ((0 x04197B0>> 21 ) << 3 ) + 0 xc0600000 unsigned int 0xc0600010
同时可以看到pte为800000000CC1F067最高位dx为1表示数据不可执行 —DA–UW-V
kd> dq C00020C8 l1 c00020c8 80000000`0cc1f067 kd> !pte 004197B0 VA 004197b0 PDE at C0600010 PTE at C00020C8 contains 000000000CA7C067 contains 800000000CC1F067 pfn ca7c ---DA--UWEV pfn cc1f ---DA--UW-V kd> eq C00020C8 00000000`0cc1f067 kd> !pte 004197B0 VA 004197b0 PDE at C0600010 PTE at C00020C8 contains 000000000CA7C067 contains 000000000CC1F067 pfn ca7c ---DA--UWEV pfn cc1f ---DA--UWEV
可以看到最高位修改为后有了可执行权限E —DA–UWEV