Spectre主要利用了分支预测和乱序执行的漏洞实现的。
本文内容主要源于Meltdown & Spectre原理简要梳理

1. 背景

由于在指令中存在许多跳转和分支,为了提前访问分支中的代码以解决时间,我们加入了分支预测功能

1.1 静态分支

对于所有的跳转指令,我们都预测执行跳转或者执行不跳转,称其为静态跳转

1.2 动态分支

动态分支将会通过历史跳转信息来预测下一次分支应该选择跳转还是选择不跳转。在intel设计中有一个称为BTB(Branch Target Buffer)的部件,当我们执行分支指令时,会将执行结果和分支指令地址记录在其中,当下次取址时,查询其中的记录,若存在,则根据历史执行记录进行预测是否跳转。

若不存在此记录,将会使用静态分支预测。

2. 过程

1
2
if (x < array1_size)
y = array2[array1[x] * 256];

如上所示的代码,看起来很正常,若x小于array1的长度的时候,循环顺利执行。

但是我们假设这里有一个存储密码的变量地址为secret,并且令a = secret-array1
于是我们可以使用array1[a]来表示密码的值。

步骤如下:

  1. 在此段代码之前,添加相关代码,使x满足分支条件;
  2. a的值赋值给x
  3. 分支预测模块会认为x < array1_size满足分支条件,因而会预执行y = array2[array1[x] * 256]
  4. 其实y = array2[array1[x] * 256]并不会执行,但CPU会预执行此段代码,然后将存储密码的值作为index,去访问array2。CPU最终发现不应执行该分支,于是刚才取出来的值将会被作废。但是array2[密码]已经被存入到CPU cache中。
  5. 利用侧信道攻击(Side-channel attack),可以获取到密码。

参考资料:

  1. Meltdown & Spectre原理简要梳理
  2. stackoverflow Spectre example