1 /*
2 american fuzzy lop++ - map display utility
3 ------------------------------------------
4
5 Originally written by Michal Zalewski
6
7 Forkserver design by Jann Horn <[email protected]>
8
9 Now maintained by Marc Heuse <[email protected]>,
10 Heiko Eißfeldt <[email protected]> and
11 Andrea Fioraldi <[email protected]> and
12 Dominik Maier <[email protected]>
13
14 Copyright 2016, 2017 Google Inc. All rights reserved.
15 Copyright 2019-2024 AFLplusplus Project. All rights reserved.
16
17 Licensed under the Apache License, Version 2.0 (the "License");
18 you may not use this file except in compliance with the License.
19 You may obtain a copy of the License at:
20
21 https://www.apache.org/licenses/LICENSE-2.0
22
23 A very simple tool that runs the targeted binary and displays
24 the contents of the trace bitmap in a human-readable form. Useful in
25 scripts to eliminate redundant inputs and perform other checks.
26
27 Exit code is 2 if the target program crashes; 1 if it times out or
28 there is a problem executing it; or 0 if execution is successful.
29
30 */
31
32 #define AFL_MAIN
33 #define AFL_SHOWMAP
34
35 #include "config.h"
36 #include "afl-fuzz.h"
37 #include "types.h"
38 #include "debug.h"
39 #include "alloc-inl.h"
40 #include "hash.h"
41 #include "sharedmem.h"
42 #include "forkserver.h"
43 #include "common.h"
44 #include "hash.h"
45
46 #include <stdio.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <time.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <dirent.h>
54 #include <fcntl.h>
55 #include <limits.h>
56
57 #include <dirent.h>
58 #include <sys/wait.h>
59 #include <sys/time.h>
60 #ifndef USEMMAP
61 #include <sys/shm.h>
62 #endif
63 #include <sys/stat.h>
64 #include <sys/types.h>
65 #include <sys/resource.h>
66
67 static afl_state_t *afl;
68
69 static char *stdin_file; /* stdin file */
70
71 static u8 *in_dir = NULL, /* input folder */
72 *out_file = NULL, /* output file or directory */
73 *at_file = NULL, /* Substitution string for @@ */
74 *in_filelist = NULL; /* input file list */
75
76 static u8 outfile[PATH_MAX];
77
78 static u8 *in_data, /* Input data */
79 *coverage_map; /* Coverage map */
80
81 static u64 total; /* tuple content information */
82 static u32 tcnt, highest; /* tuple content information */
83
84 static u32 in_len; /* Input data length */
85
86 static u32 map_size = MAP_SIZE, timed_out = 0;
87
88 static bool quiet_mode, /* Hide non-essential messages? */
89 edges_only, /* Ignore hit counts? */
90 raw_instr_output, /* Do not apply AFL filters */
91 cmin_mode, /* Generate output in afl-cmin mode? */
92 binary_mode, /* Write output as a binary map */
93 keep_cores, /* Allow coredumps? */
94 remove_shm = true, /* remove shmem? */
95 collect_coverage, /* collect coverage */
96 have_coverage, /* have coverage? */
97 no_classify, /* do not classify counts */
98 debug, /* debug mode */
99 print_filenames, /* print the current filename */
100 wait_for_gdb;
101
102 static volatile u8 stop_soon, /* Ctrl-C pressed? */
103 child_crashed; /* Child crashed? */
104
105 static sharedmem_t shm;
106 static afl_forkserver_t *fsrv;
107 static sharedmem_t *shm_fuzz;
108
109 /* Classify tuple counts. Instead of mapping to individual bits, as in
110 afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */
111
112 static const u8 count_class_human[256] = {
113
114 [0] = 0, [1] = 1, [2] = 2, [3] = 3,
115 [4 ... 7] = 4, [8 ... 15] = 5, [16 ... 31] = 6, [32 ... 127] = 7,
116 [128 ... 255] = 8
117
118 };
119
120 static const u8 count_class_binary[256] = {
121
122 [0] = 0,
123 [1] = 1,
124 [2] = 2,
125 [3] = 4,
126 [4 ... 7] = 8,
127 [8 ... 15] = 16,
128 [16 ... 31] = 32,
129 [32 ... 127] = 64,
130 [128 ... 255] = 128
131
132 };
133
kill_child()134 static void kill_child() {
135
136 timed_out = 1;
137 if (fsrv->child_pid > 0) {
138
139 kill(fsrv->child_pid, fsrv->child_kill_signal);
140 fsrv->child_pid = -1;
141
142 }
143
144 }
145
146 /* dummy functions */
write_to_testcase(afl_state_t * afl,void ** mem,u32 a,u32 b)147 u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
148
149 (void)afl;
150 (void)mem;
151 return a + b;
152
153 }
154
show_stats(afl_state_t * afl)155 void show_stats(afl_state_t *afl) {
156
157 (void)afl;
158
159 }
160
update_bitmap_score(afl_state_t * afl,struct queue_entry * q)161 void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
162
163 (void)afl;
164 (void)q;
165
166 }
167
fuzz_run_target(afl_state_t * afl,afl_forkserver_t * fsrv,u32 i)168 fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
169 u32 i) {
170
171 (void)afl;
172 (void)fsrv;
173 (void)i;
174 return 0;
175
176 }
177
classify_counts(afl_forkserver_t * fsrv)178 void classify_counts(afl_forkserver_t *fsrv) {
179
180 u8 *mem = fsrv->trace_bits;
181 const u8 *map = binary_mode ? count_class_binary : count_class_human;
182
183 u32 i = map_size;
184
185 if (edges_only) {
186
187 while (i--) {
188
189 if (*mem) { *mem = 1; }
190 mem++;
191
192 }
193
194 } else if (!raw_instr_output) {
195
196 while (i--) {
197
198 *mem = map[*mem];
199 mem++;
200
201 }
202
203 }
204
205 }
206
deinit_shmem(afl_forkserver_t * fsrv,sharedmem_t * shm_fuzz)207 static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
208 sharedmem_t *shm_fuzz) {
209
210 afl_shm_deinit(shm_fuzz);
211 fsrv->support_shmem_fuzz = 0;
212 fsrv->shmem_fuzz_len = NULL;
213 fsrv->shmem_fuzz = NULL;
214 ck_free(shm_fuzz);
215 return NULL;
216
217 }
218
219 /* Get rid of temp files (atexit handler). */
220
at_exit_handler(void)221 static void at_exit_handler(void) {
222
223 if (stdin_file) { unlink(stdin_file); }
224
225 if (remove_shm) {
226
227 if (shm.map) afl_shm_deinit(&shm);
228 if (fsrv->use_shmem_fuzz) deinit_shmem(fsrv, shm_fuzz);
229
230 }
231
232 afl_fsrv_killall();
233
234 }
235
236 /* Analyze results. */
237
analyze_results(afl_forkserver_t * fsrv)238 static void analyze_results(afl_forkserver_t *fsrv) {
239
240 u32 i;
241 for (i = 0; i < map_size; i++) {
242
243 if (fsrv->trace_bits[i]) {
244
245 total += fsrv->trace_bits[i];
246 if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
247 // if (!coverage_map[i]) { coverage_map[i] = 1; }
248 coverage_map[i] |= fsrv->trace_bits[i];
249
250 }
251
252 }
253
254 }
255
256 /* Write results. */
257
write_results_to_file(afl_forkserver_t * fsrv,u8 * outfile)258 static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
259
260 s32 fd;
261 u32 i, ret = 0;
262
263 u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"),
264 caa = !!getenv("AFL_CMIN_ALLOW_ANY");
265
266 if (!outfile || !*outfile) {
267
268 FATAL("Output filename not set (Bug in AFL++?)");
269
270 }
271
272 if (cmin_mode &&
273 (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
274
275 if (strcmp(outfile, "-")) {
276
277 // create empty file to prevent error messages in afl-cmin
278 fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
279 close(fd);
280
281 }
282
283 return ret;
284
285 }
286
287 if (!strncmp(outfile, "/dev/", 5)) {
288
289 fd = open(outfile, O_WRONLY);
290
291 if (fd < 0) { PFATAL("Unable to open '%s'", out_file); }
292
293 } else if (!strcmp(outfile, "-")) {
294
295 fd = dup(1);
296 if (fd < 0) { PFATAL("Unable to open stdout"); }
297
298 } else {
299
300 unlink(outfile); /* Ignore errors */
301 fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
302 if (fd < 0) { PFATAL("Unable to create '%s'", outfile); }
303
304 }
305
306 if (binary_mode) {
307
308 for (i = 0; i < map_size; i++) {
309
310 if (fsrv->trace_bits[i]) { ret++; }
311
312 }
313
314 ck_write(fd, fsrv->trace_bits, map_size, outfile);
315 close(fd);
316
317 } else {
318
319 FILE *f = fdopen(fd, "w");
320
321 if (!f) { PFATAL("fdopen() failed"); }
322
323 for (i = 0; i < map_size; i++) {
324
325 if (!fsrv->trace_bits[i]) { continue; }
326 ret++;
327
328 total += fsrv->trace_bits[i];
329 if (highest < fsrv->trace_bits[i]) { highest = fsrv->trace_bits[i]; }
330
331 if (cmin_mode) {
332
333 fprintf(f, "%u%03u\n", i, fsrv->trace_bits[i]);
334
335 } else {
336
337 fprintf(f, "%06u:%u\n", i, fsrv->trace_bits[i]);
338
339 }
340
341 }
342
343 fclose(f);
344
345 }
346
347 return ret;
348
349 }
350
pre_afl_fsrv_write_to_testcase(afl_forkserver_t * fsrv,u8 * mem,u32 len)351 void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) {
352
353 static u8 buf[MAX_FILE];
354 u32 sent = 0;
355
356 if (unlikely(afl->custom_mutators_count)) {
357
358 ssize_t new_size = len;
359 u8 *new_mem = mem;
360 u8 *new_buf = NULL;
361
362 LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
363
364 if (el->afl_custom_post_process) {
365
366 new_size =
367 el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
368
369 if (unlikely(!new_buf || new_size <= 0)) {
370
371 return;
372
373 } else {
374
375 new_mem = new_buf;
376 len = new_size;
377
378 }
379
380 }
381
382 });
383
384 if (new_mem != mem && new_mem != NULL) {
385
386 mem = buf;
387 memcpy(mem, new_mem, new_size);
388
389 }
390
391 if (unlikely(afl->custom_mutators_count)) {
392
393 LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
394
395 if (el->afl_custom_fuzz_send) {
396
397 el->afl_custom_fuzz_send(el->data, mem, len);
398 sent = 1;
399
400 }
401
402 });
403
404 }
405
406 }
407
408 if (likely(!sent)) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
409
410 }
411
412 /* Execute target application. */
413
showmap_run_target_forkserver(afl_forkserver_t * fsrv,u8 * mem,u32 len)414 static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
415 u32 len) {
416
417 pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
418
419 if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
420
421 if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
422 FSRV_RUN_ERROR) {
423
424 FATAL("Error running target");
425
426 }
427
428 if (fsrv->trace_bits[0]) {
429
430 fsrv->trace_bits[0] -= 1;
431 have_coverage = true;
432
433 } else {
434
435 have_coverage = false;
436
437 }
438
439 if (!no_classify) { classify_counts(fsrv); }
440
441 if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); }
442
443 if (!fsrv->last_run_timed_out && !stop_soon &&
444 WIFSIGNALED(fsrv->child_status)) {
445
446 child_crashed = true;
447
448 } else {
449
450 child_crashed = false;
451
452 }
453
454 if (!quiet_mode) {
455
456 if (timed_out || fsrv->last_run_timed_out) {
457
458 SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
459 timed_out = 0;
460
461 } else if (stop_soon) {
462
463 SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
464
465 } else if (child_crashed) {
466
467 SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST,
468 WTERMSIG(fsrv->child_status));
469
470 }
471
472 }
473
474 if (stop_soon) {
475
476 SAYF(cRST cLRD "\n+++ afl-showmap folder mode aborted by user +++\n" cRST);
477 exit(1);
478
479 }
480
481 }
482
483 /* Read initial file. */
484
read_file(u8 * in_file)485 static u32 read_file(u8 *in_file) {
486
487 if (print_filenames) {
488
489 SAYF("Processing %s\n", in_file);
490 fflush(stdout);
491
492 }
493
494 struct stat st;
495 s32 fd = open(in_file, O_RDONLY);
496
497 if (fd < 0) { WARNF("Unable to open '%s'", in_file); }
498
499 if (fstat(fd, &st) || !st.st_size) {
500
501 if (!be_quiet && !quiet_mode) {
502
503 WARNF("Zero-sized input file '%s'.", in_file);
504
505 }
506
507 }
508
509 if (st.st_size > MAX_FILE) {
510
511 if (!be_quiet && !quiet_mode) {
512
513 WARNF("Input file '%s' is too large, only reading %ld bytes.", in_file,
514 MAX_FILE);
515
516 }
517
518 in_len = MAX_FILE;
519
520 } else {
521
522 in_len = st.st_size;
523
524 }
525
526 in_data = ck_alloc_nozero(in_len);
527
528 ck_read(fd, in_data, in_len, in_file);
529
530 close(fd);
531
532 // OKF("Read %u byte%s from '%s'.", in_len, in_len == 1 ? "" : "s", in_file);
533
534 return in_len;
535
536 }
537
538 #ifdef __linux__
539 /* Execute the target application with an empty input (in Nyx mode). */
showmap_run_target_nyx_mode(afl_forkserver_t * fsrv)540 static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
541
542 afl_fsrv_write_to_testcase(fsrv, NULL, 0);
543
544 if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
545 FSRV_RUN_ERROR) {
546
547 FATAL("Error running target in Nyx mode");
548
549 }
550
551 }
552
553 #endif
554
555 /* Execute target application. */
556
showmap_run_target(afl_forkserver_t * fsrv,char ** argv)557 static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
558
559 static struct itimerval it;
560 int status = 0;
561
562 if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
563
564 MEM_BARRIER();
565
566 fsrv->child_pid = fork();
567
568 if (fsrv->child_pid < 0) { PFATAL("fork() failed"); }
569
570 if (!fsrv->child_pid) {
571
572 struct rlimit r;
573
574 if (quiet_mode) {
575
576 s32 fd = open("/dev/null", O_RDWR);
577
578 if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) {
579
580 *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
581 PFATAL("Descriptor initialization failed");
582
583 }
584
585 close(fd);
586
587 }
588
589 if (fsrv->mem_limit) {
590
591 r.rlim_max = r.rlim_cur = ((rlim_t)fsrv->mem_limit) << 20;
592
593 #ifdef RLIMIT_AS
594
595 setrlimit(RLIMIT_AS, &r); /* Ignore errors */
596
597 #else
598
599 setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
600
601 #endif /* ^RLIMIT_AS */
602
603 }
604
605 if (!keep_cores) {
606
607 r.rlim_max = r.rlim_cur = 0;
608
609 } else {
610
611 r.rlim_max = r.rlim_cur = RLIM_INFINITY;
612
613 }
614
615 setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
616
617 if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); }
618
619 setsid();
620
621 execv(fsrv->target_path, argv);
622
623 *(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
624 exit(0);
625
626 }
627
628 /* Configure timeout, wait for child, cancel timeout. */
629
630 if (fsrv->exec_tmout) {
631
632 fsrv->last_run_timed_out = 0;
633 it.it_value.tv_sec = (fsrv->exec_tmout / 1000);
634 it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000;
635
636 signal(SIGALRM, kill_child);
637
638 setitimer(ITIMER_REAL, &it, NULL);
639
640 }
641
642 if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
643
644 fsrv->child_pid = 0;
645 it.it_value.tv_sec = 0;
646 it.it_value.tv_usec = 0;
647 setitimer(ITIMER_REAL, &it, NULL);
648
649 MEM_BARRIER();
650
651 /* Clean up bitmap, analyze exit condition, etc. */
652
653 if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) {
654
655 FATAL("Unable to execute '%s'", argv[0]);
656
657 }
658
659 if (fsrv->trace_bits[0]) {
660
661 fsrv->trace_bits[0] -= 1;
662 have_coverage = true;
663
664 } else {
665
666 have_coverage = false;
667
668 }
669
670 if (!no_classify) { classify_counts(fsrv); }
671
672 if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); }
673
674 if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) {
675
676 child_crashed = true;
677
678 }
679
680 if (!quiet_mode) {
681
682 if (timed_out || fsrv->last_run_timed_out) {
683
684 SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
685 timed_out = 0;
686
687 } else if (stop_soon) {
688
689 SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
690
691 } else if (child_crashed) {
692
693 SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST,
694 WTERMSIG(status));
695
696 }
697
698 }
699
700 }
701
702 /* Handle Ctrl-C and the like. */
703
handle_stop_sig(int sig)704 static void handle_stop_sig(int sig) {
705
706 (void)sig;
707 stop_soon = true;
708 afl_fsrv_killall();
709
710 }
711
712 /* Do basic preparations - persistent fds, filenames, etc. */
713
set_up_environment(afl_forkserver_t * fsrv,char ** argv)714 static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
715
716 char *afl_preload;
717 char *frida_afl_preload = NULL;
718
719 set_sanitizer_defaults();
720
721 if (get_afl_env("AFL_PRELOAD")) {
722
723 if (fsrv->qemu_mode) {
724
725 /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
726
727 } else if (fsrv->frida_mode) {
728
729 afl_preload = getenv("AFL_PRELOAD");
730 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
731 if (afl_preload) {
732
733 frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
734
735 } else {
736
737 frida_afl_preload = alloc_printf("%s", frida_binary);
738
739 }
740
741 ck_free(frida_binary);
742
743 setenv("LD_PRELOAD", frida_afl_preload, 1);
744 setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
745
746 } else {
747
748 /* CoreSight mode uses the default behavior. */
749
750 setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
751 setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
752
753 }
754
755 } else if (fsrv->frida_mode) {
756
757 u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
758 setenv("LD_PRELOAD", frida_binary, 1);
759 setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
760 ck_free(frida_binary);
761
762 }
763
764 if (frida_afl_preload) { ck_free(frida_afl_preload); }
765
766 }
767
768 /* Setup signal handlers, duh. */
769
setup_signal_handlers(void)770 static void setup_signal_handlers(void) {
771
772 struct sigaction sa;
773
774 sa.sa_handler = NULL;
775 #ifdef SA_RESTART
776 sa.sa_flags = SA_RESTART;
777 #else
778 sa.sa_flags = 0;
779 #endif
780 sa.sa_sigaction = NULL;
781
782 sigemptyset(&sa.sa_mask);
783
784 /* Various ways of saying "stop". */
785
786 sa.sa_handler = handle_stop_sig;
787 sigaction(SIGHUP, &sa, NULL);
788 sigaction(SIGINT, &sa, NULL);
789 sigaction(SIGTERM, &sa, NULL);
790
791 }
792
execute_testcases(u8 * dir)793 u32 execute_testcases(u8 *dir) {
794
795 struct dirent **nl;
796 s32 nl_cnt, subdirs = 1;
797 u32 i, done = 0;
798 u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
799
800 if (!be_quiet) { ACTF("Scanning '%s'...", dir); }
801
802 /* We use scandir() + alphasort() rather than readdir() because otherwise,
803 the ordering of test cases would vary somewhat randomly and would be
804 difficult to control. */
805
806 nl_cnt = scandir(dir, &nl, NULL, alphasort);
807
808 if (nl_cnt < 0) { return 0; }
809
810 for (i = 0; i < (u32)nl_cnt; ++i) {
811
812 struct stat st;
813
814 u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
815
816 if (lstat(fn2, &st) || access(fn2, R_OK)) {
817
818 PFATAL("Unable to access '%s'", fn2);
819
820 }
821
822 /* obviously we want to skip "descending" into . and .. directories,
823 however it is a good idea to skip also directories that start with
824 a dot */
825 if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
826
827 free(nl[i]); /* not tracked */
828 done += execute_testcases(fn2);
829 ck_free(fn2);
830 continue;
831
832 }
833
834 if (!S_ISREG(st.st_mode) || !st.st_size) {
835
836 free(nl[i]);
837 ck_free(fn2);
838 continue;
839
840 }
841
842 if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) {
843
844 WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
845 stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
846 stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
847
848 }
849
850 if (!collect_coverage)
851 snprintf(outfile, sizeof(outfile), "%s/%s", out_file, nl[i]->d_name);
852
853 free(nl[i]);
854
855 if (read_file(fn2)) {
856
857 if (wait_for_gdb) {
858
859 fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
860 fprintf(stderr, "exec: kill -CONT %d\n", getpid());
861 kill(0, SIGSTOP);
862
863 }
864
865 showmap_run_target_forkserver(fsrv, in_data, in_len);
866 ck_free(in_data);
867 ++done;
868
869 if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
870
871 if (collect_coverage)
872 analyze_results(fsrv);
873 else
874 tcnt = write_results_to_file(fsrv, outfile);
875
876 }
877
878 }
879
880 free(nl); /* not tracked */
881 return done;
882
883 }
884
execute_testcases_filelist(u8 * fn)885 u32 execute_testcases_filelist(u8 *fn) {
886
887 u32 done = 0;
888 u8 buf[4096];
889 u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
890 FILE *f;
891
892 if (!be_quiet) { ACTF("Reading from '%s'...", fn); }
893
894 if ((f = fopen(fn, "r")) == NULL) { FATAL("could not open '%s'", fn); }
895
896 while (fgets(buf, sizeof(buf), f) != NULL) {
897
898 struct stat st;
899 u8 *fn2 = buf, *fn3;
900
901 while (*fn2 == ' ') {
902
903 ++fn2;
904
905 }
906
907 while (*fn2 &&
908 (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
909 fn2[strlen(fn2) - 1] == ' ')) {
910
911 fn2[strlen(fn2) - 1] = 0;
912
913 }
914
915 if (debug) { printf("Getting coverage for '%s'\n", fn2); }
916
917 if (!*fn2) { continue; }
918
919 if (lstat(fn2, &st) || access(fn2, R_OK)) {
920
921 WARNF("Unable to access '%s'", fn2);
922 continue;
923
924 }
925
926 ++done;
927
928 if (!S_ISREG(st.st_mode) || !st.st_size) { continue; }
929
930 if ((fn3 = strrchr(fn2, '/'))) {
931
932 ++fn3;
933
934 } else {
935
936 fn3 = fn2;
937
938 }
939
940 if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) {
941
942 WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
943 stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
944 stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
945
946 }
947
948 if (!collect_coverage) {
949
950 snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3);
951
952 }
953
954 if (read_file(fn2)) {
955
956 if (wait_for_gdb) {
957
958 fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
959 fprintf(stderr, "exec: kill -CONT %d\n", getpid());
960 kill(0, SIGSTOP);
961
962 }
963
964 showmap_run_target_forkserver(fsrv, in_data, in_len);
965 ck_free(in_data);
966
967 if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
968
969 if (collect_coverage)
970 analyze_results(fsrv);
971 else
972 tcnt = write_results_to_file(fsrv, outfile);
973
974 }
975
976 }
977
978 return done;
979
980 }
981
982 /* Show banner. */
983
show_banner(void)984 static void show_banner(void) {
985
986 SAYF(cCYA "afl-showmap" VERSION cRST " by Michal Zalewski\n");
987
988 }
989
990 /* Display usage hints. */
991
usage(u8 * argv0)992 static void usage(u8 *argv0) {
993
994 show_banner();
995
996 SAYF(
997 "\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
998
999 "Required parameters:\n"
1000 " -o file - file to write the trace data to\n\n"
1001
1002 "Execution control settings:\n"
1003 " -t msec - timeout for each run (default: 1000ms)\n"
1004 " -m megs - memory limit for child process (default: none)\n"
1005 #if defined(__linux__) && defined(__aarch64__)
1006 " -A - use binary-only instrumentation (ARM CoreSight mode)\n"
1007 #endif
1008 " -O - use binary-only instrumentation (FRIDA mode)\n"
1009 #if defined(__linux__)
1010 " -Q - use binary-only instrumentation (QEMU mode)\n"
1011 " -U - use Unicorn-based instrumentation (Unicorn mode)\n"
1012 " -W - use qemu-based instrumentation with Wine (Wine mode)\n"
1013 " (Not necessary, here for consistency with other afl-* "
1014 "tools)\n"
1015 " -X - use Nyx mode\n"
1016 #endif
1017 "\n"
1018 "Other settings:\n"
1019 " -i dir - process all files below this directory, must be combined "
1020 "with -o.\n"
1021 " With -C, -o is a file, without -C it must be a "
1022 "directory\n"
1023 " and each bitmap will be written there individually.\n"
1024 " -I filelist - alternatively to -i, -I is a list of files\n"
1025 " -C - collect coverage, writes all edges to -o and gives a "
1026 "summary\n"
1027 " Must be combined with -i.\n"
1028 " -q - sink program's output and don't show messages\n"
1029 " -e - show edge coverage only, ignore hit counts\n"
1030 " -r - show real tuple values instead of AFL filter values\n"
1031 " -s - do not classify the map\n"
1032 " -c - allow core dumps\n\n"
1033
1034 "This tool displays raw tuple data captured by AFL instrumentation.\n"
1035 "For additional help, consult %s/README.md.\n\n"
1036
1037 "If you use -i/-I mode, then custom mutator post_process send send "
1038 "functionality\n"
1039 "is supported.\n\n"
1040
1041 "Environment variables used:\n"
1042 "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
1043 "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
1044 "inputs\n"
1045 "AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
1046 "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
1047 "crash\n"
1048 "AFL_DEBUG: enable extra developer output\n"
1049 "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
1050 "startup (in milliseconds)\n"
1051 "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, "
1052 "etc.\n"
1053 " (default: SIGKILL)\n"
1054 "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on "
1055 "termination\n"
1056 " (default: SIGTERM). If unset and "
1057 "AFL_KILL_SIGNAL is\n"
1058 " set, that value will be used.\n"
1059 "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
1060 "size the\n"
1061 " target was compiled for\n"
1062 "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
1063 "AFL_PRINT_FILENAMES: Print the queue entry currently processed will to "
1064 "stdout\n"
1065 "AFL_QUIET: do not print extra informational output\n"
1066 "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n",
1067 argv0, doc_path);
1068
1069 exit(1);
1070
1071 }
1072
1073 /* Main entry point */
1074
main(int argc,char ** argv_orig,char ** envp)1075 int main(int argc, char **argv_orig, char **envp) {
1076
1077 // TODO: u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
1078
1079 s32 opt, i;
1080 bool mem_limit_given = false, timeout_given = false, unicorn_mode = false,
1081 use_wine = false;
1082 char **use_argv;
1083
1084 char **argv = argv_cpy_dup(argc, argv_orig);
1085
1086 afl_forkserver_t fsrv_var = {0};
1087 if (getenv("AFL_DEBUG")) { debug = true; }
1088 if (get_afl_env("AFL_PRINT_FILENAMES")) { print_filenames = true; }
1089
1090 fsrv = &fsrv_var;
1091 afl_fsrv_init(fsrv);
1092 map_size = get_map_size();
1093 fsrv->map_size = map_size;
1094
1095 doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
1096
1097 if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
1098
1099 while ((opt = getopt(argc, argv, "+i:I:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
1100
1101 switch (opt) {
1102
1103 case 's':
1104 no_classify = true;
1105 break;
1106
1107 case 'C':
1108 collect_coverage = true;
1109 quiet_mode = true;
1110 break;
1111
1112 case 'i':
1113 if (in_dir) { FATAL("Multiple -i options not supported"); }
1114 in_dir = optarg;
1115 break;
1116
1117 case 'I':
1118 if (in_filelist) { FATAL("Multiple -I options not supported"); }
1119 in_filelist = optarg;
1120 break;
1121
1122 case 'o':
1123
1124 if (out_file) { FATAL("Multiple -o options not supported"); }
1125 out_file = optarg;
1126 break;
1127
1128 case 'm': {
1129
1130 u8 suffix = 'M';
1131
1132 if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
1133 mem_limit_given = true;
1134
1135 if (!optarg) { FATAL("Wrong usage of -m"); }
1136
1137 if (!strcmp(optarg, "none")) {
1138
1139 fsrv->mem_limit = 0;
1140 break;
1141
1142 }
1143
1144 if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
1145 optarg[0] == '-') {
1146
1147 FATAL("Bad syntax used for -m");
1148
1149 }
1150
1151 switch (suffix) {
1152
1153 case 'T':
1154 fsrv->mem_limit *= 1024 * 1024;
1155 break;
1156 case 'G':
1157 fsrv->mem_limit *= 1024;
1158 break;
1159 case 'k':
1160 fsrv->mem_limit /= 1024;
1161 break;
1162 case 'M':
1163 break;
1164
1165 default:
1166 FATAL("Unsupported suffix or bad syntax for -m");
1167
1168 }
1169
1170 if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
1171
1172 if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
1173
1174 FATAL("Value of -m out of range on 32-bit systems");
1175
1176 }
1177
1178 }
1179
1180 break;
1181
1182 case 'f': // only in here to avoid a compiler warning for use_stdin
1183
1184 FATAL("Option -f is not supported in afl-showmap");
1185 // currently not reached:
1186 fsrv->use_stdin = 0;
1187 fsrv->out_file = strdup(optarg);
1188
1189 break;
1190
1191 case 't':
1192
1193 if (timeout_given) { FATAL("Multiple -t options not supported"); }
1194 timeout_given = true;
1195
1196 if (!optarg) { FATAL("Wrong usage of -t"); }
1197
1198 if (strcmp(optarg, "none")) {
1199
1200 fsrv->exec_tmout = atoi(optarg);
1201
1202 if (fsrv->exec_tmout < 20 || optarg[0] == '-') {
1203
1204 FATAL("Dangerously low value of -t");
1205
1206 }
1207
1208 } else {
1209
1210 // The forkserver code does not have a way to completely
1211 // disable the timeout, so we'll use a very, very long
1212 // timeout instead.
1213 WARNF(
1214 "Setting an execution timeout of 120 seconds ('none' is not "
1215 "allowed).");
1216 fsrv->exec_tmout = 120 * 1000;
1217
1218 }
1219
1220 break;
1221
1222 case 'e':
1223
1224 if (edges_only) { FATAL("Multiple -e options not supported"); }
1225 if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); }
1226 edges_only = true;
1227 break;
1228
1229 case 'q':
1230
1231 quiet_mode = true;
1232 break;
1233
1234 case 'Z':
1235
1236 /* This is an undocumented option to write data in the syntax expected
1237 by afl-cmin. Nobody else should have any use for this. */
1238
1239 cmin_mode = true;
1240 quiet_mode = true;
1241 break;
1242
1243 case 'H':
1244 /* Another afl-cmin specific feature. */
1245 at_file = optarg;
1246 break;
1247
1248 case 'O': /* FRIDA mode */
1249
1250 if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
1251
1252 fsrv->frida_mode = true;
1253 setenv("AFL_FRIDA_INST_SEED", "1", 1);
1254
1255 break;
1256
1257 /* FIXME: We want to use -P for consistency, but it is already unsed for
1258 * undocumenetd feature "Another afl-cmin specific feature." */
1259 case 'A': /* CoreSight mode */
1260
1261 #if !defined(__aarch64__) || !defined(__linux__)
1262 FATAL("-A option is not supported on this platform");
1263 #endif
1264
1265 if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
1266
1267 fsrv->cs_mode = true;
1268 break;
1269
1270 case 'Q':
1271
1272 if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
1273
1274 fsrv->qemu_mode = true;
1275 break;
1276
1277 case 'U':
1278
1279 if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
1280
1281 unicorn_mode = true;
1282 break;
1283
1284 case 'W': /* Wine+QEMU mode */
1285
1286 if (use_wine) { FATAL("Multiple -W options not supported"); }
1287 fsrv->qemu_mode = true;
1288 use_wine = true;
1289
1290 break;
1291
1292 case 'Y': // fallthrough
1293 #ifdef __linux__
1294 case 'X': /* NYX mode */
1295
1296 if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
1297
1298 fsrv->nyx_mode = 1;
1299 fsrv->nyx_parent = true;
1300 fsrv->nyx_standalone = true;
1301
1302 break;
1303 #else
1304 case 'X':
1305 FATAL("Nyx mode is only availabe on linux...");
1306 break;
1307 #endif
1308
1309 case 'b':
1310
1311 /* Secret undocumented mode. Writes output in raw binary format
1312 similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */
1313
1314 binary_mode = true;
1315 break;
1316
1317 case 'c':
1318
1319 if (keep_cores) { FATAL("Multiple -c options not supported"); }
1320 keep_cores = true;
1321 break;
1322
1323 case 'r':
1324
1325 if (raw_instr_output) { FATAL("Multiple -r options not supported"); }
1326 if (edges_only) { FATAL("-e and -r are mutually exclusive"); }
1327 raw_instr_output = true;
1328 break;
1329
1330 case 'h':
1331 usage(argv[0]);
1332 return -1;
1333 break;
1334
1335 default:
1336 usage(argv[0]);
1337
1338 }
1339
1340 }
1341
1342 if (optind == argc || !out_file) { usage(argv[0]); }
1343
1344 if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
1345
1346 if (in_dir || in_filelist) {
1347
1348 if (!out_file && !collect_coverage)
1349 FATAL("for -i/-I you need to specify either -C and/or -o");
1350
1351 }
1352
1353 if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
1354 if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
1355
1356 check_environment_vars(envp);
1357
1358 if (getenv("AFL_NO_FORKSRV")) { /* if set, use the fauxserver */
1359 fsrv->use_fauxsrv = true;
1360
1361 }
1362
1363 if (getenv("AFL_DEBUG")) {
1364
1365 DEBUGF("");
1366 for (i = 0; i < argc; i++)
1367 SAYF(" %s", argv[i]);
1368 SAYF("\n");
1369
1370 }
1371
1372 // if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
1373
1374 setenv("AFL_NO_AUTODICT", "1", 1);
1375
1376 /* initialize cmplog_mode */
1377 shm.cmplog_mode = 0;
1378 setup_signal_handlers();
1379
1380 set_up_environment(fsrv, argv);
1381
1382 #ifdef __linux__
1383 if (!fsrv->nyx_mode) {
1384
1385 fsrv->target_path = find_binary(argv[optind]);
1386
1387 } else {
1388
1389 fsrv->target_path = ck_strdup(argv[optind]);
1390
1391 }
1392
1393 #else
1394 fsrv->target_path = find_binary(argv[optind]);
1395 #endif
1396
1397 fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
1398
1399 if (!quiet_mode) {
1400
1401 show_banner();
1402 ACTF("Executing '%s'...", fsrv->target_path);
1403
1404 }
1405
1406 if (in_dir || in_filelist) {
1407
1408 /* If we don't have a file name chosen yet, use a safe default. */
1409 u8 *use_dir = ".";
1410
1411 if (access(use_dir, R_OK | W_OK | X_OK)) {
1412
1413 use_dir = get_afl_env("TMPDIR");
1414 if (!use_dir) { use_dir = "/tmp"; }
1415
1416 }
1417
1418 stdin_file = at_file ? strdup(at_file)
1419 : (char *)alloc_printf("%s/.afl-showmap-temp-%u",
1420 use_dir, (u32)getpid());
1421 unlink(stdin_file);
1422
1423 // If @@ are in the target args, replace them and also set use_stdin=false.
1424 detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
1425
1426 fsrv->dev_null_fd = open("/dev/null", O_RDWR);
1427 if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
1428
1429 fsrv->out_file = stdin_file;
1430 fsrv->out_fd =
1431 open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
1432 if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); }
1433
1434 } else {
1435
1436 // If @@ are in the target args, replace them and also set use_stdin=false.
1437 detect_file_args(argv + optind, at_file, &fsrv->use_stdin);
1438
1439 }
1440
1441 if (fsrv->qemu_mode) {
1442
1443 if (use_wine) {
1444
1445 use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind,
1446 argv + optind);
1447
1448 } else {
1449
1450 use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind,
1451 argv + optind);
1452
1453 }
1454
1455 } else if (fsrv->cs_mode) {
1456
1457 use_argv =
1458 get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
1459
1460 #ifdef __linux__
1461
1462 } else if (fsrv->nyx_mode) {
1463
1464 use_argv = ck_alloc(sizeof(char *) * (1));
1465 use_argv[0] = argv[0];
1466
1467 fsrv->nyx_id = 0;
1468
1469 u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
1470 fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
1471 if (fsrv->nyx_handlers == NULL) {
1472
1473 FATAL("failed to initialize libnyx.so...");
1474
1475 }
1476
1477 fsrv->nyx_use_tmp_workdir = true;
1478 fsrv->nyx_bind_cpu_id = 0;
1479 #endif
1480
1481 } else {
1482
1483 use_argv = argv + optind;
1484
1485 }
1486
1487 afl = calloc(1, sizeof(afl_state_t));
1488
1489 if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
1490
1491 s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
1492 if (forksrv_init_tmout < 1) {
1493
1494 FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
1495
1496 }
1497
1498 fsrv->init_tmout = (u32)forksrv_init_tmout;
1499
1500 }
1501
1502 if (getenv("AFL_CRASH_EXITCODE")) {
1503
1504 long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
1505 if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
1506 exitcode < -127 || exitcode > 128) {
1507
1508 FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
1509 getenv("AFL_CRASH_EXITCODE"));
1510
1511 }
1512
1513 fsrv->uses_crash_exitcode = true;
1514 // WEXITSTATUS is 8 bit unsigned
1515 fsrv->crash_exitcode = (u8)exitcode;
1516
1517 }
1518
1519 #ifdef __linux__
1520 if (!fsrv->nyx_mode && (in_dir || in_filelist)) {
1521
1522 (void)check_binary_signatures(fsrv->target_path);
1523
1524 }
1525
1526 #else
1527 if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
1528 #endif
1529
1530 shm_fuzz = ck_alloc(sizeof(sharedmem_t));
1531
1532 /* initialize cmplog_mode */
1533 shm_fuzz->cmplog_mode = 0;
1534 u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
1535 shm_fuzz->shmemfuzz_mode = true;
1536 if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
1537 #ifdef USEMMAP
1538 setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1);
1539 #else
1540 u8 *shm_str = alloc_printf("%d", shm_fuzz->shm_id);
1541 setenv(SHM_FUZZ_ENV_VAR, shm_str, 1);
1542 ck_free(shm_str);
1543 #endif
1544 fsrv->support_shmem_fuzz = true;
1545 fsrv->shmem_fuzz_len = (u32 *)map;
1546 fsrv->shmem_fuzz = map + sizeof(u32);
1547
1548 configure_afl_kill_signals(fsrv, NULL, NULL,
1549 (fsrv->qemu_mode || unicorn_mode
1550 #ifdef __linux__
1551 || fsrv->nyx_mode
1552 #endif
1553 )
1554 ? SIGKILL
1555 : SIGTERM);
1556
1557 if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
1558
1559 u32 save_be_quiet = be_quiet;
1560 be_quiet = !debug;
1561 if (map_size > 4194304) {
1562
1563 fsrv->map_size = map_size;
1564
1565 } else {
1566
1567 fsrv->map_size = 4194304; // dummy temporary value
1568
1569 }
1570
1571 u32 new_map_size =
1572 afl_fsrv_get_mapsize(fsrv, use_argv, &stop_soon,
1573 (get_afl_env("AFL_DEBUG_CHILD") ||
1574 get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
1575 ? 1
1576 : 0);
1577 be_quiet = save_be_quiet;
1578
1579 if (new_map_size) {
1580
1581 // only reinitialize when it makes sense
1582 if (map_size < new_map_size ||
1583 (new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) {
1584
1585 if (!be_quiet)
1586 ACTF("Acquired new map size for target: %u bytes\n", new_map_size);
1587
1588 afl_shm_deinit(&shm);
1589 afl_fsrv_kill(fsrv);
1590 fsrv->map_size = new_map_size;
1591 fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0);
1592
1593 }
1594
1595 map_size = new_map_size;
1596
1597 }
1598
1599 fsrv->map_size = map_size;
1600
1601 } else {
1602
1603 afl_fsrv_start(fsrv, use_argv, &stop_soon,
1604 (get_afl_env("AFL_DEBUG_CHILD") ||
1605 get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
1606 ? 1
1607 : 0);
1608
1609 }
1610
1611 if (in_dir || in_filelist) {
1612
1613 afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
1614 if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
1615 afl->afl_env.afl_custom_mutator_library =
1616 getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
1617 afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
1618 setup_custom_mutators(afl);
1619
1620 } else {
1621
1622 if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
1623
1624 WARNF(
1625 "Custom mutator environment detected, this is only supported in "
1626 "-i/-I mode!\n");
1627
1628 }
1629
1630 }
1631
1632 if (in_dir || in_filelist) {
1633
1634 DIR *dir_in, *dir_out = NULL;
1635 u8 *dn = NULL;
1636
1637 if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
1638
1639 if (in_filelist) {
1640
1641 if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
1642
1643 } else {
1644
1645 // if a queue subdirectory exists switch to that
1646 dn = alloc_printf("%s/queue", in_dir);
1647
1648 if ((dir_in = opendir(dn)) != NULL) {
1649
1650 closedir(dir_in);
1651 in_dir = dn;
1652
1653 } else {
1654
1655 ck_free(dn);
1656
1657 }
1658
1659 if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
1660
1661 }
1662
1663 if (!collect_coverage) {
1664
1665 if (!(dir_out = opendir(out_file))) {
1666
1667 if (mkdir(out_file, 0700)) {
1668
1669 PFATAL("cannot create output directory %s", out_file);
1670
1671 }
1672
1673 }
1674
1675 } else {
1676
1677 if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
1678 FATAL("coult not grab memory");
1679 edges_only = false;
1680 raw_instr_output = true;
1681
1682 }
1683
1684 atexit(at_exit_handler);
1685
1686 if (get_afl_env("AFL_DEBUG")) {
1687
1688 int j = optind;
1689 DEBUGF("%s:", fsrv->target_path);
1690 while (argv[j] != NULL) {
1691
1692 SAYF(" \"%s\"", argv[j++]);
1693
1694 }
1695
1696 SAYF("\n");
1697
1698 }
1699
1700 map_size = fsrv->map_size;
1701
1702 if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
1703 shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
1704
1705 if (in_dir) {
1706
1707 if (execute_testcases(in_dir) == 0) {
1708
1709 FATAL("could not read input testcases from %s", in_dir);
1710
1711 }
1712
1713 } else {
1714
1715 if (execute_testcases_filelist(in_filelist) == 0) {
1716
1717 FATAL("could not read input testcases from %s", in_filelist);
1718
1719 }
1720
1721 }
1722
1723 if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
1724
1725 if (dir_out) { closedir(dir_out); }
1726
1727 if (collect_coverage) {
1728
1729 memcpy(fsrv->trace_bits, coverage_map, map_size);
1730 tcnt = write_results_to_file(fsrv, out_file);
1731
1732 }
1733
1734 } else {
1735
1736 if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
1737 shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
1738
1739 #ifdef __linux__
1740 if (!fsrv->nyx_mode) {
1741
1742 #endif
1743 showmap_run_target(fsrv, use_argv);
1744 #ifdef __linux__
1745
1746 } else {
1747
1748 showmap_run_target_nyx_mode(fsrv);
1749
1750 }
1751
1752 #endif
1753 tcnt = write_results_to_file(fsrv, out_file);
1754 if (!quiet_mode) {
1755
1756 OKF("Hash of coverage map: %llx",
1757 hash64(fsrv->trace_bits, fsrv->map_size, HASH_CONST));
1758
1759 }
1760
1761 }
1762
1763 if (!quiet_mode || collect_coverage) {
1764
1765 if (!tcnt && !have_coverage) { FATAL("No instrumentation detected" cRST); }
1766 OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
1767 "in '%s'." cRST,
1768 tcnt, fsrv->real_map_size, highest, total, out_file);
1769 if (collect_coverage)
1770 OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
1771 "with %llu input files.",
1772 tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
1773 fsrv->total_execs);
1774
1775 }
1776
1777 if (stdin_file) {
1778
1779 unlink(stdin_file);
1780 ck_free(stdin_file);
1781 stdin_file = NULL;
1782
1783 }
1784
1785 remove_shm = 0;
1786 afl_shm_deinit(&shm);
1787 if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
1788
1789 u32 ret;
1790
1791 if (cmin_mode && !!getenv("AFL_CMIN_CRASHES_ONLY")) {
1792
1793 ret = fsrv->last_run_timed_out;
1794
1795 } else {
1796
1797 ret = child_crashed * 2 + fsrv->last_run_timed_out;
1798
1799 }
1800
1801 if (fsrv->target_path) { ck_free(fsrv->target_path); }
1802
1803 afl_fsrv_deinit(fsrv);
1804
1805 if (stdin_file) { ck_free(stdin_file); }
1806 if (collect_coverage) { free(coverage_map); }
1807
1808 argv_cpy_free(argv);
1809 if (fsrv->qemu_mode) { free(use_argv[2]); }
1810
1811 exit(ret);
1812
1813 }
1814
1815