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