
الفيزينغ باستخدام AFL/QEMU مع محاكاة كاملة للنظام.
جديد: لمن يرغبون في تجربة TriforceAFL و TLSF، أنشأ ريتشارد جونسون ملف Dockerfile يقوم بتثبيت كلاهما (بل ويبني لك نواة Linux أيضًا). وهو متاح هنا https://hub.docker.com/r/moflow/afl-triforce/tags/.
جديد أيضًا: afl-tmin يعمل الآن مع خادم التفرع!
https://github.com/nccgroup/TriforceAFL جيسي هيرتز [email protected] تيم نيوشام [email protected]
هذه نسخة مُرقّعة من AFL تدعم التضمين على مستوى النظام الكامل باستخدام QEMU. تم تحديث QEMU المرفق للسماح بتتبع الفروع عند تشغيل محاكي نظام لمعمارية x86_64. تمت إضافة تعليمات إضافية لبدء خادم التفرع الخاص بـ AFL، وضبط إعدادات التضمين، وتحديد بداية ونهاية حالات الاختبار.
ملاحظة: لم يتم اختبار جميع أدوات AFL مع التغييرات الجديدة. هذه الأدوات خضعت لبعض الاختبارات:
للبناء:
make
للحصول على خريطة تغطية:
echo hello > /tmp/hello
./afl-showmap -o coverage.txt -QQ --
./afl-qemu-system-trace -kernel ../bzImage
-initrd ../initramfs.cpio.gz -m 1G -nographic
-append "console=ttyS0" -aflFile /tmp/hello
cat coverage.txt
للتضمين:
egrep ' (panic|log_store)$' ../mykern/kallsyms ffffffff8108e570 t log_store ffffffff8181064b T panic
mkdir inputs
echo hello > inputs/hello
./afl-fuzz -i inputs -o outputs -QQ --
afl-qemu-system-trace -kernel bzImage -initrd root.cpio.gz
-m 1G -nographic -append "console=ttyS0"
-aflPanicAddr ffffffff8181064b -aflDmesgAddr ffffffff8108e570
-aflFile @@
(ملاحظة: بخلاف استخدام الخيار "-Q"، يجب عليك تحديد سطر الأوامر الكامل لـ afl-qemu-system-trace عند استخدام الخيار "-QQ").
لمزيد من التفاصيل حول كيفية استخدام هذه النسخة المعدلة من AFL، انظر مضمِّن استدعاءات نظام Linux الخاص بنا على https://github.com/nccgroup/TriforceLinuxSyscallFuzzer.
خيارات AFL الجديدة: -QQ - استخدام qemu في محاكاة النظام الكامل بدلاً من وضع المستخدم (-Q)
خيارات QEMU الجديدة: -aflFile - اسم الملف الذي يحتوي على مدخلات المضمِّن -aflPanicAddr - عنوان لموقع انهيار النواة لاكتشاف الانهيار -aflDmesgAddr - عنوان نواة Linux لدالة تسجيل dmesg لاكتشاف التسجيل واعتراض رسائل السجل
تعليمات QEMU الجديدة: 0f 24 - aflCall edi=1 startForkserver(esi=enableTicks) بدء خادم التفرع الخاص بـ AFL. بعد هذه النقطة، سيتم تشغيل كل اختبار في عملية فرعية منفصلة. إذا كانت enableTicks غير صفرية، سيعيد QEMU تمكين مؤقت وحدة المعالجة المركزية بعد تفرع عملية فرعية، وإلا فلن يتم تمكينه. edi=2 getWork(esi=ptr, edx=sz) ملء ptr[0..sz] بحالة الاختبار التالية. يُرجع الحجم الفعلي الممتلئ (<= sz). edi=3 startWork(esi=ptr) إخبار AFL ببدء التتبع. تشير الوسيطة إلى مخزن مؤقت يحتوي على قيمتين 64-بت تحددان عنوان البداية والنهاية للكود المراد تتبعه. التعليمات خارج هذا النطاق لا يتم تتبعها. edi=4 doneWork(esi=exitCode) إخبار AFL بأن حالة الاختبار اكتملت. إذا تم اكتشاف انهيار، سيوقف AFL حالة الاختبار فورًا. وإلا فسيستمر حتى يتم استدعاء doneWork. يُرجع كود الخروج المحدد إلى AFL. (يمكن للكود، لكنه لا يقوم بذلك حاليًا، أن يدمج القيمة 64 عبر عملية OR في جميع أكواد الخروج إذا تم اكتشاف أي سجلات dmesg أثناء حالة الاختبار.)
محرك كتلة QEMU الجديد: -drive filename=privmem: يحتفظ محرك الكتلة هذا بصورة محرك التخزين في ذاكرة نسخ-عند-الكتابة بحيث لا يتم حفظ التغييرات على القرص أبدًا. التغييرات التي يجريها أحد حالات الاختبار معزولة عن حالات الاختبار الأخرى.
كتبه ويصونه ميشال زاليفسكي [email protected]
حقوق النشر 2013، 2014، 2015، 2016 شركة Google Inc. جميع الحقوق محفوظة. صدر بموجب شروط وأحكام رخصة Apache، الإصدار 2.0.
للإصدارات الجديدة والمعلومات الإضافية، تفضل بزيارة: http://lcamtuf.coredump.cx/afl/
لمقارنة الملاحظات مع المستخدمين الآخرين أو الحصول على إشعارات حول الميزات الرئيسية الجديدة، أرسل بريدًا إلى [email protected].
** انظر QuickStartGuide.txt إذا لم يكن لديك وقت لقراءة هذا الملف. **
التضمين هو أحد أقوى الاستراتيجيات وأكثرها إثباتًا لتحديد المشكلات الأمنية في البرمجيات الواقعية؛ وهو المسؤول عن الغالبية العظمى من أخطاء تنفيذ التعليمات البرمجية عن بُعد وتصعيد الامتيازات المكتشفة حتى الآن في البرمجيات الحرجة أمنيًا.
للأسف، التضمين أيضًا ضحل نسبيًا؛ فالطفرات العشوائية العمياء تجعل من غير المرجح جدًا الوصول إلى مسارات كود معينة في الكود المختبر، مما يترك بعض الثغرات الأمنية بعيدة تمامًا عن متناول هذه التقنية.
كانت هناك محاولات عديدة لحل هذه المشكلة. أحد الأساليب المبكرة - التي ابتكرها تافيس أورماندي - هو تقطير المجموعة. تعتمد الطريقة على إشارات التغطية لاختيار مجموعة فرعية من البذور المثيرة للاهتمام من مجموعة ضخمة وعالية الجودة من الملفات المرشحة، ثم تضمينها بالوسائل التقليدية. يعمل هذا النهج بشكل استثنائي، لكنه يتطلب توفر مثل هذه المجموعة بسهولة. بالإضافة إلى ذلك، توفر قياسات تغطية الكتل فهمًا مبسطًا جدًا لحالة البرنامج، وهي أقل فائدة لتوجيه جهود التضمين على المدى الطويل.
أما الأبحاث الأخرى الأكثر تطورًا فقد ركزت على تقنيات مثل تحليل تدفق البرنامج ("التنفيذ الرمزي الملموس")، أو التنفيذ الرمزي، أو التحليل الثابت. كل هذه الطرق واعدة للغاية في البيئات التجريبية، لكنها تميل إلى المعاناة من مشكلات الموثوقية والأداء في الاستخدامات العملية - ولا تقدم حاليًا بديلاً قابلاً للتطبيق عن تقنيات التضمين "الغبية".
American Fuzzy Lop هو مضمِّن يعمل بالقوة الغاشمة، مقترنًا بخوارزمية جينية بسيطة للغاية لكنها صلبة كالصخر، وموجهة بالقياس الآلي. يستخدم شكلاً معدلاً من تغطية الحواف لالتقاط التغييرات الدقيقة والمحلية النطاق في تدفق تحكم البرنامج دون عناء.
لتبسيط الأمور قليلاً، يمكن تلخيص الخوارزمية برمتها على النحو التالي:
تحميل حالات الاختبار الأولية المقدمة من المستخدم في قائمة الانتظار،
أخذ ملف الإدخال التالي من قائمة الانتظار،
محاولة تقليم حالة الاختبار إلى أصغر حجم لا يغير السلوك المُقاس للبرنامج،
طفرات متكررة للملف باستخدام مجموعة متوازنة ومدروسة جيدًا من استراتيجيات التضمين التقليدية،
إذا أسفرت أي من الطفرات المولدة عن انتقال حالة جديد مسجل بواسطة القياس الآلي، أضف المخرج المطفر كإدخال جديد في قائمة الانتظار.
الانتقال إلى 2.
يتم أيضًا استبعاد حالات الاختبار المكتشفة دوريًا للتخلص من تلك التي أصبحت قديمة بسبب اكتشافات أحدث وأعلى تغطية؛ كما تخضع للعديد من خطوات تقليل الجهد الأخرى الموجهة بالقياس الآلي.
كنتيجة جانبية لعملية التضمين، تنشئ الأداة مجموعة صغيرة مكتفية ذاتيًا من حالات الاختبار المثيرة للاهتمام. هذه المجموعة مفيدة للغاية لتغذية أنظمة اختبار أخرى كثيفة العمالة أو الموارد - على سبيل المثال، لاختبار الإجهاد للمتصفحات، أو تطبيقات المكاتب، أو مجموعات الرسوميات، أو الأدوات مغلقة المصدر.
تم اختبار المضمِّن بدقة لتقديم أداء خارج الصندوق متفوق بكثير على التضمين الأعمى أو الأدوات القائمة على التغطية فقط.
عندما يكون الكود المصدري متاحًا، يمكن حقن القياس الآلي بواسطة أداة مصاحبة تعمل كبديل مباشر لـ gcc أو clang في أي عملية بناء قياسية لكود طرف ثالث.
للقياس الآلي تأثير أداء متواضع إلى حد ما؛ وبالاقتران مع التحسينات الأخرى المنفذة بواسطة afl-fuzz، يمكن تضمين معظم البرامج بسرعة مماثلة أو حتى أسرع مما هو ممكن مع الأدوات التقليدية.
قد تختلف الطريقة الصحيحة لإعادة ترجمة البرنامج الهدف اعتمادًا على تفاصيل عملية البناء، لكن النهج شبه العالمي سيكون:
$ CC=/path/to/afl/afl-gcc ./configure $ make clean all
بالنسبة لبرامج C++، ستحتاج أيضًا إلى تعيين CXX=/path/to/afl/afl-g++.
يمكن استخدام أغلفة clang (afl-clang و afl-clang++) بنفس الطريقة؛ قد يختار مستخدمو clang أيضًا الاستفادة من وضع قياس آلي عالي الأداء، كما هو موضح في llvm_mode/README.llvm.