You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为自定义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触发效率。

初始语料库设置

  1. 创建语料库目录:比如mkdir fuzz_corpus;
  2. 添加初始测试文件:
    • 针对第一个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:直接放入几个真实场景下的文件内容(比如配置文件、日志片段等);
  3. 指定语料库运行Fuzzer:编译后的fuzzer运行时添加目录参数:./my_fuzzer -use_value_profile=1 fuzz_corpus/

内容的提问来源于stack exchange,提问作者fghoussen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:10:25