Home Resources

Meltdown

Table of Contents

Meltdown

考虑代码1 , 2 , 3:

1: retry:
2:   mov al, byte [rcx]         // 读取地址 rcx 处一字节的数据到寄存器 rax
3:   shl rax, 0xC               // 将刚读取到数据乘 4096
4:   jz retry
5:   mov rbx, qword [rbx + rax] // 读取 rbx+rax 处的数据(位于我们开辟的用户区数据)
  1. 一页数据为 4096 字节( 1 << 0xC = 4096
  2. rbx 中地址开始 256*4096 长度的内存位于用户区(256 页的数据)。
  3. rcx 中为内核空间的地址

第 1 行代码执行的是非法操作,读取内核空间 rcx 地址的一个字节(设这个字节为 x )到 al ,它会触发异常,但是由于分支预测的存在,第 2、3、4 行可能被先执行,第 2 行将获取的一个字节的数据(该数据范围 0~255 )乘以~4096~ 存在 rax ,访问 rbx+rax 数据,这是用户区数据,它被缓存。

异常处理时,会撤销分支预测时执行的那些代码,清空相关寄存器,因此寄存器里面不会直接存有我们想要的数据(那一个字节)。

漏洞就是,上面最后一步对于用户区数据的缓存没有被撤销。

因此,如果这段代码执行之前我们实现清理缓存确保用户区我们开辟的那 256 页数据没有被缓存,执行这段代码后,这 256 页中有一页是被缓存的,也即 rbx + x*4096 。我们依此访问 rbx + n*4096n: 0~255 )记录这些位置的访问时间,时间最短的那次的 n 就是 x

还有就是第 3 行是干嘛要说明一下,执行第 1 行时触发异常,异常处理时会清空相关寄存器,如果异常处理在执行完第 2 行时就执行,那么~rax~ 将为 0,不是我们需要的值,所以对于这种情况我们跳过。

下图截自 Meltdown1

meltdown-fig-4.png

Figure 1: 展示遍历访问 256 页数据时每页的访问时间,通过 meltdown 攻击缓存的页的数据访问时间明显较短

Footnotes:

Author: lotuc, Published at: 2018-01-15 Mon 00:00, Modified At: 2023-01-18 Wed 14:51 (orgmode - Publishing)