Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-43499-pmg110-root — OPPO PMG110(カーネル6.6)を標的としたCVE-2026-43499用のAndroid LPEエクスプロイト。futex PI UAFを利用してroot権限を取得し、LD_PRELOAD経由でsuデーモンをインストールします。 | Kitploit
ツール/GitHubGitHub/soralis0912/cve-2026-43499-pmg110-root
Androidセキュリティ特権昇格脆弱性分析エクスプロイトポストエクスプロイトペネトレーションテストモバイルセキュリティレッドチーミングペイロード開発

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
バイナリエクスプロイト
GitHubsoralis0912/cve-2026-43499-pmg110-root

CVE-2026-43499-pmg110-root

OPPO PMG110(カーネル6.6)を標的としたCVE-2026-43499用のAndroid LPEエクスプロイト。futex PI UAFを利用してroot権限を取得し、LD_PRELOAD経由でsuデーモンをインストールします。

リポジトリを見る
124日前未レビュー

pmg110-root

CVE-2026-43499 (futex PI rt_mutex_waiter use-after-free) ローカル権限昇格、 OPPO PMG110 / K15 Pro+ — MediaTek MT6991、ColorOS 16 向けに移植。

プッシュするファイルは 1 つだけ。LD_PRELOAD で実行します:

root@kitploit:~
adb push out/preload-pmg110-16.0.9.400.so /data/local/tmp/preload.so
adb shell chmod 644 /data/local/tmp/preload.so
adb shell LD_PRELOAD=/data/local/tmp/preload.so /system/bin/true

成功すると、永続化された su が残されます:

root@kitploit:~
adb shell /data/local/tmp/su -c id      # uid=0(root)

実機で検証済み (2026-07-27): 環境変数の上書きなしの素の実行から約 35 秒で uid=0 を取得し、その後、通常の非特権 adb shell からも su が応答しました:

root@kitploit:~
$ adb shell "/data/local/tmp/su -c 'echo 0 > /proc/sys/kernel/kptr_restrict'"
$ adb shell "/data/local/tmp/su -c 'grep -w init_task /proc/kallsyms'"
ffffffe89033e780 D init_task

このエクスプロイトと su のインストールは、どちらもこのデバイス上で検証済みです。そのルート化されたシェルがその後読み出した内容は、エクスプロイトとは独立に P0_KERNEL_PHYS_LOAD、シンボルオフセット、KS_MTE_TAGGED=0 も裏付けています — targets/pmg110-16.0.9.400/NOTES.md を参照してください。

何を行うか、何を行わないか

Write 1 (SELinux permissive) と Write 2 (cred → init_cred) を実行し、子プロセスを uid=0 にした上で、そこから組み込みの su デーモンをインストールします。

  • プッシュするファイルは依然として 1 つだけ。 su は 2 つ目の成果物ではありません。su_daemon.c はスタンドアロンの aarch64 PIE としてビルドされ、.incbin でライブラリの .rodata に埋め込まれるため、preload.so に同梱されて実行時に書き出されます。warhol-root のルートを、変更なしで踏襲。
  • root スクリプトなし、ksud なし、KernelSU なし
  • 呼び出し元プロセスは非特権のままです。root を取得するのはデーモンに依頼するためであり、これは後でシェルから行うのと同じ方法です
  • SELinux は warhol-root と同様、permissive のままになります。デーモンはソケット越しに非特権クライアントへ応答する必要があるためです。enforcing に戻すには再起動してください。

su は 3 か所にインストールされます。そのうちの 1 つが、実際に到達できる場所だからです:

デーモンは /data/local/tmp/temp_su.sock で待ち受け、/data/local/tmp/su_daemon.log にログを出力します。root は再起動をまたいで持続しません — 起動のたびに LD_PRELOAD の行を再実行してください。

KernelSU をインストールする場合は、代わりに ghostlock-oneplus の /data/local/tmp/a/e ルートを使用してください。

warhol-root との関係

エクスプロイトの中核以外はすべて warhol-root のもので、再発明ではなく流用しています:

  • レイアウト — targets/<device>/ 以下のデバイス別ヘッダーをビルド時に source/src/ へステージングする構造。DEVICE を切り替えても、以前のデバイスのヘッダーが残ることはありません
  • ビルド — source/Makefile のツールチェーン選択 (NDK があれば NDK、なければ NDK sysroot をターゲットとするホストの clang) と、.so をリンクする前に build/embed/su_daemon_aarch64_pie を生成する 2 段階の埋め込みルール
  • su ルート — su_daemon.c と su_blob.S は warhol-root のものとバイト単位で同一で、su_install.c はその preload.c インストーラーです

エクスプロイトの中核は warhol-root のものではありません。 warhol-root は popsicle であり、GKI 6.12 / android16 に固定され、generate_target.py は他のバナーをすべて拒否します。PMG110 は 6.6 / android15 のため、ここでの中核は ghostlock 6.6 ツリーです — それ自体は同じコードの子孫 (kernelsnitch/utils.h と timeutils.h は 2 つのリポジトリ間でバイト単位で同一) であり、さらに開発が進められています。

エクスプロイト本体のすべての行 — Write 1、Write 2、KernelSnitch、pselect ルート — は、両ツリーで同じコードです。

su のインストールが呼び出される場所

これが唯一の構造上の違いであり、2 つのツリーが異なる形で root を取得することによって生じます。

warhol-root はエクスプロイトプロセス自体を root 化するため、run_direct_root() から直接 install_embedded_su() を呼び出します。こちらでは Write 2 がフォークした子プロセスの cred ポインタを交換し、親は非特権の呼び出し元のままです。したがって、インストールを実行できるのは child_main() 内の子プロセスだけです — そこで実行されます。

両ツリーとも util.c に ENOSYS を返す同じ弱い install_embedded_su() スタブを持っています。強い定義を提供することが、このルートを有効にします。これは知っておく価値があります。何らかの理由で su_install.c が省かれたビルドでも、リンクも実行も成功し、ただ su=0/38 と報告して何もインストールしないからです。

ビルド

root@kitploit:~
make                      # = make preload -> out/preload-<DEVICE>.so
make DEVICE=<name>        # use targets/<name>/
make devices              # list available DEVICE values
make info                 # show the selected target and the resolved toolchain

ツールチェーンは自動で見つかります。まず ANDROID_NDK_HOME / ANDROID_NDK_ROOT、次に Linux と macOS の一般的な NDK インストール先、それらがすべて見つからなければ NDK sysroot をターゲットとするホストの clang が使われます。検索を上書きする場合にのみ ANDROID_NDK_HOME を設定してください。make info は選択した内容を表示します。

ビルドは 2 段階で、これが知っておくべきポイントです:

  1. su_daemon.c → build/embed/su_daemon_aarch64_pie、スタンドアロンの aarch64 PIE
  2. su_blob.S がそのバイナリを .rodata に .incbin し、全体が 1 つの preload.so にリンクされる

したがって、組み込みの su を変更する唯一の方法は make clean して再ビルドすることです。su_daemon.c を編集するだけで十分で、依存関係も宣言されていますが、blob はビルド成果物であり追跡対象外です。

targets/<device>/{target.h,device_offsets.h} はビルドのたびに source/src/ へ再ステージングされるため、別のデバイスの古いヘッダーが黙って取り込まれることはありません。

out/*.so は追跡対象外です (warhol-root と同じ規約) — clone して make してください。

.so は -fvisibility=hidden でビルドされ、エクスポートするシンボルはゼロです。LD_PRELOAD ライブラリはプロセス全体のシンボル解決で優先されるため、エクスポートしたシンボルはホストバイナリや libc 内の同名シンボルをシャドウする可能性があります。このフラグは C のコード生成にのみ作用するため、su_blob.S は 2 つのシンボルを手動で .hidden にしています。この行がないと、blob の境界がライブラリがエクスポートする唯一のものになってしまいます。

環境変数

検証した実行では、これらはどれも必要ありませんでした。

ログの読み方

root@kitploit:~
[*] futex_hashsize 2048 (8 possible CPUs)
[*] ks collisions=3/3 baseline=8 threshold=10x (80) accepted=[1244..1597] slowest_rejected=N
[+] child uid = 0
[+] embedded su wrote 15304 bytes to /apex/com.android.virt/bin/su
[+] embedded su daemon ready pid=NNNN socket=/data/local/tmp/temp_su.sock daemon=/apex/com.android.virt/bin/su
[+] embedded su install ok=1 errno=0 daemon=NNNN
[+] su ready: /data/local/tmp/su and /apex/com.android.virt/bin/su
[+] ghostlock preload verdict: EXPLOIT OK

child uid = 0 はエクスプロイトの成功を意味し、それ以降はすべてインストールの処理です。この 2 つは意図的に分けて報告され、判定も同様に分けられています:

真ん中の判定こそが区別する価値のあるものです。それは、target.h のオフセットがこのビルドに対して正しく、問題はインストールのどこかにあることを示しており、デバッグ対象がまったく別のものになります。その中の su=0/38 (ENOSYS) は、具体的には弱いスタブがリンクされたことを意味します。

mm_struct leak failed の後に prepare_kernel_page retry N/24 が続いても、それは失敗ではありません。 ループの進行状況であり、成功した実行でも同じものが表示されます。24 回の試行を使い果たして prepare_kernel_page timeout が現れるまで、何も失敗していません。同様に、child uid = 2000 を伴う probing cfi ... expected=9 は、10 ラウンド中の 1 ラウンドが外れただけです。

切り詰められたログから実行を判断しないでください — ここでは、その誤りによって丸 1 ラウンドの誤診を費やしました。

実行全体が失敗することも普通です。 pselect レースは 100% ではありません。5 回続けて負けて Write 1 failed で終わる実行もあれば、次の実行では初回で ret=9 を取れます。このデバイスで観測済みです。ret=4 expected=9 はレースに負けたときの姿であり、target.h の誤りではありません — 1 回の失敗はオフセットを導き直す理由にはなりません。再実行してください。

ファイル

ライセンス

認可されたセキュリティ研究および教育目的にのみ使用できます。

ツールをダウンロード
デバイスOPPO PMG110 / K15 Pro+ / OP61E5L1
SoCMediaTek MT6991 (Dimensity 9500s)
カーネル6.6.118-android15-8-g93e223c276e7-abogki500782043-4k (GKI、4K ページ)
ビルドColorOS 16 / PMG110_16.0.9.400(CN01) — 16.0.8.300 と同じカーネルバイト
バグCVE-2026-43499、このイメージでは未修正 (バージョンではなく逆アセンブルで確認)
パス理由
/apex/com.android.virt/bin/suそのディレクトリにマウントされた tmpfs 上。root シェルの PATH に含まれる
/data/local/tmp/suPATH をいじらずに素の adb shell から到達可能
/apex/com.android.virt/bin/su adbd のマウント名前空間内setns 経由でインストールされるため、新しい adb shell からも見える
ファイル関係
util.c slide.c fops.c pipe.c root.c miniadb.c common.h offset.h kernelsnitch/*ghostlock のもの、バイト単位で同一
su_daemon.c su_blob.Swarhol-root のもの、バイト単位で同一 (su_blob.S は .hidden 行を 2 行追加 — ビルドを参照)
su_install.cwarhol-root の preload.c インストーラー。このツリーの preload.c にはすでに別の役割があるため、独立したファイルに移動された
main.cghostlock のものに加え、ルート化された子プロセスでの su 呼び出しと結果の報告
preload.cこのツリーにのみ存在 — コンストラクタと二重出力のログ
offsets.h構造体定義のみ。エントリは targets/<device>/device_offsets.h からステージングされる
変数効果
GHOSTLOCK_LOGログの出力先 (デフォルト: /data/local/tmp/.ghostlock.log)。出力は stdout とファイルの両方に書き出される
GHOSTLOCK_KS_VERBOSE=1KernelSnitch の衝突アドレスとスイープ範囲を表示
GHOSTLOCK_KS_THRESHOLD=<n>衝突閾値の倍率を上書き
GHOSTLOCK_MTE=1カーネルポインタのタグもスイープ (15 倍遅い)
GHOSTLOCK_PHYS_LOAD=0x...カーネルの物理ロードアドレスを上書き
PSELECT_SHIFT=<n>スタックオーバーレイのシフトを上書き (置き換えであり、加算ではない)
判定意味
EXPLOIT OKroot を取得し、su が応答
EXPLOIT OK, SU INSTALL FAILEDWrite 1 と Write 2 は成功。インストールだけが失敗
EXPLOIT FAILED書き込みが成功しなかった
ABORTED報告する前に実行が終了した — 最後の [!] 行を確認
パス内容
source/src/preload.cコンストラクタ: エクスプロイトを実行し、報告し、停止する
source/src/main.cエクスプロイト本体 (Write 1 / Write 2)
source/src/su_daemon.csu バイナリ — スタンドアロンの aarch64 PIE としてビルドされ、.so にはリンクされない
source/src/su_blob.Sその PIE を .so の .rodata に .incbin する
source/src/su_install.cblob を書き出し、デーモンを起動し、動作確認を行う
source/src/target.hステージング先 (gitignore 対象)
targets/<device>/target.hコンパイル時のレイアウト: 構造体オフセット、physmap 定数、slab と futex の形状
targets/<device>/device_offsets.hkallsyms からのグローバルシンボルオフセット
tools/extract_device.pyboot.img → オフセット、BTF 構造体フィールド、pselect オーバーレイ結果
tools/preloader_memlayout.pyMediaTek プレローダー → P0_KERNEL_PHYS_LOAD
tools/qemu_verify.pyQEMU でカーネルを起動します: スタックオーバーレイの計測、線形マップの安定性の確認
tools/device_probe.sh非特権の adb shell から実行する事前チェック