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 [![中文](https://img.shields.io/badge/语言-中文-red)](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, 内核漏洞利用, 协议分析, 客户端加密, 权限提升, 逆向工具