2(页目录指针表的索引) 9 (PDI) 9(PTI) 12(物理页的偏移)
PDT 和PTT相当于数组,PDE PDT就是数组里面每一项的值 PDI就是PDE在数组内的索引。PTI也是一样的道理、
为了实现突破4GB寻址,PTE变成了8字节,可寻址范围也变成了FFFFFFFF FFFFFFFF ,那么PDE也必须是4字节位,因为如果PDE是4字节,而PTE超过4GB的时候就找不到PET了。
这种分页方式增大的是PTE,也就是可以识别超过4G的物理内存,10 10 12 只能识别4G,它的PET只有4字节
**实际上2 9 9 12分页模式使用了36位PTE,最大可以识别的物理内存是 64G **
PDPTE的0-11位是属性位 12-35位是PDT的物理地址
X为在PDE和PTE的最高位,在2-9-9-12分页模式下可以设置开启X为来保护程序。一般只保护系统服务,因为这个x位对性能有影响
2-9-9-12分页模式拆解线性地址 找物理页
拆分的地址是: 0x12ff60
线性基址c0600000
2 9 9 12分页没有指向cr3的线性地址地址。
CPU 可读 可写 可执行判断
可读 可写的判断
mov eax,ebx
ebx就是要进行可读判断 eax进行可写判断
可执行判断,如果PDE PTE其中任何一个的最高位是1 那么这个指令就会执行失败。
jmp 0x12345678
2-9-9-12 PDE PTE查找公式
// addr 存放的是线性地址
pPDE = (int*)(0xc0600000 + ((addr >> 18) & 0x3ff8));
pPTE = (int*)(0xc0000000 + ((addr >> 9) & 0x7ffff8));
实验 跳转到数据区 修改PDE PTE属性 实现执行代码:
#include "stdafx.h"
typedef struct
{
DWORD PDPTE_index;
DWORD PDI;
DWORD PTI;
DWORD Page_index;
}PAGE_EXTEND,*PPAGE_EXTEND;
void ParsePage(DWORD dwAddress,PPAGE_EXTEND pPage)
{
pPage->PDPTE_index=dwAddress>>30;
pPage->PDI=dwAddress>>21&0x1ff;
pPage->PTI=dwAddress>>12&0x1ff;
pPage->Page_index=dwAddress&0xfff;
printf("%x\n%x\n%x\n%x\n",pPage->PDPTE_index,pPage->PDI,pPage->PTI,pPage->Page_index);
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={0xc3};
PAGE_EXTEND page;
printf("a=%x\n",&a);
ParsePage((DWORD)&a,&page); //以2 9 9 12分页方式解析数组a地址
__asm{
lea eax,a
call eax //跳转到数据区地址a
}
int i=0;
while (1)
{
printf("i=%d\n",i++);
}
}
可以看到数组a对应的PTE属性最高位是1,把它改为0 即可实现数据区执行代码、