تصور کنید ابزاری دارید که در هر ثانیه صدها ایده برای شکستن سیستم شما میدهد، اما ۹۳ درصد آنها حتی نمیتوانند از درِ ورودی عبور کنند. این واقعیت تلخِ تکیه بر هوش مصنوعی برای یافتن باگهای امنیتی است.
طبق گزارش منتشرشده از این مورد مطالعاتی، تنها ۷٪ از ورودیهای باینری پیشنهادی برای یک تجزیهکننده بسته (Packet Parser) در زبان C++ توانستند پوشش کد (Code Coverage) را افزایش دهند. این نتیجه، شکاف عمیقی را میان توانایی هوش مصنوعی زاینده (Generative AI) — شبیه به نویسندهای که با اعتمادبهنفس زیاد اما بدون دانش فنی مینویسد — و نیازهای واقعی یک ابزار فازینگ (Fuzzing) نشان میدهد.
برای توسعهدهندگان، وسوسه این است که هر ورودی تولیدشده توسط AI را به عنوان یک داده معتبر بپذیرند. اما افزودن حجم زیاد داده بدون اثبات کارایی، فقط باعث ایجاد نویز میشود. در این آزمایش، هدف یک برنامه کوچک به نام packet_decoder بود؛ یک تجزیهکننده پروتکل باینری که با استاندارد C++17 و ابزار libFuzzer اجرا میشد. مجموعه داده اولیه شامل ۱۴ بذر (Seed) دستنویس بود که ۶۲٪ از خطوط کد را پوشش میداد و حفرههای اصلی در بخشهای تایید چکسام (Checksum) و اعتبارسنجی طول بسته بود.
همانطور که در بحثهای گذشته ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، تکیه بر خروجی خام مدلها بدون لایهی اعتبارسنجی، ریسک خطای سیستماتیک را بالا میبرد. برای حل مشکل نویز، در این گردشکار از دسترسی رایگان MonkeyCode استفاده شد تا یک خط لوله «پیشنهاد و تایید» (Propose-and-Verify) ایجاد شود. هدف این بود که سرعت مدل حفظ شود اما هر ورودی مجبور باشد کارایی خود را ثابت کند. قانون ساده بود: یک ورودی تنها زمانی «بذر» محسوب میشود که در یک اجرای تمیز، حداقل یک لبهی پوشش (Coverage Edge) جدید ایجاد کند.
این فرآیند از چهار مرحله مجزا تشکیل شده است:
۱. تولید محدود
از مدل خواسته شد بهجای توضیحات، فقط پیشنهاد بدهد. درخواست اول بهطور عمدی محدود بود و تنها ورودیهای باینری کدگذاریشده به فرمت Hex را میخواست. به مدل صراحتاً گفته شد که از حدس زدن شدت باگ یا نوشتن پاراگرافهای تحلیل خودداری کند تا خروجی پاک بماند. پارامترهایی مثل حداکثر ۱۰ بذر و حداکثر ۶۴ بایت برای هر بذر تعیین شد. با این حال، مدل گاهی خروجیهای JSON معتبری میداد که شامل رشتههای Hex با طول فرد یا یادداشتهای بیفایده بود.
۲. اعتبارسنجی ساختاری
پیش از صرف هرگونه توان محاسباتی، یک تجزیهکننده پایتونی ورودیها را بررسی میکرد. تنها فرمت پذیرفتهشده، Hex حروف کوچک با طول زوج و سقف ۶۴ بایت بود.
- ورودیهای ردشده: رشتههای Hex با طول فرد، کاراکترهای غیر Hex و بافرهای بیش از ۶۴ بایت.
- سازوکار: تابع
parse_seedابتدا فاصلههای خالی را حذف و سپس مجموعه کاراکترها را تایید میکرد.
این مرحله مانع از آن میشد که خروجیهای بدساخت مدل، باعث شکستهای گیجکننده در فرآیند فازینگ شوند.
۳. اجرای ایزوله
هر ورودی نرمالشده در یک فراخوانی مجزای libFuzzer اجرا میشد. برای جلوگیری از توقف کل دسته به دلیل یک بذر کند، مهلت زمانی ۳۰ ثانیهای اعمال شد.
- پارامترهای اجرا: اجراکننده از
-runs=200و-max_len=64استفاده کرد. - مدیریت کرش: اگر ASan (AddressSanitizer) باعث توقف برنامه (Crash) میشد، ورودی به عنوان گزارش باگ علامتگذاری میشد اما به مجموعه بذرها اضافه نمیشد؛ زیرا کرش با افزایش پوشش کد متفاوت است.
۴. دفتر ثبت پوشش (Coverage Ledger)
تصمیم نهایی بر عهده یک دفتر ثبت بود که بهدنبال حداقل یک لبه پوشش جدید میگشت، نه صرفاً نبود خطا.
- تشخیص: تجزیهکننده با استفاده از یک عبارت منظم (
NEW_EDGE_RE) بهدنبال نشانگرNEWدر لاگها میگشت (مثلاً#1 NEW cov: 192). - اقدام: اگر خط
NEWیافت نمیشد، بذر بدون توجه به «تمیز» بودن اجرا، رد میشد.
نتایج و تحلیل
بر اساس مستندات این گزارش، نتایج تکاندهنده بود: ۸۷ بذر کاندید تولید شد. تجزیهکننده ۱۱ مورد را به دلیل ساختار غلط رد کرد. از ۷۶ مورد اجراشده، تنها ۶ مورد پوشش جدید ایجاد کردند. سه ورودی باعث کرش شدند که برای شکار باگ عالی هستند اما برای قرار گرفتن در مجموعه بذرها خطرناکاند، چون میتوانند با تکرار کرش، باگهای دیگر را پنهان کنند.
یکی از آن ۶ بذر پذیرفتهشده، در نهایت شاخهای از چکسام را پیدا کرد که ۱۴ بذر دستنویس اولیه هرگز به آن نرسیده بودند. این ثابت میکند که اگرچه نرخ موفقیت پایین است، اما سرعت تولید AI میتواند «سوزن را در انبار کاه» پیدا کند، به شرطی که فیلترهای سختگیرانه داشته باشد.
درسهای آموختهشده
این تجربه نشان میدهد که اعتبارسنجی ساختاری بسیار ارزشمندتر از مهندسی پرامپت (Prompt Engineering) — هنر سؤال درست پرسیدن برای گرفتن بهترین جواب از مدل — است. با رد کردن Hexهای غلط پیش از اجرا، توسعهدهندگان در زمان محاسبات صرفهجویی کرده و از شکستهای گمراهکننده دور میمانند.
- جداسازی تولید از قضاوت: مدل ۸۷ ورودی محتمل ساخت، اما دفتر ثبت تنها شواهدی را پذیرفت که واقعاً اثر داشت.
- ذخیرهسازی در استخر سرد: از آنجا که بذری که اکنون پوشش جدیدی نمیدهد ممکن است بعد از اضافه شدن بذر دیگر مفید شود، کاندیداهای ردشده باید در یک «استخر سرد» نگه داشته شوند و حذف نگردند.
برای جامعه فنی، این موضوع این فرض را میشکند که مدلهای زبانی میتوانند نیازهای یک فازر را «درک» یا «استدلال» کنند. مدل میتواند مسیرهای محتمل را پیشنهاد دهد، اما نمیتواند هدف را اجرا کند. دفتر ثبت تنها منبع حقیقت است.
محدودیتها
این روش برای تجزیهکنندههای بدون وضعیت (Stateless) بهترین بازدهی را دارد و برای مسیرهایی که به زمانبندی یا ترکیب چند ورودی وابسته هستند، کاربرد ندارد. اگر هزینه راهاندازی هدف شما زیاد است یا به سختافزار خاصی نیاز دارد، از این روش دوری کنید.
اگر مجموعه بذرهای C++ شما متوقف شده است، پیش از ارسال درخواستهای بیشتر به مدل، یک دفتر ثبت پوشش پیادهسازی کنید. حالا باید دید این رویکرد چگونه در تجزیهکنندههای وضعیتدار (Stateful) که ورودیهای تکگانه در آنها کافی نیست، مقیاس میپذیرد.
گام بعدی شما
- اگر از AI برای تولید تست استفاده میکنید، لایهای برای اعتبارسنجی ساختاری (مانند چک کردن طول و فرمت Hex) اضافه کنید تا هزینه GPU هدر نرود.
- بهجای اعتماد به «توضیحات» مدل درباره دلیل انتخاب یک ورودی، یک سیستم ثبت پوشش (Coverage Ledger) برای تایید عملی خروجیها بسازید.
- ورودیهای ردشده را حذف نکنید و در یک دیتابیس جداگانه (Cold Pool) نگه دارید تا در مراحل بعدی دوباره تست شوند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو