Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
android-badbinder-demo — Demostración de CVE-2019-2215 (Bad Binder) para Android Q | Kitploit
Herramientas/GitHubGitHub/i-redbyte/android-badbinder-demo
Seguridad AndroidEscalada de PrivilegiosExplotaciónAprendizaje y EducaciónExplotación de Binarios
GitHubi-redbyte/android-badbinder-demo

android-badbinder-demo

Demostración de CVE-2019-2215 (Bad Binder) para Android Q

Ver Repositorio
5114hace 10 mesesAún no revisado

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

CVE-2019-2215 (Bad Binder) — Análisis del exploit

Este repositorio es un pequeño proyecto de prueba para investigar la vulnerabilidad
CVE-2019-2215 (Bad Binder) y escribir un prototipo funcional de exploit para Android con una interfaz gráfica simple en Kotlin/Jetpack Compose.

En el README:

  1. Describo la preparación del entorno y la ejecución del prototipo del exploit.
  2. Analizo las etapas principales de explotación de CVE-2019-2215 y las comparo con funciones específicas en el código C.
  3. Enumero por separado las dificultades que encontré en el camino y cómo las resolví.

APK listo (GitHub Actions)

En el repositorio hay configurado un workflow de GitHub Actions que en cada push/PR compila el proyecto con el comando ./gradlew assembleDebug y publica el badbinder-debug.apk listo como artefacto.

Se puede descargar así:

  1. Abrir la pestaña Actions en el repositorio.
  2. Seleccionar la ejecución del workflow deseada.
  3. Al final de la página encontrar la sección Artifacts y tomar el archivo badbinder-debug-apk con el APK compilado.

Esto se hizo para mayor comodidad, si solo quieres probar la aplicación sin montar un entorno local.


Brevemente sobre la vulnerabilidad

CVE-2019-2215 es un Use-After-Free (UAF) en el subsistema IPC Binder del kernel de Android.

De forma simplificada:

  • en el kernel existe una estructura struct binder_thread que describe el hilo que realiza llamadas a Binder;
  • esta estructura puede ser liberada (free), pero con una cierta secuencia de llamadas sigue estando en las listas de espera (waitqueue);
  • más tarde el kernel intenta trabajar con memoria ya liberada en remove_wait_queue, lo que abre un escenario clásico de UAF;
  • si se elige cuidadosamente el entorno y las asignaciones posteriores, se puede hacer que el kernel lea/escriba en direcciones arbitrarias, y luego obtener privilegios de kernel y después root en userspace.

Un análisis teórico más detallado lo hice basándome en los materiales:

  1. https://cloudfuzz.github.io/android-kernel-exploitation/
  2. https://dayzerosec.com/blog/2019/11/07/analyzing-androids-cve-2019-2215-dev-binder-uaf.html
  3. https://hernan.de/blog/tailoring-cve-2019-2215-to-achieve-root/

1. Preparación del entorno y ejecución del prototipo del exploit

1.1. Elección y preparación del dispositivo virtual

Según la tarea se recomienda usar un AVD con imagen Android 10.0 (Q) x86_64.
Hice lo siguiente:

  1. En Android Studio creé un AVD (dispositivo Pixel, Android 10 (Q), x86_64).
  2. Me aseguré de que en la imagen estuviera habilitado Binder y existiera el dispositivo /dev/binder.
  3. Activé la depuración por USB/ADB y verifiqué el acceso al dispositivo:
    adb shell
    ls -l /dev/binder
    

En esta etapa me encontré con un hecho desagradable:
en la actualidad las imágenes AVD actuales ya vienen con el kernel parcheado, en el que CVE-2019-2215 está corregida. Es decir, realmente no se podrá obtener root en un emulador oficial moderno: el exploit falla en etapas posteriores o simplemente no da escalada de privilegios.

Como resultado, uso el AVD como entrenador para reproducir la lógica del exploit:

  • obtengo las mismas secuencias de llamadas al sistema,
  • observo los intentos de UAF, la fuga de direcciones y el intento de sobrescribir addr_limit,
  • pero la «obtención de root» final en el kernel actual parcheado, naturalmente, no funciona (y esto es esperable).

Este es un matiz importante: todo el código y el informe a continuación — educativos, no «de combate».


1.2. Compilación de la aplicación Android con el exploit nativo

Hice una pequeña aplicación Android:

  • UI en Kotlin + Jetpack Compose,
  • Parte nativa en C a través de JNI — el propio código del exploit,
  • la comunicación entre ellos — mediante callback de JNI, para que las cadenas del código C lleguen directamente a la UI.

Pasos principales:

  1. Creé un proyecto normal en Android Studio (Kotlin, soporte mínimo para Android 10).

  2. Conecté NDK y CMake.

  3. Añadí el archivo nativo con el exploit (el famoso cve-2019-2215.c con las funciones leak_task_struct, overwrite_addr_limit, etc.).

  4. En CMakeLists.txt añadí la compilación de libcve-2019-2215.so.

  5. En MainActivity:

    init {
        System.loadLibrary("cve-2019-2215")
    }
    
    external fun runNativeExploit(): String
    external fun setNativeLogger(logger: NativeLogger)
    
  6. Del lado de Kotlin hice un ExploitViewModel que implementa la interfaz NativeLogger y guarda todos los mensajes en StateFlow<List<String>>. La UI está suscrita a ese flujo y muestra el log en una «terminal».

Al iniciar la actividad llamo a setNativeLogger(viewModel) para que el código nativo reciba el objeto al que puede enviar cadenas.


1.3. Ejecución y escenario de uso

  1. Compilo e instalo la aplicación:

    ./gradlew installDebug
    
  2. Arranco el AVD y la propia aplicación.

  3. En pantalla veo una «terminal» y el botón RUN EXPLOIT.

  4. Al pulsarlo:

    • Kotlin llama a runNativeExploit() en un hilo en segundo plano.
    • El código C comienza a ejecutar todas las etapas del exploit y a registrar los pasos.
    • A través del callback de JNI el log llega al ViewModel y se muestra en la UI de Compose.

En un kernel vulnerable real esperaría ver al final algo como:

[+] Selinux changed: Permissive now.
[+] Root escalation successful!
uid=0(root)...

En el emulador actual de Android 10 esto, por supuesto, no ocurre, pero todo lo demás — fuga de task_struct, intento de sobrescribir addr_limit, cálculo de cred y kernel_base — funciona como «escenario», que es lo que se pedía para la tarea.


2. Análisis de las etapas principales del exploit y comparación con el código

A continuación — el esquema lógico del exploit con referencia a funciones C específicas.

2.1. Escenario general del exploit

El plan de alto nivel es el siguiente:

  1. Crear un UAF en el objeto struct binder_thread y usarlo para filtrar la dirección de task_struct del propio proceso (leak_task_struct).
  2. Con un segundo ciclo de UAF y estructuras cuidadosamente elegidas, sobrescribir el campo addr_limit en task_struct (overwrite_addr_limit) — esto elimina la restricción entre las direcciones de user-space y kernel-space para posteriores copy_to_user / copy_from_user.
  3. Usando pipes, implementar lectura/escritura arbitraria de cualquier memoria del kernel (arb_read / arb_write).
  4. Con esto, encontrar cred del proceso actual y la base del kernel (verifying), luego:
    • desactivar SELinux (selinux_enforcing = 0),
    • sobrescribir los campos de cred para convertirse en root y obtener el conjunto completo de capabilities (runNativeExploit).

En paralelo integré un logger JNI para que todas estas etapas fueran visibles directamente en la UI.


2.2. Etapa 1 — fuga de la dirección de task_struct (leak_task_struct)

Función clave:

void leak_task_struct() {
    android_log("[*] Starting leak_task_struct...");

    cpu_set_t cpu_set;
    CPU_ZERO(&cpu_set);
    CPU_SET(0, &cpu_set);
    ret = sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
    assert(ret >= 0);
    ...
}

Qué hace la función:

  1. Fija el hilo en la CPU 0 (sched_setaffinity) para que el comportamiento del asignador del kernel sea más predecible. Esto mejora la estabilidad de la explotación del UAF.

  2. Abre /dev/binder, crea un descriptor epoll:

    fd = open("/dev/binder", O_RDONLY);
    epfd = epoll_create(1000);
    

    El descriptor de Binder se registra en epoll:

    epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
    
  3. Prepara un array de struct iovec iov_buffers[IOVEC_N] y asigna memoria:

Descargar herramienta