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