
Fuzzer قائم على القواعد النحوية مع تغذية راجعة
Nautilus هو مولد اختبارات (fuzzer) يعتمد على التغطية والقواعد النحوية. يمكنك استخدامه لتحسين تغطية اختباراتك واكتشاف المزيد من الأخطاء. من خلال تحديد قواعد نحوية للمدخلات شبه الصالحة، يستطيع Nautilus إجراء طفرات معقدة واكتشاف حالات اختبار أكثر إثارة للاهتمام. تم توثيق العديد من الأفكار وراء هذا المولد في ورقة بحثية نُشرت في NDSS 2019.
أضافت الإصدارة 2.0 العديد من التحسينات على هذا النموذج الأولي وأصبحت الآن متوافقة بنسبة 100% مع AFL++. بالإضافة إلى تحسينات سهولة الاستخدام العامة، تتضمن الإصدارة 2.0 الكثير من الميزات الجديدة الرائعة:
تقوم بتحديد قواعد نحوية باستخدام قواعد مثل EXPR -> EXPR + EXPR أو EXPR -> NUM و NUM -> 1. من هذه القواعد، يقوم المولد ببناء شجرة. يسمح هذا التمثيل الداخلي بتطبيق طفرات أكثر تعقيدًا من البايتات الخام. ثم يتم تحويل هذه الشجرة إلى مدخل حقيقي للتطبيق الهدف. في القواعد النحوية الحرة السياقية العادية، تكون هذه العملية مباشرة: يتم ربط جميع الأوراق. الشجرة اليسرى في المثال أدناه ستتحول إلى المدخل a=1+2 واليمنى إلى a=1+1+1+2. لزيادة تعبيرية القواعد النحوية الخاصة بك، باستخدام Nautilus يمكنك تقديم دوال Python لعملية التحويل العكسي للسماح بتحديدات أكثر تعقيدًا.
# checkout the git
git clone '[email protected]:nautilus-fuzz/nautilus.git'
cd nautilus
/path/to/AFLplusplus/afl-clang-fast test.c -o test #afl-clang-fast as provided by AFL
# all arguments can also be set using the config.ron file
cargo run --release -- -g grammars/grammar_py_example.py -o /tmp/workdir -- ./test @@
# or if you want to use QEMU mode:
cargo run /path/to/AFLplusplus/afl-qemu-trace -- ./test_bin @@
هنا، نستخدم Python لتوليد قواعد نحوية لمدخلات صالحة تشبه XML. لاحظ استخدام قاعدة برمجية لضمان تطابق وسمي الفتح والإغلاق.
#ctx.rule(NONTERM: string, RHS: string|bytes) adds a rule NONTERM->RHS. We can use {NONTERM} in the RHS to request a recursion.
ctx.rule("START","<document>{XML_CONTENT}</document>")
ctx.rule("XML_CONTENT","{XML}{XML_CONTENT}")
ctx.rule("XML_CONTENT","")
#ctx.script(NONTERM:string, RHS: [string]], func) adds a rule NONTERM->func(*RHS).
# In contrast to normal `rule`, RHS is an array of nonterminals.
# It's up to the function to combine the values returned for the NONTERMINALS with any fixed content used.
ctx.script("XML",["TAG","ATTR","XML_CONTENT"], lambda tag,attr,body: b"<%s %s>%s</%s>"%(tag,attr,body,tag) )
ctx.rule("ATTR","foo=bar")
ctx.rule("TAG","some_tag")
ctx.rule("TAG","other_tag")
#sometimes we don't want to explore the set of possible inputs in more detail. For example, if we fuzz a script
#interpreter, we don't want to spend time on fuzzing all different variable names. In such cases we can use Regex
#terminals. Regex terminals are only mutated during generation, but not during normal mutation stages, saving a lot of time.
#The fuzzer still explores different values for the regex, but it won't be able to learn interesting values incrementally.
#Use this when incremantal exploration would most likely waste time.
ctx.regex("TAG","[a-z]+")
لاختبار القواعد النحوية الخاصة بك، يمكنك استخدام المولد:
$ cargo run --bin generator -- -g grammars/grammar_py_exmaple.py -t 100
<document><some_tag foo=bar><other_tag foo=bar><other_tag foo=bar><some_tag foo=bar></some_tag></other_tag><some_tag foo=bar><other_tag foo=bar></other_tag></some_tag><other_tag foo=bar></other_tag><some_tag foo=bar></some_tag></other_tag><other_tag foo=bar></other_tag><some_tag foo=bar></some_tag></some_tag></document>
يمكنك أيضًا استخدام Nautilus مع AFL. فقط وجه AFL -o إلى نفس دليل العمل، وسيقوم AFL بالمزامنة مع Nautilus. لاحظ أن هذا في اتجاه واحد. يستورد AFL مدخلات Nautilus، وليس العكس.
#Terminal/Screen 1
./afl-fuzz -Safl -i /tmp/seeds -o /tmp/workdir/ ./test @@
#Terminal/Screen 2
cargo run --release -- -o /tmp/workdir -- ./test @@