This commit is contained in:
hexcoder-
2020-04-17 13:30:12 +02:00
41 changed files with 610 additions and 529 deletions

View File

@ -69,7 +69,7 @@ ifneq "$(shell uname -m)" "x86_64"
endif endif
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
override CFLAGS += -Wall -g -Wno-pointer-sign \ override CFLAGS += -Wall -g -Wno-pointer-sign -Wmissing-declarations\
-I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \ -I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"

View File

@ -1,11 +1,12 @@
# TODO list for AFL++ # TODO list for AFL++
## Roadmap 2.64 ## Roadmap 2.65
- AFL_MAP_SIZE for afl-llvm-pass, qemu_mode and unicorn_mode
- fix stability calculation bug
- random crc32 HASH_CONST per run? because with 65536 paths we have collisions - random crc32 HASH_CONST per run? because with 65536 paths we have collisions
- namespace for targets? e.g. network - namespace for targets? e.g. network
- libradamsa as a custom module? - libradamsa as a custom module?
- fix stability calculation bug
## Further down the road ## Further down the road

View File

@ -12,21 +12,27 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++2.63d (development): ### Version ++2.63d (development):
- llvm_mode LTO mode: - llvm_mode LTO mode:
- now requires llvm11 - but compiles all targets! :) - now requires llvm11 - but compiles all targets! :)
- autodictionary feature added, enable with AFL_LLVM_LTO_AUTODICTIONARY - autodictionary feature added, enable with `AFL_LLVM_LTO_AUTODICTIONARY`
- variable map size usage - variable map size usage
- afl-fuzz: - afl-fuzz:
- variable map size support added (only LTO mode can use this) - variable map size support added (only LTO mode can use this)
- snapshot feature usage now visible in UI - snapshot feature usage now visible in UI
- Now setting "-L -1" will enable MOpt in parallel to normal mutation. - Now setting `-L -1` will enable MOpt in parallel to normal mutation.
Additionally this allows to run dictionaries, radamsa and cmplog. Additionally, this allows to run dictionaries, radamsa and cmplog.
- fix for cmplog/redqueen mode if stdin was used
- fix for writing a better plot_data file
- qemu_mode: fix for persistent mode
- compare-transform/AFL_LLVM_LAF_TRANSFORM_COMPARES now transforms also - compare-transform/AFL_LLVM_LAF_TRANSFORM_COMPARES now transforms also
static global and local variable comparisons (cannot find all though) static global and local variable comparisons (cannot find all though)
- extended forkserver: map_size and more information is communicated to - extended forkserver: map_size and more information is communicated to
afl-fuzz (and afl-fuzz acts accordingly) afl-fuzz (and afl-fuzz acts accordingly)
- more refactoring - new environment variable: AFL_MAP_SIZE to specify the size of the shared map
- if AFL_CC/AFL_CXX is set but empty afl compilers did fail, fixed - if AFL_CC/AFL_CXX is set but empty afl compilers did fail, fixed
(this bug is in vanilla afl too) (this bug is in vanilla afl too)
- added NO_PYTHON flag to disable python support when building afl-fuzz - added NO_PYTHON flag to disable python support when building afl-fuzz
- Bugfix: in persistent mode, fuzzing could get stuck after initial crash (#319)
- Bugfix: alf-plot output (#320)
- more refactoring
### Version ++2.63c (release): ### Version ++2.63c (release):
@ -314,7 +320,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
you use the new -p option :-) - see docs/power_schedules.md you use the new -p option :-) - see docs/power_schedules.md
- added afl-system-config script to set all system performance options for fuzzing - added afl-system-config script to set all system performance options for fuzzing
- llvm_mode works with llvm 3.9 up to including 8 ! - llvm_mode works with llvm 3.9 up to including 8 !
- qemu_mode got upgraded from 2.1 to 3.1 - incorporated from - qemu_mode got upgraded from 2.1 to 3.1 - incorporated from
https://github.com/andreafioraldi/afl and with community patches added https://github.com/andreafioraldi/afl and with community patches added

View File

@ -243,6 +243,11 @@ checks or alter some of the more exotic semantics of the tool:
normally indicated by the cycle counter in the UI turning green. May be normally indicated by the cycle counter in the UI turning green. May be
convenient for some types of automated jobs. convenient for some types of automated jobs.
- AFL_MAP_SIZE sets the size of the shared map that afl-fuzz, afl-showmap,
afl-tmin and afl-analyze create to gather instrumentation data from
the target. This must be equal or larger than the size the target was
compiled with.
- Setting AFL_NO_AFFINITY disables attempts to bind to a specific CPU core - Setting AFL_NO_AFFINITY disables attempts to bind to a specific CPU core
on Linux systems. This slows things down, but lets you run more instances on Linux systems. This slows things down, but lets you run more instances
of afl-fuzz than would be prudent (if you really want to). of afl-fuzz than would be prudent (if you really want to).

View File

@ -364,6 +364,16 @@ int main(int argc, char **argv, char **envp) {
be_quiet = 1; be_quiet = 1;
u8 *ptr;
if (!be_quiet &&
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
u32 map_size = atoi(ptr);
if (map_size != MAP_SIZE)
FATAL("AFL_MAP_SIZE is not supported by afl-gcc-fast");
}
check_environment_vars(envp); check_environment_vars(envp);
find_obj(argv[0]); find_obj(argv[0]);

View File

@ -443,11 +443,11 @@ typedef struct afl_state {
fast_cal, /* Try to calibrate faster? */ fast_cal, /* Try to calibrate faster? */
disable_trim; /* Never trim in fuzz_one */ disable_trim; /* Never trim in fuzz_one */
u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */ u8 *virgin_bits, /* Regions yet untouched by fuzzing */
virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */ *virgin_tmout, /* Bits we haven't seen in tmouts */
virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */ *virgin_crash; /* Bits we haven't seen in crashes */
u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */ u8 *var_bytes; /* Bytes that appear to be variable */
volatile u8 stop_soon, /* Ctrl-C pressed? */ volatile u8 stop_soon, /* Ctrl-C pressed? */
clear_screen; /* Window resized? */ clear_screen; /* Window resized? */
@ -535,7 +535,7 @@ typedef struct afl_state {
*queue_top, /* Top of the list */ *queue_top, /* Top of the list */
*q_prev100; /* Previous 100 marker */ *q_prev100; /* Previous 100 marker */
struct queue_entry *top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */ struct queue_entry **top_rated; /* Top entries for bitmap bytes */
struct extra_data *extras; /* Extra tokens to fuzz with */ struct extra_data *extras; /* Extra tokens to fuzz with */
u32 extras_cnt; /* Total number of tokens read */ u32 extras_cnt; /* Total number of tokens read */
@ -584,9 +584,9 @@ typedef struct afl_state {
u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs; u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs;
double stats_avg_exec; double stats_avg_exec;
u8 clean_trace[MAP_SIZE]; u8 *clean_trace;
u8 clean_trace_custom[MAP_SIZE]; u8 *clean_trace_custom;
u8 first_trace[MAP_SIZE]; u8 *first_trace;
/*needed for afl_fuzz_one */ /*needed for afl_fuzz_one */
// TODO: see which we can reuse // TODO: see which we can reuse
@ -608,6 +608,9 @@ typedef struct afl_state {
u8 * ex_buf; u8 * ex_buf;
size_t ex_size; size_t ex_size;
u8 * map_tmp_buf;
size_t map_tmp_size;
} afl_state_t; } afl_state_t;
/* A global pointer to all instances is needed (for now) for signals to arrive /* A global pointer to all instances is needed (for now) for signals to arrive
@ -794,7 +797,7 @@ struct custom_mutator {
}; };
void afl_state_init(afl_state_t *); void afl_state_init(afl_state_t *, uint32_t map_size);
void afl_state_deinit(afl_state_t *); void afl_state_deinit(afl_state_t *);
void read_afl_environment(afl_state_t *, char **); void read_afl_environment(afl_state_t *, char **);
@ -808,6 +811,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
/* Python */ /* Python */
#ifdef USE_PYTHON #ifdef USE_PYTHON
void load_custom_mutator_py(afl_state_t *, char *);
void finalize_py_module(void *); void finalize_py_module(void *);
size_t pre_save_py(void *, u8 *, size_t, u8 **); size_t pre_save_py(void *, u8 *, size_t, u8 **);
@ -835,7 +839,6 @@ u32 calculate_score(afl_state_t *, struct queue_entry *);
/* Bitmap */ /* Bitmap */
void read_bitmap(afl_state_t *, u8 *);
void write_bitmap(afl_state_t *); void write_bitmap(afl_state_t *);
u32 count_bits(afl_state_t *, u8 *); u32 count_bits(afl_state_t *, u8 *);
u32 count_bytes(afl_state_t *, u8 *); u32 count_bytes(afl_state_t *, u8 *);
@ -873,7 +876,7 @@ void show_init_stats(afl_state_t *);
/* Run */ /* Run */
fsrv_run_result_t run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32);
void write_to_testcase(afl_state_t *, void *, u32); void write_to_testcase(afl_state_t *, void *, u32);
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
void sync_fuzzers(afl_state_t *); void sync_fuzzers(afl_state_t *);

View File

@ -51,6 +51,16 @@ char * get_afl_env(char *env);
extern u8 be_quiet; extern u8 be_quiet;
extern u8 *doc_path; /* path to documentation dir */ extern u8 *doc_path; /* path to documentation dir */
/* Find binary, used by analyze, showmap, tmin
@returns the path, allocating the string */
u8 *find_binary(u8 *fname);
/* Read a bitmap from file fname to memory
This is for the -B option again. */
void read_bitmap(u8 *fname, u8 *map, size_t len);
/* Get unix time in milliseconds */ /* Get unix time in milliseconds */
u64 get_cur_time(void); u64 get_cur_time(void);
@ -105,5 +115,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms,
volatile u8 *stop_soon_p); volatile u8 *stop_soon_p);
u32 get_map_size();
#endif #endif

View File

@ -407,8 +407,7 @@
#define FS_OPT_SNAPSHOT 0x20000000 #define FS_OPT_SNAPSHOT 0x20000000
#define FS_OPT_AUTODICT 0x10000000 #define FS_OPT_AUTODICT 0x10000000
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
#define FS_OPT_SET_MAPSIZE(x) \ #define FS_OPT_SET_MAPSIZE(x) (x <= 1 || x > 0x1000000 ? 0 : ((x - 1) << 1))
(x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1))
#endif /* ! _HAVE_CONFIG_H */ #endif /* ! _HAVE_CONFIG_H */

View File

@ -31,7 +31,6 @@
/* __FUNCTION__ is non-iso */ /* __FUNCTION__ is non-iso */
#ifdef __func__ #ifdef __func__
#define __FUNCTION__ __func__ #define __FUNCTION__ __func__
#else
#endif #endif
/******************* /*******************

View File

@ -61,11 +61,12 @@ typedef struct afl_forkserver {
u64 total_execs; /* How often run_target was called */ u64 total_execs; /* How often run_target was called */
u8 *out_file, /* File to fuzz, if any */ u8 *out_file, /* File to fuzz, if any */
*target_path; /* Path of the target */ *target_path; /* Path of the target */
FILE *plot_file; /* Gnuplot output file */ FILE *plot_file; /* Gnuplot output file */
u8 last_run_timed_out; /* Traced process timed out? */ /* Note: lat_run_timed_out is u32 to send it to the child as 4 byte array */
u32 last_run_timed_out; /* Traced process timed out? */
u8 last_kill_signal; /* Signal that killed the child */ u8 last_kill_signal; /* Signal that killed the child */
@ -100,12 +101,10 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output); volatile u8 *stop_soon_p, u8 debug_child_output);
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len); void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len);
fsrv_run_result_t afl_fsrv_run_target( fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
afl_forkserver_t *fsrv, u32 timeout, volatile u8 *stop_soon_p);
void(classify_counts_func)(afl_forkserver_t *fsrv), void afl_fsrv_killall(void);
volatile u8 *stop_soon_p); void afl_fsrv_deinit(afl_forkserver_t *fsrv);
void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
#ifdef __APPLE__ #ifdef __APPLE__
#define MSG_FORK_ON_APPLE \ #define MSG_FORK_ON_APPLE \

View File

@ -44,8 +44,7 @@ typedef struct sharedmem {
u8 *map; /* shared memory region */ u8 *map; /* shared memory region */
size_t size_alloc; /* actual allocated size */ size_t map_size; /* actual allocated size */
size_t size_used; /* in use by shmem app */
int cmplog_mode; int cmplog_mode;
struct cmp_map *cmp_map; struct cmp_map *cmp_map;

View File

@ -223,10 +223,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
if ((!(getenv("AFL_LLVM_LTO_AUTODICTIONARY") // disabled when autodictionary if (getenv("LAF_TRANSFORM_COMPARES") ||
&& instrument_mode != INSTRUMENT_LTO)) // and lto_mode is used getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
&& (getenv("LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES"))) { if (!be_quiet && getenv("AFL_LLVM_LTO_AUTODICTIONARY") &&
instrument_mode != INSTRUMENT_LTO)
WARNF(
"using AFL_LLVM_LAF_TRANSFORM_COMPARES together with "
"AFL_LLVM_LTO_AUTODICTIONARY makes no sense. Use only "
"AFL_LLVM_LTO_AUTODICTIONARY.");
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
@ -716,30 +721,30 @@ int main(int argc, char **argv, char **envp) {
"Environment variables used:\n" "Environment variables used:\n"
"AFL_CC: path to the C compiler to use\n" "AFL_CC: path to the C compiler to use\n"
"AFL_CXX: path to the C++ compiler to use\n" "AFL_CXX: path to the C++ compiler to use\n"
"AFL_PATH: path to instrumenting pass and runtime "
"(afl-llvm-rt.*o)\n"
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
"AFL_INST_RATIO: percentage of branches to instrument\n"
"AFL_QUIET: suppress verbose output\n"
"AFL_DEBUG: enable developer debugging output\n" "AFL_DEBUG: enable developer debugging output\n"
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
"AFL_HARDEN: adds code hardening to catch memory bugs\n" "AFL_HARDEN: adds code hardening to catch memory bugs\n"
"AFL_USE_ASAN: activate address sanitizer\n" "AFL_INST_RATIO: percentage of branches to instrument\n"
"AFL_USE_MSAN: activate memory sanitizer\n"
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
"AFL_USE_CFISAN: activate control flow sanitizer\n"
"AFL_LLVM_WHITELIST: enable whitelisting (selective "
"instrumentation)\n"
"AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
"AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" "AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n"
"AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n"
"AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison "
"function calls\n"
" to cascaded comparisons\n"
"AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to " "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to "
"cascaded " "cascaded "
"comp.\n" "comp.\n"
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n", "AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n"
" to cascaded comparisons\n"
"AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison "
"function calls\n"
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n"
"AFL_LLVM_WHITELIST: enable whitelisting (selective "
"instrumentation)\n"
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
"AFL_PATH: path to instrumenting pass and runtime "
"(afl-llvm-rt.*o)\n"
"AFL_QUIET: suppress verbose output\n"
"AFL_USE_ASAN: activate address sanitizer\n"
"AFL_USE_CFISAN: activate control flow sanitizer\n"
"AFL_USE_MSAN: activate memory sanitizer\n"
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n",
callname, BIN_PATH, BIN_PATH); callname, BIN_PATH, BIN_PATH);
SAYF( SAYF(
@ -747,21 +752,21 @@ int main(int argc, char **argv, char **envp) {
"AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" "AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n"
"AFL_LLVM_INSTRUMENT: set instrumentation mode: DEFAULT, CFG " "AFL_LLVM_INSTRUMENT: set instrumentation mode: DEFAULT, CFG "
"(INSTRIM), LTO, CTX, NGRAM-2 ... NGRAM-16\n" "(INSTRIM), LTO, CTX, NGRAM-2 ... NGRAM-16\n"
"You can also use the old environment variables:" " You can also use the old environment variables instead:"
"AFL_LLVM_CTX: use context sensitive coverage\n" " AFL_LLVM_CTX: use context sensitive coverage\n"
"AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
"AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage\n"
"AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
"AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed (sub " " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed (sub "
"option to INSTRIM)\n"); "option to INSTRIM)\n");
#ifdef AFL_CLANG_FLTO #ifdef AFL_CLANG_FLTO
SAYF( SAYF(
"\nafl-clang-lto specific environment variables:\n" "\nafl-clang-lto specific environment variables:\n"
"AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
"bb\n"
"AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
"global var\n" "global var\n"
"AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
"bb\n"
"AFL_REAL_LD: use this lld linker instead of the compiled in path\n" "AFL_REAL_LD: use this lld linker instead of the compiled in path\n"
"\nafl-clang-lto was built with linker target \"%s\" and LTO flags " "\nafl-clang-lto was built with linker target \"%s\" and LTO flags "
"\"%s\"\n" "\"%s\"\n"
@ -796,6 +801,16 @@ int main(int argc, char **argv, char **envp) {
} }
u8 *ptr2;
if (!be_quiet && instrument_mode != INSTRUMENT_LTO &&
((ptr2 = getenv("AFL_MAP_SIZE")) || (ptr2 = getenv("AFL_MAPSIZE")))) {
u32 map_size = atoi(ptr2);
if (map_size != MAP_SIZE)
FATAL("AFL_MAP_SIZE is not supported by afl-clang-fast");
}
if (debug) { if (debug) {
SAYF(cMGN "[D]" cRST " cd \"%s\";", getthecwd()); SAYF(cMGN "[D]" cRST " cd \"%s\";", getthecwd());

View File

@ -608,20 +608,22 @@ bool AFLLTOPass::runOnModule(Module &M) {
} }
// save highest location ID to global variable }
// do this after each function to fail faster
if (afl_global_id > MAP_SIZE) {
uint32_t pow2map = 1, map = afl_global_id; // save highest location ID to global variable
while ((map = map >> 1)) // do this after each function to fail faster
pow2map++; if (!be_quiet && afl_global_id > MAP_SIZE) {
FATAL(
"We have %u blocks to instrument but the map size is only %u! Edit "
"config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
"afl-fuzz and llvm_mode.",
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map);
} uint32_t pow2map = 1, map = afl_global_id;
while ((map = map >> 1))
pow2map++;
WARNF(
"We have %u blocks to instrument but the map size is only %u. Either "
"edit config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
"afl-fuzz and llvm_mode and then make this target - or set "
"AFL_MAP_SIZE with at least size %u when running afl-fuzz with this "
"target.",
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id);
} }
@ -635,7 +637,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (!f) { if (!f) {
fprintf(stderr, fprintf(stderr,
"Error: init function could not be found (this hould not " "Error: init function could not be found (this should not "
"happen)\n"); "happen)\n");
exit(-1); exit(-1);

View File

@ -125,6 +125,7 @@ class AFLCoverage : public ModulePass {
std::list<std::string> myWhitelist; std::list<std::string> myWhitelist;
uint32_t ngram_size = 0; uint32_t ngram_size = 0;
uint32_t debug = 0; uint32_t debug = 0;
uint32_t map_size = MAP_SIZE;
char * ctx_str = NULL; char * ctx_str = NULL;
}; };
@ -192,6 +193,19 @@ bool AFLCoverage::runOnModule(Module &M) {
be_quiet = 1; be_quiet = 1;
/*
char *ptr;
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
map_size = atoi(ptr);
if (map_size < 8 || map_size > (1 << 29))
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30",
map_size); if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3);
}
*/
/* Decide instrumentation ratio */ /* Decide instrumentation ratio */
char * inst_ratio_str = getenv("AFL_INST_RATIO"); char * inst_ratio_str = getenv("AFL_INST_RATIO");
@ -365,7 +379,7 @@ bool AFLCoverage::runOnModule(Module &M) {
// if yes we store a context ID for this function in the global var // if yes we store a context ID for this function in the global var
if (has_calls) { if (has_calls) {
ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(MAP_SIZE)); ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(map_size));
StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext); StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
StoreCtx->setMetadata(M.getMDKindID("nosanitize"), StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None)); MDNode::get(C, None));
@ -509,7 +523,7 @@ bool AFLCoverage::runOnModule(Module &M) {
/* Make up cur_loc */ /* Make up cur_loc */
// cur_loc++; // cur_loc++;
cur_loc = AFL_R(MAP_SIZE); cur_loc = AFL_R(map_size);
/* There is a problem with Ubuntu 18.04 and llvm 6.0 (see issue #63). /* There is a problem with Ubuntu 18.04 and llvm 6.0 (see issue #63).
The inline function successors() is not inlined and also not found at runtime The inline function successors() is not inlined and also not found at runtime
@ -705,6 +719,56 @@ bool AFLCoverage::runOnModule(Module &M) {
} }
/*
// This is currently disabled because we not only need to create/insert a
// function (easy), but also add it as a constructor with an ID < 5
if (getenv("AFL_LLVM_DONTWRITEID") == NULL) {
// yes we could create our own function, insert it into ctors ...
// but this would be a pain in the butt ... so we use afl-llvm-rt.o
Function *f = ...
if (!f) {
fprintf(stderr,
"Error: init function could not be created (this should not
happen)\n"); exit(-1);
}
... constructor for f = 4
BasicBlock *bb = &f->getEntryBlock();
if (!bb) {
fprintf(stderr,
"Error: init function does not have an EntryBlock (this should
not happen)\n"); exit(-1);
}
BasicBlock::iterator IP = bb->getFirstInsertionPt();
IRBuilder<> IRB(&(*IP));
if (map_size <= 0x800000) {
GlobalVariable *AFLFinalLoc = new GlobalVariable(
M, Int32Ty, true, GlobalValue::ExternalLinkage, 0,
"__afl_final_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0,
false);
ConstantInt *const_loc = ConstantInt::get(Int32Ty, map_size);
StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None));
}
}
*/
/* Say something nice. */ /* Say something nice. */
if (!be_quiet) { if (!be_quiet) {

View File

@ -233,7 +233,9 @@ if [ "$ORIG_CPU_TARGET" = "" ]; then
gcc test-instr.c -o test-instr || exit 1 gcc test-instr.c -o test-instr || exit 1
unset AFL_INST_RATIO unset AFL_INST_RATIO
export ASAN_OPTIONS=detect_leaks=0
echo "[*] Comparing two afl-showmap -Q outputs..."
echo 0 | ./afl-showmap -m none -Q -q -o .test-instr0 ./test-instr || exit 1 echo 0 | ./afl-showmap -m none -Q -q -o .test-instr0 ./test-instr || exit 1
echo 1 | ./afl-showmap -m none -Q -q -o .test-instr1 ./test-instr || exit 1 echo 1 | ./afl-showmap -m none -Q -q -o .test-instr1 ./test-instr || exit 1

View File

@ -293,8 +293,8 @@ static void print_mappings(void) {
void afl_forkserver(CPUState *cpu) { void afl_forkserver(CPUState *cpu) {
u32 map_size = 0; u32 map_size = 0;
static unsigned char tmp[4] = {0, 0, 0, 0}; unsigned char tmp[4] = {0};
if (forkserver_installed == 1) return; if (forkserver_installed == 1) return;
forkserver_installed = 1; forkserver_installed = 1;

View File

@ -84,6 +84,7 @@ static volatile u8 stop_soon, /* Ctrl-C pressed? */
static u8 *target_path; static u8 *target_path;
static u8 qemu_mode; static u8 qemu_mode;
static u32 map_size = MAP_SIZE;
/* Constants used for describing byte behavior. */ /* Constants used for describing byte behavior. */
@ -115,7 +116,7 @@ static u8 count_class_lookup[256] = {
static void classify_counts(u8 *mem) { static void classify_counts(u8 *mem) {
u32 i = MAP_SIZE; u32 i = map_size;
if (edges_only) { if (edges_only) {
@ -144,7 +145,7 @@ static void classify_counts(u8 *mem) {
static inline u8 anything_set(void) { static inline u8 anything_set(void) {
u32 *ptr = (u32 *)trace_bits; u32 *ptr = (u32 *)trace_bits;
u32 i = (MAP_SIZE >> 2); u32 i = (map_size >> 2);
while (i--) while (i--)
if (*(ptr++)) return 1; if (*(ptr++)) return 1;
@ -209,7 +210,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
/* Execute target application. Returns exec checksum, or 0 if program /* Execute target application. Returns exec checksum, or 0 if program
times out. */ times out. */
static u32 run_target(char **argv, u8 *mem, u32 len, u8 first_run) { static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
static struct itimerval it; static struct itimerval it;
int status = 0; int status = 0;
@ -217,7 +218,7 @@ static u32 run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
s32 prog_in_fd; s32 prog_in_fd;
u32 cksum; u32 cksum;
memset(trace_bits, 0, MAP_SIZE); memset(trace_bits, 0, map_size);
MEM_BARRIER(); MEM_BARRIER();
prog_in_fd = write_to_file(prog_in, mem, len); prog_in_fd = write_to_file(prog_in, mem, len);
@ -311,7 +312,7 @@ static u32 run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
} }
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); cksum = hash32(trace_bits, map_size, HASH_CONST);
/* We don't actually care if the target is crashing or not, /* We don't actually care if the target is crashing or not,
except that when it does, the checksum should be different. */ except that when it does, the checksum should be different. */
@ -560,16 +561,16 @@ static void analyze(char **argv) {
code. */ code. */
in_data[i] ^= 0xff; in_data[i] ^= 0xff;
xor_ff = run_target(argv, in_data, in_len, 0); xor_ff = analyze_run_target(argv, in_data, in_len, 0);
in_data[i] ^= 0xfe; in_data[i] ^= 0xfe;
xor_01 = run_target(argv, in_data, in_len, 0); xor_01 = analyze_run_target(argv, in_data, in_len, 0);
in_data[i] = (in_data[i] ^ 0x01) - 0x10; in_data[i] = (in_data[i] ^ 0x01) - 0x10;
sub_10 = run_target(argv, in_data, in_len, 0); sub_10 = analyze_run_target(argv, in_data, in_len, 0);
in_data[i] += 0x20; in_data[i] += 0x20;
add_10 = run_target(argv, in_data, in_len, 0); add_10 = analyze_run_target(argv, in_data, in_len, 0);
in_data[i] -= 0x10; in_data[i] -= 0x10;
/* Classify current behavior. */ /* Classify current behavior. */
@ -795,8 +796,10 @@ static void usage(u8 *argv0) {
" (must contain abort_on_error=1 and symbolize=0)\n" " (must contain abort_on_error=1 and symbolize=0)\n"
"MSAN_OPTIONS: custom settings for MSAN\n" "MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_ANALYZE_HEX: print file offsets in hexadecimal instead of decimal\n" "AFL_ANALYZE_HEX: print file offsets in hexadecimal instead of decimal\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_SKIP_BIN_CHECK: skip checking the location of and the target\n" "AFL_SKIP_BIN_CHECK: skip checking the location of and the target\n"
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
@ -805,61 +808,6 @@ static void usage(u8 *argv0) {
} }
/* Find binary. */
static void find_binary(u8 *fname) {
u8 * env_path = 0;
struct stat st;
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
target_path = ck_strdup(fname);
if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4)
FATAL("Program '%s' not found or not executable", fname);
} else {
while (env_path) {
u8 *cur_elem, *delim = strchr(env_path, ':');
if (delim) {
cur_elem = ck_alloc(delim - env_path + 1);
memcpy(cur_elem, env_path, delim - env_path);
delim++;
} else
cur_elem = ck_strdup(env_path);
env_path = delim;
if (cur_elem[0])
target_path = alloc_printf("%s/%s", cur_elem, fname);
else
target_path = ck_strdup(fname);
ck_free(cur_elem);
if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4)
break;
ck_free(target_path);
target_path = 0;
}
if (!target_path) FATAL("Program '%s' not found or not executable", fname);
}
}
/* Main entry point */ /* Main entry point */
int main(int argc, char **argv, char **envp) { int main(int argc, char **argv, char **envp) {
@ -902,7 +850,7 @@ int main(int argc, char **argv, char **envp) {
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) FATAL("Multiple -m options not supported");
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) { FATAL("Bad syntax used for -m"); } if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
@ -986,18 +934,20 @@ int main(int argc, char **argv, char **envp) {
if (optind == argc || !in_file) usage(argv[0]); if (optind == argc || !in_file) usage(argv[0]);
map_size = get_map_size();
use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX");
check_environment_vars(envp); check_environment_vars(envp);
sharedmem_t shm = {0}; sharedmem_t shm = {0};
trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); trace_bits = afl_shm_init(&shm, map_size, 0);
atexit(at_exit_handler); atexit(at_exit_handler);
setup_signal_handlers(); setup_signal_handlers();
set_up_environment(); set_up_environment();
find_binary(argv[optind]); target_path = find_binary(argv[optind]);
detect_file_args(argv + optind, prog_in, &use_stdin); detect_file_args(argv + optind, prog_in, &use_stdin);
if (qemu_mode) { if (qemu_mode) {
@ -1020,7 +970,7 @@ int main(int argc, char **argv, char **envp) {
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
mem_limit, exec_tmout, edges_only ? ", edges only" : ""); mem_limit, exec_tmout, edges_only ? ", edges only" : "");
run_target(use_argv, in_data, in_len, 1); analyze_run_target(use_argv, in_data, in_len, 1);
if (child_timed_out) if (child_timed_out)
FATAL("Target binary times out (adjusting -t may help)."); FATAL("Target binary times out (adjusting -t may help).");
@ -1032,6 +982,8 @@ int main(int argc, char **argv, char **envp) {
OKF("We're done here. Have a nice day!\n"); OKF("We're done here. Have a nice day!\n");
if (target_path) ck_free(target_path);
afl_shm_deinit(&shm); afl_shm_deinit(&shm);
exit(0); exit(0);

View File

@ -37,6 +37,10 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <limits.h> #include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
u8 be_quiet = 0; u8 be_quiet = 0;
u8 *doc_path = ""; u8 *doc_path = "";
@ -68,7 +72,7 @@ char *afl_environment_variables[] = {
"AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
"AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
"AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
//"AFL_PERSISTENT", // not implemented anymore, so warn additionally //"AFL_PERSISTENT", // not implemented anymore, so warn additionally
"AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV", "AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV",
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
@ -218,10 +222,12 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
} }
} else } else {
ck_free(own_copy); ck_free(own_copy);
}
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
if (cp) ck_free(cp); if (cp) ck_free(cp);
@ -353,6 +359,79 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
} }
/* Find binary, used by analyze, showmap, tmin
@returns the path, allocating the string */
u8 *find_binary(u8 *fname) {
// TODO: Merge this function with check_binary of afl-fuzz-init.c
u8 *env_path = NULL;
u8 *target_path = NULL;
struct stat st;
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
target_path = ck_strdup(fname);
if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4) {
free(target_path);
FATAL("Program '%s' not found or not executable", fname);
}
} else {
while (env_path) {
u8 *cur_elem, *delim = strchr(env_path, ':');
if (delim) {
cur_elem = ck_alloc(delim - env_path + 1);
memcpy(cur_elem, env_path, delim - env_path);
delim++;
} else {
cur_elem = ck_strdup(env_path);
}
env_path = delim;
if (cur_elem[0]) {
target_path = alloc_printf("%s/%s", cur_elem, fname);
} else {
target_path = ck_strdup(fname);
}
ck_free(cur_elem);
if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4)
break;
ck_free(target_path);
target_path = NULL;
}
if (!target_path) FATAL("Program '%s' not found or not executable", fname);
}
return target_path;
}
void check_environment_vars(char **envp) { void check_environment_vars(char **envp) {
if (be_quiet) return; if (be_quiet) return;
@ -414,6 +493,20 @@ char *get_afl_env(char *env) {
} }
/* Read mask bitmap from file. This is for the -B option. */
void read_bitmap(u8 *fname, u8 *map, size_t len) {
s32 fd = open(fname, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fname);
ck_read(fd, map, len, fname);
close(fd);
}
u64 get_cur_time(void) { u64 get_cur_time(void) {
struct timeval tv; struct timeval tv;
@ -805,3 +898,21 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms,
} }
u32 get_map_size() {
uint32_t map_size = MAP_SIZE;
char * ptr;
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
map_size = atoi(ptr);
if (map_size < 8 || map_size > (1 << 29))
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size);
if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3);
}
return map_size;
}

View File

@ -97,6 +97,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->use_stdin = from->use_stdin; fsrv_to->use_stdin = from->use_stdin;
fsrv_to->out_fd = from->out_fd;
fsrv_to->dev_null_fd = from->dev_null_fd; fsrv_to->dev_null_fd = from->dev_null_fd;
fsrv_to->exec_tmout = from->exec_tmout; fsrv_to->exec_tmout = from->exec_tmout;
fsrv_to->mem_limit = from->mem_limit; fsrv_to->mem_limit = from->mem_limit;
@ -107,7 +108,6 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
#endif #endif
// These are forkserver specific. // These are forkserver specific.
fsrv_to->out_fd = -1;
fsrv_to->out_dir_fd = -1; fsrv_to->out_dir_fd = -1;
fsrv_to->child_pid = -1; fsrv_to->child_pid = -1;
fsrv_to->use_fauxsrv = 0; fsrv_to->use_fauxsrv = 0;
@ -395,7 +395,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
if (!be_quiet) if (!be_quiet && getenv("AFL_DEBUG"))
ACTF("Extended forkserver functions received (%08x).", status); ACTF("Extended forkserver functions received (%08x).", status);
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
@ -407,15 +407,26 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
fsrv->map_size = FS_OPT_GET_MAPSIZE(status); u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
if (fsrv->map_size % 8) // should not happen
fsrv->map_size = (((fsrv->map_size + 8) >> 3) << 3); if (!fsrv->map_size) fsrv->map_size = MAP_SIZE;
if (!be_quiet) ACTF("Target map size: %u", fsrv->map_size);
if (fsrv->map_size > MAP_SIZE) if (unlikely(tmp_map_size % 8)) {
// should not happen
WARNF("Target reported non-aligned map size of %ud", tmp_map_size);
tmp_map_size = (((tmp_map_size + 8) >> 3) << 3);
}
if (!be_quiet) ACTF("Target map size: %u", tmp_map_size);
if (tmp_map_size > fsrv->map_size)
FATAL( FATAL(
"Target's coverage map size of %u is larger than the one this " "Target's coverage map size of %u is larger than the one this "
"afl++ is compiled with (%u)\n", "afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and "
fsrv->map_size, MAP_SIZE); "recompile or set AFL_MAP_SIZE)\n",
tmp_map_size, fsrv->map_size);
fsrv->map_size = tmp_map_size;
} }
@ -444,7 +455,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u32 len = status, offset = 0, count = 0; u32 len = status, offset = 0, count = 0;
u8 *dict = ck_alloc(len); u8 *dict = ck_alloc(len);
if (dict == NULL) if (dict == NULL)
FATAL("Could not allocate %u bytes of autodictionary memmory", len); FATAL("Could not allocate %u bytes of autodictionary memory", len);
while (len != 0) { while (len != 0) {
@ -695,10 +706,8 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
/* Execute target application, monitoring for timeouts. Return status /* Execute target application, monitoring for timeouts. Return status
information. The called program will update afl->fsrv->trace_bits. */ information. The called program will update afl->fsrv->trace_bits. */
fsrv_run_result_t afl_fsrv_run_target( fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
afl_forkserver_t *fsrv, u32 timeout, volatile u8 *stop_soon_p) {
void(classify_counts_func)(afl_forkserver_t *fsrv),
volatile u8 *stop_soon_p) {
s32 res; s32 res;
u32 exec_ms; u32 exec_ms;
@ -727,7 +736,7 @@ fsrv_run_result_t afl_fsrv_run_target(
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (stop_soon_p) return 0; if (*stop_soon_p) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)"); RPFATAL(res, "Unable to request new process from fork server (OOM?)");
} }
@ -784,9 +793,6 @@ fsrv_run_result_t afl_fsrv_run_target(
behave very normally and do not have to be treated as volatile. */ behave very normally and do not have to be treated as volatile. */
MEM_BARRIER(); MEM_BARRIER();
u32 tb4 = *(u32 *)fsrv->trace_bits;
if (likely(classify_counts_func)) classify_counts_func(fsrv);
/* Report outcome to caller. */ /* Report outcome to caller. */
@ -811,7 +817,8 @@ fsrv_run_result_t afl_fsrv_run_target(
} }
if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR; // Fauxserver should handle this now.
// if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
return FSRV_RUN_OK; return FSRV_RUN_OK;

View File

@ -43,21 +43,7 @@ void write_bitmap(afl_state_t *afl) {
if (fd < 0) PFATAL("Unable to open '%s'", fname); if (fd < 0) PFATAL("Unable to open '%s'", fname);
ck_write(fd, afl->virgin_bits, MAP_SIZE, fname); ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname);
close(fd);
}
/* Read bitmap from file. This is for the -B option again. */
void read_bitmap(afl_state_t *afl, u8 *fname) {
s32 fd = open(fname, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fname);
ck_read(fd, afl->virgin_bits, MAP_SIZE, fname);
close(fd); close(fd);
@ -88,7 +74,8 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
u32 i = (afl->fsrv.map_size >> 2); u32 i = (afl->fsrv.map_size >> 2);
#endif /* ^WORD_SIZE_64 */ #endif /* ^WORD_SIZE_64 */
if (i == 0) i = 1; // the map size must be a minimum of 8 bytes.
// for variable/dynamic map sizes this is ensured in the forkserver
u8 ret = 0; u8 ret = 0;
@ -98,6 +85,7 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
that have not been already cleared from the virgin map - since this will that have not been already cleared from the virgin map - since this will
almost always be the case. */ almost always be the case. */
// the (*current) is unnecessary but speeds up the overall comparison
if (unlikely(*current) && unlikely(*current & *virgin)) { if (unlikely(*current) && unlikely(*current & *virgin)) {
if (likely(ret < 2)) { if (likely(ret < 2)) {
@ -110,18 +98,20 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64
if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || if (*virgin == 0xffffffffffffffff || (cur[0] && vir[0] == 0xff) ||
(cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) ||
(cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || (cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) ||
(cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) (cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) ||
(cur[7] && vir[7] == 0xff))
ret = 2; ret = 2;
else else
ret = 1; ret = 1;
#else #else
if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) ||
(cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) ||
(cur[3] && vir[3] == 0xff))
ret = 2; ret = 2;
else else
ret = 1; ret = 1;
@ -139,7 +129,7 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
} }
if (unlikely(ret) && unlikely(virgin_map == afl->virgin_bits)) if (unlikely(ret) && likely(virgin_map == afl->virgin_bits))
afl->bitmap_changed = 1; afl->bitmap_changed = 1;
return ret; return ret;
@ -155,8 +145,6 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
u32 i = (afl->fsrv.map_size >> 2); u32 i = (afl->fsrv.map_size >> 2);
u32 ret = 0; u32 ret = 0;
if (i == 0) i = 1;
while (i--) { while (i--) {
u32 v = *(ptr++); u32 v = *(ptr++);
@ -191,8 +179,6 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
u32 i = (afl->fsrv.map_size >> 2); u32 i = (afl->fsrv.map_size >> 2);
u32 ret = 0; u32 ret = 0;
if (i == 0) i = 1;
while (i--) { while (i--) {
u32 v = *(ptr++); u32 v = *(ptr++);
@ -218,8 +204,6 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
u32 i = (afl->fsrv.map_size >> 2); u32 i = (afl->fsrv.map_size >> 2);
u32 ret = 0; u32 ret = 0;
if (i == 0) i = 1;
while (i--) { while (i--) {
u32 v = *(ptr++); u32 v = *(ptr++);
@ -256,8 +240,6 @@ void simplify_trace(afl_state_t *afl, u64 *mem) {
u32 i = (afl->fsrv.map_size >> 3); u32 i = (afl->fsrv.map_size >> 3);
if (i == 0) i = 1;
while (i--) { while (i--) {
/* Optimize for sparse bitmaps. */ /* Optimize for sparse bitmaps. */
@ -291,8 +273,6 @@ void simplify_trace(afl_state_t *afl, u32 *mem) {
u32 i = (afl->fsrv.map_size >> 2); u32 i = (afl->fsrv.map_size >> 2);
if (i == 0) i = 1;
while (i--) { while (i--) {
/* Optimize for sparse bitmaps. */ /* Optimize for sparse bitmaps. */
@ -357,8 +337,6 @@ void classify_counts(afl_forkserver_t *fsrv) {
u32 i = (fsrv->map_size >> 3); u32 i = (fsrv->map_size >> 3);
if (i == 0) i = 1;
while (i--) { while (i--) {
/* Optimize for sparse bitmaps. */ /* Optimize for sparse bitmaps. */
@ -388,8 +366,6 @@ void classify_counts(afl_forkserver_t *fsrv) {
u32 i = (fsrv->map_size >> 2); u32 i = (fsrv->map_size >> 2);
if (i == 0) i = 1;
while (i--) { while (i--) {
/* Optimize for sparse bitmaps. */ /* Optimize for sparse bitmaps. */
@ -649,7 +625,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
u8 new_fault; u8 new_fault;
write_to_testcase(afl, mem, len); write_to_testcase(afl, mem, len);
new_fault = run_target(afl, &afl->fsrv, afl->hang_tmout); new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
/* A corner case that one user reported bumping into: increasing the /* A corner case that one user reported bumping into: increasing the
timeout actually uncovers a crash. Make sure we don't discard it if timeout actually uncovers a crash. Make sure we don't discard it if

View File

@ -62,7 +62,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
write_to_testcase(afl, out_buf, len); write_to_testcase(afl, out_buf, len);
fault = run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) return 1; if (afl->stop_soon) return 1;

View File

@ -442,23 +442,6 @@ void read_testcases(afl_state_t *afl) {
} }
/* Examine map coverage. Called once, for first test case. */
static void check_map_coverage(afl_state_t *afl) {
u32 i;
if (count_bytes(afl, afl->fsrv.trace_bits) < 100) return;
for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; ++i)
if (afl->fsrv.trace_bits[i]) return;
if (afl->fsrv.map_size != MAP_SIZE) return;
WARNF("Recompile binary with newer version of afl to improve coverage!");
}
/* Perform dry run of all test cases to confirm that the app is working as /* Perform dry run of all test cases to confirm that the app is working as
expected. This is done only for the initial inputs, and only once. */ expected. This is done only for the initial inputs, and only once. */
@ -501,8 +484,6 @@ void perform_dry_run(afl_state_t *afl) {
case FSRV_RUN_OK: case FSRV_RUN_OK:
if (q == afl->queue) check_map_coverage(afl);
if (afl->crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); if (afl->crash_mode) FATAL("Test case '%s' does *NOT* crash", fn);
break; break;
@ -1419,6 +1400,8 @@ void setup_dirs_fds(afl_state_t *afl) {
"# unix_time, cycles_done, cur_path, paths_total, " "# unix_time, cycles_done, cur_path, paths_total, "
"pending_total, pending_favs, map_size, unique_crashes, " "pending_total, pending_favs, map_size, unique_crashes, "
"unique_hangs, max_depth, execs_per_sec\n"); "unique_hangs, max_depth, execs_per_sec\n");
fflush(afl->fsrv.plot_file);
/* ignore errors */ /* ignore errors */
} }

View File

@ -27,9 +27,6 @@
#include "afl-fuzz.h" #include "afl-fuzz.h"
void load_custom_mutator(afl_state_t *, const char *); void load_custom_mutator(afl_state_t *, const char *);
#ifdef USE_PYTHON
void load_custom_mutator_py(afl_state_t *, char *);
#endif
void setup_custom_mutator(afl_state_t *afl) { void setup_custom_mutator(afl_state_t *afl) {
@ -239,7 +236,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
write_to_testcase(afl, retbuf, retlen); write_to_testcase(afl, retbuf, retlen);
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs; ++afl->trim_execs;
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }

View File

@ -27,7 +27,7 @@
/* MOpt */ /* MOpt */
int select_algorithm(afl_state_t *afl) { static int select_algorithm(afl_state_t *afl) {
int i_puppet, j_puppet; int i_puppet, j_puppet;
@ -2366,7 +2366,7 @@ abandon_entry:
} }
/* MOpt mode */ /* MOpt mode */
u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
if (!MOpt_globals.is_pilot_mode) { if (!MOpt_globals.is_pilot_mode) {

View File

@ -41,8 +41,8 @@ it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
(void **)&((py_mutator_t *)py_mutator)->name##_buf, \ (void **)&((py_mutator_t *)py_mutator)->name##_buf, \
&((py_mutator_t *)py_mutator)->name##_size &((py_mutator_t *)py_mutator)->name##_size
size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
u8 *add_buf, size_t add_buf_size, size_t max_size) { u8 *add_buf, size_t add_buf_size, size_t max_size) {
size_t mutated_size; size_t mutated_size;
PyObject *py_args, *py_value; PyObject *py_args, *py_value;

View File

@ -249,7 +249,6 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
if (!q->trace_mini) { if (!q->trace_mini) {
u32 len = (afl->fsrv.map_size >> 3); u32 len = (afl->fsrv.map_size >> 3);
if (len == 0) len = 1;
q->trace_mini = ck_alloc(len); q->trace_mini = ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
@ -272,12 +271,12 @@ void cull_queue(afl_state_t *afl) {
struct queue_entry *q; struct queue_entry *q;
u32 len = (afl->fsrv.map_size >> 3); u32 len = (afl->fsrv.map_size >> 3);
u32 i; u32 i;
u8 temp_v[MAP_SIZE >> 3]; u8 * temp_v;
if (len == 0) len = 1;
if (afl->dumb_mode || !afl->score_changed) return; if (afl->dumb_mode || !afl->score_changed) return;
temp_v = ck_maybe_grow((void **)&afl->map_tmp_buf, &afl->map_tmp_size, afl->fsrv.map_size >> 3);
afl->score_changed = 0; afl->score_changed = 0;
memset(temp_v, 255, len); memset(temp_v, 255, len);

View File

@ -37,7 +37,7 @@ struct range {
}; };
struct range *add_range(struct range *ranges, u32 start, u32 end) { static struct range *add_range(struct range *ranges, u32 start, u32 end) {
struct range *r = ck_alloc_nozero(sizeof(struct range)); struct range *r = ck_alloc_nozero(sizeof(struct range));
r->start = start; r->start = start;
@ -47,7 +47,7 @@ struct range *add_range(struct range *ranges, u32 start, u32 end) {
} }
struct range *pop_biggest_range(struct range **ranges) { static struct range *pop_biggest_range(struct range **ranges) {
struct range *r = *ranges; struct range *r = *ranges;
struct range *prev = NULL; struct range *prev = NULL;

View File

@ -33,10 +33,13 @@
/* Execute target application, monitoring for timeouts. Return status /* Execute target application, monitoring for timeouts. Return status
information. The called program will update afl->fsrv->trace_bits. */ information. The called program will update afl->fsrv->trace_bits. */
fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv, fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
u32 timeout) { u32 timeout) {
return afl_fsrv_run_target(fsrv, timeout, classify_counts, &afl->stop_soon); fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon);
// TODO: Don't classify for faults?
classify_counts(fsrv);
return res;
} }
@ -50,7 +53,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
s32 doc_fd; s32 doc_fd;
char fn[PATH_MAX]; char fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir, snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
afl->document_counter++, describe_op(afl, 0)); afl->document_counter++, describe_op(afl, 0));
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
@ -188,7 +191,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
write_to_testcase(afl, use_mem, q->len); write_to_testcase(afl, use_mem, q->len);
fault = run_target(afl, &afl->fsrv, use_tmout); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */ we want to bail out quickly. */
@ -406,7 +409,7 @@ void sync_fuzzers(afl_state_t *afl) {
write_to_testcase(afl, mem, st.st_size); write_to_testcase(afl, mem, st.st_size);
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) goto close_sync; if (afl->stop_soon) goto close_sync;
@ -493,7 +496,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail);
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs; ++afl->trim_execs;
if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming; if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming;
@ -600,7 +603,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
write_to_testcase(afl, out_buf, len); write_to_testcase(afl, out_buf, len);
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) return 1; if (afl->stop_soon) return 1;

View File

@ -75,12 +75,14 @@ list_t afl_states = {.element_prealloc_count = 0};
/* Initializes an afl_state_t. */ /* Initializes an afl_state_t. */
void afl_state_init(afl_state_t *afl) { void afl_state_init(afl_state_t *afl, uint32_t map_size) {
/* thanks to this memset, growing vars like out_buf /* thanks to this memset, growing vars like out_buf
and out_size are NULL/0 by default. */ and out_size are NULL/0 by default. */
memset(afl, 0, sizeof(afl_state_t)); memset(afl, 0, sizeof(afl_state_t));
if (!map_size) afl->shm.map_size = MAP_SIZE;
afl->w_init = 0.9; afl->w_init = 0.9;
afl->w_end = 0.3; afl->w_end = 0.3;
afl->g_max = 5000; afl->g_max = 5000;
@ -97,9 +99,17 @@ void afl_state_init(afl_state_t *afl) {
afl->cpu_aff = -1; /* Selected CPU core */ afl->cpu_aff = -1; /* Selected CPU core */
#endif /* HAVE_AFFINITY */ #endif /* HAVE_AFFINITY */
afl->fsrv.use_stdin = 1; afl->virgin_bits = ck_alloc(map_size);
afl->virgin_tmout = ck_alloc(map_size);
afl->virgin_crash = ck_alloc(map_size);
afl->var_bytes = ck_alloc(map_size);
afl->top_rated = ck_alloc(map_size * sizeof(void *));
afl->clean_trace = ck_alloc(map_size);
afl->clean_trace_custom = ck_alloc(map_size);
afl->first_trace = ck_alloc(map_size);
afl->fsrv.map_size = MAP_SIZE; afl->fsrv.use_stdin = 1;
afl->fsrv.map_size = map_size;
afl->fsrv.function_opt = (u8 *)afl; afl->fsrv.function_opt = (u8 *)afl;
afl->fsrv.function_ptr = &maybe_add_auto; afl->fsrv.function_ptr = &maybe_add_auto;
@ -364,12 +374,21 @@ void afl_state_deinit(afl_state_t *afl) {
if (afl->pass_stats) ck_free(afl->pass_stats); if (afl->pass_stats) ck_free(afl->pass_stats);
if (afl->orig_cmp_map) ck_free(afl->orig_cmp_map); if (afl->orig_cmp_map) ck_free(afl->orig_cmp_map);
free(afl->out_buf); if (afl->out_buf) free(afl->out_buf);
free(afl->out_scratch_buf); if (afl->out_scratch_buf) free(afl->out_scratch_buf);
free(afl->eff_buf); if (afl->eff_buf) free(afl->eff_buf);
free(afl->in_buf); if (afl->in_buf) free(afl->in_buf);
free(afl->in_scratch_buf); if (afl->in_scratch_buf) free(afl->in_scratch_buf);
free(afl->ex_buf); if (afl->ex_buf) free(afl->ex_buf);
ck_free(afl->virgin_bits);
ck_free(afl->virgin_tmout);
ck_free(afl->virgin_crash);
ck_free(afl->var_bytes);
ck_free(afl->top_rated);
ck_free(afl->clean_trace);
ck_free(afl->clean_trace_custom);
ck_free(afl->first_trace);
list_remove(&afl_states, afl); list_remove(&afl_states, afl);

View File

@ -145,14 +145,15 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
if (afl->plot_prev_qp == afl->queued_paths && if (unlikely(afl->plot_prev_qp == afl->queued_paths &&
afl->plot_prev_pf == afl->pending_favored && afl->plot_prev_pf == afl->pending_favored &&
afl->plot_prev_pnf == afl->pending_not_fuzzed && afl->plot_prev_pnf == afl->pending_not_fuzzed &&
afl->plot_prev_ce == afl->current_entry && afl->plot_prev_ce == afl->current_entry &&
afl->plot_prev_qc == afl->queue_cycle && afl->plot_prev_qc == afl->queue_cycle &&
afl->plot_prev_uc == afl->unique_crashes && afl->plot_prev_uc == afl->unique_crashes &&
afl->plot_prev_uh == afl->unique_hangs && afl->plot_prev_uh == afl->unique_hangs &&
afl->plot_prev_md == afl->max_depth) afl->plot_prev_md == afl->max_depth) ||
unlikely(!afl->queue_cycle))
return; return;
afl->plot_prev_qp = afl->queued_paths; afl->plot_prev_qp = afl->queued_paths;
@ -388,9 +389,9 @@ void show_stats(afl_state_t *afl) {
/* Lord, forgive me this. */ /* Lord, forgive me this. */
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
" process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
" overall results " bSTG bH2 bH2 bRT "\n"); " overall results " bSTG bH2 bH2 bRT "\n");
if (afl->dumb_mode) { if (afl->dumb_mode) {
@ -472,9 +473,9 @@ void show_stats(afl_state_t *afl) {
" uniq hangs : " cRST "%-6s" bSTG bV "\n", " uniq hangs : " cRST "%-6s" bSTG bV "\n",
time_tmp, tmp); time_tmp, tmp);
SAYF(bVR bH bSTOP cCYA SAYF(bVR bH bSTOP cCYA
" cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); " map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
/* This gets funny because we want to print several variable-length variables /* This gets funny because we want to print several variable-length variables
together, but then cram them into a fixed-width field - so we need to together, but then cram them into a fixed-width field - so we need to
@ -504,9 +505,9 @@ void show_stats(afl_state_t *afl) {
SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
SAYF(bVR bH bSTOP cCYA SAYF(bVR bH bSTOP cCYA
" stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
((double)afl->queued_favored) * 100 / afl->queued_paths); ((double)afl->queued_favored) * 100 / afl->queued_paths);
@ -580,7 +581,7 @@ void show_stats(afl_state_t *afl) {
/* Aaaalmost there... hold on! */ /* Aaaalmost there... hold on! */
SAYF(bVR bH cCYA bSTOP SAYF(bVR bH cCYA bSTOP
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
" path geometry " bSTG bH5 bH2 bVL "\n"); " path geometry " bSTG bH5 bH2 bVL "\n");

View File

@ -150,44 +150,46 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
if (more_help > 1) if (more_help > 1)
SAYF( SAYF(
"Environment variables used:\n" "Environment variables used:\n"
"AFL_PATH: path to AFL support binaries\n"
"AFL_QUIET: suppress forkserver status messages\n"
"AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"AFL_BENCH_JUST_ONE: run the target just once\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_NO_UI: switch status screen off\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
"AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
"AFL_POST_LIBRARY: postprocess generated test cases before use as target input\n"
"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"ASAN_OPTIONS: custom settings for ASAN\n" "ASAN_OPTIONS: custom settings for ASAN\n"
" (must contain abort_on_error=1 and symbolize=0)\n" " (must contain abort_on_error=1 and symbolize=0)\n"
"MSAN_OPTIONS: custom settings for MSAN\n" "MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
"AFL_BENCH_JUST_ONE: run the target just once\n"
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
"AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
"AFL_NO_UI: switch status screen off\n"
"AFL_PATH: path to AFL support binaries\n"
"AFL_POST_LIBRARY: postprocess generated test cases before use as target input\n"
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
"AFL_QUIET: suppress forkserver status messages\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
"AFL_SKIP_BIN_CHECK: skip the check, if the target is an excutable\n" "AFL_SKIP_BIN_CHECK: skip the check, if the target is an excutable\n"
"AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
"AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
//"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n" //"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n"
//"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
"\n" "\n"
); );
else else
@ -231,7 +233,7 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt; s32 opt;
u64 prev_queued = 0; u64 prev_queued = 0;
u32 sync_interval_cnt = 0, seek_to, show_help = 0; u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE;
u8 * extras_dir = 0; u8 * extras_dir = 0;
u8 mem_limit_given = 0, exit_1 = 0; u8 mem_limit_given = 0, exit_1 = 0;
char **use_argv; char **use_argv;
@ -244,11 +246,14 @@ int main(int argc, char **argv_orig, char **envp) {
afl_state_t *afl = calloc(1, sizeof(afl_state_t)); afl_state_t *afl = calloc(1, sizeof(afl_state_t));
if (!afl) { FATAL("Could not create afl state"); } if (!afl) { FATAL("Could not create afl state"); }
afl_state_init(afl); if (get_afl_env("AFL_DEBUG")) afl->debug = 1;
map_size = get_map_size();
afl_state_init(afl, map_size);
afl_fsrv_init(&afl->fsrv); afl_fsrv_init(&afl->fsrv);
if (get_afl_env("AFL_DEBUG")) afl->debug = 1;
read_afl_environment(afl, envp); read_afl_environment(afl, envp);
if (afl->shm.map_size) afl->fsrv.map_size = afl->shm.map_size;
exit_1 = !!afl->afl_env.afl_bench_just_one; exit_1 = !!afl->afl_env.afl_bench_just_one;
SAYF(cCYA "afl-fuzz" VERSION cRST SAYF(cCYA "afl-fuzz" VERSION cRST
@ -420,6 +425,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) FATAL("Multiple -m options not supported");
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m");
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
afl->fsrv.mem_limit = 0; afl->fsrv.mem_limit = 0;
@ -474,7 +481,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->in_bitmap) FATAL("Multiple -B options not supported"); if (afl->in_bitmap) FATAL("Multiple -B options not supported");
afl->in_bitmap = optarg; afl->in_bitmap = optarg;
read_bitmap(afl, afl->in_bitmap); read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
break; break;
case 'C': /* crash mode */ case 'C': /* crash mode */
@ -908,13 +915,14 @@ int main(int argc, char **argv_orig, char **envp) {
check_crash_handling(); check_crash_handling();
check_cpu_governor(afl); check_cpu_governor(afl);
afl->fsrv.trace_bits = afl_shm_init(&afl->shm, MAP_SIZE, afl->dumb_mode); afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->dumb_mode);
setup_post(afl); setup_post(afl);
if (!afl->in_bitmap) memset(afl->virgin_bits, 255, MAP_SIZE); if (!afl->in_bitmap) memset(afl->virgin_bits, 255, afl->fsrv.map_size);
memset(afl->virgin_tmout, 255, MAP_SIZE); memset(afl->virgin_tmout, 255, afl->fsrv.map_size);
memset(afl->virgin_crash, 255, MAP_SIZE); memset(afl->virgin_crash, 255, afl->fsrv.map_size);
init_count_class16(); init_count_class16();

View File

@ -411,6 +411,15 @@ int main(int argc, char **argv) {
} }
u8 *ptr;
if (!be_quiet &&
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
u32 map_size = atoi(ptr);
if (map_size != MAP_SIZE) FATAL("AFL_MAP_SIZE is not supported by afl-gcc");
}
find_as(argv[0]); find_as(argv[0]);
edit_params(argc, argv); edit_params(argc, argv);

View File

@ -60,7 +60,7 @@
#include <sys/shm.h> #include <sys/shm.h>
#endif #endif
list_t shm_list = {.element_prealloc_count = 0}; static list_t shm_list = {.element_prealloc_count = 0};
/* Get rid of shared memory. */ /* Get rid of shared memory. */
@ -72,7 +72,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
#ifdef USEMMAP #ifdef USEMMAP
if (shm->map != NULL) { if (shm->map != NULL) {
munmap(shm->map, shm->size_alloc); munmap(shm->map, shm->map_size);
shm->map = NULL; shm->map = NULL;
} }
@ -99,7 +99,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
shm->size_alloc = shm->size_used = map_size; shm->map_size = map_size;
shm->map = NULL; shm->map = NULL;

View File

@ -52,6 +52,7 @@
#include <signal.h> #include <signal.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h> #include <sys/time.h>
@ -63,8 +64,7 @@
static char *stdin_file; /* stdin file */ static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */ static u8 *in_dir = NULL, /* input folder */
*out_file = NULL, *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
*at_file = NULL; /* Substitution string for @@ */
static u8 *in_data; /* Input data */ static u8 *in_data; /* Input data */
@ -73,6 +73,8 @@ static u32 total, highest; /* tuple content information */
static u32 in_len, /* Input data length */ static u32 in_len, /* Input data length */
arg_offset; /* Total number of execs */ arg_offset; /* Total number of execs */
static u32 map_size = MAP_SIZE;
static u8 quiet_mode, /* Hide non-essential messages? */ static u8 quiet_mode, /* Hide non-essential messages? */
edges_only, /* Ignore hit counts? */ edges_only, /* Ignore hit counts? */
raw_instr_output, /* Do not apply AFL filters */ raw_instr_output, /* Do not apply AFL filters */
@ -113,7 +115,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
u8 * mem = fsrv->trace_bits; u8 * mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human; const u8 *map = binary_mode ? count_class_binary : count_class_human;
u32 i = MAP_SIZE; u32 i = map_size;
if (edges_only) { if (edges_only) {
@ -176,10 +178,10 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (binary_mode) { if (binary_mode) {
for (i = 0; i < MAP_SIZE; i++) for (i = 0; i < map_size; i++)
if (fsrv->trace_bits[i]) ret++; if (fsrv->trace_bits[i]) ret++;
ck_write(fd, fsrv->trace_bits, MAP_SIZE, outfile); ck_write(fd, fsrv->trace_bits, map_size, outfile);
close(fd); close(fd);
} else { } else {
@ -188,7 +190,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (!f) PFATAL("fdopen() failed"); if (!f) PFATAL("fdopen() failed");
for (i = 0; i < MAP_SIZE; i++) { for (i = 0; i < map_size; i++) {
if (!fsrv->trace_bits[i]) continue; if (!fsrv->trace_bits[i]) continue;
ret++; ret++;
@ -219,18 +221,20 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
/* Execute target application. */ /* Execute target application. */
void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv,
u32 len) { u8 *mem, u32 len) {
afl_fsrv_write_to_testcase(fsrv, mem, len); afl_fsrv_write_to_testcase(fsrv, mem, len);
if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
&stop_soon) == FSRV_RUN_ERROR) { FSRV_RUN_ERROR) {
FATAL("Error running target"); FATAL("Error running target");
} }
classify_counts(fsrv);
if (stop_soon) { if (stop_soon) {
SAYF(cRST cLRD "\n+++ afl-showmap folder mode aborted by user +++\n" cRST); SAYF(cRST cLRD "\n+++ afl-showmap folder mode aborted by user +++\n" cRST);
@ -242,7 +246,7 @@ void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
/* Read initial file. */ /* Read initial file. */
u32 read_file(u8 *in_file) { static u32 read_file(u8 *in_file) {
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
@ -267,7 +271,7 @@ u32 read_file(u8 *in_file) {
/* Execute target application. */ /* Execute target application. */
static void run_target(afl_forkserver_t *fsrv, char **argv) { static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
static struct itimerval it; static struct itimerval it;
int status = 0; int status = 0;
@ -485,11 +489,9 @@ static void usage(u8 *argv0) {
"\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" "\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
"Required parameters:\n" "Required parameters:\n"
" -o file - file to write the trace data to\n\n" " -o file - file to write the trace data to\n\n"
"Execution control settings:\n" "Execution control settings:\n"
" -t msec - timeout for each run (none)\n" " -t msec - timeout for each run (none)\n"
" -m megs - memory limit for child process (%d MB)\n" " -m megs - memory limit for child process (%d MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
@ -497,9 +499,7 @@ static void usage(u8 *argv0) {
" -W - use qemu-based instrumentation with Wine (Wine mode)\n" " -W - use qemu-based instrumentation with Wine (Wine mode)\n"
" (Not necessary, here for consistency with other afl-* " " (Not necessary, here for consistency with other afl-* "
"tools)\n\n" "tools)\n\n"
"Other settings:\n" "Other settings:\n"
" -i dir - process all files in this directory, -o must be a " " -i dir - process all files in this directory, -o must be a "
"directory\n" "directory\n"
" and each bitmap will be written there individually.\n" " and each bitmap will be written there individually.\n"
@ -512,75 +512,22 @@ static void usage(u8 *argv0) {
"For additional help, consult %s/README.md.\n\n" "For additional help, consult %s/README.md.\n\n"
"Environment variables used:\n" "Environment variables used:\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"AFL_DEBUG: enable extra developer output\n"
"AFL_QUIET: do not print extra informational output"
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing " "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
"inputs\n" "inputs\n"
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n" "AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n", "AFL_DEBUG: enable extra developer output\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_QUIET: do not print extra informational output",
argv0, MEM_LIMIT, doc_path); argv0, MEM_LIMIT, doc_path);
exit(1); exit(1);
} }
/* Find binary. */
static void find_binary(afl_forkserver_t *fsrv, u8 *fname) {
u8 * env_path = 0;
struct stat st;
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
fsrv->target_path = ck_strdup(fname);
if (stat(fsrv->target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4)
FATAL("Program '%s' not found or not executable", fname);
} else {
while (env_path) {
u8 *cur_elem, *delim = strchr(env_path, ':');
if (delim) {
cur_elem = ck_alloc(delim - env_path + 1);
memcpy(cur_elem, env_path, delim - env_path);
delim++;
} else
cur_elem = ck_strdup(env_path);
env_path = delim;
if (cur_elem[0])
fsrv->target_path = alloc_printf("%s/%s", cur_elem, fname);
else
fsrv->target_path = ck_strdup(fname);
ck_free(cur_elem);
if (!stat(fsrv->target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4)
break;
ck_free(fsrv->target_path);
fsrv->target_path = NULL;
}
if (!fsrv->target_path)
FATAL("Program '%s' not found or not executable", fname);
}
}
/* Main entry point */ /* Main entry point */
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
@ -597,6 +544,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl_forkserver_t fsrv_var = {0}; afl_forkserver_t fsrv_var = {0};
afl_forkserver_t *fsrv = &fsrv_var; afl_forkserver_t *fsrv = &fsrv_var;
afl_fsrv_init(fsrv); afl_fsrv_init(fsrv);
map_size = get_map_size();
fsrv->map_size = map_size;
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
@ -624,6 +573,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) FATAL("Multiple -m options not supported");
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m");
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
fsrv->mem_limit = 0; fsrv->mem_limit = 0;
@ -667,6 +618,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) FATAL("Multiple -t options not supported");
timeout_given = 1; timeout_given = 1;
if (!optarg) FATAL("Wrong usage of -t");
if (strcmp(optarg, "none")) { if (strcmp(optarg, "none")) {
fsrv->exec_tmout = atoi(optarg); fsrv->exec_tmout = atoi(optarg);
@ -766,12 +719,12 @@ int main(int argc, char **argv_orig, char **envp) {
check_environment_vars(envp); check_environment_vars(envp);
sharedmem_t shm = {0}; sharedmem_t shm = {0};
fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
setup_signal_handlers(); setup_signal_handlers();
set_up_environment(fsrv); set_up_environment(fsrv);
find_binary(fsrv, argv[optind]); fsrv->target_path = find_binary(argv[optind]);
if (!quiet_mode) { if (!quiet_mode) {
@ -878,12 +831,11 @@ int main(int argc, char **argv_orig, char **envp) {
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue; if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
#endif #endif
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
dir_ent->d_name);
if (read_file(infile)) { if (read_file(infile)) {
run_target_forkserver(fsrv, use_argv, in_data, in_len); showmap_run_target_forkserver(fsrv, use_argv, in_data, in_len);
ck_free(in_data); ck_free(in_data);
tcnt = write_results_to_file(fsrv, outfile); tcnt = write_results_to_file(fsrv, outfile);
@ -898,11 +850,9 @@ int main(int argc, char **argv_orig, char **envp) {
} else { } else {
run_target(fsrv, use_argv); showmap_run_target(fsrv, use_argv);
tcnt = write_results_to_file(fsrv, out_file); tcnt = write_results_to_file(fsrv, out_file);
} }
if (!quiet_mode) { if (!quiet_mode) {
@ -931,6 +881,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (stdin_file) ck_free(stdin_file); if (stdin_file) ck_free(stdin_file);
argv_cpy_free(argv); argv_cpy_free(argv);
if (fsrv->qemu_mode) free(use_argv[2]);
exit(ret); exit(ret);

View File

@ -62,8 +62,7 @@
static u8 *mask_bitmap; /* Mask for trace bits (-B) */ static u8 *mask_bitmap; /* Mask for trace bits (-B) */
static u8 *in_file, /* Minimizer input test case */ static u8 *in_file, /* Minimizer input test case */
*out_file, *out_file, *output_file; /* Minimizer output file */
*output_file; /* Minimizer output file */
static u8 *in_data; /* Input data for trimming */ static u8 *in_data; /* Input data for trimming */
@ -71,7 +70,8 @@ static u32 in_len, /* Input data length */
orig_cksum, /* Original checksum */ orig_cksum, /* Original checksum */
missed_hangs, /* Misses due to hangs */ missed_hangs, /* Misses due to hangs */
missed_crashes, /* Misses due to crashes */ missed_crashes, /* Misses due to crashes */
missed_paths; /* Misses due to exec path diffs */ missed_paths, /* Misses due to exec path diffs */
map_size = MAP_SIZE;
static u8 crash_mode, /* Crash-centric mode? */ static u8 crash_mode, /* Crash-centric mode? */
hang_mode, /* Minimize as long as it hangs */ hang_mode, /* Minimize as long as it hangs */
@ -106,7 +106,7 @@ static const u8 count_class_lookup[256] = {
static void apply_mask(u32 *mem, u32 *mask) { static void apply_mask(u32 *mem, u32 *mask) {
u32 i = (MAP_SIZE >> 2); u32 i = (map_size >> 2);
if (!mask) return; if (!mask) return;
@ -122,10 +122,8 @@ static void apply_mask(u32 *mem, u32 *mask) {
static void classify_counts(afl_forkserver_t *fsrv) { static void classify_counts(afl_forkserver_t *fsrv) {
if (hang_mode) return; /* We only want hangs */
u8 *mem = fsrv->trace_bits; u8 *mem = fsrv->trace_bits;
u32 i = MAP_SIZE; u32 i = map_size;
if (edges_only) { if (edges_only) {
@ -147,8 +145,6 @@ static void classify_counts(afl_forkserver_t *fsrv) {
} }
apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap);
} }
/* See if any bytes are set in the bitmap. */ /* See if any bytes are set in the bitmap. */
@ -156,7 +152,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
static inline u8 anything_set(afl_forkserver_t *fsrv) { static inline u8 anything_set(afl_forkserver_t *fsrv) {
u32 *ptr = (u32 *)fsrv->trace_bits; u32 *ptr = (u32 *)fsrv->trace_bits;
u32 i = (MAP_SIZE >> 2); u32 i = (map_size >> 2);
while (i--) while (i--)
if (*(ptr++)) return 1; if (*(ptr++)) return 1;
@ -219,13 +215,13 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
/* Execute target application. Returns 0 if the changes are a dud, or /* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */ 1 if they should be kept. */
static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
u8 first_run) { u8 first_run) {
afl_fsrv_write_to_testcase(fsrv, mem, len); afl_fsrv_write_to_testcase(fsrv, mem, len);
fsrv_run_result_t ret = fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, &stop_soon); afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child"); if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child");
@ -251,6 +247,9 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
} }
classify_counts(fsrv);
apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap);
if (ret == FSRV_RUN_TMOUT) { if (ret == FSRV_RUN_TMOUT) {
missed_hangs++; missed_hangs++;
@ -338,7 +337,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
memset(tmp_buf + set_pos, '0', use_len); memset(tmp_buf + set_pos, '0', use_len);
u8 res; u8 res;
res = run_target(fsrv, argv, tmp_buf, in_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
if (res) { if (res) {
@ -411,7 +410,7 @@ next_del_blksize:
/* Tail */ /* Tail */
memcpy(tmp_buf + del_pos, in_data + del_pos + del_len, tail_len); memcpy(tmp_buf + del_pos, in_data + del_pos + del_len, tail_len);
res = run_target(fsrv, argv, tmp_buf, del_pos + tail_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, del_pos + tail_len, 0);
if (res) { if (res) {
@ -474,7 +473,7 @@ next_del_blksize:
for (r = 0; r < in_len; r++) for (r = 0; r < in_len; r++)
if (tmp_buf[r] == i) tmp_buf[r] = '0'; if (tmp_buf[r] == i) tmp_buf[r] = '0';
res = run_target(fsrv, argv, tmp_buf, in_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
if (res) { if (res) {
@ -510,7 +509,7 @@ next_del_blksize:
if (orig == '0') continue; if (orig == '0') continue;
tmp_buf[i] = '0'; tmp_buf[i] = '0';
res = run_target(fsrv, argv, tmp_buf, in_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
if (res) { if (res) {
@ -742,7 +741,9 @@ static void usage(u8 *argv0) {
" (must contain abort_on_error=1 and symbolize=0)\n" " (must contain abort_on_error=1 and symbolize=0)\n"
"MSAN_OPTIONS: custom settings for MSAN\n" "MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n" "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
@ -751,76 +752,6 @@ static void usage(u8 *argv0) {
} }
/* Find binary. */
static void find_binary(afl_forkserver_t *fsrv, u8 *fname) {
u8 * env_path = 0;
struct stat st;
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
fsrv->target_path = ck_strdup(fname);
if (stat(fsrv->target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4)
FATAL("Program '%s' not found or not executable", fname);
} else {
while (env_path) {
u8 *cur_elem, *delim = strchr(env_path, ':');
if (delim) {
cur_elem = ck_alloc(delim - env_path + 1);
memcpy(cur_elem, env_path, delim - env_path);
delim++;
} else
cur_elem = ck_strdup(env_path);
env_path = delim;
if (cur_elem[0])
fsrv->target_path = alloc_printf("%s/%s", cur_elem, fname);
else
fsrv->target_path = ck_strdup(fname);
ck_free(cur_elem);
if (!stat(fsrv->target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4)
break;
ck_free(fsrv->target_path);
fsrv->target_path = NULL;
}
if (!fsrv->target_path)
FATAL("Program '%s' not found or not executable", fname);
}
}
/* Read mask bitmap from file. This is for the -B option. */
static void read_bitmap(u8 *fname) {
s32 fd = open(fname, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fname);
ck_read(fd, mask_bitmap, MAP_SIZE, fname);
close(fd);
}
/* Main entry point */ /* Main entry point */
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
@ -834,6 +765,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl_forkserver_t fsrv_var = {0}; afl_forkserver_t fsrv_var = {0};
afl_forkserver_t *fsrv = &fsrv_var; afl_forkserver_t *fsrv = &fsrv_var;
afl_fsrv_init(fsrv); afl_fsrv_init(fsrv);
map_size = get_map_size();
fsrv->map_size = map_size;
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
@ -883,6 +816,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) FATAL("Multiple -m options not supported");
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m");
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
fsrv->mem_limit = 0; fsrv->mem_limit = 0;
@ -919,6 +854,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) FATAL("Multiple -t options not supported");
timeout_given = 1; timeout_given = 1;
if (!optarg) FATAL("Wrong usage of -t");
fsrv->exec_tmout = atoi(optarg); fsrv->exec_tmout = atoi(optarg);
if (fsrv->exec_tmout < 10 || optarg[0] == '-') if (fsrv->exec_tmout < 10 || optarg[0] == '-')
@ -978,8 +915,8 @@ int main(int argc, char **argv_orig, char **envp) {
to be useful. */ to be useful. */
if (mask_bitmap) FATAL("Multiple -B options not supported"); if (mask_bitmap) FATAL("Multiple -B options not supported");
mask_bitmap = ck_alloc(MAP_SIZE); mask_bitmap = ck_alloc(map_size);
read_bitmap(optarg); read_bitmap(optarg, mask_bitmap, map_size);
break; break;
case 'h': case 'h':
@ -996,14 +933,14 @@ int main(int argc, char **argv_orig, char **envp) {
check_environment_vars(envp); check_environment_vars(envp);
sharedmem_t shm = {0}; sharedmem_t shm = {0};
fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
atexit(at_exit_handler); atexit(at_exit_handler);
setup_signal_handlers(); setup_signal_handlers();
set_up_environment(fsrv); set_up_environment(fsrv);
find_binary(fsrv, argv[optind]); fsrv->target_path = find_binary(argv[optind]);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin); detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
@ -1038,7 +975,7 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : "");
run_target(fsrv, use_argv, in_data, in_len, 1); tmin_run_target(fsrv, use_argv, in_data, in_len, 1);
if (hang_mode && !fsrv->last_run_timed_out) if (hang_mode && !fsrv->last_run_timed_out)
FATAL( FATAL(

View File

@ -1841,6 +1841,8 @@ static const unsigned char heap[] = {2,3,4,105,111,116,97,2,3,7,112,97,116,116,1
#include <stdio.h> #include <stdio.h>
#include <netdb.h> #include <netdb.h>
#include "./radamsa.h"
#ifndef EMULTIHOP #ifndef EMULTIHOP
#define EMULTIHOP -1 #define EMULTIHOP -1
#endif #endif
@ -2155,17 +2157,17 @@ static word *gc(int size, word *regs) {
/*** OS Interaction and Helpers ***/ /*** OS Interaction and Helpers ***/
static void signal_handler(int signal) { //static void signal_handler(int signal) {
switch (signal) { // switch (signal) {
case SIGINT: // case SIGINT:
breaked |= 2; // breaked |= 2;
break; // break;
case SIGPIPE: // case SIGPIPE:
break; /* can cause loop when reporting errors */ // break; /* can cause loop when reporting errors */
default: // default:
breaked |= 4; // breaked |= 4;
} // }
} //}
/* list length, no overflow or valid termination checks */ /* list length, no overflow or valid termination checks */
static uint llen(word *ptr) { static uint llen(word *ptr) {
@ -2176,7 +2178,7 @@ static uint llen(word *ptr) {
} }
return len; return len;
} }
/*
static void set_signal_handler(void) { static void set_signal_handler(void) {
struct sigaction sa; struct sigaction sa;
sa.sa_handler = signal_handler; sa.sa_handler = signal_handler;
@ -2185,7 +2187,7 @@ static void set_signal_handler(void) {
sigaction(SIGINT, &sa, NULL); sigaction(SIGINT, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL); sigaction(SIGPIPE, &sa, NULL);
} }
*/
static word mkpair(word h, word a, word d) { static word mkpair(word h, word a, word d) {
word *pair; word *pair;
allocate(3, pair); allocate(3, pair);
@ -30683,7 +30685,7 @@ static void heap_metrics(int *rwords, int *rnobjs) {
get_obj_metrics(rwords, rnobjs); get_obj_metrics(rwords, rnobjs);
hp = hp_start; hp = hp_start;
} }
/*
static void read_heap(const char *path) { static void read_heap(const char *path) {
struct stat st; struct stat st;
off_t pos = 0; off_t pos = 0;
@ -30703,25 +30705,26 @@ static void read_heap(const char *path) {
} while (n && (pos += n) < st.st_size); } while (n && (pos += n) < st.st_size);
close(fd); close(fd);
} }
*/
/* find a fasl image source to *hp or exit */ /* find a fasl image source to *hp or exit */
static void find_heap(int *nargs, char ***argv, int *nobjs, int *nwords) { //static void find_heap(int *nargs, char ***argv, int *nobjs, int *nwords) {
file_heap = NULL; // file_heap = NULL;
if ((word)heap == 0) { // if ((word)heap == 0) {
/* if no preloaded heap, try to load it from first vm arg */ /* if no preloaded heap, try to load it from first vm arg */
if (*nargs < 2) // if (*nargs < 2)
exit(1); // exit(1);
read_heap(argv[0][1]); // read_heap(argv[0][1]);
++*argv; // ++*argv;
--*nargs; // --*nargs;
hp = file_heap; // hp = file_heap;
if (*hp == '#') // if (*hp == '#')
while (*hp++ != '\n'); // while (*hp++ != '\n');
} else { // } else {
hp = heap; /* builtin heap */ // hp = heap; /* builtin heap */
} // }
heap_metrics(nwords, nobjs); // heap_metrics(nwords, nobjs);
} //}
static word *decode_fasl(uint nobjs) { static word *decode_fasl(uint nobjs) {
word *ptrs; word *ptrs;
@ -30744,7 +30747,7 @@ static word *load_heap(uint nobjs) {
free(file_heap); free(file_heap);
return entry; return entry;
} }
/*
static void setup(int nwords, int nobjs) { static void setup(int nwords, int nobjs) {
tcgetattr(0, &tsettings); tcgetattr(0, &tsettings);
state = IFALSE; state = IFALSE;
@ -30757,7 +30760,7 @@ static void setup(int nwords, int nobjs) {
memend = memstart + nwords - MEMPAD; memend = memstart + nwords - MEMPAD;
} }
int secondary(int nargs, char **argv) { static int secondary(int nargs, char **argv) {
word *prog; word *prog;
int rval, nobjs=0, nwords=0; int rval, nobjs=0, nwords=0;
find_heap(&nargs, &argv, &nobjs, &nwords); find_heap(&nargs, &argv, &nobjs, &nwords);
@ -30772,6 +30775,7 @@ int secondary(int nargs, char **argv) {
} }
return 127; return 127;
} }
*/
void radamsa_init(void) { void radamsa_init(void) {
int nobjs=0, nwords=0; int nobjs=0, nwords=0;
@ -30787,7 +30791,7 @@ void radamsa_init(void) {
} }
/* bvec → value library call test with preserved state */ /* bvec → value library call test with preserved state */
word library_call(word val) { static word library_call(word val) {
word program_state = state; word program_state = state;
word res; word res;
state = IFALSE; state = IFALSE;
@ -30798,7 +30802,8 @@ word library_call(word val) {
return res; return res;
} }
size_t list_length(word lispval) { /*
static size_t list_length(word lispval) {
size_t l = 0; size_t l = 0;
while(lispval != INULL) { while(lispval != INULL) {
lispval = G(lispval, 2); lispval = G(lispval, 2);
@ -30806,8 +30811,9 @@ size_t list_length(word lispval) {
} }
return l; return l;
} }
*/
size_t copy_list(uint8_t *ptr, word lispval, size_t max) { static size_t copy_list(uint8_t *ptr, word lispval, size_t max) {
size_t n = 0; size_t n = 0;
while(pairp((word)lispval) && max-- && lispval != INULL) { while(pairp((word)lispval) && max-- && lispval != INULL) {
*ptr++ = 255 & immval(G(lispval, 1)); // *ptr++ = car(list) *ptr++ = 255 & immval(G(lispval, 1)); // *ptr++ = car(list)

View File

@ -1,13 +1,13 @@
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
extern void radamsa_init(void); void radamsa_init(void);
extern size_t radamsa(uint8_t *ptr, size_t len, size_t radamsa(uint8_t *ptr, size_t len,
uint8_t *target, size_t max, uint8_t *target, size_t max,
unsigned int seed); unsigned int seed);
extern size_t radamsa_inplace(uint8_t *ptr, size_t radamsa_inplace(uint8_t *ptr,
size_t len, size_t len,
size_t max, size_t max,
unsigned int seed); unsigned int seed);

View File

@ -671,7 +671,7 @@ test -e ../afl-qemu-trace && {
test -e test-instr -a -e test-compcov && { test -e test-instr -a -e test-compcov && {
{ {
mkdir -p in mkdir -p in
echo 0 > in/in echo 00000 > in/in
$ECHO "$GREY[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds" $ECHO "$GREY[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds"
{ {
../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1 ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr >>errors 2>&1

View File

@ -27,6 +27,7 @@ extern void mock_assert(const int result, const char* const expression,
(compile with `--wrap=exit`) */ (compile with `--wrap=exit`) */
extern void exit(int status); extern void exit(int status);
extern void __real_exit(int status); extern void __real_exit(int status);
void __wrap_exit(int status);
void __wrap_exit(int status) { void __wrap_exit(int status) {
assert(0); assert(0);
} }
@ -34,6 +35,7 @@ void __wrap_exit(int status) {
/* ignore all printfs */ /* ignore all printfs */
extern int printf(const char *format, ...); extern int printf(const char *format, ...);
extern int __real_printf(const char *format, ...); extern int __real_printf(const char *format, ...);
int __wrap_printf(const char *format, ...);
int __wrap_printf(const char *format, ...) { int __wrap_printf(const char *format, ...) {
return 1; return 1;
} }

View File

@ -22,6 +22,7 @@ extern void mock_assert(const int result, const char* const expression,
mock_assert((int)(expression), #expression, __FILE__, __LINE__); mock_assert((int)(expression), #expression, __FILE__, __LINE__);
#include "alloc-inl.h" #include "alloc-inl.h"
void __wrap_exit(int status);
/* remap exit -> assert, then use cmocka's mock_assert /* remap exit -> assert, then use cmocka's mock_assert
(compile with `--wrap=exit`) */ (compile with `--wrap=exit`) */
extern void exit(int status); extern void exit(int status);
@ -30,6 +31,7 @@ void __wrap_exit(int status) {
assert(0); assert(0);
} }
int __wrap_printf(const char *format, ...);
/* ignore all printfs */ /* ignore all printfs */
extern int printf(const char *format, ...); extern int printf(const char *format, ...);
extern int __real_printf(const char *format, ...); extern int __real_printf(const char *format, ...);

View File

@ -27,6 +27,7 @@ extern void mock_assert(const int result, const char* const expression,
(compile with `--wrap=exit`) */ (compile with `--wrap=exit`) */
extern void exit(int status); extern void exit(int status);
extern void __real_exit(int status); extern void __real_exit(int status);
void __wrap_exit(int status);
void __wrap_exit(int status) { void __wrap_exit(int status) {
assert(0); assert(0);
} }
@ -34,6 +35,7 @@ void __wrap_exit(int status) {
/* ignore all printfs */ /* ignore all printfs */
extern int printf(const char *format, ...); extern int printf(const char *format, ...);
extern int __real_printf(const char *format, ...); extern int __real_printf(const char *format, ...);
int __wrap_printf(const char *format, ...);
int __wrap_printf(const char *format, ...) { int __wrap_printf(const char *format, ...) {
return 1; return 1;
} }