首页
社区
课程
招聘
[求助]内核页表随机化的计算公式
2021-6-6 22:41 9270

[求助]内核页表随机化的计算公式

2021-6-6 22:41
9270

看了 hzqst 大表哥的文章 [原创]逆向TesSafe.sys有感:鹅厂是如何定位随机化的PTE_BASE,得到4个基址的计算公式分别为:

1
2
3
4
pte_base = (index << 39) | FFFF000000000000;
pde_base = (index << 30) | pte_base;
ppe_base = (index << 21) | pde_base;
pxe_base = (index << 12) | ppe_base;

实际测试后也确实是这样,想知道上面的公式是通过简单的找规律逆运算出来的,还是说微软对这些地址的排布有一定的讲究?希望大家能解答一下我的问题,谢谢。


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞4
打赏
分享
最新回复 (13)
雪    币: 665
活跃值: (995)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lytywg 2021-6-7 04:08
2
0
就是PTE正好需要512G才能映射完,各级页表依次在PTE后面,因为这样写比较方便所以微软就这样写了,没别的理由
雪    币: 2418
活跃值: (2282)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dearfuture 2021-6-7 09:32
3
0
index是自映射项的下标,一旦index确定了,页表基址就确定了。也可以反过来说,一旦页表基址确定了,index就确定了。
这种一一对应的关系是由windows的页表顺序连续映射方案决定的。PTE_BASE一定映射虚拟地址0,PTE_BASE[1]一定映射虚拟地址1...以此类推,接下来一定有一个PTE_BASE[index]映射PTE_BASE,这个index就是自映射项的下标,而且PTE_BASE[index][index]映射PTE_BASE[index](也就是PDE_BASE)...用简单的数学知识推一下就能得出这些公式了
雪    币: 1226
活跃值: (1605)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
烟花易冷丶 2021-6-7 14:17
4
1


最后于 2021-6-7 14:22 被烟花易冷丶编辑 ,原因:
雪    币: 1226
活跃值: (1605)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
烟花易冷丶 2021-6-7 14:23
5
0
不太会看雪的编辑方式..总会存在大量空白,勉强看吧
雪    币: 741
活跃值: (554)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小白iii 2021-6-9 07:23
6
0
烟花易冷丶 不太会看雪的编辑方式..总会存在大量空白,勉强看吧
请问 PTE 只有一个固定值,PMDL4 有 4 个固定值应该怎么理解呢
雪    币: 741
活跃值: (554)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小白iii 2021-6-9 07:24
7
0
lytywg 就是PTE正好需要512G才能映射完,各级页表依次在PTE后面,因为这样写比较方便所以微软就这样写了,没别的理由
可能是我钻牛角尖了,这边思路没缕过来。
雪    币: 3446
活跃值: (3708)
能力值: ( LV8,RANK:131 )
在线值:
发帖
回帖
粉丝
coneco 2 2021-6-10 21:44
8
0
你先计算出Win10 1607以前,0x1ED这个index是怎么得来的,(自己用windbg本地内核调试算一下),然后观察规律。最后观察Win10 1607之后的index的变化。
你提到的公式的左移操作数(39,30,21,12)都相差9,这个你观察Win10 1607以前的index能知道原因。
雪    币: 3446
活跃值: (3708)
能力值: ( LV8,RANK:131 )
在线值:
发帖
回帖
粉丝
coneco 2 2021-6-10 21:46
9
0
给你看一下win8.1下这个0x1ED代表什么意思:
已知当前进程的CR3为35d02000,
kd> !dq 35d02000+1ed*8 l1
#35d02f68 80000000`35d02863
注意,这里的PFN仍然是35d02
雪    币: 665
活跃值: (995)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lytywg 2021-6-12 16:03
10
1
小白iii 可能是我钻牛角尖了,这边思路没缕过来。

我之前没说全,整理下思路吧
1. 让PTE_BASE按照512GB对齐实现自映射,所以微软设计成PTE_BASE就是某一项PML4E,这一项的索引记为index,为什么微软要这样设计呢,很简单就是这样的写法比较好,其它实现也有,但是没这种好。


2. 页表是自映射的,你把PML4T的物理地址放在某一个PML4E里面,寻到页表底的时候,PFN指向的是PT, 表现在虚拟地址上不就是PTE_BASE吗


3.假设把PML4T的物理地址放在某一个PDPTE里面,寻到表底指向的是PDT,也就是PDE_BASE,但此时不需要放专门往某个PDPTE写入PML4T物理地址了,只是解释下连续映射各级BASE的原理,接下来就是自映射的性质了,当你读PTE_BASE+(index << 30)时,此时读到的虚拟地址对应的是的内容是PDPT的index项, 因为该PDPT的物理地址就是PML4T,PML4T的index项的PFN又写成PML4T的物理地址>>12, 产生了套娃(所谓的自映射),所以该PDPE项的PFN是PML4T的物理地址 >> 12,寻到表底PFN指向的是PDT,所以那个地方就是PDE_BASE


4. PPE_BASE及PXE_BASE依此类推


5.所以index就是通过对比PML4T的物理地址和某一项PML4E指向的物理地址来确定

最后于 2021-6-12 16:21 被lytywg编辑 ,原因:
雪    币: 3377
活跃值: (3412)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2021-6-12 21:15
11
0
评论很精彩,感谢分享!
雪    币: 741
活跃值: (554)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小白iii 2021-6-12 22:44
12
0
lytywg 小白iii 可能是我钻牛角尖了,这边思路没缕过来。 我之前没说全,整理下思路吧1.&nbsp;让PTE_BASE按照512GB对齐实现自 ...
二级页表自映射刚完全搞懂,现在换成4级以后,又有点乱了。
雪    币: 2063
活跃值: (3823)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lhxdiao 2021-6-12 23:07
13
0
基址可以通过index计算出来,反之亦可,这种是通过Windows特征码判断是否可用的,可能以后Windows 10更新就把这个特性又改了
雪    币: 741
活跃值: (554)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小白iii 2021-6-13 00:58
14
0

对于二级页表,我自己的推断是这样的,感觉逻辑是行得通的,四级页表的推算卡住了一步,再想不通我就准备先放着了:

PDT 是页目录表,保存了 1024 个 PDE,指向 1024 个 页表。

PT 是页表,保存了 1024 个 PTE,每一项索引一个页面,一个页表管理 4MB 的页面。

CR3 指向页目录表,其中 PDT[0] 指向第一个 PT,PDT [0] [0] 指向第一个 PTE

由于 PDT 本身占用 4KB,所以在 4MB 个 PTE 中,肯定存在一个 PTE 指向 PDT 基址。

假设 PTE_BASE 为 0xXXXXXXXX,则可以计算出他的 index 和 PDI 分别为  

由于PTE_BASE 一定对齐到了 4MB,所以找到页目录中的第一项就是 PTE_BASE

假设基址是 D0000000,其对应的 index 为 D0000000 / 4kb = D 0000,对应的 PDI 为 832

又因为 PTE_BASE 是 PTE基址,所以要求 C0000000 能够直接找到 PDT[0],即页目录表基址 ,为了满足这一条件,要求 PDT[index] 刚好可以获取到 PDT 的地址,二次寻址找到的就是 PDT[0]

除了存在 PTE_BASE[index] == PTE_BASE 外,由于 PDE_BASE 也使用了一个分页,所以也会存在页表中,即 PTE_BASE[index2] == PDE_BASE。前面已经推算出,PDT[index] 就是当前的页目录,所以可以通过 PDI 先找到 PDT,再通过 PDI 就能找到页目录的基址了。


最后于 2021-6-13 01:00 被小白iii编辑 ,原因:
游客
登录 | 注册 方可回帖
返回