diff --git a/AFL源码分析_林睿健.docx b/202212723005_林睿健.docx similarity index 100% rename from AFL源码分析_林睿健.docx rename to 202212723005_林睿健.docx diff --git a/src/AFLplusplus-stable/src/afl-fuzz.c b/src/AFLplusplus-stable/src/afl-fuzz.c index 7a94003..e3f6ad9 100644 --- a/src/AFLplusplus-stable/src/afl-fuzz.c +++ b/src/AFLplusplus-stable/src/afl-fuzz.c @@ -807,6 +807,16 @@ int main(int argc, char **argv_orig, char **envp) { afl->out_dir = optarg; break; + /* + 1.首先检查sync_id是否已被设置,防止多次设置-M/-S选项。 + 2.使用ck_strdup函数将传入的实例名称存入特定结构的chunk中,并将此chunk的地址写入sync_id。 + 3.检查Master实例名中是否存在:若存在,则表示这里是使用了并行确定性检查的实验性功能,那么使用sscanf获取当前的Master实例序号与Master实例最大序号,做如下检查: + 任意一项不通过则抛出致命错误"Bogus master ID passed to -M", + 随后程序退出 + a.当前的Master实例序号与Master实例最大序号均不应为空 + b.当前的Master实例序号应小于Master实例最大序号 + c.Master实例最大序号应不超过1000000 + 4.将force_deterministic标志位置位。*/ case 'M': { /* main sync ID */ u8 *c; diff --git a/src/AFLplusplus-stable/src/afl-tmin.c b/src/AFLplusplus-stable/src/afl-tmin.c index 23e0ff1..b4d4e07 100644 --- a/src/AFLplusplus-stable/src/afl-tmin.c +++ b/src/AFLplusplus-stable/src/afl-tmin.c @@ -97,6 +97,10 @@ static sharedmem_t *shm_fuzz; /* Classify tuple counts. This is a slow & naive version, but good enough here. */ +/* + 静态数组count_class_lookup,用于分类统计结果。 + 根据不同的输入值范围,将其映射到对应的分类编号。 +*/ static const u8 count_class_lookup[256] = { [0] = 0, @@ -111,6 +115,10 @@ static const u8 count_class_lookup[256] = { }; +/* + 函数kill_child用于杀死子进程。 + 如果子进程的PID大于0,则向其发送终止信号。 +*/ static void kill_child() { if (fsrv->child_pid > 0) { @@ -122,6 +130,11 @@ static void kill_child() { } +/* + 函数deinit_shmem用于反初始化共享内存。 + 参数fsrv是forkserver结构体,shm_fuzz是共享内存结构体。 + 该函数会释放共享内存资源,并设置相关指针为NULL。 +*/ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv, sharedmem_t *shm_fuzz) { @@ -135,7 +148,11 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv, } /* Apply mask to classified bitmap (if set). */ - +/* + 函数apply_mask用于对分类位图应用掩码(如果设置了掩码)。 + 参数mem是内存地址,mask是掩码地址。 + 如果掩码不为NULL,则对每个掩码位进行按位取反操作。 +*/ static void apply_mask(u32 *mem, u32 *mask) { u32 i = (map_size >> 2); @@ -152,6 +169,12 @@ static void apply_mask(u32 *mem, u32 *mask) { } +/* + 函数classify_counts用于对计数结果进行分类。 + 参数fsrv是forkserver结构体。 + 如果设置了edges_only,则将所有非零计数结果归为一类; + 否则,使用count_class_lookup数组对计数结果进行分类。 +*/ static void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; @@ -180,7 +203,11 @@ static void classify_counts(afl_forkserver_t *fsrv) { } /* See if any bytes are set in the bitmap. */ - +/* + 内联函数anything_set用于检查位图中是否有任何设置的字节。 + 参数fsrv是forkserver结构体。 + 如果发现任何非零字节,则返回1。 +*/ static inline u8 anything_set(afl_forkserver_t *fsrv) { u32 *ptr = (u32 *)fsrv->trace_bits; @@ -196,6 +223,11 @@ static inline u8 anything_set(afl_forkserver_t *fsrv) { } +/* + 函数at_exit_handler用于处理退出时的清理工作。 + 如果设置了remove_shm,则会反初始化共享内存; + 如果设置了remove_out_file,则会删除输出文件。 +*/ static void at_exit_handler(void) { if (remove_shm) { @@ -211,7 +243,11 @@ static void at_exit_handler(void) { } /* Read initial file. */ - +/* + 函数read_initial_file用于读取初始文件。 + 参数in_file是输入文件的路径。 + 该函数会打开文件,检查文件大小,并将其内容读入内存。 +*/ static void read_initial_file(void) { struct stat st; @@ -239,7 +275,11 @@ static void read_initial_file(void) { } /* Write output file. */ - +/* + 函数write_to_file用于将数据写入文件。 + 参数path是文件路径,mem是内存数据,len是数据长度。 + 该函数会尝试删除已存在的文件,然后创建新文件并写入数据。 +*/ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { s32 ret; @@ -260,7 +300,11 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { /* Execute target application. Returns 0 if the changes are a dud, or 1 if they should be kept. */ - +/* + 函数tmin_run_target用于执行目标程序并检查结果。 + 参数fsrv是forkserver结构体,mem是要传递给目标程序的数据,len是数据长度,first_run表示是否是第一次运行。 + 该函数会将数据写入测试用例,运行目标程序,并根据结果决定是否保留这些变化。 +*/ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, u8 first_run) { @@ -280,7 +324,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 */ - + /* 如果处于挂起模式,总是丢弃超时的输入 */ if (hang_mode) { switch (ret) { @@ -300,7 +344,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, classify_counts(fsrv); apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap); - + /* 根据当前模式处理崩溃输入 */ if (ret == FSRV_RUN_TMOUT) { missed_hangs++; @@ -326,7 +370,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, } } else { - + /* 适当处理非崩溃输入 */ /* Handle non-crashing inputs appropriately. */ if (crash_mode) { @@ -352,7 +396,11 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len, } /* Actually minimize! */ - +/* + 函数minimize是测试用例最小化的核心函数。 + 参数fsrv是forkserver结构体。 + 该函数通过不同的阶段(块规范化、块删除、字母表最小化和字符最小化)来最小化测试用例。 +*/ static void minimize(afl_forkserver_t *fsrv) { static u32 alpha_map[256]; @@ -631,7 +679,11 @@ finalize_all: } /* Handle Ctrl-C and the like. */ - +/* + 函数handle_stop_sig用于处理停止信号。 + 参数sig是信号编号。 + 该函数设置一个全局标志以指示程序应该尽快停止。 +*/ static void handle_stop_sig(int sig) { (void)sig; @@ -641,7 +693,11 @@ static void handle_stop_sig(int sig) { } /* Do basic preparations - persistent fds, filenames, etc. */ - +/* + 函数set_up_environment用于设置环境。 + 参数fsrv是forkserver结构体,argv是参数列表。 + 该函数会设置一些环境变量和文件描述符,为执行目标程序做准备。 +*/ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { u8 *x; @@ -739,7 +795,10 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { } /* Setup signal handlers, duh. */ - +/* + 函数setup_signal_handlers用于设置信号处理程序。 + 该函数会为程序设置一些信号处理程序,以便正确处理如Ctrl-C等信号。 +*/ static void setup_signal_handlers(void) { struct sigaction sa; @@ -764,7 +823,11 @@ static void setup_signal_handlers(void) { } /* Display usage hints. */ - +/* + 函数usage用于显示程序的使用帮助。 + 参数argv0是程序的名称。 + 该函数会打印出程序的使用方法和选项。 +*/ static void usage(u8 *argv0) { SAYF( @@ -829,7 +892,11 @@ static void usage(u8 *argv0) { } /* Main entry point */ - +/* + 程序的主入口点。 + 参数argc是参数个数,argv是参数列表,envp是环境变量列表。 + 该函数会解析命令行参数,设置环境,执行测试用例最小化,并处理退出清理。 +*/ int main(int argc, char **argv_orig, char **envp) { s32 opt;