/* american fuzzy lop - fuzzer code -------------------------------- Written and maintained by Michal Zalewski Forkserver design by Jann Horn Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 This is the real deal: the program takes an instrumented binary and attempts a variety of basic fuzzing tricks, paying close attention to how they affect the execution path. */ #ifndef _AFL_FUZZ_H #define _AFL_FUZZ_H #define AFL_MAIN #define MESSAGES_TO_STDOUT #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define _FILE_OFFSET_BITS 64 #ifdef __ANDROID__ #include "android-ashmem.h" #endif #include "config.h" #include "types.h" #include "debug.h" #include "alloc-inl.h" #include "hash.h" #include "sharedmem.h" #include "forkserver.h" #include "common.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) # include # define HAVE_ARC4RANDOM 1 #endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ /* For systems that have sched_setaffinity; right now just Linux, but one can hope... */ #ifdef __linux__ # define HAVE_AFFINITY 1 #endif /* __linux__ */ struct queue_entry { u8* fname; /* File name for the test case */ u32 len; /* Input length */ u8 cal_failed, /* Calibration failed? */ trim_done, /* Trimmed? */ was_fuzzed, /* historical, but needed for MOpt */ passed_det, /* Deterministic stages passed? */ has_new_cov, /* Triggers new coverage? */ var_behavior, /* Variable behavior? */ favored, /* Currently favored? */ fs_redundant; /* Marked as redundant in the fs? */ u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level, /* Number of fuzzing iterations */ exec_cksum; /* Checksum of the execution trace */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ n_fuzz, /* Number of fuzz, does not overflow */ depth; /* Path depth */ u8* trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ struct queue_entry *next, /* Next element, if any */ *next_100; /* 100 elements ahead */ }; struct extra_data { u8* data; /* Dictionary token data */ u32 len; /* Dictionary token length */ u32 hit_cnt; /* Use count in the corpus */ }; /* Fuzzing stages */ enum { /* 00 */ STAGE_FLIP1, /* 01 */ STAGE_FLIP2, /* 02 */ STAGE_FLIP4, /* 03 */ STAGE_FLIP8, /* 04 */ STAGE_FLIP16, /* 05 */ STAGE_FLIP32, /* 06 */ STAGE_ARITH8, /* 07 */ STAGE_ARITH16, /* 08 */ STAGE_ARITH32, /* 09 */ STAGE_INTEREST8, /* 10 */ STAGE_INTEREST16, /* 11 */ STAGE_INTEREST32, /* 12 */ STAGE_EXTRAS_UO, /* 13 */ STAGE_EXTRAS_UI, /* 14 */ STAGE_EXTRAS_AO, /* 15 */ STAGE_HAVOC, /* 16 */ STAGE_SPLICE, /* 17 */ STAGE_PYTHON, /* 18 */ STAGE_CUSTOM_MUTATOR }; /* Stage value types */ enum { /* 00 */ STAGE_VAL_NONE, /* 01 */ STAGE_VAL_LE, /* 02 */ STAGE_VAL_BE }; /* Execution status fault codes */ enum { /* 00 */ FAULT_NONE, /* 01 */ FAULT_TMOUT, /* 02 */ FAULT_CRASH, /* 03 */ FAULT_ERROR, /* 04 */ FAULT_NOINST, /* 05 */ FAULT_NOBITS }; /* MOpt: Lots of globals, but mostly for the status UI and other things where it really makes no sense to haul them around as function parameters. */ extern u64 limit_time_puppet, orig_hit_cnt_puppet, last_limit_time_start, tmp_pilot_time, total_pacemaker_time, total_puppet_find, temp_puppet_find, most_time_key, most_time, most_execs_key, most_execs, old_hit_count; extern s32 SPLICE_CYCLES_puppet, limit_time_sig, key_puppet, key_module; extern double w_init, w_end, w_now; extern s32 g_now; extern s32 g_max; #define operator_num 16 #define swarm_num 5 #define period_core 500000 extern u64 tmp_core_time; extern s32 swarm_now; extern double x_now[swarm_num][operator_num], L_best[swarm_num][operator_num], eff_best[swarm_num][operator_num], G_best[operator_num], v_now[swarm_num][operator_num], probability_now[swarm_num][operator_num], swarm_fitness[swarm_num]; extern u64 stage_finds_puppet[swarm_num][operator_num], /* Patterns found per fuzz stage */ stage_finds_puppet_v2[swarm_num][operator_num], stage_cycles_puppet_v2[swarm_num][operator_num], stage_cycles_puppet_v3[swarm_num][operator_num], stage_cycles_puppet[swarm_num][operator_num], operator_finds_puppet[operator_num], core_operator_finds_puppet[operator_num], core_operator_finds_puppet_v2[operator_num], core_operator_cycles_puppet[operator_num], core_operator_cycles_puppet_v2[operator_num], core_operator_cycles_puppet_v3[operator_num]; /* Execs per fuzz stage */ #define RAND_C (rand()%1000*0.001) #define v_max 1 #define v_min 0.05 #define limit_time_bound 1.1 #define SPLICE_CYCLES_puppet_up 25 #define SPLICE_CYCLES_puppet_low 5 #define STAGE_RANDOMBYTE 12 #define STAGE_DELETEBYTE 13 #define STAGE_Clone75 14 #define STAGE_OverWrite75 15 #define period_pilot 50000 extern double period_pilot_tmp; extern s32 key_lv; extern u8 *in_dir, /* Input directory with test cases */ *out_dir, /* Working & output directory */ *tmp_dir , /* Temporary directory for input */ *sync_dir, /* Synchronization directory */ *sync_id, /* Fuzzer ID */ *power_name, /* Power schedule name */ *use_banner, /* Display banner */ *in_bitmap, /* Input bitmap */ *file_extension, /* File extension */ *orig_cmdline; /* Original command line */ extern u8 *doc_path, /* Path to documentation dir */ *target_path, /* Path to target binary */ *out_file; /* File to fuzz, if any */ extern u32 exec_tmout; /* Configurable exec timeout (ms) */ extern u32 hang_tmout; /* Timeout used for hang det (ms) */ extern u64 mem_limit; /* Memory cap for child (MB) */ extern u8 cal_cycles, /* Calibration cycles defaults */ cal_cycles_long, debug, /* Debug mode */ python_only; /* Python-only mode */ extern u32 stats_update_freq; /* Stats update frequency (execs) */ enum { /* 00 */ EXPLORE, /* AFL default, Exploration-based constant schedule */ /* 01 */ FAST, /* Exponential schedule */ /* 02 */ COE, /* Cut-Off Exponential schedule */ /* 03 */ LIN, /* Linear schedule */ /* 04 */ QUAD, /* Quadratic schedule */ /* 05 */ EXPLOIT, /* AFL's exploitation-based const. */ POWER_SCHEDULES_NUM }; extern char *power_names[POWER_SCHEDULES_NUM]; extern u8 schedule; /* Power schedule (default: EXPLORE)*/ extern u8 havoc_max_mult; extern u8 skip_deterministic, /* Skip deterministic stages? */ force_deterministic, /* Force deterministic stages? */ use_splicing, /* Recombine input files? */ dumb_mode, /* Run in non-instrumented mode? */ score_changed, /* Scoring for favorites changed? */ kill_signal, /* Signal that killed the child */ resuming_fuzz, /* Resuming an older fuzzing job? */ timeout_given, /* Specific timeout given? */ not_on_tty, /* stdout is not a tty */ term_too_small, /* terminal dimensions too small */ no_forkserver, /* Disable forkserver? */ crash_mode, /* Crash mode! Yeah! */ in_place_resume, /* Attempt in-place resume? */ auto_changed, /* Auto-generated tokens changed? */ no_cpu_meter_red, /* Feng shui on the status screen */ no_arith, /* Skip most arithmetic ops */ shuffle_queue, /* Shuffle input queue? */ bitmap_changed, /* Time to update bitmap? */ qemu_mode, /* Running in QEMU mode? */ unicorn_mode, /* Running in Unicorn mode? */ skip_requested, /* Skip request, via SIGUSR1 */ run_over10m, /* Run time over 10 minutes? */ persistent_mode, /* Running in persistent mode? */ deferred_mode, /* Deferred forkserver mode? */ fixed_seed, /* do not reseed */ fast_cal, /* Try to calibrate faster? */ uses_asan; /* Target uses ASAN? */ extern s32 out_fd, /* Persistent fd for out_file */ #ifndef HAVE_ARC4RANDOM dev_urandom_fd, /* Persistent fd for /dev/urandom */ #endif dev_null_fd, /* Persistent fd for /dev/null */ fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_st_fd; /* Fork server status pipe (read) */ extern s32 forksrv_pid, /* PID of the fork server */ child_pid, /* PID of the fuzzed program */ out_dir_fd; /* FD of the lock file */ extern u8* trace_bits; /* SHM with instrumentation bitmap */ extern u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ extern u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ extern volatile u8 stop_soon, /* Ctrl-C pressed? */ clear_screen, /* Window resized? */ child_timed_out; /* Traced process timed out? */ extern u32 queued_paths, /* Total number of queued testcases */ queued_variable, /* Testcases with variable behavior */ queued_at_start, /* Total number of initial inputs */ queued_discovered, /* Items discovered during this run */ queued_imported, /* Items imported via -S */ queued_favored, /* Paths deemed favorable */ queued_with_cov, /* Paths with new coverage bytes */ pending_not_fuzzed, /* Queued but not done yet */ pending_favored, /* Pending favored paths */ cur_skipped_paths, /* Abandoned inputs in cur cycle */ cur_depth, /* Current path depth */ max_depth, /* Max path depth */ useless_at_start, /* Number of useless starting paths */ var_byte_count, /* Bitmap bytes with var behavior */ current_entry, /* Current queue entry ID */ havoc_div; /* Cycle count divisor for havoc */ extern u64 total_crashes, /* Total number of crashes */ unique_crashes, /* Crashes with unique signatures */ total_tmouts, /* Total number of timeouts */ unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ total_execs, /* Total execve() calls */ start_time, /* Unix start time (ms) */ last_path_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ last_hang_time, /* Time for most recent hang (ms) */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ trim_execs, /* Execs done to trim input files */ bytes_trim_in, /* Bytes coming into the trimmer */ bytes_trim_out, /* Bytes coming outa the trimmer */ blocks_eff_total, /* Blocks subject to effector maps */ blocks_eff_select; /* Blocks selected as fuzzable */ extern u32 subseq_tmouts; /* Number of timeouts in a row */ extern u8 *stage_name, /* Name of the current fuzz stage */ *stage_short, /* Short stage name */ *syncing_party; /* Currently syncing with... */ extern s32 stage_cur, stage_max; /* Stage progression */ extern s32 splicing_with; /* Splicing with which test case? */ extern u32 master_id, master_max; /* Master instance job splitting */ extern u32 syncing_case; /* Syncing with case #... */ extern s32 stage_cur_byte, /* Byte offset of current stage op */ stage_cur_val; /* Value used for stage op */ extern u8 stage_val_type; /* Value type (STAGE_VAL_*) */ extern u64 stage_finds[32], /* Patterns found per fuzz stage */ stage_cycles[32]; /* Execs per fuzz stage */ #ifndef HAVE_ARC4RANDOM extern u32 rand_cnt; /* Random number counter */ #endif extern u64 total_cal_us, /* Total calibration time (us) */ total_cal_cycles; /* Total calibration cycles */ extern u64 total_bitmap_size, /* Total bit count for all bitmaps */ total_bitmap_entries; /* Number of bitmaps counted */ extern s32 cpu_core_count; /* CPU core count */ #ifdef HAVE_AFFINITY extern s32 cpu_aff; /* Selected CPU core */ #endif /* HAVE_AFFINITY */ extern FILE* plot_file; /* Gnuplot output file */ extern struct queue_entry *queue, /* Fuzzing queue (linked list) */ *queue_cur, /* Current offset within the queue */ *queue_top, /* Top of the list */ *q_prev100; /* Previous 100 marker */ extern struct queue_entry* top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ extern struct extra_data* extras; /* Extra tokens to fuzz with */ extern u32 extras_cnt; /* Total number of tokens read */ extern struct extra_data* a_extras; /* Automatically selected extras */ extern u32 a_extras_cnt; /* Total number of tokens available */ u8* (*post_handler)(u8* buf, u32* len); /* hooks for the custom mutator function */ size_t (*custom_mutator)(u8 *data, size_t size, u8* mutated_out, size_t max_size, unsigned int seed); size_t (*pre_save_handler)(u8 *data, size_t size, u8 **new_data); /* Interesting values, as per config.h */ extern s8 interesting_8[INTERESTING_8_LEN]; extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN]; extern s32 interesting_32[INTERESTING_8_LEN + INTERESTING_16_LEN + INTERESTING_32_LEN]; /* Python stuff */ #ifdef USE_PYTHON #include extern PyObject *py_module; enum { /* 00 */ PY_FUNC_INIT, /* 01 */ PY_FUNC_FUZZ, /* 02 */ PY_FUNC_INIT_TRIM, /* 03 */ PY_FUNC_POST_TRIM, /* 04 */ PY_FUNC_TRIM, PY_FUNC_COUNT }; extern PyObject *py_functions[PY_FUNC_COUNT]; #endif /**** Prototypes ****/ /* Python stuff */ #ifdef USE_PYTHON int init_py(); void finalize_py(); void fuzz_py(char*, size_t, char*, size_t, char**, size_t*); u32 init_trim_py(char*, size_t); u32 post_trim_py(char); void trim_py(char**, size_t*); #endif /* Queue */ void mark_as_det_done(struct queue_entry*); void mark_as_variable(struct queue_entry*); void mark_as_redundant(struct queue_entry*, u8); void add_to_queue(u8*, u32, u8); void destroy_queue(void); void update_bitmap_score(struct queue_entry*); void cull_queue(void); /* Bitmap */ void write_bitmap(void); void read_bitmap(u8*); u8 has_new_bits(u8*); u32 count_bits(u8*); u32 count_bytes(u8*); u32 count_non_255_bytes(u8*); #ifdef __x86_64__ void simplify_trace(u64*); void classify_counts(u64*); #else void simplify_trace(u32*); void classify_counts(u32*); #endif void init_count_class16(void); void minimize_bits(u8*, u8*); /* Misc */ u8* DI(u64); u8* DF(double); u8* DMS(u64); u8* DTD(u64, u64); /* Extras */ void load_extras_file(u8*, u32*, u32*, u32); void load_extras(u8*); void maybe_add_auto(u8*, u32); void save_auto(void); void load_auto(void); void destroy_extras(void); /**** Inline routines ****/ /* Generate a random number (from 0 to limit - 1). This may have slight bias. */ static inline u32 UR(u32 limit) { #ifdef HAVE_ARC4RANDOM if (fixed_seed) { return random() % limit; } /* The boundary not being necessarily a power of 2, we need to ensure the result uniformity. */ return arc4random_uniform(limit); #else if (!fixed_seed && unlikely(!rand_cnt--)) { u32 seed[2]; ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom"); srandom(seed[0]); rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG); } return random() % limit; #endif } /* Find first power of two greater or equal to val (assuming val under 2^63). */ static u64 next_p2(u64 val) { u64 ret = 1; while (val > ret) ret <<= 1; return ret; } /* Get unix time in milliseconds */ static u64 get_cur_time(void) { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); } /* Get unix time in microseconds */ static u64 get_cur_time_us(void) { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return (tv.tv_sec * 1000000ULL) + tv.tv_usec; } #endif