Windows保护模式学习笔记(九)—— 2-9-9-12分页
前言
一、学习自
滴水编程达人
中级班课程,官网:https://bcdaren.com
二、海东老师牛逼!
要点回顾
在之前的笔记中我们已经讲解了10-10-12分页方式,在这种分页方式下物理地址最多可达4GB。但随着硬件的发展,4GB的物理地址范围已经无法满足要求
Intel在1996年就已经意识到这个问题了,所以设计了新的分页方式,也就是我们本节课要讲的2-9-9-12分页,又称为PAE(物理地址扩展)分页
10-10-12分页
原理
- Intel认为一张页的大小为4K是比较合理的,所以先确定页的大小为4K,4KB等于4096个字节,也就是2的12次方,所以32位的最后一部分就确定为了12位
- 当初的物理内存比较小,所以4个字节的PTE就够了,加上页的尺寸是4K,所以一个页能存储1024个 PTE,也就是2的10次方,第二个10也就确定了
- 同理,PDT也需要10个比特位,10+10+12刚好32位
环境配置
若想将操作系统设置为10-10-12分页,只要将C:\boot.ini文件中的 noexecute 改为 execute,重启即可。具体步骤在学习10-10-12分页时已经介绍,这里不再详述。
2-9-9-12分页
描述:2-9-9-12分页(PAE,物理地址扩展)
原理
- 页的大小是确定的,4KB不能随便改,所以32位的最后一部分就确定为了12位。
- 如果想增大物理内存的访问范围,就需要增大PTE,增大了多少呢?考虑对齐的因素,增加到8个字节
由于PTE增大了,而PTT表的大小没变,依然是4KB,所以每张PTT表能放的PTE个数由原来的1024个减少到512个,512等于2的9次方,因此PTI=9
- 由于2的9次方个PDE就能找到所有的PTT表,因此PDI=9
- 分配到这里时,还剩下前2位未分配。
与10-10-12不同,CR3不直接指向PDT表,而是指向一张新的表,叫做PDPT表(页目录指针表)
PDPT表中的每一个成员叫做PDPTE(Page-Directory-Point-Table Entry,页目录指针表项),每项占8个字节
PDPT表只有4个成员,因为2位比特位只能满足四种情况:00 01 10 11
PDPTE
结构图:
P位
:第0位,有效位
Avail
:这部分供操作系统软件随意使用,CPU不使用
Base Addr
:指向PDT表地址,由两部分组成
第一部分:高四字节32~35位
第二部分:低4字节12~31位
这两部分加起来共24位,后12位补0
灰色部分
:保留位
注意:PWT位
与PCD位
在本篇不作描述
PDE
结构图:
PAT位
:页属性表
只有当PS=1时,PAT位才是有意义的(页属性表只针对页)
具体含义这里不作介绍,感兴趣的同学可以查阅资料
注意:
- G位、PCD位、PWT位可以暂且不管。
- 其他属性位的含义在上面学习PDPTE时或在学习10-10-12分页的PDE与PTE时已经介绍,这里不再详述
PTE
结构图:
注意:
- PTE中12~35位是物理页基址,低12位补0
- 物理页基址+12位页内偏移指向具体数据
XD/NX标志位
描述:
- Intel中称为XD,AMD中称为NX,即No Excetion
- 段的属性有可读、可写和可执行
- 页的属性有可读、可写
- 当RET执行返回的时候,如果把堆栈里面的数据指向一段提前准备好的数据(把数据当作代码来执行,漏洞都是依赖这点,比如SQL注入也是),那么就会产生任意代码执行的后果
- 所以,Intel就在这方面做了硬件保护,设置了一个不可执行位 – XD/NX位。
- 当XD=1时,软件产生了溢出也没有关系,即使EIP蹦到了危险的“数据区”,也是不可以执行的
- 在PAE分页模式下,PDE与PTE的最高位为XD/NX位.
环境配置
若想将操作系统设置为2-9-9-12分页,只要将C:\boot.ini文件中的 execute 改为 noexecute,重启即可。具体步骤在学习10-10-12分页时已经介绍,这里不再详述。
实验:通过线性地址找到物理地址
第一步:新建一个记事本,写入"Hello World"
第二步:使用Cheat Engine附加进程
第三步:找到"Hello World"的线性地址
注意:这里搜索到三个结果,需要判断哪个是缓存,哪个才是真正的线性地址
将Hello World的最后一个字符’d’改为’m’,保存
线性地址最终确定为:0104FE58
第五步:将线性地址拆分为2-9-9-12四组比特组
0 1 0 4 F E58
=
0000 0001 0000 0100 1111 E58
=
00 // 0x0
000001000 // 0x8
001001111 // 0x4F
E58 // 12个比特位刚好三个字节
第六步:获得进程的Cr3
在WinDbg中输入命令:!process 0 0
DirBase的值就是进程的Cr3
第六步:通过Cr3找到字符串的物理地址
第一层:PDPT表
线性地址前两位比特位为0,所以找下标为0的PDPTE
第二层:PDT表
乘8是因为每一个PDE占8个字节
第三层:PTT表
乘8是因为每一个PTE占8个字节
第四层:物理页
寻找物理页时就不用再乘8了
使用db命令以字符形式查看数据
实验成功!