分析一下插桩代码。 有源码根据gcc提供的信息就可以插桩,无源码就需要了dynamo。。
这个AFL_USE_ASAN afl的回显就是用的asan,asan的话,栈是和gs 差不多,然后有函数调用监控,还有危险函数的hook。并且会重写堆的数据结构。
然后 重点函数就是add_instrumentation, 他有一个while 循环每行的读汇编代码,
如果是跳转,那么就直接插桩,
这里是在合适的地方插桩,比如函数头。
来看一下经过gcc编译插桩后的结果
然后具体看一下 afl_maybe_log
如果没有保存共享空间,那么就是第一次运行 afl_maybe_log 那么这个程序就是 fork server
获取共享内存并且映射到自己的进程内存空间
0xc6就是读fd 0xc7 就是写fd 先写到0xc7 通知server 已经初始化完毕。,然后读取0xc6 告知可以运行targer 就当成了server 对target 就 一直fork 然后等待子进程 运行结束,然后将子进程的状态传给 fuzz 程序。(0xc6(控制队列)和0xc7(状态队列)与fuzzer进程通信)
子程序就 关闭fd
然后进行了共享内存的读写
这个进行读写也是挺有意思的 _afl_prev_loc 这个a2就是传入的参数,他这个是代表的程序块的id 这个值是随机的
prelocation 代表的是上一个id/2
这样做的原因是 假设target中存在A->A
和B->B
这样两个跳转,如果不右移,那么这两个分支对应的异或后的key都是0,从而无法区分;另一个例子是A->B
和B->A
,如果不右移,这两个分支对应的异或后的key也是相同的。为了防止这样就移位了。