-
-
[原创]libFuzzer模糊测试引擎调研与自定义开发
-
发表于: 2024-10-4 15:19 7575
-
项目地址:llvm-project/compiler-rt/lib/fuzzer at main · llvm/llvm-project (github.com)
libFuzzer 是由 LLVM 项目开发的覆盖率引导模糊测试引擎,广泛用于自动发现软件中的漏洞和错误。它通过不断生成和测试输入数据,提高代码覆盖率,找到潜在的缺陷。libFuzzer 尤其适合测试用 C 和 C++ 编写的代码。
libFuzzer 是一个面向库的模糊测试引擎,广泛用于发现软件中的漏洞。了解其模块结构有助于深入理解其工作原理和扩展能力。以下是 libFuzzer 的主要模块结构:
libFuzzer 的主要功能包括:
源码位置:llvm-project/compiler-rt/lib/fuzzer at main · llvm/llvm-project (github.com)
这个 Fuzzer
类的构成可以分为以下几个部分:
主要功能函数:
时间与状态函数:
静态回调函数(Static Callback Functions):
其他功能函数:
这个类主要涉及模糊测试的核心功能,包括种子语料库的处理、崩溃管理、变异调度、统计信息打印等多个方面。
Libfuzzer源码学习项目:Dor1s/libfuzzer-workshop: Repository for materials of "Modern fuzzing of C/C++ Projects" workshop. (github.com)
libfuzzer最新源码位置:llvm-project/compiler-rt/lib/fuzzer at main · llvm/llvm-project (github.com)
源码讲解:https://www.bilibili.com/video/BV1RH4y1r74p/?spm_id_from=333.788
libFuzzer 是 LLVM 项目中的一部分,专门用于通过模糊测试来自动化测试 C/C++ 项目中的漏洞。其核心流程大致分为以下几个步骤:
主函数入口代码如下:
在这个主函数中,调用了 fuzzer::FuzzerDriver
函数,并传入了用户定义的 LLVMFuzzerTestOneInput
函数。LLVMFuzzerTestOneInput
是由用户编写的,用于定义模糊测试的目标函数,它接收输入数据进行测试并返回测试结果。FuzzerDriver
函数则负责模糊测试的核心逻辑。
FuzzerDriver
是 libFuzzer 的核心函数,它的主要作用是设置和启动模糊测试。函数签名如下:
核心步骤包括:
主循环 (Fuzzer::Loop):Loop
是 libFuzzer 中用于执行模糊测试的核心循环。它会不断从语料库中提取输入数据,进行输入变异,并将变异后的输入传递给 LLVMFuzzerTestOneInput
进行测试。循环的目的是通过广泛探索输入空间,发现导致程序崩溃或行为异常的输入,从而发现潜在的漏洞。
变异引擎:MutationDispatcher
是 libFuzzer 的变异引擎,它会生成各种输入数据变种,覆盖尽可能多的代码路径。变异策略包括:
测试结果收集:
每次输入变异后,libFuzzer 会将结果反馈给 Fuzzer
对象,判断程序是否崩溃或异常。出现崩溃时,libFuzzer 会记录触发崩溃的输入,并终止循环进行进一步分析。
更多版本:Release LLVM 18.1.8 · llvm/llvm-project (github.com)
libFuzzer的源码根据需要下载对应版本进行源码编译。
一键配置clang脚本:,该脚本在Ubuntu20上成功测试运行过:
与覆盖率相关的选项如下:
以下是与覆盖率相关的选项的使用方法和案例说明:
在libfuzzer中有很多命令并未实现可以自行寻找,这是在vscode匹配命令选项的正则表达式:Options\.\w+\s*=\s*Flags\.\w+
;
为了满足以下二次开发需求:
首先,修改 libFuzzer/FuzzerLoop.cpp
,增加用于导出模糊测试过程中数据的接口。我们可以通过直接修改 libFuzzer 的覆盖率部分,创建接口来收集并输出信息。下面是覆盖率和其他统计信息的部分代码片段:
在 Fuzzer::PrintStats
函数中,我们已经将覆盖率、执行次数、内存使用情况等统计信息打印,并通过 ExportDataToFrontend
函数导出到外部系统,可以进一步传递到前端页面。
要实现 libFuzzer 的持久模糊测试,并且避免在发现 crash 后终止,可以通过修改 libFuzzer 源码来调整其行为。libFuzzer 默认行为是当检测到崩溃(如非法内存访问、堆溢出等)时终止模糊测试。为了避免这种情况,目标是允许 fuzzing 继续进行而不退出。
定位崩溃处理逻辑:
libFuzzer 在检测到 crash 后会调用 LLVMFuzzerTestOneInput
,这段代码可能会引发未处理异常,导致 fuzzing 过程终止。我们可以通过修改 libFuzzer 的 crash 处理逻辑,使其在崩溃时记录问题但继续模糊测试。
关键代码修改点:
需要查找 libFuzzer 源码中的崩溃处理位置,一般在 FuzzerLoop.cpp
和 FuzzerDriver.cpp
文件中。
持久化模糊测试的入口:
如果你想让模糊测试保持“持久化”,即反复利用同一测试环境进行测试,可以在 FuzzerLoop.cpp
中引入一个持久化模式(Persistent Mode)。这种模式会允许测试继续,而不是每次退出。
实现持久化模式:
在 FuzzerLoop.cpp
中找到模糊测试的主要循环。将其改成持久化循环模式,像这样:
捕获崩溃并继续测试:
修改 libFuzzer 中的 FuzzerDriver.cpp
文件,让崩溃不会终止程序。可以在捕获崩溃的地方加入 try-catch
或平台相关的异常处理机制,确保在崩溃时记录并恢复。
处理信号(Signal Handling):
在某些情况下,libFuzzer 可能通过信号(如 SIGSEGV, SIGABRT)来处理崩溃。你可以修改信号处理函数,确保信号不会导致进程终止。
编译脚本文件路径:llvm-project/compiler-rt/lib/fuzzer/build.sh at main · llvm/llvm-project (github.com)
在完成代码修改后,需要重新编译 libFuzzer 生成 libFuzzer.a
静态库。可以使用如下编译脚本:
将修改后的源码放置到 libFuzzer 源码目录,运行该脚本编译,生成一个 libFuzzer.a
静态库,用于后续的模糊测试项目链接使用。
自定义的libFuzzer的使用方式:
这里的libFuzzer.a是自己使用项目提供的build.sh编译出来的版本,还可以添加其他编译选项自行添加!
教程地址:fuzzing/tutorial/libFuzzerTutorial.md 在 master ·谷歌/模糊测试 (github.com)
文件位置:FTS/woff2-2016-05-06/target.cc
准备对:CVE-2014-0160 进行复现
漏洞原理:OpenSSL 心脏滴血漏洞(CVE-2014-0160)漏洞讲解(小白可懂,简单详细)-CSDN博客
使用github项目已经准备好的编译脚本:
创建一个包含 LLVMFuzzerTestOneInput
函数的模糊测试目标:
文件所在路径:fuzzer-test-suite/openssl-1.0.1f
在项目根目录中,运行以下命令编译模糊测试目标,详细的编译选项可以查看build.sh :
在项目根目录中,运行以下命令开始模糊测试,成功跑出堆溢出漏洞:
#include "FuzzerDefs.h"
extern
"C"
{
// 该函数由用户定义,用于测试目标函数
int
LLVMFuzzerTestOneInput(
const
uint8_t *Data,
size_t
Size);
}
// extern "C"
ATTRIBUTE_INTERFACE
int
main(
int
argc,
char
**argv) {
return
fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);
}
#include "FuzzerDefs.h"
extern
"C"
{
// 该函数由用户定义,用于测试目标函数
int
LLVMFuzzerTestOneInput(
const
uint8_t *Data,
size_t
Size);
}
// extern "C"
ATTRIBUTE_INTERFACE
int
main(
int
argc,
char
**argv) {
return
fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);
}
int
FuzzerDriver(
int
*argc,
char
***argv, UserCallback Callback) {
// 进行对象初始化
auto
*MD =
new
MutationDispatcher(Rand, Options);
auto
*Corpus =
new
InputCorpus(Options.OutputCorpus);
auto
*F =
new
Fuzzer(Callback, *Corpus, *MD, Options);
// 解析命令选项
...
// 读取并处理输入的语料库文件,传入模糊测试主循环
auto
CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs));
F->Loop(CorporaFiles);
}
int
FuzzerDriver(
int
*argc,
char
***argv, UserCallback Callback) {
// 进行对象初始化
auto
*MD =
new
MutationDispatcher(Rand, Options);
auto
*Corpus =
new
InputCorpus(Options.OutputCorpus);
auto
*F =
new
Fuzzer(Callback, *Corpus, *MD, Options);
// 解析命令选项
...
// 读取并处理输入的语料库文件,传入模糊测试主循环
auto
CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs));
F->Loop(CorporaFiles);
}
#!/bin/bash
# 安装 Clang 的依赖
sudo
apt-get --
yes
install
curl subversion
screen
gcc g++ cmake ninja-build golang autoconf libtool apache2 python-dev pkg-config zlib1g-dev libgcrypt20-dev libgss-dev libssl-dev libxml2-dev ragel nasm libarchive-dev
make
automake libdbus-1-dev libboost-dev autoconf-archive libtinfo5
# 定义 Clang 的版本和下载链接
CLANG_VERSION=
"18.1.8"
CLANG_TAR=
"clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-18.04.tar.xz"
CLANG_URL=
"https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/${CLANG_TAR}"
CLANG_INSTALL_DIR=
"/usr/local/clang-${CLANG_VERSION}"
# 检查 Clang 是否已下载
if
[ -f
"${CLANG_TAR}"
];
then
echo
"Clang 已经下载 (${CLANG_TAR})"
else
echo
"正在下载 Clang..."
wget
"${CLANG_URL}"
fi
# 检查 Clang 是否已安装
if
[ -d
"${CLANG_INSTALL_DIR}"
];
then
echo
"Clang 已经安装在 ${CLANG_INSTALL_DIR}"
else
echo
"正在安装 Clang..."
# 创建目录
sudo
mkdir
-p
"${CLANG_INSTALL_DIR}"
echo
"正在安装 解压时间比较久..."
# 解压 Clang
sudo
tar
-xf
"${CLANG_TAR}"
-C
"${CLANG_INSTALL_DIR}"
--strip-components=1
fi
# 检查环境变量是否已经设置
if
!
grep
-q
"${CLANG_INSTALL_DIR}/bin"
~/.bashrc;
then
echo
"添加环境变量..."
echo
"export PATH=${CLANG_INSTALL_DIR}/bin:\$PATH"
>> ~/.bashrc
echo
"export LD_LIBRARY_PATH=${CLANG_INSTALL_DIR}/lib:\$LD_LIBRARY_PATH"
>> ~/.bashrc
# 使环境变量生效
source
~/.bashrc
else
echo
"环境变量已经配置"
fi
# 运行 Clang 验证安装
echo
"验证 Clang 安装..."
clang --version
echo
"如果验证失败再次运行该命令: source ~/.bashrc"
#!/bin/bash
# 安装 Clang 的依赖
sudo
apt-get --
yes
install
curl subversion
screen
gcc g++ cmake ninja-build golang autoconf libtool apache2 python-dev pkg-config zlib1g-dev libgcrypt20-dev libgss-dev libssl-dev libxml2-dev ragel nasm libarchive-dev
make
automake libdbus-1-dev libboost-dev autoconf-archive libtinfo5
# 定义 Clang 的版本和下载链接
CLANG_VERSION=
"18.1.8"
CLANG_TAR=
"clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-18.04.tar.xz"
CLANG_URL=
"https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/${CLANG_TAR}"
CLANG_INSTALL_DIR=
"/usr/local/clang-${CLANG_VERSION}"
# 检查 Clang 是否已下载
if
[ -f
"${CLANG_TAR}"
];
then
echo
"Clang 已经下载 (${CLANG_TAR})"
else
echo
"正在下载 Clang..."
wget
"${CLANG_URL}"
fi
# 检查 Clang 是否已安装
if
[ -d
"${CLANG_INSTALL_DIR}"
];
then
echo
"Clang 已经安装在 ${CLANG_INSTALL_DIR}"
else
echo
"正在安装 Clang..."
# 创建目录
sudo
mkdir
-p
"${CLANG_INSTALL_DIR}"
echo
"正在安装 解压时间比较久..."
# 解压 Clang
sudo
tar
-xf
"${CLANG_TAR}"
-C
"${CLANG_INSTALL_DIR}"
--strip-components=1
fi
# 检查环境变量是否已经设置
if
!
grep
-q
"${CLANG_INSTALL_DIR}/bin"
~/.bashrc;
then
echo
"添加环境变量..."
echo
"export PATH=${CLANG_INSTALL_DIR}/bin:\$PATH"
>> ~/.bashrc
echo
"export LD_LIBRARY_PATH=${CLANG_INSTALL_DIR}/lib:\$LD_LIBRARY_PATH"
>> ~/.bashrc
# 使环境变量生效
source
~/.bashrc
else
echo
"环境变量已经配置"
fi
# 运行 Clang 验证安装
echo
"验证 Clang 安装..."
clang --version
echo
"如果验证失败再次运行该命令: source ~/.bashrc"
// 是否打印新覆盖的 PC 地址
Options.PrintNewCovPcs = Flags.print_pcs;
// 是否打印新覆盖的函数
Options.PrintNewCovFuncs = Flags.print_funcs;
// 是否打印覆盖率信息
Options.PrintCoverage = Flags.print_coverage;
// 是否打印完整的覆盖率信息
Options.PrintFullCoverage = Flags.print_full_coverage;
// 是否打印新覆盖的 PC 地址
Options.PrintNewCovPcs = Flags.print_pcs;
// 是否打印新覆盖的函数
Options.PrintNewCovFuncs = Flags.print_funcs;
// 是否打印覆盖率信息
Options.PrintCoverage = Flags.print_coverage;
// 是否打印完整的覆盖率信息
Options.PrintFullCoverage = Flags.print_full_coverage;
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_pcs=1
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_pcs=1
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
2544448443
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x562f5c3345c0
,
0x562f5c336f94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x562f5c336f98
,
0x562f5c360cd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
NEW_PC:
0x562f5c220771
in
ReadWOFF2Header
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
woff2_dec.cc:
987
:
7
#21 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 33Mb L: 4/4 MS: 4 CrossOver-InsertByte-ChangeBit-CopyPart-
NEW_PC:
0x562f5c2161a8
in
ReadU32
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
.
/
buffer
.h:
127
:
9
#999 NEW cov: 17 ft: 18 corp: 3/9b lim: 11 exec/s: 0 rss: 34Mb L: 4/4 MS: 3 ChangeByte-ShuffleBytes-CMP- DE: "wOF2"-
NEW_PC:
0x562f5c22077c
in
ReadU32
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
.
/
buffer
.h:
127
:
9
#1300 NEW cov: 18 ft: 19 corp: 4/17b lim: 11 exec/s: 0 rss: 34Mb L: 8/8 MS: 1 PersAutoDict- DE: "wOF2"-
NEW_PC:
0x562f5c22103f
in
ReadWOFF2Header
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
woff2_dec.cc:
995
:
7
#1618 NEW cov: 19 ft: 20 corp: 5/29b lim: 14 exec/s: 0 rss: 34Mb L: 12/12 MS: 3 InsertRepeatedBytes-PersAutoDict-InsertRepeatedBytes- DE: "wOF2"-
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
2544448443
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x562f5c3345c0
,
0x562f5c336f94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x562f5c336f98
,
0x562f5c360cd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
NEW_PC:
0x562f5c220771
in
ReadWOFF2Header
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
woff2_dec.cc:
987
:
7
#21 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 33Mb L: 4/4 MS: 4 CrossOver-InsertByte-ChangeBit-CopyPart-
NEW_PC:
0x562f5c2161a8
in
ReadU32
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
.
/
buffer
.h:
127
:
9
#999 NEW cov: 17 ft: 18 corp: 3/9b lim: 11 exec/s: 0 rss: 34Mb L: 4/4 MS: 3 ChangeByte-ShuffleBytes-CMP- DE: "wOF2"-
NEW_PC:
0x562f5c22077c
in
ReadU32
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
.
/
buffer
.h:
127
:
9
#1300 NEW cov: 18 ft: 19 corp: 4/17b lim: 11 exec/s: 0 rss: 34Mb L: 8/8 MS: 1 PersAutoDict- DE: "wOF2"-
NEW_PC:
0x562f5c22103f
in
ReadWOFF2Header
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
woff2_dec.cc:
995
:
7
#1618 NEW cov: 19 ft: 20 corp: 5/29b lim: 14 exec/s: 0 rss: 34Mb L: 12/12 MS: 3 InsertRepeatedBytes-PersAutoDict-InsertRepeatedBytes- DE: "wOF2"-
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_funcs=1
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_funcs=1
ub20@ub20:~
/
FTS
/
woff$ .
/
woff2
-
2016
-
05
-
06
-
fsanitize_fuzzer
-
print_funcs
=
1
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
2688967800
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x55b819abf5c0
,
0x55b819ac1f94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x55b819ac1f98
,
0x55b819aebcd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
#10 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 32Mb L: 4/4 MS: 3 CrossOver-InsertByte-CrossOver-
...
#144927 NEW cov: 29 ft: 30 corp: 14/437b lim: 1390 exec/s: 48309 rss: 47Mb L: 119/119 MS: 1 PersAutoDict- DE: "\012\000\000\000\000\000\000\000"-
NEW_FUNC[
1
/
1
]:
0x55b8199a0050
in
woff2::ReadBase128(woff2::
Buffer
*
, unsigned
int
*
)
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
variable_length.cc:
94
...
ub20@ub20:~
/
FTS
/
woff$ .
/
woff2
-
2016
-
05
-
06
-
fsanitize_fuzzer
-
print_funcs
=
1
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
2688967800
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x55b819abf5c0
,
0x55b819ac1f94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x55b819ac1f98
,
0x55b819aebcd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
#10 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 32Mb L: 4/4 MS: 3 CrossOver-InsertByte-CrossOver-
...
#144927 NEW cov: 29 ft: 30 corp: 14/437b lim: 1390 exec/s: 48309 rss: 47Mb L: 119/119 MS: 1 PersAutoDict- DE: "\012\000\000\000\000\000\000\000"-
NEW_FUNC[
1
/
1
]:
0x55b8199a0050
in
woff2::ReadBase128(woff2::
Buffer
*
, unsigned
int
*
)
/
home
/
ub20
/
FTS
/
woff
/
SRC
/
src
/
variable_length.cc:
94
...
.
/openssl-1
.0.1f-fsanitize_fuzzer -print_coverage=1
.
/openssl-1
.0.1f-fsanitize_fuzzer -print_coverage=1
UNCOVERED_FUNC: hits:
0
edges:
0
/
5
Init()
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
9
COVERED_FUNC: hits:
42
edges:
2
/
5
LLVMFuzzerTestOneInput
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
26
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
27
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
27
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
0
COVERED_FUNC: hits:
42
edges:
19
/
34
ssleay_rand_add
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
194
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
228
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
228
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
249
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
249
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
260
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
263
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
266
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
294
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
294
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
0
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
306
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
0
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
311
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
321
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
322
UNCOVERED_FUNC: hits:
0
edges:
0
/
5
Init()
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
9
COVERED_FUNC: hits:
42
edges:
2
/
5
LLVMFuzzerTestOneInput
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
26
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
27
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
27
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f
/
target.cc:
0
COVERED_FUNC: hits:
42
edges:
19
/
34
ssleay_rand_add
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
194
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
228
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
228
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
249
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
249
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
260
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
263
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
266
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
294
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
294
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
0
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
306
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
0
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
311
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
321
UNCOVERED_PC:
/
home
/
ub20
/
FTS
/
openssl
-
1.0
.
1f_crash
/
BUILD
/
crypto
/
rand
/
md_rand.c:
322
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_full_coverage=1
.
/woff2-2016-05-06-fsanitize_fuzzer
-print_full_coverage=1
ub20@ub20:~
/
FTS
/
woff$ .
/
woff2
-
2016
-
05
-
06
-
fsanitize_fuzzer
-
print_coverage
=
1
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
3116423339
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x5652816785c0
,
0x56528167af94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x56528167af98
,
0x5652816a4cd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
#27 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 33Mb L: 4/4 MS: 5 ChangeBit-ChangeBit-ChangeBinInt-CopyPart-CopyPart-
#433 NEW cov: 17 ft: 18 corp: 3/10b lim: 6 exec/s: 0 rss: 33Mb L: 5/5 MS: 1 CMP- DE: "wOF2"-
#636 REDUCE cov: 17 ft: 18 corp: 3/9b lim: 6 exec/s: 0 rss: 33Mb L: 4/4 MS: 3 ShuffleBytes-ChangeBit-EraseBytes-
#884 REDUCE cov: 18 ft: 19 corp: 4/17b lim: 8 exec/s: 0 rss: 34Mb L: 8/8 MS: 3 InsertRepeatedBytes-ChangeByte-PersAutoDict- DE: "wOF2"-
#1635 NEW cov: 19 ft: 20 corp: 5/29b lim: 14 exec/s: 0 rss: 34Mb L: 12/12 MS: 1 CrossOver-
#3505 NEW cov: 20 ft: 21 corp: 6/58b lim: 29 exec/s: 0 rss: 35Mb L: 29/29 MS: 5 PersAutoDict-CrossOver-InsertRepeatedBytes-ChangeByte-ChangeBinInt- DE: "wOF2"-
#4629 NEW cov: 21 ft: 22 corp: 7/87b lim: 38 exec/s: 0 rss: 35Mb L: 29/29 MS: 4 ChangeBit-CopyPart-ShuffleBytes-ChangeBit-
#9279 REDUCE cov: 21 ft: 22 corp: 7/72b lim: 80 exec/s: 0 rss: 35Mb L: 14/29 MS: 5 EraseBytes-EraseBytes-ChangeBit-EraseBytes-ChangeBinInt-
#9535 REDUCE cov: 22 ft: 23 corp: 8/86b lim: 80 exec/s: 0 rss: 35Mb L: 14/29 MS: 1 ChangeByte-
#27928 REDUCE cov: 23 ft: 24 corp: 9/99b lim: 261 exec/s: 0 rss: 37Mb L: 13/29 MS: 3 ChangeBit-EraseBytes-ChangeBinInt-
#31817 NEW cov: 24 ft: 25 corp: 10/120b lim: 293 exec/s: 0 rss: 37Mb L: 21/29 MS: 4 ChangeBit-EraseBytes-ChangeBit-ChangeBinInt-
#40024 REDUCE cov: 24 ft: 25 corp: 10/119b lim: 373 exec/s: 0 rss: 38Mb L: 12/29 MS: 2 EraseBytes-CMP- DE: "\001\000\000\000\000\000\000\014"-
#42588 NEW cov: 25 ft: 26 corp: 11/155b lim: 397 exec/s: 0 rss: 38Mb L: 36/36 MS: 4 CrossOver-CopyPart-InsertByte-ChangeBinInt-
^C
=
=
12029
=
=
libFuzzer: run interrupted; exiting
COVERAGE:
UNCOVERED_FUNC: hits:
0
edges:
0
/
19
brotli::ZopfliCreateCommands(unsigned
long
, unsigned
long
, unsigned
long
, std::vector<unsigned
int
, std::allocator<unsigned
int
>> const&, brotli::ZopfliNode const
*
,
int
*
, unsigned
long
*
, brotli::Command
*
, unsigned
long
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
437
UNCOVERED_FUNC: hits:
0
edges:
0
/
18
brotli::Command::Command(unsigned
long
, unsigned
long
, unsigned
long
, unsigned
long
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
.
/
.
/
command.h:
102
UNCOVERED_FUNC: hits:
0
edges:
0
/
31
brotli::ZopfliComputeShortestPath(unsigned
long
, unsigned
long
, unsigned char const
*
, unsigned
long
, unsigned
long
,
int
const
*
, brotli::HashToBinaryTree
*
, brotli::ZopfliNode
*
, std::vector<unsigned
int
, std::allocator<unsigned
int
>>
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
510
UNCOVERED_FUNC: hits:
0
edges:
0
/
27
brotli::ZopfliCostModel::SetFromLiteralCosts(unsigned
long
, unsigned
long
, unsigned char const
*
, unsigned
long
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
77
UNCOVERED_FUNC: hits:
0
edges:
0
/
44
brotli::HashToBinaryTree::FindAllMatches(unsigned char const
*
, unsigned
long
, unsigned
long
, unsigned
long
, unsigned
long
, brotli::BackwardMatch
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
.
/
.
/
hash
.h:
681
...
ub20@ub20:~
/
FTS
/
woff$ .
/
woff2
-
2016
-
05
-
06
-
fsanitize_fuzzer
-
print_coverage
=
1
INFO: Running with entropic power schedule (
0xFF
,
100
).
INFO: Seed:
3116423339
INFO: Loaded
1
modules (
10708
inline
8
-
bit counters):
10708
[
0x5652816785c0
,
0x56528167af94
),
INFO: Loaded
1
PC tables (
10708
PCs):
10708
[
0x56528167af98
,
0x5652816a4cd8
),
INFO:
-
max_len
is
not
provided; libFuzzer will
not
generate inputs larger than
4096
bytes
INFO: A corpus
is
not
provided, starting
from
an empty corpus
#2 INITED cov: 15 ft: 16 corp: 1/1b exec/s: 0 rss: 32Mb
#27 NEW cov: 16 ft: 17 corp: 2/5b lim: 4 exec/s: 0 rss: 33Mb L: 4/4 MS: 5 ChangeBit-ChangeBit-ChangeBinInt-CopyPart-CopyPart-
#433 NEW cov: 17 ft: 18 corp: 3/10b lim: 6 exec/s: 0 rss: 33Mb L: 5/5 MS: 1 CMP- DE: "wOF2"-
#636 REDUCE cov: 17 ft: 18 corp: 3/9b lim: 6 exec/s: 0 rss: 33Mb L: 4/4 MS: 3 ShuffleBytes-ChangeBit-EraseBytes-
#884 REDUCE cov: 18 ft: 19 corp: 4/17b lim: 8 exec/s: 0 rss: 34Mb L: 8/8 MS: 3 InsertRepeatedBytes-ChangeByte-PersAutoDict- DE: "wOF2"-
#1635 NEW cov: 19 ft: 20 corp: 5/29b lim: 14 exec/s: 0 rss: 34Mb L: 12/12 MS: 1 CrossOver-
#3505 NEW cov: 20 ft: 21 corp: 6/58b lim: 29 exec/s: 0 rss: 35Mb L: 29/29 MS: 5 PersAutoDict-CrossOver-InsertRepeatedBytes-ChangeByte-ChangeBinInt- DE: "wOF2"-
#4629 NEW cov: 21 ft: 22 corp: 7/87b lim: 38 exec/s: 0 rss: 35Mb L: 29/29 MS: 4 ChangeBit-CopyPart-ShuffleBytes-ChangeBit-
#9279 REDUCE cov: 21 ft: 22 corp: 7/72b lim: 80 exec/s: 0 rss: 35Mb L: 14/29 MS: 5 EraseBytes-EraseBytes-ChangeBit-EraseBytes-ChangeBinInt-
#9535 REDUCE cov: 22 ft: 23 corp: 8/86b lim: 80 exec/s: 0 rss: 35Mb L: 14/29 MS: 1 ChangeByte-
#27928 REDUCE cov: 23 ft: 24 corp: 9/99b lim: 261 exec/s: 0 rss: 37Mb L: 13/29 MS: 3 ChangeBit-EraseBytes-ChangeBinInt-
#31817 NEW cov: 24 ft: 25 corp: 10/120b lim: 293 exec/s: 0 rss: 37Mb L: 21/29 MS: 4 ChangeBit-EraseBytes-ChangeBit-ChangeBinInt-
#40024 REDUCE cov: 24 ft: 25 corp: 10/119b lim: 373 exec/s: 0 rss: 38Mb L: 12/29 MS: 2 EraseBytes-CMP- DE: "\001\000\000\000\000\000\000\014"-
#42588 NEW cov: 25 ft: 26 corp: 11/155b lim: 397 exec/s: 0 rss: 38Mb L: 36/36 MS: 4 CrossOver-CopyPart-InsertByte-ChangeBinInt-
^C
=
=
12029
=
=
libFuzzer: run interrupted; exiting
COVERAGE:
UNCOVERED_FUNC: hits:
0
edges:
0
/
19
brotli::ZopfliCreateCommands(unsigned
long
, unsigned
long
, unsigned
long
, std::vector<unsigned
int
, std::allocator<unsigned
int
>> const&, brotli::ZopfliNode const
*
,
int
*
, unsigned
long
*
, brotli::Command
*
, unsigned
long
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
437
UNCOVERED_FUNC: hits:
0
edges:
0
/
18
brotli::Command::Command(unsigned
long
, unsigned
long
, unsigned
long
, unsigned
long
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
.
/
.
/
command.h:
102
UNCOVERED_FUNC: hits:
0
edges:
0
/
31
brotli::ZopfliComputeShortestPath(unsigned
long
, unsigned
long
, unsigned char const
*
, unsigned
long
, unsigned
long
,
int
const
*
, brotli::HashToBinaryTree
*
, brotli::ZopfliNode
*
, std::vector<unsigned
int
, std::allocator<unsigned
int
>>
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
510
UNCOVERED_FUNC: hits:
0
edges:
0
/
27
brotli::ZopfliCostModel::SetFromLiteralCosts(unsigned
long
, unsigned
long
, unsigned char const
*
, unsigned
long
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
backward_references.cc:
77
UNCOVERED_FUNC: hits:
0
edges:
0
/
44
brotli::HashToBinaryTree::FindAllMatches(unsigned char const
*
, unsigned
long
, unsigned
long
, unsigned
long
, unsigned
long
, brotli::BackwardMatch
*
)
/
home
/
ub20
/
FTS
/
woff
/
BROTLI
/
enc
/
.
/
.
/
hash
.h:
681
...
/
/
设置详细程度的级别
Options.Verbosity
=
Flags.verbosity;
/
/
设置最大输入长度
Options.MaxLen
=
Flags.max_len;
...
/
/
是否处理 SIGINT 信号
Options.HandleInt
=
Flags.handle_int;
/
/
是否处理 SIGSEGV 信号
Options.HandleSegv
=
Flags.handle_segv;
/
/
是否处理 SIGTERM 信号
Options.HandleTerm
=
Flags.handle_term;
/
/
是否处理 SIGXFSZ 信号
Options.HandleXfsz
=
Flags.handle_xfsz;
/
/
是否处理 SIGUSR1 信号
Options.HandleUsr1
=
Flags.handle_usr1;
/
/
是否处理 SIGUSR2 信号
Options.HandleUsr2
=
Flags.handle_usr2;
/
/
是否处理 Windows 异常
Options.HandleWinExcept
=
Flags.handle_winexcept;
/
/
是否启用分叉的种子组
Options.ForkCorpusGroups
=
Flags.fork_corpus_groups;
/
/
设置详细程度的级别
Options.Verbosity
=
Flags.verbosity;
/
/
设置最大输入长度
Options.MaxLen
=
Flags.max_len;
...
/
/
是否处理 SIGINT 信号
Options.HandleInt
=
Flags.handle_int;
/
/
是否处理 SIGSEGV 信号
Options.HandleSegv
=
Flags.handle_segv;
/
/
是否处理 SIGTERM 信号
Options.HandleTerm
=
Flags.handle_term;
/
/
是否处理 SIGXFSZ 信号
Options.HandleXfsz
=
Flags.handle_xfsz;
/
/
是否处理 SIGUSR1 信号
Options.HandleUsr1
=
Flags.handle_usr1;
/
/
是否处理 SIGUSR2 信号
Options.HandleUsr2
=
Flags.handle_usr2;
/
/
是否处理 Windows 异常
Options.HandleWinExcept
=
Flags.handle_winexcept;
/
/
是否启用分叉的种子组
Options.ForkCorpusGroups
=
Flags.fork_corpus_groups;
// 返回总的程序计数器覆盖率(PC Coverage)
size_t
GetTotalPCCoverage()
const
{
return
TPC.GetTotalPCCoverage();
}
// 返回发现的特征数量
size_t
GetNumFeatures()
const
{
return
Corpus.NumFeatures();
}
// 返回活跃输入的数量
size_t
GetNumActiveUnits()
const
{
return
Corpus.NumActiveUnits();
}
// 返回语料库大小(以字节为单位)
size_t
GetSizeInBytes()
const
{
return
Corpus.SizeInBytes();
}
// 返回触发重点功能(Focus Function)的输入数量
size_t
GetNumInputsThatTouchFocusFunction()
const
{
return
Corpus.NumInputsThatTouchFocusFunction();
}
// 返回每秒执行次数
size_t
GetExecPerSec()
const
{
return
execPerSec();
}
// 返回临时最大变异长度
size_t
GetTmpMaxMutationLen()
const
{
return
TmpMaxMutationLen;
}
// 返回峰值内存使用量(以MB为单位)
size_t
GetPeakRSSMb()
const
{
return
GetPeakRSSMb();
}
// 打印模糊测试的统计信息并导出数据
void
Fuzzer::PrintStats(
const
char
*Where,
const
char
*End,
size_t
Units,
size_t
Features) {
size_t
ExecPerSec = GetExecPerSec();
if
(!Options.Verbosity)
return
;
Printf(
"#%zd\t%s"
, TotalNumberOfRuns, Where);
if
(
size_t
N = GetTotalPCCoverage())
Printf(
" cov: %zd"
, N);
if
(
size_t
N = Features ? Features : GetNumFeatures())
Printf(
" ft: %zd"
, N);
if
(!Corpus.empty()) {
Printf(
" corp: %zd"
, GetNumActiveUnits());
if
(
size_t
N = GetSizeInBytes()) {
if
(N < (1 << 14))
Printf(
"/%zdb"
, N);
else
if
(N < (1 << 24))
Printf(
"/%zdKb"
, N >> 10);
else
Printf(
"/%zdMb"
, N >> 20);
}
if
(
size_t
FF = GetNumInputsThatTouchFocusFunction())
Printf(
" focus: %zd"
, FF);
}
if
(
size_t
Lim = GetTmpMaxMutationLen())
Printf(
" lim: %zd"
, Lim);
if
(Units)
Printf(
" units: %zd"
, Units);
Printf(
" exec/s: %zd"
, ExecPerSec);
Printf(
" rss: %zdMb"
, GetPeakRSSMb());
// 添加魔改标识
Printf(
" [MODIFIED] Custom version of Fuzzer::PrintStats is running!\n"
);
// 输出结束符
Printf(
"%s"
, End);
// 可以在这里添加接口将数据传递到前端
ExportDataToFrontend({
{
"TotalNumberOfRuns"
, TotalNumberOfRuns},
{
"PCCoverage"
, GetTotalPCCoverage()},
{
"NumFeatures"
, GetNumFeatures()},
{
"NumActiveUnits"
, GetNumActiveUnits()},
{
"SizeInBytes"
, GetSizeInBytes()},
{
"ExecPerSec"
, GetExecPerSec()},
{
"PeakRSSMb"
, GetPeakRSSMb()}
});
}
// 示例数据导出函数,可将数据通过接口传递给前端
void
ExportDataToFrontend(
const
std::map<std::string,
size_t
>& data) {
// 通过网络接口、文件、或者其他方式将数据传递到前端页面
// 这里可以通过 JSON 格式将数据发送到 HTTP 服务器或 WebSocket
}
// 返回总的程序计数器覆盖率(PC Coverage)
size_t
GetTotalPCCoverage()
const
{
return
TPC.GetTotalPCCoverage();
}
// 返回发现的特征数量
size_t
GetNumFeatures()
const
{
return
Corpus.NumFeatures();
}
// 返回活跃输入的数量
size_t
GetNumActiveUnits()
const
{
return
Corpus.NumActiveUnits();
}
// 返回语料库大小(以字节为单位)
size_t
GetSizeInBytes()
const
{
return
Corpus.SizeInBytes();
}
// 返回触发重点功能(Focus Function)的输入数量
size_t
GetNumInputsThatTouchFocusFunction()
const
{
return
Corpus.NumInputsThatTouchFocusFunction();
}
// 返回每秒执行次数
size_t
GetExecPerSec()
const
{
return
execPerSec();
}
// 返回临时最大变异长度
size_t
GetTmpMaxMutationLen()
const
{
return
TmpMaxMutationLen;
}
// 返回峰值内存使用量(以MB为单位)
size_t
GetPeakRSSMb()
const
{
return
GetPeakRSSMb();
}
// 打印模糊测试的统计信息并导出数据
void
Fuzzer::PrintStats(
const
char
*Where,
const
char
*End,
size_t
Units,
size_t
Features) {
size_t
ExecPerSec = GetExecPerSec();
if
(!Options.Verbosity)
return
;
Printf(
"#%zd\t%s"
, TotalNumberOfRuns, Where);
if
(
size_t
N = GetTotalPCCoverage())
Printf(
" cov: %zd"
, N);
if
(
size_t
N = Features ? Features : GetNumFeatures())
Printf(
" ft: %zd"
, N);
if
(!Corpus.empty()) {
Printf(
" corp: %zd"
, GetNumActiveUnits());
if
(
size_t
N = GetSizeInBytes()) {
if
(N < (1 << 14))
Printf(
"/%zdb"
, N);
else
if
(N < (1 << 24))
Printf(
"/%zdKb"
, N >> 10);
else
Printf(
"/%zdMb"
, N >> 20);
}
if
(
size_t
FF = GetNumInputsThatTouchFocusFunction())
Printf(
" focus: %zd"
, FF);
}
if
(
size_t
Lim = GetTmpMaxMutationLen())
Printf(
" lim: %zd"
, Lim);
if
(Units)
Printf(
" units: %zd"
, Units);
Printf(
" exec/s: %zd"
, ExecPerSec);
Printf(
" rss: %zdMb"
, GetPeakRSSMb());
// 添加魔改标识
Printf(
" [MODIFIED] Custom version of Fuzzer::PrintStats is running!\n"
);
// 输出结束符
Printf(
"%s"
, End);
// 可以在这里添加接口将数据传递到前端
ExportDataToFrontend({
{
"TotalNumberOfRuns"
, TotalNumberOfRuns},
{
"PCCoverage"
, GetTotalPCCoverage()},
{
"NumFeatures"
, GetNumFeatures()},
{
"NumActiveUnits"
, GetNumActiveUnits()},
{
"SizeInBytes"
, GetSizeInBytes()},
{
"ExecPerSec"
, GetExecPerSec()},
{
"PeakRSSMb"
, GetPeakRSSMb()}
});
}
// 示例数据导出函数,可将数据通过接口传递给前端
void
ExportDataToFrontend(
const
std::map<std::string,
size_t
>& data) {
// 通过网络接口、文件、或者其他方式将数据传递到前端页面
// 这里可以通过 JSON 格式将数据发送到 HTTP 服务器或 WebSocket
}
while
(
true
) {
int
result = LLVMFuzzerTestOneInput(Data, Size);
if
(result == 0) {
// 记录崩溃信息,但不终止
// 继续模糊测试循环
continue
;
}
else
{
// 如果检测到崩溃,记录日志或者保存问题
LogCrash();
// 但不要退出程序,继续模糊测试
continue
;
}
}
while
(
true
) {
int
result = LLVMFuzzerTestOneInput(Data, Size);
if
(result == 0) {
// 记录崩溃信息,但不终止
// 继续模糊测试循环
continue
;
}
else
{
// 如果检测到崩溃,记录日志或者保存问题
LogCrash();
// 但不要退出程序,继续模糊测试
continue
;
}
}
try
{
LLVMFuzzerTestOneInput(Data, Size);
}
catch
(...) {
// 捕获异常,记录崩溃,不退出
ReportCrash();
continue
;
// 继续模糊测试
}
try
{
LLVMFuzzerTestOneInput(Data, Size);
}
catch
(...) {
// 捕获异常,记录崩溃,不退出
ReportCrash();
continue
;
// 继续模糊测试
}
signal
(SIGSEGV, HandleSignal);
signal
(SIGABRT, HandleSignal);
void
HandleSignal(
int
signal
) {
// 捕获信号并记录信息
LogSignalCrash(
signal
);
// 继续执行
}
signal
(SIGSEGV, HandleSignal);
signal
(SIGABRT, HandleSignal);
void
HandleSignal(
int
signal
) {
// 捕获信号并记录信息
LogSignalCrash(
signal
);
// 继续执行
}
#!/bin/sh
LIBFUZZER_SRC_DIR=$(
dirname
$0)
CXX=
"${CXX:-clang}"
for
f
in
$LIBFUZZER_SRC_DIR/*.cpp;
do
$CXX -g -O2 -fno-omit-frame-pointer -std=c++17 $f -c &
done
wait
rm
-f libFuzzer.a
ar r libFuzzer.a Fuzzer*.o
rm
-f Fuzzer*.o
#!/bin/sh
LIBFUZZER_SRC_DIR=$(
dirname
$0)
CXX=
"${CXX:-clang}"
for
f
in
$LIBFUZZER_SRC_DIR/*.cpp;
do
$CXX -g -O2 -fno-omit-frame-pointer -std=c++17 $f -c &
done
wait
rm
-f libFuzzer.a
ar r libFuzzer.a Fuzzer*.o
rm
-f Fuzzer*.o
clang
+
+
-
g
-
O1 fuzz_target.cc libFuzzer.a
-
o mytarget_fuzzer
clang
+
+
-
g
-
O1 fuzz_target.cc libFuzzer.a
-
o mytarget_fuzzer
#使用官方案例进行测试
ub20@ub20:~$git clone https:
/
/
github.com
/
google
/
fuzzer
-
test
-
suite.git FTS
ub20@ub20:~$cd FTS; mkdir
-
p woff; cd woff;
ub20@ub20:~$~
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh
#使用官方案例进行测试
ub20@ub20:~$git clone https:
/
/
github.com
/
google
/
fuzzer
-
test
-
suite.git FTS
ub20@ub20:~$cd FTS; mkdir
-
p woff; cd woff;
ub20@ub20:~$~
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh
/
/
Copyright
2016
Google Inc.
All
Rights Reserved.
/
/
Licensed under the Apache License, Version
2.0
(the
"License"
);
#include <stddef.h>
#include <stdint.h>
#include "woff2_dec.h"
/
/
Entry point
for
LibFuzzer.
extern
"C"
int
LLVMFuzzerTestOneInput(const uint8_t
*
data, size_t size) {
std::string buf;
woff2::WOFF2StringOut out(&buf);
out.SetMaxSize(
30
*
1024
*
1024
);
woff2::ConvertWOFF2ToTTF(data, size, &out);
return
0
;
}
/
/
Copyright
2016
Google Inc.
All
Rights Reserved.
/
/
Licensed under the Apache License, Version
2.0
(the
"License"
);
#include <stddef.h>
#include <stdint.h>
#include "woff2_dec.h"
/
/
Entry point
for
LibFuzzer.
extern
"C"
int
LLVMFuzzerTestOneInput(const uint8_t
*
data, size_t size) {
std::string buf;
woff2::WOFF2StringOut out(&buf);
out.SetMaxSize(
30
*
1024
*
1024
);
woff2::ConvertWOFF2ToTTF(data, size, &out);
return
0
;
}
ub20@ub20:~
/
woff$ ~
/
Fuzz
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh
ub20@ub20:~
/
woff$ ~
/
Fuzz
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh
正克隆到
'SRC'
...
remote: Enumerating objects:
1150
, done.
remote: Counting objects:
100
%
(
24
/
24
), done.
remote: Compressing objects:
100
%
(
23
/
23
), done.
remote: Total
1150
(delta
2
), reused
20
(delta
0
), pack
-
reused
1126
(
from
1
)
接收对象中:
100
%
(
1150
/
1150
),
3.48
MiB |
6.03
MiB
/
s, 完成.
处理 delta 中:
100
%
(
680
/
680
), 完成.
...
#编译成功后
ub20@ub20:~
/
woff$ ls
backward_references.o compress_fragment_two_pass.o font.o normalize.o table_tags.o woff2_dec.o
bit_reader.o decode.o glyph.o seeds transform.o woff2_enc.o
block_splitter.o dictionary.o histogram.o SRC utf8_util.o woff2_out.o
BROTLI encode.o huffman.o state.o variable_length.o
brotli_bit_stream.o encode_parallel.o literal_cost.o static_dict.o woff2
-
2016
-
05
-
06
-
fsanitize_fuzzer
compress_fragment.o entropy_encode.o metablock.o streams.o woff2_common.o
ub20@ub20:~
/
woff$ ~
/
Fuzz
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh
ub20@ub20:~
/
woff$ ~
/
Fuzz
/
FTS
/
woff2
-
2016
-
05
-
06
/
build.sh