SEEDLAB2.0-Spectre Attack Lab

Spectre Attack Lab
Spectre在很多现代处理器中都有,比如Intel、AMD,ARM等
该漏洞允许程序突破进程内、进程间的隔离,如此,恶意程序就能从它不能访问的区域读取数据.本来这不应该发生,对于进程间隔离,有硬件保护机制;对于进程内隔离,有软件保护机制,但是CPU设计导致的缺陷使得攻击成为了可能。

注意,对于本实验的大多数代码,当使用gcc编译时都需要加上-march=native,march标志告诉编译器enable本地机器的所有指令子集。
Meltdown和Spectre都是利用CPU cache作为侧信道来偷取被保护的信息。其中用到的技术称为FLUSH+RELOAD
在这里插入图片描述

在下面的代码中,我们有一个规模为104096的数组。我们首先访问其中两个元素,分贝是array[34096]和array[74096]。因此,包含着两个元素的页就会被cache
然后我们读取元素,从array[0
4096]到array[94096]并测量读取所花费的时间
在代码中,(1)在内存读之前读取CPU的时间戳(TSC),而(2)在内存读之后读取计时器。他们的差值就是花在内存读上的时间。
需要注意,cache在是cache block层次上完成的,而不是byte层次。一个典型的cache block是64字节。我们使用array[k
4096],所以程序用到的元素不会有两个落在相同的cache block中
在这里插入图片描述

编译并运行
在这里插入图片描述

可以看到读取array[34096]和array[74096]时要比读取其他元素快得多

我们来尝试通过侧信道提取victim function会使用的secret value
假设victim function使用secret value作为索引加载array中的某个元素,同时假设该sexret value不能从外部访问到。我们的目标是使用侧信道获得这个secret value
我们使用的技术为FLUSH+RELOAD
在这里插入图片描述

该过程分为三步
1.从cache memory中FLUSH整个数组,确保数组没有被cache
2.调用victim function,它会基于secret value访问数组的一个元素,这个动作会造成相应的数组元素被cache
3.RELOAD整个数组,并测量加载每个元素的时间。如果一个特定的元素的加载时间特别快,那么极有可能是已经在cache中的元素,该元素就是被victim function访问过的,因此,我们就可以知道secret value是什么
代码如下
在这里插入图片描述在这里插入图片描述

编译并运行,结果如下

在这里插入图片描述

来看看下面的代码,代码检查x是否小于size,如果是,data变量将会被更新。假设size是10,那么如果x是15,则第3行不会被执行
在这里插入图片描述

但是从CPU内部看的时候,即使x的值大于size,第3行的代码仍然有可能成功执行。这是因为有乱序执行技术的存在
乱序执行是一种允许CPU最大化利用所有执行单元的技术。
在微架构层次,第2行有两个操作:从memory加载size的值,并将其与x比较。如果size不在cache中,那么当其值被读出来之前可能要花费几百个CPU时钟周期。与保持空转不同,现代CPU会尝试预测比较的结果,并给予预测结果推测地执行分支。
这种执行会在比较结束前启动,称之为乱序执行。在进行乱序执行时,CPU存储着当前的状态以及寄存器的值。当size的值最终得到时,CPU会检查实际的输出。如果预测是对的,那么推测执行的结果会被承认,性能会得到很大的提升。如果预测是错的,那么CPU会恢复回保存的状态,所以乱序执行的结果将会被丢弃仿佛从来没有发生过一样。
这就是为什么从外面看,第3行从来没有被执行过。
在这里插入图片描述

这些CPU清除了乱序执行对寄存器、memory的影响,但是对cache的影响还保留着。
代码如下
在这里插入图片描述

CPU进行推测执行时,他们可以预测if条件的输出。CPU会记录过去的分支情况,并使用这些之前的结果来预测哪个分支将会被采用
因此如果想要一个特定的分支被采用,我们需要训练CPU,这样我们的分支才会成为预测结果
从(3)开始的for训练负责训练这一过程。在训练内部,我们使用一个小的参数调用victim,这些值比size小,所以(1)的if条件的true分支总是会被采用。这是训练过程,其训练CPU期待if条件总是为true
一旦CPU训练好,我们传一个较大的值97给victim()(5),这个值比size大,所以实际执行的时候,if条件是false分支会发生,而不是true分支。然而,我们从memory中flush了size变量,所以从memory中获取它的值的时候需要等一会儿。
这就是CPU什么时候会做出预测,以及启动推测执行
在这里插入图片描述

编译并运行
在这里插入图片描述

可以看到,(2)会被执行

通过上面的实验,我们知道即使条件是false,我们也可以让CPU去执行true分支

在同一个浏览器访问来自不同server的web页面时,它们经常在同一个进程中被打开。在浏览器内部提供的沙盒机制为这些页面提供了隔离机制,所以一个页将不能访问另一个页的数据。大多数软件保护依赖于条件判断来决定某访问是否得到允许。在Spectre 攻击中,及时条件检查失败,我们也可以让CPU执行被保护代码的分支。
在这里插入图片描述

实验环境如上。其中有两个区域:一个是受限的区域,一个是不受限的区域。限制是通过一个在沙盒函数中实现的条件语句实现的。
代码如下
在这里插入图片描述

沙盒函数只有对于用户提供的x,当x小于buffer中的size时,返回buffer[x]的值;否则,不会返回任何东西。因此,这个沙盒函数在受限区域内永远不会返回任何东西给用户。
在受限区域内有secret value,它的地址攻击者是知道的,然而攻击者不能直接访问有secret value的内存。唯一可以访问secret的方法就是通过上述的sandbox函数。
在(1)定义了secret。假设我们不能直接访问secret变量或者buffer_size变量(我们假设我们可以从cache中flush buffer_size)
我们的目标是通过sepctre attack打印secret
在这里插入图片描述

最重要的是(2)(3)(4)
(4)计算了secret距离buffer的起始处的偏移。偏移,一定是大于10的,被喂给restrictedAccess()函数。因为我们已经训练CPU在restrictAccess()里走true分支,在乱序执行中,CPU会返回buffer[larger_x],其中包含了secret value
Secret value之后造成其在array中相应的元素被加载到cache中。
所有的这些步骤最终都会被推翻,所以从外部来看,restrictedAccess()只会返回0,而不是secret的值
然而,cache没有被清除,array[s*4096+DELTA]仍然保留在cache中。
现在我们使用侧信道技术找出array[]的哪个元素在cache中即可
编译并执行
在这里插入图片描述

成功了

在第一次运行的时候可以看到有噪音,结果并不总是正确的
这是因为CPU有时会加载额外的值到cache中,希望它能够在之后被使用,或者阈值不是非常精确
cache中的噪声会影响我们攻击的结果
我们需要执行攻击多次
我们可以使用统计学技术
创建一个规模为256的score数组,一个元素对应一个可能的secret value
之后运行攻击多次

在这里插入图片描述在这里插入图片描述

编译并运行
在这里插入图片描述

当运行时可以看到,scores[0]总是有最高的分数。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值