فازینگ (Fuzzing) به یکی از مؤثرترین تکنیکهای خودکار برای کشف آسیبپذیریها و باگهای (bug) نرمافزاری تبدیل شده است. با وجود سالها پژوهش که جنبههای مختلف این حوزه را هدف قرار دادهاند، ارزیابی میزان پیشرفت واقعی فازینگ در گذر زمان همچنان چالشبرانگیز است. در این مقاله، ما یک تحلیل تجربی در مقیاس وسیع از روند پیشرفت فازینگ ارائه میدهیم که بر پایه ++AFL انجام شده است؛ پیشرفتهترین فازری که به صورت مستمر بهبودها و نوآوریهای حاصل از پژوهشهای علمی را در خود جای داده است.
ما با بهرهگیری از مجموعه آزمایشهایی در حدود ۶۴۵٬۰۰۰ ساعت پردازنده (CPU)، به صورت جامع میزان پیشرفت فازینگ را از منظر پوشش کد (Code Coverage) اندازهگیری و تأثیر قابلیتها و مکانیزمهای مختلف را در طول سالهای گذشته ارزیابی کردهایم. نتایج، به طور شگفتآور و غیرمنتظرهای، نشان دهنده رسیدن به یک ثبات نسبی در اکتشاف رفتارهای جدید برنامه است؛ بدین معنا که اگرچه برخی تکنیکها منجر به بهبودهای عملکردی محدود در اجرا شدهاند، اما پیشرفت کلی در فعالسازی مسیرهای اجرایی جدید و دستیابی به پوشش جدید تا حد زیادی متوقف شده است.
به منظور بررسی اینکه آیا مشاهدات ما به LibAFL و Fuzzilli نیز قابل تعمیم است یا خیر، دریافتیم که این الگوی مشاهده شده در هر سه فازر برقرار است. برای درک عمیقتر این وضعیت رکود، مطالعه تجربی خود را با یک پیمایش نظاممند از ۴۰۵ مقاله داوری شده در حوزه فازینگ تکمیل کردیم که بین سالهای ۲۰۱۸ تا ۲۰۲۴ در برترین مجامع علمی امنیت و مهندسی نرمافزار منتشر شدهاند. در این میان، ۶۰ مقاله را شناسایی کردیم که توسعهها یا بهبودهایی را برای AFL++/AFL ارائه کرده بودند. سپس امکان اذغام و یکپارچهسازی (Integration) این دستاوردها را در فازر پایه بررسی و تحلیل کردیم که آیا این قابلیتها در نهایت توسط فازر مبنا پذیرفته و بهکار گرفته شدهاند یا خیر.
بهطور غیرمنتظره، در عمل میزان پذیرش و بهکارگیری این دستاوردهای پژوهشی بسیار محدود مشاهده میشود؛ بهگونهای که عدم بازتولیدپذیری نتایج، وابستگی به پیشنیازها و مؤلفههای خارجی پیچیده، و سودمندی عملی محدود، به عنوان اصلیترین موانع پذیرش شناخته شدند. همچنین، در جریان بررسی و بحث پیرامون نتایج تحلیل با نگهدارندگان ++AFL، دریافتیم که شکاف میان پژوهشهای دانشگاهی و پذیرش در کاربردهای عملی و واقعی بهطور فزایندهای در حال افزایش است. این موضوع بر ضرورت تعریف استانداردهای سختگیرانهتر برای تکرارپذیری یا قابلیت بازتولید نتایج (reproducibility) و همچنین اتخاذ رویکردی واقعبینانهتر در ارزیابی معیارها (benchmarking) برای بهبودهای پیشنهادی در حوزه فازینگ تأکید میکند.
۱. مقدمه (Introduction)
پیشرفت علمی بر پایه بهبود و پالایش مداوم دانش موجود شکل میگیرد. روشهای جدید بر دستاوردهای پیشین بنا میشوند و به نوبه خود امکان توسعه رویکردهای پیشرفتهتر را فراهم میکنند. ارزیابی منظم و دقیق پیشرفت علمی برای تأیید میزان واقعی این پیشرفتها امری ضروری است؛ بهگونهای که بتوان نوآوریهایی را که منجر به بهبودهای اساسی میشوند از آنهایی که صرفاً اصلاحات تدریجی و جزئی ارائه میدهند، تفکیک کرد [1, 2, 3, 4]. این اصل بهطور کلی در تمام حوزههای علوم کامپیوتر و به ویژه در امنیت رایانه (computer security) نیز کاربرد دارد [5].
ارزیابی تجربی دقیق در تست نرمافزار، برای شناسایی امیدوارکنندهترین ایدهها در این زمینه که به سرعت در حال تکامل میباشد، بسیار مهم است. در سالهای اخیر، فازینگ به عنوان یکی از مؤثرترین تکنیکهای تست برای یافتن آسیبپذیریهای نرمافزاری ظهور کرده است. فازینگها با تولید خودکار ورودیهای (نیمه)تصادفی برای بررسی مسیرهای اجرا، هزاران باگ حیاتی را در سیستمهای پرکاربرد کشف کردهاند [6، 7، 8]. تأثیر فازینگ هم در دانشگاه و هم در صنعت مشهود است، به طوری که صدها مقاله تحقیقاتی، پذیرش توسط شرکتهایی مانند گوگل و مایکروسافت و ابتکارات بزرگی مانند OSS-Fuzz [8] منجر به کشف دهها هزار آسیبپذیری در دنیای واقعی شده است.
پژوهش در حوزه فازینگ گسترده است و همچنان در حال رشد میباشد [6, 7, 9]؛ بهطوریکه بهبودهای پیشنهادی در این زمینه طیفی از تکنیکهای هوشمندتر ابزارگذاری (instrumentation) و استراتژیهای جدید جهش ورودی (input mutation) تا سازوکارهای پیشرفته زمانبندی (scheduling) را در بر میگیرد. با وجود این تنوع، تمامی این رویکردها یک هدف مشترک را دنبال میکنند و آن هم شناسایی مؤثر و قابلاطمینان خطاهای نرمافزاری است.
اما این پرسش همچنان مطرح است که آیا این نوآوریها واقعاً موجب بهبود معنادار کارایی فازینگ شدهاند، یا آخرین جهش بزرگ در این حوزه همان معرفی فازینگ هدایت شده با پوشش کد (coverage-guided fuzzing) با AFL در سال ۲۰۱۳ بوده است [10]؟ پاسخ به این سؤال چالشبرانگیز است و نیازمند یک ارزیابی تجربی جامع و سیستماتیک میباشد.
در این مقاله، ما به صورت نظاممند (systematic) پیشرفتهای پژوهشی در حوزه فازینگ طی هفت سال گذشته را مورد بررسی قرار میدهیم. ما یک مطالعه تجربی در مقیاس بزرگ انجام دادهایم تا تکامل ++AFL را به عنوان پیشرفتهترین فازر عمومی و همه منظوره (general-purpose fuzzer) ارزیابی کنیم و به طور جامع اثر بهبودهای مختلف را در طول زمان تحلیل نماییم.
برای تکمیل این تصویر و رسیدن به یک نتیجهگیری کلیتر در حوزه فازینگ، همچنین دو فازر پرکاربرد دیگر را نیز مورد آزمایش قرار دادیم: LibAFL به عنوان جایگزینی برای ++AFL، و Fuzzilli که به عنوان استاندارد صنعتی بالفعل و غیررسمی (de facto) برای فازینگ موتورهای جاوااسکریپت (JavaScript) در صنعت شناخته میشود.
به منظور انجام این مطالعه، یک معیار ثابت برای اندازهگیری پیشرفت ضروری است. یک شاخص استاندارد و پذیرفته شده برای اثربخشی یک فازر، میزان پوشش کدی است که به دست میآورد. پوشش به ویژه به سه دلیل مرتبط است: اول، یک فازر نمیتواند خطا را در کدهایی که هرگز مورد کاوش و اجرا قرار نگرفتهاند شناسایی کند؛ بنابراین، پوشش کد بالاتر با احتمال بیشتر کشف باگها همبستگی دارد [11].
دوم، پوشش کد بهسادگی قابل اندازهگیری است و به یک معیار استاندارد در پژوهشهای فازینگ تبدیل شده است: یکی از مطالعات اخیر نشان داده است که ۷۷٪ از مقالات فعلی حوزه فازینگ هنگام ارزیابی ابزارهای خود، نوعی از پوشش کد را گزارش میکنند [9]. در نهایت، دستورالعملهای تثبیت شده برای ارزیابی فازینگ توصیه میکنند که پوشش کد (به صورت یالهای منحصر به فرد یا بلوکهای پایه اجرا شده) بهعنوان یک معیار ثانویه پایدار در کنار نتایج مستقیم کشف آسیبپذیریها مورد استفاده قرار گیرد [9, 12, 13].
از این رو، ما پوشش کد را به عنوان معیار اصلی خود در نظر میگیریم. همچنین یک آزمایش بر روی قابلیت کشف باگ انجام دادیم، اما دریافتیم که این معیار برای اندازهگیری پیشرفتهای کوچک و تدریجی بین نسخههای مختلف یک فازر درشتدانه (coarse-grained). با در نظر گرفتن این زمینه، در این مقاله به بررسی پرسش پژوهشی زیر میپردازیم:
چگونه فازینگ در سالهای گذشته پیشرفت کرده است، و آیا فازرها اکنون میتوانند پوشش کد قابلتوجهی بیشتری را به دست آورند؟
ما برای پاسخ به این پرسش، به صورت نظاممند سیر تکامل زمانی ++AFL را ارزیابی میکنیم. ++AFL یک فازر عمومی و پرکاربرد است که به طور طبیعی به عنوان معیاری برای سنجش پیشرفت در حوزه فازینگ عمل میکند. این ابزار که تکاملیافتهی AFL میباشد، به طور خاص برای یکپارچهسازی «گامهای تدریجی پژوهش در فازینگ» توسعه یافته و به دلیل ادغام تعداد زیادی از تکنیکهای پیشنهادی در پژوهشهای دانشگاهی شناخته میشود [14].
در واقع، بسیاری از ابزارهای فازینگ دانشگاهی خود بر پایه یا به عنوان توسعهای از ++AFL ساخته شدهاند (برای مثال [15, 16, 17, 18, 19, 20, 21]). علاوه بر این، ++AFL (و نسخه پیشین آن یعنی AFL) بهطور گسترده به عنوان نقطه مرجع (reference point) برای ارزیابی روشهای جدید فازینگ استفاده میشود. چنانچه پژوهشهای فازینگ واقعاً موجب پیشرفت وضعیت فعلی (state of the art) شده باشند، این پیشرفت باید در تکامل ++AFL نمود پیدا کند. بنابراین، بررسی روند توسعه آن میتواند معیاری برای ردگیری مسیر پیشرفت در پژوهشهای فازینگ باشد.
به جای آزمایش تمام نسخههای منتشر شده، ما به دقت ۱۰ نسخه نماینده از ++AFL را انتخاب کردیم که نقاط عطف مهم را پوشش میدهند (مانند تغییرات عمده نسخه یا افزودن قابلیتهای کلیدی). برای اطمینان از معنادار و قابل تعمیم بودن نتایج، این نسخهها را روی ۱۵پروژه نرمافزاری واقعی با حوزههای کاربردی و انواع ورودیهای متنوع مورد آزمایش قرار دادیم.
یکی از چالشهای اصلی در ارزیابی بلندمدت فازرها، تکامل ابزارگذاری (instrumentation) و رفتار کامپایلرها است. به منظور جداسازی تأثیرات خود ++AFL، هر نسخه را هم با جدیدترین کامپایلر موجود و هم با کامپایلری که در زمان انتشار آن نسخه در دسترس بوده است مورد آزمایش قرار دادیم. برای تضمین مقایسهای منصفانه و سازگار، تمام آزمایشها را در یک محیط کنترل و کانتینری شده (containerized) روی سختافزار یکسان انجام دادیم و هر آزمایش را ۱۰ بار تکرار کردیم.
بر اساس بیش از ۶۴۵٬۰۰۰ ساعت پردازش CPU (معادل ۷۳٫۶ سال CPU)، ما به دقت بررسی کردیم که چگونه پیکربندیها و قابلیتهای مختلف بر توانایی ++AFL در کاوش کد تأثیر میگذارند. نتایج آزمایشات حاکی از آن است که برخی قابلیتهای کلیدی مانند CmpLog و dict2file به طور قابلتوجهی عملکرد (از نظر پوشش کد) را بهبود میبخشند. با این حال، این قابلیتها سالها پیش اضافه شدهاند و مشاهده میکنیم که از آن زمان به بعد، روند بهبود تا حد زیادی متوقف شده است. یک نمونه تصویری از این روند برای هدف SQLite در شکل ۱ نشان داده شده است: پس از افزایش قابل توجه در اوایل سال ۲۰۲۱، پیشرفتها تا حد زیادی متوقف شدهاند. با انجام آزمایشهای مشابه روی LibAFL و Fuzzilli نیز دریافتیم که عملکرد آنها از نظر پوشش کد دچار رکود (plateau) شده است؛ نتیجهای که با مشاهدات ما در مورد ++AFL کاملاً همراستا است.
به منظور درک دلایل احتمالی توقف پیشرفت، ما یک تحلیل پژوهشی از تمامی ۴۰۵ مقاله فازینگ منتشرشده بین سالهای ۲۰۱۸ تا ۲۰۲۴ در برترین مجامع علمی امنیت رایانه و مهندسی نرمافزار انجام دادیم. از این میان، ۶۰ مقاله مبتنی بر AFL یا ++AFL بودند و ۴۴ مقاله نیز کد منبع خود را به صورت عمومی در دسترس قرار داده بودند.
ما این مقالات را بر اساس امکانسنجی ادغام و یکپارچهسازی (integration feasibility) در مبانی مربوطه ارزیابی کردیم و همچنین بررسی نمودیم که کدامیک واقعاً مورد پذیرش و استفاده قرار گرفتهاند. با ترکیب این یافتهها با بازخوردهایی که از طریق بحث با نگهدارندگان ++AFL دریافت کردیم، نتایج تحلیل ما نشان میدهد که تنها بخش کوچکی از تکنیکها واقعاً در ++AFL ادغام شدهاند. ما چندین دلیل برای این وضعیت شناسایی کردیم، از جمله پیادهسازیهای بیش از حد پیچیده، نتایج غیرقابل تکرار و بازتولید و بهبودهایی که فاقد اهمیت آماری هستند. این عوامل، فرآیند ادغام این روشها در ++AFL را با مشکل مواجه میکنند.
بر اساس این مطالعه کلان (meta-study)، ما سه درس کلیدی برای جامعه پژوهشی استخراج میکنیم: برای ایجاد پیشرفت معنادار، پژوهش باید نه تنها بر نوآوری، بلکه بر قابلیت ادغام و یکپارچهسازی (integrability)، تکرارپذیری یا قابلیت بازتولید (reproducibility)و کاربردپذیری عملی (practical relevance) نیز تمرکز داشته باشد.
مشارکتها (Contributions). در مجموع، مشارکتهای کلیدی ما عبارتاند از:
- ما یک ارزیابی نظاممند و جامع از ++AFL طراحی میکنیم؛ یکی از پرکاربردترین فازرهای عمومی که مجموعهای از کارهای موفق پژوهشی در حوزه فازینگ را در خود ادغام کرده است. ما بررسی میکنیم که این ابزار در طی هفت سال گذشته چگونه از نظر ابزارگذاری (instrumentation)، استراتژیهای جهش (mutation strategies) و سازوکارهای زمانبندی (scheduling mechanisms) تکامل یافته است.
- ما یک مطالعه تجربی گسترده انجام دادیم که بیش از ۶۴۵٬۰۰۰ ساعت پردازشی CPU را در بر میگیرد و چندین هدف مختلف را پوشش میدهد. یافته اصلی ما این است که اثربخشی ++AFL و سایر فازرها، علیرغم وجود بهبودهای متعدد در ادبیات علمی، تا حد زیادی به مرحله سکون و رکود (plateau) رسیده است.
- ما یک مطالعه کلان (meta-study) بر روی فازینگ انجام دادیم که شامل تحلیل ۴۰۵ مقاله داوریشده است و بهصورت نظاممند میزان قابلیت ادغام و یکپارچهسازی (integrability) آنها در ++AFL را ارزیابی میکند. نتایج حاکی از آن است که تنها بخش کوچکی از تکنیکهای پیشنهادی واقعاً مورد استفاده و پذیرش قرار گرفتهاند؛ که این امر اغلب به دلیل عدم تعمیمپذیری کافی، سودمندی عملی محدود، یا پیچیدگی در یکپارچهسازی آنهاست.
ما دستاوردها و خروجیهای تولید شده پژوهشی (research artifacts) خود را در اینجا بارگذاری کردهایم (https://anonymous.4open.science/r/aflpp-archaelogy-830B).
ساختار رساله. این رساله شامل پژوهشهایی است که زیربنای آن را تشکیل میدهند:
- چالشهای حل نشده حوزه فازینگ: دامها، نقاط کور و درسهای آموخته شده از دنیای واقعی
- نوآوری یافت نشد: بررسی سایهسازی ورودی در فازینگ از طریق راهاندازی مجدد فازر تطبیقی
- امنیت پهپادها و پرونده اسرارآمیز DroneID شرکت DJI
۲. تکامل ++AFL
فازینگ همچنان یک حوزه پژوهشی فعال است که زمان و منابع قابلتوجهی از سوی دانشگاه و صنعت در آن سرمایهگذاری میشود. یکی از پرکاربردترین فازرهای مدرن، ++AFL میباشد که به عنوان جانشین AFL معرفی شده است. ++AFL امروزه به عنوان استاندارد بالفعل و غیررسمی (de facto standard) در فازینگ متنباز شناخته میشود و به طور گسترده به عنوان مبنای ارزیابی فازرهای عمومی مورد استفاده قرار میگیرد. این ابزار بر رویکرد فازینگ هدایت شده با پوشش کد (coverage-guided fuzzing) AFL بنا شده و از توسعه جامعهمحور (community-driven development) بهره میبرد.
هرگاه تکنیکها یا بهبودهای جدیدی از پژوهشهای دانشگاهی نشان دهند که نسبت به نسخه فعلی ++AFL عملکرد بهتری دارند، این قابلیتها اغلب برای به روز نگه داشتن آن به ++AFL افزوده میشوند [22, 23, 24]. از زمان آغاز توسعه ++AFL در سال ۲۰۱۹، قابلیتهای متعددی در آن ادغام شدهاند؛ از جمله بهبود پشتیبانی از ابزارگذاری (instrumentation)، راهبردهای مؤثرتر زمانبندی (scheduling) و تکنیکهای مختلف جهش ورودی (mutation). در ادامه، تاریخچه توسعه ++AFL را تشریح کرده و ویژگیهای کلیدی و تغییرات در تنظیمات پیشفرض آن را برجسته میکنیم.
۲.۱ ویژگیهای فازینگ در ++AFL
تنظیمات، زمانبندها (schedulers) و عملیات جهش (mutations) مختلفی وجود دارند که میتوانند برای تنظیم دقیق (fine-tuning) جنبههای گوناگون فازر به کار روند و به طور بالقوه بر روند فازینگ تأثیر بگذارند. برخی تنظیمات به صورت پیشفرض تنظیم شدهاند، اما پیشفرضها ممکن است در نسخههای مختلف تغییر کنند. ویژگیهای زیر به طور مستقیم بر فرآیند فازینگ اثر میگذارند و کاربر میتواند آنها را کنترل کند.
قطعی در برابر غیرقطعی (Deterministic vs Havoc). ابزار ++AFL در فرآیند فازینگ، انواع مختلفی از جهشها (mutations) را روی نمونههای آزمایشی اعمال میکند که به طور کلی به دو مرحله قطعی (deterministic) و غیرقطعی (non-deterministic) تقسیم میشوند. فازر در مرحله قطعی (deterministic stage)، به صورت سیستماتیک و نظاممند مجموعهای از جهشهای از پیش تعریف شده از جمله وارونسازی بیتها (bit flips)، تبادل بایتها (byte swaps)، جهشهای حسابی (arithmetic mutations) و تزریق مقادیر ویژه (inserting special values) را اعمال میکند این اصلاحات کنترل شده تضمین میکنند که حالات مرزی (edge cases – سناریوهای خاص و کمرخداد) مشترک به طور جامع مورد کاوش و بررسی قرار گیرند. در مقابل، مرحله غیرقطعی به طور متوالی و پشت سرهم چندین جهش تصادفی را به همان مورد آزمایش اعمال میکند، از جمله درج بایت (byte insertion)، حذف (deletion)، جایگزینی بلوک (block replacement) و پیوند از سایر ورودیها (input splicing). این جهشهای پیشرفتهتر به فازر اجازه میدهند تا مسیرهای اجرایی پیچیده و غیربدیهی را که روشهای قطعی ممکن است از دست بدهند، بررسی کند. در نهایت، مرحلهی پیوند، دو ورودی را ادغام میکند و مرحلهی غیرقطعی (havoc) را به ورودی ادغام شده اعمال میکند. طی سالهای اخیر، تنظیمات پیشفرض این مراحل بنا به شرایط و اهداف خاص مانند ادغام جهشدهندههای (mutators) به روز شده، تغییر کردهاند. اثربخشی جهشهای قطعی (deterministic) و غیر قطعی (Havoc) میتواند به طور قابل توجهی متفاوت باشد. فازینگ قطعی اغلب چندین روز زمان میبرد، زیرا ++AFL تمام جهشها را به صورت جامع و کامل روی هر ورودی اعمال میکند. در مقابل، فازینگ غیرقطعی امکان کاوش سریعتر فضای حالت را فراهم میکند و معمولاً در بازه زمانی حدود ۲۴ ساعت به مرحله اشباع پوشش (coverage saturation) میرسد. از این رو، در پژوهشهای علمی اغلب فازینگ قطعی نادیده گرفته میشود، زیرا آزمایشها معمولاً با هدف حداکثرسازی پوشش در بازههای زمانی محدود انجام میشوند. در نسخه 4.10c، مرحله قطعی به طور کامل بازنویسی (rewritten) شده است [25] که این موضوع مقایسه مستقیم آن با نسخه اولیه را دشوار میسازد. ما به منظور خوانایی بهتر، به هر دو نوع صرفاً به عنوان مرحله قطعی (deterministic stage) اشاره میکنیم.
زمانبندهای توان (Power Schedules). در ++AFL، زمانبندهای توان تعیین میکنند که فازر چه مقدار «انرژی» (energy) به هر بذر ورودی (seed) اختصاص دهد تا از روی آن ورودی، موارد آزمون (Test Case) جدید تولید کند. این انرژی با استفاده از الگوریتمهای مختلف و همراه با امتیاز عملکرد (performance score) هر مورد آزمون محاسبه میشود. دو زمانبند یا برنامه مهم در این زمینه Explore (کاوش) و Fast (سریع) هستند که ابتدا توسط Falko Böhme و همکارانش پیشنهاد شدند [22] و بعدها ابتدا در AFL و سپس در ++AFL ادغام شدند. در نسخه اولیه AFL++ (2.52c)، زمانبند پیشفرض Explore بود؛ این روش به تمامی بذرها (seed) مقدار انرژی کم اما ثابت اختصاص میدهد و در نتیجه، کاوشی متوازن در کل فضای ورودیها ایجاد میکند. در مقابل، زمانبند Fast، انرژی را به صورت معکوس با فراوانی مسیرهای اجرا شده توسط بذر تخصیص میدهد: به این معنا که بذرهایی که مسیرهای کمترتکرارشونده را فعال میکنند، انرژی بیشتری دریافت میکنند و در نتیجه جهشهای بیشتری از روی آنها تولید میشود. این رویکرد، فازر را به سمت کاوش مسیرهای کمتر اجرا شده سوق میدهد و احتمال کشف رفتارهای جدید برنامه را افزایش میدهد [14]. در طول زمان، تنظیم پیشفرض زمانبند توان (power schedule) بر اساس یافتههای تجربی جدید و رفع باگها تغییر کرده است. از نسخه 3.0c، زمانبند پیشفرض از Explore به Fast تغییر داده شد؛ با این حال، این تغییر بعدها در نسخه 4.10c مجدداً به حالت قبل بازگشت. کاربران همچنان میتوانند از طریق پارامتر خط فرمان، زمانبند توان موردنظر خود را به صورت دستی انتخاب کنند.
CmpLog .CmpLog یک ویژگی ابزارگذاری (instrumentation) و فازینگ است که در نسخه 2.61c به ++AFL اضافه شد و هدف آن افزایش توانایی فازر در برخورد با مقایسههای ورودی پیچیده (complex input comparisons) با ثبت عملوندهای (operands) مورد استفاده در این مقایسهها در حافظه مشترک (shared memory) است. این مکانیزم تا حدی از Redqueen [24] الهام گرفته است؛ رویکردی که بر تبدیل ورودی به وضعیت (input-to-state transformation) تمرکز دارد تا بتواند محدودیتهایی مانند بایتهای جادویی (magic bytes) کدگذاری شده (Hardcoded) و موانع مشابه در باینریهای هدف را دور بزند. ++AFL با استفاده از عملوندهای ثبت شده در مقایسهها، میتواند جهشهای هدفمند (targeted mutations) انجام دهد (مانند تزریق مستقیم این مقادیر به ورودی هدف). برای استفاده از CmpLog، لازم است دو نسخه از برنامه هدف ساخته شود: یکی با ابزارگذاری استاندارد ++AFL و دیگری با فعالسازی ابزارگذاری مختص CmpLog [14, 26].
Dict2File. قابلیت dict2file در نسخه 3.0c ابزار ++AFL اضافه شد و هدف آن خودکارسازی استخراج توکنهای جهش (mutation tokens)مفید است. این ویژگی از یک LLVM pass استفاده میکند که پارامترهای مقایسه رشتهای ثابت (constant string comparison parameters) را از کد منبع برنامه هدف استخراج میکند. سپس یک فایل دیکشنری به صورت خودکار تولید میشود که میتواند در زمان اجرا به فازر داده شود تا این مقادیر در فرآیند جهش ورودی (mutation) مورد استفاده قرار گیرند [26].
MOpt .MOpt کوتاه شده عبارت «زمانبندی جهش بهینهسازی شده» (Optimized Mutation Scheduling)، یک بهبود ادغام شده در ++AFL است که با هدف افزایش کارایی فازینگ از طریق بهینهسازی احتمال انتخاب عملگرهای جهش (mutation operators) طراحی شده است. این روش نخستینبار توسط Yunqian Lyu و همکارانش پیشنهاد شد [23] و از یک نسخه سفارشیسازی شده از الگوریتم بهینهسازی ازدحام ذرات (Particle Swarm Optimization) بهره میبرد تا استراتژیهای جهش را به صورت پویا و بر اساس اثربخشی آنها در طول فرآیند فازینگ تنظیم کند. در پیادهسازی AFL++، MOpt به دو مرحله تقسیم میشود: (۱) مرحله ارزیابی اولیه و مقدماتی (Pilot stage) در این مرحله عملگرهای جهش ارزیابی میشوند و احتمالات بر اساس میزان اثربخشی آنها، اختصاص داده خواهد شد. (۲) و یک مرحله کد (Code stage) که جهشها را بر اساس احتمالات حاصل از مرحله قبل تولید میکند. نخستین نسخه ++AFL که از mOpt پشتیبانی میکند، نسخه 2.53c است.
۲.۲ ویژگیهای ابزارگذاری (Instrumentation) در ++AFL
فازرهای مدرن هدایت شده با پوشش کد (coverage-guided) معمولاً به ابزارگذاری مبتنی بر کد منبع (source-based instrumentation) از طریق گذرهای LLVM (LLVM passes) متکی هستند؛ این گذرها اطلاعات پوشش را به برنامه اضافه میکنند تا فازر بتواند جریان اجرای برنامه را رهگیری کند. ++AFL شامل گذرهای مختلف LLVM و در نتیجه گزینههای متنوع ابزارگذاری است. این گزینهها میتوانند با تقسیم محدودیتهای پیچیده (complex constraints)، ارائه بازخورد اضافی (additional feedback) یا کاهش احتمال تصادمها (collisions) به بهبود فرآیند فازینگ کمک کنند. علاوه بر این، ++AFL از حالت موسوم به حالت ماندگار (persistent mode) نیز پشتیبانی میکند؛ حالتی که در آن تعداد فورک (fork) شدنهای برنامه هدف کاهش مییابد و در نتیجه موجب افزایش قابل توجه کارایی (performance) میشود [14, 27]. ++AFL برای مواردی که کد منبع در دسترس نیست، حالت QEMU (صرفا باینری – binary-only mode) و همچنین حالت مبتنی بر اسنپشات (snapshot) بر پایه Nyx را ارائه میدهد [26, 28]. در نهایت، قابلیتهای ابزارگذاری موجود به نسخههای ++AFL و کامپایلر Clang وابسته هستند.
CompCov .CompCov یا LAF-Intel قابلیتی است که از نخستین نسخه ++AFL در دسترس بوده و با استفاده از گذرهای LLVM (LLVM passes) پیادهسازی شده است. این ویژگی توانایی فازر را در برخورد با شرطهای مقایسهای پیچیده (complex conditional statements) در برنامه هدف افزایش میدهد. CompCov این کار را با تبدیل مقایسههای پیچیده به مقایسههای سادهتر در زمان کامپایل انجام میدهد. برای مثال، مقایسههای چندبایتی (multi-byte comparisons) به چندین مقایسه تکبایتی (single-byte comparisons) شکسته میشوند؛ در نتیجه فازر میتواند این محدودیتها را به صورت مرحلهای و متوالی پشت سر بگذارد [14].
ابزارگذاری کلاسیک AFL (AFL Classic Instrumentation). ابزارگذاری کلاسیک از AFL اولیه به ++AFL منتقل شده است و یک مکانیزم سبک برای ردگیری پوشش کد (coverage tracking) محسوب میشود. در این روش، در زمان کامپایل به هر بلوک پایه (basic block) یک شناسه شبهتصادفی (pseudo-random ID) اختصاص داده میشود. سپس در زمان اجرا، با انجام عمل XOR بین شناسه بلوک پایه فعلی و شناسه بلوک پایه قبلی، یک شناسه یال (edge ID) محاسبه میشود. این شناسه به عنوان اندیس برای بهروزرسانی بیتمپ پوشش کد (coverage bitmap) مورد استفاده قرار میگیرد. اگرچه این رویکرد به دلیل سادگی و سربار اجرایی پایین (low runtime overhead) بسیار کارآمد میباشد، اما استفاده از اندیسهای مبتنی بر شناسههای شبهتصادفی، به ویژه در اهداف بزرگ با تعداد زیاد بلوکهای پایه، میتواند منجر به تصادم (collision) شود [30]. این تصادمها ممکن است موجب شوند که پوشش جدید (novel coverage) توسط فازر شناسایی نگردد.
CTX .CTX یا پوشش شاخههای حساس به زمینه (Context-Sensitive Branch Coverage)، یک تکنیک پیشرفته ابزارگذاری در ++AFL است که مکانیزم سنتی پوشش یال (edge coverage) در ابزارگذاری کلاسیک را گسترش میدهد. در این روش، علاوه بر یالهای اجرایی، زمینه فراخوانی (calling context) هر تابع نیز در اطلاعات پوشش لحاظ میشود؛ یعنی اطلاعات پوشش مربوط به یک تابع، بر اساس تابعی که آن را فراخوانی کرده (caller) از یکدیگر متمایز میشوند. در نتیجه، فازر میتواند بین فراخوانیهای یکسان از یک تابع که از نقاط مختلف برنامه انجام شدهاند تمایز قائل شود، حتی اگر مسیر اجرایی داخل تابع مشابه باشد [26].
PCGuard بومی LLVM و AFL++ PCGuard. ابزار ++AFL مکانیزم ابزارگذاری trace-pc-guard را که بر پایه LLVM SanitizerCoverage توسعه یافته است، از AFL اولیه به ارث میبرد [31]. این روش نسبت به ابزارگذاری کلاسیک AFL دقت بالاتری دارد، زیرا با شکستن یالهای بحرانی (critical edges) و افزودن بلوکهای ساختگی ابزارگذاری شده (instrumented dummy blocks)، پوشش دقیقتری از جریان کنترل برنامه فراهم میکند. با این حال، این روش همچنان از شناسههای تصادفی (random IDs) استفاده میکند؛ بنابراین احتمال بروز تصادم (collision) همچنان وجود دارد. در نسخه 2.66c از ++AFL، یک پیادهسازی بدون تصادم (collision-free) از PCGuard مبتنی بر LLVM اضافه شده است که در آن شناسههای تصادفی با یک شمارنده سراسری (global counter) جایگزین شدهاند.
۳. طراحی و راهاندازی آزمایش
ما مجموعه جامعی از آزمایشها را طراحی کردیم تا تکامل ++AFL را به صورت نظاممند ارزیابی کنیم. به منظور دستیابی به نتایج معنادار با هزینه محاسباتی قابلقبول، لازم است به پرسشهای زیر پاسخ داده شود:
۱. کدام نسخههای ++AFL باید مورد ارزیابی قرار گیرند؟
۲. کدام اهداف (targets) میبایست انتخاب شوند؟
۳. کدام ویژگیها باید تحلیل گردند؟
۴. کدام حالتهای ابزارگذاری (instrumentation modes) باید بررسی شوند؟
۵. هدف چگونه میبایست ابزارگذاری شود؟
۶. چه نوع پیکربندی پایه (baseline configuration) باید استفاده شود؟
تنظیمات عمومی (General Setup). مطابق با توصیههای Caroline Lemieux Klees و همکارانش [12] و همچنین Moritz Schloegel و همکاران [9]، ما تمامی آزمایشها را ۱۰ بار تکرار کردیم تا اعتبار آماری نتایج حفظ گردد. تمامی آزمایشها در یک محیط داکرایز شده (dockerized environment) اجرا شدند و همگی روی یک پیکربندی سختافزاری یکسان صورت گرفتند که از این قرار میباشد: «دو پردازنده AMD EPYC 9654 (۱۹۲ هسته فیزیکی/ ۳۸۴ هسته منطقی)، ۷۶۸ گیگابایت حافظه RAM و فضای ذخیرهسازی SSD به عنوان رسانه پشتیبان (backing medium)». هر فازر در یک کانتینر اختصاصی اجرا گردید و به هر کانتینر یک CPU اختصاص داده شد. به منظور محاسبه پوشش کد (code coverage)، از هر برنامه هدف یک باینری با ابزارگذاری پوشش کد (coverage instrumentation) با استفاده از LLVM نسخه ۱۸ کامپایل کردیم و سپس مجموعه وروردی (corpus) تولید شده در فرآیند فازینگ را مجدداً روی آن بازپخش (replay) نمودیم.
انتخاب نسخه ++AFL. با توجه به تعداد زیاد قابلیتها و تنوع بالای اهداف آزمایشی، ارزیابی تمامی ۳۴ نسخه منتشر شده از نظر محاسباتی امکانپذیر نبود. برای این منظور، ابتدا یک مقدماتی (pilot experiment) روی دو هدف نماینده انجام پذیرفت (SQLite برای ورودیهای ساختیافته (structured inputs) و Bloaty برای ورودیهای باینری (binary inputs))
در این آزمایش، هر نسخه با پیکربندی پیشفرض خود اجرا شد. نتایج مربوط به SQLite3 به صورت نمونه در شکل ۱ ارائه شده است و نتایج Bloaty در پیوست A قرار دارد. مشاهده شد که برخی نسخهها تفاوت عملکردی ناچیزی با یکدیگر دارند؛ بنابراین آنها را با اطمینان از تحلیلهای بعدی حذف کردیم. همچنین نسخههایی که ویژگیهای کلیدی را معرفی کردهاند در اولویت قرار گرفتند؛ مانند CmpLog در نسخه 2.61c و بازطراحی حالت قطعی (deterministic mode) در نسخه 4.10c.
علاوه بر این، سازگاری گسترده با نسخههای مختلف LLVM نیز در فرآیند انتخاب لحاظ شده است. در نهایت، ۱۰ نسخه از ++AFL در بازه 2.52c تا 4.32c انتخاب شدند. این مجموعه شامل اولین و آخرین نسخه هر شاخه اصلی (major version) نیز بود (برای مثال 3.0c و 3.14c) تا هم بهبودهای تدریجی (incremental improvements) و هم تغییرات بنیادین (major changes) پوشش داده شوند. جدول ۱ خلاصهای از این ۱۰ نسخه منتخب ++AFL را نشان میدهد؛ شامل تغییرات تنظیمات پیشفرض در طول زمان (مانند حالت قطعی (deterministic mode) و زمانبندی بذرها (seed scheduling)) و همچنین وجود قابلیتهای کلیدی مانند MOpt ،CmpLog و dict2file.
جدول ۱: نسخههای ارزیابیشده ++AFL همراه با تنظیمات پیشفرض مربوط به زمانبند (scheduler) و حالت قطعی (deterministic mode):
انتخاب اهداف (Target Selection). به منظور ارزیابی تکامل ++AFL و قابلیتهای آن، مجموعه متنوعی از پروژههای متنباز را از پروژه FuzzBench انتخاب کردیم. این اهداف حوزههای مختلف و ساختارهای ورودی گوناگون را پوشش میدهند و در نتیجه یک مبنای ارزیابی جامع فراهم میکنند.
FuzzBench با اجرای فازرها و اهداف در کانتینرهای داکر (Docker) و با یک تنظیمات ساخت استاندارد (standardized build setup)، امکان ارزیابیهای قابل مقایسه و منسجم را فراهم میکند. ما یک محیط آزمایشی سفارشی توسعه دادیم تا کنترل دقیقتری روی تنظیماتی مانند نسخه Clang و پیکربندیهای ++AFL داشته باشیم؛ زیرا این موارد در FuzzBench بهراحتی قابل تغییر نیستند. این محیط به ما اجازه میدهد نسخههای مختلف ++AFL را به صورت مستقل پیکربندی و اجرا کنیم، در حالی که همچنان از فایلهای داکر (Docker) از پیش ساخته شده در FuzzBench و OSS-Fuzz برای تنظیم و راهاندازی مهار اهداف (target harness setup) استفاده کردیم.
اهداف انتخاب شده حوزههای کاربردی متنوعی را پوشش میدهند، از جمله تحلیل باینری (binary analysis) مانند Bloaty و Libpcap، پردازش تصویر و رسانه مانند Libjpeg و OpenH264، ارتباطات شبکهای مانند cURL و عملیات رمزنگاری همچون OpenSSL.
همچنین، اهدافی را انتخاب کردیم که قابلیتهای فازینگ دستور زبان (grammar fuzzing) در ++AFL را به چالش میکشند، مانند Libxslt و SQLite. گزارشهای موجود در FuzzBench [32] به ما در اولویتبندی اهدافی با نتایج متنوع فازینگ مانند HarfBuzz کمک کردند. همچنین توصیههای نگهدارنده AFL++ [33] منجر به انتخاب اهدافی مانند STB و FreeType گردید. علاوه بر این، پروژههای Bloaty، HarfBuzz، libaom، libxml2، assimp و mruby بیشتر در آزمایش شناسایی باگ (bug finding experiment) استفاده شدند. در مجموع، آزمایشهای اصلی ما بر روی ۱۰ مورد از این ۱۵ هدف انجام شده است.
انتخاب ویژگیهای فازینگ (Fuzzing Feature Selection). ابزار ++AFL طی سالهای اخیر با مشارکت جامعه و پژوهشهای دانشگاهی به طور قابل توجهی تکامل یافته و مجموعهای از قابلیتها به آن افزوده شده است که کارایی فازینگ، ابزارگذاری (instrumentation) و سازگاری با اهداف مختلف را بهبود میبخشد. از جمله موارد قابل توجه میتوان به جهشدهندههای جدید مانند mOpt، ابزارگذاری پیشرفته مانند CmpLog و همچنین پشتیبانی باینریها گسترده و توسعهیافته از طریق QEMU و Frida اشاره کرد. با این حال، آزمایش تمام این ویژگیها به منابع محاسباتی عظیمی نیاز دارد.
مطالعه ما تاثیر ویژگیهای منتخب را در چارچوب فازینگ عمومی مبتنی بر کد منبع (source-based fuzzing) بررسی میکند و ویژگیهایی را که برای باینریهای بسته طراحی شدهاند (مانند حالت مبتنی بر QEMU یا فازینگ مبتنی بر اسنپ شات (snapshot) با Nyx [28]) حذف گردید.
تمام ویژگیهای مورد آزمایش به صورت جداگانه (in isolation) ارزیابی شدهاند تا سهم هرکدام به طور مستقل اندازهگیری شود؛ هرچند ترکیب چندین ویژگی ممکن است در عمل عملکرد بهتری ایجاد کند. علاوه بر این، ما از تنظیمات پیشفرض هر ویژگی استفاده کردهایم. برخی از این قابلیتها، امکان تنظیم دقیق از طریق گزینههای خط فرمان (command-line options) را دارند، اما تنظیم دقیق پارامترها (parameter tuning) به عنوان بخشی از ارزیابی ما نبوده است.
به منظور انجام یک تحلیل متمرکز و در عین حال معنادار، ما ۱۰ ویژگی از ++AFL را انتخاب کردیم و آنها را برای یک ارزیابی هدفمند، در دو دسته ویژگیهای مرتبط با فازینگ و ویژگیهای مرتبط با ابزارگذاری (instrumentation) طبقهبندی کردیم. ویژگیهای انتخاب شده در بخش فازینگ شامل پیکربندی پیشفرض (default configuration)، حالت فازینگ قطعی (deterministic mode) در دو وضعیت فعال و غیرفعال و زمانبند پیشفرض (default scheduler) که بسته به نسخه ++AFL بین دو سیاست Explore و Fast تغییر میکند، میباشد.
ما همچنین تاثیر قابلیتهای جهشدهنده MOpt (mOpt mutator)، دیکشنریهای استخراج شده خودکار (dict2file)، مکانیزم ثبت عملوندهای مقایسه (CmpLog) و قابلیت بهبود پردازش مقایسهها (CompCov) را نیز ارزیابی کردیم. این ویژگیها به این دلیل انتخاب شدند که نمایانگر بهبودهای عملکردی کلیدی در ++AFL هستند و همچنین امکان بررسی این موضوع را فراهم میکنند که پیادهسازی و اثربخشی آنها در نسخههای مختلف ++AFL چگونه تکامل یافته است. علاوه بر این موارد، ++AFL به طور مستمر با بهبودهای بالقوه جدید به روزرسانی میشود؛ اما چنین تغییراتی همیشه به صورت صریح قابل پیکربندی یا مستقیماً قابل کنترل توسط کاربر نیستند.
انتخاب حالت ابزارگذاری (Instrumentation Mode Selection). در حالی که ویژگیهای فازینگ نحوه جهش (mutate) ورودیها را تعریف میکنند، ویژگیهای ابزارگذاری (instrumentation) نحوه جمعآوری بازخورد پوشش (coverage feedback) را مشخص میکنند. ابزارگذاری، یکی از مؤلفههای کلیدی در فازینگ مبتنی بر بازخورد است که امکان شناسایی وضعیتهای جدید برنامه، هدایت جهشها، و در نهایت بیشینهسازی پوشش کد را فراهم میکند. ++AFL طی سالهای گذشته، تکنیکهای مختلفی را برای ابزارگذاری با موازنههای متفاوت از نظر دقت (precision)، کارایی (performance) و سازگاری (compatibility) در خود ادغام کرده است. ما برای انجام تحلیل خود، حالتهای ابزارگذاری PCGuard، Classic، CTX، و llvm-native را در ++AFL انتخاب کردیم که همگی به طور مفصل در بخش ۲ توضیح داده شدهاند.
ابزارگذاری هدف (Target Instrumentation). به منظور اطمینان از انجام یک مقایسه منصفانه میان نسخههای مختلف ++AFL، از یک رویکرد ابزارگذاری ترکیبی یا هیبریدی (hybrid instrumentation) استفاده کردیم. هر هدف (target) به دو روش ابزارگذاری شدند: (۱) با استفاده از یک نسخه جدید از ++AFL و کامپایلر متناظر آن و (۲) با استفاده از ابزارگذاری و کامپایلر اصلی مربوط به هر نسخه. این رویکرد، تأثیر عوامل خارجی مانند بهینهسازیهای کامپایلر را کاهش میدهد و کمک میکند بهبودهای ناشی از راهبردهای فازینگ به صورت مستقل بررسی شوند. ارزیابی تمام نسخهها تحت یک پیکربندی مدرن، تغییرات ایجاد شده در منطق فازینگ (fuzzing logic) را آشکار میسازد؛ در حالی که استفاده از پیکربندیهای اصلی هر نسخه، امکان بررسی میزان پیشرفت در تکنیکهای ابزارگذاری را در طول زمان فراهم میکند.
نسخه 4.20c ابزار ++AFL یک مدل جدید از forkserver را معرفی کرد که با نسخههای قدیمیتر سازگار نبود. ما به منظور حل این مشکل، نسخههای قدیمیتر از 4.20c (از 4.10c شروع میشود) را با استفاده از AFL++ 4.10c ابزارگذاری کردیم، در حالی که نسخههای c4.20 و جدیدتر برای اطمینان از سازگاری توسط AFL++ 4.21c ابزارگذاری شدند. از آنجا که نسخه 4.30c ساختار نقشه CmpLog را تغییر میدهد و نیاز به کامپایل مجدد اهداف (targets) دارد، ما اهداف را در آزمایش CmpLogبا همان نسخه مربوطه تحت آزمایش (یعنی 4.32c) کامپایل کردیم. نسخه کامپایلر در تمام آزمایشها ثابت نگه داشته شد و از LLVM نسخه 18.0 استفاده گردید. این کار تضمین میکرد که همه فازرها از یک باینری ابزارگذاری شده یکسان استفاده کنند و در نتیجه هرگونه اختلاف ناشی از تفاوت در باینری حذف شود. همچنین، در آزمایشهایی که به مقایسه حالتهای مختلف ابزارگذاری اختصاص داشتند، از هر دو پیکربندی جدیدترین نسخه (latest) و پیکربندی بومی یا متناظر با همان نسخه (native / version-matched) استفاده کردیم تا تأثیر تکنیکهای ابزارگذاری و بهینهسازیهای کامپایلر بهطور دقیق ارزیابی شود.
پیکربندی مبنا (Baseline Configuration). در آزمایشهای اولیه مشاهده کردیم که در اکثر نسخههای AFL++، با حذف مرحله قطعی (deterministic stage) بهبود قابل توجهی حاصل میشود (رجوع شود به بخش ۴.۱)، به جز نسخههایی که دارای مرحله قطعی جدید بودند (≥4.10c). از این رو، برای اطمینان از ارزیابی جداگانه و مستقل ویژگیهای مختلف، در تمامی آزمایشها (مگر در مواردی که خلاف آن ذکر شده باشد) مرحله قطعی (deterministic stage) غیرفعال گشت و از آن صرفنظر شد.
++AFL از استراتژیهای اجرایی مختلفی برای بهینهسازی سرعت و کارایی فازینگ استفاده میکند. مدل forkserver با نگه داشتن فرآیند در حافظه و ایجاد نمونههای جدید (fork) در صورت نیاز، سربار راهاندازی فرآیند را کاهش میدهد. حالت پایدار (persistent mode) نیز با اجرای چندین دور فازینگ درون همان فرایند، بدون ایجاد نمونههای جدید (fork) پرهزینه، این سربار را بیشتر کاهش میدهد.
از آنجا که حالت پایدار (persistent) اجرای سریعتری فراهم میکند و انتخاب اهداف ما بر اساس اهداف FuzzBench انجام شده بود (که از قبل از آن پشتیبانی میکنند)، تمامی آزمایشها با استفاده از این راهبرد انجام شدند. علاوه بر این، ویژگی مورد آزمایش حافظه مشترک (shared memory test case feature)، که موارد آزمایشی را از طریق حافظه مشترک به برنامه هدف منتقل میکند، به طور پیشفرض در مهارهای FuzzBench (یا FuzzBench harnesses) فعال شده است و سرعت بیشتری را فراهم میکند.
۴. ارزیابی تجربی
ما اکنون در این بخش، چهار آزمایش خود را که بهترتیب شامل ارزیابی بهبود عملکرد فازر (fuzzer improvement)، ابزارگذاری (instrumentation)، عملکرد بلندمدت فراتر از ۲۴ ساعت و توانایی کشف باگها (bug finding) میباشند، مورد بحث قرار میدهیم. در ادامه، دو مطالعه موردی (case study) را شرح داده و درسهای آموخته شده را بیان خواهیم کرد. در نهایت، بررسی میکنیم که آیا مشاهدات ما در مورد دو فازر دیگر، یعنی LibAFL و Fuzzilli نیز صادق هستند یا خیر.
۴.۱ آزمایش ۱: بهبود فازر
ما ابتدا سهم هر یک از ویژگیهای کلیدی معرفی شده در ++AFL را در طول زمان به صورت جداگانه ارزیابی میکنیم. همانطور که پیشتر توضیح داده شد، تمام اهداف با استفاده از نسخه 4.10c یا c4.21 ابزارگذاری میشوند تا تأثیر کامپایلر (همانطور که در بخش قبلی توضیح داده شد) به حداقل برسد. ما ویژگیهای مختلف را در دو گروه «بهبودهای ابزارگذاری و بازخورد (شامل CmpLog، CompCov و dict2file)» و «استراتژیهای جهش و زمانبندی (شامل mOpt، Fast وExplore)» دستهبندی کردیم. به عنوان مبنا (baseline)، ابتدا پیکربندی پیشفرض هر نسخه را ارزیابی میکنیم تا یک نقطه مرجع برای مقایسه فراهم شود.
پیکربندی پیشفرض (Default Configuration). در اولین آزمایش، نسخههای مختلف ++AFL را با پیکربندیهای پیشفرض خود اجرا کردیم. این ارزیابی نشان داد که برای هفت هدف، بین نسخههای 2.68c تا 3.0c افزایش قابل توجهی در پوشش کد رخ داده است. برای نمونه، در مورد Bloaty، میانگین پوشش کد 19.3٪ افزایش یافته است (رجوع شود به شکل 2a). این روند همچنین در آزمایش اکتشافی قبلی که شامل تمام نسخههای ++AFL بود نیز مشاهده شد (شکل ۱). تحلیل یادداشتهای انتشار حاکی از آن است که در نسخه 3.0c چند تغییر مهم اعمال شده است، از جمله دو مورد اصلی: (۱) تغییر زمانبند پیشفرض از Explore به Fast و (۲) غیرفعال شدن مرحله قطعی (deterministic stage).
به منظور بررسی اینکه آیا تغییرات مذکور عامل اصلی اثرات مشاهده شده میباشند یا خیر، آزمایش دیگری (دوم) انجام شد که در آن هر نسخه منتخب با و بدون مرحله قطعی (deterministic stage) ارزیابی گردید. نتایج تأیید کردند که غیرفعالسازی این مرحله، عامل اصلی بهبود عملکرد مشاهده شده است. شکل 2b تفاوتهای میان این دو تنظیم را نشان میدهد. نمودار سمت چپ، نتایج مربوط به Bloaty را در پیکربندی پیشفرض نمایش میدهد، که در آن تنظیمات مرحله قطعی در نسخههای مختلف تغییر میکنند. نمودار سمت راست، همان هدف را با تنظیمات ثابت برای مرحله قطعی نشان میدهد.
در مجموع، میزان بهبود ناشی از حذف این مرحله از +24٪ در نسخه 3.0c تا 4.03-٪ در نسخه 4.32c متغیر است. این موضوع نشان میدهد که بازنگری مرحله قطعی در نسخه c4.10 تأثیر مثبتی بر این نسخه و نسخههای بعدی داشته است. از آنجا که غیرفعالسازی مرحله قطعی در اکثر نسخهها بهطور قابل توجهی عملکرد را بهبود بخشیده است، در آزمایشهای خود این مرحله را غیرفعال کردیم تا اثر آن به صورت مستقل بررسی شود.
بهبودهای ابزارگذاری و بازخورد (Instrumentation & Feedback Enhancements). بهدلیل تعداد زیاد ترکیبهای مختلف ویژگیها در میان ده هدف و ده نسخه از ++AFL، یک جمعبندی تلفیقی در شکل ۳ ارائه شده است؛ بهطوریکه هر میله خطا (error bar) و نشانگرهای مربوط به آن، نمایانگر نتایج تمام ده هدف هستند.
این نمودار، بهبود نسبی هر نسخه را نسبت به ++AFL نسخه 2.52c در حالت غیرفعال بودن مرحله قطعی (skip-det) نشان میدهد. از آنجا که تجمیع نتایج روی تمام اهداف مقداری واریانس (variance) ایجاد میکند، برای استخراج روند کلی، از رگرسیون خطی استفاده شده است. نتایج رگرسیون نشان دهنده یک روند افزایشی ملایم است؛ به طوری که شیب آن 0.61٪ به ازای هر نسخه و مقدار (R2 = 0.52) میباشد.
این مقدار نشان میدهد که بخش قابل توجهی از واریانس ناشی از تفاوتهای وابسته به هدف (target-specific differences) است، نه خودِ پیشرفت نسخهها؛ به همین دلیل الگوی بهبود به صورت قوی خطی نیست. همانطور که خط میانگین (median) نشان میدهد، روند کلی بهبود پس از نسخه 2.68c تقریباً متوقف شده و در بازه ۲ تا ۴ درصد باقی میماند و پس از نسخه 4.10c مجددا افزایش پیدا میکند.
نتایج تحلیل ویژگیها بیانگر آن است که اغلب آنها تا نسخه 3.0c بهبود عملکرد قابلتوجهی ایجاد میکنند. در حالی که dict2file و CmpLog افزایش عملکرد کمی را پس از 3.0c نشان میدهند، CompCov پس از نسخه 3.14c کاهش عملکرد را تجربه میکند، سپس از نسخه 4.10c به بعد مجدا بهبود مییابد و در نهایت در نسخه 4.32c به بهترین عملکرد میانه (۸٪) خود میرسد.
به منظور نمایش بهتر این روندها (همانطور که در شکل ۳ نشان داده شده است)، دو هدف را به عنوان مطالعه موردی برای CmpLog انتخاب کردیم: یکی با عملکرد مطلوب (Freetype2) و دیگری با میزان بهبود متوسط (Libxslt). زمانی که CmpLog در نسخه 2.61c معرفی گردید، موجب کاهش پوشش کد (۳.۲٪− نسبت به حالت skip-det) گردید، اما از نسخه 3.14c به بعد، مزیتهای قابل توجهی به همراه افزایش متوسط ۲٬۷۸۸ شاخه (+۳۲.۸٪) را از خود نشان داد. عامل این بهبود و ارتقاء، به روزرسانی بین نسخههای 3.0c تا 3.14c، مانند پشتیبانی از اعداد اعشاری و برخی تبدیلها (مانند toupper، tolower، tohex)، میباشد (رجوع شود به پیوست B).
با این حال، از این نسخه به بعد، عملکرد در بازه ۱۰٬۲۰۰ تا ۱۰٬۷۰۰ شاخه پوششیافته تقریباً ثابت ماند و تا نسخه 4.32c دیگر بهبود قابل توجهی را تجربه نکرد. در این نسخه، میانگین پوشش به حدود ۱۱٬۲۰۰ شاخه رسید. این بهبود مطابق با یادداشتهای انتشار، ناشی از اصلاح نقشه CmpLog در نسخه 4.30c است.
در مجموع، بهبود قابل توجه CmpLog عمدتاً مربوط به Freetype2 میباشد، در حالی که برای سایر اهداف همانطور که برای Libxslt در شکل ۳ نشان داده شده است، اثر آن محدودتر بوده و در بازه ۰.۱ تا ۳.۰۴ درصد نسبت به skip-det قرار دارد.
استراتژیهای جهش و زمانبندی (Mutation & Scheduling Strategies). ما استراتژیهای مختلف زمانبندی و جهش را مطابق با نمودارهای پایین در شکل ۳ مقایسه کردیم. برخلاف بهبودهای ابزارگذاری و بازخورد که بهطور کلی روندی نسبتاً پایدار و افزایشی در طول نسخهها دارند، روند عملکرد این بخشها همانطور که در خط میانه (median line) نیز مشاهده میشود، ناپایدارتر است. همانطور که میانه (میانگین) نشان میدهد، پس از همان اثر مثبت اولیه مشاهده شده برای ویژگیهای ابزارگذاری و بازخورد تا نسخه c2.68، عملکرد کلی تا نسخه 4.10c ابتدا کاهش یافته و سپس دوباره بهبود مییابد. رگرسیون خطی تنها یک روند صعودی بسیار جزئی را با شیب 0.52٪ نشان میدهد که حتی کوچکتر از روند مشاهده شده برای بهبودهای ابزارگذاری و بازخورد است.
اولین نسخه آزمایش شده که شامل mOpt (2.61c) میباشد در مقایسه با Fast، Explore و skip-det، تأثیر مثبت اندکی را نشان میدهد. از نسخه 2.68، بهبود چشمگیرتری بین 2 تا 8 درصد نسبت به نسخه پایه c2.52 (skip-det) مشاهده میشود. با این حال، بهبود متوسط خود mOpt (نسخه 2.68c) در مقایسه با پیکربندی skip-det همان نسخه (2.68c) تنها بهبود اندکی (2٪) دارد. از آن نقطه به بعد، عملکرد mOpt تا نسخه 4.00c کاهش مییابد و سپس دوباره شروع به بازیابی میکند. روند مشابهی برای زمانبند Fast نیز مشاهده شده است که در نسخه c4.32 به اوج خود رسید، در حالی که زمانبند دوم یعنی Explore، در نسخههای پس از 2.68c عملکرد پایدارتر و یکنواختتری داشت.
به منظور تحلیل دقیقتر این روندها،mOpt را روی دو هدف Libpcap و Bloaty به طور مفصل بررسی کردیم. همانطور که در شکل ۳ نشان داده شده است، افت و سپس بازیابی عملکرد mOpt در هر دو هدف قابل مشاهده است و آخرین نسخه در هر دو مورد، عملکرد بهتری از خط مبنای skip-det (نمودار خاکستری) دارد. نکته قابل توجه این است که یک باگ که در نسخه AFL++ 4.09c معرفی شده بود، به طور موقت استفاده از mOpt را مختل میکرد، اما طبق یادداشتهای انتشار نسخه c4.20 این مشکل برطرف شده است.
نتیجهگیری ۱: بهبودهای مرتبط با ابزارگذاری (instrumentation) و بازخورد (feedback) در طول نسخههای مختلف ++AFL، بهبودهایی کوچک اما پیوسته ایجاد میکنند و تا نسخه 3.0c پیشرفتهای قابل توجهی مشاهده میشود. در مقابل، راهبردهای جهش (mutation) و زمانبندی (scheduling) عملکردی ناپایدارتر دارند و میزان اثربخشی آنها در نسخههای مختلف با نوسان همراه است.
۴.۲ آزمایش ۲: ابزارگذاری (Instrumentation)
در این آزمایش، تأثیر انواع مختلف ابزارگذاری (instrumentation) را در دو سناریو بررسی میکنیم: (۱) هدفهایی که با استفاده از یک نسخه جدید از فازر و کامپایلر ابزارگذاری شدهاند (پسوند latest)؛ مشابه آنچه در آزمایش قبلی انجام شد (رجوع شود به بخش ۴.۱). (۲) هدفهایی که با استفاده از همان ترکیب فازر/کامپایلر متناظر با هر نسخه انتشار ابزارگذاری شدهاند (پسوند pinned). همانطور که در بخش ۳ توضیح داده شد، انواع ابزارگذاری مورد ارزیابی شامل Classic، llvm-native، CTX و ابزارگذاری پیشفرض در ++AFL نسخه 4.21c یعنی PCGuard میباشند.
نتایج ارائه شده در شکل ۴، بهبود جزئی قابل مشاهدهای را از نظر پوشش کد (coverage) فراتر از خط مبنای انتخاب شده (AFL++ 2.52c با PCGuard) نشان میدهد؛ افزایشی که نمیتوان آن را به بهبودهای کلی فازر مشاهده شده در آزمایش قبلی نسبت داد. همچنین، در تقریباً تمامی نسخهها، ابزارگذاری با استفاده از کامپایلر متناظر با همان نسخه (پین شده – pinned) اندکی عملکرد بهتری نسبت به ابزارگذاری با استفاده از یک نسخه جدید از کامپایلر نشان میدهد.
برای نشان دادن این روند، یک مدل رگرسیون خطی روی دادهها اعمال (fit) و همچنین میانگین ترکیبی (combined median) را روی تمامی اهداف و انواع ابزارگذاری رسم کردیم. نتایج رگرسیون شیبی برابر با 0.34٪ و مقدار (R2 = 0.18) را نشان میدهند. این مقادیر بیانگر آن هستند که تنها یک روند افزایشی بسیار جزئی در طول نسخهها وجود دارد. همچنین پایین بودن مقدار (R2) نشان میدهد که بخش عمده واریانس ناشی از تفاوتهای عملکرد وابسته به هدف (target-specific performance differences) است، نه خود روند پیشرفت نسخهها. این آزمایش نیز واریانس قابل توجهی نشان میدهد که به احتمال زیاد ناشی از تفاوت در نوع برنامههای هدف میباشد. نموداری که مقادیر خارج از بازه بین چارکی (IQR) را نیز شامل میشود، در پیوست D ارائه شده است.
نتیجهگیری ۲: انواع مختلف ابزارگذاری (instrumentation) در مقایسه با ابزارگذاری پیشفرض PCGuard که در آزمایشهای قبلی استفاده شد (نمایش داده شده با میله خاکستری)، تأثیر ناچیزی بر میزان پوشش کد (coverage) دارد و یا تقریباً هیچ تأثیری ندارند.
۴.۳ آزمایش ۳: آزمایش بلندمدت (Long-Term Experiment)
فراتر از آزمایشهای استاندارد ۲۴ ساعته، ارزیابی اجراهای طولانیمدت نیز اهمیت دارد، به ویژه برای اهداف پیچیدهای که در مدت یک روز به نقطه اشباع پوشش (coverage saturation) دست نمییابند. به همین منظور، زیرمجموعهای از نسخههای ++AFL شامل 2.52c، 3.0c، 4.0c و 4.32c و همچنین دو هدف Bloaty و SQLite3 را برای یک کمپین ۷ روزه انتخاب کردیم. این دو هدف بهگونهای انتخاب شدند که نمایانگر ویژگیهای ورودی متفاوتی باشند: SQLite3 به ورودی ساختاریافته (structured input) نیاز دارد، در حالی که Bloaty ورودی باینری (binary input) را پردازش میکند.
در این آزمایش، از پیکربندی پیشفرض و بدون تغییر هر نسخه ++AFL استفاده گردید. در نتیجه، برخی فازرها (برای مثال c2.52 و c4.32) از مرحله قطعی (deterministic stage) استفاده میکردند، در حالی که برخی دیگر (برای مثال c3.0 و c4.0) این مرحله را شامل نمیشدند.
نتایج در شکل ۵ نشان داده شده است. در هر دو هدف، نسخه 4.32c در ابتدای اجرا برنامه را با کارایی بیشتری کاوش میکند و در ۴۸ ساعت نخست نسبت به نسخههای 3.0c و 4.0c به پوشش بیشتری دست مییابد. در مقابل، نسخه 2.52c به طور محسوسی عقبتر است و تنها به حدود ۵۰ درصد از پوششی میرسد که سایر نسخهها به آن دست یافتهاند. در مورد SQLite3، کمی پس از ۲۴ ساعت، نسخه 3.0c فاصله خود را جبران میکند و به آن میرسد. این نسخه پس از ۴۸ ساعت، از سایر نسخهها پیشی میگیرد و در طول کل دوره هفتروزه این برتری جزئی را حفظ میکند؛ به طوریکه میانگین پوشش آن 21,359.5 شاخه است، در حالی که این مقدار برای نسخه 4.32c برابر با 21,186.5 شاخه میباشد.
روند مشابهی در Bloaty نیز مشاهده میشود. در اینجا نسخه 3.0c کمی پیش از مرز ۲۴ ساعت از 4.0c عبور میکند و تا پایان هفت روز تقریباً به 4.32c میرسد. در نهایت، نسخه 4.32c تنها برتری بسیار ناچیزی در تعداد شاخههای پوششیافته دارد (6,756.5 در برابر 6,752.5 شاخه پوششیافته).
نکته جالب این است که نسخههای 3.0c و 4.0c هر دو از یک پیکربندی پیشفرض یکسان برای زمانبندی بذرها (seed) (Fast) استفاده کرده و هر دو مرحله قطعی (deterministic stage) را غیرفعال میکنند؛ با این حال، نسخه 3.0c بهطور مستمر عملکرد بهتری نسبت به 4.0c نشان میدهد. این مشاهده با نتایج آزمایشهای قبلی ما نیز همراستا است، جایی که مشاهده کرده بودیم نسخه 3.0c در برخی موارد حتی از نسخههای جدیدتر ++AFL نیز بهتر عمل میکند. با این حال، همانطور که در مطالعه موردی ارائه شده در پیوست C بررسی شده است، نتوانستیم بهطور دقیق تغییرات کد مشخصی را در نسخههای بعدی ++AFL شناسایی کنیم که موجب این افت عملکرد شده باشند.
یک توضیح احتمالی برای اینکه چرا این رگرسیون که در نهایت به نسخه ۳.۰c یک مزیت بلندمدت میدهد، مورد توجه قرار نگرفت، این است که ویژگیهای جدید ++AFL معمولاً با استفاده از FuzzBench در Google Cloud ارزیابی میشوند. این کمپینها به دلیل محدودیتهای فنی، به ۲۳ ساعت اجرا محدود میشوند که مانع از شناسایی رگرسیونهایی میگردد که فقط در اجراهای طولانیتر ظاهر میشوند.
نتیجهگیری ۳: در حالی که آخرین نسخه آزمایش شده ++AFL در ۲۴ ساعت نخست عملکرد مؤثرتری دارد، نسخه 3.0c در یک هدف از آن پیشی میگیرد و در هدف دیگر نیز طی اجرای هفت روزه عملکرد تقریباً مشابهی با آن دارد.
۴.۴ آزمایش ۴: کشف باگ در ++AFL
معیار اصلی برای اندازهگیری عملکرد فازر در این مقاله، مطابق با یافتههای Böhme و همکارانش [11]، پوشش شاخهها (branch coverage) میباشد. با این حال، پوشش در نهایت تنها یک نماینده برای هدف واقعی فازینگ یعنی یافتن باگها است. برای ارزیابی مستقیم این جنبه، یک آزمایش کشف باگ روی شش هدف از مجموعه FuzzBench صورت پذیرفت. این اهداف از مجموعه پیشفرض FuzzBench (شامل: HarfBuzz، Bloaty، libxml2 و mruby) و همچنین آزمایشهای عمومی باگ در FuzzBench (شامل: libaom و assimp) انتخاب شدند.
هدفها با همان فلگها (flags) و سنیتایزرهایی (sanitizer) کامپایل و فاز میشوند که در FuzzBench استفاده میگردد. به منظور حذف موارد تکراری (deduplication) در کرشها (Crash)، هر گزارش سنیتایزر را تحلیل و نوع باگ (Bug) و محل وقوع آن در کد منبع پروژه را استخراج میکنیم. هر جفت منحصربهفرداز نوع باگ و محل کد منبع به عنوان یک باگ مستقل در نظر گرفته میشود. نتایج این آزمایش که در جدول ۲ خلاصه شدهاند، چند الگوی جالب را نشان میدهند:
برای اکثریت اهداف (Bloaty، libxml2 و mruby)، تعداد باگهای منحصر به فرد بسیار کم است و اغلب در تمام نسخههای ++AFL تقریباً ثابت باقی میماند. در مقابل، هدف HarfBuzz تنوع بیشتری را از خود نشان میدهد. در حالی که نسخههای جدیدتر مانند v4.32c و نوع SAND آن، بالاترین میانگین و بیشینه را به دست میآورند، نسخه قدیمیتر c3.0 همچنان برخی باگها را آشکار میکند که در نسخههای جدیدتر مشاهده نمیشوند.
نکته جالب این است که نسخه c4.32 همراه با SAND در اهداف assimp و mruby هیچ باگی پیدا نمیکند، اما نسخه 4.32c بدون SAND و همچنین نسخههای قدیمیتر مانند 3.0c (در assimp) و 4.0c (در mruby) قادر به فعالسازی (trigger) این باگها هستند. در مورد libaom نیز تقریباً همه نسخهها همان سه باگ یکسان را پوشش میدهند.
نتیجهگیریها: تعداد پایین باگها، همراه با تفاوتهای اغلب ناچیز بین نسخههای مختلف فازر، موجب میشود آزمایشهای مبتنی بر کشف باگ برای اندازهگیری دقیق و ریزبینانهی پیشرفت بین نسخههای مختلف ++AFL مناسب نباشند.
۴.۵ مطالعه موردی: بهبود نسخههای 2.61c تا 2.68c
با شروع از نسخه c2.61 تا c2.68 ابزار ++AFL، بهبود قابل توجهی در اکثر اهداف و پیکربندیها در میزان پوشش مشاهده شد (رجوع شود به شکل ۳). بررسی دقیقتر نشان داد که تفاوت قابل توجهی در تعداد کل اجراها (executions) بین این دو نسخه وجود دارد. برای مثال، در مورد Freetype2، نسخه c2.68 تقریباً ۵۶۰٪ اجرای بیشتری نسبت به c2.61 داشته است؛ روندی که در سایر اهداف نیز مشاهده شد.
به منظور شناسایی بهبود مشخصی که مسئول این افزایش در تعداد اجراها بود، ابتدا نسخههای میانی (intermediate versions) را بررسی کردیم و آزمایشهایی را برای محدود کردن تغییرات مربوطه به انجام رساندیم. در نهایت مشخص شد که این بهبود بین نسخههای c2.65 و c2.66 رخ داده است (رجوع شود به شکل ۶).
طبق یادداشتهای انتشار (release notes)، چندین تغییر میتوانست در این بهبود نقش داشته باشد. با این حال، محتملترین عامل، معرفی ویژگی مورد آزمایش حافظه مشترک (shared memory test case feature)، بود؛ قابلیتی که به جای استفاده از ورودی استاندارد یا فایل، امکان انتقال ورودی آزمایشی را از طریق حافظه مشترک فراهم میکند. این فرضیه با یک آزمایش تأیید شد؛ به طوریکه تغییراتی (commit) که بلافاصله قبل از اضافه شدن این قابلیت قرار داشت، با تغییراتی که این ویژگی را اضافه کرده بود مقایسه شدند.
جدول ۲: باگهای منحصر به فرد کشف شده توسط نسخههای مختلف ++AFL روی شش هدف از مجموعه FuzzBench (اجرای ۲۴ ساعته؛ ۱۰ اجرا برای هر مورد؛ حالت skip-det):
نتیجهگیری ۴: ویژگی مورد آزمایش حافظه مشترک (shared memory test case feature) به طور قابل توجهی سرعت فازینگ را افزایش میدهد و موجب بهبود پوشش در تمامی اهداف میشود.
۴.۶ مطالعه موردی: بهبود بین نسخههای 2.68c تا c3.0
با گذار از نسخه 2.68c به نسخه بعدی، یعنی 3.0c در ++AFL، بهبودهایی در پوشش شاخهها مشاهده شد. اگرچه این تفاوت برای اکثر اهداف جزئی است، اما در مواردی مانند Libpcap، Bloaty و Libxslt برجستهتر است. طبق یادداشتهای انتشار، چندین تنظیم پیشفرض در نسخه 3.0c تغییر کردهاند، از جمله تغییر زمانبند پیشفرض از Explore به Fast و همچنین معرفی یک مکانیزم جدید انتخاب بذر (seed) بر اساس وزنهای تصادفی به جای رویکرد ترتیبی (sequential). به منظور ارزیابی تاثیر این تغییرات، آزمایشی روی هدف Libpcap صورت پذیرفته و زمانبندهای مختلف و مکانیزم جدید انتخاب بذر مقایسه شده است. نتایج (شکل ۷) نشان میدهند که این تغییرات تأثیر قابل توجهی بر عملکرد این هدف نداشتهاند. این آزمایش نشان میدهد که بهبودهای عملکردی مشاهده شده صرفاً ناشی از تغییرات قابل ملاحظه در پیکربندی پیشفرض نیستند.
ما برای بررسی این موضوع، تغییرات ثبت شده (Commit) بین نسخههای ۲.۶۸c و ۳.۰c را به دو نیم تقسیم و کمپین را مجددا اجرا کردیم. ما یک تغییر جزئی اما قابل توجه را در شش خط از فایل کد منبع در afl-fuzz-one.c شناسایی کردیم. چنانچه هیچ یافته جدیدی در عرض پنج ثانیه رخ ندهد، حالت غیرقطعی (havoc) وارد مرحلهای میشود که در آن جهشهای پرهزینهتری انجام میدهد. نمودار سمت راست در شکل ۷ این تأثیر را با مقایسه تغییرات ثبت شده (Commit) قبل و بعد از این تغییر، نشان میدهد.
نتیجهگیری ۵: تغییرات کوچک میتوانند تاثیرات قابل توجهی داشته باشند. گسترش مرحله غیرقطعی (havoc) در نسخه 3.0c در ++AFL به طور مثبت بر کاوش برنامه تأثیر گذاشته است. در مورد Libpcap نیز این تغییر منجر به بهبود متوسطی در حدود 11.2٪ شده است.
۴.۷ درسهای آموخته شده (Lessons Learned)
بر اساس تمام آزمایشهایی که در این مطالعه انجام شد، مشاهدات خود را در قالب چهار بینش (insight) کلیدی خلاصه میکنیم:
(۱) پیشرفت تا حد زیادی متوقف شد. پوشش کد تا نسخه 3.0c در ++AFL بهبود یافت، اما پس از آن تا حد زیادی ثابت ماند و وارد فاز سکون یا رکود (plateau) شد (به شکل 3 مراجعه شود)، و به دلیل مرحله قطعی جدید 4.10c، بهبود اندکی حاصل شد.
(۲) تعداد کمی از ویژگیها اثرات مثبت (بهبودهای) عمومی ایجاد میکنند. تنها چند ویژگی، که قابل اعتمادترین آنها dict2file ،CmpLog ،CompCov و مرحله قطعی جدید میباشند، منجر به دستاوردهای تکرارپذیر در اهداف متنوع میشوند. اکثر ویژگیهای دیگر فقط در موارد محدود و خاص اثر مثبت از خود نشان میدهند.
(۳) بزرگترین دستاوردها از ویژگیهای ساده ناشی میشوند: ما شاهده کردیم که تغییرات نسبتاً کوچکی مانند گسترش حالت غیرقطعی (havoc)، استفاده از حافظه مشترک برای انتقال موارد آزمایشی (test case) و غیرفعالسازی مرحله قطعی (c→3.0c2.68) برخی از قابل توجهترین بهبودهای عملکرد را به همراه داشتهاند.
(۴) بهبودها به ندرت بین اهداف مختلف قابل تعمیم هستند: آنچه روی اهدافی مانند Freetype2 یا cURL عملکرد خوبی دارد، لزوماً به بهبود مشابهی در اهداف دیگر مانند OpenSSL و STB منجر نمیشود. شکل ۸ (و جدول ۵ در پیوست) بهترین پیکربندی را برای هر هدف نشان میدهند و بیانگر تنوع زیاد بین اهداف و نسخهها هستند.
با ترسیم تاریخچه تجربی ++AFL، یک پرسش پژوهشی جدید مطرح میشود: ایدههای جدید جامعه تحقیقاتی فازینگ با چه سرعت و سهولتی وارد عمل (practice) میشوند؟ در حالی که این پژوهشها اغلب بهبودهای پیچیده و پیشرفتهای را پیشنهاد میکنند، مشاهدات تجربی ما از رشد محدود در پوشش کد، با تعداد بالای مقالات منتشرشده در این حوزه در تضاد است. این پرسش در بخش ۵ مورد بررسی قرار خواهد گرفت.
۴.۸ تعمیمپذیری مشاهدات (Generalizability of Observations)
یکی از پرسشهای کلیدی این است که آیا مشاهدات مابهویژه L1 مختص ++AFL میباشند یا نشاندهنده یک روند گستردهتر در حوزه فازینگ هستند. برای بررسی این فرضیه، تنها فازر همهمنظوره و عمومی (general-purpose) دیگری را که هم بهطور فعال توسعه داده میشود و هم دستاوردهای پژوهشی جدید در آن ادغام میشوند، یعنی LibAFL، نیز در مطالعه خود وارد کردیم. در گام دوم، بررسی میکنیم که آیا مشاهدات ما برای فازرهایی که توسط صنعت پشتیبانی میشوند نیز برقرار است یا خیر. متأسفانه، چنین فازرهایی معمولاً متنباز (open source) نیستند؛ با این حال، یک استثنای مهم وجود دارد و آن هم Fuzzilli میباشد. این ابزار یکی از پیشرفتهترین فازرها در حوزه فازینگ جاوا اسکریپت (JavaScript fuzzing) به شمار میآید و بهطور فعال توسط مهندسان گوگل (Google) نگهداری و توسعه داده میشود.
4.8.1 آزمایش ۵: LibAFL
ما در این آزمایش، بررسی میکنیم که آیا مشاهدات و نتایج بهدستآمده در خصوص LibAFL نیز برقرار میباشند یا خیر. LibAFL به عنوان یک جایگزین نوین برای ++AFL توسعه یافته است و بهطور خاص به عنوان جانشینی برای LibFuzzer (که توسعه و پشتیبانی آن متوقف شده است) معرفی شده است. از آنجا که LibAFL اساساً با هدف ارائه یک کتابخانه فازینگ (Fuzzing Library) طراحی شده، نه یک فازر کامل و مستقل (Standalone Fuzzer)، برخلاف ++AFL فاقد یک پیادهسازی کامل از فازر و همچنین تنظیمات پیشفرض آماده برای اجرا است.
تنظیمات آزمایش. LibAFL در زمان انجام این مطالعه، دارای ۲۷ نسخه انتشاریافته میباشد که روند توسعه آن از آوریل ۲۰۲۱ آغاز شده است. در این پژوهش، ۱۰ نسخه از نقاط مختلف چرخه توسعه این فازر انتخاب شدند. انتخاب نسخهها از 0.4.0 که در سال ۲۰۲۱ منتشر شد و نخستین نسخهای است که یک مهار درونفرآیندی (in-process harness) برای اهداف FuzzBench ارائه میدهد، آغاز گردید.
این مهار چنین امکانی را فراهم میسازد که همان مجموعه اهداف مورد استفاده در آزمایشهای ++AFL را در این آزمایش نیز بهکار گیریم؛ موضوعی که قابلیت مقایسهپذیری مستقیم نتایج میان دو فازر را تسهیل میکند. همچنین، بر اساس مستندات موجود در مخزن گیت LibAFL، این مهار با بهینهترین تنظیمات قابل دستیابی برای فازر پیکربندی شده است.
نتایج. شکل ۹ میزان بهبود مهار LibAFL را در سراسر مجموعه اهدافِ مورد بررسی نشان میدهد. در این شکل، میانه (میانگین) میزان بهبود به همراه بازه صدک ۲۵ تا ۷۵ام (25th–75th percentile range) نسبت به نخستین نسخه انتخاب شده، یعنی نسخه 0.4.0، برای تمامی ده هدف آزمایشی ترسیم شده است. مطابق با مقادیر میانه، بیشترین میزان بهبود عملکرد بین نسخههای 0.4.0 و 0.9.0 مشاهده میشود؛ بهگونهای که میانه بهبود برابر با ٪۱۶ بوده و صدک ۷۵ام به ٪۲۵ میرسد. پس از این بازه، مقدار میانه تقریباً در سطح ۱۶٪ تثبیت شده است. نسخهای از این نمودار که شامل مقادیر خارج از دامنه بین چارکی (Interquartile Range – IQR) نیز هست، در پیوست ۱۶ ارائه شده است.
بهبود قابل توجه در نسخههای ابتدایی را میتوان به عوامل متعددی نسبت داد؛ از جمله ادغام و بهکارگیری تکنیکهای شناختهشده و اثباتشده از ++AFL، مانند CmpLog (از نسخه 0.4.0 تا نسخههای بعدی 0.9.0+)، mOpt (از نسخه 0.5.0 تا 0.8.0) و همچنین بهبود راهبردهای تخصیص توان (Power Schedules) در نسخه 0.6.0. افزون بر این، مجموعهای از اصلاحات و رفع اشکالهای مختلف در خود فازر نیز در این بهبود نقش داشتهاند.
به منظور نمایش روند کلی تغییرات، یک مدل رگرسیون خطی بر روی مقادیر میانه بهبود نسبی در نسخههای مختلف برازش (fitted) شد. نتایج حاکی از آن است که مدل حاصل یک روند مثبتِ متوسط را نشان میدهد (بهگونهایکه بهطور میانگین، به ازای هر نسخه، 1.53٪ افزایش در میزان بهبود نسبی مشاهده میشود) و مقدار ضریب تعیین آن (R²) برابر 0.55 است. این مقدار بیانگر آن است که بخش قابل توجهی از واریانس دادهها ناشی از تفاوتهای ساختاری و سیستماتیک میان اهداف آزمایشی است، نه صرفاً ناشی از پیشرفت نسخهها. به بیان دیگر، اگرچه نسخههای جدیدتر بهطور کلی موجب بهبود پوشش میشوند، اما این بهبودها از یک روند کاملاً خطی پیروی نکرده و میزان آنها در نسخههای مختلف متفاوت است.
۴.۸.۲ آزمایش ۶: Fuzzilli
بهطور بالقوه، مشاهدات ما ممکن است تحت تأثیر این واقعیت قرار گرفته باشند که فازرهای مورد بررسی توسط جامعه متنباز توسعه یافته و نگهداری میشوند. ما در این مطالعه به منظور رفع این نگرانی، یک فازر با نگهداری صنعتی نیز اضافه کردهایم که Fuzzilli میباشد. ما این فازر جاوااسکریپت را انتخاب کردیم، زیرا صنعت بهطور فعال یک فازر متنباز و عمومی را نگهداری نمیکند. با این حال، Fuzzilli به طور فعال توسعه و نگهداری میشود و به صورت مداوم برای فازینگ موتورهای جاوااسکریپت SpiderMonkey موزیلا و V8 گوگل مورد استفاده قرار میگیرد.
تنظیمات آزمایش. در این مطالعه، ۱۳ تغییرات ثبت شده (commit) از Fuzzilli انتخاب شد که کل بازه زمانی توسعه این فازر را پوشش میدهند. به منظور ارزیابی، از آخرین نسخههای موتورهای جاوااسکریپت مورد استفاده در مرورگرهای Chromium (V8) و Mozilla (SpiderMonkey) استفاده گردید. در طول زمان، قابلیتهای مختلفی از جمله معرفی جهشدهندهها (mutators) و کاهشدهندههای (reducers) جدید، گسترش پشتیبانی از زبان جاوااسکریپت و مجموعهای از بهینهسازیهای جزئی در پروفایلهای وابسته به موتورهای هدف به پایگاه کد Fuzzilli اضافه شده است. برخلاف ++AFL، بخش عمدهای از این قابلیتها بهصورت پیشفرض فعال میباشند، از این رو، نیازی به انتخاب یا پیکربندی دستی آنها پیش از اجرا نخواهد بود.
نتایج. شکل ۱۰ نتایج آزمایشهای مربوط به Fuzzilli را نشان میدهد. همانطور که در نمودار مشاهده میشود، میزان پوشش کد (coverage) به دستآمده در میان تغییرات ثبت (commit) و انتخاب شده افزایش مییابد. مشابه آزمایشهای قبلی، ما بهبود میانه را به همراه محدوده صدک 25 تا 75 در هر دو هدف ترسیم میکنیم. مقدار میانه طی دو سال ابتدایی توسعه، افزایش اندک اما پیوستهای داشت و به حدود ۲٪ رسید. پس از آن، در سال ۲۰۲۲ یک جهش قابل توجه تا حدود ۶.۵٪ را تجربه کرد و سپس روند کلی تقریباً ثابت ماند. مدل رگرسیون دارای شیبی برابر با 0.87٪ بهازای هر نسخه است و مقدار ضریب تعیین آن (R²) آن برابر با 0.86 میباشد. این نتایج نشاندهنده یک روند افزایشی منسجم بوده و بیانگر آن است که مدل بخش عمدهای از واریانس تغییرات را در میان نسخهها توضیح میدهد.
نکات کلیدی: مشاهدات ما، به ویژه L1 و L4، بهصورت کلیتر نیز برای LibAFL و Fuzzilli صادق هستند. شکل ۱۱ تمام میزان بهبودها را در طول زمان نشان میدهد: رشد اولیه و قوی LibAFL ناشی از پذیرش اولیه تکنیکهای اثبات شده و شناخته شده است.
۵. فراتحلیل متون علمی (Meta-Study of Scientific Literature)
ارزیابی ما از روند توسعه زمانی ++AFL نشان میدهد که طی چهار سال گذشته، این فازر دچار نوعی رکود (stagnation) شده و تنها در نسخههای اخیر بهبود جزئی داشته است. در همین بازه زمانی، تعداد زیادی مقاله پژوهشی در حوزه فازینگ عمومی و همهمنظوره (general-purpose fuzzing) منتشر شده است.
این عدم تطابق (discrepancy) یک پرسش پژوهشی طبیعی را مطرح میکند: ایدههای جدید ارائه شده در جامعه علمی فازینگ تا چه حد به عمل و ابزارهای واقعی راه پیدا میکنند؟ ما برای پاسخ به این سؤال، یک بررسی نظاممند (literature survey) از مقالات فازینگ منتشرشده در سالهای اخیر انجام دادیم. هدف ما این بود که بررسی کنیم آیا این پژوهشهای انجام شده در ++AFL ادغام شدهاند یا خیر و در صورت عدم ادغام، دلایل آن را مورد تحلیل قرار دهیم. در ادامه ابتدا روششناسی مطالعه را ارائه کرده و سپس نتایج به دست آمده را مورد بحث قرار میدهیم.
۵.۱ روششناسی (Methodology)
در این مطالعه، تمامی مقالات مرتبط با فازینگ که در بازه زمانی ۲۰۱۸ تا ۲۰۲۴ در مجلات و کنفرانسهای برتر امنیتی شامل USENIX Security، IEEE Symposium on Security and Privacy (S&P)، ACM CCS و NDSS، و همچنین در حوزه مهندسی نرمافزار شامل ICSE، FSE و ASE منتشر شده بودند، مورد بررسی قرار گرفت.
در این بررسی، تنها مقالاتی لحاظ شدند که مشارکت اصلی آنها ارائه یک تکنیک فازینگ باشد (به عنوان مثال یک زمانبند جدید (scheduler)، راهبرد جهش (mutation strategy)، یا معیار پوشش جدید (coverage metric)). مقالاتی که صرفاً از فازینگ به عنوان ابزار کمکی برای اهداف دیگر استفاده کرده بودند (مانند تولید ورودیهای متنوع (generating diverse inputs)) از این مجموعه حذف شدند.
در مجموع، جستوجوی ما منجر به شناسایی ۴۰۵ مقاله کاندید گردید. به منظور ارزیابی قابلیت ادغام عملی، این مجموعه را بیشتر به کارهایی که از ++AFL یا نسخه پیشین آن AFL به عنوان مبنا استفاده کرده بودند، محدود کردیم؛ زیرا اشتراک در پایگاه کد میتواند موانع ادغام را کاهش دهد. با این حال، لازم به ذکر است که استثناهایی نیز وجود داشتند؛ برای مثال، روش Redqueen با وجود آن که پیادهسازی آن مبتنی بر kAFL بود، توانسته است در نهایت ادغام شود.
با در نظر گرفتن این فرایض، در مجموع ۴۴ مقاله مبتنی بر AFL و ۱۶ مقاله مبتنی بر ++AFL شناسایی شدند (به جدول ۳ مراجعه کنید). به دلایل عملی، تنها کارهایی مورد بررسی قرار گرفتند که کد منبع آنها بهصورت عمومی در دسترس باشد، زیرا این موضوع برای پذیرش و استفاده مجدد از یک تکنیک اهمیت اساسی دارد. برای ۴۴ مقاله باقیمانده، از معیارهای توصیف شده در ادامه استفاده کردیم تا میزان قابلیت ادغام (integrability) آنها در نسخههای اصلی (upstream) از AFL یا ++AFL را ارزیابی کنیم.
جدول ۳: مقالات مبتنی بر AFL یا ++AFL. ارجاعات هایلایتشده (خاکستری) نشاندهنده مقالاتی هستند که کد منبع آنها بهصورت عمومی در دسترس نیست. ردیف آخر نیز تعداد مقالات دارای کد منبع / مجموع کل مقالات را خلاصه میکند:
معیارهای ادغام. قابلیت ادغام یک روش به عوامل زیر وابسته است:
- پیچیدگی تنظیمات و راهاندازی (Setup complexity): کیفیت مستندسازی و میزان وابستگی به ابزارهای خارجی.
- سازگاری با پایگاه کد (Code-base compatibility): میزان انطباق با ساختار ++AFL از نظر حالتها (modes)، گذرها (passes) و عملگرهای جهش mutators)، با حداقل تغییرات در کد.
- میزان سود در برابر پیچیدگی (Benefit vs. complexity): آیا بهبودهای حاصل از نظر آماری قابل توجه و توجیهکننده افزایش پیچیدگی اضافه شده میباشند یا خیر.
- عمومیت (Generality): میزان تطابق رویکرد با دامنه استفاده ++AFL، یعنی اینکه آیا اصول فازینگ همهمنظوره را دنبال میکند یا خیر.
به منظور اعمال این معیارها، هم مقاله و هم هرگونه آثار و خروجیهای تولید شده پژوهشی (artifact) در دسترس عموم (مانند مخازن GitHub) را مورد بررسی قرار دادیم. برای مثال، به منظور برآورد میزان پیچیدگی کد، بررسی کردیم که آیا نویسندگان مقدار کد اضافه شده به AFL یا ++AFL را گزارش کردهاند یا خیر، و در صورت وجود، آن را با جزئیات بیشتری در خروجی بررسی کردیم.
چنانچه در مقاله میزان تغییرات کد بهصورت دقیق مشخص نشده بود، مخزن مربوطه را کپی (clone) کرده و یک مقایسه (diff) نسبت به نسخه پایه (baseline) تولید کردیم. با این حال، این رویکرد برای همه مقالات قابل اعمال نبود؛ زیرا برخی تنها کد ناقص ارائه کردهاند، برخی دیگر نسخه یا تغییرات ثبت شده (commit) دقیق فازر پایه را مشخص نکردهاند، یا کد صرفاً بهصورت تصویر داکر (Docker images) یا یکپارچهسازی در FuzzBench منتشر شده است که همگی فرآیند تحلیل را پیچیدهتر میکند.
بر اساس این بررسی دستی، به هر کار یک امتیاز (score) برای برآورد احتمال ادغام آن در ++AFL اختصاص دادیم. اگرچه این فهرست بررسی (checklist) چارچوبی ساختاریافته برای ارزیابی هر کار فراهم میکند، اما امتیاز نهایی مبتنی بر قضاوت ما، تجربه پژوهشی، محتوای مقاله و آثار و خروجیهای تولید شده (artifact) آن بوده است. شایان ذکر است که دیگر پژوهشگران ممکن است به امتیازی متفاوت دست یابند.
جدول ۴: مقالات مبتنی بر AFL یا ++AFL، بههمراه ارزیابی میزان قابلیت ادغام آنها در ++AFL و نتیجه نهایی این ارزیابی:
۵.۲ نتایج (Results)
مطالعه نظاممند ما در مجموع منجر به شناسایی ۴۴ مقاله گردید و برای هر یک از آنها، طرح امتیازدهی قابلیت ادغام (integration scoring scheme) را اعمال کردیم. استفاده از AFL همانطور که در جدول ۳ نشان داده شده است، در سال ۲۰۲۰ به اوج خود رسیده است اما از سال ۲۰۲۱ به بعد، استفاده از ++AFL به طور بیشتری رواج یافت.
جالب توجه است که برخی از کارهای منتشرشده در سال ۲۰۲۴ همچنان بر اساس AFL که اکنون منسوخ شده است، انجام شدهاند. نتایج ارزیابی ما در جدول ۴ خلاصه شده است. بر اساس امتیازدهی انجامشده، ۱۷ مقاله به عنوان قابل ادغام شناسایی شدند، در حالی که ۲۷ مقاله باقیمانده با درجات مختلفی از امکانپذیری، بصورت بالقوه قابل ادغام میباشند. با این حال، برای اهداف این تحلیل، این دسته از مقالات به عنوان «غیرعملی برای ادغام» در نظر گرفته شدند. سپس این نتایج را با تلاشهای ادغام در ++AFL مقایسه کردیم و چهار نتیجهگیری متمایز را مشاهده نمودیم:
عدم امکانپذیری ادغام (۲۷ مقاله). این مقالات دارای اهداف یا مفروضات زیربنایی هستند که (بهطور قابل توجهی) از فلسفه فازینگ همهمنظوره در ++AFL فاصله دارند.
توجه میشود که ما Untracer (در جدول ۶) را از نظر عملی «غیرقابل ادغام» در نظر گرفته بودیم، اما ++AFL بهصورت جزئی آن را با ارائه یک فایل اسکلت (skeleton file) برای سازگاری ادغام کرده است؛ از این رو، آن را در شمار موارد ادغامشده لحاظ کردیم. تأکید میکنیم که این قضاوت به هیچ عنوان به معنای بیارزش بودن این پژوهشها نیست؛ بلکه صرفاً بیانگر آن است که تمرکز آنها با هسته طراحی ++AFL همراستا نیست. در ادامه، چهار دلیل اصلی برای دستهبندی مقالاتی که ادغام آنها غیرعملی تشخیص داده شده است را بیان میکنیم:
الف) دامنه مسئلهمحور (Domain-specific scope): یعنی تمرکز بر یک دامنه ورودی محدود یا یک کلاس خاص از «حملات» که با فلسفه «همهمنظوره و یکسان برای همه» (one-size-fits-all) در ++AFL ناسازگار است [16, 17, 45, 52, 53, 60, 67, 77, 79, 86].
ب) الزامات خارجی سنگین (Heavy external requirements): شامل تحلیلهای پرهزینه محاسباتی مانند اجرای نمادین (symbolic execution) یا ردیابی کامل وابستگی داده (full taint tracking) که با مدل سبک fork-server در AFL++ در تضاد میباشند [39, 41, 49, 51, 69, 75].
ج) پوشش داده شده توسط ++AFL: یعنی مسائلی که پیشتر بهصورت مستقل یا با روشهای مشابه حل شدهاند (اغلب در زمینه فازینگ فقط باینری) [50, 58, 59].
د) فازینگ هدایت شده یا مبتنی بر قیود (Directed / Invariant-driven fuzzing): فازینگ هدایت شده یا مبتنی بر قیود که فرآیند آزمون را به سمت نقاط مشخصی از برنامه هدایت میکند یا قیود خاصی را بر اجرای برنامه تحمیل مینماید؛ و در نتیجه هدفی را دنبال میکند که به طور اساسی با استراتژی پوشش گسترده (breadth-first coverage) در ++AFL تفاوت دارد [15, 43, 65, 76, 81, 82, 85].
تلاشهای ناموفق برای یکپارچهسازی (6 مقاله). مقالات قرارگرفته در این دسته [20، 21، 38، 48، 54، 74] که در جدول 4 با پسزمینه خاکستری مشخص شدهاند، از سوی توسعهدهندگان ++AFL به عنوان گزینههای بالقوه برای یکپارچهسازی مورد بررسی قرار گرفتند، اما در نهایت در این چارچوب ادغام نشدند. مجدداً تأکید میشود که این موضوع بههیچوجه بیانگر فقدان ارزش علمی یا فنی این پژوهشها نیست. طبقهبندی ارائه شده در این مطالعه بر مبنای منابع عمومی، از جمله گزارش مشکلات موجود در GitHub (issueها) و یا درخواستهای pull [91,92,93] و همچنین ارتباط مستقیم ما با توسعهدهندگان ++AFL انجام شده است.
برای مثال، EcoFuzz در ابتدا رویکردی امیدبخش به نظر میرسید، اما نتایج گزارش شده توسط آن با قابلیت اطمینان کافی قابل بازتولید نبودند [92]. همچنین FOX یکی دیگر از گزینههای پیشنهادی برای یکپارچهسازی بود، اما اعمال تغییراتی مانند غیرفعالسازی هرس کردن یال (edge pruning) [94] منجر به افزایش مصنوعی میزان پوشش (inflated coverage) شد؛ موضوعی که مانع از دستیابی این روش به بهبودهای ادعا شده گردید. افزون بر این، FairFuzz در مقایسه با خط مبنا (baseline) بهبودهای قابلتوجهی از خود نشان داد، اما تغییرات گسترده و پیچیدگی بالای کد منبع آن، ادغام کامل این روش را با چالش مواجه ساخت. با این وجود، این پژوهش الهامبخش توسعه یک راهبرد زمانبندی جدید مبتنی بر شاخههای نادر (rare-branch-based scheduling) در ++AFL گردید [91].
قابلیکپارچهسازی بالقوه (7 مقاله). ما این مقالات را به عنوان پژوهشهایی با قابلیت بالقوه برای ادغام در ++AFL در نظر گرفتیم، اگرچه تاکنون از سوی توسعهدهندگان ++AFL مورد پذیرش و استفاده قرار نگرفتهاند. این پژوهشها از نظر رویکرد طراحی، همراستایی قابلتوجهی با فلسفه طراحی ++AFL دارند و عمدتاً از طریق ارائه راهبردهای جهش جدید (new mutation strategies) [19, 66, 73, 87]، یا سازوکارهای بازخوردی (feedback mechanisms)، [64, 68, 84] این همسویی را نشان میدهند.
اگرچه این مطالعات از منظر فنی امیدوارکننده به نظر میرسند، ممکن است با اولویتها و ملاحظات عملی توسعهدهندگان ++AFL همخوانی کامل نداشته باشند. با این حال، با قطعیت نمیتوان مشخص کرد که آیا این مقالات اساساً برای یکپارچهسازی مورد ارزیابی قرار گرفتهاند، یا اینکه از منظر کاربرد عملی، تأثیرگذاری کافی برای توجیه پذیرش و ادغام در شاخه اصلی (upstream) را نداشتهاند.
ادغام شده در ++AFL (6 مقاله). این دسته شامل پژوهشهایی است که قابلیتها و دستاوردهای آنها به صورت کامل [23, 89, 90] یا جزئی [38, 42, 44] در AFL++ ادغام شدهاند. اگرچه این فهرست تنها شامل سه مقاله با ادغام کامل و سه مقاله با ادغام جزئی است، اما ++AFL در عمل طیف بسیار گستردهتری از قابلیتها و تکنیکها را در بر میگیرد.
بخش قابلتوجهی از این قابلیتها ریشه در پژوهشهایی دارند که مبتنی بر AFL یا ++AFL نبودهاند، یا در مجلات و کنفرانسهای سطحبالای حوزه امنیت و مهندسی نرمافزار منتشر نشدهاند؛ ازاینرو، در محدوده تحلیل ادبیات پژوهشی حاضر قرار نگرفتهاند. برای دستیابی به دیدگاهی جامعتر درباره منشأ قابلیتها و تکنیکهای ادغامشده، خواننده به پیوست 6 ارجاع داده میشود؛ بخشی که منشأ توسعه و ادغام ویژگیها و تکنیکهای مختلف را بهصورت نظاممند ردیابی و مستندسازی کرده است.
5.3 آموختهها (Lessons Learned)
همانگونه که در بخش 4.7 مورد بحث قرار گرفت، نسخههای ++AFL که پس از نسخه 3.0c منتشر شدند، تنها بهبودهایی محدود و عمدتاً وابسته به هدف (target-specific) ایجاد کردند؛ هرچند در بازه میان نسخههای 4.21c تا 4.32c افزایش عملکرد محسوستری مشاهده شد. فراتحلیل (meta-study) انجام شده در این پژوهش روشن میسازد که چرا این وضعیت سکون یا رکود (plateau) برای مدت طولانی تداوم یافته و همچنان به عنوان مانعی اساسی باقی مانده است: با وجود آنکه ادبیات پژوهشی حوزه فازینگ مملو از ایدهها و رویکردهای نوین است، تنها تعداد محدودی از این پژوهشها قادرند الزامات و محدودیتهای عملی لازم برای پذیرش و ادغام در شاخه اصلی توسعه (upstream adoption) را برآورده سازند. با این حال، در صورت پذیرش و ادغام، پژوهشهای حوزه فازینگ میتوانند واقعاً سطح فناوری موجود (state of the art) را ارتقا دهند؛ همانگونه که این موضوع در معرفی مرحله قطعی (deterministic stage) جدید، برگرفته از MendelFuzz [89]، بهوضوح مشاهده میشود.
در نهایت، شکل 12 و جدول 6 در پیوست نشان میدهند که بخش عمدهای از قابلیتهایی که در ++AFL ادغام شده و موفقیت عملی خود را اثبات کردهاند، الزاماً منشأ خود را از کنفرانسهای تراز اول حوزه امنیت و مهندسی نرمافزار نگرفتهاند؛ بلکه برخی از آنها از کارگاههای علمی (workshops) [95]، مجلات علمی [96]، یا حتی مشارکتهای فردی و صنعتی [29، 97، 98، 99، 100] سرچشمه گرفتهاند. علاوه بر این، هم جدول و هم شکل مذکور نشان میدهند که تمرکز پژوهشهای ادغام شده طی سالهای اخیر، از دستههای ویژگیها (features)، بهبودها (improvements) و کاربردهای خاص (special use cases)، بهتدریج به سمت دسته اخیر، یعنی کاربردهای خاص، سوق یافته است. در مجموع، از این مطالعه سه درس کلیدی استخراج میشود:
L5– نوآوری و اعتبار علمی، بهتنهایی کافی نیستند. ارزش علمی یک تکنیک یا حتی انتشار آن در مجامع علمی تراز اول، در صورتی که آن تکنیک موجب اختلال در مدل forkserver، لایه انتزاعی (abstraction layer)، یا مستلزم استفاده از موتورهای جانبی سنگین (heavyweight side engines) باشد، تأثیر چندانی بر پذیرش و ادغام آن در ++AFL ندارد. در مقابل، بسیاری از قابلیتهایی که با موفقیت در ++AFL ادغام شدهاند، از کارگاههای علمی، مجلات پژوهشی، بخش صنعت، یا حتی مشارکتهای فردی نشات گرفتهاند. این موضوع به روشنی نشان میدهد که در عمل، قابلیت یکپارچهسازی عملی (practical integrability) و نه صرفاً میزان نوآوری یا اعتبار محل انتشار، عامل تعیینکننده اصلی در پذیرش و بهکارگیری یک تکنیک است.
L6 – قابلیت ادغام در مقابل دستاوردهای حاشیهای. پژوهشهایی که بهبودهایی محدود اما قابلتکرار (repeatable) ارائه میدهند و در عین حال تنها به تغییرات جزئی در کد نیاز دارند (به عنوان مثال افزودن جهشگرهای جدید (new mutators) یا زمانبندهای سبک (lightweight schedulers)) در مقایسه با بازنویسیهای پیچیدهای که افزایش سرعت دو رقمی را صرفاً بر روی یک بنچمارک خاص (niche benchmark) وعده میدهند، احتمال بسیار بیشتری برای ادغام در ++AFL دارند. نکتهای برخلاف انتظار این است که دقیقاً همان پژوهشهایی که ادعای نوآوری کمتری دارند و در نتیجه ممکن است در فرایند داوری علمی کمتر مورد توجه قرار گیرند، در عمل قادرند بهبودهایی ارائه دهند که واقعاً موجب پیشرفت محسوس و اثرگذار در کاربردهای عملی شوند.
L7 – بازتولیدپذیری بهعنوان دروازهبان پذیرش. بیش از یکسوم از پژوهشهای بررسی شده هیچگونه آثار و خروجیهای تولید شده (artifact) یا بسته قابلبازتولید ارائه نمیدهند، بهطوریکه ادغام و بازتولید نتایج عملاً غیرممکن میشود. در مورد چهار مورد از شش کاندیدای ادغام، بهبودهای مورد انتظار که در مقاله گزارش شده بودند، هنگام تلاش توسعهدهندگان برای یکپارچهسازی در ++AFL محقق نشدند. اگرچه پذیرش رویکرد ارزیابی آثار و خروجیهای تولید شده پژوهشی (artifact evaluation) در جامعه امنیت میتواند به بهبود دسترسپذیری و کیفیت دادههای پژوهشی منجر شود، اما ارزیابیهای فعلی در حوزه فازینگ اغلب در نشان دادن میزان مقیاسپذیری (scalability) روشها نسبت به اهداف جدید (new targets) یا محیطهای اجرایی متفاوت (different environments) ناکام میباشند.
نتایج ما بیانگر آن است که تکرارپذیری یا قابلیت بازتولید (reproducibility)، نقش کلیدی در پر کردن شکاف میان پژوهش و عمل ایفا میکند، زیرا امکان ارزیابی دقیق و نظاممند و همچنین پیشرفت تجمعی علم (cumulative scientific progress) را فراهم میسازد.
۶ بحث و محدودیتها (Discussion and Limitations)
در این بخش، به بازاندیشی درباره پیامدهای گستردهتر یافتههای خود و همچنین محدودیتهای روششناسی و دامنه پژوهش میپردازیم.
مقایسهپذیری ++AFL و LibAFL. اگرچه مقایسه مستقیم نتایج فازرها در نگاه اول وسوسهبرانگیز است، اما روششناسی ما که به جای مقایسه مطلق، به سنجش میزان بهبود نسبت به پیکربندی پایه هر فازر میپردازد، امکان چنین مقایسهای را فراهم نمیسازد؛ زیرا مفروضات و سناریوهای استفاده در میان فازرها با یکدیگر متفاوت هستند. برای مثال، ++AFL در پلتفرم FuzzBench با یک پیکربندی پایه اجرا میشود، در حالی که توسعهدهندگان LibAFL ترجیح دادهاند یک مهار بهینه (optimal harness) را حفظ کنند. از اینرو، نمیتوان نتیجهگیری قطعی داشت که آیا LibAFL بهطور کلی برتر از ++AFL است یا خیر، زیرا این مقایسه به مجموعهای از مفروضات پنهان و وابسته به پیکربندیهای مورد استفاده محدود میشود.
همچنین، رشد اولیه و نسبتاً سریع بهبود در LibAFL ممکن است ناشی از یک مرحله آغازین «افزایش» (ramp-up phase) باشد؛ دورهای که در آن قابلیتهای اثبات شده از سایر فازرها اضافه شده و سطح بلوغ سیستم بهطور کلی افزایش مییابد. در مقابل، ++AFL که از شاخهای بالغ از AFL منشعب شده است، چنین مرحله آغازین افزایشی و پرشتاب را تجربه نکرده است.
کاملبودن مطالعه ادبیات پژوهشی و فیلترسازی مقالات. ما تمرکز خود را بر مجلات و کنفرانسهای سطح A در حوزه مهندسی نرمافزار و امنیت [101] قرار دادیم، زیرا این مجامع استانداردهای روششناختی جامعه را تعیین میکنند (برای مثال، معمولاً الزامات سختگیرانهای برای ارزیابی و بازتولیدپذیری اعمال میکنند). با این حال، این انتخاب موجب حذف ایدههای ارزشمند موجود در کنفرانسهای کوچکتر، مجلات تخصصیتر و کارگاههای علمی (workshops) میشود. فرآیند انتخاب مقالات از طریق فیلترسازی کلیدواژهای (keyword filtering)، حذف موارد تکراری (deduplication) و بازبینی دستی انجام شد. این رویکرد اگرچه فرآیند را کارآمدتر و ساختاریافتهتر میکند، اما ممکن است منجر به از دست رفتن پژوهشهای کمتر دیده شده شود. همچنین، تحلیل ما به ابزارهای مبتنی بر AFL و ++AFL محدود شد تا امکان سنجش و امتیازدهی یکپارچهسازی به صورت سازگار فراهم گردد؛ موضوعی که میتواند موجب حذف برخی آثار مهم مانند Redqueen [24] شود. مطالعات آینده میتوانند دامنه بررسی را گسترش داده و سایر پایههای مرجع (baselines) و مجامع انتشاراتی را نیز در تحلیل وارد کنند.
امتیازدهی ادغامپذیری یا قابلیت یکپارچهسازی (Integrability Scoring). ما امکان یکپارچهسازی مقالات حوزه فازینگ را در ++AFL با در نظر گرفتن عواملی همچون دسترسپذیری آثار و خروجیهای تولید شده (artifact availability)، پیچیدگی کد (code complexity)، مدیریت ساخت و وابستگیها (build and dependency management)، کیفیت مستندسازی (documentation quality)، تاریخچه بهروزرسانی (update history) و دادههای عملکرد گزارش شده (reported performance data) ارزیابی کردیم. لازم به تأکید است که ما فازرها را کامپایل یا اجرا نکردهایم؛ بنابراین امتیازهای ارائه شده صرفاً مبتنی بر قضاوتهای سطحبالا (high-level judgments) هستند و باید به عنوان شاخصهای راهنما (indicative measures) در نظر گرفته شوند، نه نتیجهگیریهای قطعی (definitive verdicts).
۷. نتیجهگیری (Conclusion)
ما در این مقاله، یک ارزیابی جامع از روند تکامل ++AFL ارائه دادیم و قابلیت یکپارچهسازی پژوهشهای جدید حوزه فازینگ را در این فازر پیشرفته بررسی کردیم. مطالعه ما که بازهای هفتساله را پوشش میدهد، نشان میدهد که اثربخشی کلی فازینگ از نظر پوشش کد (code coverage) تا حد زیادی به یک حالت سکون یا رکود (plateau) رسیده است. اگرچه تغییرات منفرد میتوانند بهبودهای قابل اندازهگیری را روی اهداف خاص (specific targets) ایجاد کنند، اما اثر ترکیبی آنها به صورت پایدار و قابل تعمیم در مجموعهای متنوع از برنامهها مقیاسپذیر نیست. با بررسی LibAFL و Fuzzilli مشاهده میکنیم که این پدیده محدود به ++AFL نبوده و در سایر فازرهای پیشرفته نیز قابل مشاهده است.
در گذشته، بسیاری از مقالات فازینگ اهداف عمومی یا همه منظوره (general-purpose fuzzing) بهبودهای عملکردی قابلتوجهی نسبت به مبنای مقایسه (baseline) خود گزارش کردهاند، اما در سالهای اخیر، افزایشهای دو رقمی در پوشش کد (double-digit coverage gains) به پدیدهای نادر تبدیل شده است.
هنگامی که تکنیکهای جدید در ارزیابیهای عملی مجدداً بررسی میشوند (رجوع شود به جدول 4)، اغلب تنها بهبودهایی جزئی یا از نظر آماری نامعقول (statistically insignificant) ارائه میدهند. این امر نشان میدهد که فازینگ عمومی ممکن است به نقطهای از بازده نزولی (diminishing returns) رسیده باشد؛ به این معنا که میوههای در دسترس و کمهزینه (low-hanging fruits) —که اغلب ماهیتی ساده داشتند و در عمل نیز در بهینهسازی کارایی و اثربخشی بازخورد پوشش (coverage feedback) موفق بودهاند— تا حد زیادی مورد کاوش قرار گرفتهاند.
ما این وضعیت را به عنوان فراخوانی برای اقدام (call to action) در جامعه فازینگ تلقی میکنیم. پژوهشهای آتی برای عبور از رکود فعلی (plateau)، احتمالاً نیازمند طراحی رویکردهایی تخصصیتر یا نوآورانه بنیادین میباشند، نه صرفاً ادامه بهینهسازی فازرهای عمومی موجود (general-purpose fuzzers). در نهایت، لازم است بر سه محور کلیدی تأکید شود: تکرارپذیری یا قابلیت بازتولید (reproducibility)، قابلیت یکپارچهسازی در شاخه اصلی توسعه (upstream integrability)، و ارتباط عملی و کاربردی (practical relevance).
منابع
[1] Karl Popper. The Logic of Scientific Discovery. Routledge, 2005.
[2] Peter McCulloch, Douglas G Altman, W Bruce Campbell, David R Flum, Paul Glasziou, John C Marshall, and Jon Nicholl. No surgical innovation without evaluation: the IDEAL recommendations. The Lancet, 374(9695), 2009.
[3] John PA Ioannidis. Why Most Published Research Findings are False. PLoS Medicine, 2(8), 2005.
[4] Thomas S. Kuhn. The Structure of Scientific Revolutions. University of Chicago Press, 1970.
[5] Cormac Herley and P.C. Van Oorschot. SoK: Science, Security and the Elusive Goal of Security as a Scientific Pursuit. In IEEE Symposium on Security and Privacy (S&P), 2017.
[6] Xiaogang Zhu, Sheng Wen, Seyit Camtepe, and Yang Xiang. Fuzzing: A Survey for Roadmap. ACM Computing Surveys (CSUR), 54(11s), 2022.
[7] Valentin JM Manès, HyungSeok Han, Choongwoo Han, Sang Kil Cha, Manuel Egele, Edward J Schwartz, and Maverick Woo. The Art, Science, and Engineering of Fuzzing: A Survey. IEEE Transactions on Software Engineering, 47(11), 2019.
[8] Google. OSS-Fuzz: Continuous Fuzzing for Open Source Software. https://github.com/google/oss-fuzz.
[9] Moritz Schloegel, Nils Bars, Nico Schiller, Lukas Bernhard, Tobias Scharnowski, Addison Crump, Arash Ale-Ebrahim, Nicolai Bissantz, Marius Muench, and Thorsten Holz. SoK: Prudent Evaluation Practices for Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2024.
[10] Michał Zalewski. American Fuzzy Lop. http://lcamtuf.coredump.cx/afl/. Accessed: January 20, 2026.
[11] Marcel Böhme, László Szekeres, and Jonathan Metzman. On the Reliability of Coverage-Based Fuzzer Benchmarking. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2022
[12] George Klees, Andrew Ruef, Benji Cooper, Shiyi Wei, and Michael Hicks. Evaluating Fuzz Testing. In ACM Conference on Computer and Communications Security (CCS), 2018.
[13] Jonathan Metzman, László Szekeres, Laurent Simon, Read Sprabery, and Abhishek Arya. FuzzBench: An Open Fuzzer Benchmarking Platform and Service. In ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE), 2021.
[14] Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. AFL++: Combining Incremental Steps of Fuzzing Research. In USENIX Workshop on Offensive Technologies (WOOT), 2020.
[15] Andrea Fioraldi, Daniele Cono D’Elia, and Davide Balzarotti. The Use of Likely Invariants as Feedback for Fuzzers. In USENIX Security Symposium, 2021.
[16] Xiaogang Zhu and Marcel Böhme. Regression Greybox Fuzzing. In ACM Conference on Computer and Communications Security (CCS), 2021.
[17] Zhiyuan Jiang, Shuitao Gan, Adrian Herrera, Flavio Toffalini, Lucio Romerio, Chaojing Tang, Manuel Egele, Chao Zhang, and Mathias Payer. Evocatio: Conjuring Bug Capabilities from a Single PoC. In ACM Conference on Computer and Communications Security (CCS), 2022.
[18] Nils Bars, Moritz Schloegel, Tobias Scharnowski, Nico Schiller, and Thorsten Holz. Fuzztruction: Using Fault Injection-based Fuzzing to Leverage Implicit Domain Knowledge. In USENIX Security Symposium, 2023.
[19] Myungho Lee, Sooyoung Cha, and Hakjoo Oh. Learning Seed-Adaptive Mutation Strategies for Greybox Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2023.
[20] Han Zheng, Jiayuan Zhang, Yuhang Huang, Zezhong Ren, He Wang, Chunjie Cao, Yuqing Zhang, Flavio Toffalini, and Mathias Payer. FISHFUZZ: Catch Deeper Bugs by Throwing Larger Nets. In USENIX Security Symposium, 2023.
[21] Dongdong She, Adam Storek, Yuchong Xie, Seoyoung Kweon, Prashast Srivastava, and Suman Jana. Fox: Coverage-guided Fuzzing as Online Stochastic Control. In ACM Conference on Computer and Communications Security (CCS), 2024.
[22] Marcel Böhme, Van-Thuan Pham, and Abhik Roychoudhury. Coverage-based Greybox Fuzzing as Markov Chain. In ACM Conference on Computer and Communications Security (CCS), 2016.
[23] Chenyang Lyu, Shouling Ji, Chao Zhang, Yuwei Li, Wei-Han Lee, Yu Song, and Raheem Beyah. MOPT: Optimized Mutation Scheduling for Fuzzers. In USENIX Security Symposium, 2019.
[24] Cornelius Aschermann, Sergej Schumilo, Tim Blazytko, Robert Gawlik, and Thorsten Holz. REDQUEEN: Fuzzing with Input-to-State Correspondence. In Symposium on Network and Distributed System Security (NDSS), 2019.
[25] kdsjZh. Enhancement on Deterministic stage. https://github.com/AFLplusplus/AFLplusplus/pull/1972. Accessed: January 20, 2026.
[26] AFLplusplus. AFLplusplus. https://github.com/AFLplusplus/AFLplusplus. Accessed: January 20, 2026.
[27] Andrea Fioraldi, Alessandro Mantovani, Dominik Maier, and Davide Balzarotti. Dissecting American Fuzzy Lop: A Fuzzbench Evaluation. ACM Transactions on Software Engineering and Methodology (TOSEM), 32(2):1–26, 2023.
[28] Sergej Schumilo, Cornelius Aschermann, Ali Abbasi, Simon Wörner, and Thorsten Holz. Nyx: Greybox Hypervisor Fuzzing using Fast Snapshots and Affine Types. In USENIX Security Symposium, 2021.
[29] lafintel. Circumventing Fuzzing Roadblocks with Compiler Transformations. https://lafintel.wordpress.com/. Accessed: January 20, 2026.
[30] Google. American Fuzzy Lop. https://github.com/google/AFL. Accessed:January 20, 2026.
[31] LLVM. SanitizerCoverage. https://clang.llvm.org/docs/SanitizerCoverage.html. Accessed: January 20, 2026.
[32] fuzzbench.com. FuzzBench Reports. https://www.fuzzbench.com/reports/. Accessed: January 20, 2026.
[33] vanhauser thc. FuzzBench - Better Coverage Benchmarks. https://github.com/google/fuzzbench/issues/1794. Accessed: January 20, 2026.
[34] Andrea Fioraldi, Dominik Christian Maier, Dongjia Zhang, and Davide Balzarotti. LibAFL: A Framework to Build Modular and Reusable Fuzzers. In ACM Conference on Computer and Communications Security (CCS), 2022.
[35] Samuel Groß, Simon Koch, Lukas Bernhard, Thorsten Holz, and Martin Johns. FUZZILLI: Fuzzing for JavaScript JIT Compiler Vulnerabilities. In Symposium on Network and Distributed System Security (NDSS), 2023.
[36] Google Project Zero. Fuzzilli. https://github.com/googleprojectzero/fuzzilli. Accessed: January 20, 2026.
[37] Sergej Schumilo, Cornelius Aschermann, Robert Gawlik, Sebastian Schinzel, and Thorsten Holz. kAFL: Hardware-Assisted Feedback Fuzzing for OS Kernels. In USENIX Security Symposium, 2017.
[38] Caroline Lemieux and Koushik Sen. FairFuzz: A Targeted Mutation Strategy for Increasing Greybox Fuzz Testing Coverage. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2018.
[39] Insu Yun, Sangho Lee, Meng Xu, Yeongjin Jang, and Taesoo Kim. QSYM: A Practical Concolic Execution Engine Tailored for Hybrid Fuzzing. In USENIX Security Symposium, 2018.
[40] Hongxu Chen, Yinxing Xue, Yuekang Li, Bihuan Chen, Xiaofei Xie, Xiuheng Wu, and Yang Liu. Hawkeye: Towards a Desired Directed Grey-box Fuzzer. In ACM Conference on Computer and Communications Security (CCS), 2018.
[41] Mingi Cho, Seoyoung Kim, and Taekyoung Kwon. Intriguer: Field-Level Constraint Solving for Hybrid Fuzzing. In ACM Conference on Computer and Communications Security (CCS), 2019.
[42] Stefan Nagy and Matthew Hicks. Full-Speed Fuzzing: Reducing Fuzzing Overhead through Coverage-Guided Tracing. In IEEE Symposium on Security and Privacy (S&P), 2019.
[43] Shirin Nilizadeh, Yannic Noller, and Corina S. Pasareanu. DifFuzz: Differential Fuzzing for Side-channel Analysis. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2019.
[44] Junjie Wang, Bihuan Chen, Lei Wei, and Yang Liu. Superion: Grammar-aware Greybox Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2019.
[45] Wen Xu, Hyungon Moon, Sanidhya Kashyap, Po-Ning Tseng, and Taesoo Kim. Fuzzing File Systems via Two-Dimensional Input Space Exploration. In IEEE Symposium on Security and Privacy (S&P), 2019.
[46] Wei You, Xuwei Liu, Shiqing Ma, David Mitchel Perry, Xiangyu Zhang, and Bin Liang. SLF: Fuzzing without Valid Seed Inputs. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2019.
[47] Wei You, Xueqiang Wang, Shiqing Ma, Jianjun Huang, Xiangyu Zhang, XiaoFeng Wang, and Bin Liang. ProFuzzer: On-the-fly Input Type Probing for Better Zero-Day Vulnerability Discovery. In IEEE Symposium on Security and Privacy (S&P), 2019.
[48] Cornelius Aschermann, Sergej Schumilo, Ali Abbasi, and Thorsten Holz. Ijon:Exploring Deep State Spaces via Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2020.
[49] Yaohui Chen, Peng Li, Jun Xu, Shengjian Guo, Rundong Zhou, Yulong Zhang, Tao Wei, and Long Lu. SAVIOR: Towards Bug-Driven Hybrid Testing. In IEEE Symposium on Security and Privacy (S&P), 2020.
[50] Sushant Dinesh, Nathan Burow, Dongyan Xu, and Mathias Payer. RetroWrite:Statically Instrumenting COTS Binaries for Fuzzing and Sanitization. In IEEE Symposium on Security and Privacy (S&P), 2020.
[51] Yannic Noller, Corina S. Pasareanu, Marcel Böhme, Youcheng Sun, Hoang Lam Nguyen, and Lars Grunske. HyDiff: Hybrid Differential Software Analysis. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2020.
[52] Yanhao Wang, Xiangkun Jia, Yuwei Liu, Kyle Zeng, Tiffany Bao, Dinghao Wu, and Purui Su. Not All Coverage Measurements Are Equal: Fuzzing by Coverage Accounting for Input Prioritization. In Symposium on Network and Distributed System Security (NDSS), 2020
[53] Cheng Wen, Haijun Wang, Yuekang Li, Shengchao Qin, Yang Liu, Zhiwu Xu, Hongxu Chen, Xiaofei Xie, Geguang Pu, and Ting Liu. MemLock: Memory Usage Guided Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2020.
[54] Tai Yue, Pengfei Wang, Yong Tang, Enze Wang, Bo Yu, Kai Lu, and Xu Zhou. EcoFuzz: Adaptive Energy-Saving Greybox Fuzzing as a Variant of the Adversarial Multi-Armed Bandit. In USENIX Security Symposium, 2020.
[55] Hongxu Chen, Shengjian Guo, Yinxing Xue, Yulei Sui, Cen Zhang, Yuekang Li, Haijun Wang, and Yang Liu. MUZZ: Thread-aware Grey-box Fuzzing for Effective Bug Hunting in Multithreaded Programs. In USENIX Security Symposium, 2020.
[56] Haijun Wang, Xiaofei Xie, Yi Li, Cheng Wen, Yuekang Li, Yang Liu, Shengchao Qin, Hongxu Chen, and Yulei Sui. Typestate-guided Fuzzer for Discovering Useafter-free Vulnerabilities. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2020.
[57] Chijin Zhou, Mingzhe Wang, Jie Liang, Zhe Liu, and Yu Jiang. Zeror: Speed Up Fuzzing with Coverage-sensitive Tracing and Scheduling. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2020.
[58] Stefan Nagy, Anh Nguyen-Tuong, Jason D. Hiser, Jack W. Davidson, and Matthew Hicks. Breaking Through Binaries: Compiler-quality Instrumentation for Better Binary-only Fuzzing. In USENIX Security Symposium, 2021.
[59] Stefan Nagy, Anh Nguyen-Tuong, Jason D. Hiser, Jack W. Davidson, and Matthew Hicks. Same Coverage, Less Bloat: Accelerating Binary-only Fuzzing with Coverage-preserving Coverage-guided Tracing. In ACM Conference on Computer and Communications Security (CCS), 2021.
[60] Gaoning Pan, Xingwei Lin, Xuhong Zhang, Yongkang Jia, Shouling Ji, Chunming Wu, Xinlei Ying, Jiashui Wang, and Yanjun Wu. V-Shuttle: Scalable and Semantics-Aware Hypervisor Virtual Device Fuzzing. In ACM Conference on Computer and Communications Security (CCS), 2021.
[61] Xinyang Ge, Ben Niu, Robert Brotzman, Yaohui Chen, HyungSeok Han, Patrice Godefroid, and Weidong Cui. HyperFuzzer: An Efficient Hybrid Fuzzer for Virtual CPUs. In ACM Conference on Computer and Communications Security (CCS), 2021.
[62] Gwangmu Lee, Woochul Shim, and Byoungyoung Lee. Constraint-guided Directed Greybox Fuzzing. In USENIX Security Symposium, 2021.
[63] Christopher Salls, Chani Jindal, Jake Corina, Christopher Kruegel, and Giovanni Vigna. Token-Level Fuzzing. In USENIX Security Symposium, 2021.
[64] Jinghan Wang, Chengyu Song, and Heng Yin. Reinforcement Learning-based Hierarchical Seed Scheduling for Greybox Fuzzing. In Symposium on Network and Distributed System Security (NDSS), 2021.
[65] Zhengjie Du, Yuekang Li, Yang Liu, and Bing Mao. Windranger: A Directed Greybox Fuzzer driven by Deviation Basic Blocks. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2022.
[66] Chenyang Lyu, Shouling Ji, Xuhong Zhang, Hong Liang, Binbin Zhao, Kangjie Lu, and Raheem Beyah. EMS: History-Driven Mutation for Coverage-based Fuzzing. In Symposium on Network and Distributed System Security (NDSS), 2022.
[67] Ruijie Meng, Zhen Dong, Jialin Li, Ivan Beschastnikh, and Abhik Roychoudhury. Linear-time Temporal Logic guided Greybox Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2022.
[68] Yuanping Yu, Xiangkun Jia, Yuwei Liu, Yanhao Wang, Qian Sang, Chao Zhang, and Purui Su. HTFuzz: Heap Operation Sequence Sensitive Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2022.
[69] Penghui Li, Wei Meng, and Kangjie Lu. SEDiff: Scope-aware Differential Fuzzing to Test Internal Function Models in Symbolic Execution. In ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE), 2022.
[70] Cheolwoo Myung, Gwangmu Lee, and Byoungyoung Lee. MundoFuzz: Hypervisor Fuzzing with Statistical Coverage Testing and Grammar Inference. In USENIX Security Symposium, 2022.
[71] Gen Zhang, Pengfei Wang, Tai Yue, Xiangdong Kong, Shan Huang, Xu Zhou, and Kai Lu. MobFuzz: Adaptive Multi-objective Optimization in Gray-box Fuzzing. In Symposium on Network and Distributed System Security (NDSS), 2022.
[72] Jingzhou Fu, Jie Liang, Zhiyong Wu, Mingzhe Wang, and Yu Jiang. Griffin:Grammar-Free DBMS Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2022.
[73] Peng Deng, Zhemin Yang, Lei Zhang, Guangliang Yang, Wenzheng Hong, Yuan Zhang, and Min Yang. NestFuzz: Enhancing Fuzzing with Comprehensive Understanding of Input Processing Logic. In ACM Conference on Computer and Communications Security (CCS), 2023.
[74] Patrick Jauernig, Domagoj Jakobovic, Stjepan Picek, Emmanuel Stapf, and Ahmad-Reza Sadeghi. DARWIN: Survival of the Fittest Fuzzing Mutators. In Symposium on Network and Distributed System Security (NDSS), 2023.
[75] Ling Jiang, Hengchen Yuan, Mingyuan Wu, Lingming Zhang, and Yuqun Zhang. Evaluating and Improving Hybrid Fuzzing. In ACM/IEEE International Conference on Automated Software Engineering (ASE), 2023.
[76] Tae Eun Kim, Jaeseung Choi, Kihong Heo, and Sang Kil Cha. DAFL: Directed Grey-box Fuzzing guided by Data Dependency. In USENIX Security Symposium, 2023.
[77] Dawei Wang, Ying Li, Zhiyu Zhang, and Kai Chen. CarpetFuzz: Automatic Program Option Constraint Extraction from Documentation for Fuzzing. In USENIX Security Symposium, 2023.
[78] Yilun Wu, Tong Zhang, Changhee Jung, and Dongyoon Lee. DEVFUZZ: Automatic Device Model-Guided Device Driver Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2023.
[79] Wen Li, Jinyang Ruan, Guangbei Yi, Long Cheng, Xiapu Luo, and Haipeng Cai. PolyFuzz: Holistic Greybox Fuzzing of Multi-Language Systems. In USENIX Security Symposium, 2023.
[80] Jiawei Yin, Menghao Li, Yuekang Li, Yong Yu, Boru Lin, Yanyan zou, Yang Liu, Wei Huo, and Jingling Xue. RSFuzzer: Discovering Deep SMI Handler Vulnerabilities in UEFI Firmware with Hybrid Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2023.
[81] Heqing Huang, Peisen Yao, Hung-Chun Chiu, Yiyuan Guo, and Charles Zhang. Titan: Efficient Multi-target Directed Greybox Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2024.
[82] Yujian Zhang, Yaokun Liu, Jinyu Xu, and Yanhao Wang. Predecessor-aware Directed Greybox Fuzzing. In IEEE Symposium on Security and Privacy (S&P), 2024.
[83] Xuwei Liu, Wei You, Yapeng Ye, Zhuo Zhang, Jianjun Huang, and Xiangyu Zhang. FuzzInMem: Fuzzing Programs via In-memory Structures. In International Conference on Software Engineering (ICSE), 2024.
[84] Pietro Borrello, Andrea Fioraldi, Daniele Cono D’Elia, Davide Balzarotti, Leonardo Querzoni, and Cristiano Giuffrida. Predictive Context-sensitive Fuzzing. In Symposium on Network and Distributed System Security (NDSS), 2024.
[85] Huanyao Rong, Wei You, Xiaofeng Wang, and Tianhao Mao. Toward Unbiased Multiple-Target Fuzzing with Path Diversity. In USENIX Security Symposium, 2024.
[86] Yupeng Yang, Yongheng Chen, Rui Zhong, Jizhou Chen, and Wenke Lee. Towards Generic Database Management System Fuzzing. In USENIX Security Symposium, 2024.
[87] Kunpeng Zhang, Xiaogang Zhu, Xi Xiao, Minhui Xue, Chao Zhang, and Sheng Wen. ShapFuzz: Efficient Fuzzing via Shapley-Guided Byte Selection. In Symposium on Network and Distributed System Security (NDSS), 2024.
[88] Kelin Wang, Mengda Chen, Liang He, Purui Su, Yan Cai, Jiongyi Chen, Bin Zhang, Chao Feng, and Chaojing Tang. OSmart: Whitebox Program Option Fuzzing. In ACM Conference on Computer and Communications Security (CCS), 2024.
[89] Han Zheng, Flavio Toffalini, Marcel Böhme, and Mathias Payer. MendelFuzz:The Return of the Deterministic Stage. In ACM SIGSOFT Symposium on the Foundations of Software Engineering (FSE), 2025.
[90] Ziqiao Kong, Shaohua Li, Heqing Huang, and Zhendong Su. Sand: Decoupling Sanitization from Fuzzing for Low Overhead. In International Conference on Software Engineering (ICSE), 2025.
[91] dkasak. FairFuzz (afl-rb) Integration. https://github.com/AFLplusplus/AFLplusplus/issues/18. Accessed: January 20, 2026.
[92] zhanggenex. Incorporating EcoFuzz? https://github.com/AFLplusplus/AFLplusplus/issues/380. Accessed: January 20, 2026.
[93] virtuald. Add manual mechanism to motivate AFL to pursue a particular input. https://github.com/AFLplusplus/AFLplusplus/issues/643. Accessed: January 20, 2026.
[94] nbars. Disabling PCGUARD edge pruning for AFL++ for evaluation. https://github.com/FOX-Fuzz/FOX/issues/3. Accessed: January 20, 2026.
[95] Chin-Chia Hsu, Che-Yu Wu, Hsu-Chun Hsiao, and Shih-Kun Huang. Instrim:Lightweight Instrumentation for Coverage-guided Fuzzing. In Symposium on Network and Distributed System Security (NDSS), Workshop on Binary Analysis Research, 2018.
[96] Van-Thuan Pham, Marcel Böhme, Andrew E Santosa, Alexandru Răzvan Căciulescu, and Abhik Roychoudhury. Smart Greybox Fuzzing. IEEE Transactions on Software Engineering, 47(9):1980–1997, 2019.
[97] Quarkslab. QBDI - A Dynamic Binary Instrumentation framework. https://github.com/QBDI/QBDI. Accessed: January 20, 2026.
[98] Google Project Zero. WinAFL - Fork of AFL for fuzzing Windows binaries. https://github.com/googleprojectzero/winafl. Accessed: January 20, 2026.
[99] RICSecLab. coresight-trace - ARM CoreSight-based tracing framework. https://github.com/RICSecLab/coresight-trace. Accessed: January 20, 2026.
[100] Quarkslab. TritonDSE - Dynamic Symbolic Execution framework. https://github.com/quarkslab/tritondse. Accessed: January 20, 2026.
[101] Lin Padgham, Young Lee, Shazia Sadiq, Michael Winikoff, Alan Fekete, Stephen MacDonell, Dali Kaafar, and Stefanie Zollmann. CORE Rankings.
[102] Dominik Maier, Lukas Seidel, and Shinjo Park. Basesafe: Baseband Sanitized Fuzzing through Emulation. In ACM Conference on Security and Privacy in Wireless and Mobile Networks, 2020.
[103] Sergej Schumilo, Cornelius Aschermann, Andrea Jemmett, Ali Abbasi, and Thorsten Holz. Nyx-net: Network Fuzzing with Incremental Snapshots. In European Conference on Computer Systems (EuroSys), 2022.
[104] choller. AFL - A Fork of AFL with Enhancements. https://github.com/choller/afl. Accessed: January 20, 2026.
[105] Google. Honggfuzz – Security Oriented, Feedback-driven Fuzzer. https://github.com/google/honggfuzz. Accessed: January 20, 2026.
[106] akihe. Radamsa – Fuzzer for Testing Software by Generating Inputs from Sample Data. https://gitlab.com/akihe/radamsa. Accessed: January 20, 2026.
[107] LLVM Project. LibFuzzer - A library for in-process, coverage-guided fuzzing. https://llvm.org/docs/LibFuzzer.html. Accessed: January 20, 2026.
[108] NCC Group. TriforceAFL - AFL fork with QEMU full-system fuzzing support. https://github.com/nccgroup/TriforceAFL. Accessed: January 20, 2026.
[109] Battelle. afl-unicorn - AFL with Unicorn CPU emulator support. https://github.com/Battelle/afl-unicorn. Accessed: January 20, 2026.
[110] Wen Xu, Sanidhya Kashyap, Changwoo Min, and Taesoo Kim. Designing New Operating Primitives to Improve Fuzzing Performance. In ACM Conference on Computer and Communications Security (CCS), 2017.
[111] Peng Chen and Hao Chen. Angora: Efficient Fuzzing by Principled Search. In IEEE Symposium on Security and Privacy (S&P), 2018.
[112] Jinghan Wang, Yue Duan, Wei Song, Heng Yin, and Chengyu Song. Be Sensitive and Collaborative: Analyzing Impact of Coverage Metrics in Greybox Fuzzing. In Symposium on Recent Advances in Intrusion Detection (RAID), 2019.
[113] Cornelius Aschermann, Tommaso Frassetto, Thorsten Holz, Patrick Jauernig, Ahmad-Reza Sadeghi, and Daniel Teuchert. NAUTILUS: Fishing for Deep Bugs with Grammars. In Symposium on Network and Distributed System Security (NDSS), 2019.
[114] Marcel Böhme, Valentin J. M. Manès, and Sang Kil Cha. Boosting Fuzzer Efficiency: An Information Theoretic Perspective. In ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE), 2020.
[115] Andrea Fioraldi, Daniele Cono D’Elia, and Leonardo Querzoni. Fuzzing Binaries for Memory Safety Errors with QASan. In IEEE Secure Development (SecDev), 2020.
[116] Sebastian Poeplau and Aurélien Francillon. Symbolic execution with SymCC: Don’t interpret, compile! In USENIX Security Symposium, 2020.
[117] Sebastian Poeplau and Aurélien Francillon. SymQEMU: Compilation-based Symbolic Execution for Binaries. In Symposium on Network and Distributed System Security (NDSS), 2021.
[118] Prashast Srivastava and Mathias Payer. Gramatron: Effective Grammar-aware Fuzzing. In International Symposium on Software Testing and Analysis (ISSTA), 2021.
ضمایم
A– تمام نسخههای ++AFL بر روی هدف Bloaty
شکل 13 تمامی نسخههای ++AFL را نشان میدهد که با تنظیمات پیشفرض خود روی هدف Bloaty مورد استفاده قرار گرفتهاند.
B– بهبود CmpLog بین نسخههای c3.0 و c3.14
شکل a14 روند بهبود ویژگی CmpLog را در طول زمان نشان میدهد که در اینجا به صورت نمونه برای هدف Freetype2 به تصویر کشیده شده است.
C– مطالعه موردی: کاهش عملکرد در بازه 3.0c تا 4.10c
نسخه 3.0c در تمامی آزمایشها، به طور مداوم عملکرد بهتری نسبت به نسخههای بعدی تا نسخه 4.10c که نهایتاً در میزان پوشش (coverage) به سطح عملکرد نسخه 3.0c نزدیک میشود، ازخود نشان میدهد. این نتایج این پرسش را مطرح میکنند که چه تغییراتی منجر به افت مشاهده شده در عملکرد شدهاند، بهویژه با توجه به اینکه مهمترین پیکربندیهای تأثیرگذار (مانند برنامهریزی پیشفرض بذرها (default seed schedule) و استفاده از مرحله قطعی (deterministic stage)) در این نسخهها بدون تغییر باقی ماندهاند. با توجه به انتخاب نسخههای بررسی شده از ++AFL، برخی از نسخههای میانی بین 3.0c و 3.14c در تحلیل ما لحاظ نشدهاند؛ در حالی که نسخه 3.14c عملکردی به مراتب ضعیفتر از خود نشان میدهد. این افت عملکرد به ویژه در پیکربندی dict2file در طیف گستردهای از اهداف (targets) و همچنین در آزمایشهای پایهای که در آن مرحله قطعی برای همه نسخهها غیرفعال شده یا از ابزارسازی LLVM-native استفاده شده است، بهطور واضح مشهود میباشد.
افت عملکرد پایدار مشاهده شده در نسخههای پس از 3.0c نشاندهنده احتمال وجود یک رگرسیون پنهان (hidden regression) است که ممکن است تمامی نسخههای بعدی را تحت تأثیر قرار داده باشد. به منظور بررسی این مسئله، یک آزمایش هدفمند با استفاده از قابلیت dict2file بر روی هدف Freetype2 انجام دادیم، زیرا این هدف بیشترین افت عملکرد را نشان میداد. هدف ما شناسایی تغییرات مسئول این کاهش و ارزیابی تأثیر آنها بر اثربخشی فازینگ بود.
مقایسه نتایج میان این نسخهها نشان میدهد که یک روند نزولی تقریباً پیوسته در میزان پوشش کد (coverage) با هر انتشار جدید وجود دارد (رجوع شود به شکل 14b). نکته قابلتوجه این است که بیشترین افت عملکرد بین نسخههای 3.0c و 3.10c رخ میدهد. ما به منظور یافتن علت، تغییرات ثبت شده (commits) بین این دو نسخه را به دو بخش تقسیم و بررسی کردیم (bisect)، اما نتایج قطعی حاصل نشد. به نظر میرسد این کاهش عملکرد ناشی از مجموعهای از تغییرات تدریجی و انباشته باشد، نه یک تغییر ثبت شده (commits) مشخص و قابلتشخیص که به طور مستقیم موجب شکست عملکرد شده باشد؛ امری که تعیین منشأ دقیق این رگرسیون را با دشواری مواجه میکند.
D– بهبود عملکرد فازر با در نظرگرفتن دادههای پرت (Outliers)
شکل 15 همان دادههای ارائه شده در شکلهای 3 و 4 را نشان میدهد، با این تفاوت که در اینجا مقادیر دادههای پرت (outlier values) نیز لحاظ شدهاند؛ مقادیری که به منظور افزایش خوانایی در متن اصلی حذف شده بودند. ما مشاهده میکنیم که این دادههای پرت ناشی از رفتار به طور قابلتوجه متفاوت فازر در برخی اهداف (targets) خاص هستند، به طوریکه عملکرد آن در این موارد انحراف چشمگیری را از روند کلی نشان میدهد.
E– نمای کلی بهترین پیکربندی
جدول ۵ مکمل شکل ۸ است و بهترین پیکربندی را به ازای هر فازر و هدف نشان میدهد.
جدول ۵: بهترین پیکربندیها به ازای هر هدف و نسخه ++AFL:
F – کارهای یکپارچه و ادغام شده در ++AFL
ما در جدول 6، ویژگیها و قابلیتهای موجود در ++AFL را فهرست کردهایم که خارج از محدوده مجامع سطحبالای علمی قرار میگیرند. نکته حائز اهمیت این است که بخش قابلتوجهی از این قابلیتها منشأیی غیرآکادمیک دارند یا از مجامع علمی با سطح اعتبار پایینتر نشأت گرفتهاند.
جدول 6: نمای کلی ابزارها و تکنیکهای فازینگ ادغامشده (یا ویژگیهای الهامگرفته) در ++AFL بر اساس مقاله اصلی ++AFL و همچنین منابع عمومی موجود. در این جدول تنها آثار و کارهای عمده نمایش داده شدهاند؛ در حالی که بهبودهای متعدد دیگری (مانند [102, 103]) که شامل اصلاح یا ارتقای ویژگیهای موجود و همچنین رفع اشکالات (bug fixes) هستند، در این جدول لحاظ نشدهاند. همچنین کُدگذاری رنگی برای تمایز میان موارد استفاده ویژه (special use cases – رنگ نارنجی)، ویژگیها (features – رنگ سبز) و بهبودها (improvements – رنگ بنفش) به کار رفته است: