因为afl-fuzz.c源码太多了,所以我只挑我比较感兴趣的部分来分析吧
detect_file_args
这个函数是将命令参数中的@@替换为真正的文件路径
1 | EXP_ST void detect_file_args(char** argv) { |
首先用getcwd拿到当前路径
然后遍历argv,判断各个参数是否含有@@
有的话,首先判断有没有定义一个文件名,如果没有的话,就使用.cur_input
之后使用alloc_printf来生成一个新的字符串,替换原来的
setup_stdio_file
假如在detect_file_args没有找到@@,就会跳到这里,设置好stdio_file
1 | EXP_ST void setup_stdio_file(void) { |
使用的还是 .cur_input
perform_dry_run
这个函数是测试输入的样例
1 | while (q) { |
首先是一个循环,遍历整个输入样例的队列
然后先是打开文件,分配一块内存,将文件内容读入内存
然后调用calibrate_case进行测试
之后对测试的结果进行判断,有FAULT_NONE,FAULT_TMOUT,FAULT_CRASH等,这里就不详细说了
calibrate_case
首先是一大堆设置参数什么的,这里就不详细说了
1 | if (dumb_mode != 1 && !no_forkserver && !forksrv_pid) |
这里是判断forkserver是否启动了,没启动就将其启动
再跳过一部分不是很重要的代码
1 | write_to_testcase(use_mem, q->len); |
这里是将testcase写到文件中去,感觉这里对磁盘的性能要求挺大的吧…….读小文件,写小文件….这里可以作为一个优化点,使用内存磁盘什么的,分一块不是很大的就够用了
1 | fault = run_target(argv, use_tmout); |
这里就是真正的运行程序,里面的逻辑其实在分析afl-as.h的时候已经讲到了
其中有一个小细节就是,假如没有@@,就会将.cur_input的fd dup2到0上
1 | cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); |
之后就是计算trace_bits的checksum,这里trace_bits就是共享内存
下面就是一些对测试样例性能的分析,把这个作为基准,详细的就不多说了
cull_queue
这是一个用来设置favored entry的函数
1 | struct queue_entry* q; |
首先是初始化temp_v(previously-unseen bytes)
1 | while (q) { |
之后将queue_entry中的所有favored设为0
1 | for (i = 0; i < MAP_SIZE; i++) |
这里就是判断有没有没被temp_v所命中的bitmap,如果有,并且在top_rated中,就将其设为favored