تخطَّ إلى المحتوى

Fuzzing الحديثة في 2026: Snapshots و Frameworks و Fuzzing ما لم تستطع قبله

· 13 min read · default
cybersecurityfuzzingvulnerability-researchreverse-engineeringtestingsecurity

Fuzzing له مشكلة سمعة: الكثيرون من المهندسين ما زالوا يتخيلونه رمي bytes عشوائية على برنامج حتى يتحطم. هذا الوصف كان تقريباً صحيحاً في 1990 وقد كان مضللاً لعقد. Fuzzing الحديثة هي coverage-guided — fuzzer يجهز الهدف و يلاحظ أي مسارات كود كل إدخال يصل إليها و يوجه الطفرة نحو inputs التي تكتشف أراضي جديدة. حلقة الملاحظة هذه هي الفرق بين poking عشوائي في parser و المشي المنظم لمساحة الحالة الخاصة بها وهذا لماذا fuzzing الآن يجد آلاف CVEs الحقيقية سنة في برمجيات أن تم تقييمها من خبراء.

منظر 2026 قد نضج جيداً ماضي أداة واحدة على الرغم من والتطورات المثيرة للاهتمام حول الوصول إلى أهداف التي conventional fuzzing لا يستطيع: أنظمة تشغيل kernels و الأكواد المدفونة خلف إعداد المكلف و التطبيقات التي input structure يهزم byte mutation. هذا الدليل يغطي منظر ذلك — coverage-guided classics و syzkaller ل kernels و Snapchange ل snapshot fuzzing و LibAFL لبناء fuzzer الهدف يحتاج بالفعل — زائد cargo-fuzz و honggfuzz للعمل اليومي.

لماذا coverage guidance غيرت كل شيء

الآلية تستحق الفهم لأنها توضح ما fuzzing جيد في و حيث يتوقف. A coverage-guided fuzzer تجميع الهدف مع البرمجة التي سجلات التي حواف control-flow graph تنفيذ لمست. يحافظ على corpus من inputs و عندما mutation input يصل حافة لا تصل previous input تلك input حكم مثير للاهتمام و أضيف ل corpus ليتم mutation بشكل إضافي. عبر ملايين iterations corpus تجمع inputs التي بشكل جماعي ممارسة عميقة و unusual paths — بما فيها paths لا أحد مكتوب test لـ.

هذا ينتج السلوك الذي يبدو تقريباً ذكي. معطى corpus seeded بـ valid PNG fuzzer سوف اكتشف chunk البناء ثم valid chunk الأنواع ثم parsing الفروع ل كل نوع تدريجي بناء inputs التي تصل أعمق إلى قارئ. لا يفهم أبداً PNG; فقط يبقي مهما حرك التغطية.

الاستتباع هو حيث fuzzing يتوقف: hard checks لا يمكنه تخمين بعده. السحر const المقارنة أو checksum أو cryptographic signature خلق جدار — random mutation سوف بشكل أساسي أبداً ينتج الحقيقي 8 bytes حتى كل شيء خلف ذلك الفحص يبقى unexplored. الاستجابات العملية seeding corpus مع inputs صالح أو إمداد القاموس من السحر القيم أو patching checksums في fuzz build. الاعتراف plateau coverage كـ "I hit جدار" بدلاً من "هناك لا أكثر bugs" هو واحد من الأكثر instincts مفيد في هذا العمل.

Kernel fuzzing: syzkaller

أنظمة تشغيل kernels هي هدف عدواني ل conventional fuzzers. الإدخال ليس ملف لكن تسلسل syscalls مع وسيطات interdependent — file descriptor من open يجب أن يتدفق إلى read و معظم syscall تسلسلات عشوائية تفشل الفور مع EINVAL. Crashes أخذ كامل الجهاز بدلاً من عملية واحدة و التغطية يجب أن تُجمع من kernel space.

syzkaller يحل كل ثلاثة. يصف syscalls في لغة إعلانية (syzlang) حتى يمكنه توليد تسلسلات معقولة مع typed صحيح و interdependent الوسيطات; يشغل الأهداف داخل VMs قابلة للتخلص حتى الأعطال هي survivable و تجميع تلقائياً; و يستخدم KCOV ل kernel التغطية الملاحظة زائد KASAN لـ اقتناص أخطاء الذاكرة التي قد تكون أخرى صامتة corruption. Google's syzbot يشغله بشكل مستمر ضد Linux و أبلغ آلاف أخطاء.

الدرس يعمم ماضي kernels: syzkaller يعمل لأن شخص coded معرفة input structure إلى الأوصاف. عندما input الهدف لديهم grammar تعليم fuzzer تلك grammar يتغلب raw byte mutation بـ واسع الهامش. التكلفة المقابلة حقيقية — توسيع syzlang ل subsystem under-tested هو عمل حقيقي و هو أيضاً أعلى قيمة مساهمة معظم الناس يمكن أن تحقق ل kernel fuzzing.

Snapshot fuzzing: الحصول ماضي الإعداد

الجبهة الثانية هي الأهداف حيث الأكواس المثيرة للاهتمام تجلس خلف expensive initialization. فكر fuzzing query parser database: كل iteration سوف احتاج إلى بدء الخادم و initialize storage و authenticate و establish جلسة قبل single query يتم parsing. بـ ربما عشر iterations لكل ثانية coverage-guided fuzzing هو hopeless — التقنية تحتاج آلاف.

Snapshot fuzzing تعكس هذا. تشغيل الهدف مرة واحدة إلى بالضبط اللحظة من الاهتمام و خذ snapshot الذاكرة من جميع آلة state و ثم استعيد تلك snapshot ل كل iteration اللاحقة. جميع إعداد التكلفة يتم دفع مرة واحدة. Snapchange (من AWS) تنفذ هذا مع KVM: التقط snapshot مع QEMU اكتب harness صغيرة Rust توصف حيث حقن input و عندما iteration ينتهي و هو تشغيل من تلك state في معدلات عالية جداً.

هذا يفتح الفئات التي كانت سابقاً غير عملية: stateful network protocols مُفزَّزة mid-session و أكواس خلف authentication و hypervisor و kernel code و أي تطبيق مع heavy startup. التجارة هي جهد — تكتب Rust fuzzer بدلاً من تشغيل أمر و يجب أن تفهم تخطيط الذاكرة للهدف جيداً بـ كافي لحقن input بشكل صحيح. إنها تقنية متخصص التي يدفع بالضبط عندما البديل لا يفعل fuzzing الهدف على الإطلاق.

Frameworks: بناء fuzzer الهدف يحتاج

التطور الثالث هو فلسفي. AFL++ و libFuzzer ممتاز في ما تم تصميمها ل و محرج عندما الهدف لا يناسب — binary بروتوكول مخصص و firmware محاكاة صورة و input هذا شجرة بدلاً من buffer. تاريخياً تحنت الأداة عادة سيء.

LibAFL من فريق AFL++ يعامل fuzzer كـ أجزاء composable: observers التي تسجل البيانات و feedbacks التي حكم interestingness و mutators التي تحول inputs و schedulers و stages و executors. تجمع المجموعة الهدف يحتاج و تحديد input نوعك الخاص و mutators إذا input هو منظم اختر executor (في-process و forkserver و QEMU محاكاة و Frida البرمجة و snapshot) و الحصول على multi-core scaling مجاني.

الإطار الصريح هو هذا التزام أكبر من تشغيل أداة لذا التسلسل يهم: ابدأ مع cargo-fuzz ل Rust أو honggfuzz/AFL++ ل native الأهداف و انتقل إلى LibAFL فقط عندما تستطيع الكلام بالضبط لماذا لا يناسبها. "الإدخال هو state machine البروتوكول و byte mutation أبداً ينتج valid رسالة ثانية" هو مثل كهذا; "أريده أسرع" عادة لا.

Everyday fuzzing أن teams بالفعل الحفاظ

معظم القيمة ل معظم teams تأتي من unglamorous continuous fuzzing من parsers و untrusted-input handlers. cargo-fuzz يجعل هذا تقريباً frictionless ل Rust: اكتب دالة تأخذ &[u8] (أو أفضل typed قيمة عبر arbitrary crate) و تشغيل أمر واحد. honggfuzz هو بشكل مماثل سهل ل native code و يضيف hardware-based التغطية عبر Intel PT/BTS التي تسمح لك fuzz ثنائيات لا تستطيع إعادة تجميع — مفيد ل closed-source المتعلقات.

اثنين الممارسات منفصلة teams التي الحصول على القيمة من teams التي توقفت fuzzing بعد أسبوع. أولاً seed corpus مع real صالح inputs; fuzzer بدء من فارغ corpus تنفق وقت ضخم rediscovering الأساسي format الصحة التي كان يمكن لك أن تسليم له. الثاني تشغيل بشكل مستمر و علاج الأوجد كـ tests: تحويل كل minimized crash إلى regression test حتى تبقى مثبتة و اسمح corpus أن تستمر بين التشغيلات حتى progress يتجمع. Fuzzing لا one-afternoon audit; إنه background عملية التي تبقى تجد الأشياء حيث الأكواس تغييرات.

Sanitizers استحق ملاحظة لأنهم multiply الفعالية. AddressSanitizer تحول silent الذاكرة corruption إلى فوراً و diagnosable crash و UBSan يمسك undefined السلوك التي قد ظهرت بخلاف كـ mysterious miscompilation لاحقاً. Fuzzing بدون sanitizers يجد فقط الأخطاء التي حدث الطريق للانهيار أنفسهم — عادة جزء صغير من ما هو بالفعل هناك.

Triage: العمل الذي يبدأ عندما crash يصل

إيجاد crash هو البداية و teams روتين underestimate الجهد بين "fuzzer توقف" و "مطور يمكن الإصلاح هذا." أربع خطوات جعل الفرق بين مفيد report و واحد mattered.

قلل الإدخال. A crashing input من fuzzer هو عادة كامل الصلة bytes التي نجت فقط لأن لا شيء أزالهم. كل fuzzer جاد سفن minimizer (cargo fuzz tmin و afl-tmin و syzkaller's syz-repro) و تشغيله تحول 4KB blob إلى حفنة من bytes الذي عزل الزناد الفعلي. هذا يهم بشكل ضخم ل المطور التي لديها فهم إنه.

أزيل التكرار. A fuzzer يشغل طوال الليل سوف يبلغ نفس bug عشرات الأوقات عبر inputs مختلفة. تجميع بـ crash الموقع و stack التوقيع يحول 200 crashes إلى ستة distinct bugs. بدون هذه الخطوة triage يبدو impossibly مكلفة و الناس إعطاء.

تقيّم exploitability بعناية. ليس كل crash هو vulnerability. null-pointer dereference في parser هو عادة denial من الخدمة; heap buffer overflow مع attacker-controlled الطول هو ربما أسوأ بكثير. Sanitizer الإخراج يساعد بشكل ضخم هنا — ASan يقول لك نوع الذاكرة خطأ و الأحجام و كل allocation و الوصول stacks. مقاومة الاختبار إلى كل شيء تسمية حرج لأن team التي يتلقى inflated severities توقف الثقة في التقارير.

تحويل إلى regression test. الـ minimized input يصبح unit test التزم جنباً إلى جنب الإصلاح. هذا ما يبقى bug مثبت و ما يجعل fuzzing مركب بمرور الوقت بدلاً من rediscovering نفس المشاكل بعد refactor.

Teams التي الحصول على sustained القيمة من fuzzing هي التي الهياكل خط أنابيب هذا مرة واحدة و ليس الذي إيجاد أكثر crashes.

اختيار حيث ابدأ

القرار يتبع الهدف. ل Rust code استخدم cargo-fuzz و استخدم arbitrary ل fuzz typed APIs بدلاً من فقط byte parsers. ل native userspace ثنائيات مع المصدر honggfuzz أو AFL++ مع sanitizers. ل ثنائيات بدون المصدر honggfuzz's hardware التغطية أو AFL++'s QEMU الوضع. ل OS kernels syzkaller و متابعة توسيع syzlang ل subsystem تهتم. ل أكواس خلف expensive الإعداد أو stateful الجلسات Snapchange أو snapshot-capable LibAFL تكوين. و ل inputs مع real البناء — بروتوكولات و ASTs و ملف التنسيقات مع grammar — إما grammar-aware mutator أو custom LibAFL fuzzer لأن byte mutation سوف plateau مبكراً.

عبر كل من هذه نفس الانضباط تطبيق: seed جيد و تشغيل مع sanitizers و تشغيل بشكل مستمر و قلل crashes و تحويل الأوجد إلى regression tests. الأداة يهم أقل من ما إذا كان الحلقة يبقى تشغيل.

الخط السفلي

Fuzzing في 2026 هي systematic vulnerability-discovery الانضباط مبني على coverage التغطية و frontierها هو الوصول إلى الأهداف التي كانت سابقاً خارج النطاق. syzkaller fuzzes kernels بـ encoding syscall البناء و تشغيل في VMs disposable; Snapchange يستخدم KVM snapshots ل fuzz code مدفونة خلف expensive الإعداد; LibAFL تدعك بناء fuzzer matched إلى هدف غير عادي بدلاً من ثني أداة monolithic; و cargo-fuzz و honggfuzz جعل everyday continuous fuzzing رخيصة بـ كافي لـ بالفعل الحفاظ. ابدأ مع الأداة السهل ل اللغة الخاصة بك و seed corpus مع real inputs و دائماً تفعيل sanitizers و علاج plateau التغطية كـ جدار لـ هندسة ماضي بدلاً من all-clear و أسفل كل crash إلى test.

المراجع و الموارد

الأدوات

الخلفية و التحليل

1337skills cheatsheets ذات الصلة