其他
四级分页下的页表自映射与基址随机化原理介绍
本文为看雪论坛精华文章
看雪论坛作者ID:REPE
一
x64分页基础
1、介绍
2、实例
kd> r idtr
idtr=fffff8037888e000
kd> dq fffff8037888e000
fffff803`7888e000 761e8e00`00107e00 00000000`fffff803
fffff803`7888e010 761e8e04`00108140 00000000`fffff803
fffff803`7888e020 761e8e03`00108600 00000000`fffff803
fffff803`7888e030 761eee00`00108ac0 00000000`fffff803
fffff803`7888e040 761eee00`00108e00 00000000`fffff803
fffff803`7888e050 761e8e00`00109140 00000000`fffff803
fffff803`7888e060 761e8e00`00109680 00000000`fffff803
fffff803`7888e070 761e8e00`00109b80 00000000`fffff803
fffff803`7888e000 -> f803`7888e000
1 1111 0000 0x1f0 PML4I
0 0000 1101 0xd PDPTI
1 1100 0100 0x1c4 PTI
0 1000 1110 0x8e PDI
000000000000 0x0 Offset
kd> r cr3
cr3=0000000052c76000
kd> !dq 52c76000+1f0*8
#52c76f80 00000000`00c08063 00000000`00000000
#52c76f90 00000000`00000000 00000000`00000000
#52c76fa0 00000000`00000000 00000000`00000000
#52c76fb0 0a000000`0bafc863 00000000`00000000
#52c76fc0 00000000`00000000 00000000`00000000
#52c76fd0 00000000`00000000 00000000`00000000
#52c76fe0 00000000`00000000 00000000`00000000
#52c76ff0 00000000`00000000 00000000`00ca8063
kd> !dq c08000+d*8
# c08068 00000000`00c09063 00000000`00000000
# c08078 00000000`00000000 00000000`00000000
# c08088 00000000`00000000 00000000`00000000
# c08098 00000000`00000000 00000000`00000000
# c080a8 00000000`00000000 00000000`00000000
# c080b8 00000000`00000000 00000000`00000000
# c080c8 00000000`00000000 00000000`00000000
# c080d8 00000000`00000000 00000000`00000000
kd> !dq c09000+1c4*8
# c09e20 00000000`00ca7063 0a000000`03996863
# c09e30 0a000000`0f5bc863 0a000000`0f5bd863
# c09e40 0a000000`0f5be863 0a000000`0f5bf863
# c09e50 0a000000`032c0863 0a000000`032c1863
# c09e60 0a000000`040c3863 0a000000`02bc4863
# c09e70 0a000000`02bc5863 0a000000`02bc6863
# c09e80 0a000000`02bc7863 0a000000`02bc8863
# c09e90 0a000000`02bc9863 0a000000`02bca863
kd> !dq ca7000+8e*8
# ca7470 89000000`0588e121 89000000`0588f963
# ca7480 89000000`05890963 89000000`05891963
# ca7490 89000000`05892963 89000000`05893963
# ca74a0 00000000`00000000 89000000`05895963
# ca74b0 89000000`05896963 89000000`05897963
# ca74c0 89000000`05898963 89000000`05899963
# ca74d0 89000000`0589a963 89000000`0589b963
# ca74e0 00000000`00000000 89000000`0589d963
kd> !dq 0588e000
# 588e000 761e8e00`00107e00 00000000`fffff803
# 588e010 761e8e04`00108140 00000000`fffff803
# 588e020 761e8e03`00108600 00000000`fffff803
# 588e030 761eee00`00108ac0 00000000`fffff803
# 588e040 761eee00`00108e00 00000000`fffff803
# 588e050 761e8e00`00109140 00000000`fffff803
# 588e060 761e8e00`00109680 00000000`fffff803
# 588e070 761e8e00`00109b80 00000000`fffff803
二
页表自映射
1、介绍
2、原理
![Cr3 + 0x100 * 8] = Cr3
0xFFFF8000`00000000 ~ 0xFFFF807F`FFFFF000
// 起始地址
0x8000`00000000
1 0000 0000 0x100
0 0000 0000 0x0
0 0000 0000 0x0
0 0000 0000 0x0
0000 0000 0000 0x0
// 结束地址
0x807F`FFFFF000
1 0000 0000 0x100
1 1111 1111 0x1FF
1 1111 1111 0x1FF
1 1111 1111 0x1FF
0000 0000 0000 0x0
// 起始地址
![Cr3 + 0x100 * 8] = PDPTE
![PDPTE + 0x0 * 8] = PDE
![PDE + 0x0 * 8] = PTE
![PTE + 0x0 * 8] = 物理页面
// 结束地址
![Cr3 + 0x100 * 8] = PDPTE
![PDPTE + 0x1FF * 8] = PDE
![PDE + 0x1FF * 8] = PTE
![PTE + 0x0 * 8] = 物理页面
// 起始地址
![Cr3 + 0x0 * 8] = PDE
![PDE + 0x0 * 8] = PTE
![PTE + 0x0 * 8] = 物理页面
// 结束地址
![Cr3 + 0x1FF * 8] = PDE
![PDE + 0x1FF * 8] = PTE
![PTE + 0x0 * 8] = 物理页面
3、规律
3.1 推导最高级页表 PML4 的基址
属于虚拟地址
虚拟地址的内容是Cr3
![Cr3 + x * 8] = PDPTE
![PDPTE + y * 8] = PDE
![PDE + z * 8] = PTE
![PTE + r * 8] = 物理页面 = Cr3
3.2 推导 PDPT 表的基址
属于虚拟地址
虚拟地址的内容不再是Cr3,而是 ![Cr3 + 0 * 8] 指向的物理地址。
![Cr3 + x * 8] = PDPTE
![PDPTE + y * 8] = PDE
![PDE + z * 8] = PTE
![PTE + r * 8] = ![Cr3]
3.3 推导 PD、PT 表的基址
3.4 结论
PML4:PML4i == PDTi == PDi == PTi == Index
PDPT:PML4i == PDTi == PDi == Index && PTi == 0
PD:PML4i == PDTi == Index && PDi == 0 && PTi == 0
PT:PML4i == Index && PDTi == 0 && PDi == 0 && PTi == 0
三
基址随机化
1、原理
0xFB7DBEDF6000
1 1111 0110 0x1F6 PML4
1 1111 0110 0x1F6 PDPT
1 1111 0110 0x1F6 PD
1 1111 0110 0x1F6 PT
000000000000 0x0
Index为:0x1F6
0x8D46A351A000
1 0001 1010 0x11A
1 0001 1010 0x11A
1 0001 1010 0x11A
1 0001 1010 0x11A
000000000000 0
Index为:0x11A
2、定位
ULONG64 GetPml4Base()
{
PHYSICAL_ADDRESS pCr3 = { 0 };
pCr3.QuadPart = __readcr3();
PULONG64 pCmpArr = MmGetVirtualForPhysical(pCr3);
int count = 0;
while ((*pCmpArr & 0xFFFFFFFFF000) != pCr3.QuadPart)
{
if (++count >= 512)
{
return -1;
}
pCmpArr++;
}
return (ULONG64)pCmpArr & 0xFFFFFFFFFFFFF000;
}
ULONG64 GetPdptBase(ULONG64 ulPml4Base)
{
return (ulPml4Base >> 21) << 21;
}
ULONG64 GetPdBase(ULONG64 ulPml4Base)
{
return (ulPml4Base >> 30) << 30;
}
ULONG64 GetPtBase(ULONG64 ulPml4Base)
{
return (ulPml4Base >> 39) << 39;
}
参考文档:
看雪ID:REPE
https://bbs.pediy.com/user-home-894067.htm
# 往期推荐
1.Android4.4和8.0 DexClassLoader加载流程分析之寻找脱壳点
3.House of cat新型glibc中IO利用手法解析 & 第六届强网杯House of cat详解
球分享
球点赞
球在看
点击“阅读原文”,了解更多!