
# GhostLock (CVE-2026-43499) exploit del kernel per dispositivi Android con bootloader bloccato
Exploit del kernel per dispositivi Android con bootloader bloccato. Ottiene root temporaneo + installazione di KernelSU senza sbloccare il bootloader o modificare l'immagine di boot. Rilevamento automatico a runtime della versione del kernel con tabella di offset multi-dispositivo.
CVE-2026-43499 — Futex PI (Priority Inheritance) Use-After-Free
Colpisce il kernel Linux 5.7 ~ 7.1. Corretto nelle versioni stabili 6.1.175, 6.6.140, 6.12.86. La maggior parte dei dispositivi Android rimane senza patch a settembre 2026.
La syscall pselect6 copia i dati fd_set sullo stack del kernel. Se combinata con il meccanismo del waiter futex PI, un frame di stack liberato può essere riutilizzato come struttura rt_mutex_waiter. Il ribilanciamento dell'albero rb durante la traversata della catena PI scrive quindi valori controllati a indirizzi arbitrari del kernel.
L'overlay dello stack pselect richiede che il rt_mutex_waiter liberato ricada nella regione stack_fds controllabile dall'utente (word 0–14). La posizione è determinata dai profili PGO/LTO del compilatore, non dalla versione del kernel. Vedi Layout dello Stack.
Nota sulla fattibilità 6.1: I kernel OPLUS 6.1 sono costantemente non realizzabili a causa dell'inlining PGO di
do_futex. Tuttavia, alcuni kernel non-OPLUS 6.1 (vivo) mantengono la catena di chiamate standard e sono realizzabili (vivo T4, X Fold3 Pro). La fattibilità deve essere verificata per ogni singolo dispositivo.
Due percorsi di root, selezionati automaticamente in base alle capacità del dispositivo:
Richiede off_ashmem_misc_fops != 0 (C ashmem con miscdevice statico in BSS).
Scrittura PI (mode=4) → reindirizza i fops del miscdevice a fops falsi
→ r/w configfs → physrw tramite pipe (r/w kernel preciso a 1 byte)
→ SELinux enforcing = 0 (singolo byte, nessuna corruzione di policycap)
→ UMH: inietta work_struct in system_unbound_wq
→ script di root → caricamento tardivo ksud → KSU installato
Disponibile su: OnePlus 13, OPPO Pad 4 Pro, dispositivi C ashmem 5.10/6.1. Non disponibile su Rust ashmem (GKI 6.12) — miscdevice allocato su heap.
Scrittura 1 (mode=1) → SELinux enforcing = 0 (scrittura a 8 byte, corrompe i byte adiacenti)
Scrittura 2 (mode=2) → task->cred = init_cred (uid=0, tutte le capability)
Shell di root → caricamento tardivo ksud → KSU → correzione policy SELinux
Dopo W1+W2, l'exploit corregge il campo config del binario della policy SELinux (|= 0xC0000000 per ANDROID_NETLINK_ROUTE + GETNEIGH) e lo ricarica tramite /sys/fs/selinux/load per ripristinare la connettività di rete.
App (seccomp) → Scrittura 1 → mini-adb TCP → adb shell: exploit completo → root
Il launcher all'avvio è fornito dalla app GhostLock Anchor separata.
Con NFDS=320, core_sys_select alloca un buffer stack_fds di 256 byte sullo stack del kernel:
stack_fds: 0 5 10 14 | 15 20 25 29
├─in─┤─out─┤─ex──┤ ├res_in┤res_out┤res_ex┤
◄── CONTROLLATO DALL'UTENTE ──►│◄── ZERATO DAL KERNEL ──►
L'exploit posiziona campi waiter falsi (task, lock) nelle bitmap di input fd_set. Per il waiter annidato 6.12 (14 word): word waiter massima realizzabile = 3. Per il waiter compatto 5.10/6.1 (10 word): word waiter massima realizzabile = 7.
La posizione del waiter dipende dalla profondità della catena di chiamate:
Tutte le scritture sul kernel usano l'alias della mappa lineare. Il bootloader sceglie kernel_phys_load, che varia in base al SoC:
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
Un valore errato fallisce silenziosamente. Leggilo su un'unità con root:
su -c 'grep -i "Kernel code" /proc/iomem' # c7810000-... → 0xc7800000
Override a runtime: KPHYS=0xc7800000 /data/local/tmp/a/e
/data/local/tmp/a/e # Default (shift=0)
PSELECT_SHIFT=-2 /data/local/tmp/a/e # OnePlus 13 (6.6)
I kernel 5.10 usano 0xffffffc008000000 (VA_BITS=39, diverso dal default 6.x 0xffffffc080000000). Questo viene gestito automaticamente tramite il campo kimage_text_base nella voce di offset del dispositivo.
make NDK_ROOT=/path/to/android-ndk
Oppure direttamente:
NDK=/path/to/android-ndk
"$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android35-clang" \
-O2 -Wall -Isrc/core -Isrc/devices -DTARGET_CONFIG_H=\"target.h\" \
src/core/main.c src/core/util.c src/core/slide.c \
src/core/fops.c src/core/pipe_physrw.c src/core/root.c \
src/core/miniadb.c src/core/umh_root.c \
-o ./ghostlock -fPIE -pie -pthread
GhostLock fornisce root temporaneo. L'installazione di KernelSU richiede ksud che include kernelsu.ko per ogni versione KMI.
| Metodo | Passaggi |
|---|---|
| APK ReSukiSU (consigliato) | Installa ReSukiSU o questo . Include . |
adb shell mkdir -p /data/local/tmp/a
adb push ./ghostlock /data/local/tmp/a/e
adb shell chmod 755 /data/local/tmp/a/e
adb shell /data/local/tmp/a/e
Esegui dopo il completamento dell'avvio e quando ADB è pronto.
Serve solo boot.img — nessun root, nessun accesso al dispositivo richiesto.
Vedi guida strumenti kallsyms per il flusso di lavoro completo, oppure:
python tools/extract_target.py --kallsyms kallsyms.txt
python tools/extract_btf.py kernel
Verifica se do_futex è inline PGO cercando nel binario del kernel tutte le istruzioni di branch che puntano a futex_wait_requeue_pi. Se __arm64_sys_futex lo chiama direttamente (bypassando do_futex), il dispositivo probabilmente non è realizzabile.
Aggiungi src/devices/<name>/offsets.h con gli offset estratti e includilo in src/devices/offsets.h. Usa la macro appropriata per gli offset delle strutture:
Per i dispositivi con waiter compatto 5.10/6.1, imposta anche .kimage_text_base=0xffffffc008000000ULL.
Solo per ricerca di sicurezza autorizzata e scopi educativi.
| Dispositivo | SoC | Kernel | Ramo GKI | SHIFT |
|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38 | android16-5 | 0 |
| OnePlus 15 (CPH2745/2747/2749) | SM8850 | 6.12.23 | android16-5 | 0 |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23 / 6.12.69 | android16-5 / android16-6 | 0 |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89 | android15-8 | -2 |
| OPPO Pad 4 Pro | SM8750 | 6.6.89 | android15-8 | -2 |
| Dispositivo | SoC | Kernel | Note |
|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38 | Stesso kernel di Ace 6T |
| OPPO Reno10 Pro+ (CPH2521) | SM8475 | 5.10.236 | Waiter compatto 5.10, waiter word=0 |
| Vivo X Fold3 Pro (PD2337) | SM8650 | 6.1.124 | Waiter compatto 6.1, waiter word=3 |
| Vivo T4 | SM8650 | 6.1.145 | Waiter compatto 6.1, waiter word=3 |
| Dispositivo | SoC | Kernel | Causa Principale |
|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58 | PGO elimina do_futex → waiter word=14 |
| OnePlus 12 | SM8650 | 6.1.141 | PGO inline di do_futex → waiter word=13/19 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | OPLUS 6.1: waiter word=13 |
| realme RMX5070 | SM6650 | 6.1.141 | OPLUS 6.1: waiter word=13 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | OPLUS 6.1: waiter word=13 |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | Non-OPLUS 6.1: stesso risultato |
| iQOO Neo 10 CN | SM8650 | 6.1.84 | Frame do_futex 0xD0 → waiter word=-11 |
| OPPO PKW110 | — | 5.15.180 | Frame do_futex 0x140 → waiter word=-29 |
| iQOO Z9 5G | — | 5.15.178 | Frame do_futex troppo grande |
| CPH2763 (OPPO) | — | 6.1.115 | OPLUS 6.1: PGO inline, waiter word=24 |
| Pattern | Catena di Chiamate | Realizzabile |
|---|
| android16-5 (6.12) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 |
| android15-8 (6.6) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 (SHIFT=-2) |
| vivo 6.1 | sys_futex → do_futex → fwrpi | ✅ waiter word=3 |
| OPLUS 6.1 | sys_futex → fwrpi (PGO inline) | ❌ waiter word=13+ |
| android16-6 (X9 Ultra) | sys_futex → fwrpi (PGO inline) | ❌ waiter word=14 |
| 5.10 OPLUS | sys_futex → do_futex → fwrpi | ✅ waiter word=0 |
| SM8650 (vivo T4, X Fold3 Pro) |
0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |
libksud.so| Release CI | Scarica da ReSukiSU CI |
| Kernel | Layout Waiter | Macro |
|---|
| 6.12.x | Annidato (14 word) | STRUCT_OFFSETS_6_12 |
| 6.6.x | Annidato (14 word) | STRUCT_OFFSETS_6_6 |
| 6.1.x (vivo) | Compatto (10 word) | STRUCT_OFFSETS_6_1 |
| 5.10.x | Compatto (10 word) | STRUCT_OFFSETS_5_10 |
| File | Descrizione |
|---|
src/core/main.c | Punto di ingresso dell'exploit, W1/W2, percorso UMH, bootstrap, script di root, correzione policy SELinux |
src/core/fops.c | Percorso pselect, scrittura PI, stadio CFI, supporto waiter compatto |
src/core/util.c | Heap spray, KernelSnitch, slab drain, configurazione payload |
src/core/pipe_physrw.c | Lettura/scrittura della memoria fisica tramite buffer pipe |
src/core/umh_root.c | Root UMH tramite iniezione in workqueue |
src/core/miniadb.c | Client Mini ADB (TCP + autenticazione RSA) |
src/core/target.h | Layout di memoria, valori predefiniti dei campi struct (6.12) |
src/core/runtime_struct_offsets.h | Override dei campi struct per dispositivo |
src/devices/offsets.h | Tabelle degli offset per dispositivo + macro STRUCT_OFFSETS_* |
tools/extract_target.py | Estrazione offset da kallsyms |
tools/extract_btf.py | Estrazione offset struct da BTF |
tools/kallsyms/ | Flusso di lavoro completo per il recupero di kallsyms |