※ 引述《Sirctal (母猪母猪 夜里哭哭)》之铭言:
: https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6
这code是来自Google关于Spectre的范例程式
https://spectreattack.com/spectre.pdf
献丑一下我只看程式码并稍微参照论文的解读
readMemoryByte()第一个参数是malicious_x、
第二个参数value回传最有可能的两个结果,第三个参数score回传对应的评分(越大越好)
readMemoryByte()会猜测真实位址为(array1真实位址 + malicious_x)的资料
一般来说你对一个只有160bytes的阵列读array1[12345678]肯定会当掉
因为在虚拟内存映射时会找不到(array1的虚拟位址+12345678),
会产生区段错误(Segmentation Fault),于是程式就被OS杀掉了
虚拟内存映射是现代CPU的基础,它令程式可以使用实际上零碎的内存来组成连续的
而且也能保证User级的应用程式彼此从内存上隔离,达成安全性
https://zh.wikipedia.org/wiki/%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98
看wiki比较详细
这份code的核心在victim_function(),原理是基于分支预测
考虑以下程式码:
if (x < array1_size)
{
temp &= array2[array1[x] * 512];
}
x就是malicious_x(不过程式执行时混入安全的training_x,每五次才会用一次malicious)
array1[x]就是我们想捞出来的资料,array1_size是一个小于array1大小的数字
假设x = 123456789,正常来说执行到array1[x]会当掉
所以码农会为这段程式码加上边界检查,当x>=array1_size就会不会跑到array1[x]
就在这时候分支预测登场了,CPU猜测会中 temp &= array2[array1[x] * 512],于是读取
array1[x],然后再读array2[array1[x] * 512]
假设array1[x]是28,那array2[28*512]到array2[29*512-1]这段就会被载进快取
后面再透过测定读取array2每一段512bytes的时间,判断是Cache Hit/Miss
这样就能猜测array1[x]
我的理解是,与Meltdown相比Spectre无法直接给定目标位址,
只能尽可能全倒出来然后去翻找,感觉挺没效率的
不过能够读取array1[12345789]而不会crash就已经很有趣了