Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-43499-S26 — Exploit del kernel Android GKI 6.12 per CVE-2026-43499, che concatena un bug di rollback di rt_mutex con la sovrascrittura dello stack di pselect per ottenere i privilegi di root su dispositivi Samsung e Pixel. | Kitploit
Strumenti/GitHubGitHub/sammyenigma/cve-2026-43499-s26
Sicurezza AndroidEscalation di PrivilegiMemory ForensicsMeccanismi di PersistenzaExploitReverse EngineeringShellcodePost-ExploitSicurezza Mobile

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Sviluppo Payload
Binary Exploitation
GitHubsammyenigma/cve-2026-43499-s26

CVE-2026-43499-S26

Exploit del kernel Android GKI 6.12 per CVE-2026-43499, che concatena un bug di rollback di rt_mutex con la sovrascrittura dello stack di pselect per ottenere i privilegi di root su dispositivi Samsung e Pixel.

Vedi Repository
122 giorni faNon ancora revisionato

CVE-2026-43499 — Exploit del kernel Android GKI 6.12 pselect / configfs

Un exploit del kernel Linux per la linea GKI 6.12 di Android (dispositivi Samsung e Pixel) che prende di mira CVE-2026-43499: un rollback difettoso di remove_waiter() in rt_mutex_start_proxy_lock() che usa current invece di waiter::task, lasciando il pi_blocked_on di un waiter puntato al suo (later-popped) kernel stack rt_mutex_waiter. Combinato con una sovrascrittura dello stack fd_set di pselect() e una camminata fake rb_tree guidata da sched_setattr del consumer, produce una primitiva di scrittura kernel deterministica e root completo.

L'exploit viene eseguito come libreria condivisa LD_PRELOAD (preload.so) e installa un demone su root piu un wallpaper come artefatti post-root.

Stato: sviluppo attivo. Il target m1q (ZF1) e il focus del bring-up. Il bootstrap pipei tmp_page-uname e la rotta attiva corrente: la camminata e provata pulita on-device (build #33: regioni rt_mutex seedate per-child) e la scansione completa dei 168 candidati e in corso. La rotta configfs CFI e un vicolo cieco su m1q (Rust ashmem — nessuno slot fops iniettabile) e resta la rotta per i target C-ashmem. Gli offset per-target variano da dispositivo a dispositivo — verificarli rispetto al binario del kernel effettivo prima di fidarsene.

Primitiva vulnerabile (CVE-2026-43499)

Quando FUTEX_CMP_REQUEUE_PI riaccoda un waiter e la camminata della catena di rilevamento deadlock del requeue restituisce -EDEADLK, __rt_mutex_start_proxy_lock() esegue il rollback tramite remove_waiter() (rtmutex.c:1535). Il rollback rimuove correttamente il waiter dall'albero di attesa ma azzera il pi_blocked_on del chiamante del requeue invece di waiter->task->pi_blocked_on. Il pi_blocked_on del WAITER resta pendente sul suo rt_mutex_waiter nello stack, che viene rimosso una volta che il futex va in timeout.

Dopo il timeout, la regione dello stack kernel del waiter viene riutilizzata: core_sys_select() copia i tre fd_set in quel buffer dello stack (il percorso stack nfds < 344 su ZF1). Un array di parole fd_set artigianale ri-materializza un finto rt_mutex_waiter / finto task / finto rt_mutex (con una radice rb_tree i cui puntatori sono controllati). Un thread consumer chiama poi sched_setattr_tid(waiter) → rt_mutex_adjust_pi() → rb_erase_cached, che produce una scrittura su indirizzo arbitrario di un valore controllato.

L'intera primitiva richiede il ciclo della catena PI: l'owner detiene f_pi_target e si blocca anche su f_pi_chain (detenuto dal waiter), quindi la camminata della catena incontra owner → chain → waiter → target → owner e fallisce con -EDEADLK. Rimuovere il ciclo fa si che il requeue ritorni successo con effetto kernel nullo.

Catena di exploitation

  1. Slide (KASLR) — leak della base del kernel. Due rotte:
    • tracefs sched_blocked_reason (primaria su m1q, provata on-device): il return PC salvato di un kworker bloccato (stack_trace_save_tsk) viene letto dal ring buffer e confrontato con l'offset worker_thread compilato nel binario. Viene eseguita prima che venga usata qualsiasi parola della rotta boot_id, cosi i target di scrittura data-alias (data_addr() = alias p0 + slide_p0_offset) restano corretti a uno slide non nullo.
    • rotta boot_id pselect (fallback, indipendente dallo slide): una scrittura pselect pianta SLIDE_LOGGERS_0_1 nei dati sysctl di boot_id tramite un alias linear-map; il valore leakato ricostruisce stext. Parcheggiata su m1q: il suo target W1 (SLIDE_RANDOM_BOOT_ID_DATA_OFF, RAM fisica bassa) ha scrivibilita dipendente dalla pagina — lo slide sposta il target attraverso i confini di pagina a ogni boot, quindi ~6/7 esecuzioni vanno in fault. Viene esercitata esplicitamente solo tramite SLIDE_FORCE_BOOTID (test del meccanismo) con tree_pc/tree_left reindirizzati alla pagina spruzzata.
  2. KernelSnitch — spray di oggetti delle dimensioni di e uso di una collisione futex-hash per localizzare un sull'heap, leakando un indirizzo di pagina heap del kernel usato come base dello spray di oggetti fake. I waiter vengono distaccati (non joinati) durante la pulizia per evitare l'OOM dello stack kernel che faceva crashare le build prima della #26.

Forma della camminata (m1q, provata on-device)

Le parole fd_set di pselect ri-materializzano un finto rt_mutex_waiter sullo stack kernel del waiter; il sched_setattr_tid(waiter) di un thread consumer lo percorre tramite rt_mutex_adjust_pi(). Mappa parole ZF1 (verificata via disasm): PSELECT_WAITER_WORD_SHIFT = 0, parola 12 = task (@+0x50), parola 13 = lock (@+0x58), parola 14 = wake_state (@+0x60 = 3). Con un finto rt_mutex seedato la camminata si completa pulitamente: le W1 *(tree_left)=tree_pc / W2 *(tree_pc&~3+8)=tree_left di rb_erase di [7] sono le uniche scritture kernel; [11] (setprio / dequeue_pi) e il wake di [9] vengono entrambi saltati (il finto waiter locale a prio 100 tiene il nodo dello stack fuori dal top-waiter). Ogni completamento entrato nella camminata dalla build #19 sopravvive on-device; i crash deterministici precedenti erano un errore di posizionamento del payload di 8 byte (SKB_DATA_DELTA), non un fault del corpo della camminata.

Stage 3 (ponte pgd-swap, solo statico/build)

Fase opzionale STAGE3=1 che fork-a un figlio bridge, scambia il suo mm->pgd con una tabella di pagine fake preparata (3 livelli: PGD→L1→L2, foglia RX loop + foglia RW stack) e lascia che il figlio esegua un blob assembly di soli registri che patcha le proprie cred attraverso una finestra di scansione fisica da 2MB — phys R/W su tutta la RAM senza le primitive configfs/pipe. Attualmente cablata solo nel target m1q e non e stata eseguita on-device.

Target supportati

41 target in src/targets/<codename>-<build>/, ognuno richiede come minimo un target.h (offset dei simboli del kernel, KIMAGE_TEXT_BASE, base della direct-map, offset delle struct). I target Pixel (comet, tokay, tegu, caiman, komodo, frankel, mustang, rango, stallion, blazer) sovrascrivono i sorgenti condivisi; i target Samsung (m1q-*) aggiungono logica specifica del dispositivo.

root@kitploit:~
make list-projects   # full list

I layout delle struct del kernel differiscono per dispositivo — gli offset devono essere verificati rispetto al binario del kernel effettivo / kallsyms per ogni target.

Build

Output: build/<PROJECT>/bin/preload.so (libreria condivisa caricata via LD_PRELOAD).

root@kitploit:~
# Default project
CC=clang make

# Specific device target (default: blazer-CP2A.260605.012)
CC=clang make PROJECT=m1q-BP4A.251205.006

# Without CC=clang: uses NDK if found ($NDK_ROOT / $ANDROID_NDK_HOME /
# $ANDROID_NDK_ROOT), otherwise host clang + Android sysroot
make PROJECT=m1q-BP4A.251205.006

# Show build configuration
make info

# Clean
make clean

La build incorpora un binario PIE su_daemon (src/su_daemon.c, compilato in build/embed/su_daemon_aarch64_pie) e assets/wallpaper.webp in preload.so tramite src/su_blob.S / src/wallpaper_blob.S.

Esecuzione sul dispositivo

Pusha gli output della build in /data/local/tmp, poi esegui l'exploit sotto LD_PRELOAD. Esegui SENZA tee su un target di bring-up attivo — tee bufferizza il proprio stdio e perde la coda del log su un kernel panic (lo stdout dell'exploit e non bufferizzato, quindi reindirizzare direttamente a un file preserva ogni riga):

root@kitploit:~
adb push build/m1q-BP4A.251205.006/bin/preload.so /data/local/tmp/preload.so
adb push build/embed/su_daemon_aarch64_pie /data/local/tmp/su_daemon_aarch64_pie
adb shell "chmod 755 /data/local/tmp/preload.so /data/local/tmp/su_daemon_aarch64_pie"

adb shell "LD_PRELOAD=/data/local/tmp/preload.so \
  /data/local/tmp/su_daemon_aarch64_pie \
  > /data/local/tmp/output.log 2>&1"

In caso di successo il demone ascolta su /data/local/tmp/temp_su.sock e su viene installato in /apex/com.android.virt/bin.

Scansione pipei m1q (bring-up corrente)

tools/run_pipei.sh pusha il binario, ne verifica lo sha256 on-device (un preload.so obsoleto produce verdetti silenziosamente illeggibili — la scala ha eseguito una volta una build < #22 il cui formato di log differisce), poi esegue la scansione completa dei 168 candidati suddivisa in chunk 3x56 cosi un panic perde al massimo un chunk (~10 min). Lo stdout dell'exploit viene trasmesso direttamente attraverso adb (nessun redirect on-device — un tee lato dispositivo perde la coda su panic); una copia lato host di ogni chunk viene mantenuta in /tmp/m1q_pipei_chunk{1..3}_stream.log:

root@kitploit:~
sh tools/run_pipei.sh

PASS = qualsiasi chunk mostra tmp_page uname changed + after uname='CatOS. PIPEI_CHILD_REGIONS deve essere impostato almeno alla dimensione del chunk, altrimenti le regioni rt_mutex per-child restano non seedate e la scansione va in panic al candidato 0. La copertura completa richiede anche TMP_UNAME_PIPEI_SPLIT_ORDER_PAGES=1 — senza di esso viene scansionata solo una pagina del blocco mm liberato di 8 pagine. run_pipei_slim.sh e la variante diagnostica a singolo candidato; run_m1q_ladder.sh e la batteria walk/isolation (oracolo B16-2, meccanismo slide, passi della scansione).

Configurazione runtime (variabili d'ambiente)

Layout del progetto

root@kitploit:~
exploit/
  Makefile
  assets/                     # wallpaper.webp (embedded post-root artifact)
  src/
    main.c                    # run_exploit() entry point (shared)
    preload.c                 # LD_PRELOAD constructor, su/wallpaper install
    util.c                    # addr translation, page prep, configfs helpers
    pipe.c                    # pipe-based physical read/write
    root.c                    # cred patching / task walk
    slide.c                   # KASLR slide (tracefs + boot_id routes)
    fops.c                    # pselect corruption + fops manipulation
    faketables.c              # stage-3 fake page-table builders (3-level)
    stage3.c                  # pgd-swap bridge child (no-op unless configured)
    stage3_loop.S, stage3_poll.S  # bridge blob + enter trampoline
    su_daemon.c               # root daemon (compiled as separate PIE)
    su_blob.S, wallpaper_blob.S   # embedded binaries
    offset.h                  # pulls per-target target.h via -DTARGET_CONFIG_H
    kernelsnitch/             # mm_struct futex-hash leak library
    targets/<codename>-<build>/    # per-device target.h + optional overrides
poc/poc.c                     # standalone POC (separate from the exploit)

I target sovrascrivono i sorgenti condivisi tramite il meccanismo pick_src del Makefile: se src/targets/<PROJECT>/<file>.c esiste viene usato al posto del condiviso src/<file>.c; altrimenti viene usata la versione condivisa.

Note e insidie

  • Non rimuovere mai il ciclo della catena PI. La primitiva di scrittura dipende dal fallimento del requeue con -EDEADLK (errno 35). Un ciclo mancante si manifesta come success=1 con effetto kernel nullo.
  • Il waiter deve detenere il lock della catena PI durante pselect. Rilasciarlo prima lascia che l'owner si svegli e corra contro la traversata fake rb_tree → panic.
  • m1q: PSELECT_WAITER_WORD_SHIFT deve essere 0 (profondita stack ZF1 verificate dall'ELF). Gli altri target hanno ancora default 1 — verificare per dispositivo prima di fidarsene.
  • p0_data_alias() usa DIRECT_MAP_BASE (la linear map), che differisce da P0_PAGE_OFFSET su ZF1. Gli alias dati per oggetti kernel dereferenziati devono usare la linear map.
  • pr_error() e fatale (exit(-1)), a differenza delle macro warning/info.
  • La ricostruzione dello slide usa SLIDE_LOGGERS_0_1, non SLIDE_NFULNL_LOGGER; la parola e un alias linear-map non randomizzato, quindi la rotta boot_id e indipendente dallo slide (usarla solo a slide=0 — eseguire prima il leak tracefs).

Disclaimer

Questo e codice di exploit per dispositivi Android ed e destinato alla ricerca di sicurezza, a test di vulnerabilita autorizzati e ad attivita difensive su hardware di proprieta o per cui si ha esplicita autorizzazione al test. L'uso improprio su dispositivi non propri e illegale. L'autore non e responsabile per dispositivi brickati, kernel brickati o garanzie decadute.

Scarica lo strumento
mm_struct
mm_struct
  • Rotta principale — bootstrap pipei tmp_page (m1q, focus corrente) — la rotta configfs CFI originale e un vicolo cieco su m1q: il Rust ashmem non ha uno slot statico write_iter iniettabile e l'oggetto heap ASHMEM_SET_NAME e un KVec il cui layout non si allinea con il private_data di configfs_bin_write_iter. m1q passa a una scrittura kmalloc: recupera il blocco mm order-3 leakato come oggetti pipe_inode_info e usa la scrittura pselect W1 (*(tree_left) = tree_pc) per sovrascrivere lo slot tmp_page di un candidato (+0x90) con la pagina del namespace UTS (init_uts_ns). Una scrittura fanout pianta un nome marker all'offset sysname e uname() riporta "CatOS" — una scrittura kernel verificabile senza dipendenza da oggetti statici. I target C-ashmem mantengono il percorso configfs.
  • Pipe physrw — forgia pagine buffer pipe nella pagina kernel spruzzata per lettura/scrittura fisica: patching delle cred, disabilitazione di SELinux e manipolazione diretta della memoria kernel.
  • Root — patcha le cred del figlio root (uid/gid/caps/SELinux SID), poi preload.c installa il demone su incorporato (montato su tmpfs in /apex/com.android.virt/bin, piu varianti adbd-namespace e locali) e scambia il wallpaper.
  • VariabileDefaultScopo
    PSELECT_ROUTE_SHIFTcompile-timeShift A/B della parola fd_set per la rotta principale (m1q)
    SLIDE_SHIFTcompile-timeShift A/B della parola fd_set per la rotta slide
    PSELECT_ROUTE_DELAY_USEC50000Ritardo del consumer prima di sched_setattr (deve essere > 0)
    SLIDE_CONSUME_USEC, SLIDE_ENTER_DELAY_USEC, SLIDE_CONSUMER_CORE—Timing/pinning della rotta slide
    SKIP_SLIDE0Usa il fallback direct-map (slide = 0)
    SLIDE_ONLY0Esegui solo lo slide KASLR ed esci
    SLIDE_P0_OFFSET, SLIDE_BOOTID_OFF—Override degli offset slide p0-alias / boot_id
    SLIDE_FORCE_BOOTID0Forza la rotta boot_id pselect dopo lo slide tracefs (test del meccanismo)
    KSNITCH_COLLISIONS4Conteggio collisioni KernelSnitch
    STAGE30Abilita la fase figlio bridge pgd-swap (m1q)
    STAGE3_DRYRUN0Prepara/verifica le tabelle poi abortisce prima dello swap
    PAGE_RECLAIM_SENDS, PSELECT_SIMPLE_LAYOUT—Ritocchi allo spray/layout fd-set
    TMP_PAGE_UNAME0Esegui il bootstrap pipei tmp_page-uname di m1q
    TMP_UNAME_PIPEI_SWEEP, TMP_UNAME_PIPEI_ALIGN_ORDER, TMP_UNAME_PIPEI_SPLIT_ORDER_PAGES—Modalita scansione; split_order scansiona tutte le 8 pagine del blocco mm liberato
    TMP_UNAME_PIPEI_SLOT, TMP_UNAME_PIPEI_SLOT_CANDIDATES—Intervallo di scansione (inizio chunk / conteggio)
    PIPEI_CHILD_REGIONS0Regioni rt_mutex seedate per-child; DEVE essere >= chunk della scansione o le regioni non seedate vanno in panic al candidato 0
    PIPEI_RECLAIM_COUNT, PIPEI_DRAIN_COUNT—Coppie pipe di reclaim/drain; aumentare in caso di reclaim miss
    PIPEI_SPONGE_MB3072Spugna flood Order-0 mantenuta durante il reclaim (build #29)
    PSELECT_W0_PRIO_OVERRIDE130Prio del top-waiter; inerte con regioni seedate (guardia legacy stale-tree, solo A/B)
    PSELECT_SKB_DELTA_OVERRIDE0Offset intra-pagina del payload A/B (solo se un dispositivo differisce da -0xe78)
    TMP_UNAME_NAME, TMP_UNAME_HOLD_SEC"CatOS", 5Nome marker / tempo di hold dopo il successo
  • SKB_DATA_DELTA e -0xe78 (misurato on-device, build #19) — la vera testa del frag skb e 8 byte in meno del -0xe80 derivato dal disasm; quell'errore di 8 byte ha causato ogni crash deterministico di pselect dalle build #6-18 (walk-entered → deref spazzatura). Valore condiviso GKI 6.12; le copie per-target di util.c portano una manopola A/B env SKB_DATA_DELTA. NON impilare PSELECT_SKB_DELTA_OVERRIDE sopra la costante cablata.
  • Il corpo della camminata e pulito; il bug era il posizionamento. Con il payload seedato agli offset modellati la camminata della catena si completa senza fault on-device. Un crash walk-entered significa che la memoria agli indirizzi delle parole fd NON e il payload (race di reclaim/posizionamento), non un errore del modello.
  • m1q: la rotta configfs CFI e un vicolo cieco (Rust ashmem) — nessuno slot fops statico iniettabile e l'involucro KVec di ASHMEM_SET_NAME non si allinea con configfs_bin_write_iter. Usa il bootstrap pipei tmp_page. Le guardie PSELECT_WRITE_RIGHT_SPRAYED / PSELECT_PI_TOP_TASK_SELF in target.h di m1q reindirizzano le scritture [11] della camminata fuori dai fops statici RO.
  • Regioni rt_mutex per-child (build #33): ogni figlio della scansione reindirizza la parola fd w13 alla propria regione seedata (payload+0x6000 + idx*0x40) dentro la pagina recuperata. Le scansioni con fake_lock condiviso andavano in panic al candidato ~9-12 (nodi stale dello stack kernel riciclati), e le regioni vuote della build #32 andavano in panic al candidato 0 (wake [9] owner==NULL sul fake_task riempito di 0x41). PIPEI_CHILD_REGIONS deve essere impostato o le regioni restano non seedate.
  • Lo slide pselect boot_id di m1q e parcheggiato — il suo target W1 e RAM bassa la cui scrivibilita di pagina varia a ogni boot; tracefs e la primaria e misura lo slide a ogni esecuzione.