
Lokaler Root-Exploit für CVE-2025-21479 (Adreno KGSL) auf iQOO Neo8 (SM8475) – physischer Speicher Lese-/Schreibzugriff, deaktiviert SELinux, startet Root-Shell
Lokaler Privilegieneskalations-Exploit-Code für CVE-2025-21479, Ziel ist die Qualcomm Adreno GPU (KGSL) auf dem vivo V2301A (iQOO Neo8 / PD2301, Snapdragon 8+ Gen 1 / SM8475, Adreno A730, Android 14, GKI-Kernel 5.10).
Prinzipiell treibt die Exploit-Ausnutzung über den CP_SMMU_TABLE_UPDATE-Befehl von KGSL die SMMU der GPU an,
erlangt die Fähigkeit zu beliebigem physischem Speicherlesen und -schreiben, deaktiviert daraufhin SELinux, lokalisiert Kernel-Symbole und erhält eine Root-
Shell – der gesamte Vorgang erfordert weder Flashen noch ein Entsperren des Bootloaders.
仅限对你自己拥有、或已获授权的设备进行安全研究。
and $12, 0x3)存在缺陷,会把 Self-Draw-State(SDS)包误判为
RingBuffer(RB)。因此在用户态将伪造的 CP_SMMU_TABLE_UPDATE 放入 SDS
块中提交,即可覆写 GPU 的 TTBR0,让 GPU 页表指向任意物理页——从此 GPU
可以读写任意物理内存。stabilize_rw 将映射加固为 2 MB 自映射区域,
支持大批量快速读取(fast_pread_bytes 等)。selinux_state.enforcing 字段清零。
随后从固定物理基址 0xA8000000 转储内核映像(默认上限 43 MB)——
SM8475 没有物理 KASLR——并直接从原始转储中解析 kallsyms 结构
(大小端自动识别),因此虚拟 KASLR 也不影响。prepare_kernel_cred(0) →
commit_creds(),并关闭 seccomp)补丁 __do_sys_capset。fork 出的子进程
调用 capset() → 变为 uid 0 → 恢复被覆盖的内核代码 → 子进程以
u:r:shell:s0 域重新执行你指定的命令(默认 sh)。内核代码最终
与运行前逐字节一致。| 型号 | vivo V2301A(iQOO Neo8,代号 PD2301,主板 taro) |
| SoC | SM8475(骁龙 8+ Gen 1)+ Adreno 730 |
| Android | 14(UP1A.231005.007,SDK 34,qssi-user) |
| 内核 | 5.10.198-gki-gfb2f5774872c |
| SELinux | Enforcing(运行时被本工具关闭) |
完整设备信息见 device_info.txt。
├── source/
│ ├── cheese.c # 漏洞利用主程序(include 了下面两个文件)
│ ├── kallsyms_lookup.c # 针对原始内核映像的 kallsyms 解析器
│ └── adrenaline.h # KGSL ioctl / 命令定义(作者 hawkes)
├── exploit # 预编译 arm64 二进制(动态链接,minSdk 21,
│ # NDK r30-beta2)
├── device_info.txt # 用于调参的目标设备信息
└── README.md
Hinweis: cheese.c wird kallsyms_lookup.c und adrenaline.h #includeen,
beim Kompilieren müssen die drei Dateien im selben Verzeichnis liegen.
Jedes neuere Android NDK (r25+) ist geeignet, Beispiel:
# 静态链接(自包含、任意 API 等级可运行;体积较大)
aarch64-linux-android34-clang -o cheese source/cheese.c -static
# 动态链接(体积小,依赖设备自带的 libc;API 等级需匹配设备)
aarch64-linux-android34-clang -o exploit_dyn source/cheese.c
# 若要兼容 API 21+ 设备,请改用 aarch64-linux-android21-clang
#推送exploit
adb push exploit /data/local/tmp/
#运行exploit
adb shell
chmod +x /data/local/tmp/exploit
/data/local/tmp/exploit
Ausführliche Anleitung hier klicken (enthält ein Ein-Klick-Tool)
Nach erfolgreichem Abschluss erhält man eine Shell mit uid=0, und SELinux ist in dieser Sitzung deaktiviert. Der Prozess führt nach Abschluss
der Rechteausweitung erneut argv[1..] aus (standardmäßig sh). Bei jedem Lauf gibt es einen Countdown
("pte wait 3 second") und einen Fortschritt beim Lesen des 43 MB großen Kernels ("Read X / 43 MB").

| Variable | Zweck |
|---|---|
CHEESE_PHYADDR=<phys> | Erzwingt die Angabe der physischen Kernel-Basisadresse (überspringt die eingebaute gPhyAddrs-Erkennungstabelle). |
CHEESE_ATTEMPT=<n> | Verwendet gPhyAddrs[n] statt gPhyAddrs[0]; nach einem GPU-Initialisierungsfehler erhöht maybe_retry automatisch und versucht es erneut. |
CHEESE_SWAPPER_PG_DIR_OFF=<off> | Überspringt den swapper_pg_dir-Scan und verwendet direkt diesen absoluten Offset. |
CHEESE_READ_FULL_KERNEL=1 | Liest das vollständige Kernel-Image (Standard-Lesegrenze ist DEFAULT_KERNEL_SIZE_MB = 43 MB). |
CHEESE_KALLSYMS_MAX_MB=<MB> | Überschreibt die Lesegrenze für kallsyms. |
CHEESE_FORCE_MANUAL_PATCHFINDER=1 | Erzwingt die Verwendung des manuellen Patchfinder-Fallbacks (init_cred, prepare_kernel_cred). |
CHEESE_SKIP_GPU=1 | Überspringt die GPU-Lese-/Schreibphase (nur zum Debuggen). |
CHEESE_NO_RETRY=1 | Beendet sich nach einem Fehler direkt, ohne erneuten Versuch mit anderer Nummer. |
Aufgrund des speziellen Mechanismus der vivo-Modelle muss es auf dem iQOO Neo8 deaktiviert werden, um die Stabilität der Root-Rechte aufrechtzuerhalten (die genauen Hintergründe werden hier nicht erläutert. Bei anderen vivo-Modellen und Kernel-Versionen ist dies möglicherweise nicht allgemein anwendbar; vr.ko muss selbst extrahiert und reverse-engineered werden). Stellen Sie vor den folgenden Schritten bitte sicher, dass die aktuelle Shell-Sitzung bereits Root-Rechte besitzt.
#备份原始apanic
dd if="$(readlink -f /dev/block/by-name/apanic)" of=/sdcard/apanic_full.bin
#adb shell内执行
adb pull /sdcard/apanic_full.bin ./
#主机端执行
#禁用vr.ko(风险自行评估)
printf '\370\037\000\000\000\000\000\000\000\000\000\000' | dd of=$(readlink -f /dev/block/by-name/apanic) bs=1 seek=$(( $(blockdev --getsize64 /dev/block/by-name/apanic) - 65472 )) conv=notrunc && sync
Wenn ein Kaltstart des Telefons später dazu führt, dass die Root-Rechte ungültig werden, muss nur der Exploit erneut ausgeführt und anschließend der Jailbreak durchgeführt werden
$(find /data/app -type f -name "libksud.so" | grep resukisu) late-load --kmi android12-5.10
Die gerätespezifischen Konstanten befinden sich oben in source/cheese.c:
KERNEL_PHYS_BASE — physikalische Kernel-Basisadresse (Standard 0xA8000000, SM8475)IDMAP_PG_DIR_OFFSET — Offset von idmap_pg_dir (Standard 0x245a000)selinux_state_offset — Offset zum Auffinden von selinux_state (Standard
0x729030, tatsächliche physikalische Adresse = physikalische Adresse von idmap_pg_dir + dieser Offset)gPhyAddrs[] — der Reihe nach zu probierende Kandidaten für die physikalische BasisadresseDEFAULT_KERNEL_SIZE_MB — Fallback-Wert / Obergrenze für das Lesen des KernelsVoraussetzungen: Adreno A730/A7xx-GPU-Serie (betroffene Firmware) und das Gerätesystem hat den von Qualcomm im Juni 2025 veröffentlichten Sicherheitspatch nicht installiert, im physischen Dump lässt sich ein Kernel mit kallsyms auflösen, und es liegt kein physisches KASLR vor.
can't get GPU r/w — GPU-Initialisierung fehlgeschlagen; zunächst abwarten, falls es weiterhin nicht funktioniert, CHEESE_ATTEMPT=1..n versuchen oder manuell CHEESE_PHYADDR angeben; zum Debuggen eines einzelnen Versuchs CHEESE_NO_RETRY=1 hinzufügen.CHEESE_READ_FULL_KERNEL=1 das vollständige Image lesen (in Verbindung mit CHEESE_KALLSYMS_MAX_MB die Obergrenze erhöhen), dann CHEESE_FORCE_MANUAL_PATCHFINDER=1 in Betracht ziehen.cheese-Exploits, auf dem dieses
Tool basiertadrenaline.h-KGSL-Header aus dem Jahr 2020, die die ioctl-Schnittstellendefinitionen bereitstellen