/* Handle stop signal (Ctrl-C, etc). *//*手动停止信号*/staticvoidhandle_stop_sig(int sig){
stop_soon =1;//设置stop_soon为1if(child_pid >0)kill(child_pid, SIGKILL);//如果child_pid存在,向其发送SIGKILL终止信号,从而被系统杀死if(forksrv_pid >0)kill(forksrv_pid, SIGKILL);//如果forksrv_pid存在,向其发送SIGKILL终止信号}/* Handle skip request (SIGUSR1). *///处理跳过请求staticvoidhandle_skipreq(int sig){
skip_requested =1;//设置skip_requested=1}/* Handle timeout (SIGALRM). *///处理超时的情况staticvoidhandle_timeout(int sig){if(child_pid >0){//如果child_pid>0,则设置child_timed_out为1,并kill掉child_pid
child_timed_out =1;kill(child_pid, SIGKILL);}elseif(child_pid ==-1&& forksrv_pid >0){//如果child_pid==-1,且forksrv_pid>0,则设置child_timed_out为1,并kill掉forksrv_pid
child_timed_out =1;kill(forksrv_pid, SIGKILL);}}/* Handle screen resize (SIGWINCH). *///处理窗口大小的变化信号staticvoidhandle_resize(int sig){
clear_screen =1;//设置clear_screen=1}* Set up signal handlers. More complicated that needs to be, because libc on
Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call
siginterrupt(), and does other unnecessary things.*//*设置信号处理程序。这需要更加复杂,因为libcSolaris不会恢复中断读取(),在调用时设置SA_RESETHAND
siginterrupt(),并执行其他不必要的操作*/
EXP_ST voidsetup_signal_handlers(void){//注册必要的信号处理函数structsigaction sa;
sa.sa_handler =NULL;//处理函数指针,相当于signal函数的func参数。
sa.sa_flags = SA_RESTART;//信号处理修改器
sa.sa_sigaction =NULL;//设置sigaction为NULLsigemptyset(&sa.sa_mask);//sa_mask 的值通常是通过使用信号集函数来设置的 初始为空/* Various ways of saying "stop". */
sa.sa_handler = handle_stop_sig;sigaction(SIGHUP,&sa,NULL);sigaction(SIGINT,&sa,NULL);sigaction(SIGTERM,&sa,NULL);/* Exec timeout notifications. */
sa.sa_handler = handle_timeout;sigaction(SIGALRM,&sa,NULL);/* Window resize */
sa.sa_handler = handle_resize;sigaction(SIGWINCH,&sa,NULL);/* SIGUSR1: skip entry */
sa.sa_handler = handle_skipreq;sigaction(SIGUSR1,&sa,NULL);/* Things we don't care about. */
sa.sa_handler = SIG_IGN;sigaction(SIGTSTP,&sa,NULL);sigaction(SIGPIPE,&sa,NULL);}
2.check_asan_opts(检查内存错误)
/* Check ASAN options. */staticvoidcheck_asan_opts(void){
u8* x =getenv("ASAN_OPTIONS");//读取环境变量ASAN_OPTIONSif(x){if(!strstr(x,"abort_on_error=1"))//检查是否设置了abort_on_error=1,如果没有抛异常FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");//不带中止abort_on_error=1-请修复!if(!strstr(x,"symbolize=0"))//检查是否设置了symbolize=0,如果没有抛异常FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");}
x =getenv("MSAN_OPTIONS");//读取环境变量MSAN_OPTIONSif(x){if(!strstr(x,"exit_code="STRINGIFY(MSAN_ERROR)))FATAL("Custom MSAN_OPTIONS set without exit_code="STRINGIFY(MSAN_ERROR)" - please fix!");if(!strstr(x,"symbolize=0"))FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");}}
3.fix_up_sync(检查ID、sync_id是否过长,检查互斥)
/* Validate and fix up out_dir and sync_dir when using -S. *///使用-S时验证并修复out_dir和sync_dir。staticvoidfix_up_sync(void){
u8* x = sync_id;if(dumb_mode)FATAL("-S / -M and -n are mutually exclusive");//-S/-M和-n是互斥的if(skip_deterministic){if(force_deterministic)FATAL("use -S instead of -M -d");elseFATAL("-S already implies -d");}while(*x){if(!isalnum(*x)&&*x !='_'&&*x !='-')FATAL("Non-alphanumeric fuzzer ID specified via -S or -M");//通过-S或-M指定的非字母数字fuzzer ID
x++;}if(strlen(sync_id)>32)//如果sync_id超过32位报错FATAL("Fuzzer ID too long");
x =alloc_printf("%s/%s", out_dir, sync_id);
sync_dir = out_dir;//设置sync_dir的值为out_dir
out_dir = x;//设置out_dir的值为out_dir/sync_idif(!force_deterministic){//如果没有设置force_deterministic
skip_deterministic =1;//设置skip_deterministic为1
use_splicing =1;//设置use_splicing为1}}
4.save_cmdline(将当前输入参数拷贝进buf空间中)
/* Make a copy of the current command line. *//*复制当前命令行*/staticvoidsave_cmdline(u32 argc,char** argv){
u32 len =1, i;
u8* buf;for(i =0; i < argc; i++)
len +=strlen(argv[i])+1;//计算参数长度
buf = orig_cmdline =ck_alloc(len);//给参数分配内存空间for(i =0; i < argc; i++){
u32 l =strlen(argv[i]);//计算长度memcpy(buf, argv[i], l);//将argv[i]中的内容存放至buf空间
buf += l;if(i != argc -1)*(buf++)=' ';}*buf =0;}
5.fix_up_banner(修剪并且创建一个运行横幅)
/* Trim and possibly create a banner for the run. */staticvoidfix_up_banner(u8* name){if(!use_banner){//如果没有设置use_bannerif(sync_id){//如果没有设置use_banner
use_banner = sync_id;//将sync_id赋值给use_banner}else{
u8* trim =strrchr(name,'/');//获取最后一个参数中最后一个“/”后的内容if(!trim)//如果没有获取到
use_banner = name;//将目标文件路径赋值给use_bannerelse
use_banner = trim +1;}}if(strlen(use_banner)>40){//如果use_banner长度超过40,
u8* tmp =ck_alloc(44);//分配44的空间给tmpsprintf(tmp,"%.40s...", use_banner);//取use_banner的前40个字节并在其后面加省略号
use_banner = tmp;//将tmp赋值给use_banner}}
6.check_if_tty(检查是否在tty终端上面运行)
/* Check if we're on TTY. */staticvoidcheck_if_tty(void){structwinsize ws;if(getenv("AFL_NO_UI")){//如果设置了AFL_NO_UI环境变量OKF("Disabling the UI because AFL_NO_UI is set.");//禁用UI
not_on_tty =1;//设置not_on_tty的值设为1return;}if(ioctl(1, TIOCGWINSZ,&ws)){//获取窗口大小if(errno == ENOTTY){//如果报错为ENOTTYOKF("Looks like we're not running on a tty, so I'll be a bit less verbose.");//看起来我们没有在tty上运行,所以我会少一点冗长。
not_on_tty =1;}return;}}
7.get_core_count(计算逻辑CPU核的数量)
/* Count the number of logical CPU cores. */staticvoidget_core_count(void){
u32 cur_runnable =0;
8.check_crash_handling(确保核心转储不会进入程序)
/* Make sure that core dumps don't go to a program. */staticvoidcheck_crash_handling(void){#ifdef__APPLE__/* Yuck! There appears to be no simple C API to query for the state of
loaded daemons on MacOS X, and I'm a bit hesitant to do something
more sophisticated, such as disabling crash reporting via Mach ports,
until I get a box to test the code. So, for now, we check for crash
reporting the awful way. */if(system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'"))return;SAYF("\n" cLRD "[-] " cRST
"Whoops, your system is configured to forward crash notifications to an\n"" external crash reporting utility. This will cause issues due to the\n"" extended delay between the fuzzed binary malfunctioning and this fact\n"" being relayed to the fuzzer via the standard waitpid() API.\n\n"" To avoid having crashes misinterpreted as timeouts, please run the\n"" following commands:\n\n"" SL=/System/Library; PL=com.apple.ReportCrash\n"" launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n"" sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n");if(!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))//如果没有获取环境变量AFL_I_DONT_CARE_ABOUT_MISSING_CRASHESFATAL("Crash reporter detected");#else/* This is Linux specific, but I don't think there's anything equivalent on
*BSD, so we can just let it slide for now. */
s32 fd =open("/proc/sys/kernel/core_pattern", O_RDONLY);
u8 fchar;if(fd <0)return;ACTF("Checking core_pattern...");if(read(fd,&fchar,1)==1&& fchar =='|'){SAYF("\n" cLRD "[-] " cRST
"Hmm, your system is configured to send core dump notifications to an\n"" external utility. This will cause issues: there will be an extended delay\n"" between stumbling upon a crash and having this information relayed to the\n"" fuzzer via the standard waitpid() API.\n\n"" To avoid having crashes misinterpreted as timeouts, please log in as root\n"" and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n"" echo core >/proc/sys/kernel/core_pattern\n");if(!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))//如果没有获取环境变量AFL_I_DONT_CARE_ABOUT_MISSING_CRASHESFATAL("Pipe at the beginning of 'core_pattern'");//报错}close(fd);#endif/* ^__APPLE__ */}
9.check_cpu_governor(检查CPU管理者)
/* Check CPU governor. */staticvoidcheck_cpu_governor(void){
FILE* f;
u8 tmp[128];
u64 min =0, max =0;if(getenv("AFL_SKIP_CPUFREQ"))//获取环境变量AFL_SKIP_CPUFREQreturn;
f =fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor","r");//打开文件只读if(!f)return;ACTF("Checking CPU scaling governor...");//“正在检查CPU比例调节器…”if(!fgets(tmp,128, f))PFATAL("fgets() failed");fclose(f);if(!strncmp(tmp,"perf",4))return;
f =fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq","r");if(f){if(fscanf(f,"%llu",&min)!=1) min =0;fclose(f);}
f =fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq","r");if(f){if(fscanf(f,"%llu",&max)!=1) max =0;fclose(f);}if(min == max)return;SAYF("\n" cLRD "[-] " cRST
"Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"" between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n"" kernel is imperfect and can miss the short-lived processes spawned by\n"" afl-fuzz. To keep things moving, run these commands as root:\n\n"" cd /sys/devices/system/cpu\n"" echo performance | tee cpu*/cpufreq/scaling_governor\n\n"" You can later go back to the original state by replacing 'performance' with\n"" 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n"" to make afl-fuzz skip this check - but expect some performance drop.\n",
min /1024, max /1024);FATAL("Suboptimal CPU scaling governor");}
10.setup_post(加载后处理器(如果可用))
/* Load postprocessor, if available. */staticvoidsetup_post(void){void* dh;
u8* fn =getenv("AFL_POST_LIBRARY");//获取环境变量AFL_POST_LIBRARY
u32 tlen =6;if(!fn)//如果没有设置AFL_POST_LIBRARY环境变量,直接返回return;ACTF("Loading postprocessor from '%s'...", fn);//输出环境变量AFL_POST_LIBRARY
dh =dlopen(fn, RTLD_NOW);//以RTLD_NOW模式打开AFL_POST_LIBRARY环境变量指向的动态链接库,在返回前解析出所有未定义的符号if(!dh)FATAL("%s",dlerror());
post_handler =dlsym(dh,"afl_postprocess");//post_handler赋值为动态链接库中afl_postprocess()函数地址if(!post_handler)//如果没有获取到afl_postprocess()函数地址,报错FATAL("Symbol 'afl_postprocess' not found.");/* Do a quick test. It's better to segfault now than later =) *//*做一个快速测试。现在做比以后做更好*/post_handler("hello",&tlen);OKF("Postprocessor installed successfully.");}