1 /*
2 american fuzzy lop++ - fuzzer code
3 --------------------------------
4
5 Originally written by Michal Zalewski
6
7 Now maintained by Marc Heuse <[email protected]>,
8 Heiko Eißfeldt <[email protected]> and
9 Andrea Fioraldi <[email protected]>
10
11 Copyright 2016, 2017 Google Inc. All rights reserved.
12 Copyright 2019-2024 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 https://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 "common.h"
29 #include <limits.h>
30 #include <stdlib.h>
31 #ifndef USEMMAP
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 #endif
38
39 #ifdef __APPLE__
40 #include <sys/qos.h>
41 #include <pthread/qos.h>
42 #endif
43
44 #ifdef PROFILING
45 extern u64 time_spent_working;
46 #endif
47
at_exit()48 static void at_exit() {
49
50 s32 i, pid1 = 0, pid2 = 0, pgrp = -1;
51 char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
52 char *ptr;
53
54 ptr = getenv("__AFL_TARGET_PID2");
55 if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) {
56
57 pgrp = getpgid(pid2);
58 if (pgrp > 0) { killpg(pgrp, SIGTERM); }
59 kill(pid2, SIGTERM);
60
61 }
62
63 ptr = getenv("__AFL_TARGET_PID1");
64 if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) {
65
66 pgrp = getpgid(pid1);
67 if (pgrp > 0) { killpg(pgrp, SIGTERM); }
68 kill(pid1, SIGTERM);
69
70 }
71
72 ptr = getenv(CPU_AFFINITY_ENV_VAR);
73 if (ptr && *ptr) unlink(ptr);
74
75 i = 0;
76 while (list[i] != NULL) {
77
78 ptr = getenv(list[i]);
79 if (ptr && *ptr) {
80
81 #ifdef USEMMAP
82
83 shm_unlink(ptr);
84
85 #else
86
87 shmctl(atoi(ptr), IPC_RMID, NULL);
88
89 #endif
90
91 }
92
93 i++;
94
95 }
96
97 int kill_signal = SIGKILL;
98 /* AFL_KILL_SIGNAL should already be a valid int at this point */
99 if ((ptr = getenv("AFL_KILL_SIGNAL"))) { kill_signal = atoi(ptr); }
100
101 if (pid1 > 0) {
102
103 pgrp = getpgid(pid1);
104 if (pgrp > 0) { killpg(pgrp, kill_signal); }
105 kill(pid1, kill_signal);
106
107 }
108
109 if (pid2 > 0) {
110
111 pgrp = getpgid(pid1);
112 if (pgrp > 0) { killpg(pgrp, kill_signal); }
113 kill(pid2, kill_signal);
114
115 }
116
117 }
118
119 /* Display usage hints. */
120
usage(u8 * argv0,int more_help)121 static void usage(u8 *argv0, int more_help) {
122
123 SAYF(
124 "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
125
126 "Required parameters:\n"
127 " -i dir - input directory with test cases (or '-' to resume, "
128 "also see \n"
129 " AFL_AUTORESUME)\n"
130 " -o dir - output directory for fuzzer findings\n\n"
131
132 "Execution control settings:\n"
133 " -P strategy - set fix mutation strategy: explore (focus on new "
134 "coverage),\n"
135 " exploit (focus on triggering crashes). You can also "
136 "set a\n"
137 " number of seconds after without any finds it switches "
138 "to\n"
139 " exploit mode, and back on new coverage (default: %u)\n"
140 " -p schedule - power schedules compute a seed's performance score:\n"
141 " explore(default), fast, exploit, seek, rare, mmopt, "
142 "coe, lin\n"
143 " quad -- see docs/FAQ.md for more information\n"
144 " -f file - location read by the fuzzed program (default: stdin "
145 "or @@)\n"
146 " -t msec - timeout for each run (auto-scaled, default %u ms). "
147 "Add a '+'\n"
148 " to auto-calculate the timeout, the value being the "
149 "maximum.\n"
150 " -m megs - memory limit for child process (%u MB, 0 = no limit "
151 "[default])\n"
152 #if defined(__linux__) && defined(__aarch64__)
153 " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
154 #endif
155 " -O - use binary-only instrumentation (FRIDA mode)\n"
156 #if defined(__linux__)
157 " -Q - use binary-only instrumentation (QEMU mode)\n"
158 " -U - use unicorn-based instrumentation (Unicorn mode)\n"
159 " -W - use qemu-based instrumentation with Wine (Wine mode)\n"
160 #endif
161 #if defined(__linux__)
162 " -X - use VM fuzzing (NYX mode - standalone mode)\n"
163 " -Y - use VM fuzzing (NYX mode - multiple instances mode)\n"
164 #endif
165 "\n"
166
167 "Mutator settings:\n"
168 " -a type - target input format, \"text\" or \"binary\" (default: "
169 "generic)\n"
170 " -g minlength - set min length of generated fuzz input (default: 1)\n"
171 " -G maxlength - set max length of generated fuzz input (default: "
172 "%lu)\n"
173 " -D - enable (a new) effective deterministic fuzzing\n"
174 " -L minutes - use MOpt(imize) mode and set the time limit for "
175 "entering the\n"
176 " pacemaker mode (minutes of no new finds). 0 = "
177 "immediately,\n"
178 " -1 = immediately and together with normal mutation.\n"
179 " Note: this option is usually not very effective\n"
180 " -c program - enable CmpLog by specifying a binary compiled for "
181 "it.\n"
182 " if using QEMU/FRIDA or the fuzzing target is "
183 "compiled\n"
184 " for CmpLog then use '-c 0'. To disable Cmplog use '-c "
185 "-'.\n"
186 " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
187 " 1=small files, 2=larger files (default), 3=all "
188 "files,\n"
189 " A=arithmetic solving, T=transformational solving,\n"
190 " X=extreme transform solving, R=random colorization "
191 "bytes.\n\n"
192 "Fuzzing behavior settings:\n"
193 " -Z - sequential queue selection instead of weighted "
194 "random\n"
195 " -N - do not unlink the fuzzing input file (for devices "
196 "etc.)\n"
197 " -n - fuzz without instrumentation (non-instrumented mode)\n"
198 " -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
199 "times)\n\n"
200
201 "Test settings:\n"
202 " -s seed - use a fixed seed for the RNG\n"
203 " -V seconds - fuzz for a specified time then terminate\n"
204 " -E execs - fuzz for an approx. no. of total executions then "
205 "terminate\n"
206 " Note: not precise and can have several more "
207 "executions.\n\n"
208
209 "Other stuff:\n"
210 " -M/-S id - distributed mode (-M sets -Z and disables trimming)\n"
211 " see docs/fuzzing_in_depth.md#c-using-multiple-cores\n"
212 " for effective recommendations for parallel fuzzing.\n"
213 " -F path - sync to a foreign fuzzer queue directory (requires "
214 "-M, can\n"
215 " be specified up to %u times)\n"
216 // " -d - skip deterministic fuzzing in -M mode\n"
217 " -T text - text banner to show on the screen\n"
218 " -I command - execute this command/script when a new crash is "
219 "found\n"
220 //" -B bitmap.txt - mutate a specific test case, use the
221 // out/default/fuzz_bitmap file\n"
222 " -C - crash exploration mode (the peruvian rabbit thing)\n"
223 " -b cpu_id - bind the fuzzing process to the specified CPU core "
224 "(0-...)\n"
225 " -e ext - file extension for the fuzz test input file (if "
226 "needed)\n"
227 "\n",
228 argv0, STRATEGY_SWITCH_TIME, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE,
229 FOREIGN_SYNCS_MAX);
230
231 if (more_help > 1) {
232
233 #if defined USE_COLOR && !defined ALWAYS_COLORED
234 #define DYN_COLOR \
235 "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n"
236 #else
237 #define DYN_COLOR
238 #endif
239
240 #ifdef AFL_PERSISTENT_RECORD
241 #define PERSISTENT_MSG \
242 "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
243 "out/crashes\n"
244 #else
245 #define PERSISTENT_MSG
246 #endif
247
248 SAYF(
249 "Environment variables used:\n"
250 "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
251 "ASAN_OPTIONS: custom settings for ASAN\n"
252 " (must contain abort_on_error=1 and symbolize=0)\n"
253 "MSAN_OPTIONS: custom settings for MSAN\n"
254 " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
255 "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
256 "AFL_BENCH_JUST_ONE: run the target just once\n"
257 "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
258 "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n"
259 "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
260 "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
261 "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
262 "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
263 "AFL_DEBUG: extra debugging output for Python mode trimming\n"
264 "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
265 "AFL_DISABLE_TRIM: disable the trimming of test cases\n"
266 "AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
267 "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
268 "AFL_EXIT_ON_TIME: exit when no new coverage is found within the specified time\n"
269 "AFL_EXIT_ON_SEED_ISSUES: exit on any kind of seed issues\n"
270 "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60\n"
271 " minutes and a cycle without finds)\n"
272 "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
273 "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
274 "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in ms)\n"
275 "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
276 "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
277 "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
278 "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n"
279 " ignore those libs for coverage\n"
280 "AFL_IGNORE_SEED_PROBLEMS: skip over crashes and timeouts in the seeds instead of\n"
281 " exiting\n"
282 "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
283 "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
284 "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
285 "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n"
286 "AFL_PIZZA_MODE: 1 - enforce pizza mode, -1 - disable for April 1st,\n"
287 " 0 (default) - activate on April 1st\n"
288 "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
289 " (default: SIGKILL)\n"
290 "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
291 " (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n"
292 " set, that value will be used.\n"
293 "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
294 " the target was compiled for\n"
295 "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
296 " then they are randomly selected instead all of them being\n"
297 " used. Defaults to 200.\n"
298 "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
299 "AFL_TRY_AFFINITY: try to bind to an unused core, but don't fail if unsuccessful\n"
300 "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
301 "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
302 "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
303 "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
304 "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
305 "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n"
306 "AFL_NO_WARN_INSTABILITY: no warn about instability issues on startup calibration\n"
307 "AFL_NO_UI: switch status screen off\n"
308 "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n"
309 " Increase this value in case the crash reports are truncated.\n"
310 " Default value is 4096.\n"
311 "AFL_NYX_DISABLE_SNAPSHOT_MODE: disable snapshot mode (must be supported by the agent)\n"
312 "AFL_NYX_LOG: output NYX hprintf messages to another file\n"
313 "AFL_NYX_REUSE_SNAPSHOT: reuse an existing Nyx root snapshot\n"
314 DYN_COLOR
315
316 "AFL_PATH: path to AFL support binaries\n"
317 "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
318 "AFL_QUIET: suppress forkserver status messages\n"
319
320 PERSISTENT_MSG
321
322 "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to\n"
323 " the queue, but execute the post-processed one\n"
324 "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
325 "AFL_TARGET_ENV: pass extra environment variables to target\n"
326 "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
327 "AFL_SKIP_BIN_CHECK: skip afl compatibility checks, also disables auto map size\n"
328 "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
329 //"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
330 "AFL_STATSD: enables StatsD metrics collection\n"
331 "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n"
332 "AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
333 "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
334 " suported formats: dogstatsd, librato, signalfx, influxdb\n"
335 "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
336 "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
337 "AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
338 "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n"
339 "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
340 "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n"
341 " afl-clang-lto/afl-gcc-fast target\n"
342 "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib)\n"
343 "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a shared lib)\n"
344 "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in\n"
345 " seconds (default: 60, minimum: 1)\n"
346 "\n"
347 );
348
349 } else {
350
351 SAYF(
352 "To view also the supported environment variables of afl-fuzz please "
353 "use \"-hh\".\n\n");
354
355 }
356
357 #ifdef USE_PYTHON
358 SAYF("Compiled with %s module support, see docs/custom_mutators.md\n",
359 (char *)PYTHON_VERSION);
360 #else
361 SAYF("Compiled without Python module support.\n");
362 #endif
363
364 #ifdef AFL_PERSISTENT_RECORD
365 SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
366 #else
367 SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
368 #endif
369
370 #ifdef USEMMAP
371 SAYF("Compiled with shm_open support.\n");
372 #else
373 SAYF("Compiled with shmat support.\n");
374 #endif
375
376 #ifdef ASAN_BUILD
377 SAYF("Compiled with ASAN_BUILD.\n");
378 #endif
379
380 #ifdef NO_SPLICING
381 SAYF("Compiled with NO_SPLICING.\n");
382 #endif
383
384 #ifdef FANCY_BOXES_NO_UTF
385 SAYF("Compiled without UTF-8 support for line rendering in status screen.\n");
386 #endif
387
388 #ifdef PROFILING
389 SAYF("Compiled with PROFILING.\n");
390 #endif
391
392 #ifdef INTROSPECTION
393 SAYF("Compiled with INTROSPECTION.\n");
394 #endif
395
396 #ifdef _DEBUG
397 SAYF("Compiled with _DEBUG.\n");
398 #endif
399
400 #ifdef _AFL_DOCUMENT_MUTATIONS
401 SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
402 #endif
403
404 SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
405
406 exit(1);
407 #undef PHYTON_SUPPORT
408
409 }
410
411 #ifndef AFL_LIB
412
stricmp(char const * a,char const * b)413 static int stricmp(char const *a, char const *b) {
414
415 if (!a || !b) { FATAL("Null reference"); }
416
417 for (;; ++a, ++b) {
418
419 int d;
420 d = tolower((int)*a) - tolower((int)*b);
421 if (d != 0 || !*a) { return d; }
422
423 }
424
425 }
426
fasan_check_afl_preload(char * afl_preload)427 static void fasan_check_afl_preload(char *afl_preload) {
428
429 char first_preload[PATH_MAX + 1] = {0};
430 char *separator = strchr(afl_preload, ':');
431 size_t first_preload_len = PATH_MAX;
432 char *basename;
433 char clang_runtime_prefix[] = "libclang_rt.asan";
434
435 if (separator != NULL && (separator - afl_preload) < PATH_MAX) {
436
437 first_preload_len = separator - afl_preload;
438
439 }
440
441 strncpy(first_preload, afl_preload, first_preload_len);
442
443 basename = strrchr(first_preload, '/');
444 if (basename == NULL) {
445
446 basename = first_preload;
447
448 } else {
449
450 basename = basename + 1;
451
452 }
453
454 if (strncmp(basename, clang_runtime_prefix,
455 sizeof(clang_runtime_prefix) - 1) != 0) {
456
457 FATAL("Address Sanitizer DSO must be the first DSO in AFL_PRELOAD");
458
459 }
460
461 if (access(first_preload, R_OK) != 0) {
462
463 FATAL("Address Sanitizer DSO not found");
464
465 }
466
467 OKF("Found ASAN DSO: %s", first_preload);
468
469 }
470
471 /* Main entry point */
472
main(int argc,char ** argv_orig,char ** envp)473 int main(int argc, char **argv_orig, char **envp) {
474
475 s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;
476 u64 prev_queued = 0;
477 u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1,
478 map_size = get_map_size();
479 u8 *extras_dir[4];
480 u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
481 extras_dir_cnt = 0 /*, have_p = 0*/;
482 char *afl_preload;
483 char *frida_afl_preload = NULL;
484 char **use_argv;
485
486 struct timeval tv;
487 struct timezone tz;
488
489 doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
490
491 if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) {
492
493 printf("afl-fuzz" VERSION "\n");
494 exit(0);
495
496 }
497
498 if (argc > 1 && strcmp(argv_orig[1], "--help") == 0) {
499
500 usage(argv_orig[0], 1);
501 exit(0);
502
503 }
504
505 #if defined USE_COLOR && defined ALWAYS_COLORED
506 if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
507
508 WARNF(
509 "Setting AFL_NO_COLOR has no effect (colors are configured on at "
510 "compile time)");
511
512 }
513
514 #endif
515
516 char **argv = argv_cpy_dup(argc, argv_orig);
517
518 afl_state_t *afl = calloc(1, sizeof(afl_state_t));
519 if (!afl) { FATAL("Could not create afl state"); }
520
521 if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
522
523 afl_state_init(afl, map_size);
524 afl->debug = debug;
525 afl_fsrv_init(&afl->fsrv);
526 if (debug) { afl->fsrv.debug = true; }
527 read_afl_environment(afl, envp);
528 if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
529 exit_1 = !!afl->afl_env.afl_bench_just_one;
530
531 SAYF(cCYA "afl-fuzz" VERSION cRST
532 " based on afl by Michal Zalewski and a large online community\n");
533
534 gettimeofday(&tv, &tz);
535 rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
536
537 afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
538
539 // still available: HjJkKqruvwz
540 while ((opt = getopt(argc, argv,
541 "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
542 "T:UV:WXx:YZ")) > 0) {
543
544 switch (opt) {
545
546 case 'a':
547
548 if (!stricmp(optarg, "text") || !stricmp(optarg, "ascii") ||
549 !stricmp(optarg, "txt") || !stricmp(optarg, "asc")) {
550
551 afl->input_mode = 1;
552
553 } else if (!stricmp(optarg, "bin") || !stricmp(optarg, "binary")) {
554
555 afl->input_mode = 2;
556
557 } else if (!stricmp(optarg, "def") || !stricmp(optarg, "default")) {
558
559 afl->input_mode = 0;
560
561 } else {
562
563 FATAL("-a input mode needs to be \"text\" or \"binary\".");
564
565 }
566
567 break;
568
569 case 'P':
570 if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) {
571
572 afl->fuzz_mode = 0;
573 afl->switch_fuzz_mode = 0;
574
575 } else if (!stricmp(optarg, "exploit") ||
576
577 !stricmp(optarg, "exploitation")) {
578
579 afl->fuzz_mode = 1;
580 afl->switch_fuzz_mode = 0;
581
582 } else {
583
584 if ((afl->switch_fuzz_mode = (u32)atoi(optarg)) > INT_MAX) {
585
586 FATAL(
587 "Parameter for option -P must be \"explore\", \"exploit\" or a "
588 "number!");
589
590 } else {
591
592 afl->switch_fuzz_mode *= 1000;
593
594 }
595
596 }
597
598 break;
599
600 case 'g':
601 afl->min_length = atoi(optarg);
602 break;
603
604 case 'G':
605 afl->max_length = atoi(optarg);
606 break;
607
608 case 'Z':
609 afl->old_seed_selection = 1;
610 break;
611
612 case 'I':
613 afl->infoexec = optarg;
614 break;
615
616 case 'b': { /* bind CPU core */
617
618 if (afl->cpu_to_bind != -1) FATAL("Multiple -b options not supported");
619
620 if (sscanf(optarg, "%d", &afl->cpu_to_bind) < 0) {
621
622 FATAL("Bad syntax used for -b");
623
624 }
625
626 break;
627
628 }
629
630 case 'c': {
631
632 if (strcmp(optarg, "-") == 0) {
633
634 if (afl->shm.cmplog_mode) {
635
636 ACTF("Disabling cmplog again because of '-c -'.");
637 afl->shm.cmplog_mode = 0;
638 afl->cmplog_binary = NULL;
639
640 }
641
642 } else {
643
644 afl->shm.cmplog_mode = 1;
645 afl->cmplog_binary = ck_strdup(optarg);
646
647 }
648
649 break;
650
651 }
652
653 case 's': {
654
655 if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
656 rand_set_seed(afl, strtoul(optarg, 0L, 10));
657 afl->fixed_seed = 1;
658 break;
659
660 }
661
662 case 'p': /* Power schedule */
663
664 if (!stricmp(optarg, "fast")) {
665
666 afl->schedule = FAST;
667
668 } else if (!stricmp(optarg, "coe")) {
669
670 afl->schedule = COE;
671
672 } else if (!stricmp(optarg, "exploit")) {
673
674 afl->schedule = EXPLOIT;
675
676 } else if (!stricmp(optarg, "lin")) {
677
678 afl->schedule = LIN;
679
680 } else if (!stricmp(optarg, "quad")) {
681
682 afl->schedule = QUAD;
683
684 } else if (!stricmp(optarg, "mopt") || !stricmp(optarg, "mmopt")) {
685
686 afl->schedule = MMOPT;
687
688 } else if (!stricmp(optarg, "rare")) {
689
690 afl->schedule = RARE;
691
692 } else if (!stricmp(optarg, "explore") || !stricmp(optarg, "afl") ||
693
694 !stricmp(optarg, "default") ||
695
696 !stricmp(optarg, "normal")) {
697
698 afl->schedule = EXPLORE;
699
700 } else if (!stricmp(optarg, "seek")) {
701
702 afl->schedule = SEEK;
703
704 } else {
705
706 FATAL("Unknown -p power schedule");
707
708 }
709
710 // have_p = 1;
711
712 break;
713
714 case 'e':
715
716 if (afl->file_extension) { FATAL("Multiple -e options not supported"); }
717
718 afl->file_extension = optarg;
719
720 break;
721
722 case 'i': /* input dir */
723
724 if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
725 if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
726 afl->in_dir = optarg;
727
728 if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
729
730 break;
731
732 case 'o': /* output dir */
733
734 if (afl->out_dir) { FATAL("Multiple -o options not supported"); }
735 afl->out_dir = optarg;
736 break;
737
738 case 'M': { /* main sync ID */
739
740 u8 *c;
741
742 if (afl->non_instrumented_mode) {
743
744 FATAL("-M is not supported in non-instrumented mode");
745
746 }
747
748 if (afl->fsrv.cs_mode) {
749
750 FATAL("-M is not supported in ARM CoreSight mode");
751
752 }
753
754 if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
755
756 /* sanity check for argument: should not begin with '-' (possible
757 * option) */
758 if (optarg && *optarg == '-') {
759
760 FATAL(
761 "argument for -M started with a dash '-', which is used for "
762 "options");
763
764 }
765
766 afl->sync_id = ck_strdup(optarg);
767 afl->old_seed_selection = 1; // force old queue walking seed selection
768 afl->disable_trim = 1; // disable trimming
769
770 if ((c = strchr(afl->sync_id, ':'))) {
771
772 *c = 0;
773
774 if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) !=
775 2 ||
776 !afl->main_node_id || !afl->main_node_max ||
777 afl->main_node_id > afl->main_node_max ||
778 afl->main_node_max > 1000000) {
779
780 FATAL("Bogus main node ID passed to -M");
781
782 }
783
784 }
785
786 afl->is_main_node = 1;
787
788 }
789
790 break;
791
792 case 'S': /* secondary sync id */
793
794 if (afl->non_instrumented_mode) {
795
796 FATAL("-S is not supported in non-instrumented mode");
797
798 }
799
800 if (afl->fsrv.cs_mode) {
801
802 FATAL("-S is not supported in ARM CoreSight mode");
803
804 }
805
806 if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
807
808 /* sanity check for argument: should not begin with '-' (possible
809 * option) */
810 if (optarg && *optarg == '-') {
811
812 FATAL(
813 "argument for -M started with a dash '-', which is used for "
814 "options");
815
816 }
817
818 afl->sync_id = ck_strdup(optarg);
819 afl->is_secondary_node = 1;
820 break;
821
822 case 'F': /* foreign sync dir */
823
824 if (!optarg) { FATAL("Missing path for -F"); }
825 if (!afl->is_main_node) {
826
827 FATAL(
828 "Option -F can only be specified after the -M option for the "
829 "main fuzzer of a fuzzing campaign");
830
831 }
832
833 if (afl->foreign_sync_cnt >= FOREIGN_SYNCS_MAX) {
834
835 FATAL("Maximum %u entried of -F option can be specified",
836 FOREIGN_SYNCS_MAX);
837
838 }
839
840 afl->foreign_syncs[afl->foreign_sync_cnt].dir = optarg;
841 while (afl->foreign_syncs[afl->foreign_sync_cnt]
842 .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) -
843 1] == '/') {
844
845 afl->foreign_syncs[afl->foreign_sync_cnt]
846 .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) - 1] =
847 0;
848
849 }
850
851 afl->foreign_sync_cnt++;
852 break;
853
854 case 'f': /* target file */
855
856 if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); }
857
858 afl->fsrv.out_file = ck_strdup(optarg);
859 afl->fsrv.use_stdin = 0;
860 default_output = 0;
861 break;
862
863 case 'x': /* dictionary */
864
865 if (extras_dir_cnt >= 4) {
866
867 FATAL("More than four -x options are not supported");
868
869 }
870
871 extras_dir[extras_dir_cnt++] = optarg;
872 break;
873
874 case 't': { /* timeout */
875
876 u8 suffix = 0;
877
878 if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
879
880 if (!optarg ||
881 sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
882 optarg[0] == '-') {
883
884 FATAL("Bad syntax used for -t");
885
886 }
887
888 if (afl->fsrv.exec_tmout < 5) { FATAL("Dangerously low value of -t"); }
889
890 if (suffix == '+') {
891
892 afl->timeout_given = 2;
893
894 } else {
895
896 afl->timeout_given = 1;
897
898 }
899
900 break;
901
902 }
903
904 case 'm': { /* mem limit */
905
906 u8 suffix = 'M';
907
908 if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
909 mem_limit_given = 1;
910
911 if (!optarg) { FATAL("Wrong usage of -m"); }
912
913 if (!strcmp(optarg, "none")) {
914
915 afl->fsrv.mem_limit = 0;
916 break;
917
918 }
919
920 if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 ||
921 optarg[0] == '-') {
922
923 FATAL("Bad syntax used for -m");
924
925 }
926
927 switch (suffix) {
928
929 case 'T':
930 afl->fsrv.mem_limit *= 1024 * 1024;
931 break;
932 case 'G':
933 afl->fsrv.mem_limit *= 1024;
934 break;
935 case 'k':
936 afl->fsrv.mem_limit /= 1024;
937 break;
938 case 'M':
939 break;
940
941 default:
942 FATAL("Unsupported suffix or bad syntax for -m");
943
944 }
945
946 if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); }
947
948 if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) {
949
950 FATAL("Value of -m out of range on 32-bit systems");
951
952 }
953
954 }
955
956 break;
957
958 case 'D': /* partial deterministic */
959
960 afl->skip_deterministic = 0;
961 break;
962
963 case 'd': /* no deterministic */
964
965 // this is the default and currently a lot of infrastructure enforces
966 // it (e.g. clusterfuzz, fuzzbench) based on that this feature
967 // originally was bad performance wise. We now have a better
968 // implementation, hence if it is activated, we do not want to
969 // deactivate it by such setups.
970
971 // afl->skip_deterministic = 1;
972 break;
973
974 case 'B': /* load bitmap */
975
976 /* This is a secret undocumented option! It is useful if you find
977 an interesting test case during a normal fuzzing process, and want
978 to mutate it without rediscovering any of the test cases already
979 found during an earlier run.
980
981 To use this mode, you need to point -B to the fuzz_bitmap produced
982 by an earlier run for the exact same binary... and that's it.
983
984 I only used this once or twice to get variants of a particular
985 file, so I'm not making this an official setting. */
986
987 if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); }
988
989 afl->in_bitmap = optarg;
990 break;
991
992 case 'C': /* crash mode */
993
994 if (afl->crash_mode) { FATAL("Multiple -C options not supported"); }
995 afl->crash_mode = FSRV_RUN_CRASH;
996 break;
997
998 case 'n': /* dumb mode */
999
1000 if (afl->is_main_node || afl->is_secondary_node) {
1001
1002 FATAL("Non instrumented mode is not supported with -M / -S");
1003
1004 }
1005
1006 if (afl->non_instrumented_mode) {
1007
1008 FATAL("Multiple -n options not supported");
1009
1010 }
1011
1012 if (afl->afl_env.afl_dumb_forksrv) {
1013
1014 afl->non_instrumented_mode = 2;
1015
1016 } else {
1017
1018 afl->non_instrumented_mode = 1;
1019
1020 }
1021
1022 break;
1023
1024 case 'T': /* banner */
1025
1026 if (afl->use_banner) { FATAL("Multiple -T options not supported"); }
1027 afl->use_banner = optarg;
1028 break;
1029
1030 #ifdef __linux__
1031 case 'X': /* NYX mode */
1032
1033 if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
1034
1035 afl->fsrv.nyx_parent = true;
1036 afl->fsrv.nyx_standalone = true;
1037 afl->fsrv.nyx_mode = 1;
1038 afl->fsrv.nyx_id = 0;
1039
1040 break;
1041
1042 case 'Y': /* NYX distributed mode */
1043 if (afl->fsrv.nyx_mode) { FATAL("Multiple -Y options not supported"); }
1044
1045 afl->fsrv.nyx_mode = 1;
1046
1047 break;
1048 #else
1049 case 'X':
1050 case 'Y':
1051 FATAL("Nyx mode is only availabe on linux...");
1052 break;
1053 #endif
1054 case 'A': /* CoreSight mode */
1055
1056 #if !defined(__aarch64__) || !defined(__linux__)
1057 FATAL("-A option is not supported on this platform");
1058 #endif
1059
1060 if (afl->is_main_node || afl->is_secondary_node) {
1061
1062 FATAL("ARM CoreSight mode is not supported with -M / -S");
1063
1064 }
1065
1066 if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); }
1067
1068 afl->fsrv.cs_mode = 1;
1069
1070 break;
1071
1072 case 'O': /* FRIDA mode */
1073
1074 if (afl->fsrv.frida_mode) {
1075
1076 FATAL("Multiple -O options not supported");
1077
1078 }
1079
1080 afl->fsrv.frida_mode = 1;
1081 if (get_afl_env("AFL_USE_FASAN")) { afl->fsrv.frida_asan = 1; }
1082
1083 break;
1084
1085 case 'Q': /* QEMU mode */
1086
1087 if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
1088
1089 afl->fsrv.qemu_mode = 1;
1090
1091 if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
1092
1093 break;
1094
1095 case 'N': /* Unicorn mode */
1096
1097 if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
1098 afl->fsrv.no_unlink = (afl->no_unlink = true);
1099
1100 break;
1101
1102 case 'U': /* Unicorn mode */
1103
1104 if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
1105 afl->unicorn_mode = 1;
1106
1107 if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; }
1108
1109 break;
1110
1111 case 'W': /* Wine+QEMU mode */
1112
1113 if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
1114 afl->fsrv.qemu_mode = 1;
1115 afl->use_wine = 1;
1116
1117 if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
1118
1119 break;
1120
1121 case 'V': {
1122
1123 afl->most_time_key = 1;
1124 if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 ||
1125 optarg[0] == '-') {
1126
1127 FATAL("Bad syntax used for -V");
1128
1129 }
1130
1131 } break;
1132
1133 case 'E': {
1134
1135 afl->most_execs_key = 1;
1136 if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 ||
1137 optarg[0] == '-') {
1138
1139 FATAL("Bad syntax used for -E");
1140
1141 }
1142
1143 } break;
1144
1145 case 'l': {
1146
1147 if (!optarg) { FATAL("missing parameter for 'l'"); }
1148 char *c = optarg;
1149 while (*c) {
1150
1151 switch (*c) {
1152
1153 case '0':
1154 case '1':
1155 afl->cmplog_lvl = 1;
1156 break;
1157 case '2':
1158 afl->cmplog_lvl = 2;
1159 break;
1160 case '3':
1161 afl->cmplog_lvl = 3;
1162
1163 if (!afl->disable_trim) {
1164
1165 ACTF("Deactivating trimming due CMPLOG level 3");
1166 afl->disable_trim = 1;
1167
1168 }
1169
1170 break;
1171 case 'a':
1172 case 'A':
1173 afl->cmplog_enable_arith = 1;
1174 break;
1175 case 's':
1176 case 'S':
1177 afl->cmplog_enable_scale = 1;
1178 break;
1179 case 't':
1180 case 'T':
1181 afl->cmplog_enable_transform = 1;
1182 break;
1183 case 'x':
1184 case 'X':
1185 afl->cmplog_enable_xtreme_transform = 1;
1186 break;
1187 case 'r':
1188 case 'R':
1189 afl->cmplog_random_colorization = 1;
1190 break;
1191 default:
1192 FATAL("Unknown option value '%c' in -l %s", *c, optarg);
1193
1194 }
1195
1196 ++c;
1197
1198 }
1199
1200 if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
1201
1202 afl->cmplog_max_filesize = MAX_FILE;
1203
1204 }
1205
1206 } break;
1207
1208 case 'L': { /* MOpt mode */
1209
1210 if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); }
1211
1212 afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT;
1213
1214 if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) {
1215
1216 FATAL("Bad syntax used for -L");
1217
1218 }
1219
1220 if (afl->limit_time_puppet == -1) {
1221
1222 afl->limit_time_sig = -1;
1223 afl->limit_time_puppet = 0;
1224
1225 } else if (afl->limit_time_puppet < 0) {
1226
1227 FATAL("-L value must be between 0 and 2000000 or -1");
1228
1229 } else {
1230
1231 afl->limit_time_sig = 1;
1232
1233 }
1234
1235 u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
1236
1237 if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
1238
1239 FATAL("limit_time overflow");
1240
1241 }
1242
1243 afl->limit_time_puppet = limit_time_puppet2;
1244 afl->swarm_now = 0;
1245 if (afl->limit_time_puppet == 0) { afl->key_puppet = 1; }
1246
1247 int j;
1248 int tmp_swarm = 0;
1249
1250 if (afl->g_now > afl->g_max) { afl->g_now = 0; }
1251 afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) /
1252 (afl->g_max) +
1253 afl->w_end;
1254
1255 for (tmp_swarm = 0; tmp_swarm < swarm_num; ++tmp_swarm) {
1256
1257 double total_puppet_temp = 0.0;
1258 afl->swarm_fitness[tmp_swarm] = 0.0;
1259
1260 for (j = 0; j < operator_num; ++j) {
1261
1262 afl->stage_finds_puppet[tmp_swarm][j] = 0;
1263 afl->probability_now[tmp_swarm][j] = 0.0;
1264 afl->x_now[tmp_swarm][j] =
1265 ((double)(random() % 7000) * 0.0001 + 0.1);
1266 total_puppet_temp += afl->x_now[tmp_swarm][j];
1267 afl->v_now[tmp_swarm][j] = 0.1;
1268 afl->L_best[tmp_swarm][j] = 0.5;
1269 afl->G_best[j] = 0.5;
1270 afl->eff_best[tmp_swarm][j] = 0.0;
1271
1272 }
1273
1274 for (j = 0; j < operator_num; ++j) {
1275
1276 afl->stage_cycles_puppet_v2[tmp_swarm][j] =
1277 afl->stage_cycles_puppet[tmp_swarm][j];
1278 afl->stage_finds_puppet_v2[tmp_swarm][j] =
1279 afl->stage_finds_puppet[tmp_swarm][j];
1280 afl->x_now[tmp_swarm][j] =
1281 afl->x_now[tmp_swarm][j] / total_puppet_temp;
1282
1283 }
1284
1285 double x_temp = 0.0;
1286
1287 for (j = 0; j < operator_num; ++j) {
1288
1289 afl->probability_now[tmp_swarm][j] = 0.0;
1290 afl->v_now[tmp_swarm][j] =
1291 afl->w_now * afl->v_now[tmp_swarm][j] +
1292 RAND_C *
1293 (afl->L_best[tmp_swarm][j] - afl->x_now[tmp_swarm][j]) +
1294 RAND_C * (afl->G_best[j] - afl->x_now[tmp_swarm][j]);
1295
1296 afl->x_now[tmp_swarm][j] += afl->v_now[tmp_swarm][j];
1297
1298 if (afl->x_now[tmp_swarm][j] > v_max) {
1299
1300 afl->x_now[tmp_swarm][j] = v_max;
1301
1302 } else if (afl->x_now[tmp_swarm][j] < v_min) {
1303
1304 afl->x_now[tmp_swarm][j] = v_min;
1305
1306 }
1307
1308 x_temp += afl->x_now[tmp_swarm][j];
1309
1310 }
1311
1312 for (j = 0; j < operator_num; ++j) {
1313
1314 afl->x_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j] / x_temp;
1315 if (likely(j != 0)) {
1316
1317 afl->probability_now[tmp_swarm][j] =
1318 afl->probability_now[tmp_swarm][j - 1] +
1319 afl->x_now[tmp_swarm][j];
1320
1321 } else {
1322
1323 afl->probability_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j];
1324
1325 }
1326
1327 }
1328
1329 if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 ||
1330 afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) {
1331
1332 FATAL("ERROR probability");
1333
1334 }
1335
1336 }
1337
1338 for (j = 0; j < operator_num; ++j) {
1339
1340 afl->core_operator_finds_puppet[j] = 0;
1341 afl->core_operator_finds_puppet_v2[j] = 0;
1342 afl->core_operator_cycles_puppet[j] = 0;
1343 afl->core_operator_cycles_puppet_v2[j] = 0;
1344 afl->core_operator_cycles_puppet_v3[j] = 0;
1345
1346 }
1347
1348 WARNF(
1349 "Note that the MOpt mode is not maintained and is not as effective "
1350 "as normal havoc mode.");
1351
1352 } break;
1353
1354 case 'h':
1355 show_help++;
1356 break; // not needed
1357
1358 case 'R':
1359
1360 FATAL(
1361 "Radamsa is now a custom mutator, please use that "
1362 "(custom_mutators/radamsa/).");
1363
1364 break;
1365
1366 default:
1367 if (!show_help) { show_help = 1; }
1368
1369 }
1370
1371 }
1372
1373 if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) {
1374
1375 FATAL("-M/-S name 'addseeds' is a reserved name, choose something else");
1376
1377 }
1378
1379 if (afl->is_main_node == 1 && afl->schedule != FAST &&
1380 afl->schedule != EXPLORE) {
1381
1382 FATAL("-M is compatible only with fast and explore -p power schedules");
1383
1384 }
1385
1386 if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
1387
1388 usage(argv[0], show_help);
1389
1390 }
1391
1392 if (unlikely(afl->afl_env.afl_persistent_record)) {
1393
1394 #ifdef AFL_PERSISTENT_RECORD
1395
1396 afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
1397
1398 if (afl->fsrv.persistent_record < 2) {
1399
1400 FATAL(
1401 "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is "
1402 "100 or 1000.");
1403
1404 }
1405
1406 #else
1407
1408 FATAL(
1409 "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in "
1410 "config.h!");
1411
1412 #endif
1413
1414 }
1415
1416 if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
1417
1418 OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
1419 "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
1420 OKF("AFL++ is open source, get it at "
1421 "https://github.com/AFLplusplus/AFLplusplus");
1422 OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
1423
1424 #ifdef __linux__
1425 if (afl->fsrv.nyx_mode) {
1426
1427 OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
1428 OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
1429
1430 }
1431
1432 #endif
1433
1434 // silently disable deterministic mutation if custom mutators are used
1435 if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
1436
1437 afl->skip_deterministic = 1;
1438
1439 }
1440
1441 if (afl->fixed_seed) {
1442
1443 OKF("Running with fixed seed: %u", (u32)afl->init_seed);
1444
1445 }
1446
1447 #if defined(__SANITIZE_ADDRESS__)
1448 if (afl->fsrv.mem_limit) {
1449
1450 WARNF("in the ASAN build we disable all memory limits");
1451 afl->fsrv.mem_limit = 0;
1452
1453 }
1454
1455 #endif
1456
1457 configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
1458 afl->afl_env.afl_fsrv_kill_signal,
1459 (afl->fsrv.qemu_mode || afl->unicorn_mode
1460 #ifdef __linux__
1461 || afl->fsrv.nyx_mode
1462 #endif
1463 )
1464 ? SIGKILL
1465 : SIGTERM);
1466
1467 setup_signal_handlers();
1468 check_asan_opts(afl);
1469
1470 afl->power_name = power_names[afl->schedule];
1471
1472 if (!afl->non_instrumented_mode && !afl->sync_id) {
1473
1474 auto_sync = 1;
1475 afl->sync_id = ck_strdup("default");
1476 afl->is_secondary_node = 1;
1477 OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id);
1478
1479 }
1480
1481 #ifdef __linux__
1482 if (afl->fsrv.nyx_mode) {
1483
1484 if (afl->fsrv.nyx_standalone && strcmp(afl->sync_id, "default") != 0) {
1485
1486 FATAL(
1487 "distributed fuzzing is not supported in this Nyx mode (use -Y "
1488 "instead)");
1489
1490 }
1491
1492 if (!afl->fsrv.nyx_standalone) {
1493
1494 if (afl->is_main_node) {
1495
1496 if (strcmp("0", afl->sync_id) != 0) {
1497
1498 FATAL(
1499 "for Nyx -Y mode, the Main (-M) parameter has to be set to 0 (-M "
1500 "0)");
1501
1502 }
1503
1504 afl->fsrv.nyx_parent = true;
1505 afl->fsrv.nyx_id = 0;
1506
1507 }
1508
1509 if (afl->is_secondary_node) {
1510
1511 long nyx_id = strtol(afl->sync_id, NULL, 10);
1512
1513 if (nyx_id == 0 || nyx_id == LONG_MAX) {
1514
1515 FATAL(
1516 "for Nyx -Y mode, the Secondary (-S) parameter has to be a "
1517 "numeric value and >= 1 (e.g. -S 1)");
1518
1519 }
1520
1521 afl->fsrv.nyx_id = nyx_id;
1522
1523 }
1524
1525 }
1526
1527 }
1528
1529 #endif
1530
1531 if (afl->sync_id) {
1532
1533 if (strlen(afl->sync_id) > 50) {
1534
1535 FATAL("sync_id max length is 50 characters");
1536
1537 }
1538
1539 fix_up_sync(afl);
1540
1541 }
1542
1543 if (!strcmp(afl->in_dir, afl->out_dir)) {
1544
1545 FATAL("Input and output directories can't be the same");
1546
1547 }
1548
1549 if (afl->non_instrumented_mode) {
1550
1551 if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
1552 if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
1553 if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
1554 if (afl->fsrv.cs_mode) { FATAL("-A and -n are mutually exclusive"); }
1555 if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
1556
1557 }
1558
1559 setenv("__AFL_OUT_DIR", afl->out_dir, 1);
1560
1561 if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
1562
1563 if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
1564
1565 FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive");
1566
1567 }
1568
1569 if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
1570
1571 if (!afl->use_banner) { afl->use_banner = argv[optind]; }
1572
1573 if (afl->shm.cmplog_mode && strcmp("0", afl->cmplog_binary) == 0) {
1574
1575 afl->cmplog_binary = strdup(argv[optind]);
1576
1577 }
1578
1579 if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
1580
1581 WARNF(cLRD
1582 "Target binary called without a prefixed path, make sure you are "
1583 "fuzzing the right binary: " cRST "%s",
1584 argv[optind]);
1585
1586 }
1587
1588 ACTF("Getting to work...");
1589
1590 switch (afl->schedule) {
1591
1592 case FAST:
1593 OKF("Using exponential power schedule (FAST)");
1594 break;
1595 case COE:
1596 OKF("Using cut-off exponential power schedule (COE)");
1597 break;
1598 case EXPLOIT:
1599 OKF("Using exploitation-based constant power schedule (EXPLOIT)");
1600 break;
1601 case LIN:
1602 OKF("Using linear power schedule (LIN)");
1603 break;
1604 case QUAD:
1605 OKF("Using quadratic power schedule (QUAD)");
1606 break;
1607 case MMOPT:
1608 OKF("Using modified MOpt power schedule (MMOPT)");
1609 break;
1610 case RARE:
1611 OKF("Using rare edge focus power schedule (RARE)");
1612 break;
1613 case SEEK:
1614 OKF("Using seek power schedule (SEEK)");
1615 break;
1616 case EXPLORE:
1617 OKF("Using exploration-based constant power schedule (EXPLORE)");
1618 break;
1619 default:
1620 FATAL("Unknown power schedule");
1621 break;
1622
1623 }
1624
1625 if (afl->shm.cmplog_mode) { OKF("CmpLog level: %u", afl->cmplog_lvl); }
1626
1627 /* Dynamically allocate memory for AFLFast schedules */
1628 if (afl->schedule >= FAST && afl->schedule <= RARE) {
1629
1630 afl->n_fuzz = ck_alloc(N_FUZZ_SIZE * sizeof(u32));
1631
1632 }
1633
1634 if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
1635 if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
1636 if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
1637 if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
1638 if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
1639
1640 if (afl->afl_env.afl_autoresume) {
1641
1642 afl->autoresume = 1;
1643 if (afl->in_place_resume) {
1644
1645 SAYF("AFL_AUTORESUME has no effect for '-i -'");
1646
1647 }
1648
1649 }
1650
1651 if (afl->afl_env.afl_hang_tmout) {
1652
1653 s32 hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
1654 if (hang_tmout < 1) { FATAL("Invalid value for AFL_HANG_TMOUT"); }
1655 afl->hang_tmout = (u32)hang_tmout;
1656
1657 }
1658
1659 if (afl->afl_env.afl_exit_on_time) {
1660
1661 u64 exit_on_time = atoi(afl->afl_env.afl_exit_on_time);
1662 afl->exit_on_time = (u64)exit_on_time * 1000;
1663
1664 }
1665
1666 if (afl->afl_env.afl_max_det_extras) {
1667
1668 s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
1669 if (max_det_extras < 1) { FATAL("Invalid value for AFL_MAX_DET_EXTRAS"); }
1670 afl->max_det_extras = (u32)max_det_extras;
1671
1672 } else {
1673
1674 afl->max_det_extras = MAX_DET_EXTRAS;
1675
1676 }
1677
1678 if (afl->afl_env.afl_testcache_size) {
1679
1680 afl->q_testcase_max_cache_size =
1681 (u64)atoi(afl->afl_env.afl_testcache_size) * 1048576;
1682
1683 }
1684
1685 if (afl->afl_env.afl_testcache_entries) {
1686
1687 afl->q_testcase_max_cache_entries =
1688 (u32)atoi(afl->afl_env.afl_testcache_entries);
1689
1690 // user_set_cache = 1;
1691
1692 }
1693
1694 if (!afl->afl_env.afl_testcache_size || !afl->afl_env.afl_testcache_entries) {
1695
1696 afl->afl_env.afl_testcache_entries = 0;
1697 afl->afl_env.afl_testcache_size = 0;
1698
1699 }
1700
1701 if (!afl->q_testcase_max_cache_size) {
1702
1703 ACTF(
1704 "No testcache was configured. it is recommended to use a testcache, it "
1705 "improves performance: set AFL_TESTCACHE_SIZE=(value in MB)");
1706
1707 } else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) {
1708
1709 FATAL("AFL_TESTCACHE_SIZE must be set to %ld or more, or 0 to disable",
1710 (2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576
1711 : 1 + ((2 * MAX_FILE) / 1048576));
1712
1713 } else {
1714
1715 OKF("Enabled testcache with %llu MB",
1716 afl->q_testcase_max_cache_size / 1048576);
1717
1718 }
1719
1720 if (afl->afl_env.afl_forksrv_init_tmout) {
1721
1722 afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout);
1723 if (!afl->fsrv.init_tmout) {
1724
1725 FATAL("Invalid value of AFL_FORKSRV_INIT_TMOUT");
1726
1727 }
1728
1729 } else {
1730
1731 afl->fsrv.init_tmout = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
1732
1733 }
1734
1735 if (afl->afl_env.afl_crash_exitcode) {
1736
1737 long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
1738 if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
1739 exitcode < -127 || exitcode > 128) {
1740
1741 FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
1742 afl->afl_env.afl_crash_exitcode);
1743
1744 }
1745
1746 afl->fsrv.uses_crash_exitcode = true;
1747 // WEXITSTATUS is 8 bit unsigned
1748 afl->fsrv.crash_exitcode = (u8)exitcode;
1749
1750 }
1751
1752 if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
1753
1754 FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
1755
1756 }
1757
1758 // Marker: ADD_TO_INJECTIONS
1759 if (getenv("AFL_LLVM_INJECTIONS_ALL") || getenv("AFL_LLVM_INJECTIONS_SQL") ||
1760 getenv("AFL_LLVM_INJECTIONS_LDAP") || getenv("AFL_LLVM_INJECTIONS_XSS")) {
1761
1762 OKF("Adding injection tokens to dictionary.");
1763 if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1764 getenv("AFL_LLVM_INJECTIONS_SQL")) {
1765
1766 add_extra(afl, "'\"\"'", 4);
1767
1768 }
1769
1770 if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1771 getenv("AFL_LLVM_INJECTIONS_LDAP")) {
1772
1773 add_extra(afl, "*)(1=*))(|", 10);
1774
1775 }
1776
1777 if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1778 getenv("AFL_LLVM_INJECTIONS_XSS")) {
1779
1780 add_extra(afl, "1\"><\"", 5);
1781
1782 }
1783
1784 }
1785
1786 OKF("Generating fuzz data with a length of min=%u max=%u", afl->min_length,
1787 afl->max_length);
1788 u32 min_alloc = MAX(64U, afl->min_length);
1789 afl_realloc(AFL_BUF_PARAM(in_scratch), min_alloc);
1790 afl_realloc(AFL_BUF_PARAM(in), min_alloc);
1791 afl_realloc(AFL_BUF_PARAM(out_scratch), min_alloc);
1792 afl_realloc(AFL_BUF_PARAM(out), min_alloc);
1793 afl_realloc(AFL_BUF_PARAM(eff), min_alloc);
1794 afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
1795
1796 afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
1797
1798 #ifdef __linux__
1799 if (!afl->fsrv.nyx_mode) {
1800
1801 check_crash_handling();
1802 check_cpu_governor(afl);
1803
1804 } else {
1805
1806 u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
1807 afl->fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
1808 if (afl->fsrv.nyx_handlers == NULL) {
1809
1810 FATAL("failed to initialize libnyx.so...");
1811
1812 }
1813
1814 }
1815
1816 #else
1817 check_crash_handling();
1818 check_cpu_governor(afl);
1819 #endif
1820
1821 #ifdef __APPLE__
1822 setenv("DYLD_NO_PIE", "1", 0);
1823 #endif
1824
1825 if (getenv("LD_PRELOAD")) {
1826
1827 WARNF(
1828 "LD_PRELOAD is set, are you sure that is what you want to do "
1829 "instead of using AFL_PRELOAD?");
1830
1831 }
1832
1833 if (afl->afl_env.afl_preload) {
1834
1835 if (afl->fsrv.qemu_mode) {
1836
1837 /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
1838
1839 } else if (afl->fsrv.frida_mode) {
1840
1841 afl_preload = getenv("AFL_PRELOAD");
1842 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1843 OKF("Injecting %s ...", frida_binary);
1844 if (afl_preload) {
1845
1846 if (afl->fsrv.frida_asan) {
1847
1848 OKF("Using Frida Address Sanitizer Mode");
1849
1850 fasan_check_afl_preload(afl_preload);
1851
1852 setenv("ASAN_OPTIONS", "detect_leaks=false", 1);
1853
1854 }
1855
1856 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1857 OKF("Injecting %s ...", frida_binary);
1858 frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
1859
1860 ck_free(frida_binary);
1861
1862 setenv("LD_PRELOAD", frida_afl_preload, 1);
1863 setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
1864
1865 }
1866
1867 } else {
1868
1869 /* CoreSight mode uses the default behavior. */
1870
1871 setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
1872 setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
1873
1874 }
1875
1876 } else if (afl->fsrv.frida_mode) {
1877
1878 if (afl->fsrv.frida_asan) {
1879
1880 OKF("Using Frida Address Sanitizer Mode");
1881 FATAL(
1882 "Address Sanitizer DSO must be loaded using AFL_PRELOAD in Frida "
1883 "Address Sanitizer Mode");
1884
1885 } else {
1886
1887 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1888 OKF("Injecting %s ...", frida_binary);
1889 setenv("LD_PRELOAD", frida_binary, 1);
1890 setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
1891 ck_free(frida_binary);
1892
1893 }
1894
1895 }
1896
1897 if (getenv("AFL_LD_PRELOAD")) {
1898
1899 FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
1900
1901 }
1902
1903 if (afl->afl_env.afl_target_env &&
1904 !extract_and_set_env(afl->afl_env.afl_target_env)) {
1905
1906 FATAL("Bad value of AFL_TARGET_ENV");
1907
1908 }
1909
1910 save_cmdline(afl, argc, argv);
1911 check_if_tty(afl);
1912 if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
1913
1914 get_core_count(afl);
1915
1916 atexit(at_exit);
1917
1918 setup_dirs_fds(afl);
1919
1920 #ifdef HAVE_AFFINITY
1921 bind_to_free_cpu(afl);
1922 #endif /* HAVE_AFFINITY */
1923
1924 #ifdef __linux__
1925 if (afl->fsrv.nyx_mode && afl->fsrv.nyx_bind_cpu_id == 0xFFFFFFFF) {
1926
1927 afl->fsrv.nyx_bind_cpu_id = 0;
1928
1929 }
1930
1931 #endif
1932
1933 #ifdef __HAIKU__
1934 /* Prioritizes performance over power saving */
1935 set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY);
1936 #endif
1937
1938 #ifdef __APPLE__
1939 if (pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0) != 0) {
1940
1941 WARNF("general thread priority settings failed");
1942
1943 }
1944
1945 #endif
1946
1947 init_count_class16();
1948
1949 if (afl->is_main_node && check_main_node_exists(afl) == 1) {
1950
1951 WARNF("it is wasteful to run more than one main node!");
1952 sleep(1);
1953
1954 } else if (!auto_sync && afl->is_secondary_node &&
1955
1956 check_main_node_exists(afl) == 0) {
1957
1958 WARNF(
1959 "no -M main node found. It is recommended to run exactly one main "
1960 "instance.");
1961 sleep(1);
1962
1963 }
1964
1965 #ifdef RAND_TEST_VALUES
1966 u32 counter;
1967 for (counter = 0; counter < 100000; counter++)
1968 printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
1969 #endif
1970
1971 if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
1972
1973 setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
1974
1975 }
1976
1977 if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
1978
1979 setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
1980
1981 }
1982
1983 if (!getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) {
1984
1985 u8 envbuf[8096] = "", tmpbuf[8096] = "";
1986 for (s32 i = optind + 1; i < argc; ++i) {
1987
1988 strcpy(tmpbuf, envbuf);
1989 if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
1990 !strchr(argv[i], '\'')) {
1991
1992 if (!strchr(argv[i], '\'')) {
1993
1994 snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
1995
1996 } else {
1997
1998 snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
1999
2000 }
2001
2002 } else {
2003
2004 snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
2005
2006 }
2007
2008 }
2009
2010 setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
2011
2012 }
2013
2014 if (!getenv("AFL_CUSTOM_INFO_OUT")) {
2015
2016 setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
2017
2018 }
2019
2020 setup_custom_mutators(afl);
2021
2022 if (afl->afl_env.afl_custom_mutator_only) {
2023
2024 if (!afl->custom_mutators_count) {
2025
2026 if (afl->shm.cmplog_mode) {
2027
2028 WARNF(
2029 "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
2030 "pointless and only allowed now to allow experiments with CMPLOG.");
2031
2032 } else {
2033
2034 FATAL(
2035 "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
2036
2037 }
2038
2039 }
2040
2041 /* This ensures we don't proceed to havoc/splice */
2042 afl->custom_only = 1;
2043
2044 /* Ensure we also skip all deterministic steps */
2045 afl->skip_deterministic = 1;
2046
2047 }
2048
2049 if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
2050
2051 if (afl->custom_only) {
2052
2053 FATAL("Custom mutators are incompatible with MOpt (-L)");
2054
2055 }
2056
2057 u32 custom_fuzz = 0;
2058 LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
2059
2060 if (el->afl_custom_fuzz) { custom_fuzz = 1; }
2061
2062 });
2063
2064 if (custom_fuzz) {
2065
2066 WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
2067
2068 }
2069
2070 }
2071
2072 write_setup_file(afl, argc, argv);
2073
2074 setup_cmdline_file(afl, argv + optind);
2075
2076 read_testcases(afl, NULL);
2077 // read_foreign_testcases(afl, 1); for the moment dont do this
2078 OKF("Loaded a total of %u seeds.", afl->queued_items);
2079
2080 pivot_inputs(afl);
2081
2082 if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
2083
2084 if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
2085 !afl->in_place_resume) {
2086
2087 char tmpfile[PATH_MAX];
2088
2089 if (afl->file_extension) {
2090
2091 snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
2092 afl->file_extension);
2093
2094 } else {
2095
2096 snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
2097
2098 }
2099
2100 /* there is still a race condition here, but well ... */
2101 if (access(tmpfile, F_OK) != -1) {
2102
2103 FATAL(
2104 "AFL_TMPDIR already has an existing temporary input file: %s - if "
2105 "this is not from another instance, then just remove the file.",
2106 tmpfile);
2107
2108 }
2109
2110 } else {
2111
2112 afl->tmp_dir = afl->out_dir;
2113
2114 }
2115
2116 /* If we don't have a file name chosen yet, use a safe default. */
2117
2118 if (!afl->fsrv.out_file) {
2119
2120 u32 j = optind + 1;
2121 while (argv[j]) {
2122
2123 u8 *aa_loc = strstr(argv[j], "@@");
2124
2125 if (aa_loc && !afl->fsrv.out_file) {
2126
2127 afl->fsrv.use_stdin = 0;
2128 default_output = 0;
2129
2130 if (afl->file_extension) {
2131
2132 afl->fsrv.out_file = alloc_printf("%s/.cur_input.%s", afl->tmp_dir,
2133 afl->file_extension);
2134
2135 } else {
2136
2137 afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
2138
2139 }
2140
2141 detect_file_args(argv + optind + 1, afl->fsrv.out_file,
2142 &afl->fsrv.use_stdin);
2143 break;
2144
2145 }
2146
2147 ++j;
2148
2149 }
2150
2151 }
2152
2153 if (!afl->fsrv.out_file) { setup_stdio_file(afl); }
2154
2155 if (afl->cmplog_binary) {
2156
2157 if (afl->unicorn_mode) {
2158
2159 FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry");
2160
2161 }
2162
2163 if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
2164 !afl->non_instrumented_mode) {
2165
2166 check_binary(afl, afl->cmplog_binary);
2167
2168 }
2169
2170 }
2171
2172 check_binary(afl, argv[optind]);
2173
2174 #ifdef AFL_PERSISTENT_RECORD
2175 if (unlikely(afl->fsrv.persistent_record)) {
2176
2177 if (!getenv(PERSIST_ENV_VAR)) {
2178
2179 FATAL(
2180 "Target binary is not compiled in persistent mode, "
2181 "AFL_PERSISTENT_RECORD makes no sense.");
2182
2183 }
2184
2185 afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
2186
2187 }
2188
2189 #endif
2190
2191 if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
2192
2193 afl->start_time = get_cur_time();
2194
2195 if (afl->fsrv.qemu_mode) {
2196
2197 if (afl->use_wine) {
2198
2199 use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2200 argv + optind);
2201
2202 } else {
2203
2204 use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2205 argv + optind);
2206
2207 }
2208
2209 } else if (afl->fsrv.cs_mode) {
2210
2211 use_argv = get_cs_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2212 argv + optind);
2213
2214 } else {
2215
2216 use_argv = argv + optind;
2217
2218 }
2219
2220 if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
2221 afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
2222
2223 u32 old_map_size = map_size;
2224 map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
2225 afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
2226 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
2227 afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
2228 afl->var_bytes = ck_realloc(afl->var_bytes, map_size);
2229 afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *));
2230 afl->clean_trace = ck_realloc(afl->clean_trace, map_size);
2231 afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size);
2232 afl->first_trace = ck_realloc(afl->first_trace, map_size);
2233 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
2234
2235 if (old_map_size < map_size) {
2236
2237 memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
2238 memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
2239 memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
2240 memset(afl->clean_trace_custom + old_map_size, 0,
2241 map_size - old_map_size);
2242 memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
2243 memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
2244
2245 }
2246
2247 }
2248
2249 afl->argv = use_argv;
2250 afl->fsrv.trace_bits =
2251 afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
2252
2253 if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
2254 !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
2255 !afl->afl_env.afl_skip_bin_check) {
2256
2257 if (map_size <= DEFAULT_SHMEM_SIZE) {
2258
2259 afl->fsrv.map_size = DEFAULT_SHMEM_SIZE; // dummy temporary value
2260 char vbuf[16];
2261 snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE);
2262 setenv("AFL_MAP_SIZE", vbuf, 1);
2263
2264 }
2265
2266 u32 new_map_size = afl_fsrv_get_mapsize(
2267 &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
2268
2269 // only reinitialize if the map needs to be larger than what we have.
2270 if (map_size < new_map_size) {
2271
2272 OKF("Re-initializing maps to %u bytes", new_map_size);
2273
2274 u32 old_map_size = map_size;
2275 afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
2276 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
2277 afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
2278 afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
2279 afl->top_rated =
2280 ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
2281 afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
2282 afl->clean_trace_custom =
2283 ck_realloc(afl->clean_trace_custom, new_map_size);
2284 afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
2285 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
2286
2287 if (old_map_size < new_map_size) {
2288
2289 memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
2290 memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
2291 memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
2292 memset(afl->clean_trace_custom + old_map_size, 0,
2293 new_map_size - old_map_size);
2294 memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
2295 memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
2296
2297 }
2298
2299 afl_fsrv_kill(&afl->fsrv);
2300 afl_shm_deinit(&afl->shm);
2301 afl->fsrv.map_size = new_map_size;
2302 afl->fsrv.trace_bits =
2303 afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
2304 setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
2305 afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
2306 afl->afl_env.afl_debug_child);
2307
2308 map_size = new_map_size;
2309
2310 }
2311
2312 }
2313
2314 if (afl->cmplog_binary) {
2315
2316 ACTF("Spawning cmplog forkserver");
2317 afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
2318 // TODO: this is semi-nice
2319 afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
2320 afl->cmplog_fsrv.cs_mode = afl->fsrv.cs_mode;
2321 afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
2322 afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
2323 afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
2324 afl->cmplog_fsrv.target_path = afl->fsrv.target_path;
2325 afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
2326
2327 if ((map_size <= DEFAULT_SHMEM_SIZE ||
2328 afl->cmplog_fsrv.map_size < map_size) &&
2329 !afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
2330 !afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode &&
2331 !afl->afl_env.afl_skip_bin_check) {
2332
2333 afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
2334 char vbuf[16];
2335 snprintf(vbuf, sizeof(vbuf), "%u", afl->cmplog_fsrv.map_size);
2336 setenv("AFL_MAP_SIZE", vbuf, 1);
2337
2338 }
2339
2340 u32 new_map_size =
2341 afl_fsrv_get_mapsize(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
2342 afl->afl_env.afl_debug_child);
2343
2344 // only reinitialize when it needs to be larger
2345 if (map_size < new_map_size) {
2346
2347 OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
2348
2349 u32 old_map_size = map_size;
2350 afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
2351 afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
2352 afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
2353 afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
2354 afl->top_rated =
2355 ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
2356 afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
2357 afl->clean_trace_custom =
2358 ck_realloc(afl->clean_trace_custom, new_map_size);
2359 afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
2360 afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
2361
2362 if (old_map_size < new_map_size) {
2363
2364 memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
2365 memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
2366 memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
2367 memset(afl->clean_trace_custom + old_map_size, 0,
2368 new_map_size - old_map_size);
2369 memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
2370 memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
2371
2372 }
2373
2374 afl_fsrv_kill(&afl->fsrv);
2375 afl_fsrv_kill(&afl->cmplog_fsrv);
2376 afl_shm_deinit(&afl->shm);
2377
2378 afl->cmplog_fsrv.map_size = new_map_size; // non-cmplog stays the same
2379 map_size = new_map_size;
2380
2381 setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
2382 afl->fsrv.trace_bits =
2383 afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
2384 afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
2385 afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
2386 afl->afl_env.afl_debug_child);
2387 afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
2388 afl->afl_env.afl_debug_child);
2389
2390 }
2391
2392 OKF("Cmplog forkserver successfully started");
2393
2394 }
2395
2396 load_auto(afl);
2397
2398 if (extras_dir_cnt) {
2399
2400 for (u8 i = 0; i < extras_dir_cnt; i++) {
2401
2402 load_extras(afl, extras_dir[i]);
2403
2404 }
2405
2406 }
2407
2408 if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) {
2409
2410 unlink(afl->fsrv.out_file);
2411 afl->fsrv.out_file = NULL;
2412 afl->fsrv.use_stdin = 0;
2413 close(afl->fsrv.out_fd);
2414 afl->fsrv.out_fd = -1;
2415
2416 if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) {
2417
2418 WARNF(
2419 "You specified -f or @@ on the command line but the target harness "
2420 "specified fuzz cases via shmem, switching to shmem!");
2421
2422 }
2423
2424 }
2425
2426 deunicode_extras(afl);
2427 dedup_extras(afl);
2428 if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
2429
2430 // after we have the correct bitmap size we can read the bitmap -B option
2431 // and set the virgin maps
2432 if (afl->in_bitmap) {
2433
2434 read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
2435
2436 } else {
2437
2438 memset(afl->virgin_bits, 255, map_size);
2439
2440 }
2441
2442 memset(afl->virgin_tmout, 255, map_size);
2443 memset(afl->virgin_crash, 255, map_size);
2444
2445 if (likely(!afl->afl_env.afl_no_startup_calibration)) {
2446
2447 perform_dry_run(afl);
2448
2449 } else {
2450
2451 ACTF("skipping initial seed calibration due option override!");
2452 usleep(1000);
2453
2454 }
2455
2456 if (afl->q_testcase_max_cache_entries) {
2457
2458 afl->q_testcase_cache =
2459 ck_alloc(afl->q_testcase_max_cache_entries * sizeof(size_t));
2460 if (!afl->q_testcase_cache) { PFATAL("malloc failed for cache entries"); }
2461
2462 }
2463
2464 cull_queue(afl);
2465
2466 // ensure we have at least one seed that is not disabled.
2467 u32 entry, valid_seeds = 0;
2468 for (entry = 0; entry < afl->queued_items; ++entry)
2469 if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
2470
2471 if (!afl->pending_not_fuzzed || !valid_seeds) {
2472
2473 FATAL("We need at least one valid input seed that does not crash!");
2474
2475 }
2476
2477 if (afl->timeout_given == 2) { // -t ...+ option
2478
2479 if (valid_seeds == 1) {
2480
2481 WARNF(
2482 "Only one valid seed is present, auto-calculating the timeout is "
2483 "disabled!");
2484 afl->timeout_given = 1;
2485
2486 } else {
2487
2488 u64 max_ms = 0;
2489
2490 for (entry = 0; entry < afl->queued_items; ++entry)
2491 if (!afl->queue_buf[entry]->disabled)
2492 if (afl->queue_buf[entry]->exec_us > max_ms)
2493 max_ms = afl->queue_buf[entry]->exec_us;
2494
2495 afl->fsrv.exec_tmout = max_ms;
2496 afl->timeout_given = 1;
2497
2498 }
2499
2500 }
2501
2502 show_init_stats(afl);
2503
2504 if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
2505
2506 afl->start_time = get_cur_time();
2507 if (afl->in_place_resume || afl->afl_env.afl_autoresume) {
2508
2509 load_stats_file(afl);
2510
2511 }
2512
2513 if (!afl->non_instrumented_mode) { write_stats_file(afl, 0, 0, 0, 0); }
2514 maybe_update_plot_file(afl, 0, 0, 0);
2515 save_auto(afl);
2516
2517 if (afl->stop_soon) { goto stop_fuzzing; }
2518
2519 /* Woop woop woop */
2520
2521 if (!afl->not_on_tty) {
2522
2523 sleep(1);
2524 if (afl->stop_soon) { goto stop_fuzzing; }
2525
2526 }
2527
2528 // (void)nice(-20); // does not improve the speed
2529 // real start time, we reset, so this works correctly with -V
2530 afl->start_time = get_cur_time();
2531
2532 #ifdef INTROSPECTION
2533 u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
2534 #endif
2535 u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1;
2536 u8 skipped_fuzz;
2537
2538 #ifdef INTROSPECTION
2539 char ifn[4096];
2540 snprintf(ifn, sizeof(ifn), "%s/introspection.txt", afl->out_dir);
2541 if ((afl->introspection_file = fopen(ifn, "w")) == NULL) {
2542
2543 PFATAL("could not create '%s'", ifn);
2544
2545 }
2546
2547 setvbuf(afl->introspection_file, NULL, _IONBF, 0);
2548 OKF("Writing mutation introspection to '%s'", ifn);
2549 #endif
2550
2551 while (likely(!afl->stop_soon)) {
2552
2553 cull_queue(afl);
2554
2555 if (unlikely((!afl->old_seed_selection &&
2556 runs_in_current_cycle > afl->queued_items) ||
2557 (afl->old_seed_selection && !afl->queue_cur))) {
2558
2559 if (unlikely((afl->last_sync_cycle < afl->queue_cycle ||
2560 (!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
2561 afl->sync_id)) {
2562
2563 if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
2564
2565 OKF("Syncing queues from other fuzzer instances first ...");
2566
2567 }
2568
2569 sync_fuzzers(afl);
2570
2571 }
2572
2573 ++afl->queue_cycle;
2574 runs_in_current_cycle = (u32)-1;
2575 afl->cur_skipped_items = 0;
2576
2577 // 1st april fool joke - enable pizza mode
2578 // to not waste time on checking the date we only do this when the
2579 // queue is fully cycled.
2580 time_t cursec = time(NULL);
2581 struct tm *curdate = localtime(&cursec);
2582 if (likely(!afl->afl_env.afl_pizza_mode)) {
2583
2584 if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) {
2585
2586 afl->pizza_is_served = 1;
2587
2588 } else {
2589
2590 afl->pizza_is_served = 0;
2591
2592 }
2593
2594 }
2595
2596 if (unlikely(afl->old_seed_selection)) {
2597
2598 afl->current_entry = 0;
2599 while (unlikely(afl->current_entry < afl->queued_items &&
2600 afl->queue_buf[afl->current_entry]->disabled)) {
2601
2602 ++afl->current_entry;
2603
2604 }
2605
2606 if (afl->current_entry >= afl->queued_items) { afl->current_entry = 0; }
2607
2608 afl->queue_cur = afl->queue_buf[afl->current_entry];
2609
2610 if (unlikely(seek_to)) {
2611
2612 if (unlikely(seek_to >= afl->queued_items)) {
2613
2614 // This should never happen.
2615 FATAL("BUG: seek_to location out of bounds!\n");
2616
2617 }
2618
2619 afl->current_entry = seek_to;
2620 afl->queue_cur = afl->queue_buf[seek_to];
2621 seek_to = 0;
2622
2623 }
2624
2625 }
2626
2627 if (unlikely(afl->not_on_tty)) {
2628
2629 ACTF("Entering queue cycle %llu.", afl->queue_cycle);
2630 fflush(stdout);
2631
2632 }
2633
2634 /* If we had a full queue cycle with no new finds, try
2635 recombination strategies next. */
2636
2637 if (unlikely(afl->queued_items == prev_queued
2638 /* FIXME TODO BUG: && (get_cur_time() - afl->start_time) >=
2639 3600 */
2640 )) {
2641
2642 if (afl->use_splicing) {
2643
2644 ++afl->cycles_wo_finds;
2645
2646 if (unlikely(afl->shm.cmplog_mode &&
2647 afl->cmplog_max_filesize < MAX_FILE)) {
2648
2649 afl->cmplog_max_filesize <<= 4;
2650
2651 }
2652
2653 switch (afl->expand_havoc) {
2654
2655 case 0:
2656 // this adds extra splicing mutation options to havoc mode
2657 afl->expand_havoc = 1;
2658 break;
2659 case 1:
2660 // add MOpt mutator
2661 /*
2662 if (afl->limit_time_sig == 0 && !afl->custom_only &&
2663 !afl->python_only) {
2664
2665 afl->limit_time_sig = -1;
2666 afl->limit_time_puppet = 0;
2667
2668 }
2669
2670 */
2671 afl->expand_havoc = 2;
2672 if (afl->cmplog_lvl && afl->cmplog_lvl < 2) afl->cmplog_lvl = 2;
2673 break;
2674 case 2:
2675 // increase havoc mutations per fuzz attempt
2676 afl->havoc_stack_pow2++;
2677 afl->expand_havoc = 3;
2678 break;
2679 case 3:
2680 // further increase havoc mutations per fuzz attempt
2681 afl->havoc_stack_pow2++;
2682 afl->expand_havoc = 4;
2683 break;
2684 case 4:
2685 afl->expand_havoc = 5;
2686 // if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl =
2687 // 3;
2688 break;
2689 case 5:
2690 // nothing else currently
2691 break;
2692
2693 }
2694
2695 } else {
2696
2697 #ifndef NO_SPLICING
2698 afl->use_splicing = 1;
2699 #else
2700 afl->use_splicing = 0;
2701 #endif
2702
2703 }
2704
2705 } else {
2706
2707 afl->cycles_wo_finds = 0;
2708
2709 }
2710
2711 #ifdef INTROSPECTION
2712 {
2713
2714 u64 cur_time = get_cur_time();
2715 fprintf(afl->introspection_file,
2716 "CYCLE cycle=%llu cycle_wo_finds=%llu time_wo_finds=%llu "
2717 "expand_havoc=%u queue=%u\n",
2718 afl->queue_cycle, afl->cycles_wo_finds,
2719 afl->longest_find_time > cur_time - afl->last_find_time
2720 ? afl->longest_find_time / 1000
2721 : ((afl->start_time == 0 || afl->last_find_time == 0)
2722 ? 0
2723 : (cur_time - afl->last_find_time) / 1000),
2724 afl->expand_havoc, afl->queued_items);
2725
2726 }
2727
2728 #endif
2729
2730 if (afl->cycle_schedules) {
2731
2732 /* we cannot mix non-AFLfast schedules with others */
2733
2734 switch (afl->schedule) {
2735
2736 case EXPLORE:
2737 afl->schedule = EXPLOIT;
2738 break;
2739 case EXPLOIT:
2740 afl->schedule = MMOPT;
2741 break;
2742 case MMOPT:
2743 afl->schedule = SEEK;
2744 break;
2745 case SEEK:
2746 afl->schedule = EXPLORE;
2747 break;
2748 case FAST:
2749 afl->schedule = COE;
2750 break;
2751 case COE:
2752 afl->schedule = LIN;
2753 break;
2754 case LIN:
2755 afl->schedule = QUAD;
2756 break;
2757 case QUAD:
2758 afl->schedule = RARE;
2759 break;
2760 case RARE:
2761 afl->schedule = FAST;
2762 break;
2763
2764 }
2765
2766 // we must recalculate the scores of all queue entries
2767 for (u32 i = 0; i < afl->queued_items; i++) {
2768
2769 if (likely(!afl->queue_buf[i]->disabled)) {
2770
2771 update_bitmap_score(afl, afl->queue_buf[i]);
2772
2773 }
2774
2775 }
2776
2777 }
2778
2779 prev_queued = afl->queued_items;
2780
2781 }
2782
2783 ++runs_in_current_cycle;
2784
2785 do {
2786
2787 if (likely(!afl->old_seed_selection)) {
2788
2789 if (likely(afl->pending_favored && afl->smallest_favored >= 0)) {
2790
2791 afl->current_entry = afl->smallest_favored;
2792
2793 /*
2794
2795 } else {
2796
2797 for (s32 iter = afl->queued_items - 1; iter >= 0; --iter)
2798 {
2799
2800 if (unlikely(afl->queue_buf[iter]->favored &&
2801 !afl->queue_buf[iter]->was_fuzzed)) {
2802
2803 afl->current_entry = iter;
2804 break;
2805
2806 }
2807
2808 }
2809
2810 */
2811
2812 afl->queue_cur = afl->queue_buf[afl->current_entry];
2813
2814 } else {
2815
2816 if (unlikely(prev_queued_items < afl->queued_items ||
2817 afl->reinit_table)) {
2818
2819 // we have new queue entries since the last run, recreate alias
2820 // table
2821 prev_queued_items = afl->queued_items;
2822 create_alias_table(afl);
2823
2824 }
2825
2826 do {
2827
2828 afl->current_entry = select_next_queue_entry(afl);
2829
2830 } while (unlikely(afl->current_entry >= afl->queued_items));
2831
2832 afl->queue_cur = afl->queue_buf[afl->current_entry];
2833
2834 }
2835
2836 }
2837
2838 skipped_fuzz = fuzz_one(afl);
2839 #ifdef INTROSPECTION
2840 ++afl->queue_cur->stats_selected;
2841
2842 if (unlikely(skipped_fuzz)) {
2843
2844 ++afl->queue_cur->stats_skipped;
2845
2846 } else {
2847
2848 if (unlikely(afl->queued_items > prev_queued_items)) {
2849
2850 afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items;
2851 prev_queued_items = afl->queued_items;
2852
2853 }
2854
2855 if (unlikely(afl->saved_crashes > prev_saved_crashes)) {
2856
2857 afl->queue_cur->stats_crashes +=
2858 afl->saved_crashes - prev_saved_crashes;
2859 prev_saved_crashes = afl->saved_crashes;
2860
2861 }
2862
2863 if (unlikely(afl->saved_tmouts > prev_saved_tmouts)) {
2864
2865 afl->queue_cur->stats_tmouts += afl->saved_tmouts - prev_saved_tmouts;
2866 prev_saved_tmouts = afl->saved_tmouts;
2867
2868 }
2869
2870 }
2871
2872 #endif
2873
2874 if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; }
2875
2876 if (unlikely(afl->old_seed_selection)) {
2877
2878 while (++afl->current_entry < afl->queued_items &&
2879 afl->queue_buf[afl->current_entry]->disabled) {};
2880 if (unlikely(afl->current_entry >= afl->queued_items ||
2881 afl->queue_buf[afl->current_entry] == NULL ||
2882 afl->queue_buf[afl->current_entry]->disabled)) {
2883
2884 afl->queue_cur = NULL;
2885
2886 } else {
2887
2888 afl->queue_cur = afl->queue_buf[afl->current_entry];
2889
2890 }
2891
2892 }
2893
2894 } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
2895
2896 u64 cur_time = get_cur_time();
2897
2898 if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 &&
2899 !afl->non_instrumented_mode) &&
2900 unlikely(cur_time > (likely(afl->last_find_time) ? afl->last_find_time
2901 : afl->start_time) +
2902 afl->switch_fuzz_mode)) {
2903
2904 if (afl->afl_env.afl_no_ui) {
2905
2906 ACTF(
2907 "No new coverage found for %llu seconds, switching to exploitation "
2908 "strategy.",
2909 afl->switch_fuzz_mode / 1000);
2910
2911 }
2912
2913 afl->fuzz_mode = 1;
2914
2915 }
2916
2917 if (likely(!afl->stop_soon && afl->sync_id)) {
2918
2919 if (likely(afl->skip_deterministic)) {
2920
2921 if (unlikely(afl->is_main_node)) {
2922
2923 if (unlikely(cur_time >
2924 (afl->sync_time >> 1) + afl->last_sync_time)) {
2925
2926 if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
2927
2928 sync_fuzzers(afl);
2929
2930 }
2931
2932 }
2933
2934 } else {
2935
2936 if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
2937
2938 if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
2939
2940 }
2941
2942 }
2943
2944 } else {
2945
2946 sync_fuzzers(afl);
2947
2948 }
2949
2950 }
2951
2952 }
2953
2954 stop_fuzzing:
2955
2956 afl->force_ui_update = 1; // ensure the screen is reprinted
2957 afl->stop_soon = 1; // ensure everything is written
2958 show_stats(afl); // print the screen one last time
2959 write_bitmap(afl);
2960 save_auto(afl);
2961
2962 if (afl->pizza_is_served) {
2963
2964 SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST,
2965 afl->stop_soon == 2 ? "programmatically" : "by the chef");
2966
2967 } else {
2968
2969 SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
2970 afl->stop_soon == 2 ? "programmatically" : "by user");
2971
2972 }
2973
2974 if (afl->most_time_key == 2) {
2975
2976 SAYF(cYEL "[!] " cRST "Time limit was reached\n");
2977
2978 }
2979
2980 if (afl->most_execs_key == 2) {
2981
2982 SAYF(cYEL "[!] " cRST "Execution limit was reached\n");
2983
2984 }
2985
2986 /* Running for more than 30 minutes but still doing first cycle? */
2987
2988 if (afl->queue_cycle == 1 &&
2989 get_cur_time() - afl->start_time > 30 * 60 * 1000) {
2990
2991 SAYF("\n" cYEL "[!] " cRST
2992 "Stopped during the first cycle, results may be incomplete.\n"
2993 " (For info on resuming, see %s/README.md)\n",
2994 doc_path);
2995
2996 }
2997
2998 if (afl->not_on_tty) {
2999
3000 u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
3001 u8 time_tmp[64];
3002 u_stringify_time_diff(time_tmp, get_cur_time(), afl->start_time);
3003 ACTF(
3004 "Statistics: %u new corpus items found, %.02f%% coverage achieved, "
3005 "%llu crashes saved, %llu timeouts saved, total runtime %s",
3006 afl->queued_discovered,
3007 ((double)t_bytes * 100) / afl->fsrv.real_map_size, afl->saved_crashes,
3008 afl->saved_hangs, time_tmp);
3009
3010 }
3011
3012 #ifdef PROFILING
3013 SAYF(cYEL "[!] " cRST
3014 "Profiling information: %llu ms total work, %llu ns/run\n",
3015 time_spent_working / 1000000,
3016 time_spent_working / afl->fsrv.total_execs);
3017 #endif
3018
3019 if (afl->afl_env.afl_final_sync) {
3020
3021 SAYF(cYEL "[!] " cRST
3022 "\nPerforming final sync, this make take some time ...\n");
3023 sync_fuzzers(afl);
3024 write_bitmap(afl);
3025 SAYF(cYEL "[!] " cRST "Done!\n\n");
3026
3027 }
3028
3029 if (afl->is_main_node) {
3030
3031 u8 path[PATH_MAX];
3032 sprintf(path, "%s/is_main_node", afl->out_dir);
3033 unlink(path);
3034
3035 }
3036
3037 if (frida_afl_preload) { ck_free(frida_afl_preload); }
3038
3039 fclose(afl->fsrv.plot_file);
3040
3041 #ifdef INTROSPECTION
3042 fclose(afl->fsrv.det_plot_file);
3043 #endif
3044
3045 destroy_queue(afl);
3046 destroy_extras(afl);
3047 destroy_custom_mutators(afl);
3048 afl_shm_deinit(&afl->shm);
3049
3050 if (afl->shm_fuzz) {
3051
3052 afl_shm_deinit(afl->shm_fuzz);
3053 ck_free(afl->shm_fuzz);
3054
3055 }
3056
3057 afl_fsrv_deinit(&afl->fsrv);
3058
3059 /* remove tmpfile */
3060 if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
3061
3062 (void)unlink(afl->fsrv.out_file);
3063
3064 }
3065
3066 if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
3067 ck_free(afl->fsrv.target_path);
3068 ck_free(afl->fsrv.out_file);
3069 ck_free(afl->sync_id);
3070 if (afl->q_testcase_cache) { ck_free(afl->q_testcase_cache); }
3071 afl_state_deinit(afl);
3072 free(afl); /* not tracked */
3073
3074 argv_cpy_free(argv);
3075
3076 alloc_report();
3077
3078 OKF("We're done here. Have a nice day!\n");
3079
3080 exit(0);
3081
3082 }
3083
3084 #endif /* !AFL_LIB */
3085
3086