Compare commits

...

25 Commits

Binary file not shown.

Binary file not shown.

@ -96,6 +96,7 @@ static afl_forkserver_t fsrv = {0}; /* The forkserver */
/* Classify tuple counts. This is a slow & naive version, but good enough here. /* Classify tuple counts. This is a slow & naive version, but good enough here.
*/ */
//将模糊测试的错误数进行归并,在不造成太大影响的情况下减少运算、提升性能
static u8 count_class_lookup[256] = { static u8 count_class_lookup[256] = {
[0] = 0, [0] = 0,
@ -110,21 +111,25 @@ static u8 count_class_lookup[256] = {
}; };
//结束子进程
static void kill_child() { static void kill_child() {
if (fsrv.child_pid > 0) { if (fsrv.child_pid > 0) {
//kill函数杀死对应pid的子进程并将其标志位置为1
kill(fsrv.child_pid, fsrv.child_kill_signal); kill(fsrv.child_pid, fsrv.child_kill_signal);
//将子进程的pid置为-1即无法选中
fsrv.child_pid = -1; fsrv.child_pid = -1;
} }
} }
//对内存中的字节进行分类通过预定的count_class_lookup数组实现分类的效果
static void classify_counts(u8 *mem, u32 mem_size) { static void classify_counts(u8 *mem, u32 mem_size) {
u32 i = mem_size; u32 i = mem_size;
//如果只对边缘探测有要求只用设置为bool变量
if (edges_only) { if (edges_only) {
while (i--) { while (i--) {
@ -148,10 +153,11 @@ static void classify_counts(u8 *mem, u32 mem_size) {
} }
/* See if any bytes are set in the bitmap. */ /* See if any bytes are set in the bitmap. */
//遍历整个bitmap检查是否有字节在bitmap里面被设置了
static inline u8 anything_set(void) { static inline u8 anything_set(void) {
//使用fsrv.trace_bits模拟bitmap
u32 *ptr = (u32 *)fsrv.trace_bits; u32 *ptr = (u32 *)fsrv.trace_bits;
//map_size的大小除以4因为是按字节进行搜索
u32 i = (map_size >> 2); u32 i = (map_size >> 2);
while (i--) { while (i--) {
@ -165,7 +171,7 @@ static inline u8 anything_set(void) {
} }
/* Get rid of temp files (atexit handler). */ /* Get rid of temp files (atexit handler). */
//在函数结束时调用,删除临时文件
static void at_exit_handler(void) { static void at_exit_handler(void) {
unlink(fsrv.out_file); /* Ignore errors */ unlink(fsrv.out_file); /* Ignore errors */
@ -173,16 +179,16 @@ static void at_exit_handler(void) {
} }
/* Read initial file. */ /* Read initial file. */
//读取需要分析的文件的起始状态
static void read_initial_file(void) { static void read_initial_file(void) {
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
//无法读取分支
if (fd < 0) { PFATAL("Unable to open '%s'", in_file); } if (fd < 0) { PFATAL("Unable to open '%s'", in_file); }
//读取到的文件内容为空分支
if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); } if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); }
//读取文件内容超过缓存最大值分支
if (st.st_size >= TMIN_MAX_FILE) { if (st.st_size >= TMIN_MAX_FILE) {
FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024); FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024);
@ -202,56 +208,63 @@ static void read_initial_file(void) {
/* Execute target application. Returns exec checksum, or 0 if program /* Execute target application. Returns exec checksum, or 0 if program
times out. */ times out. */
//起一个目标程序的镜像进程,用于在不影响程序正常使用的前提下对程序进行模糊测试
static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) { static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
//将该程序的镜像地址写入到测试栈中
afl_fsrv_write_to_testcase(&fsrv, mem, len); afl_fsrv_write_to_testcase(&fsrv, mem, len);
//使用afl_fsrv_run_target函数尝试运行镜像进程并将结果返回到fsrv_run_result_t对象中
fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon); fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon);
//创建镜像失败分支
if (ret == FSRV_RUN_ERROR) { if (ret == FSRV_RUN_ERROR) {
FATAL("Error in forkserver"); FATAL("Error in forkserver");
} else if (ret == FSRV_RUN_NOINST) { }
//运行镜像缺失分支
else if (ret == FSRV_RUN_NOINST) {
FATAL("Target not instrumented"); FATAL("Target not instrumented");
} else if (ret == FSRV_RUN_NOBITS) { }
//运行报错分支
else if (ret == FSRV_RUN_NOBITS) {
FATAL("Failed to run target"); FATAL("Failed to run target");
} }
//调用classify_counts函数对测试进程内存中的字节进行分类以作进一步模糊测试
classify_counts(fsrv.trace_bits, fsrv.map_size); classify_counts(fsrv.trace_bits, fsrv.map_size);
//全局变量中total_execs自增对测试程序数进行记录
total_execs++; total_execs++;
if (stop_soon) { if (stop_soon) {
//用户操作退出Ctrl+C弹出退出示警
SAYF(cRST cLRD "\n+++ Analysis aborted by user +++\n" cRST); SAYF(cRST cLRD "\n+++ Analysis aborted by user +++\n" cRST);
exit(1); exit(1);
} }
/* Always discard inputs that time out. */ /* Always discard inputs that time out. */
//镜像运行超时全局变量中exec_hangs自增对测试程序超时数进行记录
if (fsrv.last_run_timed_out) { if (fsrv.last_run_timed_out) {
exec_hangs++; exec_hangs++;
return 0; return 0;
} }
//校验和
u64 cksum = hash64(fsrv.trace_bits, fsrv.map_size, HASH_CONST); u64 cksum = hash64(fsrv.trace_bits, fsrv.map_size, HASH_CONST);
if (ret == FSRV_RUN_CRASH) { if (ret == FSRV_RUN_CRASH) {
/* We don't actually care if the target is crashing or not, /* We don't actually care if the target is crashing or not,
except that when it does, the checksum should be different. */ except that when it does, the checksum should be different. */
//校验和全1异或每位取反
cksum ^= 0xffffffff; cksum ^= 0xffffffff;
} }
//记录初始校验和
if (first_run) { orig_cksum = cksum; } if (first_run) { orig_cksum = cksum; }
return cksum; return cksum;
@ -261,13 +274,14 @@ static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
#ifdef USE_COLOR #ifdef USE_COLOR
/* Helper function to display a human-readable character. */ /* Helper function to display a human-readable character. */
//将内存内字节打印成用户可读字符
static void show_char(u8 val) { static void show_char(u8 val) {
switch (val) { switch (val) {
case 0 ... 32: case 0 ... 32:
case 127 ... 255: case 127 ... 255:
//通过格式化输出实现
SAYF("#%02x", val); SAYF("#%02x", val);
break; break;
@ -279,7 +293,7 @@ static void show_char(u8 val) {
} }
/* Show the legend */ /* Show the legend */
//将内存字节设置为不同字体颜色,方便用户区分
static void show_legend(void) { static void show_legend(void) {
SAYF(" " cLGR bgGRA " 01 " cRST " - no-op block " cBLK bgLGN SAYF(" " cLGR bgGRA " 01 " cRST " - no-op block " cBLK bgLGN
@ -298,7 +312,7 @@ static void show_legend(void) {
#endif /* USE_COLOR */ #endif /* USE_COLOR */
/* Interpret and report a pattern in the input file. */ /* Interpret and report a pattern in the input file. */
//以16进制形式储存文件分析字节行为
static void dump_hex(u32 len, u8 *b_data) { static void dump_hex(u32 len, u8 *b_data) {
u32 i; u32 i;
@ -314,7 +328,7 @@ static void dump_hex(u32 len, u8 *b_data) {
u8 rtype = b_data[i] & 0x0f; u8 rtype = b_data[i] & 0x0f;
/* Look ahead to determine the length of run. */ /* Look ahead to determine the length of run. */
//确定运行长度
while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) { while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) {
if (rtype < (b_data[i + rlen] & 0x0f)) { if (rtype < (b_data[i + rlen] & 0x0f)) {
@ -328,7 +342,7 @@ static void dump_hex(u32 len, u8 *b_data) {
} }
/* Try to do some further classification based on length & value. */ /* Try to do some further classification based on length & value. */
//对字节相应类型进行分类
if (rtype == RESP_FIXED) { if (rtype == RESP_FIXED) {
switch (rlen) { switch (rlen) {
@ -340,7 +354,7 @@ static void dump_hex(u32 len, u8 *b_data) {
/* Small integers may be length fields. */ /* Small integers may be length fields. */
if (val && (val <= in_len || SWAP16(val) <= in_len)) { if (val && (val <= in_len || SWAP16(val) <= in_len)) {
//判断为运行长度
rtype = RESP_LEN; rtype = RESP_LEN;
break; break;
@ -349,7 +363,7 @@ static void dump_hex(u32 len, u8 *b_data) {
/* Uniform integers may be checksums. */ /* Uniform integers may be checksums. */
if (val && abs(in_data[i] - in_data[i + 1]) > 32) { if (val && abs(in_data[i] - in_data[i + 1]) > 32) {
//判断为校验和
rtype = RESP_CKSUM; rtype = RESP_CKSUM;
break; break;
@ -360,7 +374,7 @@ static void dump_hex(u32 len, u8 *b_data) {
} }
case 4: { case 4: {
//同上
u32 val = *(u32 *)(in_data + i); u32 val = *(u32 *)(in_data + i);
/* Small integers may be length fields. */ /* Small integers may be length fields. */
@ -406,17 +420,17 @@ static void dump_hex(u32 len, u8 *b_data) {
for (off = 0; off < rlen; off++) { for (off = 0; off < rlen; off++) {
/* Every 16 digits, display offset. */ /* Every 16 digits, display offset. */
//每4个字节作为一组进行输出
if (!((i + off) % 16)) { if (!((i + off) % 16)) {
if (off) { SAYF(cRST cLCY ">"); } if (off) { SAYF(cRST cLCY ">"); }
if (use_hex_offsets) { if (use_hex_offsets) {
//规格化输出
SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off); SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off);
} else { } else {
//规格化输出
SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off); SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off);
} }
@ -424,7 +438,7 @@ static void dump_hex(u32 len, u8 *b_data) {
} }
switch (rtype) { switch (rtype) {
//根据rtype分析的不同类型进行不同的上色便于用户区分
case RESP_NONE: case RESP_NONE:
SAYF(cLGR bgGRA); SAYF(cLGR bgGRA);
break; break;
@ -448,11 +462,11 @@ static void dump_hex(u32 len, u8 *b_data) {
break; break;
} }
//输出
show_char(in_data[i + off]); show_char(in_data[i + off]);
if (off != rlen - 1 && (i + off + 1) % 16) { if (off != rlen - 1 && (i + off + 1) % 16) {
//补齐
SAYF(" "); SAYF(" ");
} else { } else {
@ -464,14 +478,14 @@ static void dump_hex(u32 len, u8 *b_data) {
} }
#else #else
//根据用户是否需求16进制进行输出的处理
if (use_hex_offsets) if (use_hex_offsets)
SAYF(" Offset %x, length %u: ", i, rlen); SAYF(" Offset %x, length %u: ", i, rlen);
else else
SAYF(" Offset %u, length %u: ", i, rlen); SAYF(" Offset %u, length %u: ", i, rlen);
switch (rtype) { switch (rtype) {
//输出测试分析得到的信息
case RESP_NONE: case RESP_NONE:
SAYF("no-op block\n"); SAYF("no-op block\n");
break; break;
@ -509,9 +523,9 @@ static void dump_hex(u32 len, u8 *b_data) {
} }
/* Actually analyze! */ /* Actually analyze! */
//分析函数
static void analyze() { static void analyze() {
//初始化变量
u32 i; u32 i;
u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0; u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0;
@ -527,14 +541,14 @@ static void analyze() {
#endif /* USE_COLOR */ #endif /* USE_COLOR */
for (i = 0; i < in_len; i++) { for (i = 0; i < in_len; i++) {
//遍历程序的每一个字节
u64 xor_ff, xor_01, sub_10, add_10; u64 xor_ff, xor_01, sub_10, add_10;
u8 xff_orig, x01_orig, s10_orig, a10_orig; u8 xff_orig, x01_orig, s10_orig, a10_orig;
/* Perform walking byte adjustments across the file. We perform four /* Perform walking byte adjustments across the file. We perform four
operations designed to elicit some response from the underlying operations designed to elicit some response from the underlying
code. */ code. */
//对程序的每个字节进行异或0xff、异或0x01、减0x10、加0x20操作然后进行运行分析查看是否会对程序的运行产生影响
in_data[i] ^= 0xff; in_data[i] ^= 0xff;
xor_ff = analyze_run_target(in_data, in_len, 0); xor_ff = analyze_run_target(in_data, in_len, 0);
@ -549,34 +563,34 @@ static void analyze() {
in_data[i] -= 0x10; in_data[i] -= 0x10;
/* Classify current behavior. */ /* Classify current behavior. */
//记录校验和,以观察是否有影响
xff_orig = (xor_ff == orig_cksum); xff_orig = (xor_ff == orig_cksum);
x01_orig = (xor_01 == orig_cksum); x01_orig = (xor_01 == orig_cksum);
s10_orig = (sub_10 == orig_cksum); s10_orig = (sub_10 == orig_cksum);
a10_orig = (add_10 == orig_cksum); a10_orig = (add_10 == orig_cksum);
if (xff_orig && x01_orig && s10_orig && a10_orig) { if (xff_orig && x01_orig && s10_orig && a10_orig) {
//如果都不报错,则将该字节标记为无用项
b_data[i] = RESP_NONE; b_data[i] = RESP_NONE;
boring_len++; boring_len++;
} else if (xff_orig || x01_orig || s10_orig || a10_orig) { } else if (xff_orig || x01_orig || s10_orig || a10_orig) {
//报错则标记为错误项
b_data[i] = RESP_MINOR; b_data[i] = RESP_MINOR;
boring_len++; boring_len++;
} else if (xor_ff == xor_01 && xor_ff == sub_10 && xor_ff == add_10) { } else if (xor_ff == xor_01 && xor_ff == sub_10 && xor_ff == add_10) {
//如果经过不同方式修改后的校验和相等,则将该字节标记为可自修复项
b_data[i] = RESP_FIXED; b_data[i] = RESP_FIXED;
} else { } else {
//否则则将该字节标记为变异项
b_data[i] = RESP_VARIABLE; b_data[i] = RESP_VARIABLE;
} }
/* When all checksums change, flip most significant bit of b_data. */ /* When all checksums change, flip most significant bit of b_data. */
//如果所有变异操作都与上一个字节的测试不一样,就翻转最高位
if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 && if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 &&
prev_a10 != add_10) { prev_a10 != add_10) {
@ -592,7 +606,7 @@ static void analyze() {
prev_a10 = add_10; prev_a10 = add_10;
} }
//输出分析结果
dump_hex(in_len, b_data); dump_hex(in_len, b_data);
SAYF("\n"); SAYF("\n");
@ -612,7 +626,7 @@ static void analyze() {
} }
/* Handle Ctrl-C and the like. */ /* Handle Ctrl-C and the like. */
//用户自出终止程序的代理函数
static void handle_stop_sig(int sig) { static void handle_stop_sig(int sig) {
(void)sig; (void)sig;
@ -623,7 +637,7 @@ static void handle_stop_sig(int sig) {
} }
/* Do basic preparations - persistent fds, filenames, etc. */ /* Do basic preparations - persistent fds, filenames, etc. */
//设置测试环境
static void set_up_environment(char **argv) { static void set_up_environment(char **argv) {
u8 *x; u8 *x;
@ -719,7 +733,7 @@ static void set_up_environment(char **argv) {
} }
/* Setup signal handlers, duh. */ /* Setup signal handlers, duh. */
//设置信号处理程序,进行初始化
static void setup_signal_handlers(void) { static void setup_signal_handlers(void) {
struct sigaction sa; struct sigaction sa;
@ -744,7 +758,7 @@ static void setup_signal_handlers(void) {
} }
/* Display usage hints. */ /* Display usage hints. */
//当用户输入-h时调用此函数回显该工具的使用方法
static void usage(u8 *argv0) { static void usage(u8 *argv0) {
SAYF( SAYF(
@ -801,7 +815,7 @@ static void usage(u8 *argv0) {
} }
/* Main entry point */ /* Main entry point */
//main函数用户使用的实际接口
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
s32 opt; s32 opt;

@ -91,170 +91,116 @@ static u8 use_64bit = 0;
to keep the code simple. */ to keep the code simple. */
static void edit_params(int argc, char **argv) { static void edit_params(int argc, char **argv) {
// 获取临时目录路径和AFL_AS环境变量
u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS");
u32 i, input_index; u32 i, input_index;
#ifdef __APPLE__ #ifdef __APPLE__
u8 use_clang_as = 0; u8 use_clang_as = 0;
/* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work // 在MacOS下若使用clang且没有设置AFL_AS则使用clang作为汇编器
with the code generated by newer versions of clang that are hand-built
by the user. See the thread here: https://goo.gl/HBWDtn.
To work around this, when using clang and running without AFL_AS
specified, we will actually call 'clang -c' instead of 'as -q' to
compile the assembly file.
The tools aren't cmdline-compatible, but at least for now, we can
seemingly get away with this by making only very minor tweaks. Thanks
to Nico Weber for the idea. */
if (clang_mode && !afl_as) { if (clang_mode && !afl_as) {
use_clang_as = 1; use_clang_as = 1;
afl_as = getenv("AFL_CC"); // 获取AFL_CC环境变量
afl_as = getenv("AFL_CC"); if (!afl_as) afl_as = getenv("AFL_CXX"); // 获取AFL_CXX环境变量
if (!afl_as) afl_as = getenv("AFL_CXX"); if (!afl_as) afl_as = "clang"; // 默认使用clang
if (!afl_as) afl_as = "clang";
} }
#endif
#endif /* __APPLE__ */ // 如果TMPDIR环境变量为空尝试从TEMP和TMP获取临时目录
/* Although this is not documented, GCC also uses TEMP and TMP when TMPDIR
is not set. We need to check these non-standard variables to properly
handle the pass_thru logic later on. */
if (!tmp_dir) { tmp_dir = getenv("TEMP"); } if (!tmp_dir) { tmp_dir = getenv("TEMP"); }
if (!tmp_dir) { tmp_dir = getenv("TMP"); } if (!tmp_dir) { tmp_dir = getenv("TMP"); }
if (!tmp_dir) { tmp_dir = "/tmp"; } if (!tmp_dir) { tmp_dir = "/tmp"; } // 默认临时目录为"/tmp"
// 为汇编参数分配内存,确保不会超过最大参数个数
as_params = ck_alloc((argc + 32) * sizeof(u8 *)); as_params = ck_alloc((argc + 32) * sizeof(u8 *));
if (unlikely((INT_MAX - 32) < argc || !as_params)) { if (unlikely((INT_MAX - 32) < argc || !as_params)) {
FATAL("Too many parameters passed to as"); // 参数过多,终止
FATAL("Too many parameters passed to as");
} }
// 设置汇编器命令
as_params[0] = afl_as ? afl_as : (u8 *)"as"; as_params[0] = afl_as ? afl_as : (u8 *)"as";
as_params[argc] = 0; as_params[argc] = 0;
/* Find the input file. It's usually located near the end. // 查找输入文件,通常位于命令行参数的最后
Assume there won't be any arguments referring to files after the input
file, e.g. as input.s -o output.o */
for (input_index = argc - 1; input_index > 0; input_index--) { for (input_index = argc - 1; input_index > 0; input_index--) {
input_file = argv[input_index]; input_file = argv[input_index];
/* Clang may add debug arguments after the input file. */ // 如果遇到调试选项,跳过
if (strncmp(input_file, "-g", 2)) break; if (strncmp(input_file, "-g", 2)) break;
} }
// 如果没有找到输入文件,输出错误信息
if (input_index == 0) if (input_index == 0)
FATAL("Could not find input file (not called through afl-gcc?)"); FATAL("Could not find input file (not called through afl-gcc?)");
// 遍历参数,处理与汇编相关的选项
for (i = 1; (s32)i < argc; i++) { for (i = 1; (s32)i < argc; i++) {
if (i == input_index) continue; // 跳过输入文件
if (i == input_index) continue; // 处理64位和32位选项
if (!strcmp(argv[i], "--64")) { if (!strcmp(argv[i], "--64")) {
use_64bit = 1; use_64bit = 1;
} else if (!strcmp(argv[i], "--32")) { } else if (!strcmp(argv[i], "--32")) {
use_64bit = 0; use_64bit = 0;
} }
#ifdef __APPLE__ #ifdef __APPLE__
// 在MacOS下处理架构选项
/* The Apple case is a bit different... */
if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) { if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) {
if (!strcmp(argv[i + 1], "x86_64")) if (!strcmp(argv[i + 1], "x86_64"))
use_64bit = 1; use_64bit = 1;
else if (!strcmp(argv[i + 1], "i386")) else if (!strcmp(argv[i + 1], "i386"))
FATAL("Sorry, 32-bit Apple platforms are not supported."); FATAL("Sorry, 32-bit Apple platforms are not supported.");
} }
#endif
/* Strip options that set the preference for a particular upstream // 跳过不相关的选项
assembler in Xcode. */
if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q"))) if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q")))
continue; continue;
#endif /* __APPLE__ */ // 将参数添加到汇编器参数列表
as_params[as_par_cnt++] = argv[i]; as_params[as_par_cnt++] = argv[i];
} }
#ifdef __APPLE__ #ifdef __APPLE__
// 如果使用clang作为汇编器追加相关选项
/* When calling clang as the upstream assembler, append -c -x assembler
and hope for the best. */
if (use_clang_as) { if (use_clang_as) {
as_params[as_par_cnt++] = "-c"; as_params[as_par_cnt++] = "-c";
as_params[as_par_cnt++] = "-x"; as_params[as_par_cnt++] = "-x";
as_params[as_par_cnt++] = "assembler"; as_params[as_par_cnt++] = "assembler";
} }
#endif
#endif /* __APPLE__ */ // 如果输入文件是"-"参数,检查是否为版本信息
if (input_file[0] == '-') { if (input_file[0] == '-') {
if (!strcmp(input_file + 1, "-version")) { if (!strcmp(input_file + 1, "-version")) {
just_version = 1; just_version = 1;
modified_file = input_file; modified_file = input_file;
goto wrap_things_up; goto wrap_things_up; // 跳到结束处理
} }
if (input_file[1]) { if (input_file[1]) {
FATAL("Incorrect use (not called through afl-gcc?)"); FATAL("Incorrect use (not called through afl-gcc?)");
} else { } else {
input_file = NULL; // 没有文件参数
input_file = NULL;
} }
} else { } else {
// 检查输入文件是否为临时文件,并决定是否需要通过工具传递
/* Check if this looks like a standard invocation as a part of an attempt
to compile a program, rather than using gcc on an ad-hoc .s file in
a format we may not understand. This works around an issue compiling
NSS. */
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/var/tmp/", 9) &&
strncmp(input_file, "/tmp/", 5) && strncmp(input_file, "/tmp/", 5) &&
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) { getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) {
pass_thru = 1; pass_thru = 1;
} else if (getenv("AFL_AS_FORCE_INSTRUMENT")) { } else if (getenv("AFL_AS_FORCE_INSTRUMENT")) {
unsetenv("AFL_AS_FORCE_INSTRUMENT"); // 强制插桩的环境变量取消
unsetenv("AFL_AS_FORCE_INSTRUMENT");
} }
} }
// 为汇编文件生成一个唯一的临时文件名
modified_file = alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(), modified_file = alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(),
(u32)time(NULL), (u32)random()); (u32)time(NULL), (u32)random());
}
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
wrap_things_up: wrap_things_up:
as_params[as_par_cnt++] = modified_file; as_params[as_par_cnt++] = modified_file;
@ -278,9 +224,13 @@ static void add_instrumentation(void) {
skip_app = 0, instrument_next = 0; skip_app = 0, instrument_next = 0;
#ifdef __APPLE__ #ifdef __APPLE__
<<<<<<< HEAD
u8 *colon_pos;
=======
u8 *colon_pos; u8 *colon_pos;
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
#endif /* __APPLE__ */ #endif /* __APPLE__ */
if (input_file) { if (input_file) {
@ -303,12 +253,6 @@ static void add_instrumentation(void) {
if (!outf) { PFATAL("fdopen() failed"); } if (!outf) { PFATAL("fdopen() failed"); }
while (fgets(line, MAX_LINE, inf)) { while (fgets(line, MAX_LINE, inf)) {
/* In some cases, we want to defer writing the instrumentation trampoline
until after all the labels, macros, comments, etc. If we're in this
mode, and if the line starts with a tab followed by a character, dump
the trampoline now. */
if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok && if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok &&
instrument_next && line[0] == '\t' && isalpha(line[1])) { instrument_next && line[0] == '\t' && isalpha(line[1])) {

@ -1895,125 +1895,132 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
these have_*, otherwise they may not work as expected. these have_*, otherwise they may not work as expected.
*/ */
void add_sanitizers(aflcc_state_t *aflcc, char **envp) { void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
// 如果启用了 ASAN (地址消毒器),则进行相关配置
if (getenv("AFL_USE_ASAN") || aflcc->have_asan) { if (getenv("AFL_USE_ASAN") || aflcc->have_asan) {
// 如果同时启用了 MSAN (内存消毒器),则报错,因为 ASAN 和 MSAN 不能同时使用
if (getenv("AFL_USE_MSAN") || aflcc->have_msan) if (getenv("AFL_USE_MSAN") || aflcc->have_msan)
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");
// 如果启用了 AFL_HARDEN则报错因为 ASAN 和 AFL_HARDEN 不能同时使用
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive"); FATAL("ASAN and AFL_HARDEN are mutually exclusive");
// 如果是 GCC 插件模式,并且没有启用静态 ASAN 库,则添加静态 ASAN 库的选项
if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) { if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) {
insert_param(aflcc, "-static-libasan"); insert_param(aflcc, "-static-libasan");
} }
// 添加 fortify 配置0表示没有额外的强化
add_defs_fortify(aflcc, 0); add_defs_fortify(aflcc, 0);
if (!aflcc->have_asan) {
// 如果没有启用 ASAN则添加相应的编译选项来启用地址消毒
if (!aflcc->have_asan) {
insert_param(aflcc, "-fsanitize=address"); insert_param(aflcc, "-fsanitize=address");
insert_param(aflcc, "-fno-common"); insert_param(aflcc, "-fno-common");
} }
aflcc->have_asan = 1; aflcc->have_asan = 1; // 标记已经启用了 ASAN
}
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) { // 如果启用了 MSAN (内存消毒器),则进行相关配置
else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
// 如果同时启用了 ASAN则报错因为 ASAN 和 MSAN 不能同时使用
if (getenv("AFL_USE_ASAN") || aflcc->have_asan) if (getenv("AFL_USE_ASAN") || aflcc->have_asan)
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");
// 如果启用了 AFL_HARDEN则报错因为 MSAN 和 AFL_HARDEN 不能同时使用
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive"); FATAL("MSAN and AFL_HARDEN are mutually exclusive");
// 添加 fortify 配置0表示没有额外的强化
add_defs_fortify(aflcc, 0); add_defs_fortify(aflcc, 0);
// 如果没有启用 MSAN则添加相应的编译选项来启用内存消毒
if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); } if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); }
aflcc->have_msan = 1;
aflcc->have_msan = 1; // 标记已经启用了 MSAN
} }
// 如果启用了 UBSAN (未定义行为消毒器),则进行相关配置
if (getenv("AFL_USE_UBSAN") || aflcc->have_ubsan) { if (getenv("AFL_USE_UBSAN") || aflcc->have_ubsan) {
// 如果没有启用 UBSAN则添加相应的编译选项来启用未定义行为消毒
if (!aflcc->have_ubsan) { if (!aflcc->have_ubsan) {
insert_param(aflcc, "-fsanitize=undefined"); insert_param(aflcc, "-fsanitize=undefined");
insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); insert_param(aflcc, "-fsanitize-undefined-trap-on-error");
insert_param(aflcc, "-fno-sanitize-recover=all"); insert_param(aflcc, "-fno-sanitize-recover=all");
} }
// 如果没有启用帧指针,则添加相应的选项来启用帧指针
if (!aflcc->have_fp) { if (!aflcc->have_fp) {
insert_param(aflcc, "-fno-omit-frame-pointer"); insert_param(aflcc, "-fno-omit-frame-pointer");
aflcc->have_fp = 1; aflcc->have_fp = 1;
} }
aflcc->have_ubsan = 1; aflcc->have_ubsan = 1; // 标记已经启用了 UBSAN
} }
// 如果启用了 TSAN (线程消毒器),则进行相关配置
if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) { if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) {
// 如果没有启用帧指针,则添加相应的选项来启用帧指针
if (!aflcc->have_fp) { if (!aflcc->have_fp) {
insert_param(aflcc, "-fno-omit-frame-pointer"); insert_param(aflcc, "-fno-omit-frame-pointer");
aflcc->have_fp = 1; aflcc->have_fp = 1;
} }
// 如果没有启用 TSAN则添加相应的编译选项来启用线程消毒
if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); } if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); }
aflcc->have_tsan = 1;
aflcc->have_tsan = 1; // 标记已经启用了 TSAN
} }
// 如果启用了 LSAN (泄漏消毒器),则进行相关配置
if (getenv("AFL_USE_LSAN") && !aflcc->have_lsan) { if (getenv("AFL_USE_LSAN") && !aflcc->have_lsan) {
// 添加编译选项来启用泄漏消毒
insert_param(aflcc, "-fsanitize=leak"); insert_param(aflcc, "-fsanitize=leak");
// 添加 LSAN 控制的定义
add_defs_lsan_ctrl(aflcc); add_defs_lsan_ctrl(aflcc);
aflcc->have_lsan = 1;
aflcc->have_lsan = 1; // 标记已经启用了 LSAN
} }
// 如果启用了 CFISAN (控制流完整性消毒器),则进行相关配置
if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) {
// 如果是 GCC 插件模式或 GCC 模式,则启用完整的控制流保护
if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) {
// 如果没有启用控制流保护,则添加相应选项
if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); } if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); }
} else { } else {
// 如果没有启用 LTO (链接时优化),则添加 LTO 选项
if (!aflcc->lto_mode && !aflcc->have_flto) { if (!aflcc->lto_mode && !aflcc->have_flto) {
uint32_t i = 0, found = 0; uint32_t i = 0, found = 0;
while (envp[i] != NULL && !found) { while (envp[i] != NULL && !found) {
if (strncmp("-flto", envp[i++], 5) == 0) found = 1; if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
} }
if (!found) { insert_param(aflcc, "-flto"); } if (!found) { insert_param(aflcc, "-flto"); }
aflcc->have_flto = 1; aflcc->have_flto = 1; // 标记已经启用了 LTO
} }
// 如果没有启用 CFISAN则添加相应选项来启用控制流完整性消毒
if (!aflcc->have_cfisan) { insert_param(aflcc, "-fsanitize=cfi"); } if (!aflcc->have_cfisan) { insert_param(aflcc, "-fsanitize=cfi"); }
// 如果没有启用隐藏符号,则启用隐藏符号选项
if (!aflcc->have_hidden) { if (!aflcc->have_hidden) {
insert_param(aflcc, "-fvisibility=hidden"); insert_param(aflcc, "-fvisibility=hidden");
aflcc->have_hidden = 1; aflcc->have_hidden = 1;
} }
aflcc->have_cfisan = 1; aflcc->have_cfisan = 1; // 标记已经启用了 CFISAN
} }
} }
} }
/* Add params to enable LLVM SanCov, the native PCGUARD */ /* Add params to enable LLVM SanCov, the native PCGUARD */
@ -2564,10 +2571,13 @@ void add_gcc_plugin(aflcc_state_t *aflcc) {
/* Add some miscellaneous params required by our instrumentation. */ /* Add some miscellaneous params required by our instrumentation. */
void add_misc_params(aflcc_state_t *aflcc) { void add_misc_params(aflcc_state_t *aflcc) {
// 如果环境变量 AFl_NO_BUILTIN 或其他相关环境变量被设置,或者启用了 LTO 模式
// 则禁用内置的字符串和内存比较函数
if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") ||
aflcc->lto_mode) { aflcc->lto_mode) {
// 禁用常见的字符串和内存比较函数的内置实现,防止与模糊测试产生冲突
insert_param(aflcc, "-fno-builtin-strcmp"); insert_param(aflcc, "-fno-builtin-strcmp");
insert_param(aflcc, "-fno-builtin-strncmp"); insert_param(aflcc, "-fno-builtin-strncmp");
insert_param(aflcc, "-fno-builtin-strcasecmp"); insert_param(aflcc, "-fno-builtin-strcasecmp");
@ -2579,31 +2589,46 @@ void add_misc_params(aflcc_state_t *aflcc) {
} }
if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } // 如果没有启用位置无关代码PIC则添加 -fPIC 参数
if (!aflcc->have_pic) {
insert_param(aflcc, "-fPIC");
}
// 如果环境变量 AFL_HARDEN 被设置,启用栈保护等安全选项
if (getenv("AFL_HARDEN")) { if (getenv("AFL_HARDEN")) {
// 启用所有函数的栈保护
insert_param(aflcc, "-fstack-protector-all"); insert_param(aflcc, "-fstack-protector-all");
if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); // 如果未设置 Fortify设置 Fortify 防护等级
if (!aflcc->fortify_set)
add_defs_fortify(aflcc, 2);
} }
// 如果环境变量 AFL_DONT_OPTIMIZE 未设置,启用优化选项
if (!getenv("AFL_DONT_OPTIMIZE")) { if (!getenv("AFL_DONT_OPTIMIZE")) {
// 启用调试符号生成
insert_param(aflcc, "-g"); insert_param(aflcc, "-g");
if (!aflcc->have_o) insert_param(aflcc, "-O3");
if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); // 如果没有设置 -O 优化级别,设置为 -O3最高优化
if (!aflcc->have_o)
insert_param(aflcc, "-O3");
// 如果没有设置循环展开,启用循环展开优化
if (!aflcc->have_unroll)
insert_param(aflcc, "-funroll-loops");
// 以下代码被注释掉了,但如果有指定架构优化选项(如 -march也可以启用
// if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-')
// insert_param(aflcc, aflcc->march_opt); // insert_param(aflcc, aflcc->march_opt);
} }
// 如果设置了 x_set 标志,插入 -x none 参数
if (aflcc->x_set) { if (aflcc->x_set) {
insert_param(aflcc, "-x"); insert_param(aflcc, "-x");
insert_param(aflcc, "none"); insert_param(aflcc, "none");
} }
} }
@ -3082,6 +3107,44 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
char **argv) { char **argv) {
<<<<<<< HEAD
u8 skip_next = 0;
while (--argc) {
u8 *cur = *(++argv);
if (skip_next > 0) {
skip_next--;
continue;
}
if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue;
if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue;
if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv))
continue;
if (*cur == '@') {
u8 *filename = cur + 1;
if (aflcc->debug) { DEBUGF("response file=%s\n", filename); }
FILE *f = fopen(filename, "r");
if (!f) {
if (!scan) insert_param(aflcc, cur);
continue;
}
struct stat st;
if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode) || st.st_size < 1) {
fclose(f);
if (!scan) insert_param(aflcc, cur);
continue;
}
static u32 rsp_count = 2000;
if (scan) {
if (rsp_count == 0) FATAL("Too many response files provided!");
--rsp_count;
}
u32 argc_read = 1;
char **argv_read = ck_alloc(sizeof(char *));
argv_read[0] = "";
char *arg_buf = NULL;
u64 arg_len = 0;
enum fsm_state {
=======
// for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
/* Process the argument list. */ /* Process the argument list. */
@ -3167,15 +3230,20 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
enum fsm_state { enum fsm_state {
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
fsm_whitespace, // whitespace seen so far fsm_whitespace, // whitespace seen so far
fsm_double_quote, // have unpaired double quote fsm_double_quote, // have unpaired double quote
fsm_single_quote, // have unpaired single quote fsm_single_quote, // have unpaired single quote
fsm_backslash, // a backslash is seen with no unpaired quote fsm_backslash, // a backslash is seen with no unpaired quote
fsm_normal // a normal char is seen fsm_normal // a normal char is seen
<<<<<<< HEAD
};
=======
}; };
// Workaround to append c to arg buffer, and append the buffer to argv // Workaround to append c to arg buffer, and append the buffer to argv
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
#define ARG_ALLOC(c) \ #define ARG_ALLOC(c) \
do { \ do { \
\ \
@ -3358,6 +3426,54 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
/* Process each of the existing argv, also add a few new args. */ /* Process each of the existing argv, also add a few new args. */
static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv,
char **envp) { char **envp) {
<<<<<<< HEAD
add_real_argv0(aflcc);
if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC) {
insert_param(aflcc, "-Wno-unused-command-line-argument");
}
if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) {
add_assembler(aflcc);
}
if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); }
if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) {
if (aflcc->lto_mode && aflcc->have_instr_env) {
load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so");
}
if (getenv("AFL_LLVM_DICT2FILE")) {
load_llvm_pass(aflcc, "afl-llvm-dict2file.so");
}
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
load_llvm_pass(aflcc, "split-switches-pass.so");
}
if (getenv("LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
load_llvm_pass(aflcc, "compare-transform-pass.so");
}
if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
load_llvm_pass(aflcc, "split-compares-pass.so");
}
if (aflcc->cmplog_mode) {
insert_param(aflcc, "-fno-inline");
load_llvm_pass(aflcc, "cmplog-switches-pass.so");
load_llvm_pass(aflcc, "split-switches-pass.so");
}
if (aflcc->lto_mode) {
insert_param(aflcc, aflcc->lto_flag);
if (!aflcc->have_c) {
add_lto_linker(aflcc);
add_lto_passes(aflcc);
}
} else {
if (aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
add_optimized_pcguard(aflcc);
} else if (aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) {
add_native_pcguard(aflcc);
} else {
load_llvm_pass(aflcc, "afl-llvm-pass.so");
}
}
=======
add_real_argv0(aflcc); add_real_argv0(aflcc);
@ -3457,6 +3573,7 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv,
} }
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
if (aflcc->cmplog_mode) { if (aflcc->cmplog_mode) {
load_llvm_pass(aflcc, "cmplog-instructions-pass.so"); load_llvm_pass(aflcc, "cmplog-instructions-pass.so");
@ -3496,50 +3613,86 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv,
} }
/* Main entry point */ /* Main entry point */
int main(int argc, char **argv, char **envp) { classDiagram
class AFLCCMain {
aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); +main(argc, argv, envp)
aflcc_state_init(aflcc, (u8 *)argv[0]); +initializeState()
+checkEnvironmentVariables()
check_environment_vars(envp); +findDependencies()
+determineCompilerMode()
find_built_deps(aflcc); +determineInstrumentationMode()
+finalizeMode()
compiler_mode_by_callname(aflcc); +processParameters()
compiler_mode_by_environ(aflcc); +maybeShowUsage()
compiler_mode_by_cmdline(aflcc, argc, argv); +notifyMode()
+debugArguments()
instrument_mode_by_environ(aflcc); +editParameters()
+executeCompiler()
mode_final_checkout(aflcc, argc, argv); }
process_params(aflcc, 1, argc, argv);
maybe_usage(aflcc, argc, argv);
mode_notification(aflcc); class AFLCCState {
-cc_params: char**
-cc_par_cnt: u32
-passthrough: u8
-debug: u8
+aflcc_state_init(state, prog_name)
}
if (aflcc->debug) debugf_args(argc, argv); class EnvironmentChecker {
+check_environment_vars(envp)
}
edit_params(aflcc, argc, argv, envp); class DependencyFinder {
+find_built_deps(aflcc)
}
if (aflcc->debug) class CompilerModeHandler {
debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); +compiler_mode_by_callname(aflcc)
+compiler_mode_by_environ(aflcc)
+compiler_mode_by_cmdline(aflcc, argc, argv)
}
if (aflcc->passthrough) { class InstrumentationModeHandler {
+instrument_mode_by_environ(aflcc)
}
argv[0] = aflcc->cc_params[0]; class ModeFinalizer {
execvp(aflcc->cc_params[0], (char **)argv); +mode_final_checkout(aflcc, argc, argv)
}
} else { class ParameterProcessor {
+process_params(aflcc, start_idx, argc, argv)
}
execvp(aflcc->cc_params[0], (char **)aflcc->cc_params); class UsageNotifier {
+maybe_usage(aflcc, argc, argv)
}
class ModeNotifier {
+mode_notification(aflcc)
} }
FATAL("Oops, failed to execute '%s' - check your PATH", aflcc->cc_params[0]); class Debugger {
+debugf_args(argc, argv)
}
return 0; class ParameterEditor {
+edit_params(aflcc, argc, argv, envp)
}
class Executor {
+execute_compiler(aflcc, argv)
} }
AFLCCMain --> AFLCCState : 使
AFLCCMain --> EnvironmentChecker : 使
AFLCCMain --> DependencyFinder : 使
AFLCCMain --> CompilerModeHandler : 使
AFLCCMain --> InstrumentationModeHandler : 使
AFLCCMain --> ModeFinalizer : 使
AFLCCMain --> ParameterProcessor : 使
AFLCCMain --> UsageNotifier : 使
AFLCCMain --> ModeNotifier : 使
AFLCCMain --> Debugger : 使
AFLCCMain --> ParameterEditor : 使
AFLCCMain --> Executor : 使

File diff suppressed because it is too large Load Diff

@ -23,6 +23,8 @@
how they affect the execution path. how they affect the execution path.
*/ */
//引入了 AFL++ 的核心头文件、CMPLog 相关头文件、通用函数头文件等。
//根据编译选项,可能还会包含其他系统头文件,如内存映射、文件操作等。
#include "afl-fuzz.h" #include "afl-fuzz.h"
#include "cmplog.h" #include "cmplog.h"
@ -82,7 +84,9 @@
\ \
\ \
} while (0) } while (0)
//定义了与 zlib 相关的宏,用于处理压缩文件的读写操作。
//对于苹果系统,引入了特定的头文件以支持线程优先级设置。
//如果启用了性能分析,则声明了一个外部变量 time_spent_working 用于记录工作时间
#include <zlib.h> #include <zlib.h>
#define ZLIBOPEN gzopen #define ZLIBOPEN gzopen
#define ZLIBREAD ck_gzread #define ZLIBREAD ck_gzread
@ -106,13 +110,14 @@
#ifdef PROFILING #ifdef PROFILING
extern u64 time_spent_working; extern u64 time_spent_working;
#endif #endif
//程序退出时的清理函数
static void at_exit() { static void at_exit() {//at_exit 函数在 AFL++ 程序退出时被调用,用于清理资源和终止子进程
//首先尝试获取环境变量 __AFL_TARGET_PID2 和 __AFL_TARGET_PID1这些变量存储了目标进程的 PID
s32 i, pid1 = 0, pid2 = 0, pgrp = -1; s32 i, pid1 = 0, pid2 = 0, pgrp = -1;
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL}; char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
char *ptr; char *ptr;
//如果找到有效的 PID则获取其进程组 ID 并向进程组发送 SIGTERM 信号以终止整个进程组,
//然后单独向目标进程发送 SIGTERM 信号。
ptr = getenv("__AFL_TARGET_PID2"); ptr = getenv("__AFL_TARGET_PID2");
if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) { if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) {
@ -130,10 +135,11 @@ static void at_exit() {
kill(pid1, SIGTERM); kill(pid1, SIGTERM);
} }
//尝试获取环境变量 CPU_AFFINITY_ENV_VAR如果存在且非空则删除该文件以解除 CPU 亲和性设置
ptr = getenv(CPU_AFFINITY_ENV_VAR); ptr = getenv(CPU_AFFINITY_ENV_VAR);
if (ptr && *ptr) unlink(ptr); if (ptr && *ptr) unlink(ptr);
//遍历 list 数组,获取每个环境变量的值,如果存在且非空,
//则根据编译选项使用不同的共享内存删除函数shm_unlink 或 shmctl来删除共享内存
i = 0; i = 0;
while (list[i] != NULL) { while (list[i] != NULL) {
@ -173,13 +179,14 @@ static void at_exit() {
pgrp = getpgid(pid1); pgrp = getpgid(pid1);
if (pgrp > 0) { killpg(pgrp, kill_signal); } if (pgrp > 0) { killpg(pgrp, kill_signal); }
kill(pid2, kill_signal); kill(pid2, kill_signal);
//最后,获取环境变量 AFL_KILL_SIGNAL 的值作为要发送的信号类型(默认为 SIGKILL
//然后再次检查 PID1 和 PID2获取其进程组 ID 并向进程组发送相应的信号,单独向目标进程发送信号以确保其被终止
} }
} }
/* Display usage hints. */ /* Display usage hints. */
//主要为显示说明
static void usage(u8 *argv0, int more_help) { static void usage(u8 *argv0, int more_help) {
SAYF( SAYF(
@ -190,7 +197,8 @@ static void usage(u8 *argv0, int more_help) {
"also see \n" "also see \n"
" AFL_AUTORESUME)\n" " AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n" " -o dir - output directory for fuzzer findings\n\n"
//-i dir指定输入目录该目录包含用于模糊测试的测试用例。如果输入为 -,则表示恢复之前的模糊测试会话。
//-o dir指定输出目录用于存储模糊测试过程中发现的结果。
"Execution control settings:\n" "Execution control settings:\n"
" -P strategy - set fix mutation strategy: explore (focus on new " " -P strategy - set fix mutation strategy: explore (focus on new "
"coverage),\n" "coverage),\n"
@ -211,6 +219,11 @@ static void usage(u8 *argv0, int more_help) {
"maximum.\n" "maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit " " -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n" "[default])\n"
//-P strategy设置固定的变异策略。可以选择 explore专注于发现新覆盖率或 exploit专注于触发崩溃。还可以设置在没有发现新结果时自动切换到 exploit 模式的时间(以秒为单位),并在发现新覆盖率时切换回 explore 模式。
//-p schedule设置功率调度策略用于计算种子的性能得分。可选的策略包括 explore默认、fast、exploit、seek、rare、mmopt、coe、lin 和 quad。具体的策略选择和效果可以参考 AFL++ 的文档。
//-f file指定被模糊测试程序读取的文件位置默认为标准输入或 @@。
//-t msec设置每次运行的超时时间自动缩放默认为指定的毫秒数。可以在超时值后加上 +,表示自动计算超时时间,指定的值为最大值。
//-m megs设置子进程的内存限制以兆字节为单位默认为 0表示不限制
#if defined(__linux__) && defined(__aarch64__) #if defined(__linux__) && defined(__aarch64__)
" -A - use binary-only instrumentation (ARM CoreSight mode)\n" " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
#endif #endif
@ -223,6 +236,12 @@ static void usage(u8 *argv0, int more_help) {
#if defined(__linux__) #if defined(__linux__)
" -X - use VM fuzzing (NYX mode - standalone mode)\n" " -X - use VM fuzzing (NYX mode - standalone mode)\n"
" -Y - use VM fuzzing (NYX mode - multiple instances mode)\n" " -Y - use VM fuzzing (NYX mode - multiple instances mode)\n"
//-A在 ARM 架构的 Linux 系统上使用二进制插桩ARM CoreSight 模式)。
//-O使用 FRIDA 模式进行二进制插桩。
//-Q在 Linux 系统上,使用 QEMU 模式进行二进制插桩。
//-U在 Linux 系统上,使用基于 Unicorn 的插桩Unicorn 模式)。
//-W在 Linux 系统上,使用基于 QEMU 和 Wine 的插桩Wine 模式)。
//-X 和 -Y在 Linux 系统上,使用 VM 模糊测试NYX 模式),分别支持独立模式和多实例模式。
#endif #endif
"\n" "\n"
@ -296,10 +315,11 @@ static void usage(u8 *argv0, int more_help) {
#if defined USE_COLOR && !defined ALWAYS_COLORED #if defined USE_COLOR && !defined ALWAYS_COLORED
#define DYN_COLOR \ #define DYN_COLOR \
"AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n" "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n"
//定义了 USE_COLOR 但未定义 ALWAYS_COLORED则定义 DYN_COLOR 宏,用于提示用户如何关闭控制台的颜色输出
#else #else
#define DYN_COLOR #define DYN_COLOR
#endif #endif
//如果定义了 AFL_PERSISTENT_RECORD则定义 PERSISTENT_MSG 宏,用于提示用户 AFL_PERSISTENT_RECORD 环境变量的作用
#ifdef AFL_PERSISTENT_RECORD #ifdef AFL_PERSISTENT_RECORD
#define PERSISTENT_MSG \ #define PERSISTENT_MSG \
"AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \ "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
@ -308,7 +328,7 @@ static void usage(u8 *argv0, int more_help) {
#define PERSISTENT_MSG #define PERSISTENT_MSG
#endif #endif
SAYF( SAYF(//用于输出详细的帮助信息,包括 AFL++ 使用的各种环境变量及其作用。
"Environment variables used:\n" "Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"ASAN_OPTIONS: custom settings for ASAN\n" "ASAN_OPTIONS: custom settings for ASAN\n"
@ -411,7 +431,59 @@ static void usage(u8 *argv0, int more_help) {
" seconds (default: 60, minimum: 1)\n" " seconds (default: 60, minimum: 1)\n"
"\n" "\n"
); );
/*
LD_BIND_LAZY AFL++ LD_BIND_NOW
ASAN_OPTIONS MSAN_OPTIONS ASAN MSAN AFL++
AFL_AUTORESUME
AFL_BENCH_JUST_ONE AFL_BENCH_UNTIL_CRASH退
AFL_CMPLOG_ONLY_NEW CMPLog
AFL_CRASH_EXITCODE AFL++ 退
AFL_CUSTOM_MUTATOR_LIBRARY AFL_CUSTOM_MUTATOR_ONLY使
AFL_CYCLE_SCHEDULES
AFL_DEBUG AFL_DEBUG_CHILD stdout/stderr
AFL_DISABLE_REDUNDANT AFL_DISABLE_TRIM
AFL_DUMB_FORKSRV使 fork
AFL_EXIT_WHEN_DONE AFL_EXIT_ON_TIME退退
AFL_EXIT_ON_SEED_ISSUES退
AFL_EXPAND_HAVOC_NOW Havoc
AFL_FAST_CAL
AFL_FORCE_UI
AFL_FORKSRV_INIT_TMOUT fork
AFL_HANG_TMOUT
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES
AFL_IGNORE_PROBLEMS AFL_IGNORE_PROBLEMS_COVERAGE
AFL_IGNORE_SEED_PROBLEMS AFL_IGNORE_TIMEOUTS退
AFL_IGNORE_UNKNOWN_ENVS
AFL_IMPORT_FIRST
AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX AFL++
AFL_PIZZA_MODE AFL++ 4 1
AFL_KILL_SIGNAL AFL_FORK_SERVER_KILL_SIGNAL fork ID
AFL_MAP_SIZE
AFL_MAX_DET_EXTRAS使
AFL_NO_AFFINITY AFL_TRY_AFFINITY使 CPU 使 CPU
AFL_NO_ARITH AFL_NO_AUTODICT
AFL_NO_CPU_RED AFL_NO_FORKSRV CPU 使 execve 使 fork
AFL_NO_SNAPSHOT AFL_NO_STARTUP_CALIBRATION使
AFL_NO_WARN_INSTABILITY AFL_NO_UI
AFL_NYX_AUX_SIZENyx 4096
AFL_NYX_DISABLE_SNAPSHOT_MODE AFL_NYX_LOG NYX hprintf
AFL_NYX_REUSE_SNAPSHOT Nyx
AFL_PATHAFL
AFL_PYTHON_MODULE使 Python
AFL_QUIET fork
AFL_POST_PROCESS_KEEP_ORIGINAL
AFL_PRELOAD LD_PRELOAD/DYLD_INSERT_LIBRARIES
AFL_TARGET_ENV
AFL_SHUFFLE_QUEUE
AFL_SKIP_BIN_CHECK AFL_SKIP_CPUFREQ AFL CPU
AFL_STATSD StatsD
AFL_NO_FASTRESUME AFL_NO_SYNC
AFL_SYNC_TIME AFL_FINAL_SYNC退
AFL_NO_CRASH_README README
AFL_TESTCACHE_SIZE AFL_TMPDIR
AFL_EARLY_FORKSERVER AFL_PERSISTENT AFL-clang-fast/AFL-clang-lto/AFL-gcc-fast fork
AFL_DEFER_FORKSRV fork __AFL_INIT
AFL_FUZZER_STATS_UPDATE_INTERVAL fuzzer_stats */
} else { } else {
SAYF( SAYF(
@ -423,50 +495,56 @@ static void usage(u8 *argv0, int more_help) {
#ifdef USE_PYTHON #ifdef USE_PYTHON
SAYF("Compiled with %s module support, see docs/custom_mutators.md\n", SAYF("Compiled with %s module support, see docs/custom_mutators.md\n",
(char *)PYTHON_VERSION); (char *)PYTHON_VERSION);
/*
USE_PYTHON AFL++ 使 Python 使
AFL++ Python */
#else #else
SAYF("Compiled without Python module support.\n"); SAYF("Compiled without Python module support.\n");
#endif #endif
/*如果定义了 AFL_PERSISTENT_RECORD则输出 AFL++ 是使用持久记录支持编译的。
AFL++ */
#ifdef AFL_PERSISTENT_RECORD #ifdef AFL_PERSISTENT_RECORD
SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n"); SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
#else #else
SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n"); SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
#endif #endif
/*如果定义了 USEMMAP则输出 AFL++ 是使用 shm_open 支持编译的。
AFL++ 使 shmat */
#ifdef USEMMAP #ifdef USEMMAP
SAYF("Compiled with shm_open support.\n"); SAYF("Compiled with shm_open support.\n");
#else #else
SAYF("Compiled with shmat support.\n"); SAYF("Compiled with shmat support.\n");
#endif #endif
/*如果定义了 ASAN_BUILD则输出 AFL++ 是使用 ASAN 构建编译的。*/
#ifdef ASAN_BUILD #ifdef ASAN_BUILD
SAYF("Compiled with ASAN_BUILD.\n"); SAYF("Compiled with ASAN_BUILD.\n");
#endif #endif
/*如果定义了 NO_SPLICING则输出 AFL++ 是使用禁止拼接选项编译的*/
#ifdef NO_SPLICING #ifdef NO_SPLICING
SAYF("Compiled with NO_SPLICING.\n"); SAYF("Compiled with NO_SPLICING.\n");
#endif #endif
/*如果定义了 FANCY_BOXES_NO_UTF则输出 AFL++ 是没有 UTF-8 支持编译的,这会影响状态屏幕中的线条渲染。*/
#ifdef FANCY_BOXES_NO_UTF #ifdef FANCY_BOXES_NO_UTF
SAYF("Compiled without UTF-8 support for line rendering in status screen.\n"); SAYF("Compiled without UTF-8 support for line rendering in status screen.\n");
#endif #endif
/*如果定义了 PROFILING则输出 AFL++ 是使用性能分析编译的。*/
#ifdef PROFILING #ifdef PROFILING
SAYF("Compiled with PROFILING.\n"); SAYF("Compiled with PROFILING.\n");
#endif #endif
/*如果定义了 INTROSPECTION则输出 AFL++ 是使用自省编译的。*/
#ifdef INTROSPECTION #ifdef INTROSPECTION
SAYF("Compiled with INTROSPECTION.\n"); SAYF("Compiled with INTROSPECTION.\n");
#endif #endif
/*如果定义了 _DEBUG则输出 AFL++ 是使用调试模式编译的*/
#ifdef _DEBUG #ifdef _DEBUG
SAYF("Compiled with _DEBUG.\n"); SAYF("Compiled with _DEBUG.\n");
#endif #endif
/*如果定义了 _AFL_DOCUMENT_MUTATIONS则输出 AFL++ 是使用记录变异编译的。*/
#ifdef _AFL_DOCUMENT_MUTATIONS #ifdef _AFL_DOCUMENT_MUTATIONS
SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n"); SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
#endif #endif
/*如果定义了 _AFL_SPECIAL_PERFORMANCE则输出 AFL++ 是使用特定系统的特殊性能选项编译的,并提醒用户这可能不适用于其他平台。*/
#ifdef _AFL_SPECIAL_PERFORMANCE #ifdef _AFL_SPECIAL_PERFORMANCE
SAYF( SAYF(
"Compiled with special performance options for this specific system, it " "Compiled with special performance options for this specific system, it "
@ -477,7 +555,9 @@ static void usage(u8 *argv0, int more_help) {
exit(1); exit(1);
#undef PHYTON_SUPPORT #undef PHYTON_SUPPORT
/*额外帮助:输出提示信息,建议用户查阅 README.md 文件以获取更多帮助。
退 exit(1) 退 1 退
使 #undef PHYTON_SUPPORT PHYTON_SUPPORT PYTHON_SUPPORT*/
} }
#ifndef AFL_LIB #ifndef AFL_LIB
@ -544,9 +624,10 @@ static void fasan_check_afl_preload(char *afl_preload) {
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;//用于存储 getopt 函数返回的选项字符
u64 prev_queued = 0; u64 prev_queued = 0;//自动同步标志,初始值为 0。
u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1, //用于记录上一次排队的项目数量。
u32 sync_interval_cnt /*同步间隔计数器*/= 0, seek_to = 0, show_help = 0, default_output = 1,
map_size = get_map_size(); map_size = get_map_size();
u8 *extras_dir[4]; u8 *extras_dir[4];
u8 mem_limit_given = 0, exit_1 = 0, debug = 0, u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
@ -557,9 +638,20 @@ int main(int argc, char **argv_orig, char **envp) {
struct timeval tv; struct timeval tv;
struct timezone tz; struct timezone tz;
/*eek_to用于指定从哪个位置开始处理队列。
show_help
default_output 1
map_size get_map_size
extras_dir[4]
mem_limit_given
exit_1
debug
extras_dir_cnt
afl_preload frida_afl_preload AFL
use_argv
struct timeval tv struct timezone tz*/
doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
//根据 DOC_PATH 环境变量或默认路径 "docs" 初始化文档路径
if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) { if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) {
printf("afl-fuzz" VERSION "\n"); printf("afl-fuzz" VERSION "\n");
@ -573,7 +665,8 @@ int main(int argc, char **argv_orig, char **envp) {
exit(0); exit(0);
} }
/*版本信息:如果命令行参数包含 --version则输出 AFL++ 的版本信息并退出程序。
--help usage 退*/
#if defined USE_COLOR && defined ALWAYS_COLORED #if defined USE_COLOR && defined ALWAYS_COLORED
if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) { if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
@ -582,11 +675,11 @@ int main(int argc, char **argv_orig, char **envp) {
"compile time)"); "compile time)");
} }
/*颜色输出:如果定义了 USE_COLOR 和 ALWAYS_COLORED并且环境变量 AFL_NO_COLOR 或 AFL_NO_COLOUR 被设置,则输出警告信息,提示用户颜色设置在编译时已配置。*/
#endif #endif
char **argv = argv_cpy_dup(argc, argv_orig); char **argv = argv_cpy_dup(argc, argv_orig);
//argv_cpy_dup复制命令行参数数组以便在后续处理中使用
afl_state_t *afl = calloc(1, sizeof(afl_state_t)); afl_state_t *afl = calloc(1, sizeof(afl_state_t));
if (!afl) { FATAL("Could not create afl state"); } if (!afl) { FATAL("Could not create afl state"); }
@ -599,15 +692,22 @@ int main(int argc, char **argv_orig, char **envp) {
read_afl_environment(afl, envp); read_afl_environment(afl, envp);
if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; } if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
exit_1 = !!afl->afl_env.afl_bench_just_one; exit_1 = !!afl->afl_env.afl_bench_just_one;
//SAYF输出 AFL++ 的版本信息和基于的原始 AFL 作者信息。
SAYF(cCYA "afl-fuzz" VERSION cRST SAYF(cCYA "afl-fuzz" VERSION cRST
" based on afl by Michal Zalewski and a large online community\n"); " based on afl by Michal Zalewski and a large online community\n");
//gettimeofday获取当前时间。
//rand_set_seed根据当前时间设置随机种子用于后续的随机数生成
gettimeofday(&tv, &tz); gettimeofday(&tv, &tz);
rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid()); rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
//afl->shmem_testcase_mode设置为 1表示始终尝试使用共享内存进行模糊测试。
afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
/*分配内存:为 afl_state_t 结构体分配内存,用于存储 AFL++ 的状态信息。
AFL_DEBUG
afl_state_init AFL
afl_fsrv_init
read_afl_environment AFL++
*/
// still available: HjJkKqruvwz // still available: HjJkKqruvwz
while ((opt = getopt(argc, argv, while ((opt = getopt(argc, argv,
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
@ -694,12 +794,25 @@ int main(int argc, char **argv_orig, char **envp) {
FATAL("Bad syntax used for -b"); FATAL("Bad syntax used for -b");
} }
/*getopt 循环:使用 getopt 函数解析命令行选项。
-a "text""binary" "default"
-P "explore""exploit" "exploit"
-g
-G
-Z
-I
-b AFL++ CPU */
break; break;
} }
case 'c': { case 'c': {
/*-c 选项
CMPLog
"-" CMPLog CMPLog cmplog_binary NULL
"-" CMPLog cmplog_binary */
if (strcmp(optarg, "-") == 0) { if (strcmp(optarg, "-") == 0) {
@ -723,7 +836,11 @@ int main(int argc, char **argv_orig, char **envp) {
} }
case 's': { case 's': {
/*-s 选项
NULL
使 fixed_seed 1使*/
if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); } if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
rand_set_seed(afl, strtoul(optarg, 0L, 10)); rand_set_seed(afl, strtoul(optarg, 0L, 10));
afl->fixed_seed = 1; afl->fixed_seed = 1;
@ -732,7 +849,12 @@ int main(int argc, char **argv_orig, char **envp) {
} }
case 'p': /* Power schedule */ case 'p': /* Power schedule */
/*-p 选项
afl->schedule FASTCOEEXPLOITLINQUADMMOPTRAREEXPLORE SEEK
*/
if (!stricmp(optarg, "fast")) { if (!stricmp(optarg, "fast")) {
afl->schedule = FAST; afl->schedule = FAST;
@ -784,7 +906,11 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'e': case 'e':
/*-e 选项
afl->file_extension -e
afl->file_extension */
if (afl->file_extension) { FATAL("Multiple -e options not supported"); } if (afl->file_extension) { FATAL("Multiple -e options not supported"); }
afl->file_extension = optarg; afl->file_extension = optarg;
@ -792,7 +918,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'i': /* input dir */ case 'i': /* input dir */
/*-i 选项
afl->in_dir -i
NULL -i
afl->in_dir
"-" afl->in_place_resume 1*/
if (afl->in_dir) { FATAL("Multiple -i options not supported"); } if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); } if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
afl->in_dir = optarg; afl->in_dir = optarg;
@ -802,13 +934,28 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'o': /* output dir */ case 'o': /* output dir */
/*-o 选项
afl->out_dir -o
afl->out_dir */
if (afl->out_dir) { FATAL("Multiple -o options not supported"); } if (afl->out_dir) { FATAL("Multiple -o options not supported"); }
afl->out_dir = optarg; afl->out_dir = optarg;
break; break;
case 'M': { /* main sync ID */ case 'M': { /* main sync ID */
/*-M 选项
ID
ARM CoreSight -M
ID -S -M
- -
ID
old_seed_selection 1使
disable_trim 1
ID : ID
is_main_node 1
*/
u8 *c; u8 *c;
if (afl->non_instrumented_mode) { if (afl->non_instrumented_mode) {
@ -862,7 +1009,14 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'S': /* secondary sync id */ case 'S': /* secondary sync id */
/*-S 选项
ID
ARM CoreSight -S
ID -S -M
- -
ID
is_secondary_node 1*/
if (afl->non_instrumented_mode) { if (afl->non_instrumented_mode) {
FATAL("-S is not supported in non-instrumented mode"); FATAL("-S is not supported in non-instrumented mode");
@ -892,7 +1046,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'F': /* foreign sync dir */ case 'F': /* foreign sync dir */
/*-F 选项
-F
foreign_syncs */
if (!optarg) { FATAL("Missing path for -F"); } if (!optarg) { FATAL("Missing path for -F"); }
if (!afl->is_main_node) { if (!afl->is_main_node) {
@ -924,7 +1084,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'f': /* target file */ case 'f': /* target file */
/*-f 选项
-f
use_stdin 0使
default_output 0使*/
if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); } if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); }
afl->fsrv.out_file = ck_strdup(optarg); afl->fsrv.out_file = ck_strdup(optarg);
@ -933,7 +1099,11 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'x': /* dictionary */ case 'x': /* dictionary */
/*-x 选项
-x
extras_dir extras_dir_cnt */
if (extras_dir_cnt >= 4) { if (extras_dir_cnt >= 4) {
FATAL("More than four -x options are not supported"); FATAL("More than four -x options are not supported");
@ -944,7 +1114,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 't': { /* timeout */ case 't': { /* timeout */
/*-t 选项
-t
+
5
timeout_given + */
u8 suffix = 0; u8 suffix = 0;
if (afl->timeout_given) { FATAL("Multiple -t options not supported"); } if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
@ -974,7 +1150,14 @@ int main(int argc, char **argv_orig, char **envp) {
} }
case 'm': { /* mem limit */ case 'm': { /* mem limit */
/*-m 选项
-m
TGkM
5
32 2000 MB*/
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) { if (mem_limit_given) {
@ -1040,19 +1223,30 @@ int main(int argc, char **argv_orig, char **envp) {
case 'd': case 'd':
case 'D': /* old deterministic */ case 'D': /* old deterministic */
/*-d 和 -D 选项
使 -z */
WARNF( WARNF(
"Parameters -d and -D are deprecated, a new enhanced deterministic " "Parameters -d and -D are deprecated, a new enhanced deterministic "
"fuzzing is active by default, to disable it use -z"); "fuzzing is active by default, to disable it use -z");
break; break;
case 'z': /* no deterministic */ case 'z': /* no deterministic */
/*-z 选项
skip_deterministic 1*/
afl->skip_deterministic = 1; afl->skip_deterministic = 1;
break; break;
case 'B': /* load bitmap */ case 'B': /* load bitmap */
/*-B 选项
in_bitmap -B
in_bitmap
*/
/* This is a secret undocumented option! It is useful if you find /* This is a secret undocumented option! It is useful if you find
an interesting test case during a normal fuzzing process, and want an interesting test case during a normal fuzzing process, and want
to mutate it without rediscovering any of the test cases already to mutate it without rediscovering any of the test cases already
@ -1070,13 +1264,22 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'C': /* crash mode */ case 'C': /* crash mode */
/*-C 选项
crash_mode -C
crash_mode FSRV_RUN_CRASH*/
if (afl->crash_mode) { FATAL("Multiple -C options not supported"); } if (afl->crash_mode) { FATAL("Multiple -C options not supported"); }
afl->crash_mode = FSRV_RUN_CRASH; afl->crash_mode = FSRV_RUN_CRASH;
break; break;
case 'n': /* dumb mode */ case 'n': /* dumb mode */
/*-n 选项
-M -S 使
non_instrumented_mode -n
AFL_DUMB_FORKSRV non_instrumented_mode 1 2*/
if (afl->is_main_node || afl->is_secondary_node) { if (afl->is_main_node || afl->is_secondary_node) {
FATAL("Non instrumented mode is not supported with -M / -S"); FATAL("Non instrumented mode is not supported with -M / -S");
@ -1102,14 +1305,26 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'T': /* banner */ case 'T': /* banner */
/*-T 选项
use_banner -T
use_banner */
if (afl->use_banner) { FATAL("Multiple -T options not supported"); } if (afl->use_banner) { FATAL("Multiple -T options not supported"); }
afl->use_banner = optarg; afl->use_banner = optarg;
break; break;
#ifdef __linux__ #ifdef __linux__
case 'X': /* NYX mode */ case 'X': /* NYX mode */
/*-X 和 -Y 选项(仅限 Linux
Nyx
-X Nyx
nyx_mode -X
nyx_parentnyx_standalone nyx_mode Nyx
-Y Nyx
nyx_mode -Y
nyx_mode Nyx */
if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
afl->fsrv.nyx_parent = true; afl->fsrv.nyx_parent = true;
@ -1132,7 +1347,12 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
#endif #endif
case 'A': /* CoreSight mode */ case 'A': /* CoreSight mode */
/*-A 选项(仅限 ARM64 和 Linux
ARM CoreSight
ARM CoreSight -M -S 使
cs_mode -A
cs_mode ARM CoreSight */
#if !defined(__aarch64__) || !defined(__linux__) #if !defined(__aarch64__) || !defined(__linux__)
FATAL("-A option is not supported on this platform"); FATAL("-A option is not supported on this platform");
#endif #endif
@ -1150,7 +1370,12 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
/*-O 选项
FRIDA
frida_mode -O
frida_mode FRIDA
AFL_USE_FASAN frida_asan 1使 FRIDA */
if (afl->fsrv.frida_mode) { if (afl->fsrv.frida_mode) {
FATAL("Multiple -O options not supported"); FATAL("Multiple -O options not supported");
@ -1163,7 +1388,12 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'Q': /* QEMU mode */ case 'Q': /* QEMU mode */
/*-Q 选项
QEMU
qemu_mode -Q
qemu_mode 1 QEMU
mem_limit MEM_LIMIT_QEMU QEMU */
if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); } if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
afl->fsrv.qemu_mode = 1; afl->fsrv.qemu_mode = 1;
@ -1173,14 +1403,24 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'N': /* Unicorn mode */ case 'N': /* Unicorn mode */
/*-N 选项
no_unlink -N
no_unlink true*/
if (afl->no_unlink) { FATAL("Multiple -N options not supported"); } if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
afl->fsrv.no_unlink = (afl->no_unlink = true); afl->fsrv.no_unlink = (afl->no_unlink = true);
break; break;
case 'U': /* Unicorn mode */ case 'U': /* Unicorn mode */
/*-U 选项
Unicorn
unicorn_mode -U
unicorn_mode 1 Unicorn
mem_limit MEM_LIMIT_UNICORN Unicorn
*/
if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); } if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
afl->unicorn_mode = 1; afl->unicorn_mode = 1;
@ -1189,7 +1429,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
/*-W 选项
Wine+QEMU
use_wine -W
qemu_mode 1 QEMU
use_wine 1 Wine
mem_limit 0*/
if (afl->use_wine) { FATAL("Multiple -W options not supported"); } if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
afl->fsrv.qemu_mode = 1; afl->fsrv.qemu_mode = 1;
afl->use_wine = 1; afl->use_wine = 1;
@ -1199,7 +1445,12 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'V': { case 'V': {
/*-V 选项
AFL++
most_time_key 1
*/
afl->most_time_key = 1; afl->most_time_key = 1;
if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 || if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 ||
optarg[0] == '-') { optarg[0] == '-') {
@ -1211,7 +1462,12 @@ int main(int argc, char **argv_orig, char **envp) {
} break; } break;
case 'E': { case 'E': {
/*-E 选项
AFL++
most_execs_key 1
*/
afl->most_execs_key = 1; afl->most_execs_key = 1;
if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 || if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 ||
optarg[0] == '-') { optarg[0] == '-') {
@ -1223,7 +1479,20 @@ int main(int argc, char **argv_orig, char **envp) {
} break; } break;
case 'l': { case 'l': {
/*-l 选项
CMPLog
CMPLog
'0''1' CMPLog 1
'2' CMPLog 2
'3' CMPLog 3
'a''A'
's''S'
't''T'
'x''X'
'r''R'
CMPLog CMPLOG_LVL_MAX cmplog_max_filesize MAX_FILE*/
if (!optarg) { FATAL("missing parameter for 'l'"); } if (!optarg) { FATAL("missing parameter for 'l'"); }
char *c = optarg; char *c = optarg;
while (*c) { while (*c) {
@ -1286,7 +1555,23 @@ int main(int argc, char **argv_orig, char **envp) {
} break; } break;
case 'L': { /* MOpt mode */ case 'L': { /* MOpt mode */
/*-L 选项
MOpt
limit_time_sig -L
havoc_max_mult HAVOC_MAX_MULT_MOPT MOpt Havoc
-1 limit_time_sig -1 MOpt limit_time_puppet 0
0 -1 0 2000000 -1
limit_time_sig 1
old_seed_selection 1使
60 * 1000
MOpt swarm_nowkey_puppetg_noww_now
swarm swarm_fitnessstage_finds_puppetprobability_nowx_nowv_nowL_bestG_besteff_best
MOpt Havoc */
if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); } if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); }
afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT;
@ -1435,35 +1720,55 @@ int main(int argc, char **argv_orig, char **envp) {
case 'h': case 'h':
show_help++; show_help++;
break; // not needed break; // not needed
/*-h 选项
show_help
break switch case
*/
case 'R': case 'R':
/*-R 选项
Radamsa
Radamsa 使custom_mutators/radamsa/使*/
FATAL( FATAL(
"Radamsa is now a custom mutator, please use that " "Radamsa is now a custom mutator, please use that "
"(custom_mutators/radamsa/)."); "(custom_mutators/radamsa/).");
break; break;
/*默认情况
show_help 1*/
default: default:
if (!show_help) { show_help = 1; } if (!show_help) { show_help = 1; }
} }
} }
/*同步 ID 检查
ID
sync_id "addseeds" "addseeds" ID*/
if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) { if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) {
FATAL("-M/-S name 'addseeds' is a reserved name, choose something else"); FATAL("-M/-S name 'addseeds' is a reserved name, choose something else");
} }
/*主节点和功率调度检查
is_main_node 1 FAST EXPLORE -M FAST EXPLORE */
if (afl->is_main_node == 1 && afl->schedule != FAST && if (afl->is_main_node == 1 && afl->schedule != FAST &&
afl->schedule != EXPLORE) { afl->schedule != EXPLORE) {
FATAL("-M is compatible only with fast and explore -p power schedules"); FATAL("-M is compatible only with fast and explore -p power schedules");
} }
/*参数检查和帮助信息显示
optind argc show_help usage 退*/
if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) { if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
usage(argv[0], show_help); usage(argv[0], show_help);
@ -1473,7 +1778,14 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->afl_env.afl_persistent_record)) { if (unlikely(afl->afl_env.afl_persistent_record)) {
#ifdef AFL_PERSISTENT_RECORD #ifdef AFL_PERSISTENT_RECORD
/*持久记录配置检查
AFL_PERSISTENT_RECORD
afl_env.afl_persistent_record
AFL++ 使 AFL_PERSISTENT_RECORD
fsrv.persistent_record
2 AFL_PERSISTENT_RECORD 2 100 1000
AFL++ 使 AFL_PERSISTENT_RECORD AFL++ AFL_PERSISTENT_RECORD */
afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record); afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
if (afl->fsrv.persistent_record < 2) { if (afl->fsrv.persistent_record < 2) {
@ -1495,13 +1807,19 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
/*内存限制调整
CMPLog 260 CMPLog */
OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea " OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
"Fioraldi and Heiko \"hexcoder\" Eißfeldt"); "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
OKF("AFL++ is open source, get it at " OKF("AFL++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus"); "https://github.com/AFLplusplus/AFLplusplus");
OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md"); OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
/*版本信息显示
AFL++ Marc "van Hauser" HeuseDominik MaierAndrea Fioraldi Heiko "hexcoder" Eißfeldt
AFL++ GitHub
AFL++ 3 README.md */
#ifdef __linux__ #ifdef __linux__
if (afl->fsrv.nyx_mode) { if (afl->fsrv.nyx_mode) {
@ -1510,18 +1828,24 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz"); OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
} }
/*Nyx 模式信息显示(仅限 Linux
Nyx Nyx Sergej Schumilo Nyx GitHub */
#endif #endif
// silently disable deterministic mutation if custom mutators are used // silently disable deterministic mutation if custom mutators are used
if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) { if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
/*确定性变异禁用
*/
afl->skip_deterministic = 1; afl->skip_deterministic = 1;
} }
if (afl->fixed_seed) { if (afl->fixed_seed) {
/*固定种子信息显示
使*/
OKF("Running with fixed seed: %u", (u32)afl->init_seed); OKF("Running with fixed seed: %u", (u32)afl->init_seed);
} }
@ -1535,7 +1859,9 @@ int main(int argc, char **argv_orig, char **envp) {
} }
#endif #endif
/*信号配置
configure_afl_kill_signals AFL++ fork QEMUUnicornfauxsrv Nyx 使 SIGKILL 使 SIGTERM */
configure_afl_kill_signals( configure_afl_kill_signals(
&afl->fsrv, afl->afl_env.afl_child_kill_signal, &afl->fsrv, afl->afl_env.afl_child_kill_signal,
afl->afl_env.afl_fsrv_kill_signal, afl->afl_env.afl_fsrv_kill_signal,
@ -1546,12 +1872,21 @@ int main(int argc, char **argv_orig, char **envp) {
) )
? SIGKILL ? SIGKILL
: SIGTERM); : SIGTERM);
/*信号处理设置
setup_signal_handlers AFL++ 便*/
setup_signal_handlers(); setup_signal_handlers();
check_asan_opts(afl); check_asan_opts(afl);
/*ASAN 构建内存限制禁用(仅限 ASAN 构建)
AFL++ 使 ASAN ASAN */
afl->power_name = power_names[afl->schedule]; afl->power_name = power_names[afl->schedule];
/*ASAN 选项检查
check_asan_opts ASAN AFL++ ASAN 使*/
/*功率调度名称设置
power_names afl->power_name */
if (!afl->non_instrumented_mode && !afl->sync_id) { if (!afl->non_instrumented_mode && !afl->sync_id) {
auto_sync = 1; auto_sync = 1;
@ -1560,7 +1895,13 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id); OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id);
} }
/*Nyx 模式同步配置(仅限 Linux
Nyx
Nyx ID "default"
Nyx
ID "0" ID "0"
ID ID 1*/
#ifdef __linux__ #ifdef __linux__
if (afl->fsrv.nyx_mode) { if (afl->fsrv.nyx_mode) {

@ -27,6 +27,9 @@
*/ */
//林睿健阅读部分
#define AFL_MAIN #define AFL_MAIN
#include "config.h" #include "config.h"
@ -97,6 +100,10 @@ static sharedmem_t *shm_fuzz;
/* Classify tuple counts. This is a slow & naive version, but good enough here. /* Classify tuple counts. This is a slow & naive version, but good enough here.
*/ */
/*
count_class_lookup
*/
static const u8 count_class_lookup[256] = { static const u8 count_class_lookup[256] = {
[0] = 0, [0] = 0,
@ -111,6 +118,10 @@ static const u8 count_class_lookup[256] = {
}; };
/*
kill_child
PID0
*/
static void kill_child() { static void kill_child() {
if (fsrv->child_pid > 0) { if (fsrv->child_pid > 0) {
@ -122,6 +133,11 @@ static void kill_child() {
} }
/*
deinit_shmem
fsrvforkservershm_fuzz
NULL
*/
static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv, static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
sharedmem_t *shm_fuzz) { sharedmem_t *shm_fuzz) {
@ -135,7 +151,11 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
} }
/* Apply mask to classified bitmap (if set). */ /* Apply mask to classified bitmap (if set). */
/*
apply_mask
memmask
NULL
*/
static void apply_mask(u32 *mem, u32 *mask) { static void apply_mask(u32 *mem, u32 *mask) {
u32 i = (map_size >> 2); u32 i = (map_size >> 2);
@ -152,6 +172,12 @@ static void apply_mask(u32 *mem, u32 *mask) {
} }
/*
classify_counts
fsrvforkserver
edges_only
使count_class_lookup
*/
static void classify_counts(afl_forkserver_t *fsrv) { static void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits; u8 *mem = fsrv->trace_bits;
@ -180,7 +206,11 @@ static void classify_counts(afl_forkserver_t *fsrv) {
} }
/* See if any bytes are set in the bitmap. */ /* See if any bytes are set in the bitmap. */
/*
anything_set
fsrvforkserver
1
*/
static inline u8 anything_set(afl_forkserver_t *fsrv) { static inline u8 anything_set(afl_forkserver_t *fsrv) {
u32 *ptr = (u32 *)fsrv->trace_bits; u32 *ptr = (u32 *)fsrv->trace_bits;
@ -196,6 +226,11 @@ static inline u8 anything_set(afl_forkserver_t *fsrv) {
} }
/*
at_exit_handler退
remove_shm
remove_out_file
*/
static void at_exit_handler(void) { static void at_exit_handler(void) {
if (remove_shm) { if (remove_shm) {
@ -211,7 +246,11 @@ static void at_exit_handler(void) {
} }
/* Read initial file. */ /* Read initial file. */
/*
read_initial_file
in_file
*/
static void read_initial_file(void) { static void read_initial_file(void) {
struct stat st; struct stat st;
@ -239,7 +278,11 @@ static void read_initial_file(void) {
} }
/* Write output file. */ /* Write output file. */
/*
write_to_file
pathmemlen
*/
static s32 write_to_file(u8 *path, u8 *mem, u32 len) { static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
s32 ret; s32 ret;
@ -260,7 +303,11 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
/* Execute target application. Returns 0 if the changes are a dud, or /* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */ 1 if they should be kept. */
/*
tmin_run_target
fsrvforkservermemlenfirst_run
*/
static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
u8 first_run) { u8 first_run) {
@ -280,7 +327,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
} }
/* Always discard inputs that time out, unless we are in hang mode */ /* Always discard inputs that time out, unless we are in hang mode */
/* 如果处于挂起模式,总是丢弃超时的输入 */
if (hang_mode) { if (hang_mode) {
switch (ret) { switch (ret) {
@ -300,7 +347,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
classify_counts(fsrv); classify_counts(fsrv);
apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap); apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap);
/* 根据当前模式处理崩溃输入 */
if (ret == FSRV_RUN_TMOUT) { if (ret == FSRV_RUN_TMOUT) {
missed_hangs++; missed_hangs++;
@ -326,7 +373,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
} }
} else { } else {
/* 适当处理非崩溃输入 */
/* Handle non-crashing inputs appropriately. */ /* Handle non-crashing inputs appropriately. */
if (crash_mode) { if (crash_mode) {
@ -352,7 +399,11 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
} }
/* Actually minimize! */ /* Actually minimize! */
/*
minimize
fsrvforkserver
*/
static void minimize(afl_forkserver_t *fsrv) { static void minimize(afl_forkserver_t *fsrv) {
static u32 alpha_map[256]; static u32 alpha_map[256];
@ -631,7 +682,11 @@ finalize_all:
} }
/* Handle Ctrl-C and the like. */ /* Handle Ctrl-C and the like. */
/*
handle_stop_sig
sig
*/
static void handle_stop_sig(int sig) { static void handle_stop_sig(int sig) {
(void)sig; (void)sig;
@ -641,7 +696,11 @@ static void handle_stop_sig(int sig) {
} }
/* Do basic preparations - persistent fds, filenames, etc. */ /* Do basic preparations - persistent fds, filenames, etc. */
/*
set_up_environment
fsrvforkserverargv
*/
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
u8 *x; u8 *x;
@ -739,7 +798,10 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} }
/* Setup signal handlers, duh. */ /* Setup signal handlers, duh. */
/*
setup_signal_handlers
便Ctrl-C
*/
static void setup_signal_handlers(void) { static void setup_signal_handlers(void) {
struct sigaction sa; struct sigaction sa;
@ -764,7 +826,11 @@ static void setup_signal_handlers(void) {
} }
/* Display usage hints. */ /* Display usage hints. */
/*
usage使
argv0
使
*/
static void usage(u8 *argv0) { static void usage(u8 *argv0) {
SAYF( SAYF(
@ -829,188 +895,272 @@ static void usage(u8 *argv0) {
} }
/* Main entry point */ /* Main entry point */
/*
argcargvenvp
退
*/
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
//程序的主入口点,接收命令行参数和环境变量
s32 opt; s32 opt;
//用于存储getopt函数返回的当前选项字符。
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0, u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
del_limit_given = 0; del_limit_given = 0;
//定义了一些标志变量用于记录是否已经设置了内存限制、超时时间、unicorn模式、wine模式和删除长度限制。
char **use_argv; char **use_argv;
//用于存储处理后的参数列表,可能会根据模式不同而进行修改。
char **argv = argv_cpy_dup(argc, argv_orig); char **argv = argv_cpy_dup(argc, argv_orig);
//复制命令行参数,以便在解析选项时修改参数列表。
afl_forkserver_t fsrv_var = {0}; afl_forkserver_t fsrv_var = {0};
//初始化一个afl_forkserver_t类型的变量用于管理forkserver。
if (getenv("AFL_DEBUG")) { debug = 1; } if (getenv("AFL_DEBUG")) { debug = 1; }
fsrv = &fsrv_var; fsrv = &fsrv_var;
afl_fsrv_init(fsrv); afl_fsrv_init(fsrv);
map_size = get_map_size(); map_size = get_map_size();
fsrv->map_size = map_size; fsrv->map_size = map_size;
//设置forkserver的共享内存区域大小。
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
//尝试访问文档路径如果不存在则使用默认的“docs”路径。
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
//打印程序的欢迎信息和版本号。
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) { while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
//循环处理命令行参数getopt会解析短选项和长选项。
switch (opt) { switch (opt) {
//根据getopt返回的选项字符执行相应的操作。
case 'i': case 'i':
//如果选项是'i',表示输入文件。
if (in_file) { FATAL("Multiple -i options not supported"); } if (in_file) { FATAL("Multiple -i options not supported"); }
//检查是否已经设置了输入文件,如果设置了多次,则报错。
in_file = optarg; in_file = optarg;
//将输入文件的路径设置到in_file变量。
break; break;
case 'o': case 'o':
//如果选项是'o',表示输出文件。
if (output_file) { FATAL("Multiple -o options not supported"); } if (output_file) { FATAL("Multiple -o options not supported"); }
//检查是否已经设置了输出文件,如果设置了多次,则报错。
output_file = optarg; output_file = optarg;
//将输出文件的路径设置到output_file变量。
break; break;
case 'f': case 'f':
//如果选项是'f',表示被测试程序读取的输入文件(标准输入)。
if (out_file) { FATAL("Multiple -f options not supported"); } if (out_file) { FATAL("Multiple -f options not supported"); }
//检查是否已经设置了输入文件,如果设置了多次,则报错。
fsrv->use_stdin = 0; fsrv->use_stdin = 0;
//设置标志,表示不使用标准输入。
out_file = ck_strdup(optarg); out_file = ck_strdup(optarg);
//复制输入文件的路径到out_file变量。
break; break;
case 'e': case 'e':
//如果选项是'e',表示仅考虑边缘覆盖,忽略命中次数。
if (edges_only) { FATAL("Multiple -e options not supported"); } if (edges_only) { FATAL("Multiple -e options not supported"); }
//检查是否已经设置了仅考虑边缘覆盖,如果设置了多次,则报错。
if (hang_mode) { if (hang_mode) {
//检查是否已经设置了挂起模式,如果同时设置了仅考虑边缘覆盖和挂起模式,则报错。
FATAL("Edges only and hang mode are mutually exclusive."); FATAL("Edges only and hang mode are mutually exclusive.");
//报错,因为仅考虑边缘覆盖和挂起模式不能同时设置。
} }
edges_only = 1; edges_only = 1;
//设置标志,表示仅考虑边缘覆盖。
break; break;
case 'x': case 'x':
//如果选项是'x',表示将非零退出代码视为崩溃。
if (exit_crash) { FATAL("Multiple -x options not supported"); } if (exit_crash) { FATAL("Multiple -x options not supported"); }
//检查是否已经设置了将非零退出代码视为崩溃,如果设置了多次,则报错。
exit_crash = 1; exit_crash = 1;
//设置标志,表示将非零退出代码视为崩溃。
break; break;
case 'm': { case 'm': {
//如果选项是'm',表示设置子进程的内存限制。
//使用花括号创建一个新的作用域,用于存储局部变量。
u8 suffix = 'M'; u8 suffix = 'M';
//定义一个变量suffix默认值为'M',表示内存单位是兆字节。
if (mem_limit_given) { FATAL("Multiple -m options not supported"); } if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
//检查是否已经设置了内存限制,如果设置了多次,则报错。
mem_limit_given = 1; mem_limit_given = 1;
//设置标志,表示已经设置了内存限制。
if (!optarg) { FATAL("Wrong usage of -m"); } if (!optarg) { FATAL("Wrong usage of -m"); }
//检查是否提供了内存限制的参数,如果没有提供,则报错。
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
//检查参数是否是“none”表示不设置内存限制。
fsrv->mem_limit = 0; fsrv->mem_limit = 0;
//设置内存限制为0。
break; break;
//跳出内存限制设置。
} }
//结束内存限制设置的条件判断。
if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
optarg[0] == '-') { optarg[0] == '-') {
//尝试解析内存限制的参数,如果解析失败或参数以负号开头,则报错。
FATAL("Bad syntax used for -m"); FATAL("Bad syntax used for -m");
//报错,因为内存限制的参数语法不正确。
} }
//结束内存限制设置的条件判断。
switch (suffix) { switch (suffix) {
//根据解析出的后缀,转换内存限制的单位。
case 'T': case 'T':
fsrv->mem_limit *= 1024 * 1024; fsrv->mem_limit *= 1024 * 1024;
break; break;
//如果后缀是'T',表示内存限制的单位是太字节,转换为兆字节。
case 'G': case 'G':
fsrv->mem_limit *= 1024; fsrv->mem_limit *= 1024;
break; break;
//如果后缀是'G',表示内存限制的单位是吉字节,转换为兆字节。
case 'k': case 'k':
fsrv->mem_limit /= 1024; fsrv->mem_limit /= 1024;
break; break;
//如果后缀是'k',表示内存限制的单位是千字节,转换为兆字节。
case 'M': case 'M':
break; break;
//如果后缀是'M',表示内存限制的单位是兆字节,不需要转换。
default: default:
FATAL("Unsupported suffix or bad syntax for -m"); FATAL("Unsupported suffix or bad syntax for -m");
//如果后缀不支持或语法错误,则报错。
} }
//结束单位转换的switch语句。
if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); } if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
//检查内存限制是否过低如果低于5兆字节则报错。
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) { if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
//检查在32位系统上内存限制是否过高如果超过2000兆字节则报错。
FATAL("Value of -m out of range on 32-bit systems"); FATAL("Value of -m out of range on 32-bit systems");
//报错因为32位系统上内存限制过高。
} }
//结束内存限制设置。
} }
//结束内存限制设置的局部作用域。
break; break;
//结束'm'选项的处理。
case 't': case 't':
//如果选项是't',表示设置每次运行的超时时间。
if (timeout_given) { FATAL("Multiple -t options not supported"); } if (timeout_given) { FATAL("Multiple -t options not supported"); }
//检查是否已经设置了超时时间,如果设置了多次,则报错。
timeout_given = 1; timeout_given = 1;
//设置标志,表示已经设置了超时时间。
if (!optarg) { FATAL("Wrong usage of -t"); } if (!optarg) { FATAL("Wrong usage of -t"); }
//检查是否提供了超时时间的参数,如果没有提供,则报错。
fsrv->exec_tmout = atoi(optarg); fsrv->exec_tmout = atoi(optarg);
//将超时时间的参数转换为整数并设置到fsrv->exec_tmout。
if (fsrv->exec_tmout < 10 || optarg[0] == '-') { if (fsrv->exec_tmout < 10 || optarg[0] == '-') {
//检查超时时间是否过低或参数以负号开头,如果是,则报错。
FATAL("Dangerously low value of -t"); FATAL("Dangerously low value of -t");
//报错,因为超时时间过低。
} }
//结束超时时间设置的条件判断。
break; break;
//结束't'选项的处理。
case 'A': /* CoreSight mode */ case 'A': /* CoreSight mode */
//如果选项是'A'表示使用ARM CoreSight模式。
#if !defined(__aarch64__) || !defined(__linux__) #if !defined(__aarch64__) || !defined(__linux__)
FATAL("-A option is not supported on this platform"); FATAL("-A option is not supported on this platform");
#endif #endif
//检查是否在支持的平台上,如果不是,则报错。
if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); } if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
//检查是否已经设置了CoreSight模式如果设置了多次则报错。
fsrv->cs_mode = 1; fsrv->cs_mode = 1;
//设置标志表示使用CoreSight模式。
break; break;
//结束'A'选项的处理。
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
//如果选项是'O'表示使用FRIDA模式。
if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); } if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
//检查是否已经设置了FRIDA模式如果设置了多次则报错。
fsrv->frida_mode = 1; fsrv->frida_mode = 1;
//设置标志表示使用FRIDA模式。
setenv("AFL_FRIDA_INST_SEED", "1", 1); setenv("AFL_FRIDA_INST_SEED", "1", 1);
//设置环境变量用于FRIDA模式。
break; break;
//结束'O'选项的处理。
case 'Q': case 'Q':
//如果选项是'Q'表示使用QEMU模式。
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
//检查是否已经设置了QEMU模式如果设置了多次则报错。
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; } if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
//如果未设置内存限制则使用QEMU模式的默认内存限制。
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
//设置标志表示使用QEMU模式。
break; break;
//结束'Q'选项的处理。
case 'U': case 'U':
//如果选项是'U'表示使用Unicorn模式。
if (unicorn_mode) { FATAL("Multiple -Q options not supported"); } if (unicorn_mode) { FATAL("Multiple -Q options not supported"); }
//检查是否已经设置了Unicorn模式如果设置了多次则报错。
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; } if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
//如果未设置内存限制则使用Unicorn模式的默认内存限制。
unicorn_mode = 1; unicorn_mode = 1;
//设置标志表示使用Unicorn模式。
break; break;
//结束'U'选项的处理。
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
//如果选项是'W'表示使用Wine+QEMU模式。
if (use_wine) { FATAL("Multiple -W options not supported"); } if (use_wine) { FATAL("Multiple -W options not supported"); }
//检查是否已经设置了Wine+QEMU模式如果设置了多次则报错。
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
//设置标志表示使用QEMU模式。
use_wine = 1; use_wine = 1;
//设置标志表示使用Wine。
if (!mem_limit_given) { fsrv->mem_limit = 0; } if (!mem_limit_given) { fsrv->mem_limit = 0; }
//如果未设置内存限制则设置为0。
break; break;
//结束'W'选项的处理。
case 'Y': // fallthough case 'Y': // fallthough
#ifdef __linux__ #ifdef __linux__
case 'X': /* NYX mode */ case 'X': /* NYX mode */
//
if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); } if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
@ -1021,6 +1171,7 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
#else #else
case 'X': case 'X':
//如果选项是'X'表示使用Nyx模式。
FATAL("Nyx mode is only availabe on linux..."); FATAL("Nyx mode is only availabe on linux...");
break; break;
#endif #endif

File diff suppressed because it is too large Load Diff

Binary file not shown.
Loading…
Cancel
Save