Nautilus 是一个基于覆盖率引导、基于语法的模糊测试工具。你可以用它来提升测试覆盖率,发现更多漏洞。通过指定半有效输入的语法,Nautilus 能够执行复杂的变异,从而挖掘出更多有趣的测试用例。该模糊测试器背后的许多思想已在 2019 年 NDSS 会议发表的论文中有所阐述。
2.0 版本为这个早期原型增加了许多改进,并且现在与 AFL++ 完全兼容。除了通用可用性改进外,2.0 版本还包含大量全新的特性:
你需要使用诸如 EXPR -> EXPR + EXPR 或 EXPR -> NUM 以及 NUM -> 1 之类的规则来指定一个语法。根据这些规则,模糊测试器会构建一棵树。这种内部表示允许应用比原始字节复杂得多的变异。然后,这棵树会被转换成目标应用程序的真实输入。在普通的上下文无关语法中,这个过程是直接的:所有叶子节点被拼接起来。下面例子中左边的树会解析为输入 a=1+2,右边的树则解析为 a=1+1+1+2。为了增强语法的表达能力,使用 Nautilus 时,你可以为解析过程提供 Python 函数,从而实现更复杂的规格说明。
# 克隆仓库
git clone '[email protected]:nautilus-fuzz/nautilus.git'
cd nautilus
/path/to/AFLplusplus/afl-clang-fast test.c -o test #afl-clang-fast 由 AFL 提供
# 所有参数也可以通过 config.ron 文件设置
cargo run --release -- -g grammars/grammar_py_example.py -o /tmp/workdir -- ./test @@
# 或者如果你想使用 QEMU 模式:
cargo run /path/to/AFLplusplus/afl-qemu-trace -- ./test_bin @@
这里,我们使用 Python 为有效的类似 XML 的输入生成一个语法。注意脚本规则的使用,以确保开标签和闭标签相匹配。
#ctx.rule(NONTERM: string, RHS: string|bytes) 添加一条规则 NONTERM -> RHS。我们可以使用 {NONTERM} 在 RHS 中请求递归。
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) 添加一条规则 NONTERM -> func(*RHS)。
# 与普通的 `rule` 不同,RHS 是一个非终结符数组。
# 由函数负责将 NONTERMINALS 返回的值与任何固定内容组合起来。
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")
#有时我们不想更细致地探索可能的输入集合。例如,当模糊测试脚本解释器时,我们不想花费时间模糊所有不同的变量名。在这种情况下,我们可以使用正则表达式终结符。
#正则表达式终结符只在生成过程中被变异,而在正常的变异阶段则不会,从而节省大量时间。
#模糊测试器仍然会探索正则表达式的不同值,但它无法逐步学习有趣的值。当逐步探索很可能浪费时间时,请使用此功能。
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 的输入,但反过来则不会。
#终端/屏幕1
./afl-fuzz -Safl -i /tmp/seeds -o /tmp/workdir/ ./test @@
#终端/屏幕2
cargo run --release -- -o /tmp/workdir -- ./test @@