写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
看此教程之前,问几个问题,
🔒 华丽的分割线 🔒
练习及参考
1️⃣ 拆两个进程的4GB
物理页。
2️⃣ 定义一个只读类型的变量,再另一个线性地址指向相同的物理页,通过修改PDE
/PTE
属性,实现可写。
3️⃣ 分析0x8043F00C
线性地址的PDE
属性。
4️⃣ 修改一个高2G线性地址的PDE
/PTE
属性,实现Ring3
可读。
5️⃣在0
线性地址挂上物理页并执行shellcode
调用MessageBox
。
6️⃣ 逆向分析MmIsAddressValid
函数。
PAE 分页
PAE
分页是啥,其实他就是2-9-9-12
分页的英文缩写。为什么要有2-9-9-12
分页,其实还是物理页不够用了,需要扩展。但想要足够的物理页,位数在那里,你想大也大不了。那么我就需要扩展物理页地址的位数,于是乎2-9-9-12
分页诞生了,它整体分页的结构如下:
与10-10-12
分页不同的地方就是,多了一层名为页目录指针表
的东西,英文缩写为PDPTT
。每个PDE
和PTE
被扩展为8个字节,物理地址描述的位数扩展为24位
,故可以描述更多的物理页,但个数减半,变成了512个。下面详细查看它们的结构。
首先看PDPTT
的结构。由2-9-9-12
的2
可知第一部分由两位二进制组成,那么最多有4种结果。也就是为什么有五个成员,它的结构如下图所示:
然后是PDE
,既然学过了10-10-12
分页,直接看下面的结构示意图吧:
非大页
大页
然后是PTE
,同理不多说了:
我们之前做一道作业题目知道,我写的shellcode
写到一个页上,它并没有执行权限,但它不是代码,仍然可以被我执行。为了弥补这个漏洞,Intel
给我们补了一个硬件层面上的漏洞,它是一个位,处于PDE
和PTE
的最高位,如下图所示:
如果最高位是1
,说明被保护。如果这个是数据,且这个X
位被置为1
,则会被报出异常不能执行。反之,和正常的10-10-12
分页没什么两样。
一个进程的线性地址仍是4GB
的线性空间,有再多的物理页有啥用呢?在10-10-12
分页下,假设进程一启动,就把所有的物理页都挂上,且没有任何交换。那么只能启动一个;如果在2-9-9-12
分页下,同样的情况,它可以启动4个进程。这个就是2-9-9-12
分页的意义。
Windows
也提供了基于硬件层面X位
的保护,如下图所示:
可以看出你自己写的普通程序压根和这个位无缘,但是还以启用的。但是有些打开之后发现提出不支持基于硬件的保护,那是因为虚拟机没开这个选项,如下图所示,转中如下图选项即可:
练习
俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习比较多,请保质保量的完成。
1️⃣ 定义一个只读类型的变量,再另一个线性地址指向相同的物理页,通过修改PDE
/PTE
属性,实现可写。
2️⃣ 自己实验有和没有DEP
保护的程序,看看效果。(本题将在下一篇提供参考)
3️⃣ 修改一个高2G线性地址的PDE
/PTE
属性,实现Ring3
可读。
4️⃣ 在0
线性地址挂上物理页并执行shellcode
调用MessageBox
。
5️⃣ 逆向分析MmIsAddressValid
函数。
下一篇
保护模式篇——TLB与CPU缓存