cuteaplane/GhostLock-for-OnePlus15T
GitHub: cuteaplane/GhostLock-for-OnePlus15T
针对锁定 Bootloader 的一加 15T 设备,利用 Linux 内核 Futex PI 漏洞(CVE-2026-43499)获取 Root 权限并加载 KernelSU 的提权利用工具。
Stars: 0 | Forks: 0
# GhostLock — OnePlus 15T
[](README_CN.md)
针对锁定 bootloader 的 OnePlus 15T 设备的内核漏洞利用程序。利用 **CVE-2026-43499** 获取 root 权限,**无需解锁 bootloader 或修改 boot.img**。
## 目录
- [漏洞概述](#vulnerability-overview)
- [支持的设备](#supported-devices)
- [前置条件](#prerequisites)
- [编译](#building)
- [用法](#usage)
- [运行模式](#run-modes)
- [技术细节](#technical-details)
- [文件结构](#file-structure)
- [添加新设备](#adding-new-devices)
- [FAQ](#faq)
## 漏洞概述
| 项目 | 详情 |
|------|--------|
| **CVE** | CVE-2026-43499 |
| **类型** | Futex PI (Priority Inheritance) Use-After-Free |
| **范围** | Linux kernel 2.6.39 ~ 7.1 |
| **修复版本** | Mainline 7.1 (commit `3bfdc63936dd`) |
| **Android 状态** | GKI 6.12.x **仍然易受攻击** |
### 根本原因
`pselect6` 系统调用将 `fd_set` 复制到内核栈中。当与 futex PI 等待者机制结合使用时,已释放的栈帧可以被重新分配为 `rt_mutex_waiter` 结构体。在 PI 链遍历期间,rb-tree 的重平衡会将受控数据写入任意的内核地址。
### 漏洞链
```
futex PI UAF (CVE-2026-43499)
├─ Forge rt_mutex_waiter object
├─ Control kernel stack via pselect/select fd_set layout
├─ Trigger rt_mutex PI operation for arbitrary write
├─ Write 1: selinux_state.enforcing = 0
└─ Write 2: cred → init_cred (uid=0, full capabilities)
```
## 支持的设备
| 设备 | 代号 | SoC | Kernel | 固件 | 状态 |
|--------|----------|-----|--------|----------|--------|
| OnePlus 15T | PLZ110 | SM8850 (Snapdragon 8 Elite) | `6.12.38-android16-5-g844001fb8721-ab14552068-4k` | ColorOS 16.0.9.400 | ✅ 已验证 |
关于 Ace 6T 和 OnePlus 15,请参阅原始仓库。
## 前置条件
### ksud (KernelSU 必需)
GhostLock 负责处理提权。安装 KernelSU 需要 **ksud**(随特定于 KMI 的 `kernelsu.ko` 一起捆绑提供):
| 来源 | 备注 |
|--------|-------|
| **ReSukiSU APK** (推荐) | 安装 [ReSukiSU](https://github.com/ReSukiSU/ReSukiSU);该 APK 内含 `libksud.so` |
| **CI Release** | 从 [ReSukiSU CI](https://github.com/cctv18/ReSukiSU_CI/releases) 下载 (`ksud-aarch64-linux-android.zip`) |
## 编译
### 前置条件
- Android NDK (r25+)
- 设置 `ANDROID_NDK_HOME` 或 `ANDROID_NDK_ROOT`
### 编译
```
# 默认 (API 35)
make
# 指定 API level
make API=34
# 指定 NDK path
NDK=/path/to/android-ndk make
```
### 产物
`ghostlock` — 静态链接的 ARM64 ELF 可执行文件。
## 用法
### 一次性设置
```
# 1. 启用 ADB TCP 模式
adb tcpip 5555
# 2. 推送 ADB key(bootstrap 模式必需)
adb push ~/.android/adbkey /data/local/tmp/a/adbkey
# 3. 推送 exploit
adb push ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
```
## 运行模式
### 完整漏洞利用 (ADB shell 上下文)
```
/data/local/tmp/a/e
```
- perf 可用,精准泄漏子进程 task_struct
- 两阶段:W1 禁用 SELinux → W2 提权 → 加载 KernelSU
### Bootstrap 模式 (App 上下文,受 seccomp 限制)
```
/data/local/tmp/a/e --bootstrap
```
1. **Write 1** → 禁用 SELinux
2. 利用已释放的权限通过 `setprop` 启用 ADB TCP 5555
3. 内置的 Mini ADB 客户端连接到 `127.0.0.1:5555`
4. 使用预推送的密钥进行 RSA 认证
5. 通过 ADB shell 执行完整的漏洞利用 (无 seccomp)
### 仅 Write 1
```
/data/local/tmp/a/e --write1
```
- 最多尝试 20 次
- 适用于调试或临时禁用 SELinux
## 技术细节
### 1. 运行时内核匹配
偏移量存储在 `src/devices/offsets.h` 查找表中,以 `uname -r` 作为键。程序在启动时自动匹配;未知的内核将被拒绝。
```
static const struct kernel_offsets known_offsets[] = {
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14275539-4k", ...),
OFFSETS_ENTRY("6.12.38-android16-5-...-ab14552068-4k", ...),
OFFSETS_ENTRY("6.12.23-android16-5-...-ab14541642-4k", ...),
{ .uname_r = NULL } /* sentinel */
};
```
#### 偏移量来源
| 类型 | 数量 | 提取方式 |
|------|-------|------------|
| kallsyms 全局符号 | 28 | `tools/extract_target.py` |
| BTF 结构体字段 | 57 | `tools/extract_btf.py` |
| 派生值 | 9 | 自动计算 |
| 固定常量 | 12 | 硬编码 |
#### 经 BTF 验证的结构体
| 结构体 | 字段数 | 用途 |
|--------|--------|---------|
| `task_struct` | 17 | 进程描述符,cred,seccomp |
| `rt_mutex_waiter` | 6 | UAF 伪造目标 |
| `cred` | 4 | 凭据,capabilities |
| `seccomp` | 3 | seccomp 过滤器状态 |
| `pipe_inode_info` | 11 | pipe 缓冲区操作 |
| `file_operations` | 13 | 伪造的 fops 表 |
| `mm_struct` | 1 | 内存描述符所有者 |
### 2. KASLR 绕过
#### SLIDE 模式 — boot_id 泄漏
当内核指针受限时 (`kptr_restrict`),通过被内核地址覆盖的 `boot_id` 泄漏基地址:
```
Read /proc/sys/kernel/random/boot_id
└─ UUID contains nfulnl_logger address
└─ KASLR slide = leaked_addr - image_offset
└─ kaslr_base
```
#### FOPS/CFI 模式 — fops 表泄漏
当 ashmem 设备可访问时,使用 configfs 读/写原语从 ashmem fops 表中读取函数指针,并计算 KASLR 偏移量。
### 3. 内核堆喷射
在 order-3 (32KB) 页面上伪造内核对象:
- **伪造的 `file_operations`** — 劫持 ashmem miscdevice fops 指针
- **伪造的 `rt_mutex_waiter`** — 模拟 PI 链等待者节点
- **伪造的 `task_struct`** — PI 遍历期间的 task 引用
- **伪造的 `rt_mutex` (lock)** — 正确的等待者/所有者信息
通过 **SKB (socket buffer)** + **KernelSnitch** 实现:
- **KernelSnitch** — futex 哈希冲突,用于泄漏 `mm_struct` 地址
- **SKB 喷射** — `sendmsg` 填充内核堆
### 4. 物理内存读写 (Pipe)
获取 KASLR 基地址后,使用 pipe 缓冲区进行物理级别的内存访问:
```
1. Locate pipe buffer in physmap
2. Forge pipe_buffer ops table pointing to known pipe_buf_ops
3. Hijack pipe_buffer.page to target physical address
4. Arbitrary physical read/write via normal pipe operations
```
支持:`pipe_read64`, `pipe_write64`, `pipe_phys_read_data`, `pipe_phys_write_data`
### 5. 两阶段写入
#### Write 1 — 禁用 SELinux
```
Target: selinux_state.enforcing (offset 0x00)
Method: child-node PI write → forge waiter __rb_parent_color
pointing to selinux_enforcing - 8
rb-tree rebalance writes 0x00
```
#### Write 2 — 提权至 Root
```
Target: child process cred pointer
Method: 1. fork child → perf_find_task() locate task_struct
2. calculate cred field offset
3. child-node PI write → cred = init_cred (uid=0, full caps)
4. clear seccomp (TIF_SECCOMP + seccomp struct zeroed)
```
在覆盖 cred 后会执行 capability 回读验证。
### 6. 内置 Mini ADB 客户端
`src/core/miniadb.c` — 用于 bootstrap 模式的轻量级 ADB 协议客户端:
```
1. TCP connect 127.0.0.1:5555
2. A_CNXN → connection request
3. A_AUTH → RSA token challenge
4. dlopen("libcrypto.so") → PEM_read_bio_RSAPrivateKey → RSA_sign
5. A_AUTH (AUTH_SIGNATURE) → signed response
6. A_CNXN → connection established
7. A_OPEN "shell:/data/local/tmp/a/e" → full exploit
```
支持 SHA-1 和 SHA-256 签名算法。
## 文件结构
```
ghostlock-oneplus/
├── Makefile # Build configuration (NDK cross-compile)
├── README.md # Documentation
├── src/
│ ├── core/ # Core exploit code
│ │ ├── main.c # Entry point: two-stage write + root shell
│ │ ├── fops.c # FOPS/CFI mode: pselect route, PI write, KASLR leak
│ │ ├── util.c # Utilities: heap spray, KASLR, kernel R/W primitives
│ │ ├── slide.c # SLIDE mode: boot_id KASLR leak + pselect route
│ │ ├── pipe.c # Pipe buffer physical memory R/W (physrw)
│ │ ├── root.c # Cred overwrite, seccomp clear, root child mgmt
│ │ ├── miniadb.c # Built-in ADB client (TCP + RSA auth)
│ │ ├── common.h # Global macros, structs, declarations, constants
│ │ ├── target.h # Target memory layout / struct offsets / KASLR params
│ │ ├── offset.h # Compile-time target config bridge (#include TARGET_CONFIG_H)
│ │ └── kernelsnitch/ # KernelSnitch — mm_struct address leak
│ │ ├── kernelsnitch.h # Core algorithm: futex hash collision + brute-force
│ │ ├── futex_hash.h # Futex hash function
│ │ ├── timeutils.h # CPU timestamp measurement (RDTSC)
│ │ └── utils.h # Helper macros (pr_info / SYSCHK / ASSERT etc.)
│ └── devices/ # Device offset tables
│ ├── offsets.h # Aggregate all device offsets (lookup table + sentinel)
│ ├── ace6t/offsets.h # OnePlus Ace 6T offsets (2 kernel versions)
│ └── op15/offsets.h # OnePlus 15 offsets (1 kernel version)
└── tools/ # Offset extraction toolchain
├── extract_target.py # Extract kallsyms global symbol offsets (28 items)
└── extract_btf.py # Extract BTF struct field offsets (57 items)
```
### 核心模块概述
| 模块 | 文件 | 职责 |
|--------|---------|----------------|
| **Entry** | `main.c` | CLI 解析,W1/W2 调度,bootstrap 流程 |
| **PI Route** | `fops.c` / `slide.c` | pselect/select 栈布局,futex PI 链操纵 |
| **KASLR** | `util.c` / `fops.c` / `slide.c` | 双模式绕过:boot_id 泄漏 + fops 表泄漏 |
| **Heap Spray** | `util.c` | Order-3 页分配,SKB 喷射,伪造对象布局 |
| **Phys R/W** | `pipe.c` | pipe 缓冲区劫持,任意物理内存访问 |
| **Priv Esc** | `root.c` | cred 覆盖,capability 验证,seccomp 清除 |
| **ADB** | `miniadb.c` | 轻量级 ADB 协议客户端,RSA 认证 |
| **Leak Engine** | `kernelsnitch/` | 利用 futex 哈希冲突获取 mm_struct 位置 |
## 添加新设备
本仓库已被修改;详情请参阅原始仓库。
## FAQ
### 问:运行时没有输出?
请确保您正在 **ADB shell** 中运行。App 上下文需要使用 `--bootstrap`。
### 问:提示 "no offsets for this kernel"?
您的内核版本尚未受支持。请按照 [添加新设备](#adding-new-devices) 提取偏移量并重新编译。
### 问:Write 1 一直失败?
- 确保绑定到了正确的 CPU 核心 (`CORE` 宏)
- 微调 `PSELECT_ENTER_DELAY_USEC` 时序
- 检查是否有其他进程产生干扰
### 问:Write 2 的 perf 返回 0?
- 检查 seccomp 是否拦截了 `perf_event_open` (在 app 上下文中使用 `--bootstrap`)
- 验证 KASLR 绕过是否成功 (`kaslr_base` 有效)
### 问:KernelSU 没有加载?
- 确认 `ksud` 存在且具有可执行权限
- 检查网络策略文件完整性 (`load_policy` 修复)
## 许可证
**仅限授权的安全研究和教育用途。**
标签:Android, Bootloader, C/C++, DSL, Web报告查看器, 事务性I/O, 内核漏洞利用, 协议分析, 客户端加密, 权限提升, 逆向工具