
إطار استغلال كومة jemalloc
shadow هو إطار عمل لاستغلال الكومة (heap) الخاص بـ jemalloc. تم تصميمه ليكون مستقلًا عن التطبيق الهدف الذي يستخدم jemalloc كموزع للكومة (سواء كان libc الخاص بـ Android، أو Firefox، أو libc الخاص بـ FreeBSD، أو jemalloc المستقل، أو أي شيء آخر). تم اختبار الإصدار الحالي (2.0) بشكل موسع مع الأهداف التالية:
بالإضافة إلى شيفرة المصدر للأداة، يتضمن هذا المستودع أيضًا وثائق حول إعداد بيئة تصحيح أخطاء مستخدم Android لاستخدام shadow، و نظرة سريعة على هياكل jemalloc الخاصة بـ Android باستخدام shadow، وبعض الملاحظات حول كيفية تصرف ثغرات double free() و unaligned free() و arbitrary free() على jemalloc الخاص بـ Android.
عند إصدار أمر خاص بـ jemalloc لأول مرة، يقوم shadow بتحليل جميع البيانات الوصفية (metadata) الخاصة بـ jemalloc التي يعرفها وحفظها في ملف pickle بلغة Python. تستخدم الأوامر اللاحقة ملف pickle هذا بدلاً من تحليل البيانات الوصفية من الذاكرة مرة أخرى لتكون أسرع.
عندما تعلم أن حالة البيانات الوصفية لـ jemalloc قد تغيرت (على سبيل المثال عندما قمت ببعض التخصيصات أو حدث جمع القمامة)، استخدم الأمر jeparse لإعادة تحليل البيانات الوصفية وإعادة إنشاء ملف pickle.
الخطوة الأولى هي تثبيت pyrsistence على جهاز المضيف.
على جهاز rooted قم بما يلي:
host$ adb shell
phone$ su root
phone# ps -e
من مخرجات ps حدد عملية، على سبيل المثال com.google.process.gapps:
...
u0_a19 4679 3214 1668980 69216 SyS_epoll_ 7fa5f41430 S com.google.process.gapps
...
phone$ cd /data/local/tmp
phone$ ./gdbserver64 :5039 --attach 4679
يمكنك العثور على ملفات GDB server الثنائية لـ ARM32 و ARM64 في دليل "bin". أو، إذا كنت لا تثق بنا، قم بما يلي:
host$ git clone http://android.googlesource.com/toolchain/gdb
host$ cd ./gdb/gdb-7.11
host$ mkdir build64; cd build64
host$ ../configure --program-prefix=aarch64-eabi-linux- --target=aarch64-eabi-linux --disable-werror
host$ make
host$ sudo make install
ثم على جهاز المضيف قم بما يلي:
host$ adb forward tcp:5039 tcp:5039
host$ aarch64-eabi-linux-gdb
(gdb) target remote :5039
(gdb) source /dir/with/shadow/gdb_driver.py
(gdb) jeparse -c /dir/with/shadow/cfg/android7_64.cfg
(gdb) jeruns -c
أحيانًا يتوقف GDB server عن الاستماع إذا استغرقت وقتًا طويلاً لإصدار الأمر target remote :5039. لذا إذا رأيت أخطاء غريبة عند إصدار الأمر jeparse، فابدأ من البداية.
تم اختبار shadow على Windows/Firefox مع ما يلي:
ملاحظة: إذا كنت تعمل مع إصدار Firefox أقدم من 36.0، استخدم فرع mozjs!
أولاً، تحتاج إلى إعداد WinDBG مع [خادم الرموز الخاص بـ Mozilla] (https://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server). تحتاج أيضًا إلى تثبيت pykd. ثم انسخ دليل shadow الذي استنسخته من GitHub إلى مسار ما (على سبيل المثال C:\tmp\).
يمكنك أيضًا العثور على ملف نصي لتهيئة WinDBG في الملف "windbg-init.cmd". ضعه في C:\tmp\ وابدأ WinDBG باستخدام windbg.exe -c "$$>< C:\tmp\windbg-init.cmd".
أخيرًا، من داخل WinDBG أصدر الأوامر التالية:
!load pykd.pyd
!py c:\\tmp\\shadow\\pykd_driver help
[shadow] De Mysteriis Dom jemalloc
[shadow] shadow v2.0
[shadow] Firefox v56.0a1 (x86-64)
[shadow] أوامر خاصة بـ jemalloc:
[shadow] jechunks : عرض معلومات عن جميع القطع (chunks) المتاحة
[shadow] jearenas : عرض معلومات عن arenas الخاصة بـ jemalloc
[shadow] jerun [-m] <address> : عرض معلومات عن run واحد
[shadow] -m : عرض معاينة المحتوى إلى البيانات الوصفية
[shadow] jeruns [-cs] : عرض معلومات عن runs الخاصة بـ jemalloc
[shadow] -c : فقط runs الحالية
[shadow] -s <size class> : runs لفئة الحجم المحددة فقط
[shadow] jebins : عرض معلومات عن bins الخاصة بـ jemalloc
[shadow] jebininfo : عرض معلومات عن أحجام bins
[shadow] jesize2bin : تحويل الحجم إلى فهرس bin
[shadow] jeregions <size class> : عرض جميع runs التي تستضيف مناطق (regions)
[shadow] لفئة الحجم المحددة
[shadow] jesearch [-cs] <hex> : البحث في الكومة عن الكلمة السداسية (hex dword) المحددة
[shadow] -c : فقط runs الحالية
[shadow] -s <size class> : فقط مناطق الحجم المحدد
[shadow] jeinfo <address> : عرض جميع التفاصيل المتاحة لعنوان
[shadow] jedump [path] : تخزين لقطة الكومة في دليل العمل الحالي
[shadow] أو في المسار المحدد
[shadow] jestore [path] : اسم مستعار لـ jedump
[shadow] jetcaches : عرض معلومات عن جميع tcaches
[shadow] jetcache [-bs] <tid> : عرض معلومات عن tcache واحد
[shadow] -b <bin index> : معلومات فقط لفهرس bin المحدد
[shadow] -s <size class> : معلومات فقط لفئة الحجم المحددة
[shadow] jeparse [-crv] : تحليل هياكل jemalloc من الذاكرة
[shadow] -c <config file> : ملف تكوين هدف jemalloc
[shadow] -r : قراءة معاينة المحتوى
[shadow] -v : إنتاج debug.log
[shadow] أوامر خاصة بـ Firefox (pykd فقط):
[shadow] nursery : عرض معلومات عن حضانة (nursery) GC الخاصة بـ SpiderMonkey
[shadow] symbol [-vjdx] <size> : عرض جميع رموز Firefox بالحجم المحدد
[shadow] -v : فقط رموز الفئات مع vtable
[shadow] -j : فقط رموز من SpiderMonkey
[shadow] -d : فقط رموز DOM
[shadow] -x : فقط رموز غير SpiderMonkey
[shadow] pa <address> [<length>] : تعديل طول ArrayObject (الطول الجديد الافتراضي 0x666)
[shadow] أوامر خاصة بـ Android:
[shadow] jefreecheck [-bm] : عرض العناوين التي يمكن تمريرها إلى free()
[shadow] -b <bin index> : عرض العناوين التي سيتم تحريرها إلى
[shadow] tcache bin الخاص بـ <bin index>
[shadow] -m <name> : البحث فقط في هذه الوحدة النمطية المحددة
[shadow] أوامر عامة:
[shadow] jeversion : إخراج رقم الإصدار
[shadow] jehelp : رسالة المساعدة هذه
إذا لم ترَ رسالة المساعدة أعلاه، فقد أخطأت في شيء ما ;)
ملاحظة: هذه الميزة خاصة بـ Firefox/Windows فقط في الوقت الحالي!
يسمح لك الأمر symbol بالبحث عن فئات (وهياكل) SpiderMonkey و DOM ذات أحجام محددة. هذا مفيد عندما تحاول استغلال ثغرات use-after-free، أو عندما تريد وضع كائنات ضحية مثيرة للاهتمام لكتابتها أو إفسادها.
في الدليل الرئيسي لـ shadow، يمكنك العثور على أداتين صغيرتين لتحليل PDB، وهما symhex.py و pdbdy.py (الأسرع). قم بتشغيلهما على "xul.pdb" لإنشاء ملف pickle بلغة Python الذي يتوقعه shadow في دليل "pdb" (باسم "pdb/xul-VERSION.pdb.pkl"). قبل تشغيلهما، تأكد من تسجيل "msdia90.dll"؛ على سبيل المثال على Windows 8.1 x86-64 يمكنك القيام بذلك باستخدام:
regsvr32 "c:\Program Files (x86)\Common Files\Microsoft Shared\VC\msdia90.dll"
من موجه المسؤول. تحتاج أيضًا إلى وحدة Python "comtypes"؛ قم بتثبيت pip ثم قم بـ pip install comtypes.
من أجل الحصول على "xul.pdb" يجب عليك إعداد WinDBG مع [خادم الرموز الخاص بـ Mozilla] (https://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server).
تمت إعادة تصميم unmask_jemalloc في البداية بتصميم معياري لدعم جميع أدوات تصحيح الأخطاء والمنصات الثلاثة الرئيسية (WinDBG و GDB و LLDB). تمت إعادة تسمية الأداة إلى shadow عند إضافة ميزات خاصة بـ Firefox/Windows/WinDBG فقط.
فيما يلي نظرة عامة على التصميم الجديد (اقرأ الأسهم كـ "استيرادات"). الهدف، بوضوح، هو جعل كل الكود المعتمد على مصحح الأخطاء في وحدات *_driver و *_engine.
---------------------------------------------------------------------------------------
الواجهة الأمامية المطلوبة لتصحيح الأخطاء (الغراء)
+------------+ +-------------+ +-------------+
| gdb_driver | | lldb_driver | | pykd_driver |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
------+-------------------+-------------------+----------------------------------------
| | |
| +--------+ |
+------------------------ | +-----+ المنطق الأساسي (مستقل عن مصحح الأخطاء)
| | |
| | |
+-----------------+
+------+ | |
| |---------------> | shadow |<-----+
| util | +------> | | |
| | | +-----------------+ |
+------+ | ^ ^ ^ ^ |
| | | | | | | | | +--------+
| | | +-----+----------+ | +----+--------+---| symbol |
| | | | | | | | +--------+
+-+ | | | +----------+ | | | +---------+
| | | | | jemalloc | | +--------+---| nursery |
| | | | +----------+ | | +---------+
| | | | ^ ^ ^ | |
| | | | | | | | |
| | | | | | +------+--------+ |
| | | | | | | | |
| | +---+---+----+----------+--------+-----+ |
| | | | | | | | |
| +-----+---+----+----+ | | | |
| | | | | | | | |
--+---------+---+----+----+-----+--------+-----+----+----------------------------------
| | | | | | | | |
| | | | | | | | | واجهات برمجة التطبيقات المعتمدة على مصحح الأخطاء
| | | | | | | | |
| | | | | | | | |
| +------------+ | +-------------+ | +-------------+
+->| gdb_engine | +--| lldb_engine | +--| pykd_engine |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
+---+ +---------+ +---------------+
| | |
| | |
-------+-------------+-------------+---------------------------------------------------
| | |
| | | الواجهة الخلفية المقدمة من مصحح الأخطاء
| | |
| | |
+-----+ +------+ +------+
| gdb | | lldb | | pykd |
+-----+ +------+ +------+
---------------------------------------------------------------------------------------