
استغلال LPE كإثبات للمفهوم لثغرة UAF في Android Binder يستخدم تقنية iovec spraying والكتابة فوق addr_limit لتحقيق قراءة/كتابة عشوائية في النواة.
إثبات مفهوم (Proof-of-Concept) مُعاد كتابته / استغلال تصعيد امتيازات محليًا (LPE) يستهدف CVE-2019-2215، وهي ثغرة استخدام بعد تحرير (Use-After-Free) في مشغّل Android Binder.
لقد وفرت بناء النواة القابل للاستغلال في مجلد vulnerable_kernel_builds. أنشئ محاكي أندرويد 10 من نوع AOSP وقم بتشغيل النواة معه
emulator -show-kernel -no-window -no-snapshot -wipe-data -avd research -kernel bzImage
للاطلاع على التفاصيل التقنية للثغرة، يمكنك التعلم من هذه المدونة الرائعة https://projectzero.google/2019/11/bad-binder-android-in-wild-exploit.html
بنية task_struct تحتوي على عضو مهم addr_limit من النوع mm_segment_t. addr_limit يخزن أعلى عنوان صالح لمساحة المستخدم. addr_limit جزء من struct thread_info أو struct thread_struct اعتمادًا على بنية الهدف. وبما أننا نتعامل مع نظام x86_64، فإن addr_limit معرّف في struct thread_struct.

إذا تمكنا من الكتابة فوق addr_limit بالقيمة 0xFFFFFFFFFFFFFFFF، سنتمكن من القراءة والكتابة في أي جزء من ذاكرة مساحة النواة. من أجل توافق أفضل للاستغلال على x86_64 و arm64، من الأفضل ضبط addr_limit إلى 0xFFFFFFFFFFFFFFFE
struct iovec يُستخدم للإدخال/الإخراج المتجهي (Vectored I/O) والمعروف أيضًا باسم الإدخال/الإخراج المبعثر/المجمّع (Scatter/Gather I/O). أحد المشكلات الرئيسية مع struct iovec هي أنها قصيرة العمر. يتم تخصيصها بواسطة استدعاءات النظام عندما تتعامل مع المخازن المؤقتة وتُحرر فورًا عند عودتها إلى وضع المستخدم.
نريد أن تبقى بنية iovec في النواة عندما نُطلق عملية إلغاء الربط (unlink) ونستبدل مؤشر iov_base بعنوان binder_thread->wait.head للحصول على قراءة وكتابة محدودة النطاق. إحدى الطرق هي استخدام استدعاءات نظام مثل readv, writev على واصف ملف pipe لأنه يمكن أن يحظر إذا كان pipe ممتلئًا أو فارغًا. pipe قناة بيانات أحادية الاتجاه يمكن استخدامها للتواصل بين العمليات. ميزة الحظر في pipe تمنحنا نافذة زمنية كبيرة لإفساد بنية iovec في مساحة النواة.
وبالمثل، يمكننا استخدام استدعاء النظام recvmsg لحظره عن طريق تمرير MSG_WAITALL كمعامل للعلامة (flag).
بما أن حجم بنية binder_thread هو 408 بايت، فإنها ستُخصص في مخبأ kmalloc-512.

سنحتاج إلى تكديس 25 بنية iovec لإعادة تخصيص القطعة المعلّقة (dangling chunk). 408 / 16 = 25.5

كما نرى من الصورة أعلاه، سيتم إتلاف iovecStack[10].iov_len و iovecStack[11].iov_base.

لذا، سنرغب في معالجة iovecStack[10]، وحجب استدعاء النظام writev ثم تشغيل عملية unlink. سيضمن ذلك أنه عند إتلاف iovecStack[11].iov_base، سنستأنف استدعاء النظام writev. وأخيرًا، نسرب محتوى قطعة binder_thread إلى مساحة المستخدم ونقرأ مؤشر task_struct منها

لتحقيق write محدود النطاق، سنستخدم استدعاء النظام recvmsg لحظره عن طريق تمرير MSG_WAITALL كمعامل للعلامة. يمكن لاستدعاء النظام recvmsg أن يحظر تمامًا مثل استدعاء النظام writev.

بما أن حجم mm_segment_t هو 0x8 بايت، سنرغب في إتلافه بالقيمة 0xFFFFFFFFFFFFFFFE لأنها أعلى عنوان صالح لمساحة النواة ولن تتسبب في تعطل العملية إذا حدث خطأ في الصفحة (page fault) على نظام arm64.

