afl fuzzer 源代码阅读

(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 */
View Code

猜你喜欢

转载自www.cnblogs.com/jg01/p/9772700.html