afl-showmap.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*
  2. american fuzzy lop - map display utility
  3. ----------------------------------------
  4. Written and maintained by Michal Zalewski <lcamtuf@google.com>
  5. Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
  6. Licensed under the Apache License, Version 2.0 (the "License");
  7. you may not use this file except in compliance with the License.
  8. You may obtain a copy of the License at:
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. A very simple tool that runs the targeted binary and displays
  11. the contents of the trace bitmap in a human-readable form. Useful in
  12. scripts to eliminate redundant inputs and perform other checks.
  13. Exit code is 2 if the target program crashes; 1 if it times out or
  14. there is a problem executing it; or 0 if execution is successful.
  15. */
  16. #define AFL_MAIN
  17. #include "config.h"
  18. #include "types.h"
  19. #include "debug.h"
  20. #include "alloc-inl.h"
  21. #include "hash.h"
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <time.h>
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include <dirent.h>
  30. #include <fcntl.h>
  31. #include <sys/wait.h>
  32. #include <sys/time.h>
  33. #include <sys/shm.h>
  34. #include <sys/stat.h>
  35. #include <sys/types.h>
  36. #include <sys/resource.h>
  37. static s32 child_pid; /* PID of the tested program */
  38. static u8* trace_bits; /* SHM with instrumentation bitmap */
  39. static u8 *out_file, /* Trace output file */
  40. *doc_path, /* Path to docs */
  41. *target_path, /* Path to target binary */
  42. *at_file; /* Substitution string for @@ */
  43. static u32 exec_tmout; /* Exec timeout (ms) */
  44. static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
  45. static s32 shm_id; /* ID of the SHM region */
  46. static u8 quiet_mode, /* Hide non-essential messages? */
  47. edges_only, /* Ignore hit counts? */
  48. cmin_mode, /* Generate output in afl-cmin mode? */
  49. binary_mode, /* Write output as a binary map */
  50. keep_cores; /* Allow coredumps? */
  51. static volatile u8
  52. stop_soon, /* Ctrl-C pressed? */
  53. child_timed_out, /* Child timed out? */
  54. child_crashed; /* Child crashed? */
  55. /* Classify tuple counts. Instead of mapping to individual bits, as in
  56. afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */
  57. static const u8 count_class_human[256] = {
  58. [0] = 0,
  59. [1] = 1,
  60. [2] = 2,
  61. [3] = 3,
  62. [4 ... 7] = 4,
  63. [8 ... 15] = 5,
  64. [16 ... 31] = 6,
  65. [32 ... 127] = 7,
  66. [128 ... 255] = 8
  67. };
  68. static const u8 count_class_binary[256] = {
  69. [0] = 0,
  70. [1] = 1,
  71. [2] = 2,
  72. [3] = 4,
  73. [4 ... 7] = 8,
  74. [8 ... 15] = 16,
  75. [16 ... 31] = 32,
  76. [32 ... 127] = 64,
  77. [128 ... 255] = 128
  78. };
  79. static void classify_counts(u8* mem, const u8* map) {
  80. u32 i = MAP_SIZE;
  81. if (edges_only) {
  82. while (i--) {
  83. if (*mem) *mem = 1;
  84. mem++;
  85. }
  86. } else {
  87. while (i--) {
  88. *mem = map[*mem];
  89. mem++;
  90. }
  91. }
  92. }
  93. /* Get rid of shared memory (atexit handler). */
  94. static void remove_shm(void) {
  95. shmctl(shm_id, IPC_RMID, NULL);
  96. }
  97. /* Configure shared memory. */
  98. static void setup_shm(void) {
  99. u8* shm_str;
  100. shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
  101. if (shm_id < 0) PFATAL("shmget() failed");
  102. atexit(remove_shm);
  103. shm_str = alloc_printf("%d", shm_id);
  104. setenv(SHM_ENV_VAR, shm_str, 1);
  105. ck_free(shm_str);
  106. trace_bits = shmat(shm_id, NULL, 0);
  107. if (!trace_bits) PFATAL("shmat() failed");
  108. }
  109. /* Write results. */
  110. static u32 write_results(void) {
  111. s32 fd;
  112. u32 i, ret = 0;
  113. u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"),
  114. caa = !!getenv("AFL_CMIN_ALLOW_ANY");
  115. if (!strncmp(out_file, "/dev/", 5)) {
  116. fd = open(out_file, O_WRONLY, 0600);
  117. if (fd < 0) PFATAL("Unable to open '%s'", out_file);
  118. } else if (!strcmp(out_file, "-")) {
  119. fd = dup(1);
  120. if (fd < 0) PFATAL("Unable to open stdout");
  121. } else {
  122. unlink(out_file); /* Ignore errors */
  123. fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
  124. if (fd < 0) PFATAL("Unable to create '%s'", out_file);
  125. }
  126. if (binary_mode) {
  127. for (i = 0; i < MAP_SIZE; i++)
  128. if (trace_bits[i]) ret++;
  129. ck_write(fd, trace_bits, MAP_SIZE, out_file);
  130. close(fd);
  131. } else {
  132. FILE* f = fdopen(fd, "w");
  133. if (!f) PFATAL("fdopen() failed");
  134. for (i = 0; i < MAP_SIZE; i++) {
  135. if (!trace_bits[i]) continue;
  136. ret++;
  137. if (cmin_mode) {
  138. if (child_timed_out) break;
  139. if (!caa && child_crashed != cco) break;
  140. fprintf(f, "%u%u\n", trace_bits[i], i);
  141. } else fprintf(f, "%06u:%u\n", i, trace_bits[i]);
  142. }
  143. fclose(f);
  144. }
  145. return ret;
  146. }
  147. /* Handle timeout signal. */
  148. static void handle_timeout(int sig) {
  149. child_timed_out = 1;
  150. if (child_pid > 0) kill(child_pid, SIGKILL);
  151. }
  152. /* Execute target application. */
  153. static void run_target(char** argv) {
  154. static struct itimerval it;
  155. int status = 0;
  156. if (!quiet_mode)
  157. SAYF("-- Program output begins --\n" cRST);
  158. MEM_BARRIER();
  159. child_pid = fork();
  160. if (child_pid < 0) PFATAL("fork() failed");
  161. if (!child_pid) {
  162. struct rlimit r;
  163. if (quiet_mode) {
  164. s32 fd = open("/dev/null", O_RDWR);
  165. if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) {
  166. *(u32*)trace_bits = EXEC_FAIL_SIG;
  167. PFATAL("Descriptor initialization failed");
  168. }
  169. close(fd);
  170. }
  171. if (mem_limit) {
  172. r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
  173. #ifdef RLIMIT_AS
  174. setrlimit(RLIMIT_AS, &r); /* Ignore errors */
  175. #else
  176. setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
  177. #endif /* ^RLIMIT_AS */
  178. }
  179. if (!keep_cores) r.rlim_max = r.rlim_cur = 0;
  180. else r.rlim_max = r.rlim_cur = RLIM_INFINITY;
  181. setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
  182. if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0);
  183. setsid();
  184. execv(target_path, argv);
  185. *(u32*)trace_bits = EXEC_FAIL_SIG;
  186. exit(0);
  187. }
  188. /* Configure timeout, wait for child, cancel timeout. */
  189. if (exec_tmout) {
  190. child_timed_out = 0;
  191. it.it_value.tv_sec = (exec_tmout / 1000);
  192. it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
  193. }
  194. setitimer(ITIMER_REAL, &it, NULL);
  195. if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed");
  196. child_pid = 0;
  197. it.it_value.tv_sec = 0;
  198. it.it_value.tv_usec = 0;
  199. setitimer(ITIMER_REAL, &it, NULL);
  200. MEM_BARRIER();
  201. /* Clean up bitmap, analyze exit condition, etc. */
  202. if (*(u32*)trace_bits == EXEC_FAIL_SIG)
  203. FATAL("Unable to execute '%s'", argv[0]);
  204. classify_counts(trace_bits, binary_mode ?
  205. count_class_binary : count_class_human);
  206. if (!quiet_mode)
  207. SAYF(cRST "-- Program output ends --\n");
  208. if (!child_timed_out && !stop_soon && WIFSIGNALED(status))
  209. child_crashed = 1;
  210. if (!quiet_mode) {
  211. if (child_timed_out)
  212. SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
  213. else if (stop_soon)
  214. SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
  215. else if (child_crashed)
  216. SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status));
  217. }
  218. }
  219. /* Handle Ctrl-C and the like. */
  220. static void handle_stop_sig(int sig) {
  221. stop_soon = 1;
  222. if (child_pid > 0) kill(child_pid, SIGKILL);
  223. }
  224. /* Do basic preparations - persistent fds, filenames, etc. */
  225. static void set_up_environment(void) {
  226. setenv("ASAN_OPTIONS", "abort_on_error=1:"
  227. "detect_leaks=0:"
  228. "symbolize=0:"
  229. "allocator_may_return_null=1", 0);
  230. setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
  231. "symbolize=0:"
  232. "abort_on_error=1:"
  233. "allocator_may_return_null=1:"
  234. "msan_track_origins=0", 0);
  235. if (getenv("AFL_PRELOAD")) {
  236. setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
  237. setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
  238. }
  239. }
  240. /* Setup signal handlers, duh. */
  241. static void setup_signal_handlers(void) {
  242. struct sigaction sa;
  243. sa.sa_handler = NULL;
  244. sa.sa_flags = SA_RESTART;
  245. sa.sa_sigaction = NULL;
  246. sigemptyset(&sa.sa_mask);
  247. /* Various ways of saying "stop". */
  248. sa.sa_handler = handle_stop_sig;
  249. sigaction(SIGHUP, &sa, NULL);
  250. sigaction(SIGINT, &sa, NULL);
  251. sigaction(SIGTERM, &sa, NULL);
  252. /* Exec timeout notifications. */
  253. sa.sa_handler = handle_timeout;
  254. sigaction(SIGALRM, &sa, NULL);
  255. }
  256. /* Detect @@ in args. */
  257. static void detect_file_args(char** argv) {
  258. u32 i = 0;
  259. u8* cwd = getcwd(NULL, 0);
  260. if (!cwd) PFATAL("getcwd() failed");
  261. while (argv[i]) {
  262. u8* aa_loc = strstr(argv[i], "@@");
  263. if (aa_loc) {
  264. u8 *aa_subst, *n_arg;
  265. if (!at_file) FATAL("@@ syntax is not supported by this tool.");
  266. /* Be sure that we're always using fully-qualified paths. */
  267. if (at_file[0] == '/') aa_subst = at_file;
  268. else aa_subst = alloc_printf("%s/%s", cwd, at_file);
  269. /* Construct a replacement argv value. */
  270. *aa_loc = 0;
  271. n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2);
  272. argv[i] = n_arg;
  273. *aa_loc = '@';
  274. if (at_file[0] != '/') ck_free(aa_subst);
  275. }
  276. i++;
  277. }
  278. free(cwd); /* not tracked */
  279. }
  280. /* Show banner. */
  281. static void show_banner(void) {
  282. SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
  283. }
  284. /* Display usage hints. */
  285. static void usage(u8* argv0) {
  286. show_banner();
  287. SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
  288. "Required parameters:\n\n"
  289. " -o file - file to write the trace data to\n\n"
  290. "Execution control settings:\n\n"
  291. " -t msec - timeout for each run (none)\n"
  292. " -m megs - memory limit for child process (%u MB)\n"
  293. " -Q - use binary-only instrumentation (QEMU mode)\n\n"
  294. "Other settings:\n\n"
  295. " -q - sink program's output and don't show messages\n"
  296. " -e - show edge coverage only, ignore hit counts\n"
  297. " -c - allow core dumps\n\n"
  298. "This tool displays raw tuple data captured by AFL instrumentation.\n"
  299. "For additional help, consult %s/README.\n\n" cRST,
  300. argv0, MEM_LIMIT, doc_path);
  301. exit(1);
  302. }
  303. /* Find binary. */
  304. static void find_binary(u8* fname) {
  305. u8* env_path = 0;
  306. struct stat st;
  307. if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
  308. target_path = ck_strdup(fname);
  309. if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
  310. !(st.st_mode & 0111) || st.st_size < 4)
  311. FATAL("Program '%s' not found or not executable", fname);
  312. } else {
  313. while (env_path) {
  314. u8 *cur_elem, *delim = strchr(env_path, ':');
  315. if (delim) {
  316. cur_elem = ck_alloc(delim - env_path + 1);
  317. memcpy(cur_elem, env_path, delim - env_path);
  318. delim++;
  319. } else cur_elem = ck_strdup(env_path);
  320. env_path = delim;
  321. if (cur_elem[0])
  322. target_path = alloc_printf("%s/%s", cur_elem, fname);
  323. else
  324. target_path = ck_strdup(fname);
  325. ck_free(cur_elem);
  326. if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
  327. (st.st_mode & 0111) && st.st_size >= 4) break;
  328. ck_free(target_path);
  329. target_path = 0;
  330. }
  331. if (!target_path) FATAL("Program '%s' not found or not executable", fname);
  332. }
  333. }
  334. /* Fix up argv for QEMU. */
  335. static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
  336. char** new_argv = ck_alloc(sizeof(char*) * (argc + 4));
  337. u8 *tmp, *cp, *rsl, *own_copy;
  338. /* Workaround for a QEMU stability glitch. */
  339. setenv("QEMU_LOG", "nochain", 1);
  340. memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc);
  341. new_argv[2] = target_path;
  342. new_argv[1] = "--";
  343. /* Now we need to actually find qemu for argv[0]. */
  344. tmp = getenv("AFL_PATH");
  345. if (tmp) {
  346. cp = alloc_printf("%s/afl-qemu-trace", tmp);
  347. if (access(cp, X_OK))
  348. FATAL("Unable to find '%s'", tmp);
  349. target_path = new_argv[0] = cp;
  350. return new_argv;
  351. }
  352. own_copy = ck_strdup(own_loc);
  353. rsl = strrchr(own_copy, '/');
  354. if (rsl) {
  355. *rsl = 0;
  356. cp = alloc_printf("%s/afl-qemu-trace", own_copy);
  357. ck_free(own_copy);
  358. if (!access(cp, X_OK)) {
  359. target_path = new_argv[0] = cp;
  360. return new_argv;
  361. }
  362. } else ck_free(own_copy);
  363. if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
  364. target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace";
  365. return new_argv;
  366. }
  367. FATAL("Unable to find 'afl-qemu-trace'.");
  368. }
  369. /* Main entry point */
  370. int main(int argc, char** argv) {
  371. s32 opt;
  372. u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0;
  373. u32 tcnt;
  374. char** use_argv;
  375. doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
  376. while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbc")) > 0)
  377. switch (opt) {
  378. case 'o':
  379. if (out_file) FATAL("Multiple -o options not supported");
  380. out_file = optarg;
  381. break;
  382. case 'm': {
  383. u8 suffix = 'M';
  384. if (mem_limit_given) FATAL("Multiple -m options not supported");
  385. mem_limit_given = 1;
  386. if (!strcmp(optarg, "none")) {
  387. mem_limit = 0;
  388. break;
  389. }
  390. if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
  391. optarg[0] == '-') FATAL("Bad syntax used for -m");
  392. switch (suffix) {
  393. case 'T': mem_limit *= 1024 * 1024; break;
  394. case 'G': mem_limit *= 1024; break;
  395. case 'k': mem_limit /= 1024; break;
  396. case 'M': break;
  397. default: FATAL("Unsupported suffix or bad syntax for -m");
  398. }
  399. if (mem_limit < 5) FATAL("Dangerously low value of -m");
  400. if (sizeof(rlim_t) == 4 && mem_limit > 2000)
  401. FATAL("Value of -m out of range on 32-bit systems");
  402. }
  403. break;
  404. case 't':
  405. if (timeout_given) FATAL("Multiple -t options not supported");
  406. timeout_given = 1;
  407. if (strcmp(optarg, "none")) {
  408. exec_tmout = atoi(optarg);
  409. if (exec_tmout < 20 || optarg[0] == '-')
  410. FATAL("Dangerously low value of -t");
  411. }
  412. break;
  413. case 'e':
  414. if (edges_only) FATAL("Multiple -e options not supported");
  415. edges_only = 1;
  416. break;
  417. case 'q':
  418. if (quiet_mode) FATAL("Multiple -q options not supported");
  419. quiet_mode = 1;
  420. break;
  421. case 'Z':
  422. /* This is an undocumented option to write data in the syntax expected
  423. by afl-cmin. Nobody else should have any use for this. */
  424. cmin_mode = 1;
  425. quiet_mode = 1;
  426. break;
  427. case 'A':
  428. /* Another afl-cmin specific feature. */
  429. at_file = optarg;
  430. break;
  431. case 'Q':
  432. if (qemu_mode) FATAL("Multiple -Q options not supported");
  433. if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
  434. qemu_mode = 1;
  435. break;
  436. case 'b':
  437. /* Secret undocumented mode. Writes output in raw binary format
  438. similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */
  439. binary_mode = 1;
  440. break;
  441. case 'c':
  442. if (keep_cores) FATAL("Multiple -c options not supported");
  443. keep_cores = 1;
  444. break;
  445. default:
  446. usage(argv[0]);
  447. }
  448. if (optind == argc || !out_file) usage(argv[0]);
  449. setup_shm();
  450. setup_signal_handlers();
  451. set_up_environment();
  452. find_binary(argv[optind]);
  453. if (!quiet_mode) {
  454. show_banner();
  455. ACTF("Executing '%s'...\n", target_path);
  456. }
  457. detect_file_args(argv + optind);
  458. if (qemu_mode)
  459. use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
  460. else
  461. use_argv = argv + optind;
  462. run_target(use_argv);
  463. tcnt = write_results();
  464. if (!quiet_mode) {
  465. if (!tcnt) FATAL("No instrumentation detected" cRST);
  466. OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file);
  467. }
  468. exit(child_crashed * 2 + child_timed_out);
  469. }