(1) 首先从main() 函数开说吧
1 /* Main entry point */ 2 3 int main(int argc, char** argv) { 4 5 s32 opt; 6 u64 prev_queued = 0; 7 u32 sync_interval_cnt = 0, seek_to; 8 u8 *extras_dir = 0; 9 u8 mem_limit_given = 0; 10 u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE"); 11 char** use_argv; 12 13 struct timeval tv; 14 struct timezone tz; 15 16 SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by <[email protected]>\n"); 17 18 doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; 19 20 gettimeofday(&tv, &tz); 21 srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); 22 23 while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q")) > 0) 24 25 switch (opt) { 26 27 case 'i': /* input dir */ 28 29 if (in_dir) FATAL("Multiple -i options not supported"); 30 in_dir = optarg; 31 32 if (!strcmp(in_dir, "-")) in_place_resume = 1; 33 34 break; 35 36 case 'o': /* output dir */ 37 38 if (out_dir) FATAL("Multiple -o options not supported"); 39 out_dir = optarg; 40 break; 41 42 case 'M': { /* master sync ID */ 43 44 u8* c; 45 46 if (sync_id) FATAL("Multiple -S or -M options not supported"); 47 sync_id = ck_strdup(optarg); 48 49 if ((c = strchr(sync_id, ':'))) { 50 51 *c = 0; 52 53 if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 || 54 !master_id || !master_max || master_id > master_max || 55 master_max > 1000000) FATAL("Bogus master ID passed to -M"); 56 57 } 58 59 force_deterministic = 1; 60 61 } 62 63 break; 64 65 case 'S': 66 67 if (sync_id) FATAL("Multiple -S or -M options not supported"); 68 sync_id = ck_strdup(optarg); 69 break; 70 71 case 'f': /* target file */ 72 73 if (out_file) FATAL("Multiple -f options not supported"); 74 out_file = optarg; 75 break; 76 77 case 'x': /* dictionary */ 78 79 if (extras_dir) FATAL("Multiple -x options not supported"); 80 extras_dir = optarg; 81 break; 82 83 case 't': { /* timeout */ 84 85 u8 suffix = 0; 86 87 if (timeout_given) FATAL("Multiple -t options not supported"); 88 89 if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 || 90 optarg[0] == '-') FATAL("Bad syntax used for -t"); 91 92 if (exec_tmout < 5) FATAL("Dangerously low value of -t"); 93 94 if (suffix == '+') timeout_given = 2; else timeout_given = 1; 95 96 break; 97 98 } 99 100 case 'm': { /* mem limit */ 101 102 u8 suffix = 'M'; 103 104 if (mem_limit_given) FATAL("Multiple -m options not supported"); 105 mem_limit_given = 1; 106 107 if (!strcmp(optarg, "none")) { 108 109 mem_limit = 0; 110 break; 111 112 } 113 114 if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || 115 optarg[0] == '-') FATAL("Bad syntax used for -m"); 116 117 switch (suffix) { 118 119 case 'T': mem_limit *= 1024 * 1024; break; 120 case 'G': mem_limit *= 1024; break; 121 case 'k': mem_limit /= 1024; break; 122 case 'M': break; 123 124 default: FATAL("Unsupported suffix or bad syntax for -m"); 125 126 } 127 128 if (mem_limit < 5) FATAL("Dangerously low value of -m"); 129 130 if (sizeof(rlim_t) == 4 && mem_limit > 2000) 131 FATAL("Value of -m out of range on 32-bit systems"); 132 133 } 134 135 break; 136 137 case 'd': /* skip deterministic */ 138 139 if (skip_deterministic) FATAL("Multiple -d options not supported"); 140 skip_deterministic = 1; 141 use_splicing = 1; 142 break; 143 144 case 'B': /* load bitmap */ 145 146 /* This is a secret undocumented option! It is useful if you find 147 an interesting test case during a normal fuzzing process, and want 148 to mutate it without rediscovering any of the test cases already 149 found during an earlier run. 150 151 To use this mode, you need to point -B to the fuzz_bitmap produced 152 by an earlier run for the exact same binary... and that's it. 153 154 I only used this once or twice to get variants of a particular 155 file, so I'm not making this an official setting. */ 156 157 if (in_bitmap) FATAL("Multiple -B options not supported"); 158 159 in_bitmap = optarg; 160 read_bitmap(in_bitmap); 161 break; 162 163 case 'C': /* crash mode */ 164 165 if (crash_mode) FATAL("Multiple -C options not supported"); 166 crash_mode = FAULT_CRASH; 167 break; 168 169 case 'n': /* dumb mode */ 170 171 if (dumb_mode) FATAL("Multiple -n options not supported"); 172 if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1; 173 174 break; 175 176 case 'T': /* banner */ 177 178 if (use_banner) FATAL("Multiple -T options not supported"); 179 use_banner = optarg; 180 break; 181 182 case 'Q': /* QEMU mode */ 183 184 if (qemu_mode) FATAL("Multiple -Q options not supported"); 185 qemu_mode = 1; 186 187 if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; 188 189 break; 190 191 default: 192 193 usage(argv[0]); 194 195 } 196 197 198 if (optind == argc || !in_dir || !out_dir) usage(argv[0]); 199 200 setup_signal_handlers(); 201 check_asan_opts(); 202 203 if (sync_id) fix_up_sync(); 204 205 if (!strcmp(in_dir, out_dir)) 206 FATAL("Input and output directories can't be the same"); 207 208 209 //fwrite(dumb_mode,sizeof(dumb_mode),sizeof(dumb_mode),ptest); 210 211 if (dumb_mode) { 212 213 if (crash_mode) FATAL("-C and -n are mutually exclusive"); 214 if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); 215 216 } 217 218 if (getenv("AFL_NO_FORKSRV")) no_forkserver = 1; 219 if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1; 220 if (getenv("AFL_NO_ARITH")) no_arith = 1; 221 if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1; 222 if (getenv("AFL_FAST_CAL")) fast_cal = 1; 223 224 if (getenv("AFL_HANG_TMOUT")) { 225 hang_tmout = atoi(getenv("AFL_HANG_TMOUT")); 226 if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); 227 } 228 229 if (dumb_mode == 2 && no_forkserver) 230 FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); 231 232 if (getenv("AFL_PRELOAD")) { 233 setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); 234 setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); 235 } 236 237 if (getenv("AFL_LD_PRELOAD")) 238 FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); 239 240 save_cmdline(argc, argv); 241 242 fix_up_banner(argv[optind]); 243 244 check_if_tty(); 245 246 get_core_count(); 247 248 #ifdef HAVE_AFFINITY 249 bind_to_free_cpu(); 250 #endif /* HAVE_AFFINITY */ 251 252 check_crash_handling(); 253 check_cpu_governor(); 254 255 setup_post(); 256 setup_shm(); 257 init_count_class16(); 258 259 setup_dirs_fds(); 260 read_testcases(); 261 load_auto(); 262 263 pivot_inputs(); 264 265 if (extras_dir) load_extras(extras_dir); 266 267 if (!timeout_given) find_timeout(); 268 269 detect_file_args(argv + optind + 1); 270 271 if (!out_file) setup_stdio_file(); 272 273 check_binary(argv[optind]); 274 275 start_time = get_cur_time(); 276 277 if (qemu_mode) 278 use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); 279 else 280 use_argv = argv + optind; 281 282 perform_dry_run(use_argv); 283 284 cull_queue(); 285 286 show_init_stats(); 287 288 seek_to = find_start_position(); 289 290 write_stats_file(0, 0, 0); 291 save_auto(); 292 293 if (stop_soon) goto stop_fuzzing; 294 295 /* Woop woop woop */ 296 297 if (!not_on_tty) { 298 sleep(4); 299 start_time += 4000; 300 if (stop_soon) goto stop_fuzzing; 301 } 302 303 while (1) { 304 305 u8 skipped_fuzz; 306 307 cull_queue(); 308 309 if (!queue_cur) { 310 311 queue_cycle++; 312 current_entry = 0; 313 cur_skipped_paths = 0; 314 queue_cur = queue; 315 316 while (seek_to) { 317 current_entry++; 318 seek_to--; 319 queue_cur = queue_cur->next; 320 } 321 322 show_stats(); 323 324 if (not_on_tty) { 325 ACTF("Entering queue cycle %llu.", queue_cycle); 326 fflush(stdout); 327 } 328 329 /* If we had a full queue cycle with no new finds, try 330 recombination strategies next. */ 331 332 if (queued_paths == prev_queued) { 333 334 if (use_splicing) cycles_wo_finds++; else use_splicing = 1; 335 336 } else cycles_wo_finds = 0; 337 338 prev_queued = queued_paths; 339 340 if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) 341 sync_fuzzers(use_argv); 342 343 } 344 345 skipped_fuzz = fuzz_one(use_argv); 346 347 if (!stop_soon && sync_id && !skipped_fuzz) { 348 349 if (!(sync_interval_cnt++ % SYNC_INTERVAL)) 350 sync_fuzzers(use_argv); 351 352 } 353 354 if (!stop_soon && exit_1) stop_soon = 2; 355 356 if (stop_soon) break; 357 358 queue_cur = queue_cur->next; 359 current_entry++; 360 361 } 362 363 if (queue_cur) show_stats(); 364 365 write_bitmap(); 366 write_stats_file(0, 0, 0); 367 save_auto(); 368 369 stop_fuzzing: 370 371 SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, 372 stop_soon == 2 ? "programmatically" : "by user"); 373 374 /* Running for more than 30 minutes but still doing first cycle? */ 375 376 if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { 377 378 SAYF("\n" cYEL "[!] " cRST 379 "Stopped during the first cycle, results may be incomplete.\n" 380 " (For info on resuming, see %s/README.)\n", doc_path); 381 382 } 383 384 fclose(plot_file); 385 destroy_queue(); 386 destroy_extras(); 387 ck_free(target_path); 388 ck_free(sync_id); 389 390 alloc_report(); 391 392 fclose(ptest); 393 394 OKF("We're done here. Have a nice day!\n"); 395 396 exit(0); 397 398 } 399 400 #endif /* !AFL_LIB */