1 /*
2 american fuzzy lop++ - fuzzer code
3 --------------------------------
4
5 Originally written by Michal Zalewski
6
7 Now maintained by Marc Heuse <mh@mh-sec.de>,
8 Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
9 Andrea Fioraldi <andreafioraldi@gmail.com>
10
11 Copyright 2016, 2017 Google Inc. All rights reserved.
12 Copyright 2019-2020 AFLplusplus Project. All rights reserved.
13
14 Licensed under the Apache License, Version 2.0 (the "License");
15 you may not use this file except in compliance with the License.
16 You may obtain a copy of the License at:
17
18 http://www.apache.org/licenses/LICENSE-2.0
19
20 This is the real deal: the program takes an instrumented binary and
21 attempts a variety of basic fuzzing tricks, paying close attention to
22 how they affect the execution path.
23
24 */
25
26 #include "afl-fuzz.h"
27 #include "cmplog.h"
28 #include <limits.h>
29 #include <stdlib.h>
30 #ifndef USEMMAP
31 #include <sys/mman.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <sys/ipc.h>
35 #include <sys/shm.h>
36 #endif
37
38 #ifdef __APPLE__
39 #include <sys/qos.h>
40 #endif
41
42 #ifdef PROFILING
43 extern u64 time_spent_working;
44 #endif
45
at_exit()46 static void at_exit() {
47
48 s32 i, pid1 = 0, pid2 = 0;
49 char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
50 char *ptr;
51
52 ptr = getenv(CPU_AFFINITY_ENV_VAR);
53 if (ptr && *ptr) unlink(ptr);
54
55 ptr = getenv("__AFL_TARGET_PID1");
56 if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) kill(pid1, SIGTERM);
57
58 ptr = getenv("__AFL_TARGET_PID2");
59 if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) kill(pid2, SIGTERM);
60
61 i = 0;
62 while (list[i] != NULL) {
63
64 ptr = getenv(list[i]);
65 if (ptr && *ptr) {
66
67 #ifdef USEMMAP
68
69 shm_unlink(ptr);
70
71 #else
72
73 shmctl(atoi(ptr), IPC_RMID, NULL);
74
75 #endif
76
77 }
78
79 i++;
80
81 }
82
83 int kill_signal = SIGKILL;
84 /* AFL_KILL_SIGNAL should already be a valid int at this point */
85 if ((ptr = getenv("AFL_KILL_SIGNAL"))) { kill_signal = atoi(ptr); }
86
87 if (pid1 > 0) { kill(pid1, kill_signal); }
88 if (pid2 > 0) { kill(pid2, kill_signal); }
89
90 }
91
92 /* Display usage hints. */
93
usage(u8 * argv0,int more_help)94 static void usage(u8 *argv0, int more_help) {
95
96 SAYF(
97 "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
98
99 "Required parameters:\n"
100 " -i dir - input directory with test cases\n"
101 " -o dir - output directory for fuzzer findings\n\n"
102
103 "Execution control settings:\n"
104 " -p schedule - power schedules compute a seed's performance score:\n"
105 " fast(default), explore, exploit, seek, rare, mmopt, "
106 "coe, lin\n"
107 " quad -- see docs/power_schedules.md\n"
108 " -f file - location read by the fuzzed program (default: stdin "
109 "or @@)\n"
110 " -t msec - timeout for each run (auto-scaled, default %u ms). "
111 "Add a '+'\n"
112 " to auto-calculate the timeout, the value being the "
113 "maximum.\n"
114 " -m megs - memory limit for child process (%u MB, 0 = no limit "
115 "[default])\n"
116 " -O - use binary-only instrumentation (FRIDA mode)\n"
117 " -Q - use binary-only instrumentation (QEMU mode)\n"
118 " -U - use unicorn-based instrumentation (Unicorn mode)\n"
119 " -W - use qemu-based instrumentation with Wine (Wine "
120 "mode)\n\n"
121
122 "Mutator settings:\n"
123 " -D - enable deterministic fuzzing (once per queue entry)\n"
124 " -L minutes - use MOpt(imize) mode and set the time limit for "
125 "entering the\n"
126 " pacemaker mode (minutes of no new paths). 0 = "
127 "immediately,\n"
128 " -1 = immediately and together with normal mutation.\n"
129 " See docs/README.MOpt.md\n"
130 " -c program - enable CmpLog by specifying a binary compiled for "
131 "it.\n"
132 " if using QEMU, just use -c 0.\n"
133 " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
134 " 1=small files, 2=larger files (default), 3=all "
135 "files,\n"
136 " A=arithmetic solving, T=transformational solving.\n\n"
137 "Fuzzing behavior settings:\n"
138 " -Z - sequential queue selection instead of weighted "
139 "random\n"
140 " -N - do not unlink the fuzzing input file (for devices "
141 "etc.)\n"
142 " -n - fuzz without instrumentation (non-instrumented mode)\n"
143 " -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
144 "times)\n\n"
145
146 "Test settings:\n"
147 " -s seed - use a fixed seed for the RNG\n"
148 " -V seconds - fuzz for a specified time then terminate\n"
149 " -E execs - fuzz for an approx. no. of total executions then "
150 "terminate\n"
151 " Note: not precise and can have several more "
152 "executions.\n\n"
153
154 "Other stuff:\n"
155 " -M/-S id - distributed mode (see docs/parallel_fuzzing.md)\n"
156 " -M auto-sets -D, -Z (use -d to disable -D) and no "
157 "trimming\n"
158 " -F path - sync to a foreign fuzzer queue directory (requires "
159 "-M, can\n"
160 " be specified up to %u times)\n"
161 // " -d - skip deterministic fuzzing in -M mode\n"
162 " -T text - text banner to show on the screen\n"
163 " -I command - execute this command/script when a new crash is "
164 "found\n"
165 //" -B bitmap.txt - mutate a specific test case, use the out/fuzz_bitmap
166 //" "file\n"
167 " -C - crash exploration mode (the peruvian rabbit thing)\n"
168 " -b cpu_id - bind the fuzzing process to the specified CPU core "
169 "(0-...)\n"
170 " -e ext - file extension for the fuzz test input file (if "
171 "needed)\n\n",
172 argv0, EXEC_TIMEOUT, MEM_LIMIT, FOREIGN_SYNCS_MAX);
173
174 if (more_help > 1) {
175
176 #if defined USE_COLOR && !defined ALWAYS_COLORED
177 #define DYN_COLOR \
178 "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n"
179 #else
180 #define DYN_COLOR
181 #endif
182
183 #ifdef AFL_PERSISTENT_RECORD
184 #define PERSISTENT_MSG \
185 "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
186 "out/crashes\n"
187 #else
188 #define PERSISTENT_MSG
189 #endif
190
191 SAYF(
192 "Environment variables used:\n"
193 "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
194 "ASAN_OPTIONS: custom settings for ASAN\n"
195 " (must contain abort_on_error=1 and symbolize=0)\n"
196 "MSAN_OPTIONS: custom settings for MSAN\n"
197 " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
198 "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
199 "AFL_BENCH_JUST_ONE: run the target just once\n"
200 "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
201 "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n"
202 "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
203 "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
204 "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
205 "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
206 "AFL_DEBUG: extra debugging output for Python mode trimming\n"
207 "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
208 "AFL_DISABLE_TRIM: disable the trimming of test cases\n"
209 "AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
210 "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
211 "AFL_EXIT_ON_TIME: exit when no new paths are found within the specified time period\n"
212 "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n"
213 "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
214 "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
215 "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
216 "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
217 "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
218 "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
219 "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
220 "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
221 "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
222 " the target was compiled for\n"
223 "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
224 " then they are randomly selected instead all of them being\n"
225 " used. Defaults to 200.\n"
226 "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
227 "AFL_TRY_AFFINITY: try to bind to an unused core, but don't fail if unsuccessful\n"
228 "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
229 "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
230 "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
231 "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
232 "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
233 "AFL_NO_UI: switch status screen off\n"
234
235 DYN_COLOR
236
237 "AFL_PATH: path to AFL support binaries\n"
238 "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
239 "AFL_QUIET: suppress forkserver status messages\n"
240
241 PERSISTENT_MSG
242
243 "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
244 "AFL_TARGET_ENV: pass extra environment variables to target\n"
245 "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
246 "AFL_SKIP_BIN_CHECK: skip afl compatibility checks, also disables auto map size\n"
247 "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
248 //"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
249 "AFL_STATSD: enables StatsD metrics collection\n"
250 "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n"
251 "AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
252 "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
253 " Supported formats are: 'dogstatsd', 'librato',\n"
254 " 'signalfx' and 'influxdb'\n"
255 "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n"
256 "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
257 //"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n"
258 //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n"
259 "\n"
260 );
261
262 } else {
263
264 SAYF(
265 "To view also the supported environment variables of afl-fuzz please "
266 "use \"-hh\".\n\n");
267
268 }
269
270 #ifdef USE_PYTHON
271 SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
272 (char *)PYTHON_VERSION);
273 #else
274 SAYF("Compiled without python module support.\n");
275 #endif
276
277 #ifdef AFL_PERSISTENT_RECORD
278 SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
279 #else
280 SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
281 #endif
282
283 #ifdef USEMMAP
284 SAYF("Compiled with shm_open support.\n");
285 #else
286 SAYF("Compiled with shmat support.\n");
287 #endif
288
289 #ifdef ASAN_BUILD
290 SAYF("Compiled with ASAN_BUILD.\n");
291 #endif
292
293 #ifdef NO_SPLICING
294 SAYF("Compiled with NO_SPLICING.\n");
295 #endif
296
297 #ifdef PROFILING
298 SAYF("Compiled with PROFILING.\n");
299 #endif
300
301 #ifdef INTROSPECTION
302 SAYF("Compiled with INTROSPECTION.\n");
303 #endif
304
305 #ifdef _DEBUG
306 SAYF("Compiled with _DEBUG.\n");
307 #endif
308
309 #ifdef _AFL_DOCUMENT_MUTATIONS
310 SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
311 #endif
312
313 SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
314
315 exit(1);
316 #undef PHYTON_SUPPORT
317
318 }
319
320 #ifndef AFL_LIB
321
stricmp(char const * a,char const * b)322 static int stricmp(char const *a, char const *b) {
323
324 if (!a || !b) { FATAL("Null reference"); }
325
326 for (;; ++a, ++b) {
327
328 int d;
329 d = tolower((int)*a) - tolower((int)*b);
330 if (d != 0 || !*a) { return d; }
331
332 }
333
334 }
335
fasan_check_afl_preload(char * afl_preload)336 static void fasan_check_afl_preload(char *afl_preload) {
337
338 char first_preload[PATH_MAX + 1] = {0};
339 char * separator = strchr(afl_preload, ':');
340 size_t first_preload_len = PATH_MAX;
341 char * basename;
342 char clang_runtime_prefix[] = "libclang_rt.asan-";
343
344 if (separator != NULL && (separator - afl_preload) < PATH_MAX) {
345
346 first_preload_len = separator - afl_preload;
347
348 }
349
350 strncpy(first_preload, afl_preload, first_preload_len);
351
352 basename = strrchr(first_preload, '/');
353 if (basename == NULL) {
354
355 basename = first_preload;
356
357 } else {
358
359 basename = basename + 1;
360
361 }
362
363 if (strncmp(basename, clang_runtime_prefix,
364 sizeof(clang_runtime_prefix) - 1) != 0) {
365
366 FATAL("Address Sanitizer DSO must be the first DSO in AFL_PRELOAD");
367
368 }
369
370 if (access(first_preload, R_OK) != 0) {
371
372 FATAL("Address Sanitizer DSO not found");
373
374 }
375
376 OKF("Found ASAN DSO: %s", first_preload);
377
378 }
379
380 /* Main entry point */
381
main(int argc,char ** argv_orig,char ** envp)382 int main(int argc, char **argv_orig, char **envp) {
383
384 s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;
385 u64 prev_queued = 0;
386 u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0,
387 map_size = get_map_size();
388 u8 *extras_dir[4];
389 u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
390 extras_dir_cnt = 0 /*, have_p = 0*/;
391 char * afl_preload;
392 char * frida_afl_preload = NULL;
393 char **use_argv;
394
395 struct timeval tv;
396 struct timezone tz;
397
398 #if defined USE_COLOR && defined ALWAYS_COLORED
399 if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
400
401 WARNF(
402 "Setting AFL_NO_COLOR has no effect (colors are configured on at "
403 "compile time)");
404
405 }
406
407 #endif
408
409 char **argv = argv_cpy_dup(argc, argv_orig);
410
411 afl_state_t *afl = calloc(1, sizeof(afl_state_t));
412 if (!afl) { FATAL("Could not create afl state"); }
413
414 if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
415
416 afl_state_init(afl, map_size);
417 afl->debug = debug;
418 afl_fsrv_init(&afl->fsrv);
419 if (debug) { afl->fsrv.debug = true; }
420 read_afl_environment(afl, envp);
421 if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
422 exit_1 = !!afl->afl_env.afl_bench_just_one;
423
424 SAYF(cCYA "afl-fuzz" VERSION cRST
425 " based on afl by Michal Zalewski and a large online community\n");
426
427 doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
428
429 gettimeofday(&tv, &tz);
430 rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
431
432 afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
433
434 while ((opt = getopt(
435 argc, argv,
436 "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) {
437
438 switch (opt) {
439
440 case 'Z':
441 afl->old_seed_selection = 1;
442 break;
443
444 case 'I':
445 afl->infoexec = optarg;
446 break;
447
448 case 'b': { /* bind CPU core */
449
450 if (afl->cpu_to_bind != -1) FATAL("Multiple -b options not supported");
451
452 if (sscanf(optarg, "%d", &afl->cpu_to_bind) < 0) {
453
454 FATAL("Bad syntax used for -b");
455
456 }
457
458 break;
459
460 }
461
462 case 'c': {
463
464 afl->shm.cmplog_mode = 1;
465 afl->cmplog_binary = ck_strdup(optarg);
466 break;
467
468 }
469
470 case 's': {
471
472 if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
473 rand_set_seed(afl, strtoul(optarg, 0L, 10));
474 afl->fixed_seed = 1;
475 break;
476
477 }
478
479 case 'p': /* Power schedule */
480
481 if (!stricmp(optarg, "fast")) {
482
483 afl->schedule = FAST;
484
485 } else if (!stricmp(optarg, "coe")) {
486
487 afl->schedule = COE;
488
489 } else if (!stricmp(optarg, "exploit")) {
490
491 afl->schedule = EXPLOIT;
492
493 } else if (!stricmp(optarg, "lin")) {
494
495 afl->schedule = LIN;
496
497 } else if (!stricmp(optarg, "quad")) {
498
499 afl->schedule = QUAD;
500
501 } else if (!stricmp(optarg, "mopt") || !stricmp(optarg, "mmopt")) {
502
503 afl->schedule = MMOPT;
504
505 } else if (!stricmp(optarg, "rare")) {
506
507 afl->schedule = RARE;
508
509 } else if (!stricmp(optarg, "explore") || !stricmp(optarg, "afl") ||
510
511 !stricmp(optarg, "default") ||
512
513 !stricmp(optarg, "normal")) {
514
515 afl->schedule = EXPLORE;
516
517 } else if (!stricmp(optarg, "seek")) {
518
519 afl->schedule = SEEK;
520
521 } else {
522
523 FATAL("Unknown -p power schedule");
524
525 }
526
527 // have_p = 1;
528
529 break;
530
531 case 'e':
532
533 if (afl->file_extension) { FATAL("Multiple -e options not supported"); }
534
535 afl->file_extension = optarg;
536
537 break;
538
539 case 'i': /* input dir */
540
541 if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
542 if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
543 afl->in_dir = optarg;
544
545 if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
546
547 break;
548
549 case 'o': /* output dir */
550
551 if (afl->out_dir) { FATAL("Multiple -o options not supported"); }
552 afl->out_dir = optarg;
553 break;
554
555 case 'M': { /* main sync ID */
556
557 u8 *c;
558
559 if (afl->non_instrumented_mode) {
560
561 FATAL("-M is not supported in non-instrumented mode");
562
563 }
564
565 if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
566
567 /* sanity check for argument: should not begin with '-' (possible
568 * option) */
569 if (optarg && *optarg == '-') {
570
571 FATAL(
572 "argument for -M started with a dash '-', which is used for "
573 "options");
574
575 }
576
577 afl->sync_id = ck_strdup(optarg);
578 afl->old_seed_selection = 1; // force old queue walking seed selection
579 afl->disable_trim = 1; // disable trimming
580
581 if ((c = strchr(afl->sync_id, ':'))) {
582
583 *c = 0;
584
585 if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) !=
586 2 ||
587 !afl->main_node_id || !afl->main_node_max ||
588 afl->main_node_id > afl->main_node_max ||
589 afl->main_node_max > 1000000) {
590
591 FATAL("Bogus main node ID passed to -M");
592
593 }
594
595 }
596
597 afl->is_main_node = 1;
598
599 }
600
601 break;
602
603 case 'S': /* secondary sync id */
604
605 if (afl->non_instrumented_mode) {
606
607 FATAL("-S is not supported in non-instrumented mode");
608
609 }
610
611 if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
612
613 /* sanity check for argument: should not begin with '-' (possible
614 * option) */
615 if (optarg && *optarg == '-') {
616
617 FATAL(
618 "argument for -M started with a dash '-', which is used for "
619 "options");
620
621 }
622
623 afl->sync_id = ck_strdup(optarg);
624 afl->is_secondary_node = 1;
625 break;
626
627 case 'F': /* foreign sync dir */
628
629 if (!optarg) { FATAL("Missing path for -F"); }
630 if (!afl->is_main_node) {
631
632 FATAL(
633 "Option -F can only be specified after the -M option for the "
634 "main fuzzer of a fuzzing campaign");
635
636 }
637
638 if (afl->foreign_sync_cnt >= FOREIGN_SYNCS_MAX) {
639
640 FATAL("Maximum %u entried of -F option can be specified",
641 FOREIGN_SYNCS_MAX);
642
643 }
644
645 afl->foreign_syncs[afl->foreign_sync_cnt].dir = optarg;
646 while (afl->foreign_syncs[afl->foreign_sync_cnt]
647 .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) -
648 1] == '/') {
649
650 afl->foreign_syncs[afl->foreign_sync_cnt]
651 .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) - 1] =
652 0;
653
654 }
655
656 afl->foreign_sync_cnt++;
657 break;
658
659 case 'f': /* target file */
660
661 if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); }
662 afl->fsrv.out_file = ck_strdup(optarg);
663 afl->fsrv.use_stdin = 0;
664 break;
665
666 case 'x': /* dictionary */
667
668 if (extras_dir_cnt >= 4) {
669
670 FATAL("More than four -x options are not supported");
671
672 }
673
674 extras_dir[extras_dir_cnt++] = optarg;
675 break;
676
677 case 't': { /* timeout */
678
679 u8 suffix = 0;
680
681 if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
682
683 if (!optarg ||
684 sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
685 optarg[0] == '-') {
686
687 FATAL("Bad syntax used for -t");
688
689 }
690
691 if (afl->fsrv.exec_tmout < 5) { FATAL("Dangerously low value of -t"); }
692
693 if (suffix == '+') {
694
695 afl->timeout_given = 2;
696
697 } else {
698
699 afl->timeout_given = 1;
700
701 }
702
703 break;
704
705 }
706
707 case 'm': { /* mem limit */
708
709 u8 suffix = 'M';
710
711 if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
712 mem_limit_given = 1;
713
714 if (!optarg) { FATAL("Wrong usage of -m"); }
715
716 if (!strcmp(optarg, "none")) {
717
718 afl->fsrv.mem_limit = 0;
719 break;
720
721 }
722
723 if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 ||
724 optarg[0] == '-') {
725
726 FATAL("Bad syntax used for -m");
727
728 }
729
730 switch (suffix) {
731
732 case 'T':
733 afl->fsrv.mem_limit *= 1024 * 1024;
734 break;
735 case 'G':
736 afl->fsrv.mem_limit *= 1024;
737 break;
738 case 'k':
739 afl->fsrv.mem_limit /= 1024;
740 break;
741 case 'M':
742 break;
743
744 default:
745 FATAL("Unsupported suffix or bad syntax for -m");
746
747 }
748
749 if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); }
750
751 if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) {
752
753 FATAL("Value of -m out of range on 32-bit systems");
754
755 }
756
757 }
758
759 break;
760
761 case 'D': /* enforce deterministic */
762
763 afl->skip_deterministic = 0;
764 break;
765
766 case 'd': /* skip deterministic */
767
768 afl->skip_deterministic = 1;
769 break;
770
771 case 'B': /* load bitmap */
772
773 /* This is a secret undocumented option! It is useful if you find
774 an interesting test case during a normal fuzzing process, and want
775 to mutate it without rediscovering any of the test cases already
776 found during an earlier run.
777
778 To use this mode, you need to point -B to the fuzz_bitmap produced
779 by an earlier run for the exact same binary... and that's it.
780
781 I only used this once or twice to get variants of a particular
782 file, so I'm not making this an official setting. */
783
784 if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); }
785
786 afl->in_bitmap = optarg;
787 break;
788
789 case 'C': /* crash mode */
790
791 if (afl->crash_mode) { FATAL("Multiple -C options not supported"); }
792 afl->crash_mode = FSRV_RUN_CRASH;
793 break;
794
795 case 'n': /* dumb mode */
796
797 if (afl->is_main_node || afl->is_secondary_node) {
798
799 FATAL("Non instrumented mode is not supported with -M / -S");
800
801 }
802
803 if (afl->non_instrumented_mode) {
804
805 FATAL("Multiple -n options not supported");
806
807 }
808
809 if (afl->afl_env.afl_dumb_forksrv) {
810
811 afl->non_instrumented_mode = 2;
812
813 } else {
814
815 afl->non_instrumented_mode = 1;
816
817 }
818
819 break;
820
821 case 'T': /* banner */
822
823 if (afl->use_banner) { FATAL("Multiple -T options not supported"); }
824 afl->use_banner = optarg;
825 break;
826
827 case 'O': /* FRIDA mode */
828
829 if (afl->fsrv.frida_mode) {
830
831 FATAL("Multiple -O options not supported");
832
833 }
834
835 afl->fsrv.frida_mode = 1;
836 if (get_afl_env("AFL_USE_FASAN")) { afl->fsrv.frida_asan = 1; }
837
838 break;
839
840 case 'Q': /* QEMU mode */
841
842 if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
843 afl->fsrv.qemu_mode = 1;
844
845 if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
846
847 break;
848
849 case 'N': /* Unicorn mode */
850
851 if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
852 afl->fsrv.no_unlink = (afl->no_unlink = true);
853
854 break;
855
856 case 'U': /* Unicorn mode */
857
858 if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
859 afl->unicorn_mode = 1;
860
861 if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; }
862
863 break;
864
865 case 'W': /* Wine+QEMU mode */
866
867 if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
868 afl->fsrv.qemu_mode = 1;
869 afl->use_wine = 1;
870
871 if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
872
873 break;
874
875 case 'V': {
876
877 afl->most_time_key = 1;
878 if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 ||
879 optarg[0] == '-') {
880
881 FATAL("Bad syntax used for -V");
882
883 }
884
885 } break;
886
887 case 'E': {
888
889 afl->most_execs_key = 1;
890 if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 ||
891 optarg[0] == '-') {
892
893 FATAL("Bad syntax used for -E");
894
895 }
896
897 } break;
898
899 case 'l': {
900
901 if (!optarg) { FATAL("missing parameter for 'l'"); }
902 char *c = optarg;
903 while (*c) {
904
905 switch (*c) {
906
907 case '0':
908 case '1':
909 afl->cmplog_lvl = 1;
910 break;
911 case '2':
912 afl->cmplog_lvl = 2;
913 break;
914 case '3':
915 afl->cmplog_lvl = 3;
916
917 if (!afl->disable_trim) {
918
919 ACTF("Deactivating trimming due CMPLOG level 3");
920 afl->disable_trim = 1;
921
922 }
923
924 break;
925 case 'a':
926 case 'A':
927 afl->cmplog_enable_arith = 1;
928 break;
929 case 't':
930 case 'T':
931 afl->cmplog_enable_transform = 1;
932 break;
933 default:
934 FATAL("Unknown option value '%c' in -l %s", *c, optarg);
935
936 }
937
938 ++c;
939
940 }
941
942 if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
943
944 afl->cmplog_max_filesize = MAX_FILE;
945
946 }
947
948 } break;
949
950 case 'L': { /* MOpt mode */
951
952 if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); }
953 afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT;
954
955 if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) {
956
957 FATAL("Bad syntax used for -L");
958
959 }
960
961 if (afl->limit_time_puppet == -1) {
962
963 afl->limit_time_sig = -1;
964 afl->limit_time_puppet = 0;
965
966 } else if (afl->limit_time_puppet < 0) {
967
968 FATAL("-L value must be between 0 and 2000000 or -1");
969
970 } else {
971
972 afl->limit_time_sig = 1;
973
974 }
975
976 u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
977
978 if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
979
980 FATAL("limit_time overflow");
981
982 }
983
984 afl->limit_time_puppet = limit_time_puppet2;
985 afl->swarm_now = 0;
986 if (afl->limit_time_puppet == 0) { afl->key_puppet = 1; }
987
988 int j;
989 int tmp_swarm = 0;
990
991 if (afl->g_now > afl->g_max) { afl->g_now = 0; }
992 afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) /
993 (afl->g_max) +
994 afl->w_end;
995
996 for (tmp_swarm = 0; tmp_swarm < swarm_num; ++tmp_swarm) {
997
998 double total_puppet_temp = 0.0;
999 afl->swarm_fitness[tmp_swarm] = 0.0;
1000
1001 for (j = 0; j < operator_num; ++j) {
1002
1003 afl->stage_finds_puppet[tmp_swarm][j] = 0;
1004 afl->probability_now[tmp_swarm][j] = 0.0;
1005 afl->x_now[tmp_swarm][j] =
1006 ((double)(random() % 7000) * 0.0001 + 0.1);
1007 total_puppet_temp += afl->x_now[tmp_swarm][j];
1008 afl->v_now[tmp_swarm][j] = 0.1;
1009 afl->L_best[tmp_swarm][j] = 0.5;
1010 afl->G_best[j] = 0.5;
1011 afl->eff_best[tmp_swarm][j] = 0.0;
1012
1013 }
1014
1015 for (j = 0; j < operator_num; ++j) {
1016
1017 afl->stage_cycles_puppet_v2[tmp_swarm][j] =
1018 afl->stage_cycles_puppet[tmp_swarm][j];
1019 afl->stage_finds_puppet_v2[tmp_swarm][j] =
1020 afl->stage_finds_puppet[tmp_swarm][j];
1021 afl->x_now[tmp_swarm][j] =
1022 afl->x_now[tmp_swarm][j] / total_puppet_temp;
1023
1024 }
1025
1026 double x_temp = 0.0;
1027
1028 for (j = 0; j < operator_num; ++j) {
1029
1030 afl->probability_now[tmp_swarm][j] = 0.0;
1031 afl->v_now[tmp_swarm][j] =
1032 afl->w_now * afl->v_now[tmp_swarm][j] +
1033 RAND_C *
1034 (afl->L_best[tmp_swarm][j] - afl->x_now[tmp_swarm][j]) +
1035 RAND_C * (afl->G_best[j] - afl->x_now[tmp_swarm][j]);
1036
1037 afl->x_now[tmp_swarm][j] += afl->v_now[tmp_swarm][j];
1038
1039 if (afl->x_now[tmp_swarm][j] > v_max) {
1040
1041 afl->x_now[tmp_swarm][j] = v_max;
1042
1043 } else if (afl->x_now[tmp_swarm][j] < v_min) {
1044
1045 afl->x_now[tmp_swarm][j] = v_min;
1046
1047 }
1048
1049 x_temp += afl->x_now[tmp_swarm][j];
1050
1051 }
1052
1053 for (j = 0; j < operator_num; ++j) {
1054
1055 afl->x_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j] / x_temp;
1056 if (likely(j != 0)) {
1057
1058 afl->probability_now[tmp_swarm][j] =
1059 afl->probability_now[tmp_swarm][j - 1] +
1060 afl->x_now[tmp_swarm][j];
1061
1062 } else {
1063
1064 afl->probability_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j];
1065
1066 }
1067
1068 }
1069
1070 if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 ||
1071 afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) {
1072
1073 FATAL("ERROR probability");
1074
1075 }
1076
1077 }
1078
1079 for (j = 0; j < operator_num; ++j) {
1080
1081 afl->core_operator_finds_puppet[j] = 0;
1082 afl->core_operator_finds_puppet_v2[j] = 0;
1083 afl->core_operator_cycles_puppet[j] = 0;
1084 afl->core_operator_cycles_puppet_v2[j] = 0;
1085 afl->core_operator_cycles_puppet_v3[j] = 0;
1086
1087 }
1088
1089 } break;
1090
1091 case 'h':
1092 show_help++;
1093 break; // not needed
1094
1095 case 'R':
1096
1097 FATAL(
1098 "Radamsa is now a custom mutator, please use that "
1099 "(custom_mutators/radamsa/).");
1100
1101 break;
1102
1103 default:
1104 if (!show_help) { show_help = 1; }
1105
1106 }
1107
1108 }
1109
1110 if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
1111
1112 usage(argv[0], show_help);
1113
1114 }
1115
1116 if (unlikely(afl->afl_env.afl_persistent_record)) {
1117
1118 #ifdef AFL_PERSISTENT_RECORD
1119
1120 afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
1121
1122 if (afl->fsrv.persistent_record < 2) {
1123
1124 FATAL(
1125 "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is "
1126 "100 or 1000.");
1127
1128 }
1129
1130 #else
1131
1132 FATAL(
1133 "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in "
1134 "config.h!");
1135
1136 #endif
1137
1138 }
1139
1140 if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
1141
1142 OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
1143 "Eißfeldt, Andrea Fioraldi and Dominik Maier");
1144 OKF("afl++ is open source, get it at "
1145 "https://github.com/AFLplusplus/AFLplusplus");
1146 OKF("NOTE: This is v3.x which changes defaults and behaviours - see "
1147 "README.md");
1148
1149 if (afl->sync_id && afl->is_main_node &&
1150 afl->afl_env.afl_custom_mutator_only) {
1151
1152 WARNF(
1153 "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options "
1154 "will result in no deterministic mutations being done!");
1155
1156 }
1157
1158 if (afl->fixed_seed) {
1159
1160 OKF("Running with fixed seed: %u", (u32)afl->init_seed);
1161
1162 }
1163
1164 #if defined(__SANITIZE_ADDRESS__)
1165 if (afl->fsrv.mem_limit) {
1166
1167 WARNF("in the ASAN build we disable all memory limits");
1168 afl->fsrv.mem_limit = 0;
1169
1170 }
1171
1172 #endif
1173
1174 afl->fsrv.kill_signal =
1175 parse_afl_kill_signal_env(afl->afl_env.afl_kill_signal, SIGKILL);
1176
1177 setup_signal_handlers();
1178 check_asan_opts(afl);
1179
1180 afl->power_name = power_names[afl->schedule];
1181
1182 if (!afl->non_instrumented_mode && !afl->sync_id) {
1183
1184 auto_sync = 1;
1185 afl->sync_id = ck_strdup("default");
1186 afl->is_secondary_node = 1;
1187 OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id);
1188
1189 }
1190
1191 if (afl->sync_id) { fix_up_sync(afl); }
1192
1193 if (!strcmp(afl->in_dir, afl->out_dir)) {
1194
1195 FATAL("Input and output directories can't be the same");
1196
1197 }
1198
1199 if (afl->non_instrumented_mode) {
1200
1201 if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
1202 if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
1203 if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
1204 if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
1205
1206 }
1207
1208 setenv("__AFL_OUT_DIR", afl->out_dir, 1);
1209
1210 if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
1211
1212 if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
1213
1214 FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive");
1215
1216 }
1217
1218 if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
1219
1220 if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
1221
1222 WARNF(cLRD
1223 "Target binary called without a prefixed path, make sure you are "
1224 "fuzzing the right binary: " cRST "%s",
1225 argv[optind]);
1226
1227 }
1228
1229 ACTF("Getting to work...");
1230
1231 switch (afl->schedule) {
1232
1233 case FAST:
1234 OKF("Using exponential power schedule (FAST)");
1235 break;
1236 case COE:
1237 OKF("Using cut-off exponential power schedule (COE)");
1238 break;
1239 case EXPLOIT:
1240 OKF("Using exploitation-based constant power schedule (EXPLOIT)");
1241 break;
1242 case LIN:
1243 OKF("Using linear power schedule (LIN)");
1244 break;
1245 case QUAD:
1246 OKF("Using quadratic power schedule (QUAD)");
1247 break;
1248 case MMOPT:
1249 OKF("Using modified MOpt power schedule (MMOPT)");
1250 break;
1251 case RARE:
1252 OKF("Using rare edge focus power schedule (RARE)");
1253 break;
1254 case SEEK:
1255 OKF("Using seek power schedule (SEEK)");
1256 break;
1257 case EXPLORE:
1258 OKF("Using exploration-based constant power schedule (EXPLORE)");
1259 break;
1260 default:
1261 FATAL("Unknown power schedule");
1262 break;
1263
1264 }
1265
1266 if (afl->shm.cmplog_mode) { OKF("CmpLog level: %u", afl->cmplog_lvl); }
1267
1268 /* Dynamically allocate memory for AFLFast schedules */
1269 if (afl->schedule >= FAST && afl->schedule <= RARE) {
1270
1271 afl->n_fuzz = ck_alloc(N_FUZZ_SIZE * sizeof(u32));
1272
1273 }
1274
1275 if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
1276 if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
1277 if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
1278 if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
1279 if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
1280
1281 if (afl->afl_env.afl_autoresume) {
1282
1283 afl->autoresume = 1;
1284 if (afl->in_place_resume) {
1285
1286 SAYF("AFL_AUTORESUME has no effect for '-i -'");
1287
1288 }
1289
1290 }
1291
1292 if (afl->afl_env.afl_hang_tmout) {
1293
1294 s32 hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
1295 if (hang_tmout < 1) { FATAL("Invalid value for AFL_HANG_TMOUT"); }
1296 afl->hang_tmout = (u32)hang_tmout;
1297
1298 }
1299
1300 if (afl->afl_env.afl_exit_on_time) {
1301
1302 u64 exit_on_time = atoi(afl->afl_env.afl_exit_on_time);
1303 afl->exit_on_time = (u64)exit_on_time * 1000;
1304
1305 }
1306
1307 if (afl->afl_env.afl_max_det_extras) {
1308
1309 s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
1310 if (max_det_extras < 1) { FATAL("Invalid value for AFL_MAX_DET_EXTRAS"); }
1311 afl->max_det_extras = (u32)max_det_extras;
1312
1313 } else {
1314
1315 afl->max_det_extras = MAX_DET_EXTRAS;
1316
1317 }
1318
1319 if (afl->afl_env.afl_testcache_size) {
1320
1321 afl->q_testcase_max_cache_size =
1322 (u64)atoi(afl->afl_env.afl_testcache_size) * 1048576;
1323
1324 }
1325
1326 if (afl->afl_env.afl_testcache_entries) {
1327
1328 afl->q_testcase_max_cache_entries =
1329 (u32)atoi(afl->afl_env.afl_testcache_entries);
1330
1331 // user_set_cache = 1;
1332
1333 }
1334
1335 if (!afl->afl_env.afl_testcache_size || !afl->afl_env.afl_testcache_entries) {
1336
1337 afl->afl_env.afl_testcache_entries = 0;
1338 afl->afl_env.afl_testcache_size = 0;
1339
1340 }
1341
1342 if (!afl->q_testcase_max_cache_size) {
1343
1344 ACTF(
1345 "No testcache was configured. it is recommended to use a testcache, it "
1346 "improves performance: set AFL_TESTCACHE_SIZE=(value in MB)");
1347
1348 } else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) {
1349
1350 FATAL("AFL_TESTCACHE_SIZE must be set to %u or more, or 0 to disable",
1351 (2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576
1352 : 1 + ((2 * MAX_FILE) / 1048576));
1353
1354 } else {
1355
1356 OKF("Enabled testcache with %llu MB",
1357 afl->q_testcase_max_cache_size / 1048576);
1358
1359 }
1360
1361 if (afl->afl_env.afl_forksrv_init_tmout) {
1362
1363 afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout);
1364 if (!afl->fsrv.init_tmout) {
1365
1366 FATAL("Invalid value of AFL_FORKSRV_INIT_TMOUT");
1367
1368 }
1369
1370 } else {
1371
1372 afl->fsrv.init_tmout = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
1373
1374 }
1375
1376 if (afl->afl_env.afl_crash_exitcode) {
1377
1378 long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
1379 if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
1380 exitcode < -127 || exitcode > 128) {
1381
1382 FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
1383 afl->afl_env.afl_crash_exitcode);
1384
1385 }
1386
1387 afl->fsrv.uses_crash_exitcode = true;
1388 // WEXITSTATUS is 8 bit unsigned
1389 afl->fsrv.crash_exitcode = (u8)exitcode;
1390
1391 }
1392
1393 if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
1394
1395 FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
1396
1397 }
1398
1399 afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
1400
1401 if (getenv("LD_PRELOAD")) {
1402
1403 WARNF(
1404 "LD_PRELOAD is set, are you sure that is what to you want to do "
1405 "instead of using AFL_PRELOAD?");
1406
1407 }
1408
1409 if (afl->afl_env.afl_preload) {
1410
1411 if (afl->fsrv.qemu_mode) {
1412
1413 /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
1414
1415 } else if (afl->fsrv.frida_mode) {
1416
1417 afl_preload = getenv("AFL_PRELOAD");
1418 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1419 OKF("Injecting %s ...", frida_binary);
1420 if (afl_preload) {
1421
1422 if (afl->fsrv.frida_asan) {
1423
1424 OKF("Using Frida Address Sanitizer Mode");
1425
1426 fasan_check_afl_preload(afl_preload);
1427
1428 setenv("ASAN_OPTIONS", "detect_leaks=false", 1);
1429
1430 }
1431
1432 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1433 OKF("Injecting %s ...", frida_binary);
1434 frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
1435
1436 ck_free(frida_binary);
1437
1438 setenv("LD_PRELOAD", frida_afl_preload, 1);
1439 setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
1440
1441 }
1442
1443 } else {
1444
1445 setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
1446 setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
1447
1448 }
1449
1450 } else if (afl->fsrv.frida_mode) {
1451
1452 if (afl->fsrv.frida_asan) {
1453
1454 OKF("Using Frida Address Sanitizer Mode");
1455 FATAL(
1456 "Address Sanitizer DSO must be loaded using AFL_PRELOAD in Frida "
1457 "Address Sanitizer Mode");
1458
1459 } else {
1460
1461 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1462 OKF("Injecting %s ...", frida_binary);
1463 setenv("LD_PRELOAD", frida_binary, 1);
1464 setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
1465 ck_free(frida_binary);
1466
1467 }
1468
1469 }
1470
1471 if (getenv("AFL_LD_PRELOAD")) {
1472
1473 FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
1474
1475 }
1476
1477 if (afl->afl_env.afl_target_env &&
1478 !extract_and_set_env(afl->afl_env.afl_target_env)) {
1479
1480 FATAL("Bad value of AFL_TARGET_ENV");
1481
1482 }
1483
1484 save_cmdline(afl, argc, argv);
1485
1486 fix_up_banner(afl, argv[optind]);
1487
1488 check_if_tty(afl);
1489 if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
1490
1491 if (afl->afl_env.afl_custom_mutator_only) {
1492
1493 /* This ensures we don't proceed to havoc/splice */
1494 afl->custom_only = 1;
1495
1496 /* Ensure we also skip all deterministic steps */
1497 afl->skip_deterministic = 1;
1498
1499 }
1500
1501 check_crash_handling();
1502 check_cpu_governor(afl);
1503
1504 get_core_count(afl);
1505
1506 atexit(at_exit);
1507
1508 setup_dirs_fds(afl);
1509
1510 #ifdef HAVE_AFFINITY
1511 bind_to_free_cpu(afl);
1512 #endif /* HAVE_AFFINITY */
1513
1514 #ifdef __HAIKU__
1515 /* Prioritizes performance over power saving */
1516 set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY);
1517 #endif
1518
1519 #ifdef __APPLE__
1520 if (pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0) != 0) {
1521
1522 WARNF("general thread priority settings failed");
1523
1524 }
1525
1526 #endif
1527
1528 init_count_class16();
1529
1530 if (afl->is_main_node && check_main_node_exists(afl) == 1) {
1531
1532 WARNF("it is wasteful to run more than one main node!");
1533 sleep(1);
1534
1535 } else if (!auto_sync && afl->is_secondary_node &&
1536
1537 check_main_node_exists(afl) == 0) {
1538
1539 WARNF(
1540 "no -M main node found. It is recommended to run exactly one main "
1541 "instance.");
1542 sleep(1);
1543
1544 }
1545
1546 #ifdef RAND_TEST_VALUES
1547 u32 counter;
1548 for (counter = 0; counter < 100000; counter++)
1549 printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
1550 #endif
1551
1552 setup_custom_mutators(afl);
1553
1554 write_setup_file(afl, argc, argv);
1555
1556 setup_cmdline_file(afl, argv + optind);
1557
1558 read_testcases(afl, NULL);
1559 // read_foreign_testcases(afl, 1); for the moment dont do this
1560 OKF("Loaded a total of %u seeds.", afl->queued_paths);
1561
1562 pivot_inputs(afl);
1563
1564 if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
1565
1566 if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
1567 !afl->in_place_resume) {
1568
1569 char tmpfile[PATH_MAX];
1570
1571 if (afl->file_extension) {
1572
1573 snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
1574 afl->file_extension);
1575
1576 } else {
1577
1578 snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
1579
1580 }
1581
1582 /* there is still a race condition here, but well ... */
1583 if (access(tmpfile, F_OK) != -1) {
1584
1585 FATAL(
1586 "AFL_TMPDIR already has an existing temporary input file: %s - if "
1587 "this is not from another instance, then just remove the file.",
1588 tmpfile);
1589
1590 }
1591
1592 } else {
1593
1594 afl->tmp_dir = afl->out_dir;
1595
1596 }
1597
1598 /* If we don't have a file name chosen yet, use a safe default. */
1599
1600 if (!afl->fsrv.out_file) {
1601
1602 u32 j = optind + 1;
1603 while (argv[j]) {
1604
1605 u8 *aa_loc = strstr(argv[j], "@@");
1606
1607 if (aa_loc && !afl->fsrv.out_file) {
1608
1609 afl->fsrv.use_stdin = 0;
1610
1611 if (afl->file_extension) {
1612
1613 afl->fsrv.out_file = alloc_printf("%s/.cur_input.%s", afl->tmp_dir,
1614 afl->file_extension);
1615
1616 } else {
1617
1618 afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
1619
1620 }
1621
1622 detect_file_args(argv + optind + 1, afl->fsrv.out_file,
1623 &afl->fsrv.use_stdin);
1624 break;
1625
1626 }
1627
1628 ++j;
1629
1630 }
1631
1632 }
1633
1634 if (!afl->fsrv.out_file) { setup_stdio_file(afl); }
1635
1636 if (afl->cmplog_binary) {
1637
1638 if (afl->unicorn_mode) {
1639
1640 FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry");
1641
1642 }
1643
1644 if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode &&
1645 !afl->non_instrumented_mode) {
1646
1647 check_binary(afl, afl->cmplog_binary);
1648
1649 }
1650
1651 }
1652
1653 check_binary(afl, argv[optind]);
1654
1655 #ifdef AFL_PERSISTENT_RECORD
1656 if (unlikely(afl->fsrv.persistent_record)) {
1657
1658 if (!getenv(PERSIST_ENV_VAR)) {
1659
1660 FATAL(
1661 "Target binary is not compiled in persistent mode, "
1662 "AFL_PERSISTENT_RECORD makes no sense.");
1663
1664 }
1665
1666 afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
1667
1668 }
1669
1670 #endif
1671
1672 if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
1673
1674 afl->start_time = get_cur_time();
1675
1676 if (afl->fsrv.qemu_mode) {
1677
1678 if (afl->use_wine) {
1679
1680 use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind,
1681 argv + optind);
1682
1683 } else {
1684
1685 use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind,
1686 argv + optind);
1687
1688 }
1689
1690 } else {
1691
1692 use_argv = argv + optind;
1693
1694 }
1695
1696 if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
1697 afl->fsrv.frida_mode || afl->unicorn_mode) {
1698
1699 map_size = afl->fsrv.map_size = MAP_SIZE;
1700 afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
1701 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
1702 afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
1703 afl->var_bytes = ck_realloc(afl->var_bytes, map_size);
1704 afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *));
1705 afl->clean_trace = ck_realloc(afl->clean_trace, map_size);
1706 afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size);
1707 afl->first_trace = ck_realloc(afl->first_trace, map_size);
1708 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
1709
1710 }
1711
1712 afl->argv = use_argv;
1713 afl->fsrv.trace_bits =
1714 afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
1715
1716 if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
1717 !afl->unicorn_mode && !afl->fsrv.frida_mode &&
1718 !afl->afl_env.afl_skip_bin_check) {
1719
1720 if (map_size <= DEFAULT_SHMEM_SIZE) {
1721
1722 afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value
1723 char vbuf[16];
1724 snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE);
1725 setenv("AFL_MAP_SIZE", vbuf, 1);
1726
1727 }
1728
1729 u32 new_map_size = afl_fsrv_get_mapsize(
1730 &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
1731
1732 // only reinitialize if the map needs to be larger than what we have.
1733 if (map_size < new_map_size) {
1734
1735 OKF("Re-initializing maps to %u bytes", new_map_size);
1736
1737 afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
1738 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
1739 afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
1740 afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
1741 afl->top_rated =
1742 ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
1743 afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
1744 afl->clean_trace_custom =
1745 ck_realloc(afl->clean_trace_custom, new_map_size);
1746 afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
1747 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
1748
1749 afl_fsrv_kill(&afl->fsrv);
1750 afl_shm_deinit(&afl->shm);
1751 afl->fsrv.map_size = new_map_size;
1752 afl->fsrv.trace_bits =
1753 afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
1754 setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
1755 afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
1756 afl->afl_env.afl_debug_child);
1757
1758 map_size = new_map_size;
1759
1760 }
1761
1762 }
1763
1764 if (afl->cmplog_binary) {
1765
1766 ACTF("Spawning cmplog forkserver");
1767 afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
1768 // TODO: this is semi-nice
1769 afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
1770 afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
1771 afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
1772 afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
1773 afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
1774
1775 if ((map_size <= DEFAULT_SHMEM_SIZE ||
1776 afl->cmplog_fsrv.map_size < map_size) &&
1777 !afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
1778 !afl->fsrv.frida_mode && !afl->unicorn_mode &&
1779 !afl->afl_env.afl_skip_bin_check) {
1780
1781 afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
1782 char vbuf[16];
1783 snprintf(vbuf, sizeof(vbuf), "%u", afl->cmplog_fsrv.map_size);
1784 setenv("AFL_MAP_SIZE", vbuf, 1);
1785
1786 }
1787
1788 u32 new_map_size =
1789 afl_fsrv_get_mapsize(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
1790 afl->afl_env.afl_debug_child);
1791
1792 // only reinitialize when it needs to be larger
1793 if (map_size < new_map_size) {
1794
1795 OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
1796
1797 afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
1798 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
1799 afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
1800 afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
1801 afl->top_rated =
1802 ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
1803 afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
1804 afl->clean_trace_custom =
1805 ck_realloc(afl->clean_trace_custom, new_map_size);
1806 afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
1807 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
1808
1809 afl_fsrv_kill(&afl->fsrv);
1810 afl_fsrv_kill(&afl->cmplog_fsrv);
1811 afl_shm_deinit(&afl->shm);
1812
1813 afl->cmplog_fsrv.map_size = new_map_size; // non-cmplog stays the same
1814 map_size = new_map_size;
1815
1816 setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
1817 afl->fsrv.trace_bits =
1818 afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
1819 afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
1820 afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
1821 afl->afl_env.afl_debug_child);
1822 afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
1823 afl->afl_env.afl_debug_child);
1824
1825 }
1826
1827 OKF("Cmplog forkserver successfully started");
1828
1829 }
1830
1831 load_auto(afl);
1832
1833 if (extras_dir_cnt) {
1834
1835 for (u8 i = 0; i < extras_dir_cnt; i++) {
1836
1837 load_extras(afl, extras_dir[i]);
1838
1839 }
1840
1841 }
1842
1843 deunicode_extras(afl);
1844 dedup_extras(afl);
1845 if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
1846
1847 // after we have the correct bitmap size we can read the bitmap -B option
1848 // and set the virgin maps
1849 if (afl->in_bitmap) {
1850
1851 read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
1852
1853 } else {
1854
1855 memset(afl->virgin_bits, 255, map_size);
1856
1857 }
1858
1859 memset(afl->virgin_tmout, 255, map_size);
1860 memset(afl->virgin_crash, 255, map_size);
1861
1862 perform_dry_run(afl);
1863
1864 if (afl->q_testcase_max_cache_entries) {
1865
1866 afl->q_testcase_cache =
1867 ck_alloc(afl->q_testcase_max_cache_entries * sizeof(size_t));
1868 if (!afl->q_testcase_cache) { PFATAL("malloc failed for cache entries"); }
1869
1870 }
1871
1872 cull_queue(afl);
1873
1874 // ensure we have at least one seed that is not disabled.
1875 u32 entry, valid_seeds = 0;
1876 for (entry = 0; entry < afl->queued_paths; ++entry)
1877 if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
1878
1879 if (!afl->pending_not_fuzzed || !valid_seeds) {
1880
1881 FATAL("We need at least one valid input seed that does not crash!");
1882
1883 }
1884
1885 if (afl->timeout_given == 2) { // -t ...+ option
1886
1887 if (valid_seeds == 1) {
1888
1889 WARNF(
1890 "Only one valid seed is present, auto-calculating the timeout is "
1891 "disabled!");
1892 afl->timeout_given = 1;
1893
1894 } else {
1895
1896 u64 max_ms = 0;
1897
1898 for (entry = 0; entry < afl->queued_paths; ++entry)
1899 if (!afl->queue_buf[entry]->disabled)
1900 if (afl->queue_buf[entry]->exec_us > max_ms)
1901 max_ms = afl->queue_buf[entry]->exec_us;
1902
1903 afl->fsrv.exec_tmout = max_ms;
1904
1905 }
1906
1907 }
1908
1909 show_init_stats(afl);
1910
1911 if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
1912
1913 afl->start_time = get_cur_time();
1914 if (afl->in_place_resume || afl->afl_env.afl_autoresume) {
1915
1916 load_stats_file(afl);
1917
1918 }
1919
1920 write_stats_file(afl, 0, 0, 0, 0);
1921 maybe_update_plot_file(afl, 0, 0, 0);
1922 save_auto(afl);
1923
1924 if (afl->stop_soon) { goto stop_fuzzing; }
1925
1926 /* Woop woop woop */
1927
1928 if (!afl->not_on_tty) {
1929
1930 sleep(1);
1931 if (afl->stop_soon) { goto stop_fuzzing; }
1932
1933 }
1934
1935 // (void)nice(-20); // does not improve the speed
1936 // real start time, we reset, so this works correctly with -V
1937 afl->start_time = get_cur_time();
1938
1939 u32 runs_in_current_cycle = (u32)-1;
1940 u32 prev_queued_paths = 0;
1941 u8 skipped_fuzz;
1942
1943 #ifdef INTROSPECTION
1944 char ifn[4096];
1945 snprintf(ifn, sizeof(ifn), "%s/introspection.txt", afl->out_dir);
1946 if ((afl->introspection_file = fopen(ifn, "w")) == NULL) {
1947
1948 PFATAL("could not create '%s'", ifn);
1949
1950 }
1951
1952 setvbuf(afl->introspection_file, NULL, _IONBF, 0);
1953 OKF("Writing mutation introspection to '%s'", ifn);
1954 #endif
1955
1956 while (likely(!afl->stop_soon)) {
1957
1958 cull_queue(afl);
1959
1960 if (unlikely((!afl->old_seed_selection &&
1961 runs_in_current_cycle > afl->queued_paths) ||
1962 (afl->old_seed_selection && !afl->queue_cur))) {
1963
1964 if (unlikely((afl->last_sync_cycle < afl->queue_cycle ||
1965 (!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
1966 afl->sync_id)) {
1967
1968 sync_fuzzers(afl);
1969
1970 }
1971
1972 ++afl->queue_cycle;
1973 runs_in_current_cycle = (u32)-1;
1974 afl->cur_skipped_paths = 0;
1975
1976 if (unlikely(afl->old_seed_selection)) {
1977
1978 afl->current_entry = 0;
1979 while (unlikely(afl->current_entry < afl->queued_paths &&
1980 afl->queue_buf[afl->current_entry]->disabled)) {
1981
1982 ++afl->current_entry;
1983
1984 }
1985
1986 if (afl->current_entry >= afl->queued_paths) { afl->current_entry = 0; }
1987
1988 afl->queue_cur = afl->queue_buf[afl->current_entry];
1989
1990 if (unlikely(seek_to)) {
1991
1992 if (unlikely(seek_to >= afl->queued_paths)) {
1993
1994 // This should never happen.
1995 FATAL("BUG: seek_to location out of bounds!\n");
1996
1997 }
1998
1999 afl->current_entry = seek_to;
2000 afl->queue_cur = afl->queue_buf[seek_to];
2001 seek_to = 0;
2002
2003 }
2004
2005 }
2006
2007 if (unlikely(afl->not_on_tty)) {
2008
2009 ACTF("Entering queue cycle %llu.", afl->queue_cycle);
2010 fflush(stdout);
2011
2012 }
2013
2014 /* If we had a full queue cycle with no new finds, try
2015 recombination strategies next. */
2016
2017 if (unlikely(afl->queued_paths == prev_queued
2018 /* FIXME TODO BUG: && (get_cur_time() - afl->start_time) >=
2019 3600 */
2020 )) {
2021
2022 if (afl->use_splicing) {
2023
2024 ++afl->cycles_wo_finds;
2025
2026 if (unlikely(afl->shm.cmplog_mode &&
2027 afl->cmplog_max_filesize < MAX_FILE)) {
2028
2029 afl->cmplog_max_filesize <<= 4;
2030
2031 }
2032
2033 switch (afl->expand_havoc) {
2034
2035 case 0:
2036 // this adds extra splicing mutation options to havoc mode
2037 afl->expand_havoc = 1;
2038 break;
2039 case 1:
2040 // add MOpt mutator
2041 /*
2042 if (afl->limit_time_sig == 0 && !afl->custom_only &&
2043 !afl->python_only) {
2044
2045 afl->limit_time_sig = -1;
2046 afl->limit_time_puppet = 0;
2047
2048 }
2049
2050 */
2051 afl->expand_havoc = 2;
2052 if (afl->cmplog_lvl && afl->cmplog_lvl < 2) afl->cmplog_lvl = 2;
2053 break;
2054 case 2:
2055 // increase havoc mutations per fuzz attempt
2056 afl->havoc_stack_pow2++;
2057 afl->expand_havoc = 3;
2058 break;
2059 case 3:
2060 // further increase havoc mutations per fuzz attempt
2061 afl->havoc_stack_pow2++;
2062 afl->expand_havoc = 4;
2063 break;
2064 case 4:
2065 afl->expand_havoc = 5;
2066 // if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl =
2067 // 3;
2068 break;
2069 case 5:
2070 // nothing else currently
2071 break;
2072
2073 }
2074
2075 } else {
2076
2077 #ifndef NO_SPLICING
2078 afl->use_splicing = 1;
2079 #else
2080 afl->use_splicing = 0;
2081 #endif
2082
2083 }
2084
2085 } else {
2086
2087 afl->cycles_wo_finds = 0;
2088
2089 }
2090
2091 #ifdef INTROSPECTION
2092 fprintf(afl->introspection_file,
2093 "CYCLE cycle=%llu cycle_wo_finds=%llu expand_havoc=%u queue=%u\n",
2094 afl->queue_cycle, afl->cycles_wo_finds, afl->expand_havoc,
2095 afl->queued_paths);
2096 #endif
2097
2098 if (afl->cycle_schedules) {
2099
2100 /* we cannot mix non-AFLfast schedules with others */
2101
2102 switch (afl->schedule) {
2103
2104 case EXPLORE:
2105 afl->schedule = EXPLOIT;
2106 break;
2107 case EXPLOIT:
2108 afl->schedule = MMOPT;
2109 break;
2110 case MMOPT:
2111 afl->schedule = SEEK;
2112 break;
2113 case SEEK:
2114 afl->schedule = EXPLORE;
2115 break;
2116 case FAST:
2117 afl->schedule = COE;
2118 break;
2119 case COE:
2120 afl->schedule = LIN;
2121 break;
2122 case LIN:
2123 afl->schedule = QUAD;
2124 break;
2125 case QUAD:
2126 afl->schedule = RARE;
2127 break;
2128 case RARE:
2129 afl->schedule = FAST;
2130 break;
2131
2132 }
2133
2134 // we must recalculate the scores of all queue entries
2135 for (u32 i = 0; i < afl->queued_paths; i++) {
2136
2137 if (likely(!afl->queue_buf[i]->disabled)) {
2138
2139 update_bitmap_score(afl, afl->queue_buf[i]);
2140
2141 }
2142
2143 }
2144
2145 }
2146
2147 prev_queued = afl->queued_paths;
2148
2149 }
2150
2151 ++runs_in_current_cycle;
2152
2153 do {
2154
2155 if (likely(!afl->old_seed_selection)) {
2156
2157 if (unlikely(prev_queued_paths < afl->queued_paths ||
2158 afl->reinit_table)) {
2159
2160 // we have new queue entries since the last run, recreate alias table
2161 prev_queued_paths = afl->queued_paths;
2162 create_alias_table(afl);
2163
2164 }
2165
2166 afl->current_entry = select_next_queue_entry(afl);
2167 afl->queue_cur = afl->queue_buf[afl->current_entry];
2168
2169 }
2170
2171 skipped_fuzz = fuzz_one(afl);
2172
2173 if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; }
2174
2175 if (unlikely(afl->old_seed_selection)) {
2176
2177 while (++afl->current_entry < afl->queued_paths &&
2178 afl->queue_buf[afl->current_entry]->disabled)
2179 ;
2180 if (unlikely(afl->current_entry >= afl->queued_paths ||
2181 afl->queue_buf[afl->current_entry] == NULL ||
2182 afl->queue_buf[afl->current_entry]->disabled))
2183 afl->queue_cur = NULL;
2184 else
2185 afl->queue_cur = afl->queue_buf[afl->current_entry];
2186
2187 }
2188
2189 } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
2190
2191 if (likely(!afl->stop_soon && afl->sync_id)) {
2192
2193 if (likely(afl->skip_deterministic)) {
2194
2195 if (unlikely(afl->is_main_node)) {
2196
2197 if (unlikely(get_cur_time() >
2198 (SYNC_TIME >> 1) + afl->last_sync_time)) {
2199
2200 if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
2201
2202 sync_fuzzers(afl);
2203
2204 }
2205
2206 }
2207
2208 } else {
2209
2210 if (unlikely(get_cur_time() > SYNC_TIME + afl->last_sync_time)) {
2211
2212 if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
2213
2214 }
2215
2216 }
2217
2218 } else {
2219
2220 sync_fuzzers(afl);
2221
2222 }
2223
2224 }
2225
2226 }
2227
2228 write_bitmap(afl);
2229 save_auto(afl);
2230
2231 stop_fuzzing:
2232
2233 afl->force_ui_update = 1; // ensure the screen is reprinted
2234 show_stats(afl); // print the screen one last time
2235
2236 SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
2237 afl->stop_soon == 2 ? "programmatically" : "by user");
2238
2239 if (afl->most_time_key == 2) {
2240
2241 SAYF(cYEL "[!] " cRST "Time limit was reached\n");
2242
2243 }
2244
2245 if (afl->most_execs_key == 2) {
2246
2247 SAYF(cYEL "[!] " cRST "Execution limit was reached\n");
2248
2249 }
2250
2251 /* Running for more than 30 minutes but still doing first cycle? */
2252
2253 if (afl->queue_cycle == 1 &&
2254 get_cur_time() - afl->start_time > 30 * 60 * 1000) {
2255
2256 SAYF("\n" cYEL "[!] " cRST
2257 "Stopped during the first cycle, results may be incomplete.\n"
2258 " (For info on resuming, see %s/README.md)\n",
2259 doc_path);
2260
2261 }
2262
2263 #ifdef PROFILING
2264 SAYF(cYEL "[!] " cRST
2265 "Profiling information: %llu ms total work, %llu ns/run\n",
2266 time_spent_working / 1000000,
2267 time_spent_working / afl->fsrv.total_execs);
2268 #endif
2269
2270 if (afl->is_main_node) {
2271
2272 u8 path[PATH_MAX];
2273 sprintf(path, "%s/is_main_node", afl->out_dir);
2274 unlink(path);
2275
2276 }
2277
2278 if (frida_afl_preload) { ck_free(frida_afl_preload); }
2279
2280 fclose(afl->fsrv.plot_file);
2281 destroy_queue(afl);
2282 destroy_extras(afl);
2283 destroy_custom_mutators(afl);
2284 afl_shm_deinit(&afl->shm);
2285
2286 if (afl->shm_fuzz) {
2287
2288 afl_shm_deinit(afl->shm_fuzz);
2289 ck_free(afl->shm_fuzz);
2290
2291 }
2292
2293 afl_fsrv_deinit(&afl->fsrv);
2294
2295 /* remove tmpfile */
2296 if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
2297
2298 (void)unlink(afl->fsrv.out_file);
2299
2300 }
2301
2302 if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
2303 ck_free(afl->fsrv.target_path);
2304 ck_free(afl->fsrv.out_file);
2305 ck_free(afl->sync_id);
2306 if (afl->q_testcase_cache) { ck_free(afl->q_testcase_cache); }
2307 afl_state_deinit(afl);
2308 free(afl); /* not tracked */
2309
2310 argv_cpy_free(argv);
2311
2312 alloc_report();
2313
2314 OKF("We're done here. Have a nice day!\n");
2315
2316 exit(0);
2317
2318 }
2319
2320 #endif /* !AFL_LIB */
2321
2322