Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/i-redbyte/android-badbinder-demo
Segurança AndroidEscalada de PrivilégiosExploraçãoAprendizado e EducaçãoExploração de Binários
GitHubi-redbyte/android-badbinder-demo

android-badbinder-demo

demo CVE-2019-2215 (Bad Binder) para Android Q

Ver Repositório
5114há 10 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2019-2215 (Bad Binder) — Análise do exploit

Este repositório é um pequeno projeto de teste para pesquisa da vulnerabilidade
CVE-2019-2215 (Bad Binder) e escrita de um protótipo funcional de exploit para Android com interface gráfica simples em Kotlin/Jetpack Compose.

No README eu:

  1. Descrevo a preparação do ambiente e a execução do protótipo do exploit.
  2. Discuto as principais etapas de exploração do CVE-2019-2215 e as relaciono com funções específicas no código C.
  3. Listo separadamente as dificuldades que encontrei pelo caminho e como as resolvi.

APK pronto (GitHub Actions)

O repositório possui um workflow do GitHub Actions que, a cada push/PR, compila o projeto com o comando ./gradlew assembleDebug e publica o badbinder-debug.apk como artefato.

Pode ser baixado assim:

  1. Abrir a aba Actions no repositório.
  2. Selecionar a execução do workflow desejada.
  3. No final da página, encontrar a seção Artifacts e pegar o arquivo badbinder-debug-apk com o APK compilado.

Isso foi feito por conveniência, caso queira apenas testar o aplicativo sem montar um ambiente local.


Breve sobre a vulnerabilidade

CVE-2019-2215 é um Use-After-Free (UAF) no subsistema de IPC Binder do kernel Android.

De forma simplificada:

  • no kernel existe uma estrutura struct binder_thread, que descreve uma thread realizando chamadas Binder;
  • esta estrutura pode ser liberada (free), mas sob uma certa sequência de chamadas ainda permanece nas listas de espera (waitqueue);
  • posteriormente o kernel tenta trabalhar com a memória já liberada em remove_wait_queue, o que abre um cenário clássico de UAF;
  • se o ambiente e as alocações subsequentes forem cuidadosamente ajustados, é possível fazer o kernel ler/escrever em endereços arbitrários, e então — obter privilégios de kernel e, em seguida, root no userspace.

Uma análise teórica mais detalhada fiz com base nos materiais:

  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. Preparação do ambiente e execução do protótipo do exploit

1.1. Escolha e preparação do dispositivo virtual

Conforme recomendado na tarefa, usei um AVD com imagem Android 10.0 (Q) x86_64.
Fiz o seguinte:

  1. No Android Studio criei um AVD (dispositivo Pixel, Android 10 (Q), x86_64).
  2. Verifiquei se a imagem possui Binder ativado e o dispositivo /dev/binder.
  3. Ativei a depuração via USB/ADB e verifiquei o acesso ao dispositivo:
    adb shell
    ls -l /dev/binder
    

Nesta etapa me deparei com um fato desagradável:
atualmente, as imagens AVD atuais já vêm com kernel corrigido, no qual o CVE-2019-2215 está fechado. Ou seja, não será possível obter root em um emulador oficial moderno — o exploit falha em estágios posteriores ou simplesmente não concede elevação de privilégios.

No final, uso o AVD como simulador para reproduzir a lógica do exploit:

  • obtenho as mesmas sequências de chamadas de sistema,
  • observo as tentativas de UAF, vazamento de endereços e tentativa de sobrescrever addr_limit,
  • mas a obtenção final de "root" no kernel atual e corrigido, naturalmente, não funciona (e isso é esperado).

Essa é uma nuance importante: todo o código e relatório abaixo são educacionais, não "de combate".


1.2. Compilação do aplicativo Android com exploit nativo

Criei um pequeno aplicativo Android:

  • UI em Kotlin + Jetpack Compose,
  • Parte nativa em C via JNI — o código do exploit em si,
  • comunicação entre eles via callback JNI, para que as strings do código C sejam enviadas diretamente para a UI.

Principais passos:

  1. Criei um projeto normal no Android Studio (Kotlin, suporte mínimo ao Android 10).

  2. Conectei o NDK e o CMake.

  3. Adicionei o arquivo nativo com o exploit (o mesmo cve-2019-2215.c com funções leak_task_struct, overwrite_addr_limit, etc.).

  4. No CMakeLists.txt adicionei a compilação de libcve-2019-2215.so.

  5. No MainActivity:

    init {
        System.loadLibrary("cve-2019-2215")
    }
    
    external fun runNativeExploit(): String
    external fun setNativeLogger(logger: NativeLogger)
    
  6. No lado Kotlin fiz um ExploitViewModel que implementa a interface NativeLogger e armazena todas as mensagens em um StateFlow<List<String>>. A UI se inscreve nesse fluxo e exibe o log em um "terminal".

Ao iniciar a activity, chamo setNativeLogger(viewModel), para que o código nativo receba um objeto para o qual possa enviar strings.


1.3. Execução e cenário de uso

  1. Compilo e instalo o aplicativo:

    ./gradlew installDebug
    
  2. Inicio o AVD e o próprio aplicativo.

  3. Na tela vejo um "terminal" e um botão RUN EXPLOIT.

  4. Ao pressionar:

    • Kotlin chama runNativeExploit() em uma thread em segundo plano.
    • O código C começa a executar todas as etapas do exploit e registra os passos.
    • Através do callback JNI, o log chega ao ViewModel e é exibido na UI Compose.

Em um kernel real vulnerável, eu esperaria ver algo como:

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

No emulador atual do Android 10 isso, obviamente, não ocorre, mas todo o resto — vazamento de task_struct, tentativa de sobrescrever addr_limit, cálculo de cred e kernel_base — funciona como um "cenário", que era o que se pedia na tarefa.


2. Análise das principais etapas do exploit e relação com o código

Abaixo — esquema lógico do exploit com vínculo às funções C específicas.

2.1. Cenário geral do exploit

O plano de alto nível é:

  1. Criar um UAF no objeto struct binder_thread e usá-lo para vazar o endereço do task_struct do próprio processo (leak_task_struct).
  2. Com um segundo ciclo de UAF e estruturas cuidadosamente ajustadas, sobrescrever o campo addr_limit no task_struct (overwrite_addr_limit) — isso remove a restrição entre endereços de user-space e kernel-space para posteriores copy_to_user / copy_from_user.
  3. Usando pipes, implementar leitura/escrita arbitrária de qualquer memória do kernel (arb_read / arb_write).
  4. Com isso, encontrar o cred do processo atual e a base do kernel (verifying), em seguida:
    • desativar o SELinux (selinux_enforcing = 0),
    • sobrescrever os campos de cred para se tornar root e obter o conjunto completo de capabilities (runNativeExploit).

Paralelamente, integrei um logger JNI para que todas essas etapas fossem visíveis diretamente na UI.


2.2. Etapa 1 — vazamento do endereço do task_struct (leak_task_struct)

Função principal:

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);
    ...
}

O que a função faz:

  1. Fixa a thread na CPU 0 (sched_setaffinity), para tornar o comportamento do alocador do kernel mais previsível. Isso melhora a estabilidade da exploração do UAF.

  2. Abre /dev/binder, cria um descritor epoll:

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

    O descritor Binder é registrado no epoll:

    epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
    
  3. Prepara um array struct iovec iov_buffers[IOVEC_N] e aloca memória:

    spinner = mmap((void *)0x100000000, page_size, PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    

    Aqui é importante que os 32 bits inferiores do endereço sejam zeros:

    if (((long) spinner & 0xffffffff) != 0) {
        android_log("[!] mmap returned wrong address!");
        return;
    }
    
Baixar ferramenta