233laoliu/mt6985-CVE-2026-43499

GitHub: 233laoliu/mt6985-CVE-2026-43499

记录了在vivo PD2241(MT6985/天玑9300)上适配CVE-2026-43499内核漏洞利用的失败过程,并留下了符号表、结构体偏移和编译脚本等可用资产。

Stars: 0 | Forks: 0

# CVE-2026-43499 失败记录:MT6985 适配尝试 ## 背景 | 项目 | 值 | |------|-----| | 设备 | vivo PD2241 (Dimensity 9300 / MT6985), Android 15 | | 固件 | PD2241_A_15.2.10.2.W10.V000L1 | | 内核 | 5.15.178-android13-8-gfb31f5bdd612-dirty | | Bootloader | **锁定** (`ro.boot.flash.locked=1`) | | SELinux | **Enforcing** | | panic_on_oops | **开启** → 任何内核 OOPS = 秒重启 | | Exploit | [CyberMeowfia](https://github.com/NebuSec/CyberMeowfia) — CVE-2026-43499 (IonStack) | | 源码树 | android_15.0_kernel_MT6985 (5.15.178) — 与设备版本不匹配 (源码是 android15 GKI, 设备跑 android13 GKI) | ## 做了哪些事 ### 1. 源码分析 → 提取结构体偏移 从 `arch/arm64/include/asm/memory.h` + `include/linux/fs.h` + `android/abi_gki_aarch64.xml` 提取: - **内存布局**: `KIMAGE_TEXT_BASE = 0xffffffc008000000`, `VA_BITS=39`, `DIRECT_MAP=256GB` - **task_struct**: 36864 bits, 完全解析 (ABI XML `layout-offset-in-bits`) - **file_operations**: 无 `iopoll` (android13 GKI), IOCTL=0x48, open=0x68 - **cred**: `atomic_t usage` = 4 字节, uid=0x04 - **struct page**: 64 字节, `slab_cache=0x18` 关键发现: **源码是 android15 GKI, 设备是 android13 GKI**——task_struct 偏移差了 0x40~0x88 字节,不能照抄源码。 ### 2. 固件解包 → 提取符号 ``` OTA zip (8.3GB) → payload.bin (8.2GB) → payload_dumper → boot.img (96MB, v4 header) → LZ4 解压 → Image (50MB ARM64) → kallsyms-finder → 187810 符号 ``` 从两版固件 (15.2.7.6 / 15.2.10.2) 中提取符号——同一个符号两版之间差了 10KB~200KB,**必须用对版本**。 ### 3. 反汇编验证 → capstone 确认关键偏移 ``` # rt_mutex_adjust_pi 中: LDR x21, [x19, #0x8b0] → pi_blocked_on = 0x8b0 (android15 值, 非 frankel) ``` 这确认了 task_struct 布局是 android15 分支,不是 frankel 的 android13。 ### 4. 编译 → 能过 NDK r29, `make PROJECT=android_15.0_kernel_MT6985` → `preload.so` (150KB)。 ### 5. 运行 → 反复崩溃 ``` [+] preload starting pid=25414 [+] p0 profile ... 所有符号正确加载 [-] KernelSnitch mm_struct leak failed ← 有时没这条 (偶尔成功) [+] slide child context route=pselect ← slide KASLR leak 子进程启动 [内核 panic] ← rt_mutex_adjust_prio_chain+0x1b0 ``` 崩溃指令 (capstone): ``` ldar w8, [x27] ; x27 = waiter->lock (从 [x28, #0x38] 加载) ; x27 值是垃圾 → 页表无映射 → translation fault ; → die() → panic → 重启 ``` ## 为什么失败 ### 根因 1: KernelSnitch 在 MTK 上不可靠 KernelSnitch 是整套 exploit 的入口——它通过 futex 哈希桶的**时序差异**泄露 `mm_struct` 地址: 1. **碰撞检测**成功——低阈值下找到 5 个碰撞 2. **bruteforce 匹配**几乎总是失败——核心问题在: ``` MT6985 有 CONFIG_KASAN_HW_TAGS=y → 内核用 MTE 标签标记 slab 分配 mm_struct 的指针带了 KASAN tag → futex_hash 基于 tagged pointer 计算 但 bruteforce 扫描 direct map (untagged 地址) → 算出来的 hash 对不上 即使加上 MTE tag 遍历 (0-14 共 15 种), 在 VA_BITS=39 的系统上 tag 位 (bit56-59) 与符号扩展位重叠 → 有些 tag 组合产生无效地址 → 漏检 ``` **Pixel 设备没有 KASAN_HW_TAGS,这个机制跑得通。MTK 不行。** ### 根因 2: `CONFIG_PANIC_ON_OOPS` 是杀手 ``` Pixel: 内核 OOPS → dump_stack → 继续跑 → exploit 可重试 MT6985: 内核 OOPS → die() → panic() → 秒重启 → 无试错空间 π 链破坏稍有偏差就全盘崩,Pixel 上偏差了只是"这次没成功,换组地址再来"。 ``` 且 bootloader 锁定 (`flash.locked=1`) → 不能刷自定义内核去掉这个选项。 ### 根因 3: 内核版本漂移 ``` 源码树: 5.15.178 android15 GKI 设备: 5.15.178-android13 (vivo vendor) ``` 虽然大版本号都是 5.15.178,但 GKI 分支不同(android13 vs android15),task_struct/cred 等关键结构体布局不一致。反复在 frankel/android15 两套偏移之间切换,最终靠反汇编才锁定。 ## 尝试过的调整 (全部没用) | 改动 | 目的 | 结果 | |------|------|------| | `THRESHOLD_MULT` 10→5→3 | 降低碰撞检测阈值 | <5 假阳性太多 | | `APPENDED_FUTEXES` 4096→8192 | 增大 hash 链差异 | 无效果 | | `REPEAT_MEASUREMENT/AVERAGE` | 增加采样精度 | 无效果 | | `MTE=1` | 让 bruteforce 遍历标签 | 更慢, 反而崩溃减少 | | `MM_STRUCT_SZ` 0x500→0x400 | 修正 mm_struct 步长 | 必要, ABI 实际 992 字节 | | `IDENTITY_END` 64GB→256GB | 扩大扫描范围 | 太慢 (MTE遍历), 仍然不匹配 | | TASK offsets: android15↔frankel | 锁定正确偏移 | 反汇编确认 android15 | | FOPS offsets: android15↔frankel | android13 无 iopoll | 用 frankel | ## target.h 现状 `exploit/targets/android_15.0_kernel_MT6985/target.h` 中: | 类别 | 可信度 | 验证方式 | |------|--------|----------| | 内存布局 | **正确** | memory.h 计算 + kallsyms `_text` 验证 | | 符号偏移 (22 个) | **正确** | 从 15.2.10.2 boot.img 提取 | | task_struct 偏移 | **正确** | ABI XML + capstone 反汇编 (pi_blocked_on=0x8b0) | | FOPS 偏移 | **正确** | ABI XML (android13 布局, 无 iopoll) | | CRED 偏移 | **待验证** | ABI XML (可能有 vendor OEM 字段影响) | **汇编能过, 跑得起来, 输在最后一公里。** ## 如果你要继续 ### 必要条件 (缺一不可) 1. **去掉 `CONFIG_PANIC_ON_OOPS`** — 要么刷自定义内核 (需要解锁 bootloader), 要么找一台默认关闭此选项的 MT6985 设备 2. **解决 KernelSnitch** — 需要 MTK Dimensity 9300 的缓存时序标定, 或者在 exploit 中完全替换 KernelSnitch 为其他 mm_struct 泄露方式 ### 可能的替代思路 - `/proc/self/pagemap` — 本设备已限制 (返回全零) - MTK 特有的调试接口 (`/proc/mtk_*`) — 存在但需要进一步分析 - MTK 相机/GPU 驱动的 ioctl 漏洞 — 更简单的提权路径 - 等社区适配 MTK 变体 ### 本仓库的残余价值 - `symbols/kallsyms_PD2241_15.2.10.2.txt` — 完整的 15.2.10.2 符号表, 后人可以直接用 - `device_config.txt` — 设备实际内核配置, 可以看到 vendor 改了什么 - `exploit/targets/android_15.0_kernel_MT6985/target.h` — 结构偏移已验证 - `scripts/server_compile.py` — 自动化编译, 改参数后重编很快 ## 踩坑清单 (后人避坑用) 1. **文件在 Windows 上解压**: `tar -xf` 对大 zip 可能失败, 用 Python `zipfile` 或先手动解压 2. **payload_dumper 的 protobuf 版本冲突**: 生成的 `update_metadata_pb2.py` 要求 protobuf 5.x, 需要手动删除 `runtime_version` 导入行 3. **直接用 `./preload.so` 运行会 segfault**: 必须用 `/system/bin/linker64 /data/local/tmp/preload.so` 4. **ABI XML 比源码更准**: `layout-offset-in-bits` 是编译器算的, 比手工数 5000 字节准 100 倍 5. **GKI 分支影响 layout**: android13/14/15 的 task_struct 不同, 不能跨分支复制 offset 6. **固件版本不同则符号偏移不同**: 15.2.7.6 和 15.2.10.2 差了 10KB~200KB 7. **vivo vendor 加了大量 OEM 字段**: `CONFIG_ANDROID_VENDOR_OEM_DATA=y`, `CONFIG_SCHED_INFO=y`, `CONFIG_RSC_*` → 偏离标准 GKI 8. **前后端符号提取工具链**: `boot.img → kernel.bin → LZ4 解压 → Image → kallsyms-finder → 符号表` ## 时间线 ``` 07/28 下载 CyberMeowfia 仓库 + MT6985 源码 07/29 源码分析 (memory.h, fs.h, ABI XML, 各种 struct) 固件解包 (payload.bin → boot.img → Image) 符号提取 (kallsyms-finder → 187810 符号) 多轮编译 + 多轮崩溃 + 反汇编验证 5 次自动重试 → 全部失败 写成这篇 ------------------------------------------- 总计: ~68M tokens, 0 root shells ``` *2026-07-29, 活着讲述了这个故事*
标签:Android系统, ARM64架构, 云资产清单, 内核漏洞, 客户端加密, 目录枚举, 移动安全, 逆向工具, 逆向工程