Windows内核实验:PAE分页(PAE paging)

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 分页

image-20230602134150946

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分页转换过程

image-20230602135849354

调试

依旧是非pae的那个程序

g_cr3:0x8c902a0
local num address:004197B0
请按任意键继续. . .
kd> .formats cr4
Evaluate expression:
Hex: 000006f9
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 //0
000000010 //2
000011001 //0x19
011110110000 //0x7b0

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 0cc1f000 + 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.

页目录和页表在虚拟内存里的表现

image-20230602130747486

总的大小变为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> ?? ((0x04197B0>> 12) << 3) + 0xc0000000
unsigned int 0xc00020c8
kd> ?? ((0x04197B0>> 21) << 3) + 0xc0600000
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