如何为自定义API调用与使用libFuzzer?实战场景求解
libFuzzer自定义API模糊测试实战方案
1. 处理std::vector<std::string> + size_t参数的API
核心是把libFuzzer生成的字节流解析为目标参数格式,以下是直接可运行的示例代码及逻辑:
#include <vector> #include <string> #include <cstring> // 假设你的目标API声明 void MyAPI(const std::vector<std::string>& strs, size_t limit); extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { // 至少要能取出size_t参数(64位系统下占8字节) if (Size < sizeof(size_t)) return 0; // 从输入头部解析size_t参数 size_t param_limit = *reinterpret_cast<const size_t*>(Data); size_t offset = sizeof(size_t); std::vector<std::string> str_vec; // 用'\0'作为字符串分隔符,解析剩余字节流 while (offset < Size) { const char* str_start = reinterpret_cast<const char*>(Data + offset); // 查找下一个'\0'的位置,避免越界 const char* str_end = reinterpret_cast<const char*>( memchr(Data + offset, '\0', Size - offset) ); if (!str_end) break; // 无分隔符则停止解析 str_vec.emplace_back(str_start, str_end - str_start); offset = (str_end - reinterpret_cast<const char*>(Data)) + 1; // 跳过'\0' } // 调用目标API MyAPI(str_vec, param_limit); return 0; }
转换逻辑说明
- 先从输入字节流的头部提取
size_t参数(字节序与系统保持一致); - 剩余字节用
'\0'分割成多个字符串,存入std::vector<std::string>; - 全程做边界检查,避免解析时的内存越界。
2. 处理文件名 + size_t参数的API
这类API需要把模糊输入写入临时文件,再传递文件名给目标函数,示例代码:
#include <cstdio> #include <cstdlib> #include <unistd.h> // 假设你的目标API声明 void MyAPI(const char* filename, size_t buffer_size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size == 0) return 0; // 创建临时文件(自动生成唯一文件名) char temp_path[] = "/tmp/fuzz_temp_XXXXXX"; int fd = mkstemp(temp_path); if (fd == -1) return 0; // 写入模糊数据到临时文件 ssize_t written = write(fd, Data, Size); close(fd); // 校验写入是否完整,失败则清理退出 if (written != static_cast<ssize_t>(Size)) { remove(temp_path); return 0; } // 解析size_t参数:这里从输入头部提取,可根据API逻辑调整 size_t param_size = 0; if (Size >= sizeof(size_t)) { param_size = *reinterpret_cast<const size_t*>(Data); } // 调用目标API MyAPI(temp_path, param_size); // 清理临时文件 remove(temp_path); return 0; }
调用逻辑说明
- 用
mkstemp创建安全的临时文件,避免文件名冲突; - 将libFuzzer的字节流写入临时文件后,传递文件名给API;
- 调用完成后必须删除临时文件,避免磁盘占用;
size_t参数的解析方式可灵活调整(比如从文件内容中提取,或用固定偏移)。
3. 语料库相关问题解答
语料库定义
语料库是一组符合目标API输入格式的测试文件集合,libFuzzer会基于这些初始输入进行变异、交叉,生成更多高效的测试用例,能大幅提升BUG触发效率。
初始语料库设置
- 创建语料库目录:比如
mkdir fuzz_corpus; - 添加初始测试文件:
- 针对第一个API:创建文件
fuzz_corpus/test_vec,内容格式为「8字节size_t值 + 多个'\0'分隔的字符串」,比如十六进制写入03 00 00 00 00 00 00 00 61 00 62 62 00 63 63 63 00(对应size_t=3,三个字符串"a"、"bb"、"ccc"); - 针对第二个API:直接放入几个真实场景下的文件内容(比如配置文件、日志片段等);
- 针对第一个API:创建文件
- 指定语料库运行Fuzzer:编译后的fuzzer运行时添加目录参数:
./my_fuzzer -use_value_profile=1 fuzz_corpus/
内容的提问来源于stack exchange,提问作者fghoussen
相关产品推荐
相关产品推荐

