1 /*
2    american fuzzy lop - file format analyzer
3    -----------------------------------------
4 
5    Written and maintained by Michal Zalewski <lcamtuf@google.com>
6 
7    Copyright 2016, 2017 Google Inc. All rights reserved.
8 
9    Licensed under the Apache License, Version 2.0 (the "License");
10    you may not use this file except in compliance with the License.
11    You may obtain a copy of the License at:
12 
13      http://www.apache.org/licenses/LICENSE-2.0
14 
15    A nifty utility that grabs an input file and takes a stab at explaining
16    its structure by observing how changes to it affect the execution path.
17 
18    If the output scrolls past the edge of the screen, pipe it to 'less -r'.
19 
20  */
21 
22 #define AFL_MAIN
23 
24 #include "config.h"
25 #include "types.h"
26 #include "debug.h"
27 #include "alloc-inl.h"
28 #include "hash.h"
29 
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40 
41 #include <sys/wait.h>
42 #include <sys/time.h>
43 #include <sys/shm.h>
44 #include <sys/stat.h>
45 #include <sys/types.h>
46 #include <sys/resource.h>
47 
48 static s32 child_pid;                 /* PID of the tested program         */
49 
50 static u8* trace_bits;                /* SHM with instrumentation bitmap   */
51 
52 static u8 *in_file,                   /* Analyzer input test case          */
53           *prog_in,                   /* Targeted program input file       */
54           *target_path,               /* Path to target binary             */
55           *doc_path;                  /* Path to docs                      */
56 
57 static u8 *in_data;                   /* Input data for analysis           */
58 
59 static u32 in_len,                    /* Input data length                 */
60            orig_cksum,                /* Original checksum                 */
61            total_execs,               /* Total number of execs             */
62            exec_hangs,                /* Total number of hangs             */
63            exec_tmout = EXEC_TIMEOUT; /* Exec timeout (ms)                 */
64 
65 static u64 mem_limit = MEM_LIMIT;     /* Memory limit (MB)                 */
66 
67 static s32 shm_id,                    /* ID of the SHM region              */
68            dev_null_fd = -1;          /* FD to /dev/null                   */
69 
70 static u8  edges_only,                /* Ignore hit counts?                */
71            use_hex_offsets,           /* Show hex offsets?                 */
72            use_stdin = 1;             /* Use stdin for program input?      */
73 
74 static volatile u8
75            stop_soon,                 /* Ctrl-C pressed?                   */
76            child_timed_out;           /* Child timed out?                  */
77 
78 
79 /* Constants used for describing byte behavior. */
80 
81 #define RESP_NONE       0x00          /* Changing byte is a no-op.         */
82 #define RESP_MINOR      0x01          /* Some changes have no effect.      */
83 #define RESP_VARIABLE   0x02          /* Changes produce variable paths.   */
84 #define RESP_FIXED      0x03          /* Changes produce fixed patterns.   */
85 
86 #define RESP_LEN        0x04          /* Potential length field            */
87 #define RESP_CKSUM      0x05          /* Potential checksum                */
88 #define RESP_SUSPECT    0x06          /* Potential "suspect" blob          */
89 
90 
91 /* Classify tuple counts. This is a slow & naive version, but good enough here. */
92 
93 static u8 count_class_lookup[256] = {
94 
95   [0]           = 0,
96   [1]           = 1,
97   [2]           = 2,
98   [3]           = 4,
99   [4 ... 7]     = 8,
100   [8 ... 15]    = 16,
101   [16 ... 31]   = 32,
102   [32 ... 127]  = 64,
103   [128 ... 255] = 128
104 
105 };
106 
classify_counts(u8 * mem)107 static void classify_counts(u8* mem) {
108 
109   u32 i = MAP_SIZE;
110 
111   if (edges_only) {
112 
113     while (i--) {
114       if (*mem) *mem = 1;
115       mem++;
116     }
117 
118   } else {
119 
120     while (i--) {
121       *mem = count_class_lookup[*mem];
122       mem++;
123     }
124 
125   }
126 
127 }
128 
129 
130 /* See if any bytes are set in the bitmap. */
131 
anything_set(void)132 static inline u8 anything_set(void) {
133 
134   u32* ptr = (u32*)trace_bits;
135   u32  i   = (MAP_SIZE >> 2);
136 
137   while (i--) if (*(ptr++)) return 1;
138 
139   return 0;
140 
141 }
142 
143 
144 /* Get rid of shared memory and temp files (atexit handler). */
145 
remove_shm(void)146 static void remove_shm(void) {
147 
148   unlink(prog_in); /* Ignore errors */
149   shmctl(shm_id, IPC_RMID, NULL);
150 
151 }
152 
153 
154 /* Configure shared memory. */
155 
setup_shm(void)156 static void setup_shm(void) {
157 
158   u8* shm_str;
159 
160   shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
161 
162   if (shm_id < 0) PFATAL("shmget() failed");
163 
164   atexit(remove_shm);
165 
166   shm_str = alloc_printf("%d", shm_id);
167 
168   setenv(SHM_ENV_VAR, shm_str, 1);
169 
170   ck_free(shm_str);
171 
172   trace_bits = shmat(shm_id, NULL, 0);
173 
174   if (!trace_bits) PFATAL("shmat() failed");
175 
176 }
177 
178 
179 /* Read initial file. */
180 
read_initial_file(void)181 static void read_initial_file(void) {
182 
183   struct stat st;
184   s32 fd = open(in_file, O_RDONLY);
185 
186   if (fd < 0) PFATAL("Unable to open '%s'", in_file);
187 
188   if (fstat(fd, &st) || !st.st_size)
189     FATAL("Zero-sized input file.");
190 
191   if (st.st_size >= TMIN_MAX_FILE)
192     FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
193 
194   in_len  = st.st_size;
195   in_data = ck_alloc_nozero(in_len);
196 
197   ck_read(fd, in_data, in_len, in_file);
198 
199   close(fd);
200 
201   OKF("Read %u byte%s from '%s'.", in_len, in_len == 1 ? "" : "s", in_file);
202 
203 }
204 
205 
206 /* Write output file. */
207 
write_to_file(u8 * path,u8 * mem,u32 len)208 static s32 write_to_file(u8* path, u8* mem, u32 len) {
209 
210   s32 ret;
211 
212   unlink(path); /* Ignore errors */
213 
214   ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
215 
216   if (ret < 0) PFATAL("Unable to create '%s'", path);
217 
218   ck_write(ret, mem, len, path);
219 
220   lseek(ret, 0, SEEK_SET);
221 
222   return ret;
223 
224 }
225 
226 
227 /* Handle timeout signal. */
228 
handle_timeout(int sig)229 static void handle_timeout(int sig) {
230 
231   child_timed_out = 1;
232   if (child_pid > 0) kill(child_pid, SIGKILL);
233 
234 }
235 
236 
237 /* Execute target application. Returns exec checksum, or 0 if program
238    times out. */
239 
run_target(char ** argv,u8 * mem,u32 len,u8 first_run)240 static u32 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
241 
242   static struct itimerval it;
243   int status = 0;
244 
245   s32 prog_in_fd;
246   u32 cksum;
247 
248   memset(trace_bits, 0, MAP_SIZE);
249   MEM_BARRIER();
250 
251   prog_in_fd = write_to_file(prog_in, mem, len);
252 
253   child_pid = fork();
254 
255   if (child_pid < 0) PFATAL("fork() failed");
256 
257   if (!child_pid) {
258 
259     struct rlimit r;
260 
261     if (dup2(use_stdin ? prog_in_fd : dev_null_fd, 0) < 0 ||
262         dup2(dev_null_fd, 1) < 0 ||
263         dup2(dev_null_fd, 2) < 0) {
264 
265       *(u32*)trace_bits = EXEC_FAIL_SIG;
266       PFATAL("dup2() failed");
267 
268     }
269 
270     close(dev_null_fd);
271     close(prog_in_fd);
272 
273     if (mem_limit) {
274 
275       r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
276 
277 #ifdef RLIMIT_AS
278 
279       setrlimit(RLIMIT_AS, &r); /* Ignore errors */
280 
281 #else
282 
283       setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
284 
285 #endif /* ^RLIMIT_AS */
286 
287     }
288 
289     r.rlim_max = r.rlim_cur = 0;
290     setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
291 
292     execv(target_path, argv);
293 
294     *(u32*)trace_bits = EXEC_FAIL_SIG;
295     exit(0);
296 
297   }
298 
299   close(prog_in_fd);
300 
301   /* Configure timeout, wait for child, cancel timeout. */
302 
303   child_timed_out = 0;
304   it.it_value.tv_sec = (exec_tmout / 1000);
305   it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
306 
307   setitimer(ITIMER_REAL, &it, NULL);
308 
309   if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed");
310 
311   child_pid = 0;
312   it.it_value.tv_sec = 0;
313   it.it_value.tv_usec = 0;
314 
315   setitimer(ITIMER_REAL, &it, NULL);
316 
317   MEM_BARRIER();
318 
319   /* Clean up bitmap, analyze exit condition, etc. */
320 
321   if (*(u32*)trace_bits == EXEC_FAIL_SIG)
322     FATAL("Unable to execute '%s'", argv[0]);
323 
324   classify_counts(trace_bits);
325   total_execs++;
326 
327   if (stop_soon) {
328     SAYF(cRST cLRD "\n+++ Analysis aborted by user +++\n" cRST);
329     exit(1);
330   }
331 
332   /* Always discard inputs that time out. */
333 
334   if (child_timed_out) {
335 
336     exec_hangs++;
337     return 0;
338 
339   }
340 
341   cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
342 
343   /* We don't actually care if the target is crashing or not,
344      except that when it does, the checksum should be different. */
345 
346   if (WIFSIGNALED(status) ||
347       (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
348       (WIFEXITED(status) && WEXITSTATUS(status))) {
349 
350     cksum ^= 0xffffffff;
351 
352   }
353 
354   if (first_run) orig_cksum = cksum;
355 
356   return cksum;
357 
358 }
359 
360 
361 #ifdef USE_COLOR
362 
363 /* Helper function to display a human-readable character. */
364 
show_char(u8 val)365 static void show_char(u8 val) {
366 
367   switch (val) {
368 
369     case 0 ... 32:
370     case 127 ... 255: SAYF("#%02x", val); break;
371 
372     default: SAYF(" %c ", val);
373 
374   }
375 
376 }
377 
378 
379 /* Show the legend */
380 
show_legend(void)381 static void show_legend(void) {
382 
383   SAYF("    " cLGR bgGRA " 01 " cRST " - no-op block              "
384               cBLK bgLGN " 01 " cRST " - suspected length field\n"
385        "    " cBRI bgGRA " 01 " cRST " - superficial content      "
386               cBLK bgYEL " 01 " cRST " - suspected cksum or magic int\n"
387        "    " cBLK bgCYA " 01 " cRST " - critical stream          "
388               cBLK bgLRD " 01 " cRST " - suspected checksummed block\n"
389        "    " cBLK bgMGN " 01 " cRST " - \"magic value\" section\n\n");
390 
391 }
392 
393 #endif /* USE_COLOR */
394 
395 
396 /* Interpret and report a pattern in the input file. */
397 
dump_hex(u8 * buf,u32 len,u8 * b_data)398 static void dump_hex(u8* buf, u32 len, u8* b_data) {
399 
400   u32 i;
401 
402   for (i = 0; i < len; i++) {
403 
404 #ifdef USE_COLOR
405     u32 rlen = 1, off;
406 #else
407     u32 rlen = 1;
408 #endif /* ^USE_COLOR */
409 
410     u8  rtype = b_data[i] & 0x0f;
411 
412     /* Look ahead to determine the length of run. */
413 
414     while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) {
415 
416       if (rtype < (b_data[i + rlen] & 0x0f)) rtype = b_data[i + rlen] & 0x0f;
417       rlen++;
418 
419     }
420 
421     /* Try to do some further classification based on length & value. */
422 
423     if (rtype == RESP_FIXED) {
424 
425       switch (rlen) {
426 
427         case 2: {
428 
429             u16 val = *(u16*)(in_data + i);
430 
431             /* Small integers may be length fields. */
432 
433             if (val && (val <= in_len || SWAP16(val) <= in_len)) {
434               rtype = RESP_LEN;
435               break;
436             }
437 
438             /* Uniform integers may be checksums. */
439 
440             if (val && abs(in_data[i] - in_data[i + 1]) > 32) {
441               rtype = RESP_CKSUM;
442               break;
443             }
444 
445             break;
446 
447           }
448 
449         case 4: {
450 
451             u32 val = *(u32*)(in_data + i);
452 
453             /* Small integers may be length fields. */
454 
455             if (val && (val <= in_len || SWAP32(val) <= in_len)) {
456               rtype = RESP_LEN;
457               break;
458             }
459 
460             /* Uniform integers may be checksums. */
461 
462             if (val && (in_data[i] >> 7 != in_data[i + 1] >> 7 ||
463                 in_data[i] >> 7 != in_data[i + 2] >> 7 ||
464                 in_data[i] >> 7 != in_data[i + 3] >> 7)) {
465               rtype = RESP_CKSUM;
466               break;
467             }
468 
469             break;
470 
471           }
472 
473         case 1: case 3: case 5 ... MAX_AUTO_EXTRA - 1: break;
474 
475         default: rtype = RESP_SUSPECT;
476 
477       }
478 
479     }
480 
481     /* Print out the entire run. */
482 
483 #ifdef USE_COLOR
484 
485     for (off = 0; off < rlen; off++) {
486 
487       /* Every 16 digits, display offset. */
488 
489       if (!((i + off) % 16)) {
490 
491         if (off) SAYF(cRST cLCY ">");
492 
493         if (use_hex_offsets)
494           SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off);
495         else
496           SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off);
497 
498       }
499 
500       switch (rtype) {
501 
502         case RESP_NONE:     SAYF(cLGR bgGRA); break;
503         case RESP_MINOR:    SAYF(cBRI bgGRA); break;
504         case RESP_VARIABLE: SAYF(cBLK bgCYA); break;
505         case RESP_FIXED:    SAYF(cBLK bgMGN); break;
506         case RESP_LEN:      SAYF(cBLK bgLGN); break;
507         case RESP_CKSUM:    SAYF(cBLK bgYEL); break;
508         case RESP_SUSPECT:  SAYF(cBLK bgLRD); break;
509 
510       }
511 
512       show_char(in_data[i + off]);
513 
514       if (off != rlen - 1 && (i + off + 1) % 16) SAYF(" "); else SAYF(cRST " ");
515 
516     }
517 
518 #else
519 
520     if (use_hex_offsets)
521       SAYF("    Offset %x, length %u: ", i, rlen);
522     else
523       SAYF("    Offset %u, length %u: ", i, rlen);
524 
525     switch (rtype) {
526 
527       case RESP_NONE:     SAYF("no-op block\n"); break;
528       case RESP_MINOR:    SAYF("superficial content\n"); break;
529       case RESP_VARIABLE: SAYF("critical stream\n"); break;
530       case RESP_FIXED:    SAYF("\"magic value\" section\n"); break;
531       case RESP_LEN:      SAYF("suspected length field\n"); break;
532       case RESP_CKSUM:    SAYF("suspected cksum or magic int\n"); break;
533       case RESP_SUSPECT:  SAYF("suspected checksummed block\n"); break;
534 
535     }
536 
537 #endif /* ^USE_COLOR */
538 
539     i += rlen - 1;
540 
541   }
542 
543 #ifdef USE_COLOR
544   SAYF(cRST "\n");
545 #endif /* USE_COLOR */
546 
547 }
548 
549 
550 
551 /* Actually analyze! */
552 
analyze(char ** argv)553 static void analyze(char** argv) {
554 
555   u32 i;
556   u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0;
557 
558   u8* b_data = ck_alloc(in_len + 1);
559   u8  seq_byte = 0;
560 
561   b_data[in_len] = 0xff; /* Intentional terminator. */
562 
563   ACTF("Analyzing input file (this may take a while)...\n");
564 
565 #ifdef USE_COLOR
566   show_legend();
567 #endif /* USE_COLOR */
568 
569   for (i = 0; i < in_len; i++) {
570 
571     u32 xor_ff, xor_01, sub_10, add_10;
572     u8  xff_orig, x01_orig, s10_orig, a10_orig;
573 
574     /* Perform walking byte adjustments across the file. We perform four
575        operations designed to elicit some response from the underlying
576        code. */
577 
578     in_data[i] ^= 0xff;
579     xor_ff = run_target(argv, in_data, in_len, 0);
580 
581     in_data[i] ^= 0xfe;
582     xor_01 = run_target(argv, in_data, in_len, 0);
583 
584     in_data[i] = (in_data[i] ^ 0x01) - 0x10;
585     sub_10 = run_target(argv, in_data, in_len, 0);
586 
587     in_data[i] += 0x20;
588     add_10 = run_target(argv, in_data, in_len, 0);
589     in_data[i] -= 0x10;
590 
591     /* Classify current behavior. */
592 
593     xff_orig = (xor_ff == orig_cksum);
594     x01_orig = (xor_01 == orig_cksum);
595     s10_orig = (sub_10 == orig_cksum);
596     a10_orig = (add_10 == orig_cksum);
597 
598     if (xff_orig && x01_orig && s10_orig && a10_orig) {
599 
600       b_data[i] = RESP_NONE;
601       boring_len++;
602 
603     } else if (xff_orig || x01_orig || s10_orig || a10_orig) {
604 
605       b_data[i] = RESP_MINOR;
606       boring_len++;
607 
608     } else if (xor_ff == xor_01 && xor_ff == sub_10 && xor_ff == add_10) {
609 
610       b_data[i] = RESP_FIXED;
611 
612     } else b_data[i] = RESP_VARIABLE;
613 
614     /* When all checksums change, flip most significant bit of b_data. */
615 
616     if (prev_xff != xor_ff && prev_x01 != xor_01 &&
617         prev_s10 != sub_10 && prev_a10 != add_10) seq_byte ^= 0x80;
618 
619     b_data[i] |= seq_byte;
620 
621     prev_xff = xor_ff;
622     prev_x01 = xor_01;
623     prev_s10 = sub_10;
624     prev_a10 = add_10;
625 
626   }
627 
628   dump_hex(in_data, in_len, b_data);
629 
630   SAYF("\n");
631 
632   OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.",
633       100.0 - ((double)boring_len * 100) / in_len);
634 
635   if (exec_hangs)
636     WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST,
637           exec_hangs);
638 
639   ck_free(b_data);
640 
641 }
642 
643 
644 
645 /* Handle Ctrl-C and the like. */
646 
handle_stop_sig(int sig)647 static void handle_stop_sig(int sig) {
648 
649   stop_soon = 1;
650 
651   if (child_pid > 0) kill(child_pid, SIGKILL);
652 
653 }
654 
655 
656 /* Do basic preparations - persistent fds, filenames, etc. */
657 
set_up_environment(void)658 static void set_up_environment(void) {
659 
660   u8* x;
661 
662   dev_null_fd = open("/dev/null", O_RDWR);
663   if (dev_null_fd < 0) PFATAL("Unable to open /dev/null");
664 
665   if (!prog_in) {
666 
667     u8* use_dir = ".";
668 
669     if (access(use_dir, R_OK | W_OK | X_OK)) {
670 
671       use_dir = getenv("TMPDIR");
672       if (!use_dir) use_dir = "/tmp";
673 
674     }
675 
676     prog_in = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, getpid());
677 
678   }
679 
680   /* Set sane defaults... */
681 
682   x = getenv("ASAN_OPTIONS");
683 
684   if (x) {
685 
686     if (!strstr(x, "abort_on_error=1"))
687       FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
688 
689     if (!strstr(x, "symbolize=0"))
690       FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
691 
692   }
693 
694   x = getenv("MSAN_OPTIONS");
695 
696   if (x) {
697 
698     if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR)))
699       FATAL("Custom MSAN_OPTIONS set without exit_code="
700             STRINGIFY(MSAN_ERROR) " - please fix!");
701 
702     if (!strstr(x, "symbolize=0"))
703       FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
704 
705   }
706 
707   setenv("ASAN_OPTIONS", "abort_on_error=1:"
708                          "detect_leaks=0:"
709                          "symbolize=0:"
710                          "allocator_may_return_null=1", 0);
711 
712   setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
713                          "symbolize=0:"
714                          "abort_on_error=1:"
715                          "allocator_may_return_null=1:"
716                          "msan_track_origins=0", 0);
717 
718   if (getenv("AFL_PRELOAD")) {
719     setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
720     setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
721   }
722 
723 }
724 
725 
726 /* Setup signal handlers, duh. */
727 
setup_signal_handlers(void)728 static void setup_signal_handlers(void) {
729 
730   struct sigaction sa;
731 
732   sa.sa_handler   = NULL;
733   sa.sa_flags     = SA_RESTART;
734   sa.sa_sigaction = NULL;
735 
736   sigemptyset(&sa.sa_mask);
737 
738   /* Various ways of saying "stop". */
739 
740   sa.sa_handler = handle_stop_sig;
741   sigaction(SIGHUP, &sa, NULL);
742   sigaction(SIGINT, &sa, NULL);
743   sigaction(SIGTERM, &sa, NULL);
744 
745   /* Exec timeout notifications. */
746 
747   sa.sa_handler = handle_timeout;
748   sigaction(SIGALRM, &sa, NULL);
749 
750 }
751 
752 
753 /* Detect @@ in args. */
754 
detect_file_args(char ** argv)755 static void detect_file_args(char** argv) {
756 
757   u32 i = 0;
758   u8* cwd = getcwd(NULL, 0);
759 
760   if (!cwd) PFATAL("getcwd() failed");
761 
762   while (argv[i]) {
763 
764     u8* aa_loc = strstr(argv[i], "@@");
765 
766     if (aa_loc) {
767 
768       u8 *aa_subst, *n_arg;
769 
770       /* Be sure that we're always using fully-qualified paths. */
771 
772       if (prog_in[0] == '/') aa_subst = prog_in;
773       else aa_subst = alloc_printf("%s/%s", cwd, prog_in);
774 
775       /* Construct a replacement argv value. */
776 
777       *aa_loc = 0;
778       n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2);
779       argv[i] = n_arg;
780       *aa_loc = '@';
781 
782       if (prog_in[0] != '/') ck_free(aa_subst);
783 
784     }
785 
786     i++;
787 
788   }
789 
790   free(cwd); /* not tracked */
791 
792 }
793 
794 
795 /* Display usage hints. */
796 
usage(u8 * argv0)797 static void usage(u8* argv0) {
798 
799   SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
800 
801        "Required parameters:\n\n"
802 
803        "  -i file       - input test case to be analyzed by the tool\n"
804 
805        "Execution control settings:\n\n"
806 
807        "  -f file       - input file read by the tested program (stdin)\n"
808        "  -t msec       - timeout for each run (%u ms)\n"
809        "  -m megs       - memory limit for child process (%u MB)\n"
810        "  -Q            - use binary-only instrumentation (QEMU mode)\n\n"
811 
812        "Analysis settings:\n\n"
813 
814        "  -e            - look for edge coverage only, ignore hit counts\n\n"
815 
816        "For additional tips, please consult %s/README.\n\n",
817 
818        argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
819 
820   exit(1);
821 
822 }
823 
824 
825 /* Find binary. */
826 
find_binary(u8 * fname)827 static void find_binary(u8* fname) {
828 
829   u8* env_path = 0;
830   struct stat st;
831 
832   if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
833 
834     target_path = ck_strdup(fname);
835 
836     if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
837         !(st.st_mode & 0111) || st.st_size < 4)
838       FATAL("Program '%s' not found or not executable", fname);
839 
840   } else {
841 
842     while (env_path) {
843 
844       u8 *cur_elem, *delim = strchr(env_path, ':');
845 
846       if (delim) {
847 
848         cur_elem = ck_alloc(delim - env_path + 1);
849         memcpy(cur_elem, env_path, delim - env_path);
850         delim++;
851 
852       } else cur_elem = ck_strdup(env_path);
853 
854       env_path = delim;
855 
856       if (cur_elem[0])
857         target_path = alloc_printf("%s/%s", cur_elem, fname);
858       else
859         target_path = ck_strdup(fname);
860 
861       ck_free(cur_elem);
862 
863       if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
864           (st.st_mode & 0111) && st.st_size >= 4) break;
865 
866       ck_free(target_path);
867       target_path = 0;
868 
869     }
870 
871     if (!target_path) FATAL("Program '%s' not found or not executable", fname);
872 
873   }
874 
875 }
876 
877 
878 /* Fix up argv for QEMU. */
879 
get_qemu_argv(u8 * own_loc,char ** argv,int argc)880 static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
881 
882   char** new_argv = ck_alloc(sizeof(char*) * (argc + 4));
883   u8 *tmp, *cp, *rsl, *own_copy;
884 
885   /* Workaround for a QEMU stability glitch. */
886 
887   setenv("QEMU_LOG", "nochain", 1);
888 
889   memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc);
890 
891   /* Now we need to actually find qemu for argv[0]. */
892 
893   new_argv[2] = target_path;
894   new_argv[1] = "--";
895 
896   tmp = getenv("AFL_PATH");
897 
898   if (tmp) {
899 
900     cp = alloc_printf("%s/afl-qemu-trace", tmp);
901 
902     if (access(cp, X_OK))
903       FATAL("Unable to find '%s'", tmp);
904 
905     target_path = new_argv[0] = cp;
906     return new_argv;
907 
908   }
909 
910   own_copy = ck_strdup(own_loc);
911   rsl = strrchr(own_copy, '/');
912 
913   if (rsl) {
914 
915     *rsl = 0;
916 
917     cp = alloc_printf("%s/afl-qemu-trace", own_copy);
918     ck_free(own_copy);
919 
920     if (!access(cp, X_OK)) {
921 
922       target_path = new_argv[0] = cp;
923       return new_argv;
924 
925     }
926 
927   } else ck_free(own_copy);
928 
929   if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
930 
931     target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace";
932     return new_argv;
933 
934   }
935 
936   FATAL("Unable to find 'afl-qemu-trace'.");
937 
938 }
939 
940 
941 /* Main entry point */
942 
main(int argc,char ** argv)943 int main(int argc, char** argv) {
944 
945   s32 opt;
946   u8  mem_limit_given = 0, timeout_given = 0, qemu_mode = 0;
947   char** use_argv;
948 
949   doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
950 
951   SAYF(cCYA "afl-analyze " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
952 
953   while ((opt = getopt(argc,argv,"+i:f:m:t:eQ")) > 0)
954 
955     switch (opt) {
956 
957       case 'i':
958 
959         if (in_file) FATAL("Multiple -i options not supported");
960         in_file = optarg;
961         break;
962 
963       case 'f':
964 
965         if (prog_in) FATAL("Multiple -f options not supported");
966         use_stdin = 0;
967         prog_in   = optarg;
968         break;
969 
970       case 'e':
971 
972         if (edges_only) FATAL("Multiple -e options not supported");
973         edges_only = 1;
974         break;
975 
976       case 'm': {
977 
978           u8 suffix = 'M';
979 
980           if (mem_limit_given) FATAL("Multiple -m options not supported");
981           mem_limit_given = 1;
982 
983           if (!strcmp(optarg, "none")) {
984 
985             mem_limit = 0;
986             break;
987 
988           }
989 
990           if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
991               optarg[0] == '-') FATAL("Bad syntax used for -m");
992 
993           switch (suffix) {
994 
995             case 'T': mem_limit *= 1024 * 1024; break;
996             case 'G': mem_limit *= 1024; break;
997             case 'k': mem_limit /= 1024; break;
998             case 'M': break;
999 
1000             default:  FATAL("Unsupported suffix or bad syntax for -m");
1001 
1002           }
1003 
1004           if (mem_limit < 5) FATAL("Dangerously low value of -m");
1005 
1006           if (sizeof(rlim_t) == 4 && mem_limit > 2000)
1007             FATAL("Value of -m out of range on 32-bit systems");
1008 
1009         }
1010 
1011         break;
1012 
1013       case 't':
1014 
1015         if (timeout_given) FATAL("Multiple -t options not supported");
1016         timeout_given = 1;
1017 
1018         exec_tmout = atoi(optarg);
1019 
1020         if (exec_tmout < 10 || optarg[0] == '-')
1021           FATAL("Dangerously low value of -t");
1022 
1023         break;
1024 
1025       case 'Q':
1026 
1027         if (qemu_mode) FATAL("Multiple -Q options not supported");
1028         if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
1029 
1030         qemu_mode = 1;
1031         break;
1032 
1033       default:
1034 
1035         usage(argv[0]);
1036 
1037     }
1038 
1039   if (optind == argc || !in_file) usage(argv[0]);
1040 
1041   use_hex_offsets = !!getenv("AFL_ANALYZE_HEX");
1042 
1043   setup_shm();
1044   setup_signal_handlers();
1045 
1046   set_up_environment();
1047 
1048   find_binary(argv[optind]);
1049   detect_file_args(argv + optind);
1050 
1051   if (qemu_mode)
1052     use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
1053   else
1054     use_argv = argv + optind;
1055 
1056   SAYF("\n");
1057 
1058   read_initial_file();
1059 
1060   ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
1061        mem_limit, exec_tmout, edges_only ? ", edges only" : "");
1062 
1063   run_target(use_argv, in_data, in_len, 1);
1064 
1065   if (child_timed_out)
1066     FATAL("Target binary times out (adjusting -t may help).");
1067 
1068   if (!anything_set()) FATAL("No instrumentation detected.");
1069 
1070   analyze(use_argv);
1071 
1072   OKF("We're done here. Have a nice day!\n");
1073 
1074   exit(0);
1075 
1076 }
1077 
1078