注释 afl-clang-fast.c afl-tmin.c

main^2
X1A 8 months ago
parent 0ba4a4b23d
commit 87123a176b

File diff suppressed because it is too large Load Diff

@ -28,209 +28,470 @@
of flags, and then calls the real compiler.
*/
#define AFL_MAIN // 定义宏AFL_MAIN
#define AFL_MAIN
#include "../config.h" // 引入配置文件
#include "../types.h" // 引入类型定义文件
#include "../debug.h" // 引入调试相关文件
#include "../alloc-inl.h" // 引入内存分配相关的文件
#include "../config.h"
#include "../types.h"
#include "../debug.h"
#include "../alloc-inl.h"
#include <stdio.h> // 引入标准输入输出库
#include <unistd.h> // 引入UNIX标准库
#include <stdlib.h> // 引入标准库
#include <string.h> // 引入字符串处理库
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
static u8* obj_path; /* 运行时库的路径 */
static u8** cc_params; /* 传递给真实编译器的参数 */
static u32 cc_par_cnt = 1; /* 参数计数初始包含argv0 */
static u8* obj_path; /* Path to runtime libraries */
static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
/* 尝试查找运行时库。如果失败,则中止。 */
/*
*/
static void find_obj(u8* argv0) {
u8 *afl_path = getenv("AFL_PATH"); // 获取环境变量AFL_PATH
u8 *afl_path = getenv("AFL_PATH"); // 获取环境变量 AFL_PATH 的值
u8 *slash, *tmp; // 定义用于存储路径分隔符和临时路径的变量
if (afl_path) { // 如果 AFL_PATH 环境变量存在
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path); // 构造运行时库的路径
if (!access(tmp, R_OK)) { // 检查路径是否可读
obj_path = afl_path; // 如果可读,设置 obj_path 为 AFL_PATH
ck_free(tmp); // 释放临时路径的内存
return; // 返回,结束函数
}
ck_free(tmp); // 如果路径不可读,释放临时路径的内存
}
slash = strrchr(argv0, '/'); // 查找 argv0 中最后一个斜杠的位置
if (slash) { // 如果找到斜杠
u8 *dir; // 定义用于存储目录路径的变量
*slash = 0; // 将斜杠位置置为字符串结束符,以便提取目录路径
dir = ck_strdup(argv0); // 复制 argv0 的目录路径
*slash = '/'; // 恢复斜杠
tmp = alloc_printf("%s/afl-llvm-rt.o", dir); // 构造运行时库的路径
if (!access(tmp, R_OK)) { // 检查路径是否可读
obj_path = dir; // 如果可读,设置 obj_path 为当前目录
ck_free(tmp); // 释放临时路径的内存
return; // 返回,结束函数
}
ck_free(tmp); // 如果路径不可读,释放临时路径的内存
ck_free(dir); // 释放目录路径的内存
}
// 检查默认的 AFL_PATH 目录下是否存在 'afl-llvm-rt.o' 文件
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
obj_path = AFL_PATH; // 如果存在,设置 obj_path 为 AFL_PATH
return; // 返回,结束函数
}
// 如果以上方法都未找到运行时库,抛出致命错误
FATAL("Unable to find 'afl-llvm-rt.o' or 'afl-llvm-pass.so'. Please set AFL_PATH");
}
/*
argv cc_params
*/
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0; // 初始化标志变量
u8 *name; // 定义用于存储程序名的变量
// 为 cc_params 分配足够的内存,以容纳传入的参数加上额外的空间
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
// 提取程序名
name = strrchr(argv[0], '/'); // 查找 argv0 中最后一个斜杠的位置
if (!name) name = argv[0]; else name++; // 如果没有斜杠,使用完整的 argv[0]
// 根据程序名确定使用的编译器
if (!strcmp(name, "afl-clang-fast++")) { // 如果程序名是 afl-clang-fast++
u8* alt_cxx = getenv("AFL_CXX"); // 获取环境变量 AFL_CXX 的值
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; // 如果存在则使用其值,否则默认使用 clang++
} else { // 如果程序名不是 afl-clang-fast++
u8* alt_cc = getenv("AFL_CC"); // 获取环境变量 AFL_CC 的值
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; // 如果存在则使用其值,否则默认使用 clang
}
#ifdef USE_TRACE_PC // 如果定义了 USE_TRACE_PC
// 添加用于 sanitization 的覆盖率参数
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; // 启用 trace-pc-guard 插桩
#ifndef __ANDROID__ // 如果不是 Android 平台
cc_params[cc_par_cnt++] = "-mllvm"; // 添加 LLVM 相关参数
cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; // 设置目标覆盖率的阈值为 0
#endif
#else // 如果没有定义 USE_TRACE_PC
// 添加 LLVM 插件的加载参数
cc_params[cc_par_cnt++] = "-Xclang"; // 添加 Clang 参数
cc_params[cc_par_cnt++] = "-load"; // 指定加载插件
cc_params[cc_par_cnt++] = "-Xclang"; // 添加 Clang 参数
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
// 追加 AFL 关键依赖项 afl-llvm-pass.so 到 cc_params用于插桩分析
#endif /* ^USE_TRACE_PC */
cc_params[cc_par_cnt++] = "-Qunused-arguments";
// 添加一个参数,告诉编译器忽略未使用的命令行参数
while (--argc) { // 循环处理剩余的命令行参数
u8* cur = *(++argv); // 获取当前参数
if (!strcmp(cur, "-m32")) bit_mode = 32; // 如果参数是 -m32设置 bit_mode 为 32
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; // 针对特定架构的设置
if (!strcmp(cur, "-m64")) bit_mode = 64; // 如果参数是 -m64设置 bit_mode 为 64
if (!strcmp(cur, "-x")) x_set = 1; // 如果参数为 -x设置 x_set 为 1表示启用此选项
// 检查是否使用地址或内存的安全检测
if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) asan_set = 1;
// 检查是否启用了 FORTIFY_SOURCE
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
// 如果链接器选项是 -Wl,-z,defs 或 -Wl,--no-undefined跳过该参数
if (!strcmp(cur, "-Wl,-z,defs") ||
!strcmp(cur, "-Wl,--no-undefined")) continue;
cc_params[cc_par_cnt++] = cur; // 将当前参数添加到 cc_params
}
// 如果环境变量 AFL_HARDEN 存在
if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all"; // 启用所有堆栈保护
// 如果未启用 FORTIFY_SOURCE添加定义以启用其功能
if (!fortify_set)
cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
}
// 如果尚未启用 AddressSanitizer
if (!asan_set) {
// 检查是否设置了使用 AddressSanitizer 的环境变量
if (getenv("AFL_USE_ASAN")) {
// 检查 MSAN 和 ASAN 互斥
if (getenv("AFL_USE_MSAN"))
FATAL("ASAN and MSAN are mutually exclusive");
// 检查 AFL_HARDEN 是否与 ASAN 互斥
if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 取消定义 FORTIFY_SOURCE
cc_params[cc_par_cnt++] = "-fsanitize=address"; // 启用 AddressSanitizer
}
// 检查是否设置了使用 MemorySanitizer 的环境变量
else if (getenv("AFL_USE_MSAN")) {
// 检查 ASAN 和 MSAN 互斥
if (getenv("AFL_USE_ASAN"))
FATAL("ASAN and MSAN are mutually exclusive");
// 检查 AFL_HARDEN 是否与 MSAN 互斥
if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 取消定义 FORTIFY_SOURCE
cc_params[cc_par_cnt++] = "-fsanitize=memory"; // 启用 MemorySanitizer
}
}
// 如果定义了 USE_TRACE_PC
#ifdef USE_TRACE_PC
// 检查 AFL_INST_RATIO 环境变量是否可用
if (getenv("AFL_INST_RATIO"))
FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'.");
#endif /* USE_TRACE_PC */
// 如果未设置 AFL_DONT_OPTIMIZE则启用优化选项
if (!getenv("AFL_DONT_OPTIMIZE")) {
cc_params[cc_par_cnt++] = "-g"; // 添加调试信息
cc_params[cc_par_cnt++] = "-O3"; // 启用高优化级别
cc_params[cc_par_cnt++] = "-funroll-loops"; // 启用循环展开
}
// 如果设置了 AFL_NO_BUILTIN则禁用特定的内置函数
if (getenv("AFL_NO_BUILTIN")) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; // 禁用 strcmp 的内置实现
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; // 禁用 strncmp 的内置实现
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; // 禁用 strcasecmp 的内置实现
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; // 禁用 strncasecmp 的内置实现
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; // 禁用 memcmp 的内置实现
}
// 添加 AFL 控制宏,确保手动控制和编译器的定义
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; // 指示支持手动控制
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; // 编译器标识
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; // 表示为不安全的生产模式
/*
使 forkserver
(便 afl-fuzz )
.o
1)
__attribute__((used))
2) -Wl,--gc-sections
'volatile'
3) __afl_persistent_loop()
- :: extern "C"
__attribute__((alias(...))) 使 __asm__
*/
// 定义一个宏,用于处理 AFL 循环的持久化
cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)="
// 开始一个代码块,其中静态的、易失的字符指针用于存放持久化的信号
"({ static volatile char *_B __attribute__((used)); "
" _B = (char*)\"" PERSIST_SIG "\"; "; // 将持久化信号字符串赋值给指针 _B
#ifdef __APPLE__ // 根据系统平台选择合适的函数名称
"__attribute__((visibility(\"default\"))) "
"int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " // Apple 平台下的持久化函数
#else
"__attribute__((visibility(\"default\"))) "
"int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " // 其他平台下的持久化函数
#endif /* ^__APPLE__ */
"_L(_A); })"; // 调用持久化函数,并结束代码块
// 定义一个宏,用于初始化 AFL
cc_params[cc_par_cnt++] = "-D__AFL_INIT()="
"do { static volatile char *_A __attribute__((used)); "
" _A = (char*)\"" DEFER_SIG "\"; "; // 将延迟信号字符串赋值给指针 _A
#ifdef __APPLE__ // 根据系统平台选择合适的初始化函数名称
"__attribute__((visibility(\"default\"))) "
"void _I(void) __asm__(\"___afl_manual_init\"); " // Apple 平台下的初始化函数
#else
"__attribute__((visibility(\"default\"))) "
"void _I(void) __asm__(\"__afl_manual_init\"); " // 其他平台下的初始化函数
#endif /* ^__APPLE__ */
"_I(); } while (0)"; // 调用初始化函数,并结束循环结构
// 如果 x_set 被设置,添加参数来指示关闭类型检查
if (x_set) {
cc_params[cc_par_cnt++] = "-x"; // 添加-x参数
cc_params[cc_par_cnt++] = "none"; // 指示后续没有特定类型
}
// 如果不是在 Android 平台下
#ifndef __ANDROID__
switch (bit_mode) { // 根据位数选择合适的运行时库
case 0: // 如果未设置位模式
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); // 使用默认的 afl-llvm-rt.o 路径
break;
case 32: // 如果设置了 32 位模式
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); // 使用 32 位运行时库路径
// 检查路径是否可读,如果不可读则抛出错误
if (access(cc_params[cc_par_cnt - 1], R_OK))
FATAL("-m32 is not supported by your compiler"); // 抛出错误信息
break;
case 64: // 如果设置了 64 位模式
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); // 使用 64 位运行时库路径
/* 查找运行时库的路径。如果找不到,则中止程序。 */
static void find_obj(u8* argv0) {
// 获取环境变量 AFL_PATH
u8 *afl_path = getenv("AFL_PATH");
u8 *slash, *tmp;
if (afl_path) { // 如果设置了AFL_PATH
// 如果找到 AFL_PATH
if (afl_path) {
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path); // 格式化路径
// 生成 afl-llvm-rt.o 的完整路径
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);
if (!access(tmp, R_OK)) { // 检查文件是否可读
obj_path = afl_path; // 设置运行时库路径
ck_free(tmp); // 释放临时字符串
return;
// 检查文件是否可读
if (!access(tmp, R_OK)) {
obj_path = afl_path; // 设置对象路径为 AFL_PATH
ck_free(tmp); // 释放临时路径内存
return; // 找到文件,结束函数
}
ck_free(tmp); // 释放临时字符串
ck_free(tmp); // 释放临时路径内存
}
slash = strrchr(argv0, '/'); // 查找路径中的最后一个斜杠
// 查找 argv0 中最后一个 '/' 的位置
slash = strrchr(argv0, '/');
if (slash) { // 如果找到斜杠
// 如果找到 '/'
if (slash) {
u8 *dir;
*slash = 0; // 将斜杠替换为结束符
dir = ck_strdup(argv0); // 复制路径
*slash = '/'; // 恢复斜杠
*slash = 0; // 将 '/' 替换为结束符,以获取目录
dir = ck_strdup(argv0); // 复制目录名
*slash = '/'; // 恢复原来的 '/' 字符
tmp = alloc_printf("%s/afl-llvm-rt.o", dir); // 格式化路径
// 生成 afl-llvm-rt.o 的完整路径
tmp = alloc_printf("%s/afl-llvm-rt.o", dir);
if (!access(tmp, R_OK)) { // 检查文件是否可读
obj_path = dir; // 设置运行时库路径
ck_free(tmp); // 释放临时字符串
return;
// 检查文件是否可读
if (!access(tmp, R_OK)) {
obj_path = dir; // 设置对象路径为找到的目录
ck_free(tmp); // 释放临时路径内存
return; // 找到文件,结束函数
}
ck_free(tmp); // 释放临时字符串
ck_free(dir); // 释放目录字符串
ck_free(tmp); // 释放临时路径内存
ck_free(dir); // 释放目录名内存
}
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) { // 检查默认路径
obj_path = AFL_PATH; // 设置运行时库路径
return;
// 检查默认路径下的 afl-llvm-rt.o 是否可读
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
obj_path = AFL_PATH; // 设置对象路径为默认的 AFL_PATH
return; // 找到文件,结束函数
}
FATAL("Unable to find 'afl-llvm-rt.o' or 'afl-llvm-pass.so'. Please set AFL_PATH"); // 查找失败时提示错误
// 如果都找不到,则抛出致命错误
FATAL("Unable to find 'afl-llvm-rt.o' or 'afl-llvm-pass.so'. Please set AFL_PATH");
}
/* 复制argv到cc_params并进行必要的编辑。 */
/* 复制 argv 到 cc_params并进行必要的编辑。 */
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0; // 初始化标志变量
u8 *name; // 当前文件名
// 初始化标志变量
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0;
u8 *name;
cc_params = ck_alloc((argc + 128) * sizeof(u8*)); // 分配参数数组内存
// 分配空间以存储参数
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
name = strrchr(argv[0], '/'); // 获取程序名
if (!name) name = argv[0]; else name++; // 如果没有斜杠,则使用完整路径
// 获取执行的程序名称
name = strrchr(argv[0], '/');
if (!name) name = argv[0]; else name++;
// 根据程序名设置编译器
// 根据程序名称选择合适的编译器
if (!strcmp(name, "afl-clang-fast++")) {
u8* alt_cxx = getenv("AFL_CXX"); // 获取环境变量AFL_CXX
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; // 设置C++编译器
u8* alt_cxx = getenv("AFL_CXX"); // 获取环境变量 AFL_CXX
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; // 设置 C++ 编译器
} else {
u8* alt_cc = getenv("AFL_CC"); // 获取环境变量AFL_CC
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; // 设置C编译器
u8* alt_cc = getenv("AFL_CC"); // 获取环境变量 AFL_CC
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; // 设置 C 编译器
}
/* 有两种编译afl-clang-fast的方式。传统模式下我们使用afl-llvm-pass.so注入插桩。
'trace-pc-guard'使LLVM */
#ifdef USE_TRACE_PC
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; // 添加Trace PC Guard标志
// 启用跟踪 PC 的覆盖率
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
#ifndef __ANDROID__
cc_params[cc_par_cnt++] = "-mllvm"; // 添加LLVM的命令行标志
cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; // 设置阈值为0
cc_params[cc_par_cnt++] = "-mllvm"; // LLVM 选项
cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; // 设定阈值
#endif
#else
cc_params[cc_par_cnt++] = "-Xclang"; // 添加编译器的命令行标志
cc_params[cc_par_cnt++] = "-load"; // 加载指定共享库
cc_params[cc_par_cnt++] = "-Xclang"; // 添加编译器的命令行标志
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); // 添加动态库路径
// 加载 afl-llvm-pass.so 插件
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
#endif /* ^USE_TRACE_PC */
cc_params[cc_par_cnt++] = "-Qunused-arguments"; // 添加未使用参数警告
cc_params[cc_par_cnt++] = "-Qunused-arguments"; // 忽略未使用的参数
// 处理命令行参数
// 循环处理输入参数
while (--argc) {
u8* cur = *(++argv); // 当前参数
u8* cur = *(++argv); // 获取当前参数
if (!strcmp(cur, "-m32")) bit_mode = 32; // 检查32位模式
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; // ARM平台
if (!strcmp(cur, "-m64")) bit_mode = 64; // 检查64位模式
// 检查位模式
if (!strcmp(cur, "-m32")) bit_mode = 32;
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
if (!strcmp(cur, "-x")) x_set = 1; // 检查-x标志
// 检查其他编译选项
if (!strcmp(cur, "-x")) x_set = 1;
// 检查Address Sanitizer
// 检查是否启用地址/内存的 sanitization
if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) asan_set = 1;
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; // 检查FORTIFY_SOURCE
// 检查 FORTIFY_SOURCE 是否启用
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
// 跳过某些链接器选项
if (!strcmp(cur, "-Wl,-z,defs") ||
!strcmp(cur, "-Wl,--no-undefined")) continue; // 跳过链接器选项
!strcmp(cur, "-Wl,--no-undefined")) continue;
cc_params[cc_par_cnt++] = cur; // 添加当前参数到编译参数数组
// 将当前参数添加到 cc_params
cc_params[cc_par_cnt++] = cur;
}
// 检查环境变量AFL_HARDEN
// 如果启用了硬化选项
if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all"; // 启用栈保护
if (!fortify_set) // 如果没有FORTIFY_SOURCE则添加相关标志
// 如果没有启用 FORTIFY_SOURCE 则添加对应宏定义
if (!fortify_set)
cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
}
// 检查Address Sanitizer和Memory Sanitizer的互斥
// 检查地址或内存 sanitization 的设置
if (!asan_set) {
if (getenv("AFL_USE_ASAN")) { // 如果启用Address Sanitizer
if (getenv("AFL_USE_ASAN")) {
if (getenv("AFL_USE_MSAN"))
FATAL("ASAN和MSAN是互斥的"); // 互斥检查
FATAL("ASAN and MSAN are mutually exclusive"); // 互斥检查
if (getenv("AFL_HARDEN"))
FATAL("ASAN和AFL_HARDEN是互斥的"); // 互斥检查
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 添加标志
cc_params[cc_par_cnt++] = "-fsanitize=address"; // 启用Address Sanitizer
} else if (getenv("AFL_USE_MSAN")) { // 如果启用Memory Sanitizer
FATAL("ASAN and AFL_HARDEN are mutually exclusive"); // 互斥检查
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 禁用 FORTIFY_SOURCE
cc_params[cc_par_cnt++] = "-fsanitize=address"; // 启用地址条件检测
} else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN"))
FATAL("ASAN和MSAN是互斥的"); // 互斥检查
FATAL("ASAN and MSAN are mutually exclusive"); // 互斥检查
if (getenv("AFL_HARDEN"))
FATAL("MSAN和AFL_HARDEN是互斥的"); // 互斥检查
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 添加标志
cc_params[cc_par_cnt++] = "-fsanitize=memory"; // 启用Memory Sanitizer
FATAL("MSAN and AFL_HARDEN are mutually exclusive"); // 互斥检查
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; // 禁用 FORTIFY_SOURCE
cc_params[cc_par_cnt++] = "-fsanitize=memory"; // 启用内存条件检测
}
}
#ifdef USE_TRACE_PC
// 检查 AFL_INST_RATIO 环境变量的设置
if (getenv("AFL_INST_RATIO"))
FATAL("AFL_INST_RATIO在'trace-pc'模式下不可用"); // 提示用户
#endif /* USE_TRACE_PC */
if (!getenv("AFL_DONT_OPTIMIZE")) { // 如果没有设置不优化选项
cc_params[cc_par_cnt++] = "-g"; // 添加调试信息
cc_params[cc_par_cnt++] = "-O3"; // 添加优化等级
cc_params[cc_par_cnt++] = "-funroll-loops"; // 启用循环展开
}
FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'.");
if (getenv("AFL_NO_BUILTIN")) { // 检查是否使用内建函数
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; // 禁用strcmp内建
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; // 禁用strncmp内建
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; // 禁用strcasecmp内建
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; // 禁用strncasecmp内建
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; // 禁用memcmp内建
}
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; // 添加手动控制标志
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; // 添加编译器标志
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; // 添加不安全模式标志
#endif /* USE_TRACE_PC */
/* 当用户尝试使用持久化或延迟fork服务器模式时
.o
// 检查是否不优化
if (!getenv("AFL_DONT_OPTIMIZE")) {
cc_params[cc_par_cnt++] = "-g"; // 启用调试信息
cc_params[cc_par_cnt++] = "-O3"; // 启用最高级别的优化
cc_params[cc_par_cnt++] = "-funroll-loops"; // 循环展开以提高性能
}
1) 使__attribute__((used))
2) 使-Wl,--gc-sections
'volatile'
3) __afl_persistent_loop()
使__asm__
// 检查是否禁用内置函数的使用
if (getenv("AFL_NO_BUILTIN")) {
// 禁用特定的内置字符串比较和内存比较函数
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
}
*/
// 添加 AFL 相关的宏定义
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; // 手动控制
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; // 标记为 AFL 编译器
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; // 不适合生产的模糊构建模式
cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)="
// 添加 AFL 循环的实现
cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)="
"({ static volatile char *_B __attribute__((used)); "
" _B = (char*)\"" PERSIST_SIG "\"; "
#ifdef __APPLE__
@ -240,9 +501,10 @@ static void edit_params(u32 argc, char** argv) {
"__attribute__((visibility(\"default\"))) "
"int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
"_L(_A); })";
"_L(_A); })"; // 定义 AFL 循环的宏
cc_params[cc_par_cnt++] = "-D__AFL_INIT()="
// 添加 AFL 初始化函数的实现
cc_params[cc_par_cnt++] = "-D__AFL_INIT()="
"do { static volatile char *_A __attribute__((used)); "
" _A = (char*)\"" DEFER_SIG "\"; "
#ifdef __APPLE__
@ -252,57 +514,59 @@ static void edit_params(u32 argc, char** argv) {
"__attribute__((visibility(\"default\"))) "
"void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
"_I(); } while (0)";
"_I(); } while (0)"; // 定义 AFL 初始化的宏
if (x_set) { // 检查是否有-x标志
cc_params[cc_par_cnt++] = "-x"; // 添加-x标志
cc_params[cc_par_cnt++] = "none"; // 设置参数
}
// 如果启用 -x 选项
if (x_set) {
cc_params[cc_par_cnt++] = "-x"; // 添加 -x 选项
cc_params[cc_par_cnt++] = "none"; // 设置为 none表示不对输入进行特定语言解析
}
#ifndef __ANDROID__
switch (bit_mode) { // 根据位模式选择运行时库
// 根据位模式选择不同的运行时库文件
switch (bit_mode) {
case 0:
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); // 添加默认路径
break;
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); // 默认情况下使用通用的运行时文件
break;
case 32:
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); // 32位库路径
if (access(cc_params[cc_par_cnt - 1], R_OK)) // 检查权限
FATAL("-m32不被你的编译器支持"); // 提示不支持
break;
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); // 使用 32 位版本的运行时文件
// 检查此文件是否可读
if (access(cc_params[cc_par_cnt - 1], R_OK))
FATAL("-m32 is not supported by your compiler"); // 如果不可读则报错
break;
case 64:
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); // 64位库路径
if (access(cc_params[cc_par_cnt - 1], R_OK)) // 检查权限
FATAL("-m64不被你的编译器支持"); // 提示不支持
break;
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); // 使用 64 位版本的运行时文件
// 检查此文件是否可读
if (access(cc_params[cc_par_cnt - 1], R_OK))
FATAL("-m64 is not supported by your compiler"); // 如果不可读则报错
break;
}
}
#endif
// 结束参数数组,以空指针结尾
cc_params[cc_par_cnt] = NULL;
cc_params[cc_par_cnt] = NULL; // 结束参数数组
}
/* 主入口点 */
int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) { // 检查终端和环境变量
// 检查标准错误是否连接到终端且 AFL_QUIET 环境变量未设置
if (isatty(2) && !getenv("AFL_QUIET")) {
#ifdef USE_TRACE_PC
SAYF(cCYA "afl-clang-fast [tpcg] " cBRI VERSION cRST " by <lszekeres@google.com>\n"); // 输出版本信息
// 如果启用了 USE_TRACE_PC打印版本信息
SAYF(cCYA "afl-clang-fast [tpcg] " cBRI VERSION cRST " by <lszekeres@google.com>\n");
#else
SAYF(cCYA "afl-clang-fast " cBRI VERSION cRST " by <lszekeres@google.com>\n"); // 输出版本信息
// 否则,仅打印版本信息
SAYF(cCYA "afl-clang-fast " cBRI VERSION cRST " by <lszekeres@google.com>\n");
#endif /* ^USE_TRACE_PC */
}
if (argc < 2) { // 检查参数数量
// 如果参数数量小于 2打印帮助信息并退出
if (argc < 2) {
SAYF("\n"
"This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"
"for clang, letting you recompile third-party code with the required runtime\n"
@ -316,22 +580,25 @@ int main(int argc, char** argv) {
"You can specify custom next-stage toolchain via AFL_CC and AFL_CXX. Setting\n"
"AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
BIN_PATH, BIN_PATH); // 输出用法说明
BIN_PATH, BIN_PATH);
exit(1); // 退出程序
exit(1); // 退出程序,返回错误码 1
}
#ifndef __ANDROID__
find_obj(argv[0]); // 查找运行时库
// 在非 Android 平台下调用 find_obj 函数查找运行时库
find_obj(argv[0]);
#endif
edit_params(argc, argv); // 编辑参数
execvp(cc_params[0], (char**)cc_params); // 执行真实编译器
// 调用 edit_params 函数处理命令行参数并设置编译参数
edit_params(argc, argv);
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); // 执行失败提示
// 使用 execvp 执行指定的编译器命令
execvp(cc_params[0], (char**)cc_params);
return 0; // 返回0表示成功
// 如果 execvp 失败,抛出致命错误并打印相关信息
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
return 0; // 正常结束程序
}

Loading…
Cancel
Save