是否可以告诉 libfuzzer 忽略某些代码?
Posted
技术标签:
【中文标题】是否可以告诉 libfuzzer 忽略某些代码?【英文标题】:Is it possible to tell libfuzzer ignore certain code? 【发布时间】:2020-12-22 21:29:04 【问题描述】:我使用 libfuzzer,到目前为止,这是一次很棒的体验。 我在 fuzz 下的代码充满了这样的分支:
bool fuzzingThisFunc()
if(!checkSomething())
fmt::printf("error log");
return false;
...
return true;
其中fmt::printf
是来自第三方库 (http://github.com/fmtlib/fmt) 的函数。
我觉得经过几次迭代后,fuzzer 进入了这个函数并有效地开始对其中的所有分支进行模糊测试(比如当它使用 DFS 而不是 BFS 时)。
我想向模糊器添加一些障碍或指令,以不将检测插入第三方库,因此我的模糊器将尝试仅覆盖我的代码。
有可能吗?
【问题讨论】:
【参考方案1】:Libfuzzer 支持源文件级别的检测。一种选择是构建没有-fsanitize=fuzzer
标志的第三方库。
检查传递给这些库的配置的 CFLAGS,以删除此标志。
只有标头的库通常包含模板,fmt 就是这种情况。它们必须在编译时实例化。我认为没有简单的方法来处理这些。您可以找到所有使用的模板参数,创建将它们与这些参数一起使用的 thunk 代码,从检测中排除此代码并修改您的调用代码以使用这些实例化的函数,但这非常困难。
当您不希望检测的代码只执行日志记录或其他可以跳过而不修改应用程序行为的活动时,您可以将其设置为编译条件。 Libfuzzer 文档建议使用FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
define 来标记您不想为模糊测试构建的代码。在 fmt 情况下,这将是:
bool fuzzingThisFunc()
if(!checkSomething())
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
fmt::printf("error log");
#endif
return false;
...
return true;
或修改库代码:
template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_string<S>::value)>
inline int printf(const S& format_str, const Args&... args)
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
using context = basic_printf_context_t<char_t<S>>;
return vprintf(to_string_view(format_str),
make_format_args<context>(args...));
#else
return 0; //C printf returns number of characters written, I assume same for fmt.
#endif
第二种情况更容易编码(每个排除的 func 一个修改),但是每次获得新的 fmt 版本时都必须添加此修改。 在第一种情况下,您必须修改每个排除的 func 调用站点。
对于这两种情况,您都应该将 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
添加到 configure 的 CFLAGS 以进行模糊测试目标构建。
【讨论】:
有趣的想法!仅标头库怎么样? 改变了我的答案。 Libfuzzer 可以探索 fmt::printf 如果它可以修改某些东西,这会影响它的内部行为。一个明显的选择是函数参数。当它们被硬编码时,例如 fmt::printf("error log") 它不能修改它。在这种情况下,您认为 libfuzzer 在探索 fmt 时会卡住的假设可能是错误的。 一旦我禁用日志记录,我的 fuzzer 立即发现了一个问题...我使用编译开关禁用所有记录器(幸运的是它们被隐藏在宏下,所以我更改了 1 个位置)。以上是关于是否可以告诉 libfuzzer 忽略某些代码?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以让 <error-page> servlet 忽略某些请求?