
فيزينغ عالي الأداء باستخدام الترجمات الثنائية من riscv إلى x86 وتقنيات فيزينغ حديثة
تاريخ البدء: ديسمبر 2021
هذه أداة فحص (fuzzer) رمادية الصندوق (greybox) قائمة على المحاكاة وموجهة بالتغطية، وتستفيد من مترجم مخصص في الوقت المناسب (Just-In-Time) لتحقيق أداء قريب من الأداء الأصلي. تعمل عن طريق رفع ملفات RISC-V elf الثنائية إلى تمثيل وسيط قبل ترجمتها في الوقت المناسب (JIT) إلى x86 أثناء التنفيذ. أثناء الترجمة في الوقت المناسب، يتم تزويد الكود بأدوات القياس (instrumentation) لتمكين تحسينات الفحص مثل تتبع التغطية، وasan، وcmpcov، أو الفحص القائم على اللقطات (snapshots).

الهدف من هذا المشروع هو إبراز فوائد استخدام بيئة محاكاة للفحص. توجد العديد من أدوات الفحص السابقة القائمة على المحاكاة، لكنها جميعًا تستخدم بشكل شبه حصري محرك محاكاة qemu للمحاكاة الأساسية. على الرغم من أن هذا المحرك يحتوي على مترجم في الوقت المناسب ناضج إلى حد ما وينشئ كودًا جيدًا جدًا، إلا أنه غير مصمم للفحص. أثناء الفحص، نعتزم تشغيل نفس العملية آلاف المرات في الثانية. وهذا يتيح مجالًا لتحسينات متخصصة لا يستفيد منها qemu بشكل كبير، مثل إعادة استخدام نفس مساحة الذاكرة لكل تشغيل للعملية وإعادة تعيين كمية محدودة فقط من الذاكرة عبر آليات البتات المتسخة.
من نواحٍ عديدة، هذا المشروع هو أقرب إلى إثبات مفهوم (proof-of-concept) أردت العمل عليه لتعلم دواخل المترجمات (compiler internals)، وللحصول على بيئة لعب قائمة على المحاكاة لتجربة تقنيات فحص مختلفة مثل مقاييس التغطية المختلفة، وجدولة البذور، والفحص القائم على اللقطات. ومع المزيد من تحسينات JIT، والأهم من ذلك توسيعه ليشمل معماريات أكثر شيوعًا مثل mips أو arm، يمكن بالتأكيد استخدامه بكفاءة لفحص الكود مغلق المصدر الذي لا يمكن ببساطة تزويده بأدوات القياس عبر إعادة الترجمة.
بالنظر إلى الاختبارات التي أجريتها حتى الآن، فإن sfuzz يتمتع بتكلفة إضافية (overhead) أقل بكثير من العديد من أدوات الفحص الشائعة الأخرى، مما يؤدي إلى أداء سريع جدًا، خاصةً لحالات الفحص الصغيرة.
مزيد من التفاصيل حول الميزات/الخيارات المعتمدة في أداة الفحص هذه مذكورة في منشور المدونة المرفق (https://seal9055.com/blog/fuzzing/sfuzz) وملفات التوثيق المدرجة أدناه:
أداة الفحص هذه مكتوبة بالكامل بلغة rust، لذلك بعد استنساخ المستودع، شغّل فقط cargo build --release للترجمة.
نظرًا لأن أداة الفحص تدعم حاليًا RISC-V فقط، يجب ترجمة الهدف إلى RISC-V باستخدام سلسلة الأدوات أدناه (أو ما شابهها). بدلًا من ذلك، إذا كان لديك بالفعل ملف RISC-V ثنائي، فسيعمل بشكل مثالي أيضًا.
بمجرد إعداد ذلك، أنشئ مجلّدي الإدخال/الإخراج، وأضف بعض ملفات البذور الأولية إلى مجلد الإدخال، ثم شغّل أداة الفحص.
./sfuzz -i in -o out -- ./test_cases/simple_test @@
يمكن تمرير علامات إضافية عبر خيارات سطر الأوامر لتحديد عدد الخيوط، أو تفعيل الفحص القائم على اللقطات، أو إضافة قاموس إلى المُبدِّل، وما إلى ذلك. يمكن عرض الخيارات الإضافية عن طريق تشغيل sfuzz مع العلم -h.
إذا كنت ترغب في اختبار أداة الفحص ضد بعض الأهداف بدرجات تعقيد متفاوتة، يمكن استخدام progrem_generator الموجود في tools/program_generator لتوليد برامج بدرجات تعقيد متفاوتة تلقائيًا. لاحظ أنك ستحتاج إلى سلسلة أدوات RISC-V لترجمة الهدف بعد ذلك.
يؤدي ذلك إلى إعداد سلسلة أدوات لترجمة ملفات riscv الثنائية التي يمكن تحميلها/استخدامها بواسطة هذا المشروع.
Riscv compiler/tooling:
sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev \
libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev \
libexpat-dev
git clone https://github.com/riscv/riscv-gnu-toolchain && cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --with-arch=rv64i
sudo make
Debugger:
gdb-multiarch
تمثل هذه القائمة مجموعة من الميزات التي أخطط لتنفيذها في المستقبل.