Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
AndroidKernelVulnerability — تشغيل وتحليل ثغرة نواة أندرويد CVE-2019-2215 | Kitploit
أدوات/GitHubGitHub/sharif-dev/androidkernelvulnerability
أمان أندرويدتصعيد الامتيازاتالتحليل الثابتالتحليل الديناميكي (عزل)الاستغلالالتعلم والتعليماستغلال الملفات الثنائيةمختبرات وتدريب عملي

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
GitHub
sharif-dev/androidkernelvulnerability

AndroidKernelVulnerability

تشغيل وتحليل ثغرة نواة أندرويد CVE-2019-2215

عرض المستودع
721911منذ 4 سنواتتمت المراجعة من قبل Kitploit

ثغرة نواة أندرويد

نظرة عامة

في نوفمبر 2017، تم اكتشاف خلل use-after-free في نواة لينكس بواسطة نظام syzkaller . في فبراير 2018، تم إصلاح هذا الخلل في بعض أنوية لينكس وإصدارات أندرويد.

لم يتم تضمين هذا الإصلاح أبداً في النشرات الأمنية الشهرية لأندرويد، لذلك لم يتم إصلاحه في العديد من الأجهزة الصادرة حديثاً مثل Pixel وPixel2.

في سبتمبر 2019، تم إبلاغ أندرويد بالآثار الأمنية لهذا الخلل من قبل Project Zero. ثم خصصت أندرويد لهذه الثغرة CVE-2019-2215 لجعلها أكثر رسمية وشهرة.

CVE-2019-2215 هي ثغرة use-after-free في binder.c تسمح بتصعيد الصلاحيات (الحصول على صلاحية الجذر) من تطبيق أندرويد. لا حاجة لتفاعل المستخدم، لاستغلال هذه الثغرة. يتطلب الأمر فقط تثبيت تطبيق محلي خبيث.

هنا سنقدم هذه الثغرة الأمنية في نواة أندرويد بمزيد من التفاصيل وسنستخدم هذه الثغرة للحصول على صلاحية الجذر (تصعيد الصلاحيات) لجهاز أندرويد بأكمله.

سنستخدم إثبات المفهوم (PoC) التالي:

https://github.com/cloudfuzz/android-kernel-exploitation

تحفيز الثغرة الأمنية

سنعرض لكم أولاً طريقة لتحفيز هذه الثغرة على محاكي أندرويد وإحداث تعطل للنواة. ثم لمعرفة مدى خطورتها، سنواصل استخدام الـ PoC للحصول على صلاحية الجذر في جهاز أندرويد المحاكى. بعدها سنحلل كود النواة لمعرفة السبب (التحليل الساكن والتحليل الديناميكي).

بعد التحليل، سنرى كيف حصلنا على صلاحية الجذر. وفي النهاية سنرى كيف يتم تخفيف هذه الثغرة باستخدام التصحيحات.

لإحداث تعطل في النواة عن طريق تحفيز هذه الثغرة، نتبع الخطوات التالية:

  1. أولاً، تحتاج إلى نظام تشغيل لينكس مع تثبيت 'gdb' و'python'.
  2. استنسخ مستودع الـ PoC. (https://github.com/cloudfuzz/android-kernel-exploitation)
  3. ثبّت محاكي أندرويد وandroid NDK (عن طريق تثبيت Android Studio)
  4. استنسخ الكود المصدري لنواة أندرويد. (سيتم استخدام فرع 'q-goldfish-android-goldfish-4.14-dev')
  5. هذه النواة مُصلحة بالفعل، وسنقوم بتغييرها لإعادة إدخال الثغرة في كود النواة هذا.
  6. الآن يجب علينا بناء النواة من الكود المصدري. نبني نواتنا باستخدام KASan.
  7. نقوم بإقلاع النواة المبنية وتشغيل المحاكي بها.
  8. بعدها باستخدام 'trigger.cpp' في مستودع الـ PoC، نقوم بتحفيز تعطل (باستخدام أمر 'adb').
  9. سنستخدم 'root-me.py' في الـ PoC وأمر 'gdb' للحصول على صلاحية الجذر في الجهاز المحاكى.

شاهد الفيديو التالي:

[فيديو]

التحليل الساكن

في هذا القسم (والقسم التالي) سنفهم سبب حدوث التعطل باستخدام التحليل الساكن والديناميكي.

هنا سنقوم بتحليل كود النواة (التحليل الساكن) لفهم المشكلة. في crash_report.txt يوجد تقرير من KASan يوضح أن هذه ثغرة use-after-free. هذا يعني أن كائناً تم تخصيصه في الكومة (وكان لدينا مرجع إليه)، ثم قمنا بتحرير الكائن من الكومة، وبعد ذلك قمنا باستدعائه خطأً عبر مرجع. في هذا التقرير تتم طباعة تتبع المكدس لهذه المراحل الثلاث.

إذا كنت تتذكر مما سبق، فقد استخدمنا 'trigger.cpp' في الـ PoC.

إليك الكود الرئيسي لـ trigger.cpp:``` int main() { //1 int fd, epfd; //2 struct epoll_event event = {.events = EPOLLIN}; //3 fd = open("/dev/binder", O_RDONLY); //4 epfd = epoll_create(1000); //5 epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); //6 ioctl(fd, BINDER_THREAD_EXIT, NULL); }

دعونا نرى ما يفعله 'trigger.cpp'.

في أندرويد (مثل أنظمة التشغيل الأخرى المبنية على يونكس) لدينا بعض العمليات (processes). كل برنامج نشغّله يُنشئ عملية واحدة (أو أكثر)، وهذه العمليات يديرها نظام التشغيل (OS). قد يبدّل نظام التشغيل بينها (تعدد المهام) أو ينهي عملية، إلخ. لأسباب أمنية، تكون العمليات معزولة عن بعضها البعض افتراضيًا.

في بعض الحالات، قد تحتاج عملية إلى تبادل بيانات مع عملية أخرى. يُسمى هذا التواصل بين العمليات (IPC). هناك عدة طرق للعمليات للتواصل في لينكس. أدخلت أندرويد آلية IPC محددة تسمى **'Binder'**. Binder هو مشغّل نواة (kernel driver) لتسهيل التواصل بين العمليات.

في أندرويد، يمكن تنفيذ IPC عن طريق استدعاء بعض دوال النواة مباشرة (معظمها في drivers/binder.c) أو باستخدام تطبيقات عالية المستوى (مثلًا في جافا).

![alt_text](https://raw.githubusercontent.com/sharif-dev/AndroidKernelVulnerability/master/images/binder.jpg)

لاستخدام **binder**، يجب علينا فتح وحدة binder الخاصة بالنواة. يتم ذلك باستخدام السطر 3 من trigger.cpp. بعدها يكون لدينا مؤشر واصف ملف (file descriptor). باستخدام واصف الملف هذا يمكن تحديد مُبادر النواة ومستقبلي الـ IPC.

جميع التفاعلات مع المشغّل ستتم عبر مجموعة صغيرة من أوامر **'ioctl**' (BINDER_THREAD_EXIT, BINDER_WRITE_READ, ...).

المزيد عن binder: [link1](https://www.nds.ruhr-uni-bochum.de/media/attachments/files/2012/03/binder.pdf), [link2](http://rts.lab.asu.edu/web_438/project_final/CSE_598_Android_Architecture_Binder.pdf)

في لينكس، لدينا مفهوم يسمى '**استطلاع الأحداث (event polling)**'. تُستخدم واجهة برمجة التطبيقات '**epoll**' عندما نريد مراقبة عدة واصفات ملفات (واصفات الملفات هي ما نملكه عند فتح مشغّل أو العمل مع الإدخال/الإخراج، إلخ).

**epoll** هو بنية نواة (kernel struct) لها حقلان مهمان.

*   interest list = قائمة واصفات الملفات التي نريد مراقبتها.
*   ready list = قائمة واصفات الملفات الجاهزة للإدخال/الإخراج (I/O).

لاستخدام استطلاع الأحداث، نقوم أولاً بإنشاء epoll (السطر 4)، ثم نضيف أو نحذف (EPOLL_CTL_ADD) حدثًا (&event) مرتبطًا بواصف ملف (**fd**) إلى الـ epoll الذي أنشأناه (**epfd**) عن طريق استدعاء دالة النواة **epoll_ctl**.

=>
`epoll_event event` هو حدث يتم تشغيله عندما يكون الملف المرتبط (fd) متاحًا لعملية القراءة.

الآن نفهم ما يفعله **trigger.cpp** (لا حاجة للتعمق!). إنه يفتح وحدة **binder**، وينشئ **epoll** للاستماع إليها عندما تكون جاهزة. ثم في السطر 6، نخرج من binder الذي بدأناه في السطر 3.

#### التخصيص:

عند استدعاء open()، فإننا في الواقع نستدعي **open_binder()** (تنفيذ open() في binder.c)، وفي open_binder()، سيتم إنشاء بنية **'binder_proc'** جديدة و:

   ` fd->pricate_data = binder_proc`

عند استدعاء **epoll_create()**، سيتم إنشاء بنية epoll جديدة وإضافتها إلى بنية قائمة انتظار.

![alt_text](https://raw.githubusercontent.com/sharif-dev/AndroidKernelVulnerability/master/images/event_poll.jpg)

عند استدعاء **epoll_ctrl(epdf, ADD, fd, event)**، يتم إنشاء **ep_item** جديد، وربط **fd** (واصف الملف المراد الاستماع إليه) بـ **ep_item**، وإدراجه في event_poll's** red black tree** (بنية بيانات في ep لحفظ ep_items). كما يستدعي **ep_item_poll()**، وهذه الدالة تتعامل مع ربط دالة الاستدعاء (callback) بـ ep_item.

يقوم بإنشاء بنية **binder_thread** جديدة (**يحدث التخصيص هنا**)، ويربطها بـ **binder_proc** (الذي تم إنشاؤه أعلاه)، ثم يتم إنشاء بنية **epoll_entry**، ولها قائمتان: **epoll_entry->wait** و **epoll_entry->whead**، وكلا القائمتين لديهما مؤشر إلى **binder_thread** الذي تم إنشاؤه سابقًا.

ثم يتم ربط **epoll_entry** بـ ep_item (**ep_item->pwqlist** هي قائمة تحتوي على هذا epoll_entry).

![alt_text](https://raw.githubusercontent.com/sharif-dev/AndroidKernelVulnerability/master/images/even_poll.jpg)

#### التحرير:

عند استدعاء **ioctl(fd, ...)**، يتم الوصول إلى **binder_proc** عبر fd->private_data، ثم يتم **تحرير** بنية **binder_thread** من الذاكرة.

#### الاستخدام:

عندما تنتهي عمليتنا الحالية، سيتم استدعاء **epoll_ctl(epfd, DEL, fd, event)**.

يستدعي **ep_remove(event_poll, ep_item)**. تحصل هذه الدالة على **epoll_entry** من **ep_item->pwqlist**، ثم تحصل على قائمة الانتظار الخاصة بـ **ep_item (ep_tem->wait)**، وهي قائمة مرتبطة، وتريد إزالة أحد عناصر قائمة الانتظار هذه.

يستخدم الكود التالي (كود زائف):```
entry = wait->entry;
entry.next.prev = entry.prev;
entry.prev.next = entry.next;

هنا wait->entry هو مؤشر إلى binder_thread الذي تمت إزالته من الذاكرة! إذن فهو استخدام بعد التحرير (use after free) ويسبّب خطأً!!

  • في ما سبق، استخدمنا أكوادًا مشابهة لأكواد النواة الفعلية، وقد تختلف في بعض التفاصيل. (في بعض الحالات يُستخدم binder_thread بدلاً من binder_thread->wait)

ملخص:

تنزيل الأداة