kuzeyardabulut/CVE-2024-1065
GitHub: kuzeyardabulut/CVE-2024-1065
针对 ARM Mali GPU 内核驱动 CVE-2024-1065 UAF 漏洞的页缓存提权 PoC,演示通过竞争重用已释放物理页面覆盖 SUID binary 代码段以实现 root 权限。
Stars: 0 | Forks: 1
# CVE-2024-1065 — 页缓存利用 PoC
CVE-2024-1065 漏洞的概念验证(PoC)利用程序,这是 ARM Mali GPU kernel 驱动程序中的一个物理页面释放后重用(UAF)漏洞。该利用程序演示了**页缓存利用**:通过竞争将一个已释放的 `MIGRATE_MOVABLE` 页面作为 SUID binary 的内存代码镜像,然后覆盖它以在磁盘上不修改任何文件的情况下,以 root 身份实现任意代码执行。
## 工作原理
1. **触发 UAF** — 通过 `KBASE_IOCTL_MEM_IMPORT` 将一个匿名页导入 Mali GPU 驱动,并将其映射两次到用户空间。释放这两个映射会将物理页面返回给 `MIGRATE_MOVABLE` buddy freelist,而 `cpu_mapping2` 仍然是它的别名引用。
2. **喷射页缓存** — 利用程序打开 `/usr/bin/passwd` 100 次,并使用 `posix_fadvise(POSIX_FADV_DONTNEED)` 反复驱逐 `PAGE_OFFSET` 处的页面,然后通过 `pread` 触发缓存未命中。每次未命中都会迫使 kernel 分配一个新的 `MIGRATE_MOVABLE` 页面,不断循环遍历 freelist,直到 UAF 页面被选中。
3. **确认重叠** — 通过 `cpu_mapping2` 在 `MAIN_OFFSET` 处读取探测字节,确认 UAF 页面现在支持该 binary 的页缓存条目。值 `0x00` 和 `0x61` 表示失败;其他任何值都是真实的 binary 代码。
4. **注入 shellcode** — 通过 `cpu_mapping2` 执行 `memcpy`,用调用 `setuid(0)`、`setgid(0)` 和 `execve("/bin/sh")` 的 shellcode 覆盖 `main()`。
5. **执行** — 调用 `execve("/usr/bin/passwd")`。ELF 加载器将 binary 的页缓存页面映射为可执行。损坏的页面已经存在 —— 不会发生磁盘读取 —— 因此 shellcode 以 root 身份运行。
## 环境要求
| 要求 | 值 |
|---|---|
| 架构 | x86-64 |
| Kernel | 5.15 (在 `5.15.0+` 上测试) |
| Kernel 配置 | `CONFIG_MALI_NO_MALI=y`, `CONFIG_MALI_CSF_SUPPORT=y`, `r48` |
| 设备 | 用户空间可访问 `/dev/mali0` |
| 目标 binary | `/usr/bin/passwd` (SUID 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 /* file offset of the page containing main() */
#define MAIN_OFFSET 0xbc0 /* intra-page offset of main() */
```
要针对其他不同的 binary,可以通过在入口点地址(`readelf -h`)反汇编 `_start` 来找到函数偏移量,然后计算:
```
PAGE_OFFSET = sym_va & ~0xfff
MAIN_OFFSET = sym_va & 0xfff
```
运行前请验证:
```
dd if= bs=1 skip=$((PAGE_OFFSET + MAIN_OFFSET)) count=8 2>/dev/null | xxd
```
## 故障排除
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 喷射在 100 次尝试后失败 | UAF 页面在竞争窗口前被消耗 | 在触发 UAF 之前预先驱逐目标页面;增加 `NUM_FDS` |
| `kernel BUG at mm/page_poison.c` | 探测检查在 `0xaa` 的页中毒字节上通过 | 在确认检查中添加 `probe != 0xaa` |
| `SYSCHK` 在 `MEM_IMPORT` 上失败 | Mali 驱动未加载或版本不正确 | 检查 `CONFIG_MALI_NO_MALI` 和驱动程序版本握手 |
## 参考
- [CVE-2024-1065 — Project Zero bug 报告](https://project-zero.issues.chromium.org/issues/42451668)
- [Dirty Pagetable — Black Hat USA 2023](https://yanglingxi1993.github.io/dirty_pagetable/dirty_pagetable.html)
- [The Dirty Pipe Vulnerability (CVE-2022-0847)](https://dirtypipe.cm4all.com)
标签:0day挖掘, ARM Mali, PoC, UAF漏洞, Web报告查看器, 内核安全, 协议分析, 安全渗透, 客户端加密, 暴力破解, 权限提升