From 903b5607bc0eea01aa9872a2a53221a953c7a559 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Wed, 16 Nov 2022 18:19:50 +0300 Subject: [PATCH 001/300] Fix argv-fuzz. --- utils/argv_fuzzing/argv-fuzz-inl.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index c15c0271..68a0c93d 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -34,6 +34,7 @@ #ifndef _HAVE_ARGV_FUZZ_INL #define _HAVE_ARGV_FUZZ_INL +#include #include #define AFL_INIT_ARGV() \ @@ -63,22 +64,22 @@ static char **afl_init_argv(int *argc) { char *ptr = in_buf; int rc = 0; - if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {} + ssize_t num = 0; + if ((num = read(0, in_buf, MAX_CMDLINE_LEN - 2)) < 0) {} + if (in_buf[num - 1] == '\n') { + in_buf[num - 1] = 0; + } - while (*ptr && rc < MAX_CMDLINE_PAR) { - - ret[rc] = ptr; + char delim = ' '; + char *curarg = strtok(ptr, &delim); + while (curarg && rc < MAX_CMDLINE_PAR) { + ret[rc] = curarg; if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; rc++; - - while (*ptr) - ptr++; - ptr++; - + curarg = strtok(NULL, &delim); } *argc = rc; - return ret; } @@ -87,4 +88,3 @@ static char **afl_init_argv(int *argc) { #undef MAX_CMDLINE_PAR #endif /* !_HAVE_ARGV_FUZZ_INL */ - From 4b7126c46c6171998af8a899dd6c1d3a6f50eb0f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Nov 2022 10:58:20 +0100 Subject: [PATCH 002/300] nits --- GNUmakefile | 3 +-- GNUmakefile.gcc_plugin | 4 ++-- GNUmakefile.llvm | 4 ++-- TODO.md | 3 ++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index c8f7f35a..56013660 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -91,9 +91,8 @@ ifneq "$(SYS)" "Darwin" #ifeq "$(HAVE_MARCHNATIVE)" "1" # SPECIAL_PERFORMANCE += -march=native #endif - # OS X does not like _FORTIFY_SOURCE=2 ifndef DEBUG - CFLAGS_OPT += -D_FORTIFY_SOURCE=2 + CFLAGS_OPT += -D_FORTIFY_SOURCE=1 endif else # On some odd MacOS system configurations, the Xcode sdk path is not set correctly diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index 17bd825d..28a1a828 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -28,14 +28,14 @@ MAN_PATH ?= $(PREFIX)/share/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2) -CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2 +CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=1 CFLAGS_SAFE := -Wall -Iinclude -Wno-pointer-sign \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \ -Wno-unused-function override CFLAGS += $(CFLAGS_SAFE) -CXXFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2 +CXXFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=1 CXXEFLAGS := $(CXXFLAGS) -Wall -std=c++11 CC ?= gcc diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 7e090f69..bcbb6d38 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -254,7 +254,7 @@ else AFL_CLANG_DEBUG_PREFIX = endif -CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2 +CFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=1 CFLAGS_SAFE := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sign \ -I ./include/ -I ./instrumentation/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ @@ -274,7 +274,7 @@ ifdef AFL_TRACE_PC $(info Compile option AFL_TRACE_PC is deprecated, just set AFL_LLVM_INSTRUMENT=PCGUARD to activate when compiling targets ) endif -CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=2 +CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=1 override CXXFLAGS += -Wall -g -I ./include/ \ -DVERSION=\"$(VERSION)\" -Wno-variadic-macros \ -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR) diff --git a/TODO.md b/TODO.md index 99d2c419..a6b52ddf 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,8 @@ ## Should - - better documentation for custom mutators + - support afl_custom_{send,post_process}, persistent and deferred fork + server in afl-showmap - better autodetection of shifting runtime timeout values - Update afl->pending_not_fuzzed for MOpt - afl-plot to support multiple plot_data From 3d07f0ab791565feb904f5897b22ef924fc06a48 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Thu, 17 Nov 2022 14:14:11 +0300 Subject: [PATCH 003/300] Handle empty input. --- utils/argv_fuzzing/argv-fuzz-inl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index 68a0c93d..2ec433e1 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -65,7 +65,10 @@ static char **afl_init_argv(int *argc) { int rc = 0; ssize_t num = 0; - if ((num = read(0, in_buf, MAX_CMDLINE_LEN - 2)) < 0) {} + if ((num = read(0, in_buf, MAX_CMDLINE_LEN - 2)) <= 0) { + *argc = 0; + return ret; + } if (in_buf[num - 1] == '\n') { in_buf[num - 1] = 0; } From 8f9726d4a901880808d46706cdb9024c5d08bb7e Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Thu, 17 Nov 2022 17:27:13 +0300 Subject: [PATCH 004/300] Fix delim. --- utils/argv_fuzzing/argv-fuzz-inl.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index 2ec433e1..94d4c123 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -73,13 +73,12 @@ static char **afl_init_argv(int *argc) { in_buf[num - 1] = 0; } - char delim = ' '; - char *curarg = strtok(ptr, &delim); + char *curarg = strtok(ptr, " "); while (curarg && rc < MAX_CMDLINE_PAR) { ret[rc] = curarg; if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; rc++; - curarg = strtok(NULL, &delim); + curarg = strtok(NULL, " "); } *argc = rc; From ba788591dc50ba01088a9e0ed76ae29878eedbdd Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Thu, 17 Nov 2022 17:38:45 +0300 Subject: [PATCH 005/300] Handle read() error. --- utils/argv_fuzzing/argv-fuzz-inl.h | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index 94d4c123..917c6222 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -34,7 +34,7 @@ #ifndef _HAVE_ARGV_FUZZ_INL #define _HAVE_ARGV_FUZZ_INL -#include +#include #include #define AFL_INIT_ARGV() \ @@ -64,24 +64,27 @@ static char **afl_init_argv(int *argc) { char *ptr = in_buf; int rc = 0; - ssize_t num = 0; - if ((num = read(0, in_buf, MAX_CMDLINE_LEN - 2)) <= 0) { - *argc = 0; - return ret; - } - if (in_buf[num - 1] == '\n') { - in_buf[num - 1] = 0; + ssize_t num = read(0, in_buf, MAX_CMDLINE_LEN - 2); + if (num < 0) { + abort(); } + in_buf[num] = '\0'; + in_buf[num + 1] = '\0'; - char *curarg = strtok(ptr, " "); - while (curarg && rc < MAX_CMDLINE_PAR) { - ret[rc] = curarg; + while (*ptr && rc < MAX_CMDLINE_PAR) { + + ret[rc] = ptr; if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; rc++; - curarg = strtok(NULL, " "); + + while (*ptr) + ptr++; + ptr++; + } *argc = rc; + return ret; } @@ -90,3 +93,4 @@ static char **afl_init_argv(int *argc) { #undef MAX_CMDLINE_PAR #endif /* !_HAVE_ARGV_FUZZ_INL */ + From ad6a4cf1c2b7089179c77544b9749e72a2dd6d0f Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Nov 2022 08:11:26 +0000 Subject: [PATCH 006/300] Fix cmplog block ID generation to use hashes rather than bit-shifts --- frida_mode/src/cmplog/cmplog_arm64.c | 5 +---- frida_mode/src/cmplog/cmplog_x64.c | 5 +---- frida_mode/src/cmplog/cmplog_x86.c | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/frida_mode/src/cmplog/cmplog_arm64.c b/frida_mode/src/cmplog/cmplog_arm64.c index 5792cbfa..095dc242 100644 --- a/frida_mode/src/cmplog/cmplog_arm64.c +++ b/frida_mode/src/cmplog/cmplog_arm64.c @@ -204,10 +204,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = context->pc; - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 1; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c index 17912648..ce6b8681 100644 --- a/frida_mode/src/cmplog/cmplog_x64.c +++ b/frida_mode/src/cmplog/cmplog_x64.c @@ -188,10 +188,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = ctx_read_reg(context, X86_REG_RIP); - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 7; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c index a3a02457..fa06d611 100644 --- a/frida_mode/src/cmplog/cmplog_x86.c +++ b/frida_mode/src/cmplog/cmplog_x86.c @@ -193,10 +193,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = ctx_read_reg(context, X86_REG_EIP); - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 1; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; From d7e788a3c0138637147621cc4d6ab8087e0af956 Mon Sep 17 00:00:00 2001 From: kobrineli Date: Fri, 18 Nov 2022 13:35:51 +0300 Subject: [PATCH 007/300] Exit on read error. --- utils/argv_fuzzing/argv-fuzz-inl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index 917c6222..e350dd4e 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -66,7 +66,7 @@ static char **afl_init_argv(int *argc) { ssize_t num = read(0, in_buf, MAX_CMDLINE_LEN - 2); if (num < 0) { - abort(); + exit(1); } in_buf[num] = '\0'; in_buf[num + 1] = '\0'; From 26a5bd625ccbd8de4fbc9b5eea263d092bd405e5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 18 Nov 2022 12:23:18 +0100 Subject: [PATCH 008/300] write queue statistics --- docs/Changelog.md | 3 +++ include/afl-fuzz.h | 14 ++++++++++--- include/config.h | 3 ++- src/afl-fuzz-init.c | 4 ++++ src/afl-fuzz-one.c | 37 ++++++++++++++++++++++++++++++++ src/afl-fuzz-stats.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz.c | 44 +++++++++++++++++++++++++++++++++----- 7 files changed, 146 insertions(+), 9 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index c5eb6be3..4df47645 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,9 @@ send fuzz data to the target as you need, e.g. via IPC. - cmplog mode now has -l R option for random colorization, thanks to guyf2010 for the PR! + - queue statistics are written every 30 minutes to + out/NAME/queue_data - likely this will be moved to a debug flag + in the future. - afl-showmap/afl-cmin - -t none now translates to -t 120000 (120 seconds) - unicorn_mode updated diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 88646db3..f9dcbf8f 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -169,12 +169,18 @@ struct queue_entry { u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level, /* Number of fuzzing iterations */ - n_fuzz_entry; /* offset in n_fuzz */ + n_fuzz_entry, /* offset in n_fuzz */ + stats_selected, /* stats: how often selected */ + stats_skipped, /* stats: how often skipped */ + stats_finds, /* stats: # of saved finds */ + stats_crashes, /* stats: # of saved crashes */ + stats_tmouts; /* stats: # of saved timeouts */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ depth, /* Path depth */ - exec_cksum; /* Checksum of the execution trace */ + exec_cksum, /* Checksum of the execution trace */ + stats_mutated; /* stats: # of mutations performed */ u8 *trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ @@ -686,7 +692,8 @@ typedef struct afl_state { u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md; u64 plot_prev_qc, plot_prev_uc, plot_prev_uh, plot_prev_ed; - 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_queue_ms, + stats_last_ms, stats_last_execs; /* StatsD */ u64 statsd_last_send_ms; @@ -1101,6 +1108,7 @@ void load_stats_file(afl_state_t *); void write_setup_file(afl_state_t *, u32, char **); void write_stats_file(afl_state_t *, u32, double, double, double); void maybe_update_plot_file(afl_state_t *, u32, double, double); +void write_queue_stats(afl_state_t *); void show_stats(afl_state_t *); void show_stats_normal(afl_state_t *); void show_stats_pizza(afl_state_t *); diff --git a/include/config.h b/include/config.h index 22c1a162..b82ead47 100644 --- a/include/config.h +++ b/include/config.h @@ -290,10 +290,11 @@ #define UI_TARGET_HZ 5 -/* Fuzzer stats file and plot update intervals (sec): */ +/* Fuzzer stats file, queue stats and plot update intervals (sec): */ #define STATS_UPDATE_SEC 60 #define PLOT_UPDATE_SEC 5 +#define QUEUE_UPDATE_SEC 1800 /* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index e41d29fd..ed52ca00 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1848,6 +1848,10 @@ static void handle_existing_out_dir(afl_state_t *afl) { } + fn = alloc_printf("%s/queue_data", afl->out_dir); + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } + ck_free(fn); + fn = alloc_printf("%s/cmdline", afl->out_dir); if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ed9e7a81..253e78b6 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -743,6 +743,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP1] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Two walking bits. */ @@ -775,6 +776,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP2] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Four walking bits. */ @@ -811,6 +813,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP4] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Effector map setup. These macros calculate: @@ -919,6 +922,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Two walking bytes. */ @@ -962,6 +966,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; if (len < 4) { goto skip_bitflip; } @@ -1005,6 +1010,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_bitflip: @@ -1097,6 +1103,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* 16-bit arithmetics, both endians. */ @@ -1227,6 +1234,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* 32-bit arithmetics, both endians. */ @@ -1356,6 +1364,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_arith: @@ -1422,6 +1431,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Setting 16-bit integers, both endians. */ @@ -1510,6 +1520,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; if (len < 4) { goto skip_interest; } @@ -1599,6 +1610,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_interest: @@ -1672,6 +1684,7 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Insertion of user-supplied extras. */ @@ -1728,6 +1741,7 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_user_extras: @@ -1786,6 +1800,7 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Insertion of auto extras. */ @@ -1842,6 +1857,7 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_extras: @@ -1988,6 +2004,7 @@ custom_mutator_stage: afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; if (likely(afl->custom_only)) { @@ -2925,11 +2942,13 @@ havoc_stage: afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_HAVOC] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; } else { afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_SPLICE] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; } @@ -3411,6 +3430,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP1] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Two walking bits. */ @@ -3442,6 +3462,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP2] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Four walking bits. */ @@ -3477,6 +3498,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP4] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Effector map setup. These macros calculate: @@ -3584,6 +3606,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Two walking bytes. */ @@ -3626,6 +3649,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; if (len < 4) { goto skip_bitflip; } @@ -3668,6 +3692,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_bitflip: @@ -3758,6 +3783,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* 16-bit arithmetics, both endians. */ @@ -3884,6 +3910,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* 32-bit arithmetics, both endians. */ @@ -4009,6 +4036,7 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_arith: @@ -4074,6 +4102,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Setting 16-bit integers, both endians. */ @@ -4160,6 +4189,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; if (len < 4) { goto skip_interest; } @@ -4247,6 +4277,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_interest: @@ -4320,6 +4351,7 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Insertion of user-supplied extras. */ @@ -4376,6 +4408,7 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_user_extras: @@ -4435,6 +4468,7 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; /* Insertion of auto extras. */ @@ -4491,6 +4525,7 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; skip_extras: @@ -5316,11 +5351,13 @@ pacemaker_fuzzing: afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_HAVOC] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; } else { afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_SPLICE] += afl->stage_max; + afl->queue_cur->stats_mutated += afl->stage_max; } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 61956dc3..ac9ad4db 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -365,6 +365,36 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } +void write_queue_stats(afl_state_t *afl) { + + FILE *f; + u8 *fn = alloc_printf("%s/queue_data", afl->out_dir); + if ((f = fopen(fn, "w")) != NULL) { + + u32 id; + fprintf(f, + "# filename, length, exec_us, selected, skipped, mutations, finds, " + "crashes, timeouts, bitmap_size, perf_score, weight, colorized, " + "favored, disabled\n"); + for (id = 0; id < afl->queued_items; ++id) { + + struct queue_entry *q = afl->queue_buf[id]; + fprintf(f, "\"%s\",%u,%llu,%u,%u,%llu,%u,%u,%u,%u,%.3f,%.3f,%u,%u,%u\n", + q->fname, q->len, q->exec_us, q->stats_selected, q->stats_skipped, + q->stats_mutated, q->stats_finds, q->stats_crashes, + q->stats_tmouts, q->bitmap_size, q->perf_score, q->weight, + q->colorized, q->favored, q->disabled); + + } + + fclose(f); + + } + + ck_free(fn); + +} + /* Update the plot file if there is a reason to. */ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, @@ -613,6 +643,16 @@ void show_stats_normal(afl_state_t *afl) { } + /* Every now and then, write queue data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { + + afl->stats_last_queue_ms = cur_ms; + write_queue_stats(afl); + + } + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 && @@ -1399,6 +1439,16 @@ void show_stats_pizza(afl_state_t *afl) { } + /* Every now and then, write queue data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { + + afl->stats_last_queue_ms = cur_ms; + write_queue_stats(afl); + + } + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 && diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a81cab7d..7bb9ba2b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2278,7 +2278,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->start_time = get_cur_time(); u32 runs_in_current_cycle = (u32)-1; - u32 prev_queued_items = 0; + u32 prev_queued_items = 0, prev_saved_crashes = 0, prev_saved_tmouts = 0; u8 skipped_fuzz; #ifdef INTROSPECTION @@ -2529,21 +2529,55 @@ int main(int argc, char **argv_orig, char **envp) { } skipped_fuzz = fuzz_one(afl); + ++afl->queue_cur->stats_selected; + if (unlikely(skipped_fuzz)) { + + ++afl->queue_cur->stats_skipped; + + } else { + + if (unlikely(afl->queued_items > prev_queued_items)) { + + afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items; + prev_queued_items = afl->queued_items; + + } + + if (unlikely(afl->saved_crashes > prev_saved_crashes)) { + + afl->queue_cur->stats_crashes += + afl->saved_crashes - prev_saved_crashes; + prev_saved_crashes = afl->saved_crashes; + + } + + if (unlikely(afl->saved_tmouts > prev_saved_tmouts)) { + + afl->queue_cur->stats_tmouts += afl->saved_tmouts - prev_saved_tmouts; + prev_saved_tmouts = afl->saved_tmouts; + + } + + } if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; } if (unlikely(afl->old_seed_selection)) { while (++afl->current_entry < afl->queued_items && - afl->queue_buf[afl->current_entry]->disabled) - ; + afl->queue_buf[afl->current_entry]->disabled) {}; if (unlikely(afl->current_entry >= afl->queued_items || afl->queue_buf[afl->current_entry] == NULL || - afl->queue_buf[afl->current_entry]->disabled)) + afl->queue_buf[afl->current_entry]->disabled)) { + afl->queue_cur = NULL; - else + + } else { + afl->queue_cur = afl->queue_buf[afl->current_entry]; + } + } } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon); From b7c87350cf3481416b782fe19bc56467090ff220 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 18 Nov 2022 17:04:16 +0100 Subject: [PATCH 009/300] Make env description extra clear --- docs/env_variables.md | 8 ++++---- unicorn_mode/unicornafl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index d1c13e15..22a5c386 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -378,10 +378,10 @@ checks or alter some of the more exotic semantics of the tool: valid terminal was detected (for virtual consoles). - Setting `AFL_FORKSRV_INIT_TMOUT` allows you to specify a different timeout - to wait for the forkserver to spin up. The default is the `-t` value times - `FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the - default would wait for `1000` milliseconds. Setting a different time here is - useful if the target has a very slow startup time, for example, when doing + to wait for the forkserver to spin up. The specified value is the new timeout, in milliseconds. + The default is the `-t` value times `FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the default would wait for `1000` milliseconds. + The `AFL_FORKSRV_INIT_TMOUT` value does not get multiplied. It overwrites the initial timeout afl-fuzz waits for the target to come up with a constant time. + Setting a different time here is useful if the target has a very slow startup time, for example, when doing full-system fuzzing or emulation, but you don't want the actual runs to wait too long for timeouts. diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 6e00ceac..0a31c2b2 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 6e00ceac6fd5627e42e1858c543c84f2fbdaedda +Subproject commit 0a31c2b28bf7037fe8b0ff376521fdbdf28a9efe From ef0921d858be0d54f3ebfe88e361ba54fb9ba69d Mon Sep 17 00:00:00 2001 From: fedotoff Date: Mon, 21 Nov 2022 12:59:23 +0300 Subject: [PATCH 010/300] Add CASR as third party tool in docs. --- docs/third_party_tools.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/third_party_tools.md b/docs/third_party_tools.md index 1175d9e5..97f2c362 100644 --- a/docs/third_party_tools.md +++ b/docs/third_party_tools.md @@ -62,3 +62,5 @@ generates builds of debian packages suitable for AFL. * [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for working with input data. +* [CASR](https://github.com/ispras/casr) - a set of tools for crash triage and + analysis. From 2c39c51263fd38de50ef41ff30075c1282997e14 Mon Sep 17 00:00:00 2001 From: fedotoff Date: Mon, 21 Nov 2022 15:18:19 +0300 Subject: [PATCH 011/300] casr-afl short description in fuzzing_in_depth. --- docs/fuzzing_in_depth.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index a0bf1566..1645ba5c 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -900,6 +900,32 @@ then color-codes the input based on which sections appear to be critical and which are not; while not bulletproof, it can often offer quick insights into complex file formats. +`casr-afl` from [CASR](https://github.com/ispras/casr) tools provides a +straightforward CASR integration with AFL++. While walking through afl +instances, `casr-afl` generates crash reports depending on target binary. For +binary with ASAN `casr-san` is used, otherwise `casr-gdb`. On the next step +report deduplication is done by `casr-cluster`. Finally, reports are triaged +into clusters. Crash reports contain many useful information: severity +(like [exploitable](https://github.com/jfoote/exploitable)), OS and package +versions, command line, stack trace, register values, disassembly, and even +source code fragment where crash appeared. + +**NOTE:** `casr-gdb` and `casr-san` should be in PATH to make `casr-afl` work. +Before using casr-afl, please, follow the installation +[guide](https://github.com/ispras/casr#getting-started). Using `casr-afl` is +very simple: + +```shell +casr-afl -i /path/to/afl/out/dir -o /path/to/casr/out/dir +``` + +Output directory contains subdirectories (cl1...clN) with report clusters. To +view reports you could use `casr-cli` tool: + +```shell +casr-cli /path/to/casr/out/dir/cl1/report.casrep +``` + ## 5. CI fuzzing Some notes on continuous integration (CI) fuzzing - this fuzzing is different to From a16726039f167548da86ce51d0cf4bd1b04e5374 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 21 Nov 2022 13:28:07 +0100 Subject: [PATCH 012/300] shorten text --- docs/fuzzing_in_depth.md | 25 +++---------------------- unicorn_mode/unicornafl | 2 +- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 1645ba5c..87f31a58 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -900,32 +900,13 @@ then color-codes the input based on which sections appear to be critical and which are not; while not bulletproof, it can often offer quick insights into complex file formats. -`casr-afl` from [CASR](https://github.com/ispras/casr) tools provides a -straightforward CASR integration with AFL++. While walking through afl -instances, `casr-afl` generates crash reports depending on target binary. For -binary with ASAN `casr-san` is used, otherwise `casr-gdb`. On the next step -report deduplication is done by `casr-cluster`. Finally, reports are triaged -into clusters. Crash reports contain many useful information: severity -(like [exploitable](https://github.com/jfoote/exploitable)), OS and package -versions, command line, stack trace, register values, disassembly, and even -source code fragment where crash appeared. - -**NOTE:** `casr-gdb` and `casr-san` should be in PATH to make `casr-afl` work. -Before using casr-afl, please, follow the installation -[guide](https://github.com/ispras/casr#getting-started). Using `casr-afl` is -very simple: - +`casr-afl` from [CASR](https://github.com/ispras/casr) tools provides +comfortable triaging for crashes found by AFL++. Reports are clustered and +contain severity and other information. ```shell casr-afl -i /path/to/afl/out/dir -o /path/to/casr/out/dir ``` -Output directory contains subdirectories (cl1...clN) with report clusters. To -view reports you could use `casr-cli` tool: - -```shell -casr-cli /path/to/casr/out/dir/cl1/report.casrep -``` - ## 5. CI fuzzing Some notes on continuous integration (CI) fuzzing - this fuzzing is different to diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 0a31c2b2..6e00ceac 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 0a31c2b28bf7037fe8b0ff376521fdbdf28a9efe +Subproject commit 6e00ceac6fd5627e42e1858c543c84f2fbdaedda From 4124a272d821629adce648fb37ca1e7f0ce0e84f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Nov 2022 10:27:30 +0100 Subject: [PATCH 013/300] crash fix for queue analysis feature --- src/afl-fuzz.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7bb9ba2b..976d61e5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2523,7 +2523,12 @@ int main(int argc, char **argv_orig, char **envp) { } - afl->current_entry = select_next_queue_entry(afl); + do { + + afl->current_entry = select_next_queue_entry(afl); + + } while (unlikely(afl->current_entry >= afl->queued_items)); + afl->queue_cur = afl->queue_buf[afl->current_entry]; } From 9734d0b3c09b3d604941d43fd96454100349d8b1 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 23 Nov 2022 18:18:26 +0000 Subject: [PATCH 014/300] Fixes to make things easier to build for ARM --- frida_mode/GNUmakefile | 3 +++ frida_mode/src/instrument/instrument_arm32.c | 10 +++++++++- frida_mode/test/png/GNUmakefile | 14 +++++++------- frida_mode/test/testinstr/GNUmakefile | 3 +++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 9f2bcd42..ccc4841d 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -191,6 +191,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all +arm: + CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all + $(BUILD_DIR): mkdir -p $(BUILD_DIR) diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index cb2a322b..84dbb3be 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -273,7 +273,15 @@ void instrument_flush(GumStalkerOutput *output) { gpointer instrument_cur(GumStalkerOutput *output) { - return gum_arm_writer_cur(output->writer.arm); + gpointer curr = NULL; + + if (output->encoding == GUM_INSTRUCTION_SPECIAL) { + curr = gum_thumb_writer_cur(output->writer.thumb); + } else { + curr = gum_arm_writer_cur(output->writer.arm); + } + + return curr; } diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index 864265e0..86fd1483 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -7,10 +7,10 @@ LIBPNG_BUILD_DIR:=$(BUILD_DIR)libpng/ HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/ PNGTEST_BUILD_DIR:=$(BUILD_DIR)pngtest/ -LIBZ_FILE:=$(LIBZ_BUILD_DIR)zlib-1.2.12.tar.gz -LIBZ_URL:=http://www.zlib.net/zlib-1.2.12.tar.gz -LIBZ_DIR:=$(LIBZ_BUILD_DIR)zlib-1.2.12/ -LIBZ_PC:=$(ZLIB_DIR)zlib.pc +LIBZ_FILE:=$(LIBZ_BUILD_DIR)zlib-1.2.13.tar.gz +LIBZ_URL:=http://www.zlib.net/zlib-1.2.13.tar.gz +LIBZ_DIR:=$(LIBZ_BUILD_DIR)zlib-1.2.13/ +LIBZ_PC:=$(LIBZ_DIR)zlib.pc LIBZ_LIB:=$(LIBZ_DIR)libz.a LIBPNG_FILE:=$(LIBPNG_BUILD_DIR)libpng-1.2.56.tar.gz @@ -48,7 +48,7 @@ all: $(TEST_BIN) CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN) arm: - ARCH="arm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN) + CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN) $(BUILD_DIR): mkdir -p $@ @@ -96,7 +96,7 @@ $(LIBZ_PC): | $(LIBZ_DIR) --static \ --archs="$(ARCH)" -$(LIBZ_LIB): $(LIBZ_PC) +$(LIBZ_LIB): | $(LIBZ_PC) CFLAGS="$(CFLAGS) -fPIC" \ make \ -C $(LIBZ_DIR) \ @@ -133,7 +133,7 @@ png: $(LIBPNG_LIB) ######### TEST ######## -$(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) +$(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) $(LIBZ_LIB) $(CXX) \ $(CFLAGS) \ $(LDFLAGS) \ diff --git a/frida_mode/test/testinstr/GNUmakefile b/frida_mode/test/testinstr/GNUmakefile index 79eee213..ebc0b2dc 100644 --- a/frida_mode/test/testinstr/GNUmakefile +++ b/frida_mode/test/testinstr/GNUmakefile @@ -18,6 +18,9 @@ all: $(TESTINSTBIN) 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all +arm: + CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TESTINSTBIN) + $(BUILD_DIR): mkdir -p $@ From 32a331ab43095c2493514a9066c30ae7665433e4 Mon Sep 17 00:00:00 2001 From: a-shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Sat, 26 Nov 2022 10:34:14 +0300 Subject: [PATCH 015/300] Update README.md --- utils/libtokencap/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md index 50104291..8705452c 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -47,9 +47,11 @@ by AFL++ in that earlier run. This demonstrates the basic principle: ``` export AFL_TOKEN_FILE=$PWD/temp_output.txt + timeout_sec="5" for i in /queue/id*; do LD_PRELOAD=/path/to/libtokencap.so \ + timeout -s SIGKILL ${timeout_sec} \ /path/to/target/program [...params, including $i...] done From 6dd9764cf6745a74772e93f3e91b83031a872766 Mon Sep 17 00:00:00 2001 From: Your Date: Thu, 1 Dec 2022 18:17:21 +0000 Subject: [PATCH 016/300] Bump FRIDA version --- frida_mode/GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index ccc4841d..d283c3d7 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -145,7 +145,7 @@ ifndef OS $(error "Operating system unsupported") endif -GUM_DEVKIT_VERSION=16.0.1 +GUM_DEVKIT_VERSION=16.0.6 GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)" From 0885dda767ec29330c57c88f3102d5ee565b645d Mon Sep 17 00:00:00 2001 From: Your Date: Thu, 1 Dec 2022 18:17:21 +0000 Subject: [PATCH 017/300] Fix branch suppression for ARM64 --- frida_mode/src/instrument/instrument_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index c7584a87..39e32b12 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -196,7 +196,7 @@ static void instrument_coverage_switch(GumStalkerObserver *self, insn = instrument_disassemble(from_insn); deterministic = instrument_is_deterministic(insn); cs_free(insn, 1); - if (deterministic) { return; } + if (!deterministic) { return; } /* * Since each block is prefixed with a restoration prologue, we need to be From 149366507da1ff8e3e8c4962f3abc6c8fd78b222 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 4 Dec 2022 04:09:12 +0100 Subject: [PATCH 018/300] update qemuafl --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 8d384d31..9c68f02c 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -fa07ebfff5 +a8af9cbde7 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index fa07ebff..a8af9cbd 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit fa07ebfff5de3d7a531caf2f9e0306960953a5e7 +Subproject commit a8af9cbde71e333ce72a46f15e655d0b82ed0939 From bf1617d3545b7c37b04ac8ddfdcf33943adf3bd2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 5 Dec 2022 16:15:29 +0100 Subject: [PATCH 019/300] fix warning --- TODO.md | 1 + src/afl-fuzz.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index a6b52ddf..862224f0 100644 --- a/TODO.md +++ b/TODO.md @@ -9,6 +9,7 @@ - afl-plot to support multiple plot_data - parallel builds for source-only targets - get rid of check_binary, replace with more forkserver communication + - first fuzzer should be a main automatically ## Maybe diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 976d61e5..172b9d7a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -501,7 +501,7 @@ int main(int argc, char **argv_orig, char **envp) { s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, + u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1, map_size = get_map_size(); u8 *extras_dir[4]; u8 mem_limit_given = 0, exit_1 = 0, debug = 0, @@ -802,6 +802,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->fsrv.out_file = ck_strdup(optarg); afl->fsrv.use_stdin = 0; + default_output = 0; break; case 'x': /* dictionary */ @@ -1911,6 +1912,7 @@ int main(int argc, char **argv_orig, char **envp) { if (aa_loc && !afl->fsrv.out_file) { afl->fsrv.use_stdin = 0; + default_output = 0; if (afl->file_extension) { @@ -2154,7 +2156,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->fsrv.out_file = NULL; afl->fsrv.use_stdin = 0; - if (!afl->unicorn_mode && !afl->fsrv.use_stdin) { + if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) { WARNF( "You specified -f or @@ on the command line but the target harness " @@ -2306,6 +2308,12 @@ int main(int argc, char **argv_orig, char **envp) { (!afl->queue_cycle && afl->afl_env.afl_import_first)) && afl->sync_id)) { + if (!afl->queue_cycle && afl->afl_env.afl_import_first) { + + OKF("Syncing queues from other fuzzer instances first ..."); + + } + sync_fuzzers(afl); } From e02753fd7db85a7f110927d7a8522df42408627f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 7 Dec 2022 19:48:20 +0000 Subject: [PATCH 020/300] Silent more deprecation warning for clang 15 and onwards --- GNUmakefile.llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index bcbb6d38..d6e45d29 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -276,7 +276,7 @@ endif CXXFLAGS ?= -O3 -funroll-loops -fPIC -D_FORTIFY_SOURCE=1 override CXXFLAGS += -Wall -g -I ./include/ \ - -DVERSION=\"$(VERSION)\" -Wno-variadic-macros \ + -DVERSION=\"$(VERSION)\" -Wno-variadic-macros -Wno-deprecated-copy-with-dtor \ -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR) ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" "" From 85b44bb73025b41d9b9a8b0aaf742f073621a98b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 12 Dec 2022 18:35:05 +0100 Subject: [PATCH 021/300] add cmplog envs --- include/envs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/envs.h b/include/envs.h index 68d83f8c..f4cdf390 100644 --- a/include/envs.h +++ b/include/envs.h @@ -124,7 +124,9 @@ static char *afl_environment_variables[] = { "AFL_LLVM_ALLOWLIST", "AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", + "AFL_CMPLOG", "AFL_LLVM_CMPLOG", + "AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX", From e26c173041b185d7ea37aa923cca3ec4aed51b1b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 13 Dec 2022 09:13:52 +0100 Subject: [PATCH 022/300] code format --- frida_mode/src/instrument/instrument_arm32.c | 4 ++++ utils/argv_fuzzing/argv-fuzz-inl.h | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 84dbb3be..51f78a35 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -276,9 +276,13 @@ gpointer instrument_cur(GumStalkerOutput *output) { gpointer curr = NULL; if (output->encoding == GUM_INSTRUCTION_SPECIAL) { + curr = gum_thumb_writer_cur(output->writer.thumb); + } else { + curr = gum_arm_writer_cur(output->writer.arm); + } return curr; diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index e350dd4e..ec22c53b 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -65,9 +65,7 @@ static char **afl_init_argv(int *argc) { int rc = 0; ssize_t num = read(0, in_buf, MAX_CMDLINE_LEN - 2); - if (num < 0) { - exit(1); - } + if (num < 1) { _exit(1); } in_buf[num] = '\0'; in_buf[num + 1] = '\0'; From e30c20cd28786a75ce195fb672bd7dd190690f01 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 16 Dec 2022 20:44:49 +0000 Subject: [PATCH 023/300] fix Solaris/Illumos build --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 56013660..6b55635f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -102,7 +102,7 @@ endif ifeq "$(SYS)" "SunOS" CFLAGS_OPT += -Wno-format-truncation - LDFLAGS = -lkstat -lrt + LDFLAGS = -lkstat -lrt -lsocket -lnsl endif ifdef STATIC From 96f05c7f6978fbc7648c0ae86b3827e0f9e6d467 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 20 Dec 2022 10:21:36 +0100 Subject: [PATCH 024/300] fix fork server timeout in afl-showmap --- src/afl-showmap.c | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 93339a8f..d85c28d9 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1233,6 +1233,36 @@ int main(int argc, char **argv_orig, char **envp) { } + if (getenv("AFL_FORKSRV_INIT_TMOUT")) { + + s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT")); + if (forksrv_init_tmout < 1) { + + FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT"); + + } + + fsrv->init_tmout = (u32)forksrv_init_tmout; + + } + + if (getenv("AFL_CRASH_EXITCODE")) { + + long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + getenv("AFL_CRASH_EXITCODE")); + + } + + fsrv->uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + fsrv->crash_exitcode = (u8)exitcode; + + } + if (in_dir) { (void)check_binary_signatures(fsrv->target_path); } shm_fuzz = ck_alloc(sizeof(sharedmem_t)); @@ -1365,36 +1395,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (getenv("AFL_FORKSRV_INIT_TMOUT")) { - - s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT")); - if (forksrv_init_tmout < 1) { - - FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT"); - - } - - fsrv->init_tmout = (u32)forksrv_init_tmout; - - } - - if (getenv("AFL_CRASH_EXITCODE")) { - - long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); - if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || - exitcode < -127 || exitcode > 128) { - - FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", - getenv("AFL_CRASH_EXITCODE")); - - } - - fsrv->uses_crash_exitcode = true; - // WEXITSTATUS is 8 bit unsigned - fsrv->crash_exitcode = (u8)exitcode; - - } - afl_fsrv_start(fsrv, use_argv, &stop_soon, (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) From 0165ca8c6c485e36fe8e5fc6182ebeba2100932b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 20 Dec 2022 13:36:56 +0100 Subject: [PATCH 025/300] hide queue introspection behind define --- include/afl-fuzz.h | 8 +++-- src/afl-fuzz-one.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-stats.c | 7 +++++ src/afl-fuzz.c | 9 ++++-- 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f9dcbf8f..ea83aaca 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -169,12 +169,16 @@ struct queue_entry { u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level, /* Number of fuzzing iterations */ - n_fuzz_entry, /* offset in n_fuzz */ + n_fuzz_entry /* offset in n_fuzz */ +#ifdef INTROSPECTION + , stats_selected, /* stats: how often selected */ stats_skipped, /* stats: how often skipped */ stats_finds, /* stats: # of saved finds */ stats_crashes, /* stats: # of saved crashes */ - stats_tmouts; /* stats: # of saved timeouts */ + stats_tmouts /* stats: # of saved timeouts */ +#endif + ; u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 253e78b6..9931820a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -743,7 +743,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP1] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Two walking bits. */ @@ -776,7 +778,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP2] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Four walking bits. */ @@ -813,7 +817,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP4] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Effector map setup. These macros calculate: @@ -922,7 +928,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Two walking bytes. */ @@ -966,7 +974,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif if (len < 4) { goto skip_bitflip; } @@ -1010,7 +1020,9 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_bitflip: @@ -1103,7 +1115,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* 16-bit arithmetics, both endians. */ @@ -1234,7 +1248,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* 32-bit arithmetics, both endians. */ @@ -1364,7 +1380,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_arith: @@ -1431,7 +1449,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Setting 16-bit integers, both endians. */ @@ -1520,7 +1540,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif if (len < 4) { goto skip_interest; } @@ -1610,7 +1632,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_interest: @@ -1684,7 +1708,9 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Insertion of user-supplied extras. */ @@ -1741,7 +1767,9 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_user_extras: @@ -1800,7 +1828,9 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Insertion of auto extras. */ @@ -1857,7 +1887,9 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_extras: @@ -2004,7 +2036,9 @@ custom_mutator_stage: afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif if (likely(afl->custom_only)) { @@ -2942,13 +2976,17 @@ havoc_stage: afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_HAVOC] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif } else { afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_SPLICE] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif } @@ -3430,7 +3468,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP1] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Two walking bits. */ @@ -3462,7 +3502,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP2] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Four walking bits. */ @@ -3498,7 +3540,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP4] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Effector map setup. These macros calculate: @@ -3606,7 +3650,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Two walking bytes. */ @@ -3649,7 +3695,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif if (len < 4) { goto skip_bitflip; } @@ -3692,7 +3740,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_bitflip: @@ -3783,7 +3833,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* 16-bit arithmetics, both endians. */ @@ -3910,7 +3962,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* 32-bit arithmetics, both endians. */ @@ -4036,7 +4090,9 @@ skip_bitflip: afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_ARITH32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_arith: @@ -4102,7 +4158,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Setting 16-bit integers, both endians. */ @@ -4189,7 +4247,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif if (len < 4) { goto skip_interest; } @@ -4277,7 +4337,9 @@ skip_arith: afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_interest: @@ -4351,7 +4413,9 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Insertion of user-supplied extras. */ @@ -4408,7 +4472,9 @@ skip_interest: afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_user_extras: @@ -4468,7 +4534,9 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif /* Insertion of auto extras. */ @@ -4525,7 +4593,9 @@ skip_user_extras: afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif skip_extras: @@ -5351,13 +5421,17 @@ pacemaker_fuzzing: afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_HAVOC] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif } else { afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_SPLICE] += afl->stage_max; +#ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; +#endif } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index ac9ad4db..87e149de 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -365,6 +365,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, } +#ifdef INTROSPECTION void write_queue_stats(afl_state_t *afl) { FILE *f; @@ -395,6 +396,8 @@ void write_queue_stats(afl_state_t *afl) { } +#endif + /* Update the plot file if there is a reason to. */ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, @@ -649,7 +652,9 @@ void show_stats_normal(afl_state_t *afl) { cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { afl->stats_last_queue_ms = cur_ms; +#ifdef INTROSPECTION write_queue_stats(afl); +#endif } @@ -1445,7 +1450,9 @@ void show_stats_pizza(afl_state_t *afl) { cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { afl->stats_last_queue_ms = cur_ms; +#ifdef INTROSPECTION write_queue_stats(afl); +#endif } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 172b9d7a..efef5523 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2279,8 +2279,10 @@ int main(int argc, char **argv_orig, char **envp) { // real start time, we reset, so this works correctly with -V afl->start_time = get_cur_time(); - u32 runs_in_current_cycle = (u32)-1; - u32 prev_queued_items = 0, prev_saved_crashes = 0, prev_saved_tmouts = 0; + #ifdef INTROSPECTION + u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; + #endif + u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1; u8 skipped_fuzz; #ifdef INTROSPECTION @@ -2542,6 +2544,7 @@ int main(int argc, char **argv_orig, char **envp) { } skipped_fuzz = fuzz_one(afl); + #ifdef INTROSPECTION ++afl->queue_cur->stats_selected; if (unlikely(skipped_fuzz)) { @@ -2573,6 +2576,8 @@ int main(int argc, char **argv_orig, char **envp) { } + #endif + if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; } if (unlikely(afl->old_seed_selection)) { From 401811a97d39362cd52f38c0fd935b1ef6c043e7 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 23 Dec 2022 12:06:40 +0000 Subject: [PATCH 026/300] afl-untracer freebsd 13.1 and above update. with the new kern.elf*.allow_wx setting, we try to make sure we still can make the maps w/x, fixing few build warnings while at it. --- utils/afl_untracer/afl-untracer.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index ed7047a4..6bee067c 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -156,7 +156,7 @@ void read_library_information(void) { *e = 0; if (n[strlen(n) - 1] == '\n') n[strlen(n) - 1] = 0; - liblist[liblist_cnt].name = strdup(n); + liblist[liblist_cnt].name = (u8 *)strdup((char *)n); liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); if (debug) @@ -210,16 +210,16 @@ void read_library_information(void) { !(region->kve_protection & KVME_PROT_EXEC)) { liblist[liblist_cnt].name = - region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; + region->kve_path[0] != '\0' ? (u8 *)strdup(region->kve_path) : 0; liblist[liblist_cnt].addr_start = region->kve_start; liblist[liblist_cnt].addr_end = region->kve_end; if (debug) { - fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_end - 1); + fprintf(stderr, "%s:%lx (%lx-%lx)\n", liblist[liblist_cnt].name, + (unsigned long)(liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start), + (unsigned long)liblist[liblist_cnt].addr_start, + (unsigned long)(liblist[liblist_cnt].addr_end - 1)); } @@ -488,6 +488,12 @@ void setup_trap_instrumentation(void) { uint32_t bitmap_index = 0; #endif +#if defined(__FreeBSD__) && __FreeBSD_version >= 1301000 + // We try to allow W/X pages despite kern.elf32/64.allow_wx system settings + int allow_wx = PROC_WX_MAPPINGS_PERMIT; + (void)procctl(P_PID, 0, PROC_WXMAP_CTL, &allow_wx); +#endif + while ((nread = getline(&line, &len, patches)) != -1) { char *end = line + len; @@ -699,7 +705,7 @@ int main(int argc, char *argv[]) { if (argc > 1) { use_stdin = 0; - inputfile = argv[1]; + inputfile = (u8 *)argv[1]; } @@ -732,7 +738,7 @@ int main(int argc, char *argv[]) { if (pid) { u32 status; - if (waitpid(pid, &status, 0) < 0) exit(1); + if (waitpid(pid, (int *)&status, 0) < 0) exit(1); /* report the test case is done and wait for the next */ __afl_end_testcase(status); From 342081d5ee367f473df3fc34c55edb5df7e42d0f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 23 Dec 2022 16:32:53 +0100 Subject: [PATCH 027/300] make CI green --- GNUmakefile | 6 ++++-- docs/Changelog.md | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 6b55635f..43f96ffe 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -628,9 +628,9 @@ distrib: all -$(MAKE) -j$(nproc) -f GNUmakefile.llvm ifneq "$(SYS)" "Darwin" -$(MAKE) -f GNUmakefile.gcc_plugin -endif -$(MAKE) -C utils/libdislocator -$(MAKE) -C utils/libtokencap +endif -$(MAKE) -C utils/afl_network_proxy -$(MAKE) -C utils/socket_fuzzing -$(MAKE) -C utils/argv_fuzzing @@ -659,8 +659,10 @@ endif .PHONY: binary-only binary-only: test_shm test_python ready $(PROGS) +ifneq "$(SYS)" "Darwin" -$(MAKE) -C utils/libdislocator -$(MAKE) -C utils/libtokencap +#endif -$(MAKE) -C utils/afl_network_proxy -$(MAKE) -C utils/socket_fuzzing -$(MAKE) -C utils/argv_fuzzing @@ -717,9 +719,9 @@ source-only: all -$(MAKE) -j$(nproc) -f GNUmakefile.llvm ifneq "$(SYS)" "Darwin" -$(MAKE) -f GNUmakefile.gcc_plugin -endif -$(MAKE) -C utils/libdislocator -$(MAKE) -C utils/libtokencap +endif # -$(MAKE) -C utils/plot_ui ifeq "$(SYS)" "Linux" ifndef NO_NYX diff --git a/docs/Changelog.md b/docs/Changelog.md index 4df47645..6bfb314d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,6 +4,10 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.05a (dev) + - MacOS: libdislocator, libtokencap etc. do not work with modern + MacOS anymore, but could be patched to work, see this issue if you + want to make the effort and send a PR: + https://github.com/AFLplusplus/AFLplusplus/issues/1594 - afl-fuzz: - added afl_custom_fuzz_send custom mutator feature. Now your can send fuzz data to the target as you need, e.g. via IPC. From 6fe38b2138ed993f3af28fc5ab92fda8f7542ef7 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:39:47 +0100 Subject: [PATCH 028/300] argv fuzz persistent --- utils/argv_fuzzing/argv-fuzz-inl.h | 43 +++++++++++++++++++ utils/argv_fuzzing/argv_fuzz_demo.c | 16 +++++++ .../argv_fuzzing/argv_fuzz_persistent_demo.c | 28 ++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 utils/argv_fuzzing/argv_fuzz_demo.c create mode 100644 utils/argv_fuzzing/argv_fuzz_persistent_demo.c diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index ec22c53b..d3440799 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -29,6 +29,10 @@ If you would like to always preserve argv[0], use this instead: AFL_INIT_SET0("prog_name"); + To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with + buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf) + to preserver argv[0]. buf should be defined as: + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; */ #ifndef _HAVE_ARGV_FUZZ_INL @@ -53,6 +57,20 @@ \ } while (0) +#define AFL_INIT_ARGV_PERSISTENT(persistent_buff) \ + do { \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + } while (0) + +#define AFL_INIT_SET0_PERSISTENT(_p, persistent_buff) \ + do { \ + \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + argv[0] = (_p); \ + if (!argc) argc = 1; \ + \ + } while (0) + #define MAX_CMDLINE_LEN 100000 #define MAX_CMDLINE_PAR 50000 @@ -87,6 +105,31 @@ static char **afl_init_argv(int *argc) { } +static char **afl_init_argv_persistent(int *argc, unsigned char *persistent_buff) { + + static char *ret[MAX_CMDLINE_PAR]; + + unsigned char *ptr = persistent_buff; + int rc = 0; + + while (*ptr && rc < MAX_CMDLINE_PAR) { + + ret[rc] = (char *)ptr; + if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; + rc++; + + while (*ptr) + ptr++; + ptr++; + + } + + *argc = rc; + + return ret; + +} + #undef MAX_CMDLINE_LEN #undef MAX_CMDLINE_PAR diff --git a/utils/argv_fuzzing/argv_fuzz_demo.c b/utils/argv_fuzzing/argv_fuzz_demo.c new file mode 100644 index 00000000..f4375316 --- /dev/null +++ b/utils/argv_fuzzing/argv_fuzz_demo.c @@ -0,0 +1,16 @@ +#include +#include +#include "argv-fuzz-inl.h" + +int main(int argc, char **argv) { +AFL_INIT_ARGV(); + if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { + if (strcmp(argv[2], "TEST2") == 0) { + abort(); + } + } else { + printf("Bad number of arguments!\n"); + } + + return 0; +} \ No newline at end of file diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c new file mode 100644 index 00000000..5ecda22b --- /dev/null +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -0,0 +1,28 @@ +#include +#include +#include "argv-fuzz-inl.h" + +__AFL_FUZZ_INIT(); + +int main(int argc, char **argv) { +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; + + while (__AFL_LOOP(100000)) { + int len = __AFL_FUZZ_TESTCASE_LEN; + + if (len < 8) continue; + + AFL_INIT_ARGV_P(buf); + + if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { + if (strcmp(argv[2], "TEST2") == 0) { abort(); } + } else { + printf("Bad number of arguments!\n"); + } + } + + return 0; +} \ No newline at end of file From a0eee2bd92cb819758e54bbac9b8d8ec7daa0764 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:44:49 +0100 Subject: [PATCH 029/300] makefile update --- utils/argv_fuzzing/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 183f6bf8..dfdd0f8e 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -56,3 +56,7 @@ install: argvfuzz32.so argvfuzz64.so clean: rm -f argvfuzz32.so argvfuzz64.so + +demo: + ../../afl-clang-fast -o argv_fuzz_demo argv_fuzz.c + ../../afl-clang-fast -o argv_fuzz_persistent_demo argv_fuzz_persistent_demo.c \ No newline at end of file From 0062a14aa32ffbf38c10a15b3cae97a63a6b3272 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:48:06 +0100 Subject: [PATCH 030/300] makefile update --- utils/argv_fuzzing/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index dfdd0f8e..bf4ae81d 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -58,5 +58,5 @@ clean: rm -f argvfuzz32.so argvfuzz64.so demo: - ../../afl-clang-fast -o argv_fuzz_demo argv_fuzz.c + ../../afl-clang-fast -o argv_fuzz_demo argv_fuzz_demo.c ../../afl-clang-fast -o argv_fuzz_persistent_demo argv_fuzz_persistent_demo.c \ No newline at end of file From 67ae1d583902a7e0a8a39c2b17321ffde045cd6d Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:49:22 +0100 Subject: [PATCH 031/300] makefile update --- utils/argv_fuzzing/argv_fuzz_persistent_demo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c index 5ecda22b..1e96ade1 100644 --- a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -15,7 +15,7 @@ int main(int argc, char **argv) { if (len < 8) continue; - AFL_INIT_ARGV_P(buf); + AFL_INIT_ARGV_PERSISTENT(buf); if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { if (strcmp(argv[2], "TEST2") == 0) { abort(); } From 6e5c08b653d7d55c5d544601d9fb19fcc16edfd6 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:50:53 +0100 Subject: [PATCH 032/300] makefile update --- utils/argv_fuzzing/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index bf4ae81d..140a53de 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -55,7 +55,7 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi clean: - rm -f argvfuzz32.so argvfuzz64.so + rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo demo: ../../afl-clang-fast -o argv_fuzz_demo argv_fuzz_demo.c From 3a134edd889ed1bf4f8d11e8e37ebba31460fb3e Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 15:51:50 +0100 Subject: [PATCH 033/300] makefile update --- utils/argv_fuzzing/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 140a53de..3ebde54b 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -41,7 +41,7 @@ __M32FLAG=$(_M32FLAG:00=-mbe32) ___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32) M32FLAG=$(___M32FLAG) -all: argvfuzz32.so argvfuzz64.so +all: argvfuzz32.so argvfuzz64.so demo argvfuzz32.so: argvfuzz.c -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)" From 3d031f93a6366ee157cfd9a27fbb6d485d328d8e Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 16:15:52 +0100 Subject: [PATCH 034/300] update --- utils/argv_fuzzing/argv_fuzz_demo.c | 9 +++++++- .../argv_fuzzing/argv_fuzz_persistent_demo.c | 23 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/utils/argv_fuzzing/argv_fuzz_demo.c b/utils/argv_fuzzing/argv_fuzz_demo.c index f4375316..5fe4d704 100644 --- a/utils/argv_fuzzing/argv_fuzz_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_demo.c @@ -3,7 +3,14 @@ #include "argv-fuzz-inl.h" int main(int argc, char **argv) { -AFL_INIT_ARGV(); + // Initialize the argv array for use with the AFL (American Fuzzy Lop) tool + AFL_INIT_ARGV(); + + /* Check the number of command line arguments and + compare the values of the first two arguments to specific strings. + If the number of arguments is not correct or the values do not match, + an error message is printed. If the values do match, the program + calls the abort() function. */ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { if (strcmp(argv[2], "TEST2") == 0) { abort(); diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c index 1e96ade1..a96cf1fe 100644 --- a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -1,28 +1,49 @@ +/* +This file contains a simple fuzzer for testing command line argument parsing +using persistent mode. +*/ + #include #include #include "argv-fuzz-inl.h" __AFL_FUZZ_INIT(); +/* The main function is an entry point for a program. + The argc parameter is an integer that indicates the number of arguments + passed to the program. The argv parameter is an array of character pointers, + with each element pointing to a null-terminated string that represents + one of the arguments. + */ int main(int argc, char **argv) { #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; + /* __AFL_LOOP() limits the maximum number of iterations before exiting + the loop and allowing the program to terminate. It protects against + accidental memory leaks and similar issues. */ while (__AFL_LOOP(100000)) { int len = __AFL_FUZZ_TESTCASE_LEN; + // Check that the length of the test case is at least 8 bytes if (len < 8) continue; + // Initialize the command line arguments using the testcase buffer AFL_INIT_ARGV_PERSISTENT(buf); + /* Check if the first argument is "XYZ" and the second argument is "TEST2" + If so, call the "abort" function to terminate the program. + Otherwise, print an error message. */ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { if (strcmp(argv[2], "TEST2") == 0) { abort(); } } else { printf("Bad number of arguments!\n"); } } - + /* Exiting the loop allows the program to terminate normally. AFL will restart + the process with a clean slate for allocated memory, file descriptors, etc. + */ return 0; } \ No newline at end of file From b189640a927e9ed17347b26f6579b0e41dcdda38 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 16:54:36 +0100 Subject: [PATCH 035/300] cleanup --- .custom-format.py | 15 +++++----- utils/argv_fuzzing/README.md | 4 +-- utils/argv_fuzzing/argv-fuzz-inl.h | 29 ++++++++++--------- utils/argv_fuzzing/argv_fuzz_demo.c | 13 ++++++--- .../argv_fuzzing/argv_fuzz_persistent_demo.c | 11 ++++++- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index 428d7b0d..00f6280f 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -26,15 +26,16 @@ import shutil with open(".clang-format") as f: fmt = f.read() -CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) -CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") +#CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) +#CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") -if shutil.which(CLANG_FORMAT_BIN) is None: - CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}" +#if shutil.which(CLANG_FORMAT_BIN) is None: +# CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}" -if shutil.which(CLANG_FORMAT_BIN) is None: - print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.") - exit(1) +#if shutil.which(CLANG_FORMAT_BIN) is None: +# print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.") +# exit(1) +CLANG_FORMAT_BIN = "clang-format" COLUMN_LIMIT = 80 for line in fmt.split("\n"): diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index e9224995..bcf388c7 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,4 +1,4 @@ -# argvfuzz +#argvfuzz AFL++ supports fuzzing file inputs or stdin. When source is available, `argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin. @@ -13,4 +13,4 @@ A few conditions need to be fulfilled for this mechanism to work correctly: 2. If the target binary does not use the default libc's `_start` implementation (crt1.o), the hook may not run. 3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the - target binary expects argv to be living on the stack, things may go wrong. \ No newline at end of file + target binary expects argv to be living on the stack, things may go wrong. diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index d3440799..bb8f2813 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -57,18 +57,20 @@ \ } while (0) -#define AFL_INIT_ARGV_PERSISTENT(persistent_buff) \ - do { \ - argv = afl_init_argv_persistent(&argc, persistent_buff); \ - } while (0) +#define AFL_INIT_ARGV_PERSISTENT(persistent_buff) \ + do { \ + \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + \ + } while (0) -#define AFL_INIT_SET0_PERSISTENT(_p, persistent_buff) \ - do { \ - \ - argv = afl_init_argv_persistent(&argc, persistent_buff); \ - argv[0] = (_p); \ - if (!argc) argc = 1; \ - \ +#define AFL_INIT_SET0_PERSISTENT(_p, persistent_buff) \ + do { \ + \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + argv[0] = (_p); \ + if (!argc) argc = 1; \ + \ } while (0) #define MAX_CMDLINE_LEN 100000 @@ -105,12 +107,13 @@ static char **afl_init_argv(int *argc) { } -static char **afl_init_argv_persistent(int *argc, unsigned char *persistent_buff) { +static char **afl_init_argv_persistent(int *argc, + unsigned char *persistent_buff) { static char *ret[MAX_CMDLINE_PAR]; unsigned char *ptr = persistent_buff; - int rc = 0; + int rc = 0; while (*ptr && rc < MAX_CMDLINE_PAR) { diff --git a/utils/argv_fuzzing/argv_fuzz_demo.c b/utils/argv_fuzzing/argv_fuzz_demo.c index 5fe4d704..6ab1e2e5 100644 --- a/utils/argv_fuzzing/argv_fuzz_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_demo.c @@ -3,6 +3,7 @@ #include "argv-fuzz-inl.h" int main(int argc, char **argv) { + // Initialize the argv array for use with the AFL (American Fuzzy Lop) tool AFL_INIT_ARGV(); @@ -12,12 +13,16 @@ int main(int argc, char **argv) { an error message is printed. If the values do match, the program calls the abort() function. */ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { - if (strcmp(argv[2], "TEST2") == 0) { - abort(); - } + + if (strcmp(argv[2], "TEST2") == 0) { abort(); } + } else { + printf("Bad number of arguments!\n"); + } return 0; -} \ No newline at end of file + +} + diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c index a96cf1fe..08a62c62 100644 --- a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -16,6 +16,7 @@ __AFL_FUZZ_INIT(); one of the arguments. */ int main(int argc, char **argv) { + #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif @@ -25,6 +26,7 @@ int main(int argc, char **argv) { the loop and allowing the program to terminate. It protects against accidental memory leaks and similar issues. */ while (__AFL_LOOP(100000)) { + int len = __AFL_FUZZ_TESTCASE_LEN; // Check that the length of the test case is at least 8 bytes @@ -37,13 +39,20 @@ int main(int argc, char **argv) { If so, call the "abort" function to terminate the program. Otherwise, print an error message. */ if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { + if (strcmp(argv[2], "TEST2") == 0) { abort(); } + } else { + printf("Bad number of arguments!\n"); + } + } + /* Exiting the loop allows the program to terminate normally. AFL will restart the process with a clean slate for allocated memory, file descriptors, etc. */ return 0; -} \ No newline at end of file + +} From 3188cac1d074352e9110d83c7ad5c3d5684d90f8 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Tue, 27 Dec 2022 16:57:30 +0100 Subject: [PATCH 036/300] cleanup --- utils/argv_fuzzing/README.md | 2 +- utils/argv_fuzzing/argv-fuzz-inl.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index bcf388c7..ca90f26c 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,4 +1,4 @@ -#argvfuzz +# argvfuzz feature AFL++ supports fuzzing file inputs or stdin. When source is available, `argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin. diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index bb8f2813..abe86d3c 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -29,10 +29,10 @@ If you would like to always preserve argv[0], use this instead: AFL_INIT_SET0("prog_name"); - To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with - buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf) - to preserver argv[0]. buf should be defined as: - unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; + To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with + buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf) + to preserver argv[0]. buf should be defined as: + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; */ #ifndef _HAVE_ARGV_FUZZ_INL From 51e0707d4d5b65cf4245b7350986c66bf639f3cd Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 09:27:22 +0100 Subject: [PATCH 037/300] readme update --- utils/argv_fuzzing/README.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index ca90f26c..e22fbe4e 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,15 +1,37 @@ -# argvfuzz feature +# argv_fuzzing feature +AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature allows for fuzzing of arguments passed to a program from the command line interface, rather than from standard input. -AFL++ supports fuzzing file inputs or stdin. When source is available, -`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin. +## With source code +When source is available, a macro from the `argv-fuzz-inl.h` header file can be used to change the program's behavior to build argv from STDIN. +### Without persistent mode +Conditions needed to use the argv_fuzzing feature: +1. Include `argv-fuzz-inl.h` header file (`#include "argv-fuzz-inl.h"`) +2. Identify your main function that parses arguments (for example, `int main(int argc, char **argv)`) +3. Use the one of the following macros (near the beginning of the main function) to initialize argv with the fuzzer's input: + - `AFL_INIT_ARGV();` or + - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]` (the name of the program being executed) + +see: [argv_fuzz_demo.c](argv_fuzz_demo.c) + +### With persistent mode +Conditions needed to use the argv_fuzzing feature with persistent mode: +1. Ensure your target can handle persistent mode fuzzing +2. Follow instructions in the [llvm_mode persistent mode](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md) +3. Use the one of the following macro near the beginning of the main function and after the buffer initialization (`unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF`): + - `AFL_INIT_ARGV_PERSISTENT(buf)`, if you want to + - `AFL_INIT_SET0_PERSISTENT("name_of_binary", buf)` + +see: [argv_fuzz_persistent_demo.c](argv_fuzz_persistent_demo.c) + +## Binary only `argvfuzz` tries to provide the same functionality for binaries. When loaded using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace argv using the same logic of `argv-fuzz-inl.h`. A few conditions need to be fulfilled for this mechanism to work correctly: -1. As it relies on hooking the loader, it cannot work on static binaries. +1. As it relies on hooking the loader, it cannot work on static binaries 2. If the target binary does not use the default libc's `_start` implementation (crt1.o), the hook may not run. 3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the From f28f6adbce0b803b80938518ca9c559e428ef9cf Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 09:41:22 +0100 Subject: [PATCH 038/300] update --- utils/argv_fuzzing/Makefile | 8 +++++--- utils/argv_fuzzing/README.md | 15 +++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 3ebde54b..fca46b09 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -11,7 +11,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -.PHONY: all install clean +.PHONY: all install clean demo PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin @@ -58,5 +58,7 @@ clean: rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo demo: - ../../afl-clang-fast -o argv_fuzz_demo argv_fuzz_demo.c - ../../afl-clang-fast -o argv_fuzz_persistent_demo argv_fuzz_persistent_demo.c \ No newline at end of file + CC = afl-clang-fast + CFLAGS = -fsanitize=address + -@$(CC) $(CFLAGS) -o argv_fuzz_demo argv_fuzz_demo.c + -@$(CC) $(CFLAGS) -o argv_fuzz_persistent_demo argv_fuzz_persistent_demo.c \ No newline at end of file diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index e22fbe4e..d248cf93 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,14 +1,16 @@ # argv_fuzzing feature -AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature allows for fuzzing of arguments passed to a program from the command line interface, rather than from standard input. +AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature allows for the fuzzing of arguments +passed to a program from the command line interface rather than from standard input. ## With source code -When source is available, a macro from the `argv-fuzz-inl.h` header file can be used to change the program's behavior to build argv from STDIN. +When the source code is available, a specific macro from the `argv-fuzz-inl.h` header file can be used to change +the program's behavior to build argv from STDIN. ### Without persistent mode Conditions needed to use the argv_fuzzing feature: 1. Include `argv-fuzz-inl.h` header file (`#include "argv-fuzz-inl.h"`) 2. Identify your main function that parses arguments (for example, `int main(int argc, char **argv)`) -3. Use the one of the following macros (near the beginning of the main function) to initialize argv with the fuzzer's input: +3. Use one of the following macros (near the beginning of the main function) to initialize argv with the fuzzer's input: - `AFL_INIT_ARGV();` or - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]` (the name of the program being executed) @@ -18,7 +20,8 @@ see: [argv_fuzz_demo.c](argv_fuzz_demo.c) Conditions needed to use the argv_fuzzing feature with persistent mode: 1. Ensure your target can handle persistent mode fuzzing 2. Follow instructions in the [llvm_mode persistent mode](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md) -3. Use the one of the following macro near the beginning of the main function and after the buffer initialization (`unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF`): +3. Use one of the following macros near the beginning of the main function and after +the buffer initialization (`unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF`): - `AFL_INIT_ARGV_PERSISTENT(buf)`, if you want to - `AFL_INIT_SET0_PERSISTENT("name_of_binary", buf)` @@ -34,5 +37,5 @@ A few conditions need to be fulfilled for this mechanism to work correctly: 1. As it relies on hooking the loader, it cannot work on static binaries 2. If the target binary does not use the default libc's `_start` implementation (crt1.o), the hook may not run. -3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the - target binary expects argv to be living on the stack, things may go wrong. +3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. +Things may go wrong if the target binary expects argv to live on the stack. From c0c985a2781f84313db80eea3662ec88fb264292 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 09:48:10 +0100 Subject: [PATCH 039/300] minor changes --- utils/argv_fuzzing/argv-fuzz-inl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index abe86d3c..cb0af2bc 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -31,7 +31,8 @@ To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf) - to preserver argv[0]. buf should be defined as: + to preserver argv[0]. buf is a pointer to a buffer containing + the input data for the current test case being processed defined as: unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; */ From 86ec1b9d71d1d2679f85676c65947324779016b3 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 09:55:14 +0100 Subject: [PATCH 040/300] makefile update --- utils/argv_fuzzing/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index fca46b09..ba811de6 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -11,7 +11,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -.PHONY: all install clean demo +.PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin @@ -41,7 +41,7 @@ __M32FLAG=$(_M32FLAG:00=-mbe32) ___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32) M32FLAG=$(___M32FLAG) -all: argvfuzz32.so argvfuzz64.so demo +all: argvfuzz32.so argvfuzz64.so argv_fuzz_persistent_demo argv_fuzz_demo argvfuzz32.so: argvfuzz.c -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)" @@ -57,8 +57,8 @@ install: argvfuzz32.so argvfuzz64.so clean: rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo -demo: - CC = afl-clang-fast - CFLAGS = -fsanitize=address - -@$(CC) $(CFLAGS) -o argv_fuzz_demo argv_fuzz_demo.c - -@$(CC) $(CFLAGS) -o argv_fuzz_persistent_demo argv_fuzz_persistent_demo.c \ No newline at end of file +argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c + $(CC) $(CFLAGS) -o $@ $^ + +argv_fuzz_demo: argv_fuzz_demo.c + $(CC) $(CFLAGS) -o $@ $^ \ No newline at end of file From 4ff37da70923196f6986d64eafdda82590b92207 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:34:56 +0100 Subject: [PATCH 041/300] makefile update --- utils/argv_fuzzing/Makefile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index ba811de6..b6630175 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -13,11 +13,20 @@ .PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo +CC ?= afl-clang-fast +CFLAGS ?= -fsanitize=address + +argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c + $(CC) $(CFLAGS) -o $@ $^ + +argv_fuzz_demo: argv_fuzz_demo.c + $(CC) $(CFLAGS) -o $@ $^ + PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl -CFLAGS = -fPIC -Wall -Wextra +CFLAGS += -fPIC -Wall -Wextra LDFLAGS = -shared UNAME_SAYS_LINUX=$(shell uname | grep -E '^Linux|^GNU' >/dev/null; echo $$?) @@ -57,8 +66,3 @@ install: argvfuzz32.so argvfuzz64.so clean: rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo -argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - $(CC) $(CFLAGS) -o $@ $^ - -argv_fuzz_demo: argv_fuzz_demo.c - $(CC) $(CFLAGS) -o $@ $^ \ No newline at end of file From 107ebb7d49aefe87bd9b610b5b6a82c85d740ab7 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:40:17 +0100 Subject: [PATCH 042/300] makefile update --- utils/argv_fuzzing/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index b6630175..ef719e9a 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -22,6 +22,8 @@ argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c argv_fuzz_demo: argv_fuzz_demo.c $(CC) $(CFLAGS) -o $@ $^ +demo: argv_fuzz_persistent_demo argv_fuzz_demo + PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl @@ -50,7 +52,7 @@ __M32FLAG=$(_M32FLAG:00=-mbe32) ___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32) M32FLAG=$(___M32FLAG) -all: argvfuzz32.so argvfuzz64.so argv_fuzz_persistent_demo argv_fuzz_demo +all: argvfuzz32.so argvfuzz64.so demo argvfuzz32.so: argvfuzz.c -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)" From c090abb00d93e60a0643f6fb9c42816bc75846e3 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:44:02 +0100 Subject: [PATCH 043/300] makefile update --- utils/argv_fuzzing/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index ef719e9a..2b30b18c 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -13,14 +13,14 @@ .PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo -CC ?= afl-clang-fast -CFLAGS ?= -fsanitize=address +#CC ?= afl-clang-fast +#CFLAGS ?= -fsanitize=address argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - $(CC) $(CFLAGS) -o $@ $^ + CC=afl-clang-fast CFLAGS=-fsanitize=address $(CC) $(CFLAGS) -o $@ $^ argv_fuzz_demo: argv_fuzz_demo.c - $(CC) $(CFLAGS) -o $@ $^ + CC=afl-clang-fast CFLAGS=-fsanitize=address $(CC) $(CFLAGS) -o $@ $^ demo: argv_fuzz_persistent_demo argv_fuzz_demo From 0710e4f17ca9224beaf3424c2cc6f07083ab7c1e Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:47:08 +0100 Subject: [PATCH 044/300] makefile update --- utils/argv_fuzzing/Makefile | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 2b30b18c..dce092d6 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -11,18 +11,11 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -.PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo +.PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo demo -#CC ?= afl-clang-fast -#CFLAGS ?= -fsanitize=address -argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - CC=afl-clang-fast CFLAGS=-fsanitize=address $(CC) $(CFLAGS) -o $@ $^ -argv_fuzz_demo: argv_fuzz_demo.c - CC=afl-clang-fast CFLAGS=-fsanitize=address $(CC) $(CFLAGS) -o $@ $^ -demo: argv_fuzz_persistent_demo argv_fuzz_demo PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin @@ -65,6 +58,14 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi +argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c + afl-clang-fast -fsanitize=address -g -o $@ $^ + +argv_fuzz_demo: argv_fuzz_demo.c + afl-clang-fast -fsanitize=address -g -o $@ $^ + +demo: argv_fuzz_persistent_demo argv_fuzz_demo + clean: rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo From 489f2d4d97c8497d6e259e9e50c27628ad075126 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:49:31 +0100 Subject: [PATCH 045/300] makefile update --- utils/argv_fuzzing/Makefile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index dce092d6..1bc6b223 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -13,10 +13,6 @@ .PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo demo - - - - PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl @@ -59,10 +55,10 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - afl-clang-fast -fsanitize=address -g -o $@ $^ + CC=afl-clang-fast $(CC) -o $@ $^ argv_fuzz_demo: argv_fuzz_demo.c - afl-clang-fast -fsanitize=address -g -o $@ $^ + CC=afl-clang-fast $(CC) -o $@ $^ demo: argv_fuzz_persistent_demo argv_fuzz_demo From 209527907ff9a843fe9d353ec1a1602f88579982 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:50:05 +0100 Subject: [PATCH 046/300] makefile update --- utils/argv_fuzzing/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 1bc6b223..7e706180 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -55,10 +55,10 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - CC=afl-clang-fast $(CC) -o $@ $^ + afl-clang-fast -fsanitize=address -g -o $@ $^ argv_fuzz_demo: argv_fuzz_demo.c - CC=afl-clang-fast $(CC) -o $@ $^ + afl-clang-fast -fsanitize=address -g -o $@ $^ demo: argv_fuzz_persistent_demo argv_fuzz_demo From 99c67defb4414c1f207123e2930d0500d338c6b8 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 10:58:44 +0100 Subject: [PATCH 047/300] readme cleanup --- utils/argv_fuzzing/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index d248cf93..14fe5e2d 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,18 +1,22 @@ # argv_fuzzing feature -AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature allows for the fuzzing of arguments -passed to a program from the command line interface rather than from standard input. +AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature +allows for the fuzzing of arguments passed to a program from the command line +interface rather than from standard input. ## With source code -When the source code is available, a specific macro from the `argv-fuzz-inl.h` header file can be used to change -the program's behavior to build argv from STDIN. +When the source code is available, a specific macro from the `argv-fuzz-inl.h` +header file can be used to change the program's behavior to build argv from STDIN. ### Without persistent mode Conditions needed to use the argv_fuzzing feature: 1. Include `argv-fuzz-inl.h` header file (`#include "argv-fuzz-inl.h"`) -2. Identify your main function that parses arguments (for example, `int main(int argc, char **argv)`) -3. Use one of the following macros (near the beginning of the main function) to initialize argv with the fuzzer's input: +2. Identify your main function that parses arguments +(for example, `int main(int argc, char **argv)`) +3. Use one of the following macros (near the beginning of the main function) +to initialize argv with the fuzzer's input: - `AFL_INIT_ARGV();` or - - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]` (the name of the program being executed) + - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]` + (the name of the program being executed) see: [argv_fuzz_demo.c](argv_fuzz_demo.c) From 5670c847bd2cc619a9d4a11e9f7ccb1f4004a0b0 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 11:00:14 +0100 Subject: [PATCH 048/300] readme update --- utils/argv_fuzzing/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index 14fe5e2d..a085c098 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,7 +1,7 @@ # argv_fuzzing feature -AFL++ supports fuzzing file inputs or stdin. The argv_fuzzing feature +AFL++ supports fuzzing file inputs or standard input. The argv_fuzzing feature allows for the fuzzing of arguments passed to a program from the command line -interface rather than from standard input. +interface rather than from STDIN. ## With source code When the source code is available, a specific macro from the `argv-fuzz-inl.h` From fd27b2c9be442c429c215fe57bd5893121795b42 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 11:04:53 +0100 Subject: [PATCH 049/300] makefile cleanup --- utils/argv_fuzzing/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 7e706180..f016c5a7 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -17,7 +17,7 @@ PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl -CFLAGS += -fPIC -Wall -Wextra +CFLAGS = -fPIC -Wall -Wextra LDFLAGS = -shared UNAME_SAYS_LINUX=$(shell uname | grep -E '^Linux|^GNU' >/dev/null; echo $$?) From 1149b131857af5e785a1bf3d72b4d15c5d542e46 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 11:07:49 +0100 Subject: [PATCH 050/300] undo custom-format --- .custom-format.py | 49 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index 00f6280f..aaa84af6 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -26,16 +26,15 @@ import shutil with open(".clang-format") as f: fmt = f.read() -#CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) -#CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") +CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) +CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") -#if shutil.which(CLANG_FORMAT_BIN) is None: -# CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}" +if shutil.which(CLANG_FORMAT_BIN) is None: + CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}" -#if shutil.which(CLANG_FORMAT_BIN) is None: -# print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.") -# exit(1) -CLANG_FORMAT_BIN = "clang-format" +if shutil.which(CLANG_FORMAT_BIN) is None: + print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.") + exit(1) COLUMN_LIMIT = 80 for line in fmt.split("\n"): @@ -59,16 +58,16 @@ def custom_format(filename): in_define = True if ( - "/*" in line - and not line.strip().startswith("/*") - and line.endswith("*/") - and len(line) < (COLUMN_LIMIT - 2) + "/*" in line + and not line.strip().startswith("/*") + and line.endswith("*/") + and len(line) < (COLUMN_LIMIT - 2) ): cmt_start = line.rfind("/*") line = ( - line[:cmt_start] - + " " * (COLUMN_LIMIT - 2 - len(line)) - + line[cmt_start:] + line[:cmt_start] + + " " * (COLUMN_LIMIT - 2 - len(line)) + + line[cmt_start:] ) define_padding = 0 @@ -77,21 +76,21 @@ def custom_format(filename): define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :])) if ( - last_line is not None - and last_line.strip().endswith("{") - and line.strip() != "" + last_line is not None + and last_line.strip().endswith("{") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - last_line is not None - and last_line.strip().startswith("}") - and line.strip() != "" + last_line is not None + and last_line.strip().startswith("}") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - line.strip().startswith("}") - and last_line is not None - and last_line.strip() != "" + line.strip().startswith("}") + and last_line is not None + and last_line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line @@ -124,4 +123,4 @@ for filename in args: with open(filename, "w") as f: f.write(code) else: - print(code) + print(code) \ No newline at end of file From 8817da8ae4038b0a155fde9e1f3ea8d4f7d8c107 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 11:10:38 +0100 Subject: [PATCH 051/300] Removed a modified file from pr --- .custom-format.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index aaa84af6..428d7b0d 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -58,16 +58,16 @@ def custom_format(filename): in_define = True if ( - "/*" in line - and not line.strip().startswith("/*") - and line.endswith("*/") - and len(line) < (COLUMN_LIMIT - 2) + "/*" in line + and not line.strip().startswith("/*") + and line.endswith("*/") + and len(line) < (COLUMN_LIMIT - 2) ): cmt_start = line.rfind("/*") line = ( - line[:cmt_start] - + " " * (COLUMN_LIMIT - 2 - len(line)) - + line[cmt_start:] + line[:cmt_start] + + " " * (COLUMN_LIMIT - 2 - len(line)) + + line[cmt_start:] ) define_padding = 0 @@ -76,21 +76,21 @@ def custom_format(filename): define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :])) if ( - last_line is not None - and last_line.strip().endswith("{") - and line.strip() != "" + last_line is not None + and last_line.strip().endswith("{") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - last_line is not None - and last_line.strip().startswith("}") - and line.strip() != "" + last_line is not None + and last_line.strip().startswith("}") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - line.strip().startswith("}") - and last_line is not None - and last_line.strip() != "" + line.strip().startswith("}") + and last_line is not None + and last_line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line @@ -123,4 +123,4 @@ for filename in args: with open(filename, "w") as f: f.write(code) else: - print(code) \ No newline at end of file + print(code) From 1bcc9bfa913b9afe07e7e0eef7d6912c79329112 Mon Sep 17 00:00:00 2001 From: Maciej Domanski Date: Wed, 28 Dec 2022 13:05:44 +0100 Subject: [PATCH 052/300] clang-format pip --- .custom-format.py | 83 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index 428d7b0d..95def5aa 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -3,7 +3,7 @@ # american fuzzy lop++ - custom code formatter # -------------------------------------------- # -# Written and maintaned by Andrea Fioraldi +# Written and maintained by Andrea Fioraldi # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. # Copyright 2019-2022 AFLplusplus Project. All rights reserved. @@ -18,24 +18,57 @@ import subprocess import sys import os -import re +# import re # TODO: for future use import shutil +import importlib.metadata -# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use - -with open(".clang-format") as f: - fmt = f.read() +# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") + +def check_clang_format_pip_version(): + """ + Check if the correct version of clang-format is installed via pip. + + Returns: + bool: True if the correct version of clang-format is installed, + False otherwise. + """ + # Check if clang-format is installed + if importlib.util.find_spec('clang_format'): + # Check if the installed version is the expected LLVM version + if importlib.metadata.version('clang-format')\ + .startswith(CURRENT_LLVM+'.'): + return True + else: + # Return False, because the clang-format version does not match + return False + else: + # If the 'clang_format' package isn't installed, return False + return False + + +with open(".clang-format") as f: + fmt = f.read() + + +CLANG_FORMAT_PIP = check_clang_format_pip_version() + if shutil.which(CLANG_FORMAT_BIN) is None: CLANG_FORMAT_BIN = f"clang-format-{CURRENT_LLVM}" -if shutil.which(CLANG_FORMAT_BIN) is None: +if shutil.which(CLANG_FORMAT_BIN) is None \ + and CLANG_FORMAT_PIP is False: print(f"[!] clang-format-{CURRENT_LLVM} is needed. Aborted.") + print(f"Run `pip3 install \"clang-format=={CURRENT_LLVM}.*\"` \ +to install via pip.") exit(1) +if CLANG_FORMAT_PIP: + CLANG_FORMAT_BIN = shutil.which("clang-format") + COLUMN_LIMIT = 80 for line in fmt.split("\n"): line = line.split(":") @@ -54,43 +87,43 @@ def custom_format(filename): for line in src.split("\n"): if line.lstrip().startswith("#"): - if line[line.find("#") + 1 :].lstrip().startswith("define"): + if line[line.find("#") + 1:].lstrip().startswith("define"): in_define = True if ( - "/*" in line - and not line.strip().startswith("/*") - and line.endswith("*/") - and len(line) < (COLUMN_LIMIT - 2) + "/*" in line + and not line.strip().startswith("/*") + and line.endswith("*/") + and len(line) < (COLUMN_LIMIT - 2) ): cmt_start = line.rfind("/*") line = ( - line[:cmt_start] - + " " * (COLUMN_LIMIT - 2 - len(line)) - + line[cmt_start:] + line[:cmt_start] + + " " * (COLUMN_LIMIT - 2 - len(line)) + + line[cmt_start:] ) define_padding = 0 if last_line is not None and in_define and last_line.endswith("\\"): last_line = last_line[:-1] - define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :])) + define_padding = max(0, len(last_line[last_line.rfind("\n") + 1:])) if ( - last_line is not None - and last_line.strip().endswith("{") - and line.strip() != "" + last_line is not None + and last_line.strip().endswith("{") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - last_line is not None - and last_line.strip().startswith("}") - and line.strip() != "" + last_line is not None + and last_line.strip().startswith("}") + and line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif ( - line.strip().startswith("}") - and last_line is not None - and last_line.strip() != "" + line.strip().startswith("}") + and last_line is not None + and last_line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line From e847b9948daba83257a665d936d83cfd9004e2ae Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 28 Dec 2022 17:40:56 +0100 Subject: [PATCH 053/300] prevent weighting < 1 --- src/afl-fuzz-queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index d8dbdfbe..5017c37c 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -51,13 +51,14 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { u32 hits = afl->n_fuzz[q->n_fuzz_entry]; - if (likely(hits)) { weight *= log10(hits) + 1; } + if (likely(hits)) { weight *= (log10(hits) + 1); } } if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); } weight *= (log(q->bitmap_size) / avg_bitmap_size); weight *= (1 + (q->tc_ref / avg_top_size)); + if (unlikely(weight < 1.0)) { weight = 1.0; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } From ffe89e8f2d142919f90de2994d23d0249b5d12ca Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Dec 2022 10:25:12 +0100 Subject: [PATCH 054/300] fix makefile typo --- GNUmakefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 43f96ffe..6921cc85 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -637,16 +637,16 @@ endif # -$(MAKE) -C utils/plot_ui -$(MAKE) -C frida_mode ifneq "$(SYS)" "Darwin" -ifeq "$(ARCH)" "aarch64" - ifndef NO_CORESIGHT + ifeq "$(ARCH)" "aarch64" + ifndef NO_CORESIGHT -$(MAKE) -C coresight_mode + endif endif -endif -ifeq "$(SYS)" "Linux" - ifndef NO_NYX + ifeq "$(SYS)" "Linux" + ifndef NO_NYX -cd nyx_mode && ./build_nyx_support.sh + endif endif -endif -cd qemu_mode && sh ./build_qemu_support.sh ifeq "$(ARCH)" "aarch64" ifndef NO_UNICORN_ARM64 @@ -662,7 +662,7 @@ binary-only: test_shm test_python ready $(PROGS) ifneq "$(SYS)" "Darwin" -$(MAKE) -C utils/libdislocator -$(MAKE) -C utils/libtokencap -#endif +endif -$(MAKE) -C utils/afl_network_proxy -$(MAKE) -C utils/socket_fuzzing -$(MAKE) -C utils/argv_fuzzing From 35f09e11a4373b0fb42c690d23127c144f72f73c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 3 Jan 2023 09:38:00 +0100 Subject: [PATCH 055/300] welcome 2023 --- .custom-format.py | 2 +- GNUmakefile.gcc_plugin | 2 +- afl-whatsup | 2 +- custom_mutators/gramatron/build_gramatron_mutator.sh | 2 +- custom_mutators/grammar_mutator/build_grammar_mutator.sh | 2 +- frida_mode/Scripting.md | 2 +- frida_mode/test/cmplog/cmplog.c | 2 +- frida_mode/test/deferred/testinstr.c | 2 +- frida_mode/test/dynamic/testinstr.c | 2 +- frida_mode/test/entry_point/testinstr.c | 2 +- frida_mode/test/exe/testinstr.c | 2 +- frida_mode/test/js/test.c | 2 +- frida_mode/test/js/test2.c | 2 +- frida_mode/test/output/testinstr.c | 2 +- frida_mode/test/perf/perf.c | 2 +- frida_mode/test/persistent_ret/testinstr.c | 2 +- frida_mode/test/testinstr/testinstr.c | 2 +- frida_mode/test/unstable/unstable.c | 2 +- include/afl-as.h | 2 +- include/afl-fuzz.h | 2 +- include/afl-prealloc.h | 2 +- include/alloc-inl.h | 2 +- include/cmplog.h | 2 +- include/common.h | 2 +- include/config.h | 2 +- include/debug.h | 2 +- include/forkserver.h | 2 +- include/hash.h | 2 +- include/list.h | 2 +- include/sharedmem.h | 2 +- include/snapshot-inl.h | 2 +- include/types.h | 2 +- include/xxhash.h | 2 +- instrumentation/afl-compiler-rt.o.c | 2 +- instrumentation/afl-gcc-cmplog-pass.so.cc | 2 +- instrumentation/afl-gcc-cmptrs-pass.so.cc | 2 +- instrumentation/afl-gcc-common.h | 2 +- instrumentation/afl-gcc-pass.so.cc | 2 +- instrumentation/afl-llvm-dict2file.so.cc | 2 +- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +- instrumentation/afl-llvm-pass.so.cc | 2 +- instrumentation/cmplog-instructions-pass.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 2 +- instrumentation/cmplog-switches-pass.cc | 2 +- qemu_mode/build_qemu_support.sh | 2 +- qemu_mode/fastexit/Makefile | 2 +- qemu_mode/libcompcov/Makefile | 2 +- qemu_mode/libcompcov/compcovtest.cc | 2 +- qemu_mode/libcompcov/libcompcov.so.c | 2 +- qemu_mode/libqasan/Makefile | 2 +- qemu_mode/libqasan/hooks.c | 2 +- qemu_mode/libqasan/libqasan.c | 2 +- qemu_mode/libqasan/libqasan.h | 2 +- qemu_mode/libqasan/malloc.c | 2 +- qemu_mode/libqasan/patch.c | 2 +- qemu_mode/libqasan/string.c | 2 +- qemu_mode/libqasan/uninstrument.c | 2 +- qemu_mode/unsigaction/Makefile | 2 +- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 2 +- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- test-instr.c | 2 +- unicorn_mode/build_unicorn_support.sh | 2 +- utils/afl_network_proxy/afl-network-client.c | 2 +- utils/afl_network_proxy/afl-network-server.c | 2 +- utils/afl_proxy/afl-proxy.c | 2 +- utils/afl_untracer/afl-untracer.c | 2 +- utils/afl_untracer/libtestinstr.c | 2 +- utils/argv_fuzzing/Makefile | 2 +- utils/argv_fuzzing/argvfuzz.c | 2 +- utils/distributed_fuzzing/sync_script.sh | 2 +- utils/libdislocator/libdislocator.so.c | 2 +- utils/libtokencap/libtokencap.so.c | 2 +- utils/persistent_mode/test-instr.c | 2 +- 94 files changed, 94 insertions(+), 94 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index 95def5aa..d07c26df 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -6,7 +6,7 @@ # Written and maintained by Andrea Fioraldi # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index 28a1a828..4c4e10c4 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -11,7 +11,7 @@ # from Laszlo Szekeres. # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/afl-whatsup b/afl-whatsup index 160a8c74..5546523a 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/custom_mutators/gramatron/build_gramatron_mutator.sh b/custom_mutators/gramatron/build_gramatron_mutator.sh index ff88ff26..c830329e 100755 --- a/custom_mutators/gramatron/build_gramatron_mutator.sh +++ b/custom_mutators/gramatron/build_gramatron_mutator.sh @@ -11,7 +11,7 @@ # Adapted for AFLplusplus by Dominik Maier # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh index 74cae8aa..593cd2dc 100755 --- a/custom_mutators/grammar_mutator/build_grammar_mutator.sh +++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh @@ -14,7 +14,7 @@ # # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/frida_mode/Scripting.md b/frida_mode/Scripting.md index 06d4212c..023e4a19 100644 --- a/frida_mode/Scripting.md +++ b/frida_mode/Scripting.md @@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code... -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c index 7c047ed6..2565b35c 100644 --- a/frida_mode/test/cmplog/cmplog.c +++ b/frida_mode/test/cmplog/cmplog.c @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2022 Google LLC +// Copyright 2019-2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index 7e564a61..0ab44582 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/dynamic/testinstr.c b/frida_mode/test/dynamic/testinstr.c index ad26d060..8b285f6d 100644 --- a/frida_mode/test/dynamic/testinstr.c +++ b/frida_mode/test/dynamic/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index 196b1d84..24d9a615 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c index 334f6518..d965502e 100644 --- a/frida_mode/test/exe/testinstr.c +++ b/frida_mode/test/exe/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c index f6778b6f..87c9cdf6 100644 --- a/frida_mode/test/js/test.c +++ b/frida_mode/test/js/test.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c index 9e9cdbb4..6b680a24 100644 --- a/frida_mode/test/js/test2.c +++ b/frida_mode/test/js/test2.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c index 334f6518..d965502e 100644 --- a/frida_mode/test/output/testinstr.c +++ b/frida_mode/test/output/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/perf/perf.c b/frida_mode/test/perf/perf.c index f6659b55..d9626974 100644 --- a/frida_mode/test/perf/perf.c +++ b/frida_mode/test/perf/perf.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index b2bc19ef..12365ceb 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c index 334f6518..d965502e 100644 --- a/frida_mode/test/testinstr/testinstr.c +++ b/frida_mode/test/testinstr/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index 7d16c26c..a87b6c74 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/include/afl-as.h b/include/afl-as.h index bbbd5582..486314e2 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index ea83aaca..edef9207 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index bdf0d87f..d19a7b52 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 6c2bafff..ae37028e 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/cmplog.h b/include/cmplog.h index c6d2957e..6e16e6b0 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/common.h b/include/common.h index 9d9a948c..b5dbc6de 100644 --- a/include/common.h +++ b/include/common.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/config.h b/include/config.h index b82ead47..b3310270 100644 --- a/include/config.h +++ b/include/config.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/debug.h b/include/debug.h index 566b1d00..cd621a72 100644 --- a/include/debug.h +++ b/include/debug.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/forkserver.h b/include/forkserver.h index a8a7e777..35bc1771 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -12,7 +12,7 @@ Dominik Maier > Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/hash.h b/include/hash.h index d8fef70c..0243c5b7 100644 --- a/include/hash.h +++ b/include/hash.h @@ -15,7 +15,7 @@ Other code written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/list.h b/include/list.h index 72bef749..283bf035 100644 --- a/include/list.h +++ b/include/list.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/sharedmem.h b/include/sharedmem.h index fbe68abe..d32bd845 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h index 8d2f41ff..3864e473 100644 --- a/include/snapshot-inl.h +++ b/include/snapshot-inl.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/types.h b/include/types.h index 96ce78f8..d6476d82 100644 --- a/include/types.h +++ b/include/types.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/xxhash.h b/include/xxhash.h index 4cabc884..7bc0a14e 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2022 Yann Collet + * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index fd5f2d4c..9c6345b6 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -3,7 +3,7 @@ ------------------------------------------------ Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-gcc-cmplog-pass.so.cc b/instrumentation/afl-gcc-cmplog-pass.so.cc index 3c781fd7..b4e6fda9 100644 --- a/instrumentation/afl-gcc-cmplog-pass.so.cc +++ b/instrumentation/afl-gcc-cmplog-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2022 AdaCore + Copyright 2019-2023 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog pass by Andrea Fioraldi , and diff --git a/instrumentation/afl-gcc-cmptrs-pass.so.cc b/instrumentation/afl-gcc-cmptrs-pass.so.cc index 0ddbac15..dbb408b0 100644 --- a/instrumentation/afl-gcc-cmptrs-pass.so.cc +++ b/instrumentation/afl-gcc-cmptrs-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2022 AdaCore + Copyright 2019-2023 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog Routines pass by Andrea Fioraldi diff --git a/instrumentation/afl-gcc-common.h b/instrumentation/afl-gcc-common.h index cda3f9d8..1d5eb466 100644 --- a/instrumentation/afl-gcc-common.h +++ b/instrumentation/afl-gcc-common.h @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AdaCore + Copyright 2019-2023 AdaCore Written by Alexandre Oliva , based on the AFL++ GCC plugin. diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc index ea938a7f..4d7fd0ef 100644 --- a/instrumentation/afl-gcc-pass.so.cc +++ b/instrumentation/afl-gcc-pass.so.cc @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AdaCore + Copyright 2019-2023 AdaCore Written by Alexandre Oliva , based on the AFL LLVM pass by Laszlo Szekeres and Michal diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index fd8baea2..bbbbe32c 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 32b1798a..db5bd55e 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -9,7 +9,7 @@ from afl-as.c are Michal's fault. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index df1ccc4f..e8d0b1e5 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -12,7 +12,7 @@ NGRAM previous location coverage comes from Adrian Herrera. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 084ad8c9..bca1f927 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 9733f86e..0498156d 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 563a4481..cd0ae76d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index f31f3cef..a064fe58 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -13,7 +13,7 @@ # counters by Andrea Fioraldi # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/fastexit/Makefile b/qemu_mode/fastexit/Makefile index 80a5ec48..c7b79277 100644 --- a/qemu_mode/fastexit/Makefile +++ b/qemu_mode/fastexit/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2022 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/Makefile b/qemu_mode/libcompcov/Makefile index cc591393..7260df87 100644 --- a/qemu_mode/libcompcov/Makefile +++ b/qemu_mode/libcompcov/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2022 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc index b2d64f8d..23215013 100644 --- a/qemu_mode/libcompcov/compcovtest.cc +++ b/qemu_mode/libcompcov/compcovtest.cc @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2022 Google LLC +// Copyright 2019-2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index c4107b8c..b6ee0019 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -5,7 +5,7 @@ Written and maintained by Andrea Fioraldi - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/qemu_mode/libqasan/Makefile b/qemu_mode/libqasan/Makefile index 79c3ab70..61782894 100644 --- a/qemu_mode/libqasan/Makefile +++ b/qemu_mode/libqasan/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2022 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index 7f20e848..a9fd0ce9 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.c b/qemu_mode/libqasan/libqasan.c index f4d590bd..12be7778 100644 --- a/qemu_mode/libqasan/libqasan.c +++ b/qemu_mode/libqasan/libqasan.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.h b/qemu_mode/libqasan/libqasan.h index 676f34b0..a430c868 100644 --- a/qemu_mode/libqasan/libqasan.h +++ b/qemu_mode/libqasan/libqasan.h @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/malloc.c b/qemu_mode/libqasan/malloc.c index d81b15e9..d2db3856 100644 --- a/qemu_mode/libqasan/malloc.c +++ b/qemu_mode/libqasan/malloc.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/patch.c b/qemu_mode/libqasan/patch.c index 15c4df15..38e0903b 100644 --- a/qemu_mode/libqasan/patch.c +++ b/qemu_mode/libqasan/patch.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/string.c b/qemu_mode/libqasan/string.c index fc2de1f2..e17cff4b 100644 --- a/qemu_mode/libqasan/string.c +++ b/qemu_mode/libqasan/string.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/uninstrument.c b/qemu_mode/libqasan/uninstrument.c index 1686a015..e37a9b46 100644 --- a/qemu_mode/libqasan/uninstrument.c +++ b/qemu_mode/libqasan/uninstrument.c @@ -7,7 +7,7 @@ for some strange reason. */ /******************************************************************************* -Copyright (c) 2019-2022, Andrea Fioraldi +Copyright (c) 2019-2023, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile index f026a2b7..c1a7397f 100644 --- a/qemu_mode/unsigaction/Makefile +++ b/qemu_mode/unsigaction/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2022 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/afl-analyze.c b/src/afl-analyze.c index a9b5b326..da1def3b 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-as.c b/src/afl-as.c index 1edc8cca..a0eb612f 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-cc.c b/src/afl-cc.c index 1c3b5405..803e784e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-common.c b/src/afl-common.c index 31005804..211d5bf2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a241f2c6..9b8660ce 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index b3a10bb7..485b82db 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index d0c829e2..8967d4bc 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 884bb569..f6de11ae 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ed52ca00..adfc55ad 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index ef30b993..22e5262e 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 9931820a..97855607 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index d8aed8c6..b509b936 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 5017c37c..e3faa392 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 0dae26a3..8da1df13 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 7f9c3bf3..7dd83150 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 8bd465f0..896b5f71 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 87e149de..bfd30845 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index efef5523..138df26c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index eee642fb..144ec9c9 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 5797def8..5438bd9f 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi Dominik Maier - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index b48c6fb3..a2c81586 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index d85c28d9..da6880cc 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-tmin.c b/src/afl-tmin.c index d93b9a41..687bb0e7 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/test-instr.c b/test-instr.c index f304e208..1d9f2e6e 100644 --- a/test-instr.c +++ b/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index a3978d9d..222974cf 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -14,7 +14,7 @@ # # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index 89ca6c4e..0416f0f9 100644 --- a/utils/afl_network_proxy/afl-network-client.c +++ b/utils/afl_network_proxy/afl-network-client.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 8f0e9df9..2ae4c165 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index afd0e5d2..531a97a2 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index 6bee067c..ee40d252 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index a3f5acc8..b7afc325 100644 --- a/utils/afl_untracer/libtestinstr.c +++ b/utils/afl_untracer/libtestinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index f016c5a7..3a4ce084 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -2,7 +2,7 @@ # american fuzzy lop++ - argvfuzz # -------------------------------- # -# Copyright 2019-2022 Kjell Braden +# Copyright 2019-2023 Kjell Braden # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c index e7cc6b72..41eead0c 100644 --- a/utils/argv_fuzzing/argvfuzz.c +++ b/utils/argv_fuzzing/argvfuzz.c @@ -2,7 +2,7 @@ american fuzzy lop++ - LD_PRELOAD for fuzzing argv in binaries ------------------------------------------------------------ - Copyright 2019-2022 Kjell Braden + Copyright 2019-2023 Kjell Braden Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index 251ae4e6..b22816f1 100755 --- a/utils/distributed_fuzzing/sync_script.sh +++ b/utils/distributed_fuzzing/sync_script.sh @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2014 Google Inc. All rights reserved. -# Copyright 2019-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index c390d004..1cd7abc6 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 07d81d59..299056ab 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 168aa429..4ead6577 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: From 8d9620eca29ec1dd6e191cf942341b53e6141db5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 4 Jan 2023 10:21:35 +0100 Subject: [PATCH 056/300] try afl-showmap fix for qemu --- src/afl-showmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index da6880cc..776f77db 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1283,6 +1283,10 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz = map + sizeof(u32); + configure_afl_kill_signals( + fsrv, NULL, NULL, + (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); + if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) { u32 save_be_quiet = be_quiet; @@ -1305,10 +1309,6 @@ int main(int argc, char **argv_orig, char **envp) { : 0); be_quiet = save_be_quiet; - configure_afl_kill_signals( - fsrv, NULL, NULL, - (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); - if (new_map_size) { // only reinitialize when it makes sense From 081c480e36fa6af63f8211e70fa109b56fa5131d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 4 Jan 2023 15:18:14 +0100 Subject: [PATCH 057/300] fix --- utils/argv_fuzzing/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 3a4ce084..9d1fc969 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -55,10 +55,10 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - afl-clang-fast -fsanitize=address -g -o $@ $^ + ../../afl-cc -fsanitize=address -g -o $@ $^ argv_fuzz_demo: argv_fuzz_demo.c - afl-clang-fast -fsanitize=address -g -o $@ $^ + ../../afl-cc -fsanitize=address -g -o $@ $^ demo: argv_fuzz_persistent_demo argv_fuzz_demo From 1c91d8ca79e8177b0a0d08527a29a28a2fc86522 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 4 Jan 2023 17:08:29 +0100 Subject: [PATCH 058/300] code format --- src/afl-showmap.c | 3 +-- utils/afl_untracer/afl-untracer.c | 3 ++- utils/argv_fuzzing/argv_fuzz_persistent_demo.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 776f77db..4e019794 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1284,8 +1284,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz = map + sizeof(u32); configure_afl_kill_signals( - fsrv, NULL, NULL, - (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); + fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) { diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index ee40d252..a18e314e 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -217,7 +217,8 @@ void read_library_information(void) { if (debug) { fprintf(stderr, "%s:%lx (%lx-%lx)\n", liblist[liblist_cnt].name, - (unsigned long)(liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start), + (unsigned long)(liblist[liblist_cnt].addr_end - + liblist[liblist_cnt].addr_start), (unsigned long)liblist[liblist_cnt].addr_start, (unsigned long)(liblist[liblist_cnt].addr_end - 1)); diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c index 08a62c62..016c3d35 100644 --- a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -56,3 +56,4 @@ int main(int argc, char **argv) { return 0; } + From 94d1740390acee396f4615a4a2a518f10f6bc02d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 06:48:07 +0000 Subject: [PATCH 059/300] Fix automatic unicornafl bindings install for python --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/build_unicorn_support.sh | 20 ++++++++++---------- unicorn_mode/unicornafl | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index bba4215c..06cac44c 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -6e00ceac +2df75f3e diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 222974cf..f20f52ef 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -117,21 +117,21 @@ done # some python version should be available now PYTHONS="`command -v python3` `command -v python` `command -v python2`" -SETUPTOOLS_FOUND=0 +PIP_FOUND=0 for PYTHON in $PYTHONS ; do - if $PYTHON -c "import setuptools" ; then + if $PYTHON -c "import pip" ; then - SETUPTOOLS_FOUND=1 + PIP_FOUND=1 PYTHONBIN=$PYTHON break fi done -if [ "0" = $SETUPTOOLS_FOUND ]; then +if [ "0" = $PIP_FOUND ]; then - echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools', or install python3-setuptools, or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ..." + echo "[-] Error: Python pip not found. Run 'sudo apt-get install python-pip', or install python3-pip, or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ..." PREREQ_NOTFOUND=1 fi @@ -199,22 +199,22 @@ echo "[*] Installing Unicorn python bindings..." cd unicorn/bindings/python || exit 1 if [ -z "$VIRTUAL_ENV" ]; then echo "[*] Info: Installing python unicornafl using --user" - THREADS=$CORES $PYTHONBIN setup.py install --user --force --prefix=|| exit 1 + THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1 else echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV" - THREADS=$CORES $PYTHONBIN setup.py install --force || exit 1 + THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1 fi cd ../../../ echo "[*] Installing Unicornafl python bindings..." cd bindings/python || exit 1 if [ -z "$VIRTUAL_ENV" ]; then echo "[*] Info: Installing python unicornafl using --user" - THREADS=$CORES $PYTHONBIN setup.py install --user --force --prefix=|| exit 1 + THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1 else echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV" - THREADS=$CORES $PYTHONBIN setup.py install --force || exit 1 + THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1 fi -echo '[*] If needed, you can (re)install the bindings from `./unicornafl/bindings/python` using `python setup.py install`' +echo '[*] If needed, you can (re)install the bindings in `./unicornafl/bindings/python` using `pip install --force .`' cd ../../ || exit 1 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 6e00ceac..2df75f3e 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 6e00ceac6fd5627e42e1858c543c84f2fbdaedda +Subproject commit 2df75f3e1045367cab95fe3471191b38c1a9f79e From db9fc49ef84c6d60b40b5aa0d2d6a205cf883133 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 07:03:45 +0000 Subject: [PATCH 060/300] Add pip to docker --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8a825b36..fd47a59f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,7 +39,7 @@ RUN apt-get update && \ apt-get -y install --no-install-recommends \ make cmake automake meson ninja-build bison flex \ git xz-utils bzip2 wget jupp nano bash-completion less vim joe ssh psmisc \ - python3 python3-dev python3-setuptools python-is-python3 \ + python3 python3-dev python3-pip python-is-python3 \ libtool libtool-bin libglib2.0-dev \ apt-transport-https gnupg dialog \ gnuplot-nox libpixman-1-dev \ From 885a6fc106757b3968b86f9a4314f662bb04de43 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 5 Jan 2023 12:43:53 +0100 Subject: [PATCH 061/300] 4.05c release --- README.md | 4 ++-- docs/Changelog.md | 11 ++++++----- include/config.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4ff8c514..eeab7aa1 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.04c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.05c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.05a +GitHub version: 4.06a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 6bfb314d..b9376711 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,7 +3,7 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. -### Version ++4.05a (dev) +### Version ++4.05c (release) - MacOS: libdislocator, libtokencap etc. do not work with modern MacOS anymore, but could be patched to work, see this issue if you want to make the effort and send a PR: @@ -11,14 +11,15 @@ - afl-fuzz: - added afl_custom_fuzz_send custom mutator feature. Now your can send fuzz data to the target as you need, e.g. via IPC. - - cmplog mode now has -l R option for random colorization, thanks + - cmplog mode now has a -l R option for random colorization, thanks to guyf2010 for the PR! - queue statistics are written every 30 minutes to - out/NAME/queue_data - likely this will be moved to a debug flag - in the future. + out/NAME/queue_data if compiled with INTROSPECTION + - new env: AFL_FORK_SERVER_KILL_SIGNAL - afl-showmap/afl-cmin - - -t none now translates to -t 120000 (120 seconds) + - `-t none` now translates to `-t 120000` (120 seconds) - unicorn_mode updated + - several minor bugfixes ### Version ++4.04c (release) - fix gramatron and grammar_mutator build scripts diff --git a/include/config.h b/include/config.h index b3310270..67b9f932 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.05a" +#define VERSION "++4.05c" /****************************************************** * * From aa39921e49f9bd20a4cade0ba76688fc31f35b12 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 11:47:25 +0000 Subject: [PATCH 062/300] Update LibAFL custom mutator to latest --- custom_mutators/libafl_base/Cargo.toml | 2 +- custom_mutators/libafl_base/src/lib.rs | 29 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/custom_mutators/libafl_base/Cargo.toml b/custom_mutators/libafl_base/Cargo.toml index 6e40fc39..ac6b0c8f 100644 --- a/custom_mutators/libafl_base/Cargo.toml +++ b/custom_mutators/libafl_base/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libafl = { git = "https://github.com/AFLplusplus/LibAFL.git", rev = "62614ce1016c86e3f00f35b56399292ceabd486b" } +libafl = { git = "https://github.com/AFLplusplus/LibAFL.git", rev = "266677bb88abe75165430f34e7de897c35560504" } custom_mutator = { path = "../rust/custom_mutator", features = ["afl_internals"] } serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib diff --git a/custom_mutators/libafl_base/src/lib.rs b/custom_mutators/libafl_base/src/lib.rs index 6f2db8ca..dc1c5e0c 100644 --- a/custom_mutators/libafl_base/src/lib.rs +++ b/custom_mutators/libafl_base/src/lib.rs @@ -18,10 +18,12 @@ use libafl::{ scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, Mutator, }, - state::{HasCorpus, HasMaxSize, HasMetadata, HasRand, State}, + prelude::UsesInput, + state::{HasCorpus, HasMaxSize, HasMetadata, HasRand, State, UsesState}, Error, }; +#[allow(clippy::identity_op)] const MAX_FILE: usize = 1 * 1024 * 1024; static mut AFL: Option<&'static afl_state> = None; @@ -64,7 +66,11 @@ impl<'de> Deserialize<'de> for AFLCorpus { } } -impl Corpus for AFLCorpus { +impl UsesState for AFLCorpus { + type State = AFLState; +} + +impl Corpus for AFLCorpus { #[inline] fn count(&self) -> usize { afl().queued_items as usize @@ -76,7 +82,11 @@ impl Corpus for AFLCorpus { } #[inline] - fn replace(&mut self, idx: usize, testcase: Testcase) -> Result<(), Error> { + fn replace( + &mut self, + idx: usize, + testcase: Testcase, + ) -> Result, Error> { unimplemented!(); } @@ -92,7 +102,7 @@ impl Corpus for AFLCorpus { entries.entry(idx).or_insert_with(|| { let queue_buf = std::slice::from_raw_parts_mut(afl().queue_buf, self.count()); let entry = queue_buf[idx].as_mut().unwrap(); - let fname = CStr::from_ptr((entry.fname as *mut i8).as_ref().unwrap()) + let fname = CStr::from_ptr((entry.fname.cast::()).as_ref().unwrap()) .to_str() .unwrap() .to_owned(); @@ -127,9 +137,10 @@ pub struct AFLState { } impl AFLState { + #[must_use] pub fn new(seed: u32) -> Self { Self { - rand: StdRand::with_seed(seed as u64), + rand: StdRand::with_seed(u64::from(seed)), corpus: AFLCorpus::default(), metadata: SerdeAnyMap::new(), max_size: MAX_FILE, @@ -153,7 +164,11 @@ impl HasRand for AFLState { } } -impl HasCorpus for AFLState { +impl UsesInput for AFLState { + type Input = BytesInput; +} + +impl HasCorpus for AFLState { type Corpus = AFLCorpus; #[inline] @@ -208,7 +223,7 @@ impl CustomMutator for LibAFLBaseCustomMutator { tokens.push(data.to_vec()); } if !tokens.is_empty() { - state.add_metadata(Tokens::new(tokens)); + state.add_metadata(Tokens::from(tokens)); } Ok(Self { state, From a8b6365a90e09a635907f0c257667e505255910a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 11:49:58 +0000 Subject: [PATCH 063/300] LibAFL custom mutator: unused variables with underscores --- custom_mutators/libafl_base/src/lib.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/custom_mutators/libafl_base/src/lib.rs b/custom_mutators/libafl_base/src/lib.rs index dc1c5e0c..bae11e1f 100644 --- a/custom_mutators/libafl_base/src/lib.rs +++ b/custom_mutators/libafl_base/src/lib.rs @@ -1,5 +1,4 @@ #![cfg(unix)] -#![allow(unused_variables)] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{ @@ -77,21 +76,21 @@ impl Corpus for AFLCorpus { } #[inline] - fn add(&mut self, testcase: Testcase) -> Result { + fn add(&mut self, _testcase: Testcase) -> Result { unimplemented!(); } #[inline] fn replace( &mut self, - idx: usize, - testcase: Testcase, + _idx: usize, + _testcase: Testcase, ) -> Result, Error> { unimplemented!(); } #[inline] - fn remove(&mut self, idx: usize) -> Result>, Error> { + fn remove(&mut self, _idx: usize) -> Result>, Error> { unimplemented!(); } @@ -235,7 +234,7 @@ impl CustomMutator for LibAFLBaseCustomMutator { fn fuzz<'b, 's: 'b>( &'s mut self, buffer: &'b mut [u8], - add_buff: Option<&[u8]>, + _add_buff: Option<&[u8]>, max_size: usize, ) -> Result, Self::Error> { self.state.set_max_size(max_size); From 462e55da0cf2eb572b93f65d1190fdaac874e25c Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 12:12:01 +0000 Subject: [PATCH 064/300] Updated rust custom mutator bindgen, fixed clippy lints --- .../rust/custom_mutator-sys/Cargo.toml | 6 +- .../rust/custom_mutator-sys/build.rs | 4 +- .../rust/custom_mutator-sys/src/lib.rs | 2 + .../rust/custom_mutator/Cargo.toml | 2 +- .../rust/custom_mutator/src/lib.rs | 98 +++++++++---------- custom_mutators/rust/example/Cargo.toml | 2 +- 6 files changed, 57 insertions(+), 57 deletions(-) diff --git a/custom_mutators/rust/custom_mutator-sys/Cargo.toml b/custom_mutators/rust/custom_mutator-sys/Cargo.toml index 104f7df0..e38c972e 100644 --- a/custom_mutators/rust/custom_mutator-sys/Cargo.toml +++ b/custom_mutators/rust/custom_mutator-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "custom_mutator-sys" -version = "0.1.0" +version = "0.1.1" authors = ["Julius Hohnerlein "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] [build-dependencies] -bindgen = "0.56" +bindgen = "0.63" diff --git a/custom_mutators/rust/custom_mutator-sys/build.rs b/custom_mutators/rust/custom_mutator-sys/build.rs index 3c88a90d..ba4390ff 100644 --- a/custom_mutators/rust/custom_mutator-sys/build.rs +++ b/custom_mutators/rust/custom_mutator-sys/build.rs @@ -15,8 +15,8 @@ fn main() { // The input header we would like to generate // bindings for. .header("wrapper.h") - .whitelist_type("afl_state_t") - .blacklist_type(r"u\d+") + .allowlist_type("afl_state_t") + .blocklist_type(r"u\d+") .opaque_type(r"_.*") .opaque_type("FILE") .opaque_type("in_addr(_t)?") diff --git a/custom_mutators/rust/custom_mutator-sys/src/lib.rs b/custom_mutators/rust/custom_mutator-sys/src/lib.rs index a38a13a8..719ac994 100644 --- a/custom_mutators/rust/custom_mutator-sys/src/lib.rs +++ b/custom_mutators/rust/custom_mutator-sys/src/lib.rs @@ -1,5 +1,7 @@ #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::used_underscore_binding)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/custom_mutators/rust/custom_mutator/Cargo.toml b/custom_mutators/rust/custom_mutator/Cargo.toml index 2d3cdbfa..30f764dc 100644 --- a/custom_mutators/rust/custom_mutator/Cargo.toml +++ b/custom_mutators/rust/custom_mutator/Cargo.toml @@ -2,7 +2,7 @@ name = "custom_mutator" version = "0.1.0" authors = ["Julius Hohnerlein "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/custom_mutators/rust/custom_mutator/src/lib.rs b/custom_mutators/rust/custom_mutator/src/lib.rs index f872241e..09ac11f3 100644 --- a/custom_mutators/rust/custom_mutator/src/lib.rs +++ b/custom_mutators/rust/custom_mutator/src/lib.rs @@ -20,7 +20,7 @@ //! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++. //! //! # Access to AFL++ internals -//! This crate has an optional feature "afl_internals", which gives access to AFL++'s internal state. +//! This crate has an optional feature "`afl_internals`", which gives access to AFL++'s internal state. //! The state is passed to [`CustomMutator::init`], when the feature is activated. //! //! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._ @@ -115,7 +115,7 @@ pub mod wrappers { impl FFIContext { fn from(ptr: *mut c_void) -> ManuallyDrop> { assert!(!ptr.is_null()); - ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut Self) }) + ManuallyDrop::new(unsafe { Box::from_raw(ptr.cast::()) }) } fn into_ptr(self: Box) -> *const c_void { @@ -141,27 +141,28 @@ pub mod wrappers { } /// panic handler called for every panic - fn panic_handler(method: &str, panic_info: Box) -> ! { + fn panic_handler(method: &str, panic_info: &Box) -> ! { use std::ops::Deref; - let cause = panic_info - .downcast_ref::() - .map(String::deref) - .unwrap_or_else(|| { + let cause = panic_info.downcast_ref::().map_or_else( + || { panic_info .downcast_ref::<&str>() .copied() .unwrap_or("") - }); - eprintln!("A panic occurred at {}: {}", method, cause); + }, + String::deref, + ); + eprintln!("A panic occurred at {method}: {cause}"); abort() } /// Internal function used in the macro #[cfg(not(feature = "afl_internals"))] + #[must_use] pub fn afl_custom_init_(seed: u32) -> *const c_void { match catch_unwind(|| FFIContext::::new(seed).into_ptr()) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_init", err), + Err(err) => panic_handler("afl_custom_init", &err), } } @@ -176,7 +177,7 @@ pub mod wrappers { FFIContext::::new(afl, seed).into_ptr() }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_init", err), + Err(err) => panic_handler("afl_custom_init", &err), } } @@ -196,32 +197,27 @@ pub mod wrappers { ) -> usize { match catch_unwind(|| { let mut context = FFIContext::::from(data); - if buf.is_null() { - panic!("null buf passed to afl_custom_fuzz") - } - if out_buf.is_null() { - panic!("null out_buf passed to afl_custom_fuzz") - } + + assert!(!buf.is_null(), "null buf passed to afl_custom_fuzz"); + assert!(!out_buf.is_null(), "null out_buf passed to afl_custom_fuzz"); + let buff_slice = slice::from_raw_parts_mut(buf, buf_size); let add_buff_slice = if add_buf.is_null() { None } else { Some(slice::from_raw_parts(add_buf, add_buf_size)) }; - match context.mutator.fuzz(buff_slice, add_buff_slice, max_size) { - Some(buffer) => { - *out_buf = buffer.as_ptr(); - buffer.len() - } - None => { - // return the input buffer with 0-length to let AFL skip this mutation attempt - *out_buf = buf; - 0 - } + if let Some(buffer) = context.mutator.fuzz(buff_slice, add_buff_slice, max_size) { + *out_buf = buffer.as_ptr(); + buffer.len() + } else { + // return the input buffer with 0-length to let AFL skip this mutation attempt + *out_buf = buf; + 0 } }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_fuzz", err), + Err(err) => panic_handler("afl_custom_fuzz", &err), } } @@ -237,9 +233,8 @@ pub mod wrappers { ) -> u32 { match catch_unwind(|| { let mut context = FFIContext::::from(data); - if buf.is_null() { - panic!("null buf passed to afl_custom_fuzz") - } + assert!(!buf.is_null(), "null buf passed to afl_custom_fuzz"); + let buf_slice = slice::from_raw_parts(buf, buf_size); // see https://doc.rust-lang.org/nomicon/borrow-splitting.html let ctx = &mut **context; @@ -247,7 +242,7 @@ pub mod wrappers { mutator.fuzz_count(buf_slice) }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_fuzz_count", err), + Err(err) => panic_handler("afl_custom_fuzz_count", &err), } } @@ -259,25 +254,27 @@ pub mod wrappers { ) -> bool { match catch_unwind(|| { let mut context = FFIContext::::from(data); - if filename_new_queue.is_null() { - panic!("received null filename_new_queue in afl_custom_queue_new_entry"); - } + assert!( + !filename_new_queue.is_null(), + "received null filename_new_queue in afl_custom_queue_new_entry" + ); + let filename_new_queue = Path::new(OsStr::from_bytes( unsafe { CStr::from_ptr(filename_new_queue) }.to_bytes(), )); - let filename_orig_queue = if !filename_orig_queue.is_null() { + let filename_orig_queue = if filename_orig_queue.is_null() { + None + } else { Some(Path::new(OsStr::from_bytes( unsafe { CStr::from_ptr(filename_orig_queue) }.to_bytes(), ))) - } else { - None }; context .mutator .queue_new_entry(filename_new_queue, filename_orig_queue) }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_queue_new_entry", err), + Err(err) => panic_handler("afl_custom_queue_new_entry", &err), } } @@ -292,7 +289,7 @@ pub mod wrappers { ManuallyDrop::into_inner(FFIContext::::from(data)); }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_deinit", err), + Err(err) => panic_handler("afl_custom_deinit", &err), } } @@ -306,13 +303,13 @@ pub mod wrappers { buf.extend_from_slice(res.as_bytes()); buf.push(0); // unwrapping here, as the error case should be extremely rare - CStr::from_bytes_with_nul(&buf).unwrap().as_ptr() + CStr::from_bytes_with_nul(buf).unwrap().as_ptr() } else { null() } }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_introspection", err), + Err(err) => panic_handler("afl_custom_introspection", &err), } } @@ -329,13 +326,13 @@ pub mod wrappers { buf.extend_from_slice(res.as_bytes()); buf.push(0); // unwrapping here, as the error case should be extremely rare - CStr::from_bytes_with_nul(&buf).unwrap().as_ptr() + CStr::from_bytes_with_nul(buf).unwrap().as_ptr() } else { null() } }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_describe", err), + Err(err) => panic_handler("afl_custom_describe", &err), } } @@ -348,12 +345,12 @@ pub mod wrappers { let mut context = FFIContext::::from(data); assert!(!filename.is_null()); - context.mutator.queue_get(Path::new(OsStr::from_bytes( + u8::from(context.mutator.queue_get(Path::new(OsStr::from_bytes( unsafe { CStr::from_ptr(filename) }.to_bytes(), - ))) as u8 + )))) }) { Ok(ret) => ret, - Err(err) => panic_handler("afl_custom_queue_get", err), + Err(err) => panic_handler("afl_custom_queue_get", &err), } } } @@ -373,7 +370,7 @@ macro_rules! _define_afl_custom_init { }; } -/// An exported macro to defined afl_custom_init meant for insternal usage +/// An exported macro to defined `afl_custom_init` meant for internal usage #[cfg(not(feature = "afl_internals"))] #[macro_export] macro_rules! _define_afl_custom_init { @@ -520,9 +517,10 @@ mod sanity_test { export_mutator!(ExampleMutator); } -#[allow(unused_variables)] /// A custom mutator. /// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`]. +#[allow(unused_variables)] +#[allow(clippy::missing_errors_doc)] pub trait CustomMutator { /// The error type. All methods must return the same error type. type Error: Debug; @@ -537,7 +535,7 @@ pub trait CustomMutator { .map(|v| !v.is_empty()) .unwrap_or(false) { - eprintln!("Error in custom mutator: {:?}", err) + eprintln!("Error in custom mutator: {err:?}"); } } diff --git a/custom_mutators/rust/example/Cargo.toml b/custom_mutators/rust/example/Cargo.toml index 070d23b1..9d53ebe5 100644 --- a/custom_mutators/rust/example/Cargo.toml +++ b/custom_mutators/rust/example/Cargo.toml @@ -2,7 +2,7 @@ name = "example_mutator" version = "0.1.0" authors = ["Julius Hohnerlein "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 57e7408774a5276baaecd9dd5a6c73f1cbbf866b Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 12:15:54 +0000 Subject: [PATCH 065/300] add update info to changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index b9376711..7a9b74c5 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,6 +19,7 @@ - afl-showmap/afl-cmin - `-t none` now translates to `-t 120000` (120 seconds) - unicorn_mode updated + - updated rust custom mutator dependencies and LibAFL custom mutator - several minor bugfixes ### Version ++4.04c (release) From a3b56e7280cb5b5cea21c66c40d4390db6f13b8f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 5 Jan 2023 12:25:02 +0000 Subject: [PATCH 066/300] rust custom mutator: mark external fns unsafe --- custom_mutators/rust/custom_mutator/src/lib.rs | 11 +++++------ custom_mutators/rust/example_lain/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/custom_mutators/rust/custom_mutator/src/lib.rs b/custom_mutators/rust/custom_mutator/src/lib.rs index 09ac11f3..3b635eb5 100644 --- a/custom_mutators/rust/custom_mutator/src/lib.rs +++ b/custom_mutators/rust/custom_mutator/src/lib.rs @@ -247,7 +247,7 @@ pub mod wrappers { } /// Internal function used in the macro - pub fn afl_custom_queue_new_entry_( + pub unsafe fn afl_custom_queue_new_entry_( data: *mut c_void, filename_new_queue: *const c_char, filename_orig_queue: *const c_char, @@ -337,7 +337,7 @@ pub mod wrappers { } /// Internal function used in the macro - pub fn afl_custom_queue_get_( + pub unsafe fn afl_custom_queue_get_( data: *mut c_void, filename: *const c_char, ) -> u8 { @@ -441,7 +441,7 @@ macro_rules! export_mutator { } #[no_mangle] - pub extern "C" fn afl_custom_queue_new_entry( + pub unsafe extern "C" fn afl_custom_queue_new_entry( data: *mut ::std::os::raw::c_void, filename_new_queue: *const ::std::os::raw::c_char, filename_orig_queue: *const ::std::os::raw::c_char, @@ -454,7 +454,7 @@ macro_rules! export_mutator { } #[no_mangle] - pub extern "C" fn afl_custom_queue_get( + pub unsafe extern "C" fn afl_custom_queue_get( data: *mut ::std::os::raw::c_void, filename: *const ::std::os::raw::c_char, ) -> u8 { @@ -757,8 +757,7 @@ mod truncate_test { let actual_output = truncate_str_unicode_safe(input, *max_len); assert_eq!( &actual_output, expected_output, - "{:#?} truncated to {} bytes should be {:#?}, but is {:#?}", - input, max_len, expected_output, actual_output + "{input:#?} truncated to {max_len} bytes should be {expected_output:#?}, but is {actual_output:#?}" ); } } diff --git a/custom_mutators/rust/example_lain/Cargo.toml b/custom_mutators/rust/example_lain/Cargo.toml index 29d606a4..c52bf86f 100644 --- a/custom_mutators/rust/example_lain/Cargo.toml +++ b/custom_mutators/rust/example_lain/Cargo.toml @@ -2,7 +2,7 @@ name = "example_lain" version = "0.1.0" authors = ["Julius Hohnerlein "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From e4ff0ebd56d8076abd2413ebfaeb7b5e6c07bc3a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 5 Jan 2023 13:52:32 +0100 Subject: [PATCH 067/300] 4.06a init --- include/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config.h b/include/config.h index 67b9f932..a5a4c473 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.05c" +#define VERSION "++4.06a" /****************************************************** * * From e4b7c4e6c9e71ff20309c66d37def67f0cbb003d Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 11 Jan 2023 21:22:23 +0000 Subject: [PATCH 068/300] afl-gotcpu disable thread_affinity api on macos arm64. --- src/afl-gotcpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 144ec9c9..c5b8a27a 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -174,7 +174,12 @@ int main(int argc, char **argv) { if (c == NULL) PFATAL("cpuset_create failed"); cpuset_set(i, c); - #elif defined(__APPLE__) + #elif defined(__APPLE__) && defined(__x86_64__) + // the api is not workable on arm64, core's principle + // differs significantly hive of core per type vs individual ones. + // Possible TODO: For arm64 is to slightly change the meaning + // of gotcpu since it makes no sense on this platform + // but rather just displaying current policy ? thread_affinity_policy_data_t c = {i}; thread_port_t native_thread = pthread_mach_thread_np(pthread_self()); if (thread_policy_set(native_thread, THREAD_AFFINITY_POLICY, From c3d7612c97db8f6629aff2348d043286f8436227 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 12 Jan 2023 09:56:35 +0100 Subject: [PATCH 069/300] fix macos ci --- utils/argv_fuzzing/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 9d1fc969..6786467a 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -55,10 +55,10 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c - ../../afl-cc -fsanitize=address -g -o $@ $^ + ../../afl-cc -g -o $@ $^ argv_fuzz_demo: argv_fuzz_demo.c - ../../afl-cc -fsanitize=address -g -o $@ $^ + ../../afl-cc -g -o $@ $^ demo: argv_fuzz_persistent_demo argv_fuzz_demo From 75fb918a37ad29b93bd6c220460404dae156fa8c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 12 Jan 2023 11:46:52 +0100 Subject: [PATCH 070/300] skip buiding arm64 container :( --- .github/workflows/container.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 8836997d..4599c335 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -47,8 +47,8 @@ jobs: uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 - with: - platforms: arm64 +# with: +# platforms: arm64 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to docker.io @@ -69,7 +69,8 @@ jobs: uses: docker/build-push-action@v3 with: context: . - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 +# ,linux/arm64 push: true tags: ${{ steps.push-tags.outputs.PUSH_TAGS }} cache-from: type=gha From e3dadbfe0f9fad435a6fa201131315500f1a348a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 13 Jan 2023 18:27:22 +0100 Subject: [PATCH 071/300] autotokens --- custom_mutators/autotokens/Makefile | 7 + custom_mutators/autotokens/autotokens.cpp | 391 ++++++++++++++++++++++ qemu_mode/qemuafl | 2 +- 3 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 custom_mutators/autotokens/Makefile create mode 100644 custom_mutators/autotokens/autotokens.cpp diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile new file mode 100644 index 00000000..1ee7f5c4 --- /dev/null +++ b/custom_mutators/autotokens/Makefile @@ -0,0 +1,7 @@ +all: autotokens.so + +autotokens.so: autotokens.cpp + $(CXX) -O3 -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ../../src/afl-performance.o + +clean: + rm -f autotokens.so *~ core \ No newline at end of file diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp new file mode 100644 index 00000000..afde8c26 --- /dev/null +++ b/custom_mutators/autotokens/autotokens.cpp @@ -0,0 +1,391 @@ +extern "C" { +#include "afl-fuzz.h" +} + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define AUTOTOKENS_DEBUG 1 +#define AUTOTOKENS_LEN_MIN 12 +#define AUTOTOKENS_CHANGE_MIN_PERCENT 5 +#define AUTOTOKENS_CHANGE_MAX_PERCENT 10 + +using namespace std; + +typedef struct my_mutator { + + afl_state *afl; + +} my_mutator_t; + +#define DEBUG \ + if (unlikely(debug)) fprintf + +static afl_state *afl_ptr; +static int debug = AUTOTOKENS_DEBUG; +static u32 current_id = 0; +static unordered_map *> file_mapping; +static unordered_map token_to_id; +static unordered_map id_to_token; +static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); +static regex regex_comment_star("/\\*(.|\n)*?\\*/", + regex::multiline | regex::optimize); +static regex regex_string("\"(.*?)\"|'(.*?')", regex::optimize); +static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); +static regex regex_whitespace(R"([ \t]+)", regex::optimize); +static vector *s; + +extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, + u8 **out_buf, uint8_t *add_buf, + size_t add_buf_size, size_t max_size) { + + DEBUG(stderr, "MUT!\n"); + + if (s == NULL) { return 0; } + + vector m = *s; + u32 i, m_size = (u32)m.size(); + + u32 rounds = MAX(8, MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * afl_ptr->havoc_div / 256)); + DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); + + for (i = 0; i < rounds; ++i) { + + u32 item, new_item; + + switch(rand_below(afl_ptr, 4)) { + /* CHANGE */ + case 0: /* fall through */ + case 1: + item = rand_below(afl_ptr, m_size); + do { + new_item = 1 + rand_below(afl_ptr, current_id); + } while(unlikely(new_item == m[item])); + m[item] = new_item; + break; + /* INSERT (+1 so we insert also after last place) */ + case 2: + new_item = 1 + rand_below(afl_ptr, current_id); + m.insert(m.begin() + rand_below(afl_ptr, m_size + 1), new_item); + ++m_size; + break; + /* ERASE - only if large enough */ + case 3: + if (m_size > 8) { m.erase(m.begin() + rand_below(afl_ptr, m_size)); } + --m_size; + break; + } + + } + + string output; + u32 m_size_1 = m_size - 1; + for (i = 0; i < m_size; ++i) { + output += id_to_token[m[i]]; + if (likely(i < m_size_1)) { output += " "; } + } + + u32 mutated_size = output.size(); + u8 *mutated_out = (u8*)afl_realloc((void**)out_buf, mutated_size); + + if (unlikely(!mutated_out)) { + + *out_buf = NULL; + return 0; + + } + + /* + *out_buf = buf; + return buf_size; + */ + memcpy(mutated_out, output.data(), mutated_size); + *out_buf = mutated_out; + DEBUG(stderr, "MUTATED to %u bytes:\n%s\n---\n", mutated_size, mutated_out); + return mutated_size; + +} + + +/* We are not using afl_custom_queue_new_entry() because not every corpus entry + will be necessarily fuzzed. so we use afl_custom_queue_get() instead */ + +extern "C" unsigned char afl_custom_queue_get(void *data, + const unsigned char *filename) { + + if (likely(!debug)) + if (!afl_ptr->queue_cur->is_ascii) { s = NULL; return 0; } + + vector *structure = NULL; + string fn = (char *)filename; + + auto entry = file_mapping.find(fn); + if (entry == file_mapping.end()) { + + // this input file was not analyzed for tokens yet, so let's do it! + + FILE *fp = fopen((char *)filename, "rb"); + if (!fp) { s = NULL; return 0; } // should not happen + fseek(fp, 0, SEEK_END); + size_t len = (size_t)ftell(fp); + if (len < AUTOTOKENS_LEN_MIN) { + + fclose(fp); + file_mapping[fn] = structure; // NULL ptr so we don't read the file again + DEBUG(stderr, "Too short (%lu) %s\n", len, filename); + s = NULL; + return 0; + + } + + string input; + input.resize(len); + rewind(fp); + fread(input.data(), input.size(), 1, fp); + fclose(fp); + + // DEBUG(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", + // input.size(), filename, input.c_str()); + + input = regex_replace(input, regex_comment_slash, "$2"); + input = regex_replace(input, regex_comment_star, ""); + + DEBUG(stderr, "After replace %lu bytes for %s\n%s\n", input.size(), + filename, input.c_str()); + + /* + u32 spaces = count(input.begin(), input.end(), ' '); + u32 tabs = count(input.begin(), input.end(), '\t'); + u32 linefeeds = count(input.begin(), input.end(), '\n'); + bool ends_with_linefeed = input[input.length() - 1] == '\n'; + DEBUG(stderr, "spaces=%u tabs=%u linefeeds=%u ends=%u\n", spaces, tabs, + linefeeds, ends_with_linefeed); + */ + + // now extract all tokens + vector tokens; + smatch match; + string::const_iterator cur = input.begin(), ende = input.end(), last = cur, + found, prev; + + DEBUG(stderr, "MATCHES:\n"); + while (regex_search(cur, ende, match, regex_string)) { + + prev = cur; + found = match[1].first; + cur = match[1].second; + DEBUG(stderr, + "string \"%s\" found at start %lu offset %lu continue at %lu\n", + match[1].str().c_str(), prev - input.begin(), match.position(), + cur - input.begin()); + if (prev < found) { // there are items between search start and find + sregex_token_iterator it{prev, found, regex_whitespace, -1}; + vector tokenized{it, {}}; + tokenized.erase( + std::remove_if(tokenized.begin(), tokenized.end(), + [](std::string const &s) { return s.size() == 0; }), + tokenized.end()); + tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); + + DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), + input.size()); + for (auto x : tokenized) { + + cerr << x << endl; + + } + + for (auto token : tokenized) { + + string::const_iterator c = token.begin(), e = token.end(), f, p; + smatch m; + + while (regex_search(c, e, m, regex_word)) { + + p = c; + f = m[0].first; + c = m[0].second; + if (p < f) { + + // there are items between search start and find + string foo(p, f); + DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + tokens.push_back(std::string(p, f)); + + } + + DEBUG(stderr, + "SUBstring \"%s\" found at start %lu offset %lu continue at " + "%lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); + tokens.push_back(m[0].str()); + + } + + if (c < e) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + tokens.push_back(std::string(c, e)); + + } + + } + + } + + if (match[1].length() > 0) { tokens.push_back(match[1]); } + + } + + if (cur < ende) { + + DEBUG(stderr, "REST!\n"); + + sregex_token_iterator it{cur, ende, regex_whitespace, -1}; + vector tokenized{it, {}}; + tokenized.erase( + std::remove_if(tokenized.begin(), tokenized.end(), + [](std::string const &s) { return s.size() == 0; }), + tokenized.end()); + tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); + + DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), + input.size()); + for (auto x : tokenized) { + + cerr << x << endl; + + } + + for (auto token : tokenized) { + + string::const_iterator c = token.begin(), e = token.end(), f, p; + smatch m; + + while (regex_search(c, e, m, regex_word)) { + + p = c; + f = m[0].first; + c = m[0].second; + if (p < f) { + + // there are items between search start and find + string foo(p, f); + DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + tokens.push_back(std::string(p, f)); + + } + + DEBUG(stderr, + "SUB2string \"%s\" found at start %lu offset %lu continue at " + "%lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); + tokens.push_back(m[0].str()); + + } + + if (c < e) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + tokens.push_back(std::string(c, e)); + + } + + } + + } + + DEBUG(stderr, "DUMPING TOKENS:\n"); + if (unlikely(debug)) + for (u32 i = 0; i < tokens.size(); ++i) { + + DEBUG(stderr, "%s ", tokens[i].c_str()); + + } + + DEBUG(stderr, "---------------------------\n"); + + /* Now we transform the tokens into an ID list and saved that */ + + structure = new vector(); + u32 id; + + for (u32 i = 0; i < tokens.size(); ++i) { + + if ((id = token_to_id[tokens[i]]) == 0) { + + // First time we see this token, add it to the list + ++current_id; + token_to_id[tokens[i]] = current_id; + id_to_token[current_id] = tokens[i]; + structure->push_back(current_id); + + } else { + + structure->push_back(id); + + } + + } + + // save the token structure to the file mapping + file_mapping[fn] = structure; + s = structure; + + // we are done! + DEBUG(stderr, "DONE! We have %lu tokens in the structure\n", + structure->size()); + + } else { + + if (entry->second == NULL) { + + DEBUG(stderr, "Skipping %s\n", filename); + s = NULL; + return 0; + + } + + s = entry->second; + DEBUG(stderr, "OK %s\n", filename); + + } + + return 1; // we always fuzz unless non-ascii or too small + +} + +extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { + + (void)(seed); + my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t)); + if (!data) { + + perror("afl_custom_init alloc"); + return NULL; + + } + + data->afl = afl_ptr = afl; + + return data; + +} + +extern "C" void afl_custom_deinit(my_mutator_t *data) { + + free(data); + +} + diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index a8af9cbd..a120c3fe 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit a8af9cbde71e333ce72a46f15e655d0b82ed0939 +Subproject commit a120c3feb573d4cade292cdeb7c1f6b1ce109efe From 9548af52b266ecc2aed81f388f7a1a7a3fcfb181 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 14 Jan 2023 09:30:25 +0100 Subject: [PATCH 072/300] texts --- custom_mutators/autotokens/README | 12 ++++++++++++ custom_mutators/autotokens/TODO | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 custom_mutators/autotokens/README create mode 100644 custom_mutators/autotokens/TODO diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README new file mode 100644 index 00000000..6849279e --- /dev/null +++ b/custom_mutators/autotokens/README @@ -0,0 +1,12 @@ +# autotokens + +This implements an improved autotoken idea presented in +[Token-Level Fuzzing][https://www.usenix.org/system/files/sec21-salls.pdf]. +It is a grammar fuzzer without actually knowing the grammar. + +It is recommended to run with together in an instance with `CMPLOG`. + +If you have a dictionary (`-x`) this improves this custom grammar mutator. + +If **not** run with `CMPLOG`, it is possible to set `AFL_CUSTOM_MUTATOR_ONLY`, +to concentrate on grammar bug classes. diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO new file mode 100644 index 00000000..700b3fa7 --- /dev/null +++ b/custom_mutators/autotokens/TODO @@ -0,0 +1,13 @@ +whitespace belassen oder notieren? MAYBE +0=space 1=tab 2=linefeed + +dictionary mitverwenden? JA aber nur ascii +-> neue liste? +wie mache ich das bei honggfuzz? +ansonsten neuer custom mutator entrypoint? + +nur is_ascii wenn cmplog aktiv, ansonsten eigene implementierung +die aber dann dafür sorgt dass eine leere struktur da ist. +is is_ascii in afl-common.o ? + +cmplog: only add tokens that were found to fit? From 7abbc8d7401e4a358986a5ff5d1157f44761e6a7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 15 Jan 2023 08:18:11 +0100 Subject: [PATCH 073/300] ensure out fd is closed in shmem mode --- src/afl-fuzz.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 138df26c..fc335742 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2154,8 +2154,12 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) { + unlink(afl->fsrv.out_file); afl->fsrv.out_file = NULL; afl->fsrv.use_stdin = 0; + close(afl->fsrv.out_fd); + afl->fsrv.out_fd = -1; + if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) { WARNF( From 5163a49350ed17149cb3c52bc79bd87e86402510 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 15 Jan 2023 08:26:15 +0100 Subject: [PATCH 074/300] fix input file deletion --- src/afl-fuzz-init.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index adfc55ad..1182bd41 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1817,17 +1817,35 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (afl->file_extension) { - fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension); + fn = alloc_printf("%s/.cur_input.%s", afl->out_dir, afl->file_extension); } else { - fn = alloc_printf("%s/.cur_input", afl->tmp_dir); + fn = alloc_printf("%s/.cur_input", afl->out_dir); } if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); + if (afl->afl_env.afl_tmpdir) { + + if (afl->file_extension) { + + fn = alloc_printf("%s/.cur_input.%s", afl->afl_env.afl_tmpdir, + afl->file_extension); + + } else { + + fn = alloc_printf("%s/.cur_input", afl->afl_env.afl_tmpdir); + + } + + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } + ck_free(fn); + + } + fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir); if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); From 35801bed7a5feb8cc3a363bafbd577f256c467f6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 15 Jan 2023 13:47:31 +0100 Subject: [PATCH 075/300] dictionary support --- custom_mutators/autotokens/TODO | 17 +- custom_mutators/autotokens/autotokens.cpp | 248 +++++++++++++++++----- include/config.h | 2 +- 3 files changed, 199 insertions(+), 68 deletions(-) diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 700b3fa7..2e5e384f 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -1,13 +1,12 @@ whitespace belassen oder notieren? MAYBE 0=space 1=tab 2=linefeed -dictionary mitverwenden? JA aber nur ascii --> neue liste? -wie mache ich das bei honggfuzz? -ansonsten neuer custom mutator entrypoint? - -nur is_ascii wenn cmplog aktiv, ansonsten eigene implementierung -die aber dann dafür sorgt dass eine leere struktur da ist. -is is_ascii in afl-common.o ? - cmplog: only add tokens that were found to fit? + +create from thin air if no good seed after a cycle and dict large enough? +(static u32 no_of_struct_inputs;) + +splice insert, splice overwrite +(linefeed, semicolon) + + diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index afde8c26..2fad8dd7 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -1,5 +1,7 @@ extern "C" { + #include "afl-fuzz.h" + } #include @@ -13,9 +15,7 @@ extern "C" { #include #define AUTOTOKENS_DEBUG 1 -#define AUTOTOKENS_LEN_MIN 12 -#define AUTOTOKENS_CHANGE_MIN_PERCENT 5 -#define AUTOTOKENS_CHANGE_MAX_PERCENT 10 +#define AUTOTOKENS_CHANGE_MIN 8 using namespace std; @@ -31,43 +31,55 @@ typedef struct my_mutator { static afl_state *afl_ptr; static int debug = AUTOTOKENS_DEBUG; static u32 current_id = 0; +static u32 valid_structures = 0; +static u32 extras_cnt = 0, a_extras_cnt = 0; static unordered_map *> file_mapping; static unordered_map token_to_id; static unordered_map id_to_token; -static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); -static regex regex_comment_star("/\\*(.|\n)*?\\*/", - regex::multiline | regex::optimize); -static regex regex_string("\"(.*?)\"|'(.*?')", regex::optimize); -static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); -static regex regex_whitespace(R"([ \t]+)", regex::optimize); -static vector *s; +static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); +static regex regex_comment_star("/\\*(.|\n)*?\\*/", + regex::multiline | regex::optimize); +static regex regex_string("\"(.*?)\"|'(.*?')", regex::optimize); +static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); +static regex regex_whitespace(R"([ \t]+)", regex::optimize); +static vector *s; // the structure of the currently selected input -extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, - u8 **out_buf, uint8_t *add_buf, - size_t add_buf_size, size_t max_size) { +extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, + u8 **out_buf, u8 *add_buf, + size_t add_buf_size, size_t max_size) { - DEBUG(stderr, "MUT!\n"); + if (s == NULL) { - if (s == NULL) { return 0; } + *out_buf = NULL; + return 0; - vector m = *s; - u32 i, m_size = (u32)m.size(); + } - u32 rounds = MAX(8, MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * afl_ptr->havoc_div / 256)); - DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); + vector m = *s; // copy of the structure we will modify + u32 i, m_size = (u32)m.size(); + + u32 rounds = + MAX(AUTOTOKENS_CHANGE_MIN, + MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * + afl_ptr->havoc_div / 256)); + // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); for (i = 0; i < rounds; ++i) { - + u32 item, new_item; - - switch(rand_below(afl_ptr, 4)) { + + switch (rand_below(afl_ptr, 4)) { + /* CHANGE */ - case 0: /* fall through */ + case 0: /* fall through */ case 1: item = rand_below(afl_ptr, m_size); do { + new_item = 1 + rand_below(afl_ptr, current_id); - } while(unlikely(new_item == m[item])); + + } while (unlikely(new_item == m[item])); + m[item] = new_item; break; /* INSERT (+1 so we insert also after last place) */ @@ -81,31 +93,32 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_s if (m_size > 8) { m.erase(m.begin() + rand_below(afl_ptr, m_size)); } --m_size; break; + // TODO: add full line insert splice, replace splace, delete + } - + } - + string output; - u32 m_size_1 = m_size - 1; + u32 m_size_1 = m_size - 1; + for (i = 0; i < m_size; ++i) { + output += id_to_token[m[i]]; if (likely(i < m_size_1)) { output += " "; } + } u32 mutated_size = output.size(); - u8 *mutated_out = (u8*)afl_realloc((void**)out_buf, mutated_size); + u8 *mutated_out = (u8 *)afl_realloc((void **)out_buf, mutated_size); if (unlikely(!mutated_out)) { - + *out_buf = NULL; return 0; - + } - /* - *out_buf = buf; - return buf_size; - */ memcpy(mutated_out, output.data(), mutated_size); *out_buf = mutated_out; DEBUG(stderr, "MUTATED to %u bytes:\n%s\n---\n", mutated_size, mutated_out); @@ -113,29 +126,106 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_s } - /* We are not using afl_custom_queue_new_entry() because not every corpus entry will be necessarily fuzzed. so we use afl_custom_queue_get() instead */ extern "C" unsigned char afl_custom_queue_get(void *data, const unsigned char *filename) { - if (likely(!debug)) - if (!afl_ptr->queue_cur->is_ascii) { s = NULL; return 0; } + if (likely(!debug)) { + + if (afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) { + + s = NULL; + return 0; + + } + + } + + // check if there are new dictionary entries and add them to the tokens + if (valid_structures) { + + while (extras_cnt < afl_ptr->extras_cnt) { + + u32 ok = 1, l = afl_ptr->extras[extras_cnt].len; + u8 *ptr = afl_ptr->extras[extras_cnt].data; + + for (u32 i = 0; i < l; ++i) { + + if (!isascii((int)ptr[i]) && !isprint((int)ptr[i])) { + + ok = 0; + break; + + } + + } + + if (ok) { + + ++current_id; + token_to_id[(char *)ptr] = current_id; + id_to_token[current_id] = (char *)ptr; + + } + + ++extras_cnt; + DEBUG(stderr, "Added from dictionary: \"%s\"\n", ptr); + + } + + while (a_extras_cnt < afl_ptr->a_extras_cnt) { + + u32 ok = 1, l = afl_ptr->a_extras[a_extras_cnt].len; + u8 *ptr = afl_ptr->a_extras[a_extras_cnt].data; + + for (u32 i = 0; i < l; ++i) { + + if (!isascii((int)ptr[i]) && !isprint((int)ptr[i])) { + + ok = 0; + break; + + } + + } + + if (ok) { + + ++current_id; + token_to_id[(char *)ptr] = current_id; + id_to_token[current_id] = (char *)ptr; + + } + + ++a_extras_cnt; + DEBUG(stderr, "Added from auto dictionary: \"%s\"\n", ptr); + + } + + } vector *structure = NULL; string fn = (char *)filename; + auto entry = file_mapping.find(fn); - auto entry = file_mapping.find(fn); if (entry == file_mapping.end()) { // this input file was not analyzed for tokens yet, so let's do it! FILE *fp = fopen((char *)filename, "rb"); - if (!fp) { s = NULL; return 0; } // should not happen + if (!fp) { + + s = NULL; + return 0; + + } // should not happen + fseek(fp, 0, SEEK_END); size_t len = (size_t)ftell(fp); - if (len < AUTOTOKENS_LEN_MIN) { + + if (len < AFL_TXT_MIN_LEN) { fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again @@ -151,6 +241,30 @@ extern "C" unsigned char afl_custom_queue_get(void *data, fread(input.data(), input.size(), 1, fp); fclose(fp); + if (!afl_ptr->shm.cmplog_mode) { + + // not running with CMPLOG? bad choice, but whatever ... + // we only want text inputs, so we have to check it ourselves. + + u32 valid_chars = 0; + for (u32 i = 0; i < len; ++i) { + + if (isascii((int)input[i]) || isprint((int)input[i])) { ++valid_chars; } + + } + + // we want at least 95% of text characters ... + if (((len * AFL_TXT_MIN_PERCENT) / 100) > valid_chars) { + + file_mapping[fn] = NULL; + DEBUG(stderr, "Not text (%lu) %s\n", len, filename); + s = NULL; + return 0; + + } + + } + // DEBUG(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", // input.size(), filename, input.c_str()); @@ -175,7 +289,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string::const_iterator cur = input.begin(), ende = input.end(), last = cur, found, prev; - DEBUG(stderr, "MATCHES:\n"); while (regex_search(cur, ende, match, regex_string)) { prev = cur; @@ -196,11 +309,12 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), input.size()); - for (auto x : tokenized) { + if (unlikely(debug)) + for (auto x : tokenized) { - cerr << x << endl; + cerr << x << endl; - } + } for (auto token : tokenized) { @@ -232,8 +346,13 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (c < e) { - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + if (unlikely(debug)) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + + } + tokens.push_back(std::string(c, e)); } @@ -248,8 +367,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (cur < ende) { - DEBUG(stderr, "REST!\n"); - sregex_token_iterator it{cur, ende, regex_whitespace, -1}; vector tokenized{it, {}}; tokenized.erase( @@ -260,11 +377,12 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), input.size()); - for (auto x : tokenized) { + if (unlikely(debug)) + for (auto x : tokenized) { - cerr << x << endl; + cerr << x << endl; - } + } for (auto token : tokenized) { @@ -279,8 +397,13 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (p < f) { // there are items between search start and find - string foo(p, f); - DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + if (unlikely(debug)) { + + string foo(p, f); + DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + + } + tokens.push_back(std::string(p, f)); } @@ -296,8 +419,13 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (c < e) { - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + if (unlikely(debug)) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + + } + tokens.push_back(std::string(c, e)); } @@ -306,15 +434,18 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - DEBUG(stderr, "DUMPING TOKENS:\n"); - if (unlikely(debug)) + if (unlikely(debug)) { + + DEBUG(stderr, "DUMPING TOKENS:\n"); for (u32 i = 0; i < tokens.size(); ++i) { DEBUG(stderr, "%s ", tokens[i].c_str()); } - DEBUG(stderr, "---------------------------\n"); + DEBUG(stderr, "---------------------------\n"); + + } /* Now we transform the tokens into an ID list and saved that */ @@ -342,6 +473,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // save the token structure to the file mapping file_mapping[fn] = structure; s = structure; + ++valid_structures; // we are done! DEBUG(stderr, "DONE! We have %lu tokens in the structure\n", diff --git a/include/config.h b/include/config.h index a5a4c473..6cfaac11 100644 --- a/include/config.h +++ b/include/config.h @@ -494,7 +494,7 @@ /* What is the minimum percentage of ascii characters present to be classifed as "is_ascii"? */ -#define AFL_TXT_MIN_PERCENT 94 +#define AFL_TXT_MIN_PERCENT 95 /* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ From 10b82c72772f40f703119fc7cd1c9063500a6bbe Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 15 Jan 2023 18:17:28 +0100 Subject: [PATCH 076/300] fixes --- custom_mutators/autotokens/Makefile | 2 +- custom_mutators/autotokens/autotokens.cpp | 40 ++++++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile index 1ee7f5c4..5dd52dee 100644 --- a/custom_mutators/autotokens/Makefile +++ b/custom_mutators/autotokens/Makefile @@ -1,7 +1,7 @@ all: autotokens.so autotokens.so: autotokens.cpp - $(CXX) -O3 -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ../../src/afl-performance.o + $(CXX) -g -O3 $(CFLAGS) -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ../../src/afl-performance.o clean: rm -f autotokens.so *~ core \ No newline at end of file diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 2fad8dd7..9fbdf52a 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -14,7 +14,7 @@ extern "C" { #include #include -#define AUTOTOKENS_DEBUG 1 +#define AUTOTOKENS_DEBUG 0 #define AUTOTOKENS_CHANGE_MIN 8 using namespace std; @@ -64,11 +64,13 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, afl_ptr->havoc_div / 256)); // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); + u32 max_rand = 4; + for (i = 0; i < rounds; ++i) { u32 item, new_item; - switch (rand_below(afl_ptr, 4)) { + switch (rand_below(afl_ptr, max_rand)) { /* CHANGE */ case 0: /* fall through */ @@ -90,9 +92,19 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, break; /* ERASE - only if large enough */ case 3: - if (m_size > 8) { m.erase(m.begin() + rand_below(afl_ptr, m_size)); } - --m_size; + if (m_size > 8) { + + m.erase(m.begin() + rand_below(afl_ptr, m_size)); + --m_size; + + } else { + + max_rand = 3; + + } + break; + // TODO: add full line insert splice, replace splace, delete } @@ -119,9 +131,16 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } + if (unlikely(debug)) { + + DEBUG(stderr, "MUTATED to %u bytes:\n", mutated_size); + fwrite(output.data(), 1, mutated_size, stderr); + DEBUG(stderr, "\n---\n"); + + } + memcpy(mutated_out, output.data(), mutated_size); *out_buf = mutated_out; - DEBUG(stderr, "MUTATED to %u bytes:\n%s\n---\n", mutated_size, mutated_out); return mutated_size; } @@ -292,11 +311,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, while (regex_search(cur, ende, match, regex_string)) { prev = cur; - found = match[1].first; - cur = match[1].second; - DEBUG(stderr, - "string \"%s\" found at start %lu offset %lu continue at %lu\n", - match[1].str().c_str(), prev - input.begin(), match.position(), + found = match[0].first; + cur = match[0].second; + DEBUG(stderr, "string %s found at start %lu offset %lu continue at %lu\n", + match[0].str().c_str(), prev - input.begin(), match.position(), cur - input.begin()); if (prev < found) { // there are items between search start and find sregex_token_iterator it{prev, found, regex_whitespace, -1}; @@ -361,7 +379,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - if (match[1].length() > 0) { tokens.push_back(match[1]); } + if (match[0].length() > 0) { tokens.push_back(match[0]); } } From 8cc1c6c54edbeb5ac7a8bcb050eb7976009517fa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 16 Jan 2023 10:18:08 +0100 Subject: [PATCH 077/300] nits --- src/afl-fuzz-one.c | 32 +++++++++++++++++++------------- src/afl-fuzz.c | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 97855607..eaf65987 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -584,7 +584,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if it has gone through deterministic testing in earlier, resumed runs (passed_det). */ - if (likely(afl->queue_cur->passed_det) || likely(afl->skip_deterministic) || + if (likely(afl->skip_deterministic) || likely(afl->queue_cur->passed_det) || likely(perf_score < (afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100 ? afl->queue_cur->depth * 30 @@ -1908,9 +1908,10 @@ custom_mutator_stage: afl->stage_name = "custom mutator"; afl->stage_short = "custom"; - afl->stage_max = HAVOC_CYCLES * perf_score / afl->havoc_div / 100; afl->stage_val_type = STAGE_VAL_NONE; bool has_custom_fuzz = false; + u32 shift = unlikely(afl->custom_only) ? 7 : 8; + afl->stage_max = (HAVOC_CYCLES * perf_score / afl->havoc_div) >> shift; if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } @@ -2063,8 +2064,9 @@ havoc_stage: afl->stage_name = "havoc"; afl->stage_short = "havoc"; - afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * - perf_score / afl->havoc_div / 100; + afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * + perf_score / afl->havoc_div) >> + 7; } else { @@ -2073,7 +2075,7 @@ havoc_stage: snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle); afl->stage_name = afl->stage_name_buf; afl->stage_short = "splice"; - afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100; + afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7; } @@ -4621,8 +4623,9 @@ pacemaker_fuzzing: afl->stage_name = MOpt_globals.havoc_stagename; afl->stage_short = MOpt_globals.havoc_stagenameshort; - afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * - perf_score / afl->havoc_div / 100; + afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * + perf_score / afl->havoc_div) >> + 7; } else { @@ -4632,7 +4635,7 @@ pacemaker_fuzzing: MOpt_globals.splice_stageformat, splice_cycle); afl->stage_name = afl->stage_name_buf; afl->stage_short = MOpt_globals.splice_stagenameshort; - afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100; + afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7; } @@ -5792,10 +5795,8 @@ void pso_updating(afl_state_t *afl) { } -/* larger change for MOpt implementation: the original fuzz_one was renamed - to fuzz_one_original. All documentation references to fuzz_one therefore - mean fuzz_one_original */ - +/* The entry point for the mutator, choosing the default mutator, and/or MOpt + depending on the configuration. */ u8 fuzz_one(afl_state_t *afl) { int key_val_lv_1 = 0, key_val_lv_2 = 0; @@ -5818,7 +5819,12 @@ u8 fuzz_one(afl_state_t *afl) { #endif - // if limit_time_sig == -1 then both are run after each other + /* + -L command line paramter => limit_time_sig value + limit_time_sig == 0 then run the default mutator + limit_time_sig > 0 then run MOpt + limit_time_sig < 0 both are run + */ if (afl->limit_time_sig <= 0) { key_val_lv_1 = fuzz_one_original(afl); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 138df26c..5e0ecd1e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1580,6 +1580,29 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { + + if (afl->custom_only) { + + FATAL("Custom mutators are incompatible with MOpt (-L)"); + + } + + u32 custom_fuzz = 0; + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz) { custom_fuzz = 1; } + + }); + + if (custom_fuzz) { + + WARNF("afl_custom_fuzz is incompatible with MOpt (-L)"); + + } + + } + if (afl->afl_env.afl_max_det_extras) { s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras); From 4b915207c42f8100f306778f617d7003c3e2193f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 16 Jan 2023 17:05:04 +0100 Subject: [PATCH 078/300] autotokens - much better tokenizer --- custom_mutators/autotokens/autotokens.cpp | 311 +++++++++++++--------- 1 file changed, 181 insertions(+), 130 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 9fbdf52a..850692a1 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -28,22 +28,41 @@ typedef struct my_mutator { #define DEBUG \ if (unlikely(debug)) fprintf -static afl_state *afl_ptr; -static int debug = AUTOTOKENS_DEBUG; -static u32 current_id = 0; -static u32 valid_structures = 0; -static u32 extras_cnt = 0, a_extras_cnt = 0; +static afl_state *afl_ptr; +static int debug = AUTOTOKENS_DEBUG; +static u32 current_id; +static u32 valid_structures; +static u32 whitespace_ids; +static u32 extras_cnt, a_extras_cnt; +static u64 all_spaces, all_tabs, all_lf, all_ws; static unordered_map *> file_mapping; static unordered_map token_to_id; static unordered_map id_to_token; -static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); -static regex regex_comment_star("/\\*(.|\n)*?\\*/", - regex::multiline | regex::optimize); -static regex regex_string("\"(.*?)\"|'(.*?')", regex::optimize); -static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); -static regex regex_whitespace(R"([ \t]+)", regex::optimize); +// static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); +static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", + regex::multiline | regex::optimize); +static regex regex_string("\"[[:print:]]*?\"|'[[:print:]]*?'", regex::optimize); static vector *s; // the structure of the currently selected input +u32 good_whitespace_or_singleval() { + + u32 i = rand_below(afl_ptr, current_id); + if (id_to_token[i].size() == 1) { return i; } + i = rand_below(afl_ptr, all_ws); + if (i < all_spaces) { + + return 0; + + } else if (i < all_tabs) { + + return 1; + + } else + + return 2; // linefeed + +} + extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { @@ -68,30 +87,76 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, for (i = 0; i < rounds; ++i) { - u32 item, new_item; - switch (rand_below(afl_ptr, max_rand)) { /* CHANGE */ case 0: /* fall through */ - case 1: - item = rand_below(afl_ptr, m_size); + case 1: { + + u32 pos = rand_below(afl_ptr, m_size); + u32 cur_item = m[pos], new_item; do { - new_item = 1 + rand_below(afl_ptr, current_id); + new_item = rand_below(afl_ptr, current_id); - } while (unlikely(new_item == m[item])); + } while (unlikely( - m[item] = new_item; + new_item == cur_item || + (whitespace_ids < new_item && whitespace_ids >= cur_item) || + (whitespace_ids >= new_item && whitespace_ids < cur_item))); + + DEBUG(stderr, "MUT: %u -> %u\n", cur_item, new_item); + m[pos] = new_item; break; - /* INSERT (+1 so we insert also after last place) */ - case 2: - new_item = 1 + rand_below(afl_ptr, current_id); - m.insert(m.begin() + rand_below(afl_ptr, m_size + 1), new_item); + + } + + /* INSERT (m_size +1 so we insert also after last place) */ + case 2: { + + u32 new_item; + do { + + new_item = rand_below(afl_ptr, current_id); + + } while (new_item >= whitespace_ids); + + u32 pos = rand_below(afl_ptr, m_size + 1); + m.insert(m.begin() + pos, new_item); ++m_size; + + // if we insert an identifier or string we might need whitespace + if (id_to_token[new_item].size() > 1) { + + // need to insert before? + + if (pos && m[pos - 1] >= whitespace_ids && + id_to_token[m[pos - 1]].size() > 1) { + + m.insert(m.begin() + pos, good_whitespace_or_singleval()); + ++m_size; + + } + + if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && + id_to_token[m[pos + 1]].size() > 1) { + + // need to insert after? + + m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); + ++m_size; + + } + + } + break; + + } + /* ERASE - only if large enough */ - case 3: + case 3: { + if (m_size > 8) { m.erase(m.begin() + rand_below(afl_ptr, m_size)); @@ -105,6 +170,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, break; + } + // TODO: add full line insert splice, replace splace, delete } @@ -112,12 +179,10 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } string output; - u32 m_size_1 = m_size - 1; for (i = 0; i < m_size; ++i) { output += id_to_token[m[i]]; - if (likely(i < m_size_1)) { output += " "; } } @@ -183,9 +248,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (ok) { - ++current_id; token_to_id[(char *)ptr] = current_id; id_to_token[current_id] = (char *)ptr; + ++current_id; } @@ -212,9 +277,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (ok) { - ++current_id; token_to_id[(char *)ptr] = current_id; id_to_token[current_id] = (char *)ptr; + ++current_id; } @@ -257,7 +322,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string input; input.resize(len); rewind(fp); - fread(input.data(), input.size(), 1, fp); + fread((void *)input.data(), input.size(), 1, fp); fclose(fp); if (!afl_ptr->shm.cmplog_mode) { @@ -287,28 +352,34 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // DEBUG(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", // input.size(), filename, input.c_str()); - input = regex_replace(input, regex_comment_slash, "$2"); + // input = regex_replace(input, regex_comment_slash, "$2"); input = regex_replace(input, regex_comment_star, ""); DEBUG(stderr, "After replace %lu bytes for %s\n%s\n", input.size(), filename, input.c_str()); - /* - u32 spaces = count(input.begin(), input.end(), ' '); - u32 tabs = count(input.begin(), input.end(), '\t'); - u32 linefeeds = count(input.begin(), input.end(), '\n'); + u32 spaces = count(input.begin(), input.end(), ' '); + u32 tabs = count(input.begin(), input.end(), '\t'); + u32 linefeeds = count(input.begin(), input.end(), '\n'); bool ends_with_linefeed = input[input.length() - 1] == '\n'; DEBUG(stderr, "spaces=%u tabs=%u linefeeds=%u ends=%u\n", spaces, tabs, linefeeds, ends_with_linefeed); - */ + all_spaces += spaces; + all_tabs += tabs; + all_lf += linefeeds; + all_ws = all_spaces + all_tabs + all_lf; // now extract all tokens vector tokens; smatch match; - string::const_iterator cur = input.begin(), ende = input.end(), last = cur, - found, prev; + string::const_iterator cur = input.begin(), ende = input.end(), found, prev; - while (regex_search(cur, ende, match, regex_string)) { + DEBUG(stderr, "START!\n"); + + while (regex_search(cur, ende, match, regex_string, + regex_constants::match_any | + regex_constants::match_not_null | + regex_constants::match_continuous)) { prev = cur; found = match[0].first; @@ -316,62 +387,42 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUG(stderr, "string %s found at start %lu offset %lu continue at %lu\n", match[0].str().c_str(), prev - input.begin(), match.position(), cur - input.begin()); + if (prev < found) { // there are items between search start and find - sregex_token_iterator it{prev, found, regex_whitespace, -1}; - vector tokenized{it, {}}; - tokenized.erase( - std::remove_if(tokenized.begin(), tokenized.end(), - [](std::string const &s) { return s.size() == 0; }), - tokenized.end()); - tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); + while (prev < found) { - DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), - input.size()); - if (unlikely(debug)) - for (auto x : tokenized) { + if (isspace(*prev)) { - cerr << x << endl; + auto start = prev; + while (isspace(*prev)) { - } - - for (auto token : tokenized) { - - string::const_iterator c = token.begin(), e = token.end(), f, p; - smatch m; - - while (regex_search(c, e, m, regex_word)) { - - p = c; - f = m[0].first; - c = m[0].second; - if (p < f) { - - // there are items between search start and find - string foo(p, f); - DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); - tokens.push_back(std::string(p, f)); + ++prev; } - DEBUG(stderr, - "SUBstring \"%s\" found at start %lu offset %lu continue at " - "%lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); - tokens.push_back(m[0].str()); + tokens.push_back(std::string(start, prev)); + DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); - } + } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { - if (c < e) { + auto start = prev; + while (isalnum(*prev) || *prev == '$' || *prev == '_' || + *prev == '.' || *prev == '/') { - if (unlikely(debug)) { - - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + ++prev; } - tokens.push_back(std::string(c, e)); + tokens.push_back(std::string(start, prev)); + DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); + + } else { + + tokens.push_back(std::string(prev, prev + 1)); + DEBUG(stderr, "OTHER \"%c\"\n", *prev); + ++prev; } @@ -383,68 +434,44 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } + DEBUG(stderr, "AFTER all strings\n"); + if (cur < ende) { - sregex_token_iterator it{cur, ende, regex_whitespace, -1}; - vector tokenized{it, {}}; - tokenized.erase( - std::remove_if(tokenized.begin(), tokenized.end(), - [](std::string const &s) { return s.size() == 0; }), - tokenized.end()); - tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); + while (cur < ende) { - DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), - input.size()); - if (unlikely(debug)) - for (auto x : tokenized) { + if (isspace(*cur)) { - cerr << x << endl; + auto start = cur; + while (isspace(*cur)) { - } - - for (auto token : tokenized) { - - string::const_iterator c = token.begin(), e = token.end(), f, p; - smatch m; - - while (regex_search(c, e, m, regex_word)) { - - p = c; - f = m[0].first; - c = m[0].second; - if (p < f) { - - // there are items between search start and find - if (unlikely(debug)) { - - string foo(p, f); - DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(p, f)); + ++cur; } - DEBUG(stderr, - "SUB2string \"%s\" found at start %lu offset %lu continue at " - "%lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); - tokens.push_back(m[0].str()); + tokens.push_back(std::string(start, cur)); + DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); - } + } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { - if (c < e) { + auto start = cur; + while (isalnum(*cur) || *cur == '$' || *cur == '_' || *cur == '.' || + *cur == '/') { - if (unlikely(debug)) { - - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + ++cur; } - tokens.push_back(std::string(c, e)); + tokens.push_back(std::string(start, cur)); + DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); + + } else { + + tokens.push_back(std::string(cur, cur + 1)); + DEBUG(stderr, "OTHER \"%c\"\n", *cur); + ++cur; } @@ -457,7 +484,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUG(stderr, "DUMPING TOKENS:\n"); for (u32 i = 0; i < tokens.size(); ++i) { - DEBUG(stderr, "%s ", tokens[i].c_str()); + DEBUG(stderr, "%s", tokens[i].c_str()); } @@ -475,10 +502,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if ((id = token_to_id[tokens[i]]) == 0) { // First time we see this token, add it to the list - ++current_id; token_to_id[tokens[i]] = current_id; id_to_token[current_id] = tokens[i]; structure->push_back(current_id); + ++current_id; } else { @@ -529,6 +556,30 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { data->afl = afl_ptr = afl; + // set common whitespace tokens + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t"] = current_id; + id_to_token[current_id] = "\t"; + ++current_id; + token_to_id["\n"] = current_id; + id_to_token[current_id] = "\n"; + ++current_id; + token_to_id["\r\n"] = current_id; + id_to_token[current_id] = "\r\n"; + ++current_id; + token_to_id[" \n"] = current_id; + id_to_token[current_id] = " \n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t"] = current_id; + id_to_token[current_id] = "\t\t"; + ++current_id; + whitespace_ids = current_id; + return data; } From 33f41e3974348d3b0b71b3a30a6483bb0418068c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 17 Jan 2023 09:52:35 +0100 Subject: [PATCH 079/300] autotokens: print stats at exit --- custom_mutators/autotokens/README | 7 ++++--- custom_mutators/autotokens/autotokens.cpp | 12 ++++++++++++ include/config.h | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index 6849279e..0dcc6a3e 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -1,6 +1,6 @@ # autotokens -This implements an improved autotoken idea presented in +This implements an improved autotoken grammar fuzzing idea presented in [Token-Level Fuzzing][https://www.usenix.org/system/files/sec21-salls.pdf]. It is a grammar fuzzer without actually knowing the grammar. @@ -8,5 +8,6 @@ It is recommended to run with together in an instance with `CMPLOG`. If you have a dictionary (`-x`) this improves this custom grammar mutator. -If **not** run with `CMPLOG`, it is possible to set `AFL_CUSTOM_MUTATOR_ONLY`, -to concentrate on grammar bug classes. +If **not** running with `CMPLOG`, it is possible to set +`AFL_CUSTOM_MUTATOR_ONLY` to concentrate on grammar bug classes. + diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 850692a1..d6b269fd 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -35,6 +35,7 @@ static u32 valid_structures; static u32 whitespace_ids; static u32 extras_cnt, a_extras_cnt; static u64 all_spaces, all_tabs, all_lf, all_ws; +static u64 all_structure_items; static unordered_map *> file_mapping; static unordered_map token_to_id; static unordered_map id_to_token; @@ -519,6 +520,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = structure; s = structure; ++valid_structures; + all_structure_items += structure->size(); // we are done! DEBUG(stderr, "DONE! We have %lu tokens in the structure\n", @@ -586,6 +588,16 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { extern "C" void afl_custom_deinit(my_mutator_t *data) { + /* we use this to print statistics at exit :-) + needs to be stderr as stdout is filtered */ + + fprintf(stderr, + "\n\nAutotoken mutator statistics:\n" + " Number of all seen tokens: %lu\n" + " Number of input structures: %lu\n" + " Number of all items in structures: %lu\n\n", + current_id - 1, valid_structures, all_structure_items); + free(data); } diff --git a/include/config.h b/include/config.h index 6cfaac11..f8a742f2 100644 --- a/include/config.h +++ b/include/config.h @@ -364,9 +364,9 @@ * * ***********************************************************/ -/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ +/* Call count interval between reseeding the PRNG from /dev/urandom: */ -#define RESEED_RNG 100000 +#define RESEED_RNG 2500000 /* The default maximum testcase cache size in MB, 0 = disable. A value between 50 and 250 is a good default value. Note that the From efe57c936880608a2de452340d63f262470d9fcd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 17 Jan 2023 09:57:23 +0100 Subject: [PATCH 080/300] more whitespace --- custom_mutators/autotokens/autotokens.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index d6b269fd..5580512a 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -559,6 +559,8 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { data->afl = afl_ptr = afl; // set common whitespace tokens + // we deliberately do not put uncommon ones here to these will count as + // identifier tokens. token_to_id[" "] = current_id; id_to_token[current_id] = " "; ++current_id; @@ -580,6 +582,21 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { token_to_id["\t\t"] = current_id; id_to_token[current_id] = "\t\t"; ++current_id; + token_to_id["\n\n"] = current_id; + id_to_token[current_id] = "\n\n"; + ++current_id; + token_to_id["\r\n\r\n"] = current_id; + id_to_token[current_id] = "\r\n\r\n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t\t\t"] = current_id; + id_to_token[current_id] = "\t\t\t\t"; + ++current_id; + token_to_id["\n\n\n\n"] = current_id; + id_to_token[current_id] = "\n\n\n\n"; + ++current_id; whitespace_ids = current_id; return data; From a41fd5cc5c4a5073f38adf06270e2985c88da9d5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 11:46:28 +0100 Subject: [PATCH 081/300] alternate tokenize, options --- custom_mutators/autotokens/README | 9 + custom_mutators/autotokens/autotokens.cpp | 432 ++++++++++++++++++---- 2 files changed, 365 insertions(+), 76 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index 0dcc6a3e..f6e9c753 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -11,3 +11,12 @@ If you have a dictionary (`-x`) this improves this custom grammar mutator. If **not** running with `CMPLOG`, it is possible to set `AFL_CUSTOM_MUTATOR_ONLY` to concentrate on grammar bug classes. +## Configuration via environment variables + +`AUTOTOKENS_ONLY_FAV` - only use this mutator on favorite queue items +`AUTOTOKENS_COMMENT` - what character or string starts a comment which will be + removed. Default: `/* ... */` +`AUTOTOKENS_ALTERNATIVE_TOKENIZE` - use an alternative tokenize implementation + (experimental) +`AUTOTOKENS_WHITESPACE` - whitespace string to use for ALTERNATIVE_TOKENIZE, + default is " " diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 5580512a..28ef91e2 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -15,7 +15,10 @@ extern "C" { #include #define AUTOTOKENS_DEBUG 0 +#define AUTOTOKENS_ONLY_FAV 0 +#define AUTOTOKENS_ALTERNATIVE_TOKENIZE 0 #define AUTOTOKENS_CHANGE_MIN 8 +#define AUTOTOKENS_WHITESPACE " " using namespace std; @@ -30,6 +33,8 @@ typedef struct my_mutator { static afl_state *afl_ptr; static int debug = AUTOTOKENS_DEBUG; +static int only_fav = AUTOTOKENS_ONLY_FAV; +static int alternative_tokenize = AUTOTOKENS_ALTERNATIVE_TOKENIZE; static u32 current_id; static u32 valid_structures; static u32 whitespace_ids; @@ -39,9 +44,12 @@ static u64 all_structure_items; static unordered_map *> file_mapping; static unordered_map token_to_id; static unordered_map id_to_token; -// static regex regex_comment_slash("(//.*)([\r\n]?)", regex::optimize); +static string whitespace = AUTOTOKENS_WHITESPACE; +static regex *regex_comment_custom; static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", regex::multiline | regex::optimize); +static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); +static regex regex_whitespace(R"([ \t]+)", regex::optimize); static regex regex_string("\"[[:print:]]*?\"|'[[:print:]]*?'", regex::optimize); static vector *s; // the structure of the currently selected input @@ -84,15 +92,15 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, afl_ptr->havoc_div / 256)); // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); - u32 max_rand = 4; + u32 max_rand = 7; for (i = 0; i < rounds; ++i) { switch (rand_below(afl_ptr, max_rand)) { /* CHANGE */ - case 0: /* fall through */ - case 1: { + case 0 ... 3: /* fall through */ + { u32 pos = rand_below(afl_ptr, m_size); u32 cur_item = m[pos], new_item; @@ -103,8 +111,9 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } while (unlikely( new_item == cur_item || - (whitespace_ids < new_item && whitespace_ids >= cur_item) || - (whitespace_ids >= new_item && whitespace_ids < cur_item))); + (!alternative_tokenize && + ((whitespace_ids < new_item && whitespace_ids >= cur_item) || + (whitespace_ids >= new_item && whitespace_ids < cur_item))))); DEBUG(stderr, "MUT: %u -> %u\n", cur_item, new_item); m[pos] = new_item; @@ -113,7 +122,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } /* INSERT (m_size +1 so we insert also after last place) */ - case 2: { + case 4 ... 5: { u32 new_item; do { @@ -126,26 +135,30 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, m.insert(m.begin() + pos, new_item); ++m_size; - // if we insert an identifier or string we might need whitespace - if (id_to_token[new_item].size() > 1) { + if (likely(!alternative_tokenize)) { - // need to insert before? + // if we insert an identifier or string we might need whitespace + if (id_to_token[new_item].size() > 1) { - if (pos && m[pos - 1] >= whitespace_ids && - id_to_token[m[pos - 1]].size() > 1) { + // need to insert before? - m.insert(m.begin() + pos, good_whitespace_or_singleval()); - ++m_size; + if (pos && m[pos - 1] >= whitespace_ids && + id_to_token[m[pos - 1]].size() > 1) { - } + m.insert(m.begin() + pos, good_whitespace_or_singleval()); + ++m_size; - if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && - id_to_token[m[pos + 1]].size() > 1) { + } - // need to insert after? + if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && + id_to_token[m[pos + 1]].size() > 1) { - m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); - ++m_size; + // need to insert after? + + m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); + ++m_size; + + } } @@ -156,7 +169,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } /* ERASE - only if large enough */ - case 3: { + case 6: { if (m_size > 8) { @@ -165,7 +178,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } else { - max_rand = 3; + max_rand = 6; } @@ -180,10 +193,16 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } string output; + u32 m_size_1 = m_size - 1; for (i = 0; i < m_size; ++i) { output += id_to_token[m[i]]; + if (unlikely(alternative_tokenize && i < m_size_1)) { + + output += whitespace; + + } } @@ -219,7 +238,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (likely(!debug)) { - if (afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) { + if ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || + (only_fav && !afl_ptr->queue_cur->favored)) { s = NULL; return 0; @@ -353,8 +373,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // DEBUG(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", // input.size(), filename, input.c_str()); - // input = regex_replace(input, regex_comment_slash, "$2"); - input = regex_replace(input, regex_comment_star, ""); + if (regex_comment_custom) { + + input = regex_replace(input, *regex_comment_custom, "$2"); + + } else { + + input = regex_replace(input, regex_comment_star, ""); + + } DEBUG(stderr, "After replace %lu bytes for %s\n%s\n", input.size(), filename, input.c_str()); @@ -377,53 +404,105 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUG(stderr, "START!\n"); - while (regex_search(cur, ende, match, regex_string, - regex_constants::match_any | - regex_constants::match_not_null | - regex_constants::match_continuous)) { + if (likely(!alternative_tokenize)) { - prev = cur; - found = match[0].first; - cur = match[0].second; - DEBUG(stderr, "string %s found at start %lu offset %lu continue at %lu\n", - match[0].str().c_str(), prev - input.begin(), match.position(), - cur - input.begin()); + while (regex_search(cur, ende, match, regex_string, + regex_constants::match_any | + regex_constants::match_not_null | + regex_constants::match_continuous)) { - if (prev < found) { // there are items between search start and find - while (prev < found) { + prev = cur; + found = match[0].first; + cur = match[0].second; + DEBUG(stderr, + "string %s found at start %lu offset %lu continue at %lu\n", + match[0].str().c_str(), prev - input.begin(), match.position(), + cur - input.begin()); - if (isspace(*prev)) { + if (prev < found) { // there are items between search start and find + while (prev < found) { - auto start = prev; - while (isspace(*prev)) { + if (isspace(*prev)) { + auto start = prev; + while (isspace(*prev)) { + + ++prev; + + } + + tokens.push_back(std::string(start, prev)); + DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); + + } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { + + auto start = prev; + while (isalnum(*prev) || *prev == '$' || *prev == '_' || + *prev == '.' || *prev == '/') { + + ++prev; + + } + + tokens.push_back(std::string(start, prev)); + DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); + + } else { + + tokens.push_back(std::string(prev, prev + 1)); + DEBUG(stderr, "OTHER \"%c\"\n", *prev); ++prev; } - tokens.push_back(std::string(start, prev)); - DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, + } + + } + + if (match[0].length() > 0) { tokens.push_back(match[0]); } + + } + + DEBUG(stderr, "AFTER all strings\n"); + + if (cur < ende) { + + while (cur < ende) { + + if (isspace(*cur)) { + + auto start = cur; + while (isspace(*cur)) { + + ++cur; + + } + + tokens.push_back(std::string(start, cur)); + DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, tokens[tokens.size() - 1].c_str()); - } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { + } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { - auto start = prev; - while (isalnum(*prev) || *prev == '$' || *prev == '_' || - *prev == '.' || *prev == '/') { + auto start = cur; + while (isalnum(*cur) || *cur == '$' || *cur == '_' || *cur == '.' || + *cur == '/') { - ++prev; + ++cur; } - tokens.push_back(std::string(start, prev)); - DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, + tokens.push_back(std::string(start, cur)); + DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, tokens[tokens.size() - 1].c_str()); } else { - tokens.push_back(std::string(prev, prev + 1)); - DEBUG(stderr, "OTHER \"%c\"\n", *prev); - ++prev; + tokens.push_back(std::string(cur, cur + 1)); + DEBUG(stderr, "OTHER \"%c\"\n", *cur); + ++cur; } @@ -431,48 +510,227 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - if (match[0].length() > 0) { tokens.push_back(match[0]); } + } else { - } + // alternative tokenize - DEBUG(stderr, "AFTER all strings\n"); + while (regex_search(cur, ende, match, regex_string)) { - if (cur < ende) { + prev = cur; + found = match[0].first; + cur = match[0].second; + DEBUG(stderr, + "string %s found at start %lu offset %lu continue at %lu\n", + match[0].str().c_str(), prev - input.begin(), match.position(), + cur - input.begin()); + if (prev < found) { // there are items between search start and find + sregex_token_iterator it{prev, found, regex_whitespace, -1}; + vector tokenized{it, {}}; + tokenized.erase(std::remove_if(tokenized.begin(), tokenized.end(), + [](std::string const &s) { - while (cur < ende) { + return s.size() == 0; - if (isspace(*cur)) { + }), - auto start = cur; - while (isspace(*cur)) { + tokenized.end()); + tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); - ++cur; + if (unlikely(debug)) { + + DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), + input.size()); + for (auto x : tokenized) { + + cerr << x << endl; + + } } - tokens.push_back(std::string(start, cur)); - DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, - tokens[tokens.size() - 1].c_str()); + for (auto token : tokenized) { - } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { + string::const_iterator c = token.begin(), e = token.end(), f, p; + smatch m; - auto start = cur; - while (isalnum(*cur) || *cur == '$' || *cur == '_' || *cur == '.' || - *cur == '/') { + while (regex_search(c, e, m, regex_word)) { - ++cur; + p = c; + f = m[0].first; + c = m[0].second; + if (p < f) { + + // there are items between search start and find + while (p < f) { + + if (unlikely(debug)) { + + string foo(p, p + 1); + DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + + } + + tokens.push_back(std::string(p, p + 1)); + ++p; + + } + + /* + string foo(p, f); + DEBUG(stderr, "before string: \"%s\"\n", + foo.c_str()); tokens.push_back(std::string(p, f)); + */ + + } + + DEBUG( + stderr, + "SUBstring \"%s\" found at start %lu offset %lu continue at " + "%lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); + tokens.push_back(m[0].str()); + + } + + if (c < e) { + + while (c < e) { + + if (unlikely(debug)) { + + string foo(c, c + 1); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + + } + + tokens.push_back(std::string(c, c + 1)); + ++c; + + } + + /* + if (unlikely(debug)) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", + foo.c_str()); + + } + + tokens.push_back(std::string(c, e)); + */ + + } } - tokens.push_back(std::string(start, cur)); - DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, - tokens[tokens.size() - 1].c_str()); + } - } else { + if (match[0].length() > 0) { tokens.push_back(match[0]); } - tokens.push_back(std::string(cur, cur + 1)); - DEBUG(stderr, "OTHER \"%c\"\n", *cur); - ++cur; + } + + if (cur < ende) { + + sregex_token_iterator it{cur, ende, regex_whitespace, -1}; + vector tokenized{it, {}}; + tokenized.erase( + std::remove_if(tokenized.begin(), tokenized.end(), + [](std::string const &s) { return s.size() == 0; }), + tokenized.end()); + tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); + + if (unlikely(debug)) { + + DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), + input.size()); + for (auto x : tokenized) { + + cerr << x << endl; + + } + + } + + for (auto token : tokenized) { + + string::const_iterator c = token.begin(), e = token.end(), f, p; + smatch m; + + while (regex_search(c, e, m, regex_word)) { + + p = c; + f = m[0].first; + c = m[0].second; + if (p < f) { + + // there are items between search start and find + while (p < f) { + + if (unlikely(debug)) { + + string foo(p, p + 1); + DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + + } + + tokens.push_back(std::string(p, p + 1)); + ++p; + + } + + /* + if (unlikely(debug)) { + + string foo(p, f); + DEBUG(stderr, "before string: \"%s\"\n", + foo.c_str()); + + } + + tokens.push_back(std::string(p, f)); + */ + + } + + DEBUG(stderr, + "SUB2string \"%s\" found at start %lu offset %lu continue at " + "%lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); + tokens.push_back(m[0].str()); + + } + + if (c < e) { + + while (c < e) { + + if (unlikely(debug)) { + + string foo(c, c + 1); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + + } + + tokens.push_back(std::string(c, c + 1)); + ++c; + + } + + /* + if (unlikely(debug)) { + + string foo(c, e); + DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + + } + + tokens.push_back(std::string(c, e)); + */ + + } } @@ -483,9 +741,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (unlikely(debug)) { DEBUG(stderr, "DUMPING TOKENS:\n"); + u32 size_1 = tokens.size() - 1; for (u32 i = 0; i < tokens.size(); ++i) { DEBUG(stderr, "%s", tokens[i].c_str()); + if (unlikely(alternative_tokenize && i < size_1)) { + + DEBUG(stderr, "%s", whitespace.c_str()); + + } } @@ -556,6 +820,22 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { } + if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } + if (getenv("AUTOTOKENS_ALTERNATIVE_TOKENIZE")) { alternative_tokenize = 1; } + if (getenv("AUTOTOKENS_WHITESPACE")) { + + whitespace = getenv("AUTOTOKENS_WHITESPACE"); + + } + + if (getenv("AUTOTOKENS_COMMENT")) { + + char buf[256]; + snprintf(buf, sizeof(buf), "(%s.*)([\r\n]?)", getenv("AUTOTOKENS_COMMENT")); + regex_comment_custom = new regex(buf, regex::optimize); + + } + data->afl = afl_ptr = afl; // set common whitespace tokens From 70f4b456faf8e361f6e0a34246708380c94cb36e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 13:58:27 +0100 Subject: [PATCH 082/300] fixes --- custom_mutators/autotokens/Makefile | 7 ++++++- custom_mutators/autotokens/autotokens.cpp | 24 ++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile index 5dd52dee..8af63635 100644 --- a/custom_mutators/autotokens/Makefile +++ b/custom_mutators/autotokens/Makefile @@ -1,7 +1,12 @@ +ifdef debug + CFLAGS += "-fsanitize=address -Wall" + CXX := clang++ +endif + all: autotokens.so autotokens.so: autotokens.cpp $(CXX) -g -O3 $(CFLAGS) -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ../../src/afl-performance.o clean: - rm -f autotokens.so *~ core \ No newline at end of file + rm -f autotokens.so *~ core diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 28ef91e2..57c35846 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -48,7 +48,7 @@ static string whitespace = AUTOTOKENS_WHITESPACE; static regex *regex_comment_custom; static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", regex::multiline | regex::optimize); -static regex regex_word("[A-Za-z0-9_$]+", regex::optimize); +static regex regex_word("[A-Za-z0-9_$.-]+", regex::optimize); static regex regex_whitespace(R"([ \t]+)", regex::optimize); static regex regex_string("\"[[:print:]]*?\"|'[[:print:]]*?'", regex::optimize); static vector *s; // the structure of the currently selected input @@ -514,7 +514,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // alternative tokenize - while (regex_search(cur, ende, match, regex_string)) { + while (regex_search(cur, ende, match, regex_string, + regex_constants::match_any | + regex_constants::match_not_null | + regex_constants::match_continuous)) { prev = cur; found = match[0].first; @@ -553,7 +556,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string::const_iterator c = token.begin(), e = token.end(), f, p; smatch m; - while (regex_search(c, e, m, regex_word)) { + while (regex_search(c, e, m, regex_word, + regex_constants::match_any | + regex_constants::match_not_null | + regex_constants::match_continuous)) { p = c; f = m[0].first; @@ -658,7 +664,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string::const_iterator c = token.begin(), e = token.end(), f, p; smatch m; - while (regex_search(c, e, m, regex_word)) { + while (regex_search(c, e, m, regex_word, + regex_constants::match_any | + regex_constants::match_not_null | + regex_constants::match_continuous)) { p = c; f = m[0].first; @@ -820,6 +829,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { } + if (getenv("AUTOTOKENS_DEBUG")) { debug = 1; } if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } if (getenv("AUTOTOKENS_ALTERNATIVE_TOKENIZE")) { alternative_tokenize = 1; } if (getenv("AUTOTOKENS_WHITESPACE")) { @@ -890,9 +900,9 @@ extern "C" void afl_custom_deinit(my_mutator_t *data) { fprintf(stderr, "\n\nAutotoken mutator statistics:\n" - " Number of all seen tokens: %lu\n" - " Number of input structures: %lu\n" - " Number of all items in structures: %lu\n\n", + " Number of all seen tokens: %u\n" + " Number of input structures: %u\n" + " Number of all items in structures: %llu\n\n", current_id - 1, valid_structures, all_structure_items); free(data); From 0db662db7b433a08b01de7f5a989843450919b88 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 14:21:44 +0100 Subject: [PATCH 083/300] fix --- custom_mutators/autotokens/autotokens.cpp | 78 ++++++++++++----------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 57c35846..94f86413 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -851,43 +851,47 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { // set common whitespace tokens // we deliberately do not put uncommon ones here to these will count as // identifier tokens. - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t"] = current_id; - id_to_token[current_id] = "\t"; - ++current_id; - token_to_id["\n"] = current_id; - id_to_token[current_id] = "\n"; - ++current_id; - token_to_id["\r\n"] = current_id; - id_to_token[current_id] = "\r\n"; - ++current_id; - token_to_id[" \n"] = current_id; - id_to_token[current_id] = " \n"; - ++current_id; - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t\t"] = current_id; - id_to_token[current_id] = "\t\t"; - ++current_id; - token_to_id["\n\n"] = current_id; - id_to_token[current_id] = "\n\n"; - ++current_id; - token_to_id["\r\n\r\n"] = current_id; - id_to_token[current_id] = "\r\n\r\n"; - ++current_id; - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t\t\t\t"] = current_id; - id_to_token[current_id] = "\t\t\t\t"; - ++current_id; - token_to_id["\n\n\n\n"] = current_id; - id_to_token[current_id] = "\n\n\n\n"; - ++current_id; - whitespace_ids = current_id; + if (!alternative_tokenize) { + + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t"] = current_id; + id_to_token[current_id] = "\t"; + ++current_id; + token_to_id["\n"] = current_id; + id_to_token[current_id] = "\n"; + ++current_id; + token_to_id["\r\n"] = current_id; + id_to_token[current_id] = "\r\n"; + ++current_id; + token_to_id[" \n"] = current_id; + id_to_token[current_id] = " \n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t"] = current_id; + id_to_token[current_id] = "\t\t"; + ++current_id; + token_to_id["\n\n"] = current_id; + id_to_token[current_id] = "\n\n"; + ++current_id; + token_to_id["\r\n\r\n"] = current_id; + id_to_token[current_id] = "\r\n\r\n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t\t\t"] = current_id; + id_to_token[current_id] = "\t\t\t\t"; + ++current_id; + token_to_id["\n\n\n\n"] = current_id; + id_to_token[current_id] = "\n\n\n\n"; + ++current_id; + whitespace_ids = current_id; + + } return data; From 22f757a169d3da3081306c0f861ef99a509073fe Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 14:33:06 +0100 Subject: [PATCH 084/300] fix --- custom_mutators/autotokens/autotokens.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 94f86413..7aecb010 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -129,7 +129,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, new_item = rand_below(afl_ptr, current_id); - } while (new_item >= whitespace_ids); + } while (!alternative_tokenize && new_item >= whitespace_ids); u32 pos = rand_below(afl_ptr, m_size + 1); m.insert(m.begin() + pos, new_item); From 8fe5e29104fc514551bbc926c5142dac68562b43 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 14:56:26 +0100 Subject: [PATCH 085/300] ignore timeout env option --- docs/env_variables.md | 3 +++ include/afl-fuzz.h | 2 +- include/envs.h | 1 + src/afl-fuzz-bitmap.c | 6 ++++++ src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 3 ++- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index 22a5c386..0a57d190 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -354,6 +354,9 @@ checks or alter some of the more exotic semantics of the tool: - Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach new coverage + - On the contrary, if you are not interested in any timeouts, you can set + `AFL_IGNORE_TIMEOUTS` to get a bit of speed instead. + - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behavior which does not allow crashes or timeout seeds in the initial -i corpus. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index edef9207..69fea579 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -398,7 +398,7 @@ typedef struct afl_env_vars { afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme, - afl_no_startup_calibration; + afl_ignore_timeouts, afl_no_startup_calibration; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index f4cdf390..0770f94d 100644 --- a/include/envs.h +++ b/include/envs.h @@ -103,6 +103,7 @@ static char *afl_environment_variables[] = { "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS", + "AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_INPUT_LEN_MIN", diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 485b82db..b4e9537e 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -457,6 +457,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(len == 0)) { return 0; } + if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { + + return 0; + + } + u8 fn[PATH_MAX]; u8 *queue_fn = ""; u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 896b5f71..104b1e4b 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -292,6 +292,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_ignore_problems = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_IGNORE_TIMEOUTS", + + afl_environment_variable_len)) { + + afl->afl_env.afl_ignore_timeouts = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 5e0ecd1e..4db55b5e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -258,8 +258,9 @@ static void usage(u8 *argv0, int more_help) { "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in ms)\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_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n" + "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n" + "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n" "AFL_PIZZA_MODE: 1 - enforce pizza mode, 0 - disable for April 1st\n" From 14d8eb9e40a6329abcb2f153174b543349c68c13 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 22:17:14 +0100 Subject: [PATCH 086/300] autotoken: splicing; splice_optout --- custom_mutators/autotokens/Makefile | 6 +- custom_mutators/autotokens/autotokens.cpp | 103 ++++++++++++++++++++-- docs/custom_mutators.md | 11 +++ include/afl-fuzz.h | 14 +++ src/afl-fuzz-mutators.c | 13 +++ src/afl-fuzz-one.c | 3 +- src/afl-fuzz-python.c | 16 ++++ 7 files changed, 155 insertions(+), 11 deletions(-) diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile index 8af63635..ab1da4b6 100644 --- a/custom_mutators/autotokens/Makefile +++ b/custom_mutators/autotokens/Makefile @@ -1,5 +1,9 @@ ifdef debug - CFLAGS += "-fsanitize=address -Wall" + CFLAGS += -fsanitize=address -Wall + CXX := clang++ +endif +ifdef DEBUG + CFLAGS += -fsanitize=address -Wall CXX := clang++ endif diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 7aecb010..c9ec4352 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -19,6 +19,13 @@ extern "C" { #define AUTOTOKENS_ALTERNATIVE_TOKENIZE 0 #define AUTOTOKENS_CHANGE_MIN 8 #define AUTOTOKENS_WHITESPACE " " +#define AUTOTOKENS_SIZE_MIN 8 +#define AUTOTOKENS_SPLICE_MIN 4 +#define AUTOTOKENS_SPLICE_MAX 64 + +#if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN + #error SPLICE_MIN must be lower than SIZE_MIN +#endif using namespace std; @@ -42,6 +49,7 @@ static u32 extras_cnt, a_extras_cnt; static u64 all_spaces, all_tabs, all_lf, all_ws; static u64 all_structure_items; static unordered_map *> file_mapping; +static unordered_map *> id_mapping; static unordered_map token_to_id; static unordered_map id_to_token; static string whitespace = AUTOTOKENS_WHITESPACE; @@ -76,6 +84,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { + (void)(data); + if (s == NULL) { *out_buf = NULL; @@ -92,14 +102,14 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, afl_ptr->havoc_div / 256)); // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); - u32 max_rand = 7; + u32 max_rand = 14; for (i = 0; i < rounds; ++i) { switch (rand_below(afl_ptr, max_rand)) { /* CHANGE */ - case 0 ... 3: /* fall through */ + case 0 ... 7: /* fall through */ { u32 pos = rand_below(afl_ptr, m_size); @@ -122,18 +132,19 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } /* INSERT (m_size +1 so we insert also after last place) */ - case 4 ... 5: { + case 8 ... 9: { u32 new_item; do { new_item = rand_below(afl_ptr, current_id); - } while (!alternative_tokenize && new_item >= whitespace_ids); + } while (unlikely(!alternative_tokenize && new_item >= whitespace_ids)); u32 pos = rand_below(afl_ptr, m_size + 1); m.insert(m.begin() + pos, new_item); ++m_size; + DEBUG(stderr, "INS: %u at %u\n", new_item, pos); if (likely(!alternative_tokenize)) { @@ -168,8 +179,63 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } + /* SPLICING */ + case 10 ... 11: { + + u32 strategy = rand_below(afl_ptr, 4), dst_off, n; + auto src = id_mapping[rand_below(afl_ptr, valid_structures)]; + u32 src_size = src->size(); + u32 src_off = rand_below(afl_ptr, src_size - AUTOTOKENS_SPLICE_MIN); + u32 rand_r = 1 + MAX(AUTOTOKENS_SPLICE_MIN, + MIN(AUTOTOKENS_SPLICE_MAX, src_size - src_off)); + + switch (strategy) { + + // insert + case 0: { + + dst_off = rand_below(afl_ptr, m_size); + n = AUTOTOKENS_SPLICE_MIN + + rand_below(afl_ptr, MIN(AUTOTOKENS_SPLICE_MAX, + rand_r - AUTOTOKENS_SPLICE_MIN)); + m.insert(m.begin() + dst_off, src->begin() + src_off, + src->begin() + src_off + n); + m_size += n; + DEBUG(stderr, "SPLICE-INS: %u at %u\n", n, dst_off); + break; + + } + + // overwrite + default: { + + dst_off = rand_below(afl_ptr, m_size - AUTOTOKENS_SPLICE_MIN); + n = AUTOTOKENS_SPLICE_MIN + + rand_below( + afl_ptr, + MIN(AUTOTOKENS_SPLICE_MAX - AUTOTOKENS_SPLICE_MIN, + MIN(m_size - dst_off - AUTOTOKENS_SPLICE_MIN, + src_size - src_off - AUTOTOKENS_SPLICE_MIN))); + + for (u32 i = 0; i < n; ++i) { + + m[dst_off + i] = (*src)[src_off + i]; + + } + + DEBUG(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); + break; + + } + + } + + break; + + } + /* ERASE - only if large enough */ - case 6: { + case 12 ... 13: { if (m_size > 8) { @@ -178,7 +244,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } else { - max_rand = 6; + max_rand = 12; } @@ -236,12 +302,15 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, extern "C" unsigned char afl_custom_queue_get(void *data, const unsigned char *filename) { + (void)(data); + if (likely(!debug)) { if ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || (only_fav && !afl_ptr->queue_cur->favored)) { s = NULL; + DEBUG(stderr, "cmplog not ascii or only_fav and not favorite\n"); return 0; } @@ -334,8 +403,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again - DEBUG(stderr, "Too short (%lu) %s\n", len, filename); s = NULL; + DEBUG(stderr, "Too short (%lu) %s\n", len, filename); return 0; } @@ -362,8 +431,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (((len * AFL_TXT_MIN_PERCENT) / 100) > valid_chars) { file_mapping[fn] = NULL; - DEBUG(stderr, "Not text (%lu) %s\n", len, filename); s = NULL; + DEBUG(stderr, "Not text (%lu) %s\n", len, filename); return 0; } @@ -766,6 +835,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } + if (tokens.size() < AUTOTOKENS_SIZE_MIN) { + + file_mapping[fn] = NULL; + s = NULL; + DEBUG(stderr, "too few tokens\n"); + return 0; + + } + /* Now we transform the tokens into an ID list and saved that */ structure = new vector(); @@ -791,8 +869,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // save the token structure to the file mapping file_mapping[fn] = structure; - s = structure; + id_mapping[valid_structures] = structure; ++valid_structures; + s = structure; all_structure_items += structure->size(); // we are done! @@ -897,6 +976,12 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { } +extern "C" void afl_custom_splice_optout(my_mutator_t *data) { + + (void)(data); + +} + extern "C" void afl_custom_deinit(my_mutator_t *data) { /* we use this to print statistics at exit :-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 4ffeda7a..322caa5b 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -48,6 +48,7 @@ C/C++: ```c void *afl_custom_init(afl_state_t *afl, unsigned int seed); unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size); +void afl_custom_splice_optout(void *data); size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size); const char *afl_custom_describe(void *data, size_t max_description_len); size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf); @@ -72,6 +73,9 @@ def init(seed): def fuzz_count(buf): return cnt +def splice_optout() + pass + def fuzz(buf, add_buf, max_size): return mutated_out @@ -132,6 +136,13 @@ def deinit(): # optional for Python for a specific queue entry, use this function. This function is most useful if `AFL_CUSTOM_MUTATOR_ONLY` is **not** used. +- `splice_optout` (optional): + + If this function is present, no splicing target is passed to the `fuzz` + function. This saves time if splicing data is not needed by the custom + fuzzing function. + This function is never called, just needs to be present to activate. + - `fuzz` (optional): This method performs custom mutations on a given input. It also accepts an diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 69fea579..1e8d085d 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -344,6 +344,7 @@ enum { /* 12 */ PY_FUNC_INTROSPECTION, /* 13 */ PY_FUNC_DESCRIBE, /* 14 */ PY_FUNC_FUZZ_SEND, + /* 15 */ PY_FUNC_SPLICE_OPTOUT, PY_FUNC_COUNT }; @@ -495,6 +496,7 @@ typedef struct afl_state { no_unlink, /* do not unlink cur_input */ debug, /* Debug mode */ custom_only, /* Custom mutator only mode */ + custom_splice_optout, /* Custom mutator no splice buffer */ is_main_node, /* if this is the main node */ is_secondary_node, /* if this is a secondary instance */ pizza_is_served; /* pizza mode */ @@ -828,6 +830,17 @@ struct custom_mutator { */ u32 (*afl_custom_fuzz_count)(void *data, const u8 *buf, size_t buf_size); + /** + * Opt-out of a splicing input for the fuzz mutator + * + * Empty dummy function. It's presence tells afl-fuzz not to pass a + * splice data pointer and len. + * + * @param data pointer returned in afl_custom_init by this custom mutator + * @noreturn + */ + void (*afl_custom_splice_optout)(void *data); + /** * Perform custom mutations on a given input * @@ -1057,6 +1070,7 @@ u8 havoc_mutation_probability_py(void *); u8 queue_get_py(void *, const u8 *); const char *introspection_py(void *); u8 queue_new_entry_py(void *, const u8 *, const u8 *); +void splice_optout(void *); void deinit_py(void *); #endif diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 22e5262e..ce43064a 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -358,6 +358,19 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { } + /* "afl_custom_splice_optout", optional, never called */ + mutator->afl_custom_splice_optout = dlsym(dh, "afl_custom_splice_optout"); + if (!mutator->afl_custom_splice_optout) { + + ACTF("optional symbol 'afl_custom_splice_optout' not found."); + + } else { + + OKF("Found 'afl_custom_splice_optout'."); + afl->custom_splice_optout = 1; + + } + /* "afl_custom_fuzz_send", optional */ mutator->afl_custom_fuzz_send = dlsym(dh, "afl_custom_fuzz_send"); if (!mutator->afl_custom_fuzz_send) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index eaf65987..5e352dcb 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1954,7 +1954,8 @@ custom_mutator_stage: u32 target_len = 0; /* check if splicing makes sense yet (enough entries) */ - if (likely(afl->ready_for_splicing_count > 1)) { + if (likely(!afl->custom_splice_optout && + afl->ready_for_splicing_count > 1)) { /* Pick a random other queue entry for passing to external API that has the necessary length */ diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index b509b936..69c305f7 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -248,6 +248,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "queue_get"); py_functions[PY_FUNC_FUZZ_SEND] = PyObject_GetAttrString(py_module, "fuzz_send"); + py_functions[PY_FUNC_SPLICE_OPTOUT] = + PyObject_GetAttrString(py_module, "splice_optout"); py_functions[PY_FUNC_QUEUE_NEW_ENTRY] = PyObject_GetAttrString(py_module, "queue_new_entry"); py_functions[PY_FUNC_INTROSPECTION] = @@ -394,6 +396,13 @@ void deinit_py(void *py_mutator) { } +void splice_optout_py(void *py_mutator) { + + // this is never called + (void)(py_mutator); + +} + struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module_name) { @@ -474,6 +483,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, } + if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { + + mutator->afl_custom_splice_optout = splice_optout_py; + afl->custom_splice_optout = 1; + + } + if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) { mutator->afl_custom_queue_new_entry = queue_new_entry_py; From 17752465e6b3c70fd0104fae7bb1f84c1cb8bb66 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 22:31:55 +0100 Subject: [PATCH 087/300] nit --- custom_mutators/autotokens/README | 2 ++ custom_mutators/autotokens/TODO | 8 +------- custom_mutators/autotokens/autotokens.cpp | 7 ++----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index f6e9c753..f82dcd98 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -11,6 +11,8 @@ If you have a dictionary (`-x`) this improves this custom grammar mutator. If **not** running with `CMPLOG`, it is possible to set `AFL_CUSTOM_MUTATOR_ONLY` to concentrate on grammar bug classes. +Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! + ## Configuration via environment variables `AUTOTOKENS_ONLY_FAV` - only use this mutator on favorite queue items diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 2e5e384f..95b79373 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -1,12 +1,6 @@ -whitespace belassen oder notieren? MAYBE -0=space 1=tab 2=linefeed - cmplog: only add tokens that were found to fit? create from thin air if no good seed after a cycle and dict large enough? (static u32 no_of_struct_inputs;) -splice insert, splice overwrite -(linefeed, semicolon) - - +splicing -> check if whitespace/token is needed \ No newline at end of file diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index c9ec4352..5e683455 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -217,11 +217,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, MIN(m_size - dst_off - AUTOTOKENS_SPLICE_MIN, src_size - src_off - AUTOTOKENS_SPLICE_MIN))); - for (u32 i = 0; i < n; ++i) { - - m[dst_off + i] = (*src)[src_off + i]; - - } + copy(src->begin() + src_off, src->begin() + src_off + n, + m.begin() + dst_off); DEBUG(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); break; From 45567791c66e128361a7533481b385497ced881f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 23:09:16 +0100 Subject: [PATCH 088/300] autotokens: define disable splice --- custom_mutators/autotokens/autotokens.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 5e683455..f6ab9ddd 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -22,6 +22,7 @@ extern "C" { #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 +#define AUTOTOKENS_SPLICE_DISABLE 0 #if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN #error SPLICE_MIN must be lower than SIZE_MIN @@ -102,7 +103,13 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, afl_ptr->havoc_div / 256)); // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); - u32 max_rand = 14; +#if AUTOTOKENS_SPLICE_DISABLE == 1 + #define AUTOTOKENS_MUT_MAX 12 +#else + #define AUTOTOKENS_MUT_MAX 14 +#endif + + u32 max_rand = AUTOTOKENS_MUT_MAX; for (i = 0; i < rounds; ++i) { @@ -179,6 +186,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } +#if AUTOTOKENS_SPLICE_DISABLE != 1 /* SPLICING */ case 10 ... 11: { @@ -230,9 +238,10 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, break; } +#endif /* ERASE - only if large enough */ - case 12 ... 13: { + default: { if (m_size > 8) { @@ -241,7 +250,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } else { - max_rand = 12; + max_rand = AUTOTOKENS_MUT_MAX - 2; } From 151a8facae2048a26c65658dfec507233a677fb0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 18 Jan 2023 23:16:18 +0100 Subject: [PATCH 089/300] autotokens: stats --- custom_mutators/autotokens/autotokens.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index f6ab9ddd..4f3289c9 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -22,7 +22,9 @@ extern "C" { #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 -#define AUTOTOKENS_SPLICE_DISABLE 0 +#ifndef AUTOTOKENS_SPLICE_DISABLE + #define AUTOTOKENS_SPLICE_DISABLE 0 +#endif #if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN #error SPLICE_MIN must be lower than SIZE_MIN @@ -49,6 +51,7 @@ static u32 whitespace_ids; static u32 extras_cnt, a_extras_cnt; static u64 all_spaces, all_tabs, all_lf, all_ws; static u64 all_structure_items; +static u64 fuzz_count; static unordered_map *> file_mapping; static unordered_map *> id_mapping; static unordered_map token_to_id; @@ -238,6 +241,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, break; } + #endif /* ERASE - only if large enough */ @@ -298,6 +302,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, memcpy(mutated_out, output.data(), mutated_size); *out_buf = mutated_out; + ++fuzz_count; return mutated_size; } @@ -997,8 +1002,9 @@ extern "C" void afl_custom_deinit(my_mutator_t *data) { "\n\nAutotoken mutator statistics:\n" " Number of all seen tokens: %u\n" " Number of input structures: %u\n" - " Number of all items in structures: %llu\n\n", - current_id - 1, valid_structures, all_structure_items); + " Number of all items in structures: %llu\n" + " Number of total fuzzes: %llu\n\n", + current_id - 1, valid_structures, all_structure_items, fuzz_count); free(data); From eeca3a0b2939c605497e9b3a615ee4a466f4a3f2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 19 Jan 2023 11:52:19 +0100 Subject: [PATCH 090/300] lots of fixes --- custom_mutators/autotokens/TODO | 2 +- custom_mutators/autotokens/autotokens.cpp | 424 ++++++++++++++-------- docs/custom_mutators.md | 1 + include/afl-fuzz.h | 11 +- src/afl-fuzz-one.c | 3 +- 5 files changed, 279 insertions(+), 162 deletions(-) diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 95b79373..2e39511c 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -3,4 +3,4 @@ cmplog: only add tokens that were found to fit? create from thin air if no good seed after a cycle and dict large enough? (static u32 no_of_struct_inputs;) -splicing -> check if whitespace/token is needed \ No newline at end of file +splicing -> check if whitespace/token is needed diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 4f3289c9..102bea0f 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -38,8 +38,10 @@ typedef struct my_mutator { } my_mutator_t; -#define DEBUG \ +#undef DEBUGF +#define DEBUGF \ if (unlikely(debug)) fprintf +#define IFDEBUG if (unlikely(debug)) static afl_state *afl_ptr; static int debug = AUTOTOKENS_DEBUG; @@ -57,12 +59,12 @@ static unordered_map *> id_mapping; static unordered_map token_to_id; static unordered_map id_to_token; static string whitespace = AUTOTOKENS_WHITESPACE; +static string output; static regex *regex_comment_custom; -static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", - regex::multiline | regex::optimize); -static regex regex_word("[A-Za-z0-9_$.-]+", regex::optimize); -static regex regex_whitespace(R"([ \t]+)", regex::optimize); -static regex regex_string("\"[[:print:]]*?\"|'[[:print:]]*?'", regex::optimize); +static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", + regex::multiline | regex::optimize); +static regex regex_word("[A-Za-z0-9_$.-]+", regex::optimize); +static regex regex_whitespace(R"([ \t]+)", regex::optimize); static vector *s; // the structure of the currently selected input u32 good_whitespace_or_singleval() { @@ -104,7 +106,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, MAX(AUTOTOKENS_CHANGE_MIN, MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * afl_ptr->havoc_div / 256)); - // DEBUG(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); + // DEBUGF(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); #if AUTOTOKENS_SPLICE_DISABLE == 1 #define AUTOTOKENS_MUT_MAX 12 @@ -112,7 +114,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, #define AUTOTOKENS_MUT_MAX 14 #endif - u32 max_rand = AUTOTOKENS_MUT_MAX; + u32 max_rand = AUTOTOKENS_MUT_MAX, new_item, pos; for (i = 0; i < rounds; ++i) { @@ -122,8 +124,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, case 0 ... 7: /* fall through */ { - u32 pos = rand_below(afl_ptr, m_size); - u32 cur_item = m[pos], new_item; + pos = rand_below(afl_ptr, m_size); + u32 cur_item = m[pos]; do { new_item = rand_below(afl_ptr, current_id); @@ -135,7 +137,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, ((whitespace_ids < new_item && whitespace_ids >= cur_item) || (whitespace_ids >= new_item && whitespace_ids < cur_item))))); - DEBUG(stderr, "MUT: %u -> %u\n", cur_item, new_item); + DEBUGF(stderr, "MUT: %u -> %u\n", cur_item, new_item); m[pos] = new_item; break; @@ -144,7 +146,6 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, /* INSERT (m_size +1 so we insert also after last place) */ case 8 ... 9: { - u32 new_item; do { new_item = rand_below(afl_ptr, current_id); @@ -154,7 +155,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u32 pos = rand_below(afl_ptr, m_size + 1); m.insert(m.begin() + pos, new_item); ++m_size; - DEBUG(stderr, "INS: %u at %u\n", new_item, pos); + DEBUGF(stderr, "INS: %u at %u\n", new_item, pos); if (likely(!alternative_tokenize)) { @@ -212,7 +213,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, m.insert(m.begin() + dst_off, src->begin() + src_off, src->begin() + src_off + n); m_size += n; - DEBUG(stderr, "SPLICE-INS: %u at %u\n", n, dst_off); + DEBUGF(stderr, "SPLICE-INS: %u at %u\n", n, dst_off); + break; } @@ -231,13 +233,36 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, copy(src->begin() + src_off, src->begin() + src_off + n, m.begin() + dst_off); - DEBUG(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); + DEBUGF(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); break; } } + if (likely(!alternative_tokenize)) { + + // do we need a whitespace/token at the beginning? + if (dst_off && id_to_token[m[dst_off - 1]].size() > 1 && + id_to_token[m[dst_off]].size() > 1) { + + m.insert(m.begin() + dst_off, good_whitespace_or_singleval()); + ++m_size; + + } + + // do we need a whitespace/token at the end? + if (dst_off + n < m_size && + id_to_token[m[dst_off + n - 1]].size() > 1 && + id_to_token[m[dst_off + n]].size() > 1) { + + m.insert(m.begin() + dst_off + n, good_whitespace_or_singleval()); + ++m_size; + + } + + } + break; } @@ -249,11 +274,32 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, if (m_size > 8) { - m.erase(m.begin() + rand_below(afl_ptr, m_size)); - --m_size; + do { + + pos = rand_below(afl_ptr, m_size); + + } while (unlikely(pos < whitespace_ids)); + + // if what we delete will result in a missing whitespace/token, + // instead of deleting we switch the item to a whitespace or token. + if (likely(!alternative_tokenize) && pos && pos < m_size && + id_to_token[m[pos - 1]].size() > 1 && + id_to_token[m[pos + 1]].size() > 1) { + + m[pos] = good_whitespace_or_singleval(); + + } else { + + m.erase(m.begin() + pos); + --m_size; + + } } else { + // if the data is already too small do not try to make it smaller + // again this run. + max_rand = AUTOTOKENS_MUT_MAX - 2; } @@ -262,14 +308,12 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } - // TODO: add full line insert splice, replace splace, delete - } } - string output; - u32 m_size_1 = m_size - 1; + u32 m_size_1 = m_size - 1; + output = ""; for (i = 0; i < m_size; ++i) { @@ -282,31 +326,108 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } - u32 mutated_size = output.size(); - u8 *mutated_out = (u8 *)afl_realloc((void **)out_buf, mutated_size); + u32 mutated_size = (u32)output.size(); + u8 *mutated_out = (u8 *)output.data(); - if (unlikely(!mutated_out)) { + if (unlikely(mutated_size > max_size)) { mutated_size = max_size; } - *out_buf = NULL; - return 0; + IFDEBUG { - } - - if (unlikely(debug)) { - - DEBUG(stderr, "MUTATED to %u bytes:\n", mutated_size); + DEBUGF(stderr, "MUTATED to %u bytes:\n", mutated_size); fwrite(output.data(), 1, mutated_size, stderr); - DEBUG(stderr, "\n---\n"); + DEBUGF(stderr, "\n---\n"); } - memcpy(mutated_out, output.data(), mutated_size); *out_buf = mutated_out; ++fuzz_count; return mutated_size; } +/* I get f*cking stack overflow using C++ regex with a regex of + "\"[[:print:]]*?\"" if this matches a long string even with regex::optimize + enabled :-( */ +u8 my_search_string(string::const_iterator cur, string::const_iterator ende, + string::const_iterator *match_begin, + string::const_iterator *match_end) { + + string::const_iterator start = cur, found_begin; + u8 quote_type = 0; + + while (cur < ende) { + + switch (*cur) { + + case '"': { + + if (cur == start || *(cur - 1) != '\\') { + + if (!quote_type) { + + found_begin = cur; + quote_type = 1; + + } else if (quote_type == 1) { + + *match_begin = found_begin; + *match_end = cur + 1; + return 1; + + } + + } + + break; + + } + + case '\'': { + + if (cur == start || *(cur - 1) != '\\') { + + if (!quote_type) { + + found_begin = cur; + quote_type = 2; + + } else if (quote_type == 2) { + + *match_begin = found_begin; + *match_end = cur + 1; + return 1; + + } + + } + + break; + + } + + case '\n': + case '\r': + case 0: { + + quote_type = 0; + break; + + } + + default: + if (unlikely(quote_type && !isprint(*cur))) { quote_type = 0; } + break; + + } + + ++cur; + + } + + return 0; + +} + /* We are not using afl_custom_queue_new_entry() because not every corpus entry will be necessarily fuzzed. so we use afl_custom_queue_get() instead */ @@ -321,7 +442,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, (only_fav && !afl_ptr->queue_cur->favored)) { s = NULL; - DEBUG(stderr, "cmplog not ascii or only_fav and not favorite\n"); + DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); return 0; } @@ -356,7 +477,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } ++extras_cnt; - DEBUG(stderr, "Added from dictionary: \"%s\"\n", ptr); + DEBUGF(stderr, "Added from dictionary: \"%s\"\n", ptr); } @@ -385,7 +506,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } ++a_extras_cnt; - DEBUG(stderr, "Added from auto dictionary: \"%s\"\n", ptr); + DEBUGF(stderr, "Added from auto dictionary: \"%s\"\n", ptr); } @@ -415,7 +536,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again s = NULL; - DEBUG(stderr, "Too short (%lu) %s\n", len, filename); + DEBUGF(stderr, "Too short (%lu) %s\n", len, filename); return 0; } @@ -443,14 +564,14 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = NULL; s = NULL; - DEBUG(stderr, "Not text (%lu) %s\n", len, filename); + DEBUGF(stderr, "Not text (%lu) %s\n", len, filename); return 0; } } - // DEBUG(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", + // DEBUGF(stderr, "Read %lu bytes for %s\nBefore comment trim:\n%s\n", // input.size(), filename, input.c_str()); if (regex_comment_custom) { @@ -463,15 +584,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - DEBUG(stderr, "After replace %lu bytes for %s\n%s\n", input.size(), - filename, input.c_str()); + DEBUGF(stderr, "After replace %lu bytes for %s\n%s\n", input.size(), + filename, input.c_str()); u32 spaces = count(input.begin(), input.end(), ' '); u32 tabs = count(input.begin(), input.end(), '\t'); u32 linefeeds = count(input.begin(), input.end(), '\n'); bool ends_with_linefeed = input[input.length() - 1] == '\n'; - DEBUG(stderr, "spaces=%u tabs=%u linefeeds=%u ends=%u\n", spaces, tabs, - linefeeds, ends_with_linefeed); + DEBUGF(stderr, "spaces=%u tabs=%u linefeeds=%u ends=%u\n", spaces, tabs, + linefeeds, ends_with_linefeed); all_spaces += spaces; all_tabs += tabs; all_lf += linefeeds; @@ -479,25 +600,28 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // now extract all tokens vector tokens; - smatch match; - string::const_iterator cur = input.begin(), ende = input.end(), found, prev; + string::const_iterator cur = input.begin(), ende = input.end(), found, prev, + match_begin, match_end; - DEBUG(stderr, "START!\n"); + DEBUGF(stderr, "START!\n"); if (likely(!alternative_tokenize)) { - while (regex_search(cur, ende, match, regex_string, - regex_constants::match_any | - regex_constants::match_not_null | - regex_constants::match_continuous)) { + while (my_search_string(cur, ende, &match_begin, &match_end)) { prev = cur; - found = match[0].first; - cur = match[0].second; - DEBUG(stderr, - "string %s found at start %lu offset %lu continue at %lu\n", - match[0].str().c_str(), prev - input.begin(), match.position(), - cur - input.begin()); + found = match_begin; + cur = match_end; + + IFDEBUG { + + string foo(match_begin, match_end); + DEBUGF(stderr, + "string %s found at start %lu offset %lu continue at %lu\n", + foo.c_str(), prev - input.begin(), found - prev, + cur - input.begin()); + + } if (prev < found) { // there are items between search start and find while (prev < found) { @@ -512,8 +636,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } tokens.push_back(std::string(start, prev)); - DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, - tokens[tokens.size() - 1].c_str()); + DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { @@ -525,14 +649,14 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - tokens.push_back(std::string(start, prev)); - DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, - tokens[tokens.size() - 1].c_str()); + tokens.push_back(string(start, prev)); + DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, + tokens[tokens.size() - 1].c_str()); } else { - tokens.push_back(std::string(prev, prev + 1)); - DEBUG(stderr, "OTHER \"%c\"\n", *prev); + tokens.push_back(string(prev, prev + 1)); + DEBUGF(stderr, "OTHER \"%c\"\n", *prev); ++prev; } @@ -541,11 +665,12 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - if (match[0].length() > 0) { tokens.push_back(match[0]); } + tokens.push_back(string(match_begin, match_end)); + DEBUGF(stderr, "TOK: %s\n", tokens[tokens.size() - 1].c_str()); } - DEBUG(stderr, "AFTER all strings\n"); + DEBUGF(stderr, "AFTER all strings\n"); if (cur < ende) { @@ -561,8 +686,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } tokens.push_back(std::string(start, cur)); - DEBUG(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, - tokens[tokens.size() - 1].c_str()); + DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { @@ -575,13 +700,13 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } tokens.push_back(std::string(start, cur)); - DEBUG(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, - tokens[tokens.size() - 1].c_str()); + DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); } else { tokens.push_back(std::string(cur, cur + 1)); - DEBUG(stderr, "OTHER \"%c\"\n", *cur); + DEBUGF(stderr, "OTHER \"%c\"\n", *cur); ++cur; } @@ -593,19 +718,21 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } else { // alternative tokenize - - while (regex_search(cur, ende, match, regex_string, - regex_constants::match_any | - regex_constants::match_not_null | - regex_constants::match_continuous)) { + while (my_search_string(cur, ende, &match_begin, &match_end)) { prev = cur; - found = match[0].first; - cur = match[0].second; - DEBUG(stderr, - "string %s found at start %lu offset %lu continue at %lu\n", - match[0].str().c_str(), prev - input.begin(), match.position(), - cur - input.begin()); + found = match_begin; + cur = match_end; + IFDEBUG { + + string foo(match_begin, match_end); + DEBUGF(stderr, + "string %s found at start %lu offset %lu continue at %lu\n", + foo.c_str(), prev - input.begin(), found - prev, + cur - input.begin()); + + } + if (prev < found) { // there are items between search start and find sregex_token_iterator it{prev, found, regex_whitespace, -1}; vector tokenized{it, {}}; @@ -619,10 +746,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, tokenized.end()); tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); - if (unlikely(debug)) { + IFDEBUG { - DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), - input.size()); + DEBUGF(stderr, "tokens1: %lu input size: %lu\n", tokenized.size(), + input.size()); for (auto x : tokenized) { cerr << x << endl; @@ -636,10 +763,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string::const_iterator c = token.begin(), e = token.end(), f, p; smatch m; - while (regex_search(c, e, m, regex_word, - regex_constants::match_any | - regex_constants::match_not_null | - regex_constants::match_continuous)) { + while (regex_search(c, e, m, regex_word)) { p = c; f = m[0].first; @@ -649,10 +773,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // there are items between search start and find while (p < f) { - if (unlikely(debug)) { + IFDEBUG { string foo(p, p + 1); - DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); } @@ -661,20 +785,21 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - /* - string foo(p, f); - DEBUG(stderr, "before string: \"%s\"\n", - foo.c_str()); tokens.push_back(std::string(p, f)); - */ + IFDEBUG { + + string foo(p, f); + DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); + tokens.push_back(std::string(p, f)); + + } } - DEBUG( - stderr, - "SUBstring \"%s\" found at start %lu offset %lu continue at " - "%lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); + DEBUGF(stderr, + "SUBstring \"%s\" found at start %lu offset %lu continue " + "at %lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); tokens.push_back(m[0].str()); } @@ -683,10 +808,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, while (c < e) { - if (unlikely(debug)) { + IFDEBUG { string foo(c, c + 1); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); } @@ -695,17 +820,14 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - /* - if (unlikely(debug)) { + IFDEBUG { - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", - foo.c_str()); + string foo(c, e); + DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - } + } - tokens.push_back(std::string(c, e)); - */ + tokens.push_back(std::string(c, e)); } @@ -713,7 +835,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - if (match[0].length() > 0) { tokens.push_back(match[0]); } + tokens.push_back(string(match_begin, match_end)); } @@ -727,10 +849,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, tokenized.end()); tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); - if (unlikely(debug)) { + IFDEBUG { - DEBUG(stderr, "tokens: %lu input size: %lu\n", tokenized.size(), - input.size()); + DEBUGF(stderr, "tokens2: %lu input size: %lu\n", tokenized.size(), + input.size()); for (auto x : tokenized) { cerr << x << endl; @@ -744,10 +866,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string::const_iterator c = token.begin(), e = token.end(), f, p; smatch m; - while (regex_search(c, e, m, regex_word, - regex_constants::match_any | - regex_constants::match_not_null | - regex_constants::match_continuous)) { + while (regex_search(c, e, m, regex_word)) { p = c; f = m[0].first; @@ -757,10 +876,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // there are items between search start and find while (p < f) { - if (unlikely(debug)) { + IFDEBUG { string foo(p, p + 1); - DEBUG(stderr, "before string: \"%s\"\n", foo.c_str()); + DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); } @@ -769,25 +888,22 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - /* - if (unlikely(debug)) { + IFDEBUG { - string foo(p, f); - DEBUG(stderr, "before string: \"%s\"\n", - foo.c_str()); + string foo(p, f); + DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); - } + } - tokens.push_back(std::string(p, f)); - */ + tokens.push_back(std::string(p, f)); } - DEBUG(stderr, - "SUB2string \"%s\" found at start %lu offset %lu continue at " - "%lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); + DEBUGF(stderr, + "SUB2string \"%s\" found at start %lu offset %lu continue " + "at %lu\n", + m[0].str().c_str(), p - input.begin(), m.position(), + c - token.begin()); tokens.push_back(m[0].str()); } @@ -796,10 +912,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, while (c < e) { - if (unlikely(debug)) { + IFDEBUG { string foo(c, c + 1); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); } @@ -808,16 +924,14 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - /* - if (unlikely(debug)) { + IFDEBUG { - string foo(c, e); - DEBUG(stderr, "after string: \"%s\"\n", foo.c_str()); + string foo(c, e); + DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - } + } - tokens.push_back(std::string(c, e)); - */ + tokens.push_back(std::string(c, e)); } @@ -827,22 +941,22 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - if (unlikely(debug)) { + IFDEBUG { - DEBUG(stderr, "DUMPING TOKENS:\n"); + DEBUGF(stderr, "DUMPING TOKENS:\n"); u32 size_1 = tokens.size() - 1; for (u32 i = 0; i < tokens.size(); ++i) { - DEBUG(stderr, "%s", tokens[i].c_str()); + DEBUGF(stderr, "%s", tokens[i].c_str()); if (unlikely(alternative_tokenize && i < size_1)) { - DEBUG(stderr, "%s", whitespace.c_str()); + DEBUGF(stderr, "%s", whitespace.c_str()); } } - DEBUG(stderr, "---------------------------\n"); + DEBUGF(stderr, "---------------------------\n"); } @@ -850,7 +964,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = NULL; s = NULL; - DEBUG(stderr, "too few tokens\n"); + DEBUGF(stderr, "too few tokens\n"); return 0; } @@ -886,21 +1000,23 @@ extern "C" unsigned char afl_custom_queue_get(void *data, all_structure_items += structure->size(); // we are done! - DEBUG(stderr, "DONE! We have %lu tokens in the structure\n", - structure->size()); + DEBUGF(stderr, "DONE! We have %lu tokens in the structure\n", + structure->size()); - } else { + } + + else { if (entry->second == NULL) { - DEBUG(stderr, "Skipping %s\n", filename); + DEBUGF(stderr, "Skipping %s\n", filename); s = NULL; return 0; } s = entry->second; - DEBUG(stderr, "OK %s\n", filename); + DEBUGF(stderr, "OK %s\n", filename); } diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 322caa5b..82131c92 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -150,6 +150,7 @@ def deinit(): # optional for Python sense to use it. You would only skip this if `post_process` is used to fix checksums etc. so if you are using it, e.g., as a post processing library. Note that a length > 0 *must* be returned! + The returned output buffer is under **your** memory management! - `describe` (optional): diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1e8d085d..229bc025 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -844,15 +844,16 @@ struct custom_mutator { /** * Perform custom mutations on a given input * - * (Optional for now. Required in the future) + * (Optional) * - * @param data pointer returned in afl_custom_init by this custom mutator + * Getting an add_buf can be skipped by using afl_custom_splice_optout(). + * + * @param[in] data Pointer returned in afl_custom_init by this custom mutator * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of the input/output data - * @param[out] out_buf the new buffer. We may reuse *buf if large enough. - * *out_buf = NULL is treated as FATAL. - * @param[in] add_buf Buffer containing the additional test case + * @param[out] out_buf The new buffer, under your memory mgmt. + * @param[in] add_buf Buffer containing an additional test case (splicing) * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 5e352dcb..bd482562 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -564,8 +564,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->cmplog_lvl == 3 || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || afl->queue_cur->favored || - !(afl->fsrv.total_execs % afl->queued_items) || - get_cur_time() - afl->last_find_time > 300000) { // 300 seconds + get_cur_time() - afl->last_find_time > 600000) { // 600 seconds if (input_to_state_stage(afl, in_buf, out_buf, len)) { From afff6f642c77e4986fdb8a4e9799c1a52e80ce32 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 19 Jan 2023 13:41:48 +0100 Subject: [PATCH 091/300] optimize --- custom_mutators/autotokens/autotokens.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 102bea0f..149ae430 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -109,9 +109,9 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, // DEBUGF(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); #if AUTOTOKENS_SPLICE_DISABLE == 1 - #define AUTOTOKENS_MUT_MAX 12 + #define AUTOTOKENS_MUT_MAX 18 #else - #define AUTOTOKENS_MUT_MAX 14 + #define AUTOTOKENS_MUT_MAX 27 #endif u32 max_rand = AUTOTOKENS_MUT_MAX, new_item, pos; @@ -120,8 +120,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, switch (rand_below(afl_ptr, max_rand)) { - /* CHANGE */ - case 0 ... 7: /* fall through */ + /* CHANGE/MUTATE single item */ + case 0 ... 9: { pos = rand_below(afl_ptr, m_size); @@ -144,7 +144,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } /* INSERT (m_size +1 so we insert also after last place) */ - case 8 ... 9: { + case 10 ... 13: { do { @@ -192,7 +192,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, #if AUTOTOKENS_SPLICE_DISABLE != 1 /* SPLICING */ - case 10 ... 11: { + case 14 ... 22: { u32 strategy = rand_below(afl_ptr, 4), dst_off, n; auto src = id_mapping[rand_below(afl_ptr, valid_structures)]; @@ -278,11 +278,11 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, pos = rand_below(afl_ptr, m_size); - } while (unlikely(pos < whitespace_ids)); + } while (unlikely(m[pos] < whitespace_ids)); // if what we delete will result in a missing whitespace/token, // instead of deleting we switch the item to a whitespace or token. - if (likely(!alternative_tokenize) && pos && pos < m_size && + if (likely(!alternative_tokenize) && pos && pos + 1 < m_size && id_to_token[m[pos - 1]].size() > 1 && id_to_token[m[pos + 1]].size() > 1) { @@ -300,7 +300,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, // if the data is already too small do not try to make it smaller // again this run. - max_rand = AUTOTOKENS_MUT_MAX - 2; + max_rand -= 4; } @@ -734,6 +734,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } if (prev < found) { // there are items between search start and find + sregex_token_iterator it{prev, found, regex_whitespace, -1}; vector tokenized{it, {}}; tokenized.erase(std::remove_if(tokenized.begin(), tokenized.end(), From 86d3c65559209ce12452e18daf96946222c19b46 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 19 Jan 2023 15:59:57 +0100 Subject: [PATCH 092/300] nit --- custom_mutators/autotokens/autotokens.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 149ae430..f4b96c7b 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -121,8 +121,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, switch (rand_below(afl_ptr, max_rand)) { /* CHANGE/MUTATE single item */ - case 0 ... 9: - { + case 0 ... 9: { pos = rand_below(afl_ptr, m_size); u32 cur_item = m[pos]; @@ -438,8 +437,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (likely(!debug)) { - if ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || - (only_fav && !afl_ptr->queue_cur->favored)) { + if (unlikely(!afl_ptr->custom_only) && + ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || + (only_fav && !afl_ptr->queue_cur->favored))) { s = NULL; DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); From 628b4b60021a0d62a2eccddca4fe321c9d57c663 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 19 Jan 2023 17:24:56 +0100 Subject: [PATCH 093/300] enhance examples --- custom_mutators/README.md | 10 ++++++++++ custom_mutators/examples/custom_send.c | 9 ++++++++- custom_mutators/examples/example.c | 4 +++- custom_mutators/examples/post_library_gif.so.c | 4 ++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/custom_mutators/README.md b/custom_mutators/README.md index 0289e150..8d01856f 100644 --- a/custom_mutators/README.md +++ b/custom_mutators/README.md @@ -11,6 +11,16 @@ The `./examples` folder contains examples for custom mutators in python and C. In `./rust`, you will find rust bindings, including a simple example in `./rust/example` and an example for structured fuzzing, based on lain, in`./rust/example_lain`. +## The AFL++ grammar agnostic grammar mutator + +In `./autotokens` you find a token-level fuzzer that does not need to know +anything about the grammar of an input as long as it is in ascii and allows +whitespace. +It is very fast and effective. + +If you are looking for an example of how to effectively create a custom +mutator take a look at this one. + ## The AFL++ Grammar Mutator If you use git to clone AFL++, then the following will incorporate our diff --git a/custom_mutators/examples/custom_send.c b/custom_mutators/examples/custom_send.c index ffea927e..7de72819 100644 --- a/custom_mutators/examples/custom_send.c +++ b/custom_mutators/examples/custom_send.c @@ -1,7 +1,14 @@ +// +// This is an example on how to use afl_custom_send +// It writes each mutated data set to /tmp/foo +// You can modify this to send to IPC, shared memory, etc. +// // cc -O3 -fPIC -shared -g -o custom_send.so -I../../include custom_send.c // cd ../.. // afl-cc -o test-instr test-instr.c -// afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo +// AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/examples/custom_send.so \ +// afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo +// #include "custom_mutator_helpers.h" diff --git a/custom_mutators/examples/example.c b/custom_mutators/examples/example.c index 3f299508..e680ec8e 100644 --- a/custom_mutators/examples/example.c +++ b/custom_mutators/examples/example.c @@ -6,7 +6,7 @@ Dominik Maier */ -// You need to use -I /path/to/AFLplusplus/include +// You need to use -I/path/to/AFLplusplus/include -I. #include "custom_mutator_helpers.h" #include @@ -118,6 +118,8 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, } + if (max_size > mutated_size) { mutated_size = max_size; } + *out_buf = mutated_out; return mutated_size; diff --git a/custom_mutators/examples/post_library_gif.so.c b/custom_mutators/examples/post_library_gif.so.c index 9cd224f4..3cb018a6 100644 --- a/custom_mutators/examples/post_library_gif.so.c +++ b/custom_mutators/examples/post_library_gif.so.c @@ -129,8 +129,8 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf, /* Allocate memory for new buffer, reusing previous allocation if possible. Note we have to use afl-fuzz's own realloc! - Note that you should only do this if you need to grow the buffer, - otherwise work with in_buf, and assign it to *out_buf instead. */ + We use afl_realloc because it is effective. + You can also work within in_buf, and assign it to *out_buf. */ *out_buf = afl_realloc(out_buf, len); From 67cfe4f6d4a03c596a5c3e1aa97d64d79263746a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 19 Jan 2023 22:24:24 +0100 Subject: [PATCH 094/300] nits --- custom_mutators/autotokens/autotokens.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index f4b96c7b..16ee8109 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -544,7 +544,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string input; input.resize(len); rewind(fp); - fread((void *)input.data(), input.size(), 1, fp); + + if (fread((void *)input.data(), 1, len, fp) != len) { + + s = NULL; + DEBUGF(stderr, "Too short read %s\n", len, filename); + return 0; + + } + fclose(fp); if (!afl_ptr->shm.cmplog_mode) { From bd2cb4cd1c2f07d5406875771cd41fb9a6e1f84d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 20 Jan 2023 12:22:29 +0100 Subject: [PATCH 095/300] more default tokens --- custom_mutators/autotokens/autotokens.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 16ee8109..f9b5bd2e 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -1105,6 +1105,12 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { id_to_token[current_id] = "\n\n\n\n"; ++current_id; whitespace_ids = current_id; + token_to_id["\""] = current_id; + id_to_token[current_id] = "\""; + ++current_id; + token_to_id["'"] = current_id; + id_to_token[current_id] = "'"; + ++current_id; } From afd2ea90dfdb9aa7668c482e7c427f95c4847843 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 20 Jan 2023 22:12:35 +0000 Subject: [PATCH 096/300] LLVM plugin 16+ support proposal. - Lifting the standard to C++17. - Beyond the cosmetic changes, it boils down to BasicBlock::getInstList being no longer available (and reading the header it is no accident). --- GNUmakefile.llvm | 6 + .../SanitizerCoveragePCGUARD.so.cc | 4 + instrumentation/afl-llvm-common.cc | 1 + instrumentation/afl-llvm-common.h | 7 + instrumentation/compare-transform-pass.so.cc | 4 + instrumentation/split-compares-pass.so.cc | 254 ++++++++++++++---- instrumentation/split-switches-pass.so.cc | 20 ++ 7 files changed, 248 insertions(+), 48 deletions(-) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index d6e45d29..09e9b5be 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -48,6 +48,7 @@ LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 ) LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && echo 1 || echo 0 ) LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) +LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 ) LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 ) LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 ) LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) @@ -81,6 +82,11 @@ ifeq "$(LLVM_NEW_API)" "1" LLVM_TOO_OLD=0 endif +ifeq "$(LLVM_NEWER_API)" "1" + $(info [+] llvm_mode detected llvm 16+, enabling c++17) + LLVM_STDCXX = c++17 +endif + ifeq "$(LLVM_TOO_OLD)" "1" $(info [!] llvm_mode detected an old version of llvm, upgrade to at least 9 or preferable 11!) $(shell sleep 1) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index ef2d3b9c..c4a564f7 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -728,7 +728,11 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( Array->setSection(getSectionName(Section)); #if (LLVM_VERSION_MAJOR >= 11) || \ (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) + #if LLVM_VERSION_MAJOR >= 16 + Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue())); + #else Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); + #endif #else Array->setAlignment(Align(4)); // cheating #endif diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index 5fcf27fb..dc34d191 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h index dee5f9fc..0112c325 100644 --- a/instrumentation/afl-llvm-common.h +++ b/instrumentation/afl-llvm-common.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "llvm/Config/llvm-config.h" @@ -35,6 +36,12 @@ typedef long double max_align_t; #if LLVM_VERSION_MAJOR >= 11 #define MNAME M.getSourceFileName() #define FMNAME F.getParent()->getSourceFileName() + #if LLVM_VERSION_MAJOR >= 16 + // None becomes deprecated + // the standard std::nullopt_t is recommended instead + // from C++17 and onwards. + constexpr std::nullopt_t None = std::nullopt; + #endif #else #define MNAME std::string("") #define FMNAME std::string("") diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 39bff510..efc99d20 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -708,7 +708,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, /* since the call is the first instruction of the bb it is safe to * replace it with a phi instruction */ BasicBlock::iterator ii(callInst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(callInst->getParent(), ii, PN); +#else ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN); +#endif } diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 95eca0cb..dd7b09a6 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -322,8 +322,12 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) { * block bb it is now at the position where the old FcmpInst was */ Instruction *fcmp_np; fcmp_np = CmpInst::Create(Instruction::FCmp, new_pred, op0, op1); +#if LLVM_MAJOR >= 16 + fcmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); +#else bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), fcmp_np); +#endif /* create a new basic block which holds the new EQ fcmp */ Instruction *fcmp_eq; @@ -331,7 +335,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) { BasicBlock *middle_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); fcmp_eq = CmpInst::Create(Instruction::FCmp, CmpInst::FCMP_OEQ, op0, op1); +#if LLVM_MAJOR >= 16 + fcmp_eq->insertInto(middle_bb, middle_bb->end()); +#else middle_bb->getInstList().push_back(fcmp_eq); +#endif /* add an unconditional branch to the end of middle_bb with destination * end_bb */ BranchInst::Create(end_bb, middle_bb); @@ -352,7 +360,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) { PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb); /* replace the old FcmpInst with our new and shiny PHI inst */ BasicBlock::iterator ii(FcmpInst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(FcmpInst->getParent(), ii, PN); +#else ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN); +#endif } @@ -409,7 +421,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst, /* create the ICMP instruction with new_pred and add it to the old basic * block bb it is now at the position where the old IcmpInst was */ CmpInst *icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); +#if LLVM_MAJOR >= 16 + icmp_np->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); +#else bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), icmp_np); +#endif /* create a new basic block which holds the new EQ icmp */ CmpInst *icmp_eq; @@ -417,7 +433,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst, BasicBlock *middle_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb); icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1); +#if LLVM_MAJOR >= 16 + icmp_eq->insertInto(middle_bb, middle_bb->end()); +#else middle_bb->getInstList().push_back(icmp_eq); +#endif /* add an unconditional branch to the end of middle_bb with destination * end_bb */ BranchInst::Create(end_bb, middle_bb); @@ -438,7 +458,11 @@ bool SplitComparesTransform::simplifyOrEqualsCompare(CmpInst *IcmpInst, PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb); /* replace the old IcmpInst with our new and shiny PHI inst */ BasicBlock::iterator ii(IcmpInst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(IcmpInst->getParent(), ii, PN); +#else ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); +#endif worklist.push_back(icmp_np); worklist.push_back(icmp_eq); @@ -518,7 +542,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M, } +#if LLVM_MAJOR >= 16 + icmp_inv_sig_cmp->insertInto(sign_bb, sign_bb->end()); +#else sign_bb->getInstList().push_back(icmp_inv_sig_cmp); +#endif BranchInst::Create(end_bb, sign_bb); /* create a new bb which is executed if signedness is equal */ @@ -528,7 +556,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M, /* we can do a normal unsigned compare now */ icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1); +#if LLVM_MAJOR >= 16 + icmp_usign_cmp->insertInto(middle_bb, middle_bb->end()); +#else middle_bb->getInstList().push_back(icmp_usign_cmp); +#endif BranchInst::Create(end_bb, middle_bb); auto term = bb->getTerminator(); @@ -543,7 +575,11 @@ bool SplitComparesTransform::simplifySignedCompare(CmpInst *IcmpInst, Module &M, PN->addIncoming(icmp_inv_sig_cmp, sign_bb); BasicBlock::iterator ii(IcmpInst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(IcmpInst->getParent(), ii, PN); +#else ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN); +#endif // save for later worklist.push_back(icmp_usign_cmp); @@ -717,7 +753,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M, } +#if LLVM_MAJOR >= 16 + icmp_inv_cmp->insertInto(inv_cmp_bb, inv_cmp_bb->end()); +#else inv_cmp_bb->getInstList().push_back(icmp_inv_cmp); +#endif worklist.push_back(icmp_inv_cmp); auto term = bb->getTerminator(); @@ -728,12 +768,18 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M, BasicBlock *cmp_low_bb = BasicBlock::Create(C, "" /*"injected"*/, end_bb->getParent(), end_bb); op0_low = new TruncInst(op0, NewIntType); - cmp_low_bb->getInstList().push_back(op0_low); op1_low = new TruncInst(op1, NewIntType); - cmp_low_bb->getInstList().push_back(op1_low); - icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low); + +#if LLVM_MAJOR >= 16 + op0_low->insertInto(cmp_low_bb, cmp_low_bb->end()); + op1_low->insertInto(cmp_low_bb, cmp_low_bb->end()); + icmp_low->insertInto(cmp_low_bb, cmp_low_bb->end()); +#else + cmp_low_bb->getInstList().push_back(op0_low); + cmp_low_bb->getInstList().push_back(op1_low); cmp_low_bb->getInstList().push_back(icmp_low); +#endif BranchInst::Create(end_bb, cmp_low_bb); BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb); @@ -754,7 +800,11 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M, } BasicBlock::iterator ii(cmp_inst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(cmp_inst->getParent(), ii, PN); +#else ReplaceInstWithInst(cmp_inst->getParent()->getInstList(), ii, PN); +#endif // We split the comparison into low and high. If this isn't our target // bitwidth we recursively split the low and high parts again until we have @@ -999,13 +1049,21 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction *bpre_op0, *bpre_op1; bpre_op0 = CastInst::Create(Instruction::BitCast, op0, IntegerType::get(C, op_size)); +#if LLVM_MAJOR >= 16 + bpre_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); +#else bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), bpre_op0); +#endif bpre_op1 = CastInst::Create(Instruction::BitCast, op1, IntegerType::get(C, op_size)); +#if LLVM_MAJOR >= 16 + bpre_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); +#else bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), bpre_op1); +#endif /* Check if any operand is NaN. * If so, all comparisons except unequal (which yields true) yield false */ @@ -1025,34 +1083,42 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction *nan_op0, *nan_op1; nan_op0 = BinaryOperator::Create(Instruction::Shl, bpre_op0, ConstantInt::get(bpre_op0->getType(), 1)); - bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), - nan_op0); - - /* compare to NaN interval */ - Instruction *is_op0_nan = - CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0, - ConstantInt::get(intType, NaN_lowend)); - bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), - is_op0_nan); - /* Check op1 for NaN */ /* Shift right 1 Bit, ignore sign bit */ nan_op1 = BinaryOperator::Create(Instruction::Shl, bpre_op1, ConstantInt::get(bpre_op1->getType(), 1)); - bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), - nan_op1); - + /* compare to NaN interval */ + Instruction *is_op0_nan = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op0, + ConstantInt::get(intType, NaN_lowend)); /* compare to NaN interval */ Instruction *is_op1_nan = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, nan_op1, ConstantInt::get(intType, NaN_lowend)); - bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), - is_op1_nan); - /* combine checks */ Instruction *is_nan = BinaryOperator::Create(Instruction::Or, is_op0_nan, is_op1_nan); +#if LLVM_MAJOR >= 16 + nan_op0->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); + is_op0_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); + nan_op1->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); + is_op1_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); + is_nan->insertInto(bb, BasicBlock::iterator(bb->getTerminator())); +#else + bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), + nan_op0); + + bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), + is_op0_nan); + + bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), + nan_op1); + + bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), + is_op1_nan); + bb->getInstList().insert(BasicBlock::iterator(bb->getTerminator()), is_nan); +#endif /* the result of the comparison, when at least one op is NaN is true only for the "NOT EQUAL" predicates. */ @@ -1079,23 +1145,30 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { isMzero_op0 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op0, ConstantInt::get(intType, MinusZero)); + isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1, + ConstantInt::get(intType, MinusZero)); + b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero), + bpre_op0); + b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero), + bpre_op1); +#if LLVM_MAJOR >= 16 + isMzero_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + isMzero_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + b_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + b_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); +#else nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0); - isMzero_op1 = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, bpre_op1, - ConstantInt::get(intType, MinusZero)); nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op1); - b_op0 = SelectInst::Create(isMzero_op0, ConstantInt::get(intType, PlusZero), - bpre_op0); nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), b_op0); - b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero), - bpre_op1); nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), b_op1); +#endif /* isolate signs of value of floating point type */ @@ -1106,26 +1179,34 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { s_s0 = BinaryOperator::Create(Instruction::LShr, b_op0, ConstantInt::get(b_op0->getType(), op_size - 1)); - nonan_bb->getInstList().insert( - BasicBlock::iterator(nonan_bb->getTerminator()), s_s0); - t_s0 = new TruncInst(s_s0, Int1Ty); - nonan_bb->getInstList().insert( - BasicBlock::iterator(nonan_bb->getTerminator()), t_s0); - s_s1 = BinaryOperator::Create(Instruction::LShr, b_op1, ConstantInt::get(b_op1->getType(), op_size - 1)); - nonan_bb->getInstList().insert( - BasicBlock::iterator(nonan_bb->getTerminator()), s_s1); + t_s0 = new TruncInst(s_s0, Int1Ty); t_s1 = new TruncInst(s_s1, Int1Ty); - nonan_bb->getInstList().insert( - BasicBlock::iterator(nonan_bb->getTerminator()), t_s1); - /* compare of the sign bits */ icmp_sign_bit = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_s0, t_s1); +#if LLVM_MAJOR >= 16 + s_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + t_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + s_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + t_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + icmp_sign_bit->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); +#else + nonan_bb->getInstList().insert( + BasicBlock::iterator(nonan_bb->getTerminator()), s_s0); + nonan_bb->getInstList().insert( + BasicBlock::iterator(nonan_bb->getTerminator()), t_s0); + + nonan_bb->getInstList().insert( + BasicBlock::iterator(nonan_bb->getTerminator()), s_s1); + nonan_bb->getInstList().insert( + BasicBlock::iterator(nonan_bb->getTerminator()), t_s1); + nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), icmp_sign_bit); +#endif /* create a new basic block which is executed if the signedness bits are * equal */ @@ -1157,17 +1238,28 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { s_e1 = BinaryOperator::Create( Instruction::LShr, b_op1, ConstantInt::get(b_op1->getType(), shiftR_exponent)); +#if LLVM_MAJOR >= 16 + s_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + s_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); +#else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), s_e0); signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), s_e1); +#endif t_e0 = new TruncInst(s_e0, IntExponentTy); t_e1 = new TruncInst(s_e1, IntExponentTy); +#if LLVM_MAJOR >= 16 + t_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + t_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); +#else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), t_e0); signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), t_e1); +#endif + if (sizeInBits - precision < exTySizeBytes * 8) { @@ -1177,10 +1269,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { m_e1 = BinaryOperator::Create( Instruction::And, t_e1, ConstantInt::get(t_e1->getType(), mask_exponent)); +#if LLVM_MAJOR >= 16 + m_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + m_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); +#else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), m_e0); signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), m_e1); +#endif } else { @@ -1214,9 +1311,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction *icmp_exponent; icmp_exponents_equal = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); +#if LLVM_MAJOR >= 16 + icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); +#else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponents_equal); +#endif // shortcut for unequal exponents signequal2_bb = signequal_bb->splitBasicBlock( @@ -1230,9 +1331,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponent = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1); +#if LLVM_MAJOR >= 16 + icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); +#else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), icmp_exponent); +#endif icmp_exponent_result = BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); break; @@ -1240,9 +1345,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { case CmpInst::FCMP_ULT: icmp_exponents_equal = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); +#if LLVM_MAJOR >= 16 + icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); +#else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), icmp_exponents_equal); +#endif // shortcut for unequal exponents signequal2_bb = signequal_bb->splitBasicBlock( @@ -1256,9 +1365,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponent = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1); +#if LLVM_MAJOR >= 16 + icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); +#else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), icmp_exponent); +#endif icmp_exponent_result = BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); break; @@ -1267,9 +1380,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } +#if LLVM_MAJOR >= 16 + icmp_exponent_result->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); +#else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), icmp_exponent_result); +#endif { @@ -1319,19 +1436,29 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { m_f1 = BinaryOperator::Create( Instruction::And, b_op1, ConstantInt::get(b_op1->getType(), mask_fraction)); +#if LLVM_MAJOR >= 16 + m_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + m_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); +#else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), m_f0); middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), m_f1); +#endif if (needTrunc) { t_f0 = new TruncInst(m_f0, IntFractionTy); t_f1 = new TruncInst(m_f1, IntFractionTy); +#if LLVM_MAJOR >= 16 + t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); +#else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f0); middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f1); +#endif } else { @@ -1346,10 +1473,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { t_f0 = new TruncInst(b_op0, IntFractionTy); t_f1 = new TruncInst(b_op1, IntFractionTy); +#if LLVM_MAJOR >= 16 + t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); +#else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f0); middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f1); +#endif } else { @@ -1370,18 +1502,26 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { case CmpInst::FCMP_OEQ: icmp_fraction_result = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1); +#if LLVM_MAJOR >= 16 + icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); +#else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), icmp_fraction_result); +#endif break; case CmpInst::FCMP_UNE: case CmpInst::FCMP_ONE: icmp_fraction_result = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1); +#if LLVM_MAJOR >= 16 + icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); +#else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), icmp_fraction_result); +#endif break; case CmpInst::FCMP_OGT: @@ -1402,21 +1542,31 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT || FcmpInst->getPredicate() == CmpInst::FCMP_UGT) { - negative_bb->getInstList().push_back( - icmp_fraction_result = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1)); - positive_bb->getInstList().push_back( - icmp_fraction_result2 = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1)); + icmp_fraction_result = CmpInst::Create( + Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); + icmp_fraction_result2 = CmpInst::Create( + Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); +#if LLVM_MAJOR >= 16 + icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); + icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); +#else + negative_bb->getInstList().push_back(icmp_fraction_result); + positive_bb->getInstList().push_back(icmp_fraction_result2); +#endif } else { - negative_bb->getInstList().push_back( - icmp_fraction_result = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1)); - positive_bb->getInstList().push_back( - icmp_fraction_result2 = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1)); + icmp_fraction_result = CmpInst::Create( + Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); + icmp_fraction_result2 = CmpInst::Create( + Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); +#if LLVM_MAJOR >= 16 + icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); + icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); +#else + negative_bb->getInstList().push_back(icmp_fraction_result); + positive_bb->getInstList().push_back(icmp_fraction_result2); +#endif } @@ -1430,8 +1580,12 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { PN2 = PHINode::Create(Int1Ty, 2, ""); PN2->addIncoming(icmp_fraction_result, negative_bb); PN2->addIncoming(icmp_fraction_result2, positive_bb); +#if LLVM_MAJOR >= 16 + PN2->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); +#else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), PN2); +#endif } break; @@ -1494,7 +1648,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } BasicBlock::iterator ii(FcmpInst); +#if LLVM_MAJOR >= 16 + ReplaceInstWithInst(FcmpInst->getParent(), ii, PN); +#else ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN); +#endif ++count; } diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index 79ba12d2..aeb9c48e 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -225,12 +225,20 @@ BasicBlock *SplitSwitchesTransform::switchConvert( BasicBlock *NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock", F); Shift = BinaryOperator::Create(Instruction::LShr, Val, ConstantInt::get(ValType, smallestIndex * 8)); +#if LLVM_VERSION_MAJOR >= 16 + Shift->insertInto(NewNode, NewNode->end()); +#else NewNode->getInstList().push_back(Shift); +#endif if (ValTypeBitWidth > 8) { Trunc = new TruncInst(Shift, ByteType); +#if LLVM_VERSION_MAJOR >= 16 + Trunc->insertInto(NewNode, NewNode->end()); +#else NewNode->getInstList().push_back(Trunc); +#endif } else { @@ -253,7 +261,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert( ICmpInst *Comp = new ICmpInst(ICmpInst::ICMP_EQ, Trunc, ConstantInt::get(ByteType, byte), "byteMatch"); +#if LLVM_VERSION_MAJOR >= 16 + Comp->insertInto(NewNode, NewNode->end()); +#else NewNode->getInstList().push_back(Comp); +#endif bytesChecked[smallestIndex] = true; bool allBytesAreChecked = true; @@ -355,7 +367,11 @@ BasicBlock *SplitSwitchesTransform::switchConvert( ICmpInst *Comp = new ICmpInst(ICmpInst::ICMP_ULT, Trunc, ConstantInt::get(ByteType, pivot), "byteMatch"); +#if LLVM_VERSION_MAJOR >= 16 + Comp->insertInto(NewNode, NewNode->end()); +#else NewNode->getInstList().push_back(Comp); +#endif BranchInst::Create(LBB, RBB, Comp, NewNode); } @@ -452,7 +468,11 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { BranchInst::Create(SwitchBlock, OrigBlock); /* We are now done with the switch instruction, delete it. */ +#if LLVM_VERSION_MAJOR >= 16 + // TODO to erase range of instructions instead ? +#else CurBlock->getInstList().erase(SI); +#endif /* we have to update the phi nodes! */ for (BasicBlock::iterator I = Default->begin(); I != Default->end(); ++I) { From 8bc7b3cf26c2e94ee99fa854c9f7007092bc9949 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 23 Jan 2023 12:45:21 +0100 Subject: [PATCH 097/300] add CFI variant for gcc --- src/afl-cc.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index 803e784e..cbf57047 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1050,18 +1050,26 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (getenv("AFL_USE_CFISAN")) { - if (!lto_mode) { + if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { - uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) cc_params[cc_par_cnt++] = "-flto"; + cc_params[cc_par_cnt++] = "-fcf-protection"; + + } else { + + if (!lto_mode) { + + uint32_t i = 0, found = 0; + while (envp[i] != NULL && !found) + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; + if (!found) cc_params[cc_par_cnt++] = "-flto"; + + } + + cc_params[cc_par_cnt++] = "-fsanitize=cfi"; + cc_params[cc_par_cnt++] = "-fvisibility=hidden"; } - cc_params[cc_par_cnt++] = "-fsanitize=cfi"; - cc_params[cc_par_cnt++] = "-fvisibility=hidden"; - } if (!getenv("AFL_DONT_OPTIMIZE")) { From 4063a3eb4c4099e37aef4f1d96e8b80d58d65fe2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 23 Jan 2023 12:50:57 +0100 Subject: [PATCH 098/300] nit --- docs/Changelog.md | 4 ++++ src/afl-cc.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 7a9b74c5..fb573c73 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,10 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. +### Version ++4.06a (dev) + - afl-cc: + - add CFI sanitizer variant to gcc targets + ### Version ++4.05c (release) - MacOS: libdislocator, libtokencap etc. do not work with modern MacOS anymore, but could be patched to work, see this issue if you diff --git a/src/afl-cc.c b/src/afl-cc.c index cbf57047..7c3682fb 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1052,7 +1052,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { - cc_params[cc_par_cnt++] = "-fcf-protection"; + cc_params[cc_par_cnt++] = "-fcf-protection=full"; } else { From 5837322310b0dc8a05347384900e7fbfcd1db42b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 23 Jan 2023 22:56:04 +0000 Subject: [PATCH 099/300] erase the switch instruction from the current parent --- instrumentation/split-switches-pass.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index aeb9c48e..dcd89652 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -469,7 +469,7 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { /* We are now done with the switch instruction, delete it. */ #if LLVM_VERSION_MAJOR >= 16 - // TODO to erase range of instructions instead ? + SI->eraseFromParent(); #else CurBlock->getInstList().erase(SI); #endif From 0251b9bfd8545b8070d8e5c1294c4b1e7968dcf4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 24 Jan 2023 14:56:14 +0100 Subject: [PATCH 100/300] llvm15 pcguard_init earlier constructor --- instrumentation/afl-compiler-rt.o.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 9c6345b6..dcff6a0f 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1514,6 +1514,9 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { _is_sancov = 1; + __afl_auto_first(); + __afl_auto_second(); + if (__afl_debug) { fprintf(stderr, From b0898de3773d8142e68bf931d62b1668b010a9e4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 25 Jan 2023 08:24:34 +0000 Subject: [PATCH 101/300] Fix FRIDA mode for OSX x64 --- frida_mode/GNUmakefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index d283c3d7..b876284f 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -98,6 +98,14 @@ ifeq "$(shell uname)" "Darwin" OS:=macos AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations GUM_ARCH:="" + TARGET_CC= \ + "clang" \ + "-target" \ + "x86_64-apple-macos10.9" + TARGET_CXX= \ + "clang++" \ + "-target" \ + "x86_64-apple-macos10.9" else ifdef DEBUG AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor From c5a84a124c56a9478cf779b5aea7369a4eed07ed Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 25 Jan 2023 13:33:02 +0100 Subject: [PATCH 102/300] fixes --- instrumentation/afl-compiler-rt.o.c | 5 +++++ utils/aflpp_driver/GNUmakefile | 23 ++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index dcff6a0f..d6d6c38c 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -149,6 +149,7 @@ u32 __afl_already_initialized_shm; u32 __afl_already_initialized_forkserver; u32 __afl_already_initialized_first; u32 __afl_already_initialized_second; +u32 __afl_already_initialized_early; u32 __afl_already_initialized_init; /* Dummy pipe for area_is_valid() */ @@ -1373,6 +1374,9 @@ __attribute__((constructor(EARLY_FS_PRIO))) void __early_forkserver(void) { __attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) { + if (__afl_already_initialized_early) return; + __afl_already_initialized_early = 1; + is_persistent = !!getenv(PERSIST_ENV_VAR); if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return; @@ -1516,6 +1520,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { __afl_auto_first(); __afl_auto_second(); + __afl_auto_early(); if (__afl_debug) { diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile index 234a1c31..b973f96a 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -8,9 +8,14 @@ ifeq "$(shell uname -s)" "Darwin" LDFLAGS += $(SDK_LD) endif +ifeq "" "$(LLVM_CONFIG)" + LLVM_CONFIG := llvm-config +endif LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) ifneq "" "$(LLVM_BINDIR)" - LLVM_BINDIR := $(LLVM_BINDIR)/ + ifeq "$(shell test -x $(LLVM_BINDIR)/clang && echo 1)" "1" + CC := $(LLVM_BINDIR)/clang + endif endif CFLAGS := -O3 -funroll-loops -g -fPIC @@ -18,31 +23,31 @@ CFLAGS := -O3 -funroll-loops -g -fPIC all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c - -$(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c + -$(CC) -I. -I../../include $(CFLAGS) -c aflpp_driver.c libAFLDriver.a: aflpp_driver.o @ar rc libAFLDriver.a aflpp_driver.o @cp -vf libAFLDriver.a ../../ debug: - $(LLVM_BINDIR)clang -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c - $(LLVM_BINDIR)clang -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c - #$(LLVM_BINDIR)clang -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c - #$(LLVM_BINDIR)clang -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + $(CC) -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c + $(CC) -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + #$(CC) -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c + #$(CC) -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c ar rc libAFLDriver.a afl-performance.o aflpp_driver.o aflpp_qemu_driver.o: aflpp_qemu_driver.c - -$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c + -$(CC) $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c libAFLQemuDriver.a: aflpp_qemu_driver.o @-ar rc libAFLQemuDriver.a aflpp_qemu_driver.o @-cp -vf libAFLQemuDriver.a ../../ aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o - @-test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." + @-test -e aflpp_qemu_driver_hook.o && $(CC) $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." aflpp_qemu_driver_hook.o: aflpp_qemu_driver_hook.c - @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." + @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(CC) $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." test: debug #clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c From c52a0a15c8ab104bc6b1ea68ace5c37173e2a384 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 25 Jan 2023 11:40:36 +0000 Subject: [PATCH 103/300] Fix FRIDA mode for OSX arm64 --- frida_mode/GNUmakefile | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index b876284f..dda267bc 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -98,14 +98,25 @@ ifeq "$(shell uname)" "Darwin" OS:=macos AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations GUM_ARCH:="" + ifeq "$(ARCH)" "arm64" TARGET_CC= \ - "clang" \ + "clang" \ + "-target" \ + "arm64-apple-macos10.9" + TARGET_CXX= \ + "clang++" \ "-target" \ + "arm64-apple-macos10.9" + else + TARGET_CC= \ + "clang" \ + "-target" \ "x86_64-apple-macos10.9" - TARGET_CXX= \ + TARGET_CXX= \ "clang++" \ "-target" \ "x86_64-apple-macos10.9" + endif else ifdef DEBUG AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor From 1b4e1d75b32c6024765ab27b36591ae97cb33f6b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 25 Jan 2023 13:52:22 +0100 Subject: [PATCH 104/300] cmplog decision updates --- src/afl-fuzz-one.c | 16 ++++++++++------ utils/aflpp_driver/GNUmakefile | 23 ++++++++++++++--------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index bd482562..b25398c4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -446,9 +446,12 @@ u8 fuzz_one_original(afl_state_t *afl) { ACTF( "Fuzzing test case #%u (%u total, %llu crashes saved, " - "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...", + "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, " + "exec_us=%llu, hits=%u, map=%u, ascii=%u)...", afl->current_entry, afl->queued_items, afl->saved_crashes, - afl->queue_cur->perf_score, afl->queue_cur->exec_us, + afl->queue_cur->perf_score, afl->queue_cur->weight, + afl->queue_cur->favored, afl->queue_cur->was_fuzzed, + afl->queue_cur->exec_us, likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0, afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii); fflush(stdout); @@ -561,10 +564,11 @@ u8 fuzz_one_original(afl_state_t *afl) { } else { - if (afl->cmplog_lvl == 3 || - (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || - afl->queue_cur->favored || - get_cur_time() - afl->last_find_time > 600000) { // 600 seconds + if (afl->queue_cur->favored || afl->cmplog_lvl == 3 || + (afl->cmplog_lvl == 2 && + (afl->queue_cur->tc_ref || + afl->fsrv.total_execs % afl->queued_items <= 10)) || + get_cur_time() - afl->last_find_time > 250000) { // 250 seconds if (input_to_state_stage(afl, in_buf, out_buf, len)) { diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile index 234a1c31..b973f96a 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -8,9 +8,14 @@ ifeq "$(shell uname -s)" "Darwin" LDFLAGS += $(SDK_LD) endif +ifeq "" "$(LLVM_CONFIG)" + LLVM_CONFIG := llvm-config +endif LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) ifneq "" "$(LLVM_BINDIR)" - LLVM_BINDIR := $(LLVM_BINDIR)/ + ifeq "$(shell test -x $(LLVM_BINDIR)/clang && echo 1)" "1" + CC := $(LLVM_BINDIR)/clang + endif endif CFLAGS := -O3 -funroll-loops -g -fPIC @@ -18,31 +23,31 @@ CFLAGS := -O3 -funroll-loops -g -fPIC all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c - -$(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c + -$(CC) -I. -I../../include $(CFLAGS) -c aflpp_driver.c libAFLDriver.a: aflpp_driver.o @ar rc libAFLDriver.a aflpp_driver.o @cp -vf libAFLDriver.a ../../ debug: - $(LLVM_BINDIR)clang -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c - $(LLVM_BINDIR)clang -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c - #$(LLVM_BINDIR)clang -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c - #$(LLVM_BINDIR)clang -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + $(CC) -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c + $(CC) -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + #$(CC) -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c + #$(CC) -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c ar rc libAFLDriver.a afl-performance.o aflpp_driver.o aflpp_qemu_driver.o: aflpp_qemu_driver.c - -$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c + -$(CC) $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c libAFLQemuDriver.a: aflpp_qemu_driver.o @-ar rc libAFLQemuDriver.a aflpp_qemu_driver.o @-cp -vf libAFLQemuDriver.a ../../ aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o - @-test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." + @-test -e aflpp_qemu_driver_hook.o && $(CC) $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." aflpp_qemu_driver_hook.o: aflpp_qemu_driver_hook.c - @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." + @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(CC) $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." test: debug #clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c From 90a259d5231242562d3cb2e62f2c8cdbf073b3a0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 25 Jan 2023 15:36:12 +0100 Subject: [PATCH 105/300] new sanitizer option handling --- src/afl-forkserver.c | 94 +++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9b8660ce..ef2fa904 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -689,69 +689,57 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); } /* Set sane defaults for ASAN if nothing else is specified. */ + u8 *have_asan_options = getenv("ASAN_OPTIONS"); + u8 *have_ubsan_options = getenv("UBSAN_OPTIONS"); + u8 *have_msan_options = getenv("MSAN_OPTIONS"); + u8 *have_lsan_options = getenv("LSAN_OPTIONS"); + u8 have_san_options = 0; + if (have_asan_options || have_ubsan_options || have_msan_options || + have_lsan_options) + have_san_options = 1; + u8 default_options[1024] = + "detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_" + "size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" + "handle_abort=0:handle_sigfpe=0:handle_sigill=0:"; - if (!getenv("ASAN_OPTIONS")) - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "malloc_context_size=0:" - "symbolize=0:" - "allocator_may_return_null=1:" - "detect_odr_violation=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 1); + if (!have_lsan_options) strcat(default_options, "detect_leaks=0:"); + + /* Set sane defaults for ASAN if nothing else is specified. */ + + if (!have_san_options) setenv("ASAN_OPTIONS", default_options, 1); /* Set sane defaults for UBSAN if nothing else is specified. */ - if (!getenv("UBSAN_OPTIONS")) - setenv("UBSAN_OPTIONS", - "halt_on_error=1:" - "abort_on_error=1:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 1); - - /* Envs for QASan */ - setenv("QASAN_MAX_CALL_STACK", "0", 0); - setenv("QASAN_SYMBOLIZE", "0", 0); + if (!have_san_options) setenv("UBSAN_OPTIONS", default_options, 1); /* MSAN is tricky, because it doesn't support abort_on_error=1 at this point. So, we do this in a very hacky way. */ - if (!getenv("MSAN_OPTIONS")) - setenv("MSAN_OPTIONS", - "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "msan_track_origins=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 1); + if (!have_msan_options) { - /* LSAN, too, does not support abort_on_error=1. */ + u8 buf[2048] = ""; + if (!have_san_options) strcpy(buf, default_options); + strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:"); + setenv("MSAN_OPTIONS", buf, 1); - if (!getenv("LSAN_OPTIONS")) - setenv("LSAN_OPTIONS", - "exitcode=" STRINGIFY(LSAN_ERROR) ":" - "fast_unwind_on_malloc=0:" - "symbolize=0:" - "print_suppressions=0", - 1); + } + + /* LSAN, too, does not support abort_on_error=1. (is this still true??) */ + + if (!have_lsan_options) { + + u8 buf[2048] = ""; + if (!have_san_options) strcpy(buf, default_options); + strcat(buf, + "exitcode=" STRINGIFY( + LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:"); + setenv("LSAN_OPTIONS", buf, 1); + + } + + /* Envs for QASan */ + setenv("QASAN_MAX_CALL_STACK", "0", 0); + setenv("QASAN_SYMBOLIZE", "0", 0); fsrv->init_child_func(fsrv, argv); From e332d37d4e18b9a6c94abf7ba31963d2a14d737f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 26 Jan 2023 12:08:38 +0100 Subject: [PATCH 106/300] update unicorn --- src/afl-fuzz.c | 2 +- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index fc335742..20c655cf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -310,7 +310,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n" " afl-clang-lto/afl-gcc-fast target\n" "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" - "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so\n" + "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n" "\n" ); diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 06cac44c..8a0216eb 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -2df75f3e +8c66300a diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 2df75f3e..8c66300a 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 2df75f3e1045367cab95fe3471191b38c1a9f79e +Subproject commit 8c66300a5059872d1843fe390390d7988ce475cc From f4a13585a1a205798093291fd04659a4158b4d50 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 26 Jan 2023 12:21:47 +0100 Subject: [PATCH 107/300] better asan defaults everwhere --- docs/Changelog.md | 1 + include/common.h | 1 + src/afl-analyze.c | 84 +------------------- src/afl-common.c | 57 +++++++++++++ src/afl-forkserver.c | 54 +------------ src/afl-showmap.c | 43 +--------- src/afl-tmin.c | 83 +------------------ utils/afl_network_proxy/afl-network-server.c | 17 +--- 8 files changed, 67 insertions(+), 273 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index fb573c73..434bc101 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -24,6 +24,7 @@ - `-t none` now translates to `-t 120000` (120 seconds) - unicorn_mode updated - updated rust custom mutator dependencies and LibAFL custom mutator + - overall better sanitizer default setting handling - several minor bugfixes ### Version ++4.04c (release) diff --git a/include/common.h b/include/common.h index b5dbc6de..c5a32cdb 100644 --- a/include/common.h +++ b/include/common.h @@ -43,6 +43,7 @@ u32 check_binary_signatures(u8 *fn); void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); void print_suggested_envs(char *mispelled_env); void check_environment_vars(char **env); +void set_sanitizer_defaults(); char **argv_cpy_dup(int argc, char **argv); void argv_cpy_free(char **argv); diff --git a/src/afl-analyze.c b/src/afl-analyze.c index da1def3b..d4a9aa91 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -656,28 +656,6 @@ static void set_up_environment(char **argv) { if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); } /* Set sane defaults... */ - - x = get_afl_env("ASAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "abort_on_error=1")) { - - FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - - } - -#ifndef ASAN_BUILD - if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { - - FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); - - } - -#endif - - } - x = get_afl_env("MSAN_OPTIONS"); if (x) { @@ -689,69 +667,9 @@ static void set_up_environment(char **argv) { } - if (!strstr(x, "symbolize=0")) { - - FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - } - x = get_afl_env("LSAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "symbolize=0")) { - - FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - - } - - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "allocator_may_return_null=1:" - "detect_odr_violation=0:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - - setenv("UBSAN_OPTIONS", - "halt_on_error=1:" - "abort_on_error=1:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "abort_on_error=1:" - "msan_track_origins=0" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", 0); - - setenv("LSAN_OPTIONS", - "exitcode=" STRINGIFY(LSAN_ERROR) ":" - "fast_unwind_on_malloc=0:" - "symbolize=0:" - "print_suppressions=0", - 0); + set_sanitizer_defaults(); if (get_afl_env("AFL_PRELOAD")) { diff --git a/src/afl-common.c b/src/afl-common.c index 211d5bf2..d83130b4 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -58,6 +58,63 @@ u8 last_intr = 0; #define AFL_PATH "/usr/local/lib/afl/" #endif +void set_sanitizer_defaults() { + + /* Set sane defaults for ASAN if nothing else is specified. */ + u8 *have_asan_options = getenv("ASAN_OPTIONS"); + u8 *have_ubsan_options = getenv("UBSAN_OPTIONS"); + u8 *have_msan_options = getenv("MSAN_OPTIONS"); + u8 *have_lsan_options = getenv("LSAN_OPTIONS"); + u8 have_san_options = 0; + if (have_asan_options || have_ubsan_options || have_msan_options || + have_lsan_options) + have_san_options = 1; + u8 default_options[1024] = + "detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_" + "size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" + "handle_abort=0:handle_sigfpe=0:handle_sigill=0:"; + + if (!have_lsan_options) strcat(default_options, "detect_leaks=0:"); + + /* Set sane defaults for ASAN if nothing else is specified. */ + + if (!have_san_options) setenv("ASAN_OPTIONS", default_options, 1); + + /* Set sane defaults for UBSAN if nothing else is specified. */ + + if (!have_san_options) setenv("UBSAN_OPTIONS", default_options, 1); + + /* MSAN is tricky, because it doesn't support abort_on_error=1 at this + point. So, we do this in a very hacky way. */ + + if (!have_msan_options) { + + u8 buf[2048] = ""; + if (!have_san_options) strcpy(buf, default_options); + strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:"); + setenv("MSAN_OPTIONS", buf, 1); + + } + + /* LSAN, too, does not support abort_on_error=1. (is this still true??) */ + + if (!have_lsan_options) { + + u8 buf[2048] = ""; + if (!have_san_options) strcpy(buf, default_options); + strcat(buf, + "exitcode=" STRINGIFY( + LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:"); + setenv("LSAN_OPTIONS", buf, 1); + + } + + /* Envs for QASan */ + setenv("QASAN_MAX_CALL_STACK", "0", 0); + setenv("QASAN_SYMBOLIZE", "0", 0); + +} + u32 check_binary_signatures(u8 *fn) { int ret = 0, fd = open(fn, O_RDONLY); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ef2fa904..89d01460 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -688,58 +688,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); } - /* Set sane defaults for ASAN if nothing else is specified. */ - u8 *have_asan_options = getenv("ASAN_OPTIONS"); - u8 *have_ubsan_options = getenv("UBSAN_OPTIONS"); - u8 *have_msan_options = getenv("MSAN_OPTIONS"); - u8 *have_lsan_options = getenv("LSAN_OPTIONS"); - u8 have_san_options = 0; - if (have_asan_options || have_ubsan_options || have_msan_options || - have_lsan_options) - have_san_options = 1; - u8 default_options[1024] = - "detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_" - "size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" - "handle_abort=0:handle_sigfpe=0:handle_sigill=0:"; - - if (!have_lsan_options) strcat(default_options, "detect_leaks=0:"); - - /* Set sane defaults for ASAN if nothing else is specified. */ - - if (!have_san_options) setenv("ASAN_OPTIONS", default_options, 1); - - /* Set sane defaults for UBSAN if nothing else is specified. */ - - if (!have_san_options) setenv("UBSAN_OPTIONS", default_options, 1); - - /* MSAN is tricky, because it doesn't support abort_on_error=1 at this - point. So, we do this in a very hacky way. */ - - if (!have_msan_options) { - - u8 buf[2048] = ""; - if (!have_san_options) strcpy(buf, default_options); - strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:"); - setenv("MSAN_OPTIONS", buf, 1); - - } - - /* LSAN, too, does not support abort_on_error=1. (is this still true??) */ - - if (!have_lsan_options) { - - u8 buf[2048] = ""; - if (!have_san_options) strcpy(buf, default_options); - strcat(buf, - "exitcode=" STRINGIFY( - LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:"); - setenv("LSAN_OPTIONS", buf, 1); - - } - - /* Envs for QASan */ - setenv("QASAN_MAX_CALL_STACK", "0", 0); - setenv("QASAN_SYMBOLIZE", "0", 0); + /* Set sane defaults for sanitizers */ + set_sanitizer_defaults(); fsrv->init_child_func(fsrv, argv); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 4e019794..1e281d08 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -597,49 +597,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { char *afl_preload; char *frida_afl_preload = NULL; - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "detect_odr_violation=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - setenv("LSAN_OPTIONS", - "exitcode=" STRINGIFY(LSAN_ERROR) ":" - "fast_unwind_on_malloc=0:" - "symbolize=0:" - "print_suppressions=0", - 0); - - setenv("UBSAN_OPTIONS", - "halt_on_error=1:" - "abort_on_error=1:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "abort_on_error=1:" - "msan_track_origins=0" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", 0); + set_sanitizer_defaults(); if (get_afl_env("AFL_PRELOAD")) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 687bb0e7..12c5e0c9 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -674,27 +674,6 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { /* Set sane defaults... */ - x = get_afl_env("ASAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "abort_on_error=1")) { - - FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - - } - -#ifndef ASAN_BUILD - if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { - - FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); - - } - -#endif - - } - x = get_afl_env("MSAN_OPTIONS"); if (x) { @@ -706,69 +685,9 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { } - if (!strstr(x, "symbolize=0")) { - - FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - } - x = get_afl_env("LSAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "symbolize=0")) { - - FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!"); - - } - - } - - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "detect_odr_violation=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - - setenv("UBSAN_OPTIONS", - "halt_on_error=1:" - "abort_on_error=1:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", - 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "abort_on_error=1:" - "msan_track_origins=0" - "allocator_may_return_null=1:" - "symbolize=0:" - "handle_segv=0:" - "handle_sigbus=0:" - "handle_abort=0:" - "handle_sigfpe=0:" - "handle_sigill=0", 0); - - setenv("LSAN_OPTIONS", - "exitcode=" STRINGIFY(LSAN_ERROR) ":" - "fast_unwind_on_malloc=0:" - "symbolize=0:" - "print_suppressions=0", - 0); + set_sanitizer_defaults(); if (get_afl_env("AFL_PRELOAD")) { diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 2ae4c165..04309ada 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -194,7 +194,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - if (!strstr(x, "symbolize=0")) { + if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); @@ -213,7 +213,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - if (!strstr(x, "symbolize=0")) { + if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); @@ -221,18 +221,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", - 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "allocator_may_return_null=1:" - "msan_track_origins=0", 0); + set_sanitizer_defaults(); if (get_afl_env("AFL_PRELOAD")) { From 614265897cd67436deb6608673aa4a3ac7e91a9f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Jan 2023 00:31:16 +0100 Subject: [PATCH 108/300] ignored llvm testcase files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 8b0f0a7f..45d8676c 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,10 @@ examples/aflpp_driver/libAFLQemuDriver.a libAFLDriver.a libAFLQemuDriver.a test/.afl_performance +test-instr +test/output +test/test-instr.ts +test/test-persistent gmon.out afl-frida-trace.so utils/afl_network_proxy/afl-network-client From 5db7be5ee2e2fe43d50576c25d90a215166dd28b Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Jan 2023 01:33:05 +0100 Subject: [PATCH 109/300] Updated unicorn, added while to build sh --- unicorn_mode/build_unicorn_support.sh | 10 ++++++---- unicorn_mode/unicornafl | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index f20f52ef..53ec2481 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -121,17 +121,19 @@ PIP_FOUND=0 for PYTHON in $PYTHONS ; do if $PYTHON -c "import pip" ; then + if $PYTHON -c "import wheel" ; then - PIP_FOUND=1 - PYTHONBIN=$PYTHON - break + PIP_FOUND=1 + PYTHONBIN=$PYTHON + break + fi fi done if [ "0" = $PIP_FOUND ]; then - echo "[-] Error: Python pip not found. Run 'sudo apt-get install python-pip', or install python3-pip, or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ..." + echo "[-] Error: Python pip or python wheel not found. Run 'sudo apt-get install python3-pip', or run '$PYTHONBIN -m ensurepip', or create a virtualenv, or ... - and 'pip3 install wheel'" PREREQ_NOTFOUND=1 fi diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 8c66300a..f2cede37 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 8c66300a5059872d1843fe390390d7988ce475cc +Subproject commit f2cede37a75bbd4a9b9438f0277727b5d4620572 From 4ec26fc7cbfab5a6229f5f5cd99d0af75f49fddf Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 27 Jan 2023 09:51:47 +0100 Subject: [PATCH 110/300] update UNICORNAFL_VERSION --- unicorn_mode/UNICORNAFL_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 8a0216eb..1c8e571f 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -8c66300a +f2cede37 From 33eba1fc5652060e8d877b02135fce2325813d0c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 27 Jan 2023 10:17:16 +0100 Subject: [PATCH 111/300] update changelog --- docs/Changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 434bc101..eee88a51 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,8 +4,16 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.06a (dev) + - afl-fuzz: + - ensure temporary file descriptor is closed when not used - afl-cc: - add CFI sanitizer variant to gcc targets + - llvm 16 support (thanks to @devnexen!) + - support llvm 15 native pcguard changes + - better sanitizer default options support for all tools + - unicorn_mode: updated and minor issues fixed + - frida_mode: fix issue on MacOS + - more minor fixes ### Version ++4.05c (release) - MacOS: libdislocator, libtokencap etc. do not work with modern From 47f35d29ac53ed1cdb87f65591b62947a7965060 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 27 Jan 2023 14:32:18 +0100 Subject: [PATCH 112/300] fix --- custom_mutators/autotokens/autotokens.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index f9b5bd2e..4a2cc08f 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -61,8 +61,10 @@ static unordered_map id_to_token; static string whitespace = AUTOTOKENS_WHITESPACE; static string output; static regex *regex_comment_custom; -static regex regex_comment_star("/\\*([:print:]|\n)*?\\*/", - regex::multiline | regex::optimize); +// multiline requires g++-11 libs :( +static regex regex_comment_star( + "/\\*([:print:]|\n)*?\\*/", + regex_constants::optimize /* | regex_constants::multiline */); static regex regex_word("[A-Za-z0-9_$.-]+", regex::optimize); static regex regex_whitespace(R"([ \t]+)", regex::optimize); static vector *s; // the structure of the currently selected input @@ -548,7 +550,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (fread((void *)input.data(), 1, len, fp) != len) { s = NULL; - DEBUGF(stderr, "Too short read %s\n", len, filename); + DEBUGF(stderr, "Too short read %s\n", filename); return 0; } From b81bc8eb6f3cb77437aae45f9e77522140b560c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 28 Jan 2023 12:14:57 +0100 Subject: [PATCH 113/300] fix warning --- src/afl-fuzz.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 20c655cf..b8114a7f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1345,12 +1345,11 @@ int main(int argc, char **argv_orig, char **envp) { } #endif - if (afl->sync_id && afl->is_main_node && - afl->afl_env.afl_custom_mutator_only) { + if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) { - WARNF( - "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options " - "will result in no deterministic mutations being done!"); + FATAL( + "Using -D determinstic fuzzing is incompatible with " + "AFL_CUSTOM_MUTATOR_ONLY!"); } From b5d8d4c866137a8a6bd55225b0eaf723123c46c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 29 Jan 2023 10:07:33 +0100 Subject: [PATCH 114/300] comment --- custom_mutators/autotokens/autotokens.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 4a2cc08f..0a010f0b 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -1,3 +1,9 @@ +/* + token level fuzzing custom mutator for afl++ + (c) by Marc Heuse + License: Apache 2.0 +*/ + extern "C" { #include "afl-fuzz.h" From 31727f36a8438cc3274b9a87c5ceab420ddf34e5 Mon Sep 17 00:00:00 2001 From: Your Date: Tue, 31 Jan 2023 06:23:00 +0000 Subject: [PATCH 115/300] Changes to revert broken branch suppression fix --- frida_mode/src/instrument/instrument_arm64.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 39e32b12..77aa8c1d 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -196,7 +196,15 @@ static void instrument_coverage_switch(GumStalkerObserver *self, insn = instrument_disassemble(from_insn); deterministic = instrument_is_deterministic(insn); cs_free(insn, 1); - if (!deterministic) { return; } + + /* + * If the branch is deterministic, then we should start execution at the + * begining of the block. From here, we will branch and skip the coverage + * code and jump right to the target code of the instrumented block. + * Otherwise, if the branch is non-deterministic, then we need to branch + * part way into the block to where the coverage instrumentation starts. + */ + if (deterministic) { return; } /* * Since each block is prefixed with a restoration prologue, we need to be From 0d55feb11db1f79ee92db5f44ed04277388c933d Mon Sep 17 00:00:00 2001 From: Your Date: Tue, 31 Jan 2023 06:49:32 +0000 Subject: [PATCH 116/300] Add support for disabling branch suppression --- frida_mode/README.md | 7 + frida_mode/frida.map | 1 + frida_mode/include/instrument.h | 1 + frida_mode/src/instrument/instrument.c | 5 + frida_mode/src/instrument/instrument_arm64.c | 22 +- frida_mode/src/instrument/instrument_x64.c | 10 +- frida_mode/src/instrument/instrument_x86.c | 12 +- frida_mode/src/js/api.js | 7 + frida_mode/src/js/js_api.c | 7 + frida_mode/test/png/GNUmakefile | 2 +- frida_mode/ts/lib/afl.ts | 12 + frida_mode/ts/package-lock.json | 432 ++++++++++++++++++- include/envs.h | 1 + 13 files changed, 502 insertions(+), 17 deletions(-) diff --git a/frida_mode/README.md b/frida_mode/README.md index 055bb3ee..aac13153 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -193,6 +193,13 @@ instrumented address block translations. backpatching information. By default, the child will report applied backpatches to the parent so that they can be applied and then be inherited by the next child on fork. +* `AFL_FRIDA_INST_NO_SUPPRESS` - Disable deterministic branch suppression. + Deterministic branch suppression skips the preamble which generates coverage + information at the start of each block, if the block is reached by a + deterministic branch. This reduces map polution, and may improve performance + when all the executing blocks have been prefetched and backpatching applied. + However, in the event that backpatching is incomplete, this may incur a + performance penatly as branch instructions are disassembled on each branch. * `AFL_FRIDA_INST_SEED` - Sets the initial seed for the hash function used to generate block (and hence edge) IDs. Setting this to a constant value may be useful for debugging purposes, e.g., investigating unstable edges. diff --git a/frida_mode/frida.map b/frida_mode/frida.map index 73fff686..baf067ab 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -22,6 +22,7 @@ js_api_set_instrument_no_optimize; js_api_set_instrument_regs_file; js_api_set_instrument_seed; + js_api_set_instrument_suppress_disable; js_api_set_instrument_trace; js_api_set_instrument_trace_unique; js_api_set_instrument_unstable_coverage_file; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 8c93d881..1825e331 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -15,6 +15,7 @@ extern guint64 instrument_hash_zero; extern char *instrument_coverage_unstable_filename; extern gboolean instrument_coverage_insn; extern char *instrument_regs_filename; +extern gboolean instrument_suppress; extern gboolean instrument_use_fixed_seed; extern guint64 instrument_fixed_seed; diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index e1e4ac22..a6aac666 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -27,6 +27,7 @@ gboolean instrument_optimize = false; gboolean instrument_unique = false; guint64 instrument_hash_zero = 0; guint64 instrument_hash_seed = 0; +gboolean instrument_suppress = false; gboolean instrument_use_fixed_seed = FALSE; guint64 instrument_fixed_seed = 0; @@ -290,6 +291,7 @@ void instrument_config(void) { (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE")); instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL); instrument_regs_filename = getenv("AFL_FRIDA_INST_REGS_FILE"); + instrument_suppress = (getenv("AFL_FRIDA_INST_NO_SUPPRESS") == NULL); instrument_debug_config(); instrument_coverage_config(); @@ -321,6 +323,9 @@ void instrument_init(void) { FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]", instrument_coverage_insn ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "suppression:" cYEL " [%c]", + instrument_suppress ? 'X' : ' '); + if (instrument_tracing && instrument_optimize) { WARNF("AFL_FRIDA_INST_TRACE implies AFL_FRIDA_INST_NO_OPTIMIZE"); diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 77aa8c1d..4372861d 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -313,7 +313,7 @@ void instrument_coverage_optimize(const cs_insn *instr, // gum_arm64_writer_put_brk_imm(cw, 0x0); - instrument_coverage_suppress_init(); + if (instrument_suppress) { instrument_coverage_suppress_init(); } code_addr = cw->pc; @@ -333,9 +333,13 @@ void instrument_coverage_optimize(const cs_insn *instr, block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code) - GUM_RESTORATION_PROLOG_SIZE); - if (!g_hash_table_add(coverage_blocks, block_start)) { + if (instrument_suppress) { - FATAL("Failed - g_hash_table_add"); + if (!g_hash_table_add(coverage_blocks, block_start)) { + + FATAL("Failed - g_hash_table_add"); + + } } @@ -371,7 +375,17 @@ void instrument_coverage_optimize(const cs_insn *instr, code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5); - gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); + if (instrument_suppress) { + + gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); + + } else { + + size_t offset = offsetof(afl_log_code, code.stp_x0_x1); + gum_arm64_writer_put_bytes(cw, &code.bytes[offset], + sizeof(afl_log_code) - offset); + + } } diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index f7b7d6c5..8338f8e7 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -380,11 +380,15 @@ void instrument_coverage_optimize(const cs_insn *instr, } - instrument_coverage_suppress_init(); + if (instrument_suppress) { - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + instrument_coverage_suppress_init(); - FATAL("Failed - g_hash_table_add"); + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + + FATAL("Failed - g_hash_table_add"); + + } } diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index f15893cb..4667ea29 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -203,13 +203,17 @@ void instrument_coverage_optimize(const cs_insn *instr, code.code = template; - instrument_coverage_suppress_init(); + if (instrument_suppress) { - // gum_x86_writer_put_breakpoint(cw); + instrument_coverage_suppress_init(); - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + // gum_x86_writer_put_breakpoint(cw); - FATAL("Failed - g_hash_table_add"); + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + + FATAL("Failed - g_hash_table_add"); + + } } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index fce7a5d7..f9ea1ffb 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -170,6 +170,12 @@ class Afl { static setInstrumentSeed(seed) { Afl.jsApiSetInstrumentSeed(seed); } + /* + * See `AFL_FRIDA_INST_NO_SUPPRESS` + */ + static setInstrumentSuppressDisable() { + Afl.jsApiSetInstrumentSuppressDisable(); + } /** * See `AFL_FRIDA_INST_TRACE_UNIQUE`. */ @@ -339,6 +345,7 @@ Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_li Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]); Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); +Afl.jsApiSetInstrumentSuppressDisable = Afl.jsApiGetFunction("js_api_set_instrument_suppress_disable", "void", []); Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []); Afl.jsApiSetInstrumentUnstableCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_unstable_coverage_file", "void", ["pointer"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 01bba4ff..2e996c1c 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -289,6 +289,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_cache_size( } +__attribute__((visibility("default"))) void +js_api_set_instrument_suppress_disable(void) { + + instrument_suppress = false; + +} + __attribute__((visibility("default"))) void js_api_set_js_main_hook( const js_main_hook_t hook) { diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index 86fd1483..408b7dcb 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -25,7 +25,7 @@ HARNESS_URL:="https://raw.githubusercontent.com/llvm/llvm-project/main/compiler- PNGTEST_FILE:=$(PNGTEST_BUILD_DIR)target.cc PNGTEST_OBJ:=$(PNGTEST_BUILD_DIR)target.o -PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libpng-1.2.56/target.cc" +PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/e0c4a994b6999bae46e8dec5bcea9a73251b8dba/benchmarks/libpng-1.2.56/target.cc" TEST_BIN:=$(BUILD_DIR)test ifeq "$(shell uname)" "Darwin" diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 7a83c0fb..6a2350e7 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -201,6 +201,13 @@ class Afl { Afl.jsApiSetInstrumentSeed(seed); } + /* + * See `AFL_FRIDA_INST_NO_SUPPRESS` + */ + public static setInstrumentSuppressDisable(): void{ + Afl.jsApiSetInstrumentSuppressDisable(); + } + /** * See `AFL_FRIDA_INST_TRACE_UNIQUE`. */ @@ -451,6 +458,11 @@ class Afl { "void", ["uint64"]); + private static readonly jsApiSetInstrumentSuppressDisable = Afl.jsApiGetFunction( + "js_api_set_instrument_suppress_disable", + "void", + []); + private static readonly jsApiSetInstrumentTrace = Afl.jsApiGetFunction( "js_api_set_instrument_trace", "void", diff --git a/frida_mode/ts/package-lock.json b/frida_mode/ts/package-lock.json index e766c2c2..670d7a83 100644 --- a/frida_mode/ts/package-lock.json +++ b/frida_mode/ts/package-lock.json @@ -1,11 +1,433 @@ { - "requires": true, + "name": "@worksbutnottested/aflplusplus-frida", + "version": "1.0.1", "lockfileVersion": 1, + "requires": true, "dependencies": { - "tsc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tsc/-/tsc-2.0.3.tgz", - "integrity": "sha512-SN+9zBUtrpUcOpaUO7GjkEHgWtf22c7FKbKCA4e858eEM7Qz86rRDpgOU2lBIDf0fLCsEg65ms899UMUIB2+Ow==", + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@types/frida-gum": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-16.5.1.tgz", + "integrity": "sha512-t+2HZG6iBO2cEKtb2KvtP33m/7TGmzSd42YqznToA34+TkS97NttsFZ9OY2s0hPyDQOg+hZTjR1QggRkEL/Ovg==" + }, + "@types/node": { + "version": "14.18.36", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", + "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "mock-require": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", + "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", + "dev": true, + "requires": { + "get-caller-file": "^1.0.2", + "normalize-path": "^2.1.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + }, + "typescript-tslint-plugin": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/typescript-tslint-plugin/-/typescript-tslint-plugin-0.5.5.tgz", + "integrity": "sha512-tR5igNQP+6FhxaPJYRlUBVsEl0n5cSuXRbg7L1y80mL4B1jUHb8uiIcbQBJ9zWyypJEdFYFUccpXxvMwZR8+AA==", + "dev": true, + "requires": { + "minimatch": "^3.0.4", + "mock-require": "^3.0.3", + "vscode-languageserver": "^5.2.1" + } + }, + "vscode-jsonrpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz", + "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==", + "dev": true + }, + "vscode-languageserver": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz", + "integrity": "sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==", + "dev": true, + "requires": { + "vscode-languageserver-protocol": "3.14.1", + "vscode-uri": "^1.0.6" + } + }, + "vscode-languageserver-protocol": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz", + "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==", + "dev": true, + "requires": { + "vscode-jsonrpc": "^4.0.0", + "vscode-languageserver-types": "3.14.0" + } + }, + "vscode-languageserver-types": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz", + "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==", + "dev": true + }, + "vscode-uri": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz", + "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true } } diff --git a/include/envs.h b/include/envs.h index f4cdf390..46fc796b 100644 --- a/include/envs.h +++ b/include/envs.h @@ -68,6 +68,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", + "AFL_FRIDA_INST_NO_SUPPRESS" "AFL_FRIDA_INST_RANGES", "AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", From 91ccbf3f68ab9e6e4bc277f86c3efed666867132 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 1 Feb 2023 17:16:51 +0100 Subject: [PATCH 117/300] fix --- custom_mutators/autotokens/autotokens.cpp | 18 ++++++++---------- src/afl-fuzz-one.c | 5 +++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 0a010f0b..548e1be9 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -451,7 +451,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, s = NULL; DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); - return 0; + return 1; } @@ -532,7 +532,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (!fp) { s = NULL; - return 0; + return 1; } // should not happen @@ -545,7 +545,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = structure; // NULL ptr so we don't read the file again s = NULL; DEBUGF(stderr, "Too short (%lu) %s\n", len, filename); - return 0; + return 1; } @@ -557,7 +557,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, s = NULL; DEBUGF(stderr, "Too short read %s\n", filename); - return 0; + return 1; } @@ -581,7 +581,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = NULL; s = NULL; DEBUGF(stderr, "Not text (%lu) %s\n", len, filename); - return 0; + return 1; } @@ -982,7 +982,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, file_mapping[fn] = NULL; s = NULL; DEBUGF(stderr, "too few tokens\n"); - return 0; + return 1; } @@ -1020,15 +1020,13 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUGF(stderr, "DONE! We have %lu tokens in the structure\n", structure->size()); - } - - else { + } else { if (entry->second == NULL) { DEBUGF(stderr, "Skipping %s\n", filename); s = NULL; - return 0; + return 1; } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b25398c4..2f016217 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1988,7 +1988,8 @@ custom_mutator_stage: if (unlikely(!mutated_buf)) { - FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size); + //FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size); + break; } @@ -2040,7 +2041,7 @@ custom_mutator_stage: new_hit_cnt = afl->queued_items + afl->saved_crashes; afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt; - afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max; + afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_cur; #ifdef INTROSPECTION afl->queue_cur->stats_mutated += afl->stage_max; #endif From 4946e9cc3a340efd9b08807ae5cb0a657e0214a9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 2 Feb 2023 12:08:45 +0100 Subject: [PATCH 118/300] small fix to compiler rt --- instrumentation/afl-compiler-rt.o.c | 66 ++++++++--------------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index d6d6c38c..6ba19b5a 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1534,6 +1534,16 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (start == stop || *start) return; + x = getenv("AFL_INST_RATIO"); + if (x) { inst_ratio = (u32)atoi(x); } + + if (!inst_ratio || inst_ratio > 100) { + + fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); + abort(); + + } + // If a dlopen of an instrumented library happens after the forkserver then // we have a problem as we cannot increase the coverage map anymore. if (__afl_already_initialized_forkserver) { @@ -1554,62 +1564,20 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { while (start < stop) { - *(start++) = offset; + if (likely(inst_ratio == 100) || R(100) < inst_ratio) + *start = offset; + else + *start = 0; // write to map[0] if (unlikely(++offset >= __afl_final_loc)) { offset = 4; } } } - } - - x = getenv("AFL_INST_RATIO"); - if (x) { inst_ratio = (u32)atoi(x); } - - if (!inst_ratio || inst_ratio > 100) { - - fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); - abort(); + return; // we are done for this special case } - /* instrumented code is loaded *after* our forkserver is up. this is a - problem. We cannot prevent collisions then :( */ - /* - if (__afl_already_initialized_forkserver && - __afl_final_loc + 1 + stop - start > __afl_map_size) { - - if (__afl_debug) { - - fprintf(stderr, "Warning: new instrumented code after the forkserver!\n"); - - } - - __afl_final_loc = 2; - - if (1 + stop - start > __afl_map_size) { - - *(start++) = ++__afl_final_loc; - - while (start < stop) { - - if (R(100) < inst_ratio) - *start = ++__afl_final_loc % __afl_map_size; - else - *start = 4; - - start++; - - } - - return; - - } - - } - - */ - /* Make sure that the first element in the range is always set - we use that to avoid duplicate calls (which can happen as an artifact of the underlying implementation in LLVM). */ @@ -1618,10 +1586,10 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { while (start < stop) { - if (R(100) < inst_ratio) + if (likely(inst_ratio == 100) || R(100) < inst_ratio) *start = ++__afl_final_loc; else - *start = 4; + *start = 0; // write to map[0] start++; From 25b4b32627a1ef1e65b328f90f3ad1fd25d8f906 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 2 Feb 2023 12:13:48 +0100 Subject: [PATCH 119/300] small fix to compiler rt --- instrumentation/afl-compiler-rt.o.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 6ba19b5a..b1ce4427 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1582,6 +1582,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { to avoid duplicate calls (which can happen as an artifact of the underlying implementation in LLVM). */ + if (__afl_final_loc < 3) __afl_final_loc = 3; // we skip the first 4 entries + *(start++) = ++__afl_final_loc; while (start < stop) { From df9ef84f5e042bdc1db764e83baa83cb30a80d31 Mon Sep 17 00:00:00 2001 From: Nikolay Shaplov Date: Fri, 3 Feb 2023 14:32:17 +0000 Subject: [PATCH 120/300] Explicitly print error code if sched_setaffinity fails --- src/afl-gotcpu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index c5b8a27a..1762cfe2 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -214,7 +214,13 @@ int main(int argc, char **argv) { #if defined(__linux__) if (sched_setaffinity(0, sizeof(c), &c)) { - PFATAL("sched_setaffinity failed for cpu %d", i); + const char *error_code = "Unkown error code"; + if (errno == EFAULT) error_code = "EFAULT"; + if (errno == EINVAL) error_code = "EINVAL"; + if (errno == EPERM) error_code = "EPERM"; + if (errno == ESRCH) error_code = "ESRCH"; + + PFATAL("sched_setaffinity failed for cpu %d, error: %s", i, error_code); } From 53c19a807c701760af577cea1f44916d9133a971 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 4 Feb 2023 14:09:50 +0100 Subject: [PATCH 121/300] code indent --- instrumentation/split-compares-pass.so.cc | 102 ++++++++++++++-------- src/afl-gotcpu.c | 4 +- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index dd7b09a6..8a07610c 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -1152,10 +1152,14 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { b_op1 = SelectInst::Create(isMzero_op1, ConstantInt::get(intType, PlusZero), bpre_op1); #if LLVM_MAJOR >= 16 - isMzero_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); - isMzero_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); - b_op0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); - b_op1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + isMzero_op0->insertInto(nonan_bb, + BasicBlock::iterator(nonan_bb->getTerminator())); + isMzero_op1->insertInto(nonan_bb, + BasicBlock::iterator(nonan_bb->getTerminator())); + b_op0->insertInto(nonan_bb, + BasicBlock::iterator(nonan_bb->getTerminator())); + b_op1->insertInto(nonan_bb, + BasicBlock::iterator(nonan_bb->getTerminator())); #else nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), isMzero_op0); @@ -1192,7 +1196,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { t_s0->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); s_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); t_s1->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); - icmp_sign_bit->insertInto(nonan_bb, BasicBlock::iterator(nonan_bb->getTerminator())); + icmp_sign_bit->insertInto(nonan_bb, + BasicBlock::iterator(nonan_bb->getTerminator())); #else nonan_bb->getInstList().insert( BasicBlock::iterator(nonan_bb->getTerminator()), s_s0); @@ -1239,8 +1244,10 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction::LShr, b_op1, ConstantInt::get(b_op1->getType(), shiftR_exponent)); #if LLVM_MAJOR >= 16 - s_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); - s_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + s_e0->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); + s_e1->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); #else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), s_e0); @@ -1251,15 +1258,16 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { t_e0 = new TruncInst(s_e0, IntExponentTy); t_e1 = new TruncInst(s_e1, IntExponentTy); #if LLVM_MAJOR >= 16 - t_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); - t_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + t_e0->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); + t_e1->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); #else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), t_e0); signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), t_e1); #endif - if (sizeInBits - precision < exTySizeBytes * 8) { @@ -1270,8 +1278,10 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction::And, t_e1, ConstantInt::get(t_e1->getType(), mask_exponent)); #if LLVM_MAJOR >= 16 - m_e0->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); - m_e1->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + m_e0->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); + m_e1->insertInto(signequal_bb, + BasicBlock::iterator(signequal_bb->getTerminator())); #else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), m_e0); @@ -1312,7 +1322,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponents_equal = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); #if LLVM_MAJOR >= 16 - icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + icmp_exponents_equal->insertInto( + signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); #else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), @@ -1332,7 +1343,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponent = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1); #if LLVM_MAJOR >= 16 - icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); + icmp_exponent->insertInto( + signequal2_bb, + BasicBlock::iterator(signequal2_bb->getTerminator())); #else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), @@ -1346,7 +1359,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponents_equal = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); #if LLVM_MAJOR >= 16 - icmp_exponents_equal->insertInto(signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); + icmp_exponents_equal->insertInto( + signequal_bb, BasicBlock::iterator(signequal_bb->getTerminator())); #else signequal_bb->getInstList().insert( BasicBlock::iterator(signequal_bb->getTerminator()), @@ -1366,7 +1380,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponent = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1); #if LLVM_MAJOR >= 16 - icmp_exponent->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); + icmp_exponent->insertInto( + signequal2_bb, + BasicBlock::iterator(signequal2_bb->getTerminator())); #else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), @@ -1381,7 +1397,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } #if LLVM_MAJOR >= 16 - icmp_exponent_result->insertInto(signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); + icmp_exponent_result->insertInto( + signequal2_bb, BasicBlock::iterator(signequal2_bb->getTerminator())); #else signequal2_bb->getInstList().insert( BasicBlock::iterator(signequal2_bb->getTerminator()), @@ -1437,8 +1454,10 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { Instruction::And, b_op1, ConstantInt::get(b_op1->getType(), mask_fraction)); #if LLVM_MAJOR >= 16 - m_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); - m_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + m_f0->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); + m_f1->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); #else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), m_f0); @@ -1451,8 +1470,10 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { t_f0 = new TruncInst(m_f0, IntFractionTy); t_f1 = new TruncInst(m_f1, IntFractionTy); #if LLVM_MAJOR >= 16 - t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); - t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + t_f0->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); + t_f1->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); #else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f0); @@ -1474,8 +1495,10 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { t_f0 = new TruncInst(b_op0, IntFractionTy); t_f1 = new TruncInst(b_op1, IntFractionTy); #if LLVM_MAJOR >= 16 - t_f0->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); - t_f1->insertInto(middle_bb, BasicBlock::iterator(middle_bb->getTerminator())); + t_f0->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); + t_f1->insertInto(middle_bb, + BasicBlock::iterator(middle_bb->getTerminator())); #else middle_bb->getInstList().insert( BasicBlock::iterator(middle_bb->getTerminator()), t_f0); @@ -1503,7 +1526,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_fraction_result = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1); #if LLVM_MAJOR >= 16 - icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); + icmp_fraction_result->insertInto( + middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); #else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), @@ -1516,7 +1540,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_fraction_result = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1); #if LLVM_MAJOR >= 16 - icmp_fraction_result->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); + icmp_fraction_result->insertInto( + middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); #else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), @@ -1542,13 +1567,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { if (FcmpInst->getPredicate() == CmpInst::FCMP_OGT || FcmpInst->getPredicate() == CmpInst::FCMP_UGT) { - icmp_fraction_result = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); - icmp_fraction_result2 = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); + icmp_fraction_result = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); + icmp_fraction_result2 = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); #if LLVM_MAJOR >= 16 - icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); - icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); + icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); + icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); #else negative_bb->getInstList().push_back(icmp_fraction_result); positive_bb->getInstList().push_back(icmp_fraction_result2); @@ -1556,13 +1581,13 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } else { - icmp_fraction_result = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); - icmp_fraction_result2 = CmpInst::Create( - Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); + icmp_fraction_result = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1); + icmp_fraction_result2 = + CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1); #if LLVM_MAJOR >= 16 - icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); - icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); + icmp_fraction_result->insertInto(negative_bb, negative_bb->end()); + icmp_fraction_result2->insertInto(positive_bb, negative_bb->end()); #else negative_bb->getInstList().push_back(icmp_fraction_result); positive_bb->getInstList().push_back(icmp_fraction_result2); @@ -1581,7 +1606,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { PN2->addIncoming(icmp_fraction_result, negative_bb); PN2->addIncoming(icmp_fraction_result2, positive_bb); #if LLVM_MAJOR >= 16 - PN2->insertInto(middle2_bb, BasicBlock::iterator(middle2_bb->getTerminator())); + PN2->insertInto(middle2_bb, + BasicBlock::iterator(middle2_bb->getTerminator())); #else middle2_bb->getInstList().insert( BasicBlock::iterator(middle2_bb->getTerminator()), PN2); diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 1762cfe2..fd9e9f54 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -217,8 +217,8 @@ int main(int argc, char **argv) { const char *error_code = "Unkown error code"; if (errno == EFAULT) error_code = "EFAULT"; if (errno == EINVAL) error_code = "EINVAL"; - if (errno == EPERM) error_code = "EPERM"; - if (errno == ESRCH) error_code = "ESRCH"; + if (errno == EPERM) error_code = "EPERM"; + if (errno == ESRCH) error_code = "ESRCH"; PFATAL("sched_setaffinity failed for cpu %d, error: %s", i, error_code); From e1434bcfcd8c13de838559fd7b797d1a3cd5a672 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 4 Feb 2023 14:34:47 +0100 Subject: [PATCH 122/300] more autotoken options --- custom_mutators/autotokens/TODO | 17 +++++++++ custom_mutators/autotokens/autotokens.cpp | 45 ++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 2e39511c..3cae3060 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -4,3 +4,20 @@ create from thin air if no good seed after a cycle and dict large enough? (static u32 no_of_struct_inputs;) splicing -> check if whitespace/token is needed + +whitespace/token check only AFTER mutation + +analyse welche einen DICT haben, und welche davon rein ascii + +corpus analyse: + + libxml + - hardbuzz + - sqlite + - libpcap +min len, max len, % wenn 95/98/99/100 ascii + +funktion und env für menge an mutationen + +env für menge an per mutation run + +only add inital dictionary, not furher finds, e.g. cmplog diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 548e1be9..a0125851 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -28,6 +28,9 @@ extern "C" { #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 +#define AUTOTOKENS_FUZZ_COUNT_SHIFT 0 +// 0 = no learning, 1 only from -x dict/autodict, 2 also from cmplog +#define AUTOTOKENS_LEARN_DICT 2 #ifndef AUTOTOKENS_SPLICE_DISABLE #define AUTOTOKENS_SPLICE_DISABLE 0 #endif @@ -53,6 +56,8 @@ static afl_state *afl_ptr; static int debug = AUTOTOKENS_DEBUG; static int only_fav = AUTOTOKENS_ONLY_FAV; static int alternative_tokenize = AUTOTOKENS_ALTERNATIVE_TOKENIZE; +static int learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; +static int fuzz_count_shift = AUTOTOKENS_FUZZ_COUNT_SHIFT; static u32 current_id; static u32 valid_structures; static u32 whitespace_ids; @@ -94,6 +99,22 @@ u32 good_whitespace_or_singleval() { } +extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf, + size_t buf_size) { + + if (s == NULL) return 0; + + u32 shift = unlikely(afl_ptr->custom_only) ? 7 : 8; + u32 stage_max = (u32)((HAVOC_CYCLES * afl_ptr->queue_cur->perf_score) / + afl_ptr->havoc_div) >> + shift; + if (fuzz_count_shift) { stage_max >>= (u32)fuzz_count_shift; }; + DEBUGF(stderr, "fuzz count: %u\n", stage_max); + + return stage_max; + +} + extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { @@ -441,6 +462,7 @@ u8 my_search_string(string::const_iterator cur, string::const_iterator ende, extern "C" unsigned char afl_custom_queue_get(void *data, const unsigned char *filename) { + static int learn_state; (void)(data); if (likely(!debug)) { @@ -458,7 +480,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } // check if there are new dictionary entries and add them to the tokens - if (valid_structures) { + if (valid_structures && learn_state < learn_dictionary_tokens) { + + if (unlikely(!learn_state)) { learn_state = 1; } while (extras_cnt < afl_ptr->extras_cnt) { @@ -1053,6 +1077,25 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { if (getenv("AUTOTOKENS_DEBUG")) { debug = 1; } if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } if (getenv("AUTOTOKENS_ALTERNATIVE_TOKENIZE")) { alternative_tokenize = 1; } + + if (getenv("AUTOTOKENS_LEARN_DICT")) { + + learn_dictionary_tokens = atoi(getenv("AUTOTOKENS_LEARN_DICT")); + if (learn_dictionary_tokens < 0 || learn_dictionary_tokens > 2) { + + learn_dictionary_tokens = 2; + + } + + } + + if (getenv("AUTOTOKENS_FUZZ_COUNT_SHIFT")) { + + fuzz_count_shift = atoi(getenv("AUTOTOKENS_FUZZ_COUNT_SHIFT")); + if (fuzz_count_shift < 0 || fuzz_count_shift > 16) { fuzz_count_shift = 0; } + + } + if (getenv("AUTOTOKENS_WHITESPACE")) { whitespace = getenv("AUTOTOKENS_WHITESPACE"); From ec87abda93d68f489f26ed2a2ae75b4f1e26d0bb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 4 Feb 2023 14:37:28 +0100 Subject: [PATCH 123/300] readme --- custom_mutators/autotokens/README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index f82dcd98..86e7c9b3 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -18,6 +18,12 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! `AUTOTOKENS_ONLY_FAV` - only use this mutator on favorite queue items `AUTOTOKENS_COMMENT` - what character or string starts a comment which will be removed. Default: `/* ... */` +`AUTOTOKENS_FUZZ_COUNT_SHIFT` - reduce the number of fuzzing performed, shifting + the value by this number set, e.g. 1. +`AUTOTOKENS_LEARN_DICT` - learn from dictionaries? + 0 = none + 1 = only -x or autodict + 2 = -x, autodict and `CMPLOG` `AUTOTOKENS_ALTERNATIVE_TOKENIZE` - use an alternative tokenize implementation (experimental) `AUTOTOKENS_WHITESPACE` - whitespace string to use for ALTERNATIVE_TOKENIZE, From 90f61552f794fc0fae5dc2585f81f31d32db1e89 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 4 Feb 2023 15:39:03 +0100 Subject: [PATCH 124/300] changes --- custom_mutators/autotokens/TODO | 9 ++++----- custom_mutators/autotokens/autotokens.cpp | 12 ++++++++++++ include/config.h | 4 ++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 3cae3060..528dff1f 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -1,5 +1,3 @@ -cmplog: only add tokens that were found to fit? - create from thin air if no good seed after a cycle and dict large enough? (static u32 no_of_struct_inputs;) @@ -16,8 +14,9 @@ corpus analyse: - libpcap min len, max len, % wenn 95/98/99/100 ascii -funktion und env für menge an mutationen - env für menge an per mutation run -only add inital dictionary, not furher finds, e.g. cmplog +AFL_TXT_MAX_LEN 65535 +AFL_TXT_MIN_LEN 16 +AFL_TXT_MIN_PERCENT=99 + diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index a0125851..46a347f8 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -34,6 +34,9 @@ extern "C" { #ifndef AUTOTOKENS_SPLICE_DISABLE #define AUTOTOKENS_SPLICE_DISABLE 0 #endif +#ifndef AFL_TXT_MAX_LEN + #define AFL_TXT_MAX_LEN 65535 +#endif #if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN #error SPLICE_MIN must be lower than SIZE_MIN @@ -571,6 +574,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUGF(stderr, "Too short (%lu) %s\n", len, filename); return 1; + } else + if (len > AFL_TXT_MAX_LEN) { + + fclose(fp); + file_mapping[fn] = structure; // NULL ptr so we don't read the file again + s = NULL; + DEBUGF(stderr, "Too long (%lu) %s\n", len, filename); + return 1; + } string input; diff --git a/include/config.h b/include/config.h index f8a742f2..ed8b844c 100644 --- a/include/config.h +++ b/include/config.h @@ -489,12 +489,12 @@ /* Minimum length of a queue input to be evaluated for "is_ascii"? */ -#define AFL_TXT_MIN_LEN 12 +#define AFL_TXT_MIN_LEN 16 /* What is the minimum percentage of ascii characters present to be classifed as "is_ascii"? */ -#define AFL_TXT_MIN_PERCENT 95 +#define AFL_TXT_MIN_PERCENT 98 /* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ From f99656e22bffb4bfac8e201ad973a1ea5a6abaa0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 5 Feb 2023 13:15:06 +0100 Subject: [PATCH 125/300] create from thin air, max mutation --- custom_mutators/autotokens/autotokens.cpp | 97 ++++++++++++++++++----- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 46a347f8..f1263600 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -24,10 +24,12 @@ extern "C" { #define AUTOTOKENS_ONLY_FAV 0 #define AUTOTOKENS_ALTERNATIVE_TOKENIZE 0 #define AUTOTOKENS_CHANGE_MIN 8 +#define AUTOTOKENS_CHANGE_MAX 64 #define AUTOTOKENS_WHITESPACE " " #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 +#define AUTOTOKENS_CREATE_FROM_THIN_AIR 1 #define AUTOTOKENS_FUZZ_COUNT_SHIFT 0 // 0 = no learning, 1 only from -x dict/autodict, 2 also from cmplog #define AUTOTOKENS_LEARN_DICT 2 @@ -61,6 +63,7 @@ static int only_fav = AUTOTOKENS_ONLY_FAV; static int alternative_tokenize = AUTOTOKENS_ALTERNATIVE_TOKENIZE; static int learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; static int fuzz_count_shift = AUTOTOKENS_FUZZ_COUNT_SHIFT; +static int create_from_thin_air = AUTOTOKENS_CREATE_FROM_THIN_AIR; static u32 current_id; static u32 valid_structures; static u32 whitespace_ids; @@ -83,7 +86,18 @@ static regex regex_word("[A-Za-z0-9_$.-]+", regex::optimize); static regex regex_whitespace(R"([ \t]+)", regex::optimize); static vector *s; // the structure of the currently selected input -u32 good_whitespace_or_singleval() { +// FUNCTIONS + +/* This function is called once after everything is set up but before + any fuzzing attempt has been performed. + This is called in afl_custom_queue_get() */ +static void first_run(void *data) { + + (void)(data); + +} + +static u32 good_whitespace_or_singleval() { u32 i = rand_below(afl_ptr, current_id); if (id_to_token[i].size() == 1) { return i; } @@ -105,6 +119,8 @@ u32 good_whitespace_or_singleval() { extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf, size_t buf_size) { + (void)(data); + if (s == NULL) return 0; u32 shift = unlikely(afl_ptr->custom_only) ? 7 : 8; @@ -135,9 +151,10 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u32 i, m_size = (u32)m.size(); u32 rounds = - MAX(AUTOTOKENS_CHANGE_MIN, - MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * - afl_ptr->havoc_div / 256)); + MIN(AUTOTOKENS_CHANGE_MAX, + MAX(AUTOTOKENS_CHANGE_MIN, + MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * + afl_ptr->havoc_div / 256))); // DEBUGF(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); #if AUTOTOKENS_SPLICE_DISABLE == 1 @@ -379,9 +396,10 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, /* I get f*cking stack overflow using C++ regex with a regex of "\"[[:print:]]*?\"" if this matches a long string even with regex::optimize enabled :-( */ -u8 my_search_string(string::const_iterator cur, string::const_iterator ende, - string::const_iterator *match_begin, - string::const_iterator *match_end) { +static u8 my_search_string(string::const_iterator cur, + string::const_iterator ende, + string::const_iterator *match_begin, + string::const_iterator *match_end) { string::const_iterator start = cur, found_begin; u8 quote_type = 0; @@ -460,25 +478,30 @@ u8 my_search_string(string::const_iterator cur, string::const_iterator ende, } /* We are not using afl_custom_queue_new_entry() because not every corpus entry - will be necessarily fuzzed. so we use afl_custom_queue_get() instead */ + will be necessarily fuzzed with this custom mutator. + So we use afl_custom_queue_get() instead. */ extern "C" unsigned char afl_custom_queue_get(void *data, const unsigned char *filename) { - static int learn_state; + static int learn_state = 0; + static int is_first_run = 1; (void)(data); - if (likely(!debug)) { + if (unlikely(is_first_run)) { - if (unlikely(!afl_ptr->custom_only) && - ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || - (only_fav && !afl_ptr->queue_cur->favored))) { + is_first_run = 0; + first_run(data); - s = NULL; - DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); - return 1; + } - } + if (unlikely(!afl_ptr->custom_only) && !create_from_thin_air && + ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || + (only_fav && !afl_ptr->queue_cur->favored))) { + + s = NULL; + DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); + return 1; } @@ -551,6 +574,42 @@ extern "C" unsigned char afl_custom_queue_get(void *data, string fn = (char *)filename; auto entry = file_mapping.find(fn); + // if there is only one active queue item at start and it is very small + // the we create once a structure randomly. + if (unlikely(create_from_thin_air)) { + + if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 && + afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) { + + DEBUGF(stderr, "Creating an entry from thin air...\n"); + structure = new vector(); + u32 item, prev, cnt = current_id >> 1; + structure->reserve(cnt + 4); + for (u32 i = 0; i < cnt; i++) { + + item = rand_below(afl_ptr, current_id); + if (i && id_to_token[item].length() > 1 && + id_to_token[prev].length() > 1) { + + structure->push_back(good_whitespace_or_singleval()); + + } + + structure->push_back(item); + prev = item; + + } + + file_mapping[fn] = structure; + s = structure; + return 1; + + } + + create_from_thin_air = 0; + + } + if (entry == file_mapping.end()) { // this input file was not analyzed for tokens yet, so let's do it! @@ -574,8 +633,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUGF(stderr, "Too short (%lu) %s\n", len, filename); return 1; - } else - if (len > AFL_TXT_MAX_LEN) { + } else if (len > AFL_TXT_MAX_LEN) { fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again @@ -1088,6 +1146,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { if (getenv("AUTOTOKENS_DEBUG")) { debug = 1; } if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } + if (getenv("AUTOTOKENS_CREATE_FROM_THIN_AIR")) { create_from_thin_air = 1; } if (getenv("AUTOTOKENS_ALTERNATIVE_TOKENIZE")) { alternative_tokenize = 1; } if (getenv("AUTOTOKENS_LEARN_DICT")) { From e6120282556e4df79c01236849e5f6f225b8e428 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 5 Feb 2023 14:19:10 +0100 Subject: [PATCH 126/300] dict fix --- custom_mutators/autotokens/README | 3 +++ custom_mutators/autotokens/autotokens.cpp | 22 +++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index 86e7c9b3..d8613232 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -24,6 +24,9 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! 0 = none 1 = only -x or autodict 2 = -x, autodict and `CMPLOG` +`AUTOTOKENS_CREATE_FROM_THIN_AIR` - if only one small start file is present and + a dictionary loaded then create one initial + structure based on the dictionary. `AUTOTOKENS_ALTERNATIVE_TOKENIZE` - use an alternative tokenize implementation (experimental) `AUTOTOKENS_WHITESPACE` - whitespace string to use for ALTERNATIVE_TOKENIZE, diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index f1263600..d3ae7e9c 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -29,7 +29,7 @@ extern "C" { #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 -#define AUTOTOKENS_CREATE_FROM_THIN_AIR 1 +#define AUTOTOKENS_CREATE_FROM_THIN_AIR 0 #define AUTOTOKENS_FUZZ_COUNT_SHIFT 0 // 0 = no learning, 1 only from -x dict/autodict, 2 also from cmplog #define AUTOTOKENS_LEARN_DICT 2 @@ -506,14 +506,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } // check if there are new dictionary entries and add them to the tokens - if (valid_structures && learn_state < learn_dictionary_tokens) { + if (likely(valid_structures || create_from_thin_air) && + learn_state < learn_dictionary_tokens) { if (unlikely(!learn_state)) { learn_state = 1; } while (extras_cnt < afl_ptr->extras_cnt) { u32 ok = 1, l = afl_ptr->extras[extras_cnt].len; - u8 *ptr = afl_ptr->extras[extras_cnt].data; + u8 *buf, *ptr = afl_ptr->extras[extras_cnt].data; for (u32 i = 0; i < l; ++i) { @@ -528,14 +529,17 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (ok) { - token_to_id[(char *)ptr] = current_id; - id_to_token[current_id] = (char *)ptr; + buf = (u8 *)malloc(afl_ptr->extras[extras_cnt].len + 1); + memcpy(buf, afl_ptr->extras[extras_cnt].data, + afl_ptr->extras[extras_cnt].len); + buf[afl_ptr->extras[extras_cnt].len] = 0; + token_to_id[(char *)buf] = current_id; + id_to_token[current_id] = (char *)buf; ++current_id; } ++extras_cnt; - DEBUGF(stderr, "Added from dictionary: \"%s\"\n", ptr); } @@ -600,8 +604,12 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - file_mapping[fn] = structure; s = structure; + file_mapping[fn] = structure; + id_mapping[valid_structures] = structure; + ++valid_structures; + all_structure_items += structure->size(); + return 1; } From 8a2547073c500fcd637a7b276b7a38313bb70b5f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Feb 2023 08:51:20 +0100 Subject: [PATCH 127/300] more options --- custom_mutators/autotokens/README | 2 ++ custom_mutators/autotokens/TODO | 4 +++- custom_mutators/autotokens/autotokens.cpp | 26 +++++++++++++++++++---- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index d8613232..e9c48662 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -24,6 +24,8 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! 0 = none 1 = only -x or autodict 2 = -x, autodict and `CMPLOG` +`AUTOTOKENS_CHANGE_MIN` - minimum number of mutations (1-256, default 8) +`AUTOTOKENS_CHANGE_MAX` - maximum number of mutations (1-4096, default 64) `AUTOTOKENS_CREATE_FROM_THIN_AIR` - if only one small start file is present and a dictionary loaded then create one initial structure based on the dictionary. diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 528dff1f..496bfd45 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -9,7 +9,6 @@ analyse welche einen DICT haben, und welche davon rein ascii corpus analyse: + libxml - - hardbuzz - sqlite - libpcap min len, max len, % wenn 95/98/99/100 ascii @@ -20,3 +19,6 @@ AFL_TXT_MAX_LEN 65535 AFL_TXT_MIN_LEN 16 AFL_TXT_MIN_PERCENT=99 +-> KEIN FAV! + +change_min/_max werte diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index d3ae7e9c..ee35c68b 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -32,7 +32,7 @@ extern "C" { #define AUTOTOKENS_CREATE_FROM_THIN_AIR 0 #define AUTOTOKENS_FUZZ_COUNT_SHIFT 0 // 0 = no learning, 1 only from -x dict/autodict, 2 also from cmplog -#define AUTOTOKENS_LEARN_DICT 2 +#define AUTOTOKENS_LEARN_DICT 1 #ifndef AUTOTOKENS_SPLICE_DISABLE #define AUTOTOKENS_SPLICE_DISABLE 0 #endif @@ -64,6 +64,8 @@ static int alternative_tokenize = AUTOTOKENS_ALTERNATIVE_TOKENIZE; static int learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; static int fuzz_count_shift = AUTOTOKENS_FUZZ_COUNT_SHIFT; static int create_from_thin_air = AUTOTOKENS_CREATE_FROM_THIN_AIR; +static int change_min = AUTOTOKENS_CHANGE_MIN; +static int change_max = AUTOTOKENS_CHANGE_MAX; static u32 current_id; static u32 valid_structures; static u32 whitespace_ids; @@ -151,8 +153,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u32 i, m_size = (u32)m.size(); u32 rounds = - MIN(AUTOTOKENS_CHANGE_MAX, - MAX(AUTOTOKENS_CHANGE_MIN, + MIN(change_max, + MAX(change_min, MIN(m_size >> 3, HAVOC_CYCLES * afl_ptr->queue_cur->perf_score * afl_ptr->havoc_div / 256))); // DEBUGF(stderr, "structure size: %lu, rounds: %u \n", m.size(), rounds); @@ -1162,7 +1164,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { learn_dictionary_tokens = atoi(getenv("AUTOTOKENS_LEARN_DICT")); if (learn_dictionary_tokens < 0 || learn_dictionary_tokens > 2) { - learn_dictionary_tokens = 2; + learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; } @@ -1175,6 +1177,22 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { } + if (getenv("AUTOTOKENS_CHANGE_MIN")) { + + change_min = atoi(getenv("AUTOTOKENS_CHANGE_MIN")); + if (change_min < 1 || change_min > 256) { change_min = AUTOTOKENS_CHANGE_MIN; } + + } + + if (getenv("AUTOTOKENS_CHANGE_MAX")) { + + change_max = atoi(getenv("AUTOTOKENS_CHANGE_MAX")); + if (change_max < 1 || change_max > 4096) { change_max = AUTOTOKENS_CHANGE_MAX; } + + } + + if (change_max < change_min) { change_max = change_min + 1; } + if (getenv("AUTOTOKENS_WHITESPACE")) { whitespace = getenv("AUTOTOKENS_WHITESPACE"); From ca063c92d20f4dee6ae9fd1d48dc531768b14ca5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Feb 2023 08:52:12 +0100 Subject: [PATCH 128/300] more options --- include/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config.h b/include/config.h index ed8b844c..49d09174 100644 --- a/include/config.h +++ b/include/config.h @@ -494,7 +494,7 @@ /* What is the minimum percentage of ascii characters present to be classifed as "is_ascii"? */ -#define AFL_TXT_MIN_PERCENT 98 +#define AFL_TXT_MIN_PERCENT 99 /* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ From ca2e8a1bf65d6f5d33244c9c7971a21294dc932b Mon Sep 17 00:00:00 2001 From: Dawin Schmidt Date: Mon, 6 Feb 2023 08:38:20 -0500 Subject: [PATCH 129/300] Add Qemu deferred initialization example --- .../README.deferred_initialization_example.md | 201 ++++++++++++++++++ qemu_mode/README.md | 2 + 2 files changed, 203 insertions(+) create mode 100644 qemu_mode/README.deferred_initialization_example.md diff --git a/qemu_mode/README.deferred_initialization_example.md b/qemu_mode/README.deferred_initialization_example.md new file mode 100644 index 00000000..0ba04b79 --- /dev/null +++ b/qemu_mode/README.deferred_initialization_example.md @@ -0,0 +1,201 @@ +# Fuzz ARM32 Python Native Extensions in Binary-only Mode (LLVM fork-based) + +This is an example on how to fuzz Python native extensions in LLVM mode with deferred initialization on ARM32. + +We use Ubuntu x86_64 to run AFL++ and an Alpine ARMv7 Chroot to build the fuzzing target. + +Check [Resources](#resources) for the code used in this example. + +## Setup Alpine ARM Chroot on your x86_64 Linux Host + +### Use systemd-nspawn + +1. Install `qemu-user-binfmt`, `qemu-user-static` and `systemd-container` dependencies. +2. Restart the systemd-binfmt service: `systemctl restart systemd-binfmt.service` +3. Download an Alpine ARM RootFS from https://alpinelinux.org/downloads/ +4. Create a new `alpine_sysroot` folder and extract: `tar xfz alpine-minirootfs-3.17.1-armv7.tar.gz -C alpine_sysroot/` +5. Copy `qemu-arm-static` to Alpine's RootFS: `cp $(which qemu-arm-static) ./alpine/usr/bin/` +6. Chroot into the container: `sudo systemd-nspawn -D alpine/ --bind-ro=/etc/resolv.conf` +7. Install dependencies: `apk update && apk add build-base musl-dev clang15 python3 python3-dev py3-pip` +8. Exit the container with `exit` + +### Alternatively use Docker + +1. Install `qemu-user-binfmt` and `qemu-user-static` +2. Run Qemu container: ```$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes``` +3. Run Alpine container: ```$ docker run -it --rm arm32v7/alpine sh``` + +## Build AFL++ Qemu Mode with ARM Support + +First, build AFL++ as described [here](https://github.com/AFLplusplus/AFLplusplus/blob/dev/docs/INSTALL.md). Then, run the Qemu build script: + +```bash +cd qemu_mode && CPU_TARGET=arm ./build_qemu_support.sh +``` + +## Compile and Build the Fuzzing Project +Build the native extension and the fuzzing harness for ARM using the Alpine container (check [Resources](#resources) for the code): +```bash +ALPINE_ROOT= +FUZZ= +sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz +CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /fuzz +clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness.a /fuzz/fuzz_harness.c +exit +``` + +Manually trigger bug: +```bash +echo -n "FUZZ" | qemu-arm-static -L $ALPINE_ROOT $FUZZ/fuzz_harness.a +``` + +## Run AFL++ +Make sure to start the forkserver *after* loading all the shared objects by setting the `AFL_ENTRYPOINT` environment variable (see [here](https://aflplus.plus/docs/env_variables/#5-settings-for-afl-qemu-trace) for details): + +Choose an address just before the `while()` loop, for example: +```bash +qemu-arm-static -L $ALPINE_ROOT $ALPINE_ROOT/usr/bin/objdump -d $FUZZ/fuzz_harness.a | grep -A 1 "PyObject_GetAttrString" + +00000584 : + 584: e28fc600 add ip, pc, #0, 12 +-- + 7c8: ebffff6d bl 584 + 7cc: e58d0008 str r0, [sp, #8] +... +``` + +Check Qemu memory maps using the instructions from [here](https://aflplus.plus/docs/tutorials/libxml2_tutorial/): +>The binary is position independent and QEMU persistent needs the real addresses, not the offsets. Fortunately, QEMU loads PIE executables at a fixed address, 0x4000000000 for x86_64. +> +> We can check it using `AFL_QEMU_DEBUG_MAPS`. You don’t need this step if your binary is not PIE. + +Setup Python environment variables and run `afl-qemu-trace`: +```bash +PYTHONPATH=$ALPINE_ROOT/usr/lib/python3.10/ PYTHONHOME=$ALPINE_ROOT/usr/bin/ QEMU_LD_PREFIX=$ALPINE_ROOT AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace $FUZZ/fuzz_harness.a + +... +40000000-40001000 r-xp 00000000 103:03 8002276 fuzz_harness.a +40001000-4001f000 ---p 00000000 00:00 0 +4001f000-40020000 r--p 0000f000 103:03 8002276 fuzz_harness.a +40020000-40021000 rw-p 00010000 103:03 8002276 fuzz_harness.a +40021000-40022000 ---p 00000000 00:00 0 +40022000-40023000 rw-p 00000000 00:00 0 +``` + +Finally, setup Qemu environment variables... +```bash +export QEMU_SET_ENV=PYTHONPATH=$ALPINE_ROOT/usr/lib/python310.zip:$ALPINE_ROOT/usr/lib/python3.10:$ALPINE_ROOT/usr/lib/python3.10/lib-dynload:$ALPINE_ROOT/usr/lib/python3.10/site-packages,PYTHONHOME=$ALPINE_ROOT/usr/bin/ +export QEMU_LD_PREFIX=$ALPINE_ROOT +``` + +... and run AFL++: +```bash +mkdir -p $FUZZ/in && echo -n "FU" > $FUZZ/in/seed +AFL_ENTRYPOINT=0x400007cc afl-fuzz -i $FUZZ/in -o $FUZZ/out -Q -- $FUZZ/fuzz_harness.a +``` + +## Resources + +### setup.py + +```python +from distutils.core import setup, Extension + +module = Extension("memory", sources=["fuzz_target.c"]) + +setup( + name="memory", + version="1.0", + description='A simple "BOOM!" extension', + ext_modules=[module], +) +``` + +### fuzz_target.c + +```c +#define PY_SSIZE_T_CLEAN +#include + +#pragma clang optimize off + +static PyObject *corruption(PyObject* self, PyObject* args) { + char arr[3]; + Py_buffer name; + + if (!PyArg_ParseTuple(args, "y*", &name)) + return NULL; + + if (name.buf != NULL) { + if (strcmp(name.buf, "FUZZ") == 0) { + arr[0] = 'B'; + arr[1] = 'O'; + arr[2] = 'O'; + arr[3] = 'M'; + } + } + + PyBuffer_Release(&name); + Py_RETURN_NONE; +} + +static PyMethodDef MemoryMethods[] = { + {"corruption", corruption, METH_VARARGS, "BOOM!"}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef memory_module = { + PyModuleDef_HEAD_INIT, + "memory", + "BOOM!", + -1, + MemoryMethods +}; + +PyMODINIT_FUNC PyInit_memory(void) { + return PyModule_Create(&memory_module); +} +``` + +### fuzz_harness.c + +```c +#include + +#pragma clang optimize off + +int main(int argc, char **argv) { + unsigned char buf[1024000]; + ssize_t size; + + Py_Initialize(); + PyObject* name = PyUnicode_DecodeFSDefault("memory"); + PyObject* module = PyImport_Import(name); + Py_DECREF(name); + + if (module != NULL) { + PyObject* corruption_func = PyObject_GetAttrString(module, "corruption"); + + while ((size = read(0, buf, sizeof(buf))) > 0 ? 1 : 0) { + PyObject* arg = PyBytes_FromStringAndSize((char *)buf, size); + + if (arg != NULL) { + PyObject* res = PyObject_CallFunctionObjArgs(corruption_func, arg, NULL); + + if (res != NULL) { + Py_XDECREF(res); + } + + Py_DECREF(arg); + } + } + + Py_DECREF(corruption_func); + Py_DECREF(module); + } + + // Py_Finalize() leaks memory on certain Python versions (see https://bugs.python.org/issue1635741) + // Py_Finalize(); + return 0; +} +``` diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 4ed2f298..92038737 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -66,6 +66,8 @@ allows to move the forkserver to a different part, e.g., just before the file is opened (e.g., way after command line parsing and config file loading, etc.) which can be a huge speed improvement. +For an example, see [README.deferred_initialization_example.md](README.deferred_initialization_example.md). + ## 4) Persistent mode AFL++'s QEMU mode now supports also persistent mode for x86, x86_64, arm, and From 24e36212d507422bbbff78a514791d7f8d47301e Mon Sep 17 00:00:00 2001 From: Dawin Schmidt Date: Mon, 6 Feb 2023 09:04:33 -0500 Subject: [PATCH 130/300] Rename fuzzing harness --- .../README.deferred_initialization_example.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/qemu_mode/README.deferred_initialization_example.md b/qemu_mode/README.deferred_initialization_example.md index 0ba04b79..d940d6b5 100644 --- a/qemu_mode/README.deferred_initialization_example.md +++ b/qemu_mode/README.deferred_initialization_example.md @@ -40,13 +40,13 @@ ALPINE_ROOT= FUZZ= sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /fuzz -clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness.a /fuzz/fuzz_harness.c +clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c exit ``` Manually trigger bug: ```bash -echo -n "FUZZ" | qemu-arm-static -L $ALPINE_ROOT $FUZZ/fuzz_harness.a +echo -n "FUZZ" | qemu-arm-static -L $ALPINE_ROOT $FUZZ/fuzz_harness ``` ## Run AFL++ @@ -54,7 +54,7 @@ Make sure to start the forkserver *after* loading all the shared objects by sett Choose an address just before the `while()` loop, for example: ```bash -qemu-arm-static -L $ALPINE_ROOT $ALPINE_ROOT/usr/bin/objdump -d $FUZZ/fuzz_harness.a | grep -A 1 "PyObject_GetAttrString" +qemu-arm-static -L $ALPINE_ROOT $ALPINE_ROOT/usr/bin/objdump -d $FUZZ/fuzz_harness | grep -A 1 "PyObject_GetAttrString" 00000584 : 584: e28fc600 add ip, pc, #0, 12 @@ -71,13 +71,13 @@ Check Qemu memory maps using the instructions from [here](https://aflplus.plus/d Setup Python environment variables and run `afl-qemu-trace`: ```bash -PYTHONPATH=$ALPINE_ROOT/usr/lib/python3.10/ PYTHONHOME=$ALPINE_ROOT/usr/bin/ QEMU_LD_PREFIX=$ALPINE_ROOT AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace $FUZZ/fuzz_harness.a +PYTHONPATH=$ALPINE_ROOT/usr/lib/python3.10/ PYTHONHOME=$ALPINE_ROOT/usr/bin/ QEMU_LD_PREFIX=$ALPINE_ROOT AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace $FUZZ/fuzz_harness ... -40000000-40001000 r-xp 00000000 103:03 8002276 fuzz_harness.a +40000000-40001000 r-xp 00000000 103:03 8002276 fuzz_harness 40001000-4001f000 ---p 00000000 00:00 0 -4001f000-40020000 r--p 0000f000 103:03 8002276 fuzz_harness.a -40020000-40021000 rw-p 00010000 103:03 8002276 fuzz_harness.a +4001f000-40020000 r--p 0000f000 103:03 8002276 fuzz_harness +40020000-40021000 rw-p 00010000 103:03 8002276 fuzz_harness 40021000-40022000 ---p 00000000 00:00 0 40022000-40023000 rw-p 00000000 00:00 0 ``` @@ -91,7 +91,7 @@ export QEMU_LD_PREFIX=$ALPINE_ROOT ... and run AFL++: ```bash mkdir -p $FUZZ/in && echo -n "FU" > $FUZZ/in/seed -AFL_ENTRYPOINT=0x400007cc afl-fuzz -i $FUZZ/in -o $FUZZ/out -Q -- $FUZZ/fuzz_harness.a +AFL_ENTRYPOINT=0x400007cc afl-fuzz -i $FUZZ/in -o $FUZZ/out -Q -- $FUZZ/fuzz_harness ``` ## Resources From dbfa23b40a6bdd1b8affc3920c68f11a6e63b231 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Feb 2023 16:38:46 +0100 Subject: [PATCH 131/300] fixes --- instrumentation/afl-compiler-rt.o.c | 10 +++++++--- src/afl-fuzz-one.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index b1ce4427..9871d7f4 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1518,9 +1518,13 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { _is_sancov = 1; - __afl_auto_first(); - __afl_auto_second(); - __afl_auto_early(); + if (!getenv("AFL_DUMP_MAP_SIZE")) { + + __afl_auto_first(); + __afl_auto_second(); + __afl_auto_early(); + + } if (__afl_debug) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 97855607..6367f597 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5798,7 +5798,7 @@ void pso_updating(afl_state_t *afl) { u8 fuzz_one(afl_state_t *afl) { - int key_val_lv_1 = 0, key_val_lv_2 = 0; + int key_val_lv_1 = -1, key_val_lv_2 = -1; #ifdef _AFL_DOCUMENT_MUTATIONS @@ -5840,7 +5840,7 @@ u8 fuzz_one(afl_state_t *afl) { } - return (key_val_lv_1 | key_val_lv_2); + return (key_val_lv_1 == 0 || key_val_lv_2 == 0 ? 0 : 1 ); } From 6596284cc41484ec5062ca53109ec5bd7899e56f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Feb 2023 17:59:17 +0100 Subject: [PATCH 132/300] endless loop fix --- src/afl-fuzz.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b8114a7f..748c7acf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2210,8 +2210,8 @@ int main(int argc, char **argv_orig, char **envp) { cull_queue(afl); // ensure we have at least one seed that is not disabled. - u32 entry, valid_seeds = 0; - for (entry = 0; entry < afl->queued_items; ++entry) + u32 valid_seeds = 0; + for (u32 entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; } if (!afl->pending_not_fuzzed || !valid_seeds) { @@ -2241,7 +2241,7 @@ int main(int argc, char **argv_orig, char **envp) { u64 max_ms = 0; - for (entry = 0; entry < afl->queued_items; ++entry) + for (u32 entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) if (afl->queue_buf[entry]->exec_us > max_ms) max_ms = afl->queue_buf[entry]->exec_us; @@ -2285,7 +2285,7 @@ int main(int argc, char **argv_orig, char **envp) { #ifdef INTROSPECTION u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; #endif - u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1; + u32 skip_count = 0, prev_queued_items = 0, runs_in_current_cycle = (u32)-1; u8 skipped_fuzz; #ifdef INTROSPECTION @@ -2547,8 +2547,57 @@ int main(int argc, char **argv_orig, char **envp) { } skipped_fuzz = fuzz_one(afl); + + if (unlikely(skipped_fuzz)) { + + ++skip_count; + + if (unlikely(skip_count > afl->active_items)) { + + if (afl->active_items > 1 && !afl->old_seed_selection) { + + u32 found = 0; + for (u32 i = 0; i < afl->queued_items; ++i) { + + if (likely(afl->queue_buf[i]->disabled && + !afl->queue_buf[i]->perf_score)) { + + ++found; + + } + + } + + if (found >= afl->active_items) { + + // all active items have a perf_score of 0 ... damn + for (u32 i = 0; i < afl->queued_items; ++i) { + + if (likely(afl->queue_buf[i]->disabled)) { + + afl->queue_buf[i]->perf_score = afl->queue_buf[i]->weight; + + } + + } + + } + + } + + skip_count = 0; + + } + + } else { + + skip_count = 0; + + } + #ifdef INTROSPECTION ++afl->queue_cur->stats_selected; + if (unlikely(skipped_fuzz)) { ++afl->queue_cur->stats_skipped; From 03e6d33a4044115c44afeb6c1ae735c0310018af Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 7 Feb 2023 15:27:31 +0100 Subject: [PATCH 133/300] fix perfscore 0 check --- src/afl-fuzz.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 748c7acf..8c2eb5b7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2559,8 +2559,8 @@ int main(int argc, char **argv_orig, char **envp) { u32 found = 0; for (u32 i = 0; i < afl->queued_items; ++i) { - if (likely(afl->queue_buf[i]->disabled && - !afl->queue_buf[i]->perf_score)) { + if (likely(!afl->queue_buf[i]->disabled && + afl->queue_buf[i]->perf_score == 0)) { ++found; @@ -2573,7 +2573,7 @@ int main(int argc, char **argv_orig, char **envp) { // all active items have a perf_score of 0 ... damn for (u32 i = 0; i < afl->queued_items; ++i) { - if (likely(afl->queue_buf[i]->disabled)) { + if (likely(!afl->queue_buf[i]->disabled)) { afl->queue_buf[i]->perf_score = afl->queue_buf[i]->weight; From ab26356bf73f2242555e6be72a004082fa22d402 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Tue, 7 Feb 2023 19:50:07 +0300 Subject: [PATCH 134/300] Increase fuzz_level for mopt_common_fuzzing Change performance score calculation for lin and quad power schedules --- src/afl-fuzz-one.c | 1 + src/afl-fuzz-queue.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 6367f597..76826945 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5683,6 +5683,7 @@ pacemaker_fuzzing: } /* block */ + ++afl->queue_cur->fuzz_level; return ret_val; } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index e3faa392..ebfc252c 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -1007,10 +1007,16 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { break; case LIN: + // Don't modify perf_score for unfuzzed seeds + if (!q->fuzz_level) break; + factor = q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1); break; case QUAD: + // Don't modify perf_score for unfuzzed seeds + if (!q->fuzz_level) break; + factor = q->fuzz_level * q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1); break; From 846e910e0c6d09808ea6f87b59e2cf79769979dc Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 8 Feb 2023 13:50:03 +0300 Subject: [PATCH 135/300] Validate -M and -p power schedule options --- src/afl-fuzz.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8c2eb5b7..de41600b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1297,6 +1297,12 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->is_main_node == 1 && afl->schedule != FAST && afl->schedule != EXPLORE) { + + FATAL("-M is compatible only with fast and explore -p power schedules"); + + } + if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) { usage(argv[0], show_help); From 05b1189a55b573a4021abed078dab098f4591ad6 Mon Sep 17 00:00:00 2001 From: Marcello Maugeri Date: Wed, 8 Feb 2023 15:53:49 +0100 Subject: [PATCH 136/300] Update afl-forkserver.c Fix typo --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 89d01460..5aa4c2ff 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1370,7 +1370,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, case Crash: case Asan: return FSRV_RUN_CRASH; - case Timout: + case Timeout: return FSRV_RUN_TMOUT; case InvalidWriteToPayload: /* ??? */ From c86d06849b46865f126a522b7b4c8eb0f72c6ba1 Mon Sep 17 00:00:00 2001 From: Marcello Maugeri Date: Wed, 8 Feb 2023 15:54:27 +0100 Subject: [PATCH 137/300] Update forkserver.h Fix typo --- include/forkserver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/forkserver.h b/include/forkserver.h index 35bc1771..50898a08 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -43,7 +43,7 @@ typedef enum NyxReturnValue { Normal, Crash, Asan, - Timout, + Timeout, InvalidWriteToPayload, Error, IoError, From f2be73186e2e16c3992f92b65ae9ba598d6fff2f Mon Sep 17 00:00:00 2001 From: Yaakov Saxon Date: Thu, 9 Feb 2023 21:37:35 +0000 Subject: [PATCH 138/300] cmplog exec with target_path --- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 8967d4bc..2bf26d19 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -41,7 +41,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { } - execv(argv[0], argv); + execv(fsrv->target_path, argv); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8c2eb5b7..e7fd3dfe 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2081,6 +2081,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; + afl->cmplog_fsrv.target_path = afl->fsrv.target_path; afl->cmplog_fsrv.init_child_func = cmplog_exec_child; if ((map_size <= DEFAULT_SHMEM_SIZE || From 673a0a3866783bf28e31d14fbd7a9009c7816ec3 Mon Sep 17 00:00:00 2001 From: Yaakov Saxon Date: Thu, 9 Feb 2023 22:02:47 +0000 Subject: [PATCH 139/300] add test for unprefixed path --- frida_mode/test/cmplog/GNUmakefile | 17 +++++++++++++++-- frida_mode/test/cmplog/Makefile | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/frida_mode/test/cmplog/GNUmakefile b/frida_mode/test/cmplog/GNUmakefile index bcaff42d..fca52f82 100644 --- a/frida_mode/test/cmplog/GNUmakefile +++ b/frida_mode/test/cmplog/GNUmakefile @@ -2,8 +2,9 @@ PWD:=$(shell pwd)/ ROOT:=$(PWD)../../../ BUILD_DIR:=$(PWD)build/ +TEST_CMPLOG_BASENAME=compcovtest TEST_CMPLOG_SRC=$(PWD)cmplog.c -TEST_CMPLOG_OBJ=$(BUILD_DIR)compcovtest +TEST_CMPLOG_OBJ=$(BUILD_DIR)$(TEST_CMPLOG_BASENAME) TEST_BIN:=$(PWD)../../build/test @@ -13,7 +14,7 @@ CMP_LOG_INPUT:=$(TEST_DATA_DIR)in QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -.PHONY: all 32 clean qemu frida frida-nocmplog format +.PHONY: all 32 clean qemu frida frida-nocmplog frida-unprefixedpath format all: $(TEST_CMPLOG_OBJ) make -C $(ROOT)frida_mode/ @@ -64,6 +65,18 @@ frida-nocmplog: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) -- \ $(TEST_CMPLOG_OBJ) @@ + +frida-unprefixedpath: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) + PATH=$(BUILD_DIR) $(ROOT)afl-fuzz \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -c 0 \ + -l 3AT \ + -Z \ + -- \ + $(TEST_CMPLOG_BASENAME) @@ + debug: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) gdb \ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ diff --git a/frida_mode/test/cmplog/Makefile b/frida_mode/test/cmplog/Makefile index 7ca9a9a5..b84e9218 100644 --- a/frida_mode/test/cmplog/Makefile +++ b/frida_mode/test/cmplog/Makefile @@ -19,6 +19,9 @@ frida: frida-nocmplog: @gmake frida-nocmplog +frida-unprefixedpath: + @gmake frida-unprefixedpath + format: @gmake format From d3cdeabf9297ed2b5a5c06ce5b59980d41cdcb40 Mon Sep 17 00:00:00 2001 From: Yaakov Saxon Date: Thu, 9 Feb 2023 22:04:18 +0000 Subject: [PATCH 140/300] Add myself to contributors :) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index eeab7aa1..821b8cb7 100644 --- a/README.md +++ b/README.md @@ -228,6 +228,7 @@ Thank you! (For people sending pull requests - please add yourself to this list Thomas Rooijakkers David Carlier Ruben ten Hove Joey Jiao fuzzah @intrigus-lgtm + Yaakov Saxon ``` From 141c324eb935ddd25a9ea898bf94ed4f3afb7a79 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 12 Feb 2023 17:55:16 +0100 Subject: [PATCH 141/300] revert perfscore 0 fix attempt --- src/afl-fuzz.c | 56 ++++---------------------------------------------- 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e7fd3dfe..6bd81304 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2211,8 +2211,8 @@ int main(int argc, char **argv_orig, char **envp) { cull_queue(afl); // ensure we have at least one seed that is not disabled. - u32 valid_seeds = 0; - for (u32 entry = 0; entry < afl->queued_items; ++entry) + u32 entry, valid_seeds = 0; + for (entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; } if (!afl->pending_not_fuzzed || !valid_seeds) { @@ -2242,7 +2242,7 @@ int main(int argc, char **argv_orig, char **envp) { u64 max_ms = 0; - for (u32 entry = 0; entry < afl->queued_items; ++entry) + for (entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) if (afl->queue_buf[entry]->exec_us > max_ms) max_ms = afl->queue_buf[entry]->exec_us; @@ -2286,7 +2286,7 @@ int main(int argc, char **argv_orig, char **envp) { #ifdef INTROSPECTION u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; #endif - u32 skip_count = 0, prev_queued_items = 0, runs_in_current_cycle = (u32)-1; + u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1; u8 skipped_fuzz; #ifdef INTROSPECTION @@ -2548,54 +2548,6 @@ int main(int argc, char **argv_orig, char **envp) { } skipped_fuzz = fuzz_one(afl); - - if (unlikely(skipped_fuzz)) { - - ++skip_count; - - if (unlikely(skip_count > afl->active_items)) { - - if (afl->active_items > 1 && !afl->old_seed_selection) { - - u32 found = 0; - for (u32 i = 0; i < afl->queued_items; ++i) { - - if (likely(!afl->queue_buf[i]->disabled && - afl->queue_buf[i]->perf_score == 0)) { - - ++found; - - } - - } - - if (found >= afl->active_items) { - - // all active items have a perf_score of 0 ... damn - for (u32 i = 0; i < afl->queued_items; ++i) { - - if (likely(!afl->queue_buf[i]->disabled)) { - - afl->queue_buf[i]->perf_score = afl->queue_buf[i]->weight; - - } - - } - - } - - } - - skip_count = 0; - - } - - } else { - - skip_count = 0; - - } - #ifdef INTROSPECTION ++afl->queue_cur->stats_selected; From 3881ccd0b7520f67fd0b34f010443dc249cbc8f1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 07:16:47 +0100 Subject: [PATCH 142/300] enable arm64 container build again --- .github/workflows/container.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 4599c335..8836997d 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -47,8 +47,8 @@ jobs: uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 -# with: -# platforms: arm64 + with: + platforms: arm64 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to docker.io @@ -69,8 +69,7 @@ jobs: uses: docker/build-push-action@v3 with: context: . - platforms: linux/amd64 -# ,linux/arm64 + platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.push-tags.outputs.PUSH_TAGS }} cache-from: type=gha From 7eaef449a1e92999c89df23ab474b3be3da595f8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 08:14:04 +0100 Subject: [PATCH 143/300] remove ALTERNATIVE_TOKENIZE --- custom_mutators/autotokens/autotokens.cpp | 548 ++++++---------------- 1 file changed, 149 insertions(+), 399 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index ee35c68b..a027ac2b 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -22,7 +22,6 @@ extern "C" { #define AUTOTOKENS_DEBUG 0 #define AUTOTOKENS_ONLY_FAV 0 -#define AUTOTOKENS_ALTERNATIVE_TOKENIZE 0 #define AUTOTOKENS_CHANGE_MIN 8 #define AUTOTOKENS_CHANGE_MAX 64 #define AUTOTOKENS_WHITESPACE " " @@ -60,7 +59,6 @@ typedef struct my_mutator { static afl_state *afl_ptr; static int debug = AUTOTOKENS_DEBUG; static int only_fav = AUTOTOKENS_ONLY_FAV; -static int alternative_tokenize = AUTOTOKENS_ALTERNATIVE_TOKENIZE; static int learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; static int fuzz_count_shift = AUTOTOKENS_FUZZ_COUNT_SHIFT; static int create_from_thin_air = AUTOTOKENS_CREATE_FROM_THIN_AIR; @@ -142,7 +140,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, (void)(data); - if (s == NULL) { + if (unlikely(s == NULL)) { *out_buf = NULL; return 0; @@ -183,9 +181,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } while (unlikely( new_item == cur_item || - (!alternative_tokenize && - ((whitespace_ids < new_item && whitespace_ids >= cur_item) || - (whitespace_ids >= new_item && whitespace_ids < cur_item))))); + ((whitespace_ids < new_item && whitespace_ids >= cur_item) || + (whitespace_ids >= new_item && whitespace_ids < cur_item)))); DEBUGF(stderr, "MUT: %u -> %u\n", cur_item, new_item); m[pos] = new_item; @@ -200,37 +197,33 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, new_item = rand_below(afl_ptr, current_id); - } while (unlikely(!alternative_tokenize && new_item >= whitespace_ids)); + } while (unlikely(new_item >= whitespace_ids)); u32 pos = rand_below(afl_ptr, m_size + 1); m.insert(m.begin() + pos, new_item); ++m_size; DEBUGF(stderr, "INS: %u at %u\n", new_item, pos); - if (likely(!alternative_tokenize)) { + // if we insert an identifier or string we might need whitespace + if (id_to_token[new_item].size() > 1) { - // if we insert an identifier or string we might need whitespace - if (id_to_token[new_item].size() > 1) { + // need to insert before? - // need to insert before? + if (pos && m[pos - 1] >= whitespace_ids && + id_to_token[m[pos - 1]].size() > 1) { - if (pos && m[pos - 1] >= whitespace_ids && - id_to_token[m[pos - 1]].size() > 1) { + m.insert(m.begin() + pos, good_whitespace_or_singleval()); + ++m_size; - m.insert(m.begin() + pos, good_whitespace_or_singleval()); - ++m_size; + } - } + if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && + id_to_token[m[pos + 1]].size() > 1) { - if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && - id_to_token[m[pos + 1]].size() > 1) { + // need to insert after? - // need to insert after? - - m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); - ++m_size; - - } + m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); + ++m_size; } @@ -290,26 +283,22 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } - if (likely(!alternative_tokenize)) { + // do we need a whitespace/token at the beginning? + if (dst_off && id_to_token[m[dst_off - 1]].size() > 1 && + id_to_token[m[dst_off]].size() > 1) { - // do we need a whitespace/token at the beginning? - if (dst_off && id_to_token[m[dst_off - 1]].size() > 1 && - id_to_token[m[dst_off]].size() > 1) { + m.insert(m.begin() + dst_off, good_whitespace_or_singleval()); + ++m_size; - m.insert(m.begin() + dst_off, good_whitespace_or_singleval()); - ++m_size; + } - } + // do we need a whitespace/token at the end? + if (dst_off + n < m_size && + id_to_token[m[dst_off + n - 1]].size() > 1 && + id_to_token[m[dst_off + n]].size() > 1) { - // do we need a whitespace/token at the end? - if (dst_off + n < m_size && - id_to_token[m[dst_off + n - 1]].size() > 1 && - id_to_token[m[dst_off + n]].size() > 1) { - - m.insert(m.begin() + dst_off + n, good_whitespace_or_singleval()); - ++m_size; - - } + m.insert(m.begin() + dst_off + n, good_whitespace_or_singleval()); + ++m_size; } @@ -332,8 +321,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, // if what we delete will result in a missing whitespace/token, // instead of deleting we switch the item to a whitespace or token. - if (likely(!alternative_tokenize) && pos && pos + 1 < m_size && - id_to_token[m[pos - 1]].size() > 1 && + if (pos && pos + 1 < m_size && id_to_token[m[pos - 1]].size() > 1 && id_to_token[m[pos + 1]].size() > 1) { m[pos] = good_whitespace_or_singleval(); @@ -362,17 +350,11 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } - u32 m_size_1 = m_size - 1; output = ""; for (i = 0; i < m_size; ++i) { output += id_to_token[m[i]]; - if (unlikely(alternative_tokenize && i < m_size_1)) { - - output += whitespace; - - } } @@ -725,336 +707,107 @@ extern "C" unsigned char afl_custom_queue_get(void *data, DEBUGF(stderr, "START!\n"); - if (likely(!alternative_tokenize)) { + while (my_search_string(cur, ende, &match_begin, &match_end)) { - while (my_search_string(cur, ende, &match_begin, &match_end)) { + prev = cur; + found = match_begin; + cur = match_end; - prev = cur; - found = match_begin; - cur = match_end; + IFDEBUG { - IFDEBUG { + string foo(match_begin, match_end); + DEBUGF(stderr, + "string %s found at start %lu offset %lu continue at %lu\n", + foo.c_str(), prev - input.begin(), found - prev, + cur - input.begin()); - string foo(match_begin, match_end); - DEBUGF(stderr, - "string %s found at start %lu offset %lu continue at %lu\n", - foo.c_str(), prev - input.begin(), found - prev, - cur - input.begin()); + } - } + if (prev < found) { // there are items between search start and find + while (prev < found) { - if (prev < found) { // there are items between search start and find - while (prev < found) { + if (isspace(*prev)) { - if (isspace(*prev)) { + auto start = prev; + while (isspace(*prev)) { - auto start = prev; - while (isspace(*prev)) { - - ++prev; - - } - - tokens.push_back(std::string(start, prev)); - DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, - tokens[tokens.size() - 1].c_str()); - - } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { - - auto start = prev; - while (isalnum(*prev) || *prev == '$' || *prev == '_' || - *prev == '.' || *prev == '/') { - - ++prev; - - } - - tokens.push_back(string(start, prev)); - DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, - tokens[tokens.size() - 1].c_str()); - - } else { - - tokens.push_back(string(prev, prev + 1)); - DEBUGF(stderr, "OTHER \"%c\"\n", *prev); ++prev; } - } - - } - - tokens.push_back(string(match_begin, match_end)); - DEBUGF(stderr, "TOK: %s\n", tokens[tokens.size() - 1].c_str()); - - } - - DEBUGF(stderr, "AFTER all strings\n"); - - if (cur < ende) { - - while (cur < ende) { - - if (isspace(*cur)) { - - auto start = cur; - while (isspace(*cur)) { - - ++cur; - - } - - tokens.push_back(std::string(start, cur)); - DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, + tokens.push_back(std::string(start, prev)); + DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", prev - start, tokens[tokens.size() - 1].c_str()); - } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { + } else if (isalnum(*prev) || *prev == '$' || *prev == '_') { - auto start = cur; - while (isalnum(*cur) || *cur == '$' || *cur == '_' || *cur == '.' || - *cur == '/') { + auto start = prev; + while (isalnum(*prev) || *prev == '$' || *prev == '_' || + *prev == '.' || *prev == '/') { - ++cur; + ++prev; } - tokens.push_back(std::string(start, cur)); - DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, + tokens.push_back(string(start, prev)); + DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", prev - start, tokens[tokens.size() - 1].c_str()); } else { - tokens.push_back(std::string(cur, cur + 1)); - DEBUGF(stderr, "OTHER \"%c\"\n", *cur); + tokens.push_back(string(prev, prev + 1)); + DEBUGF(stderr, "OTHER \"%c\"\n", *prev); + ++prev; + + } + + } + + } + + tokens.push_back(string(match_begin, match_end)); + DEBUGF(stderr, "TOK: %s\n", tokens[tokens.size() - 1].c_str()); + + } + + DEBUGF(stderr, "AFTER all strings\n"); + + if (cur < ende) { + + while (cur < ende) { + + if (isspace(*cur)) { + + auto start = cur; + while (isspace(*cur)) { + ++cur; } - } + tokens.push_back(std::string(start, cur)); + DEBUGF(stderr, "WHITESPACE %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); - } + } else if (isalnum(*cur) || *cur == '$' || *cur == '_') { - } else { + auto start = cur; + while (isalnum(*cur) || *cur == '$' || *cur == '_' || *cur == '.' || + *cur == '/') { - // alternative tokenize - while (my_search_string(cur, ende, &match_begin, &match_end)) { - - prev = cur; - found = match_begin; - cur = match_end; - IFDEBUG { - - string foo(match_begin, match_end); - DEBUGF(stderr, - "string %s found at start %lu offset %lu continue at %lu\n", - foo.c_str(), prev - input.begin(), found - prev, - cur - input.begin()); - - } - - if (prev < found) { // there are items between search start and find - - sregex_token_iterator it{prev, found, regex_whitespace, -1}; - vector tokenized{it, {}}; - tokenized.erase(std::remove_if(tokenized.begin(), tokenized.end(), - [](std::string const &s) { - - return s.size() == 0; - - }), - - tokenized.end()); - tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); - - IFDEBUG { - - DEBUGF(stderr, "tokens1: %lu input size: %lu\n", tokenized.size(), - input.size()); - for (auto x : tokenized) { - - cerr << x << endl; - - } + ++cur; } - for (auto token : tokenized) { + tokens.push_back(std::string(start, cur)); + DEBUGF(stderr, "IDENTIFIER %ld \"%s\"\n", cur - start, + tokens[tokens.size() - 1].c_str()); - string::const_iterator c = token.begin(), e = token.end(), f, p; - smatch m; + } else { - while (regex_search(c, e, m, regex_word)) { - - p = c; - f = m[0].first; - c = m[0].second; - if (p < f) { - - // there are items between search start and find - while (p < f) { - - IFDEBUG { - - string foo(p, p + 1); - DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(p, p + 1)); - ++p; - - } - - IFDEBUG { - - string foo(p, f); - DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); - tokens.push_back(std::string(p, f)); - - } - - } - - DEBUGF(stderr, - "SUBstring \"%s\" found at start %lu offset %lu continue " - "at %lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); - tokens.push_back(m[0].str()); - - } - - if (c < e) { - - while (c < e) { - - IFDEBUG { - - string foo(c, c + 1); - DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(c, c + 1)); - ++c; - - } - - IFDEBUG { - - string foo(c, e); - DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(c, e)); - - } - - } - - } - - tokens.push_back(string(match_begin, match_end)); - - } - - if (cur < ende) { - - sregex_token_iterator it{cur, ende, regex_whitespace, -1}; - vector tokenized{it, {}}; - tokenized.erase( - std::remove_if(tokenized.begin(), tokenized.end(), - [](std::string const &s) { return s.size() == 0; }), - tokenized.end()); - tokens.reserve(tokens.size() + tokenized.size() * 2 + 1); - - IFDEBUG { - - DEBUGF(stderr, "tokens2: %lu input size: %lu\n", tokenized.size(), - input.size()); - for (auto x : tokenized) { - - cerr << x << endl; - - } - - } - - for (auto token : tokenized) { - - string::const_iterator c = token.begin(), e = token.end(), f, p; - smatch m; - - while (regex_search(c, e, m, regex_word)) { - - p = c; - f = m[0].first; - c = m[0].second; - if (p < f) { - - // there are items between search start and find - while (p < f) { - - IFDEBUG { - - string foo(p, p + 1); - DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(p, p + 1)); - ++p; - - } - - IFDEBUG { - - string foo(p, f); - DEBUGF(stderr, "before string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(p, f)); - - } - - DEBUGF(stderr, - "SUB2string \"%s\" found at start %lu offset %lu continue " - "at %lu\n", - m[0].str().c_str(), p - input.begin(), m.position(), - c - token.begin()); - tokens.push_back(m[0].str()); - - } - - if (c < e) { - - while (c < e) { - - IFDEBUG { - - string foo(c, c + 1); - DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(c, c + 1)); - ++c; - - } - - IFDEBUG { - - string foo(c, e); - DEBUGF(stderr, "after string: \"%s\"\n", foo.c_str()); - - } - - tokens.push_back(std::string(c, e)); - - } + tokens.push_back(std::string(cur, cur + 1)); + DEBUGF(stderr, "OTHER \"%c\"\n", *cur); + ++cur; } @@ -1065,15 +818,9 @@ extern "C" unsigned char afl_custom_queue_get(void *data, IFDEBUG { DEBUGF(stderr, "DUMPING TOKENS:\n"); - u32 size_1 = tokens.size() - 1; for (u32 i = 0; i < tokens.size(); ++i) { DEBUGF(stderr, "%s", tokens[i].c_str()); - if (unlikely(alternative_tokenize && i < size_1)) { - - DEBUGF(stderr, "%s", whitespace.c_str()); - - } } @@ -1157,7 +904,6 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { if (getenv("AUTOTOKENS_DEBUG")) { debug = 1; } if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } if (getenv("AUTOTOKENS_CREATE_FROM_THIN_AIR")) { create_from_thin_air = 1; } - if (getenv("AUTOTOKENS_ALTERNATIVE_TOKENIZE")) { alternative_tokenize = 1; } if (getenv("AUTOTOKENS_LEARN_DICT")) { @@ -1180,14 +926,22 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { if (getenv("AUTOTOKENS_CHANGE_MIN")) { change_min = atoi(getenv("AUTOTOKENS_CHANGE_MIN")); - if (change_min < 1 || change_min > 256) { change_min = AUTOTOKENS_CHANGE_MIN; } + if (change_min < 1 || change_min > 256) { + + change_min = AUTOTOKENS_CHANGE_MIN; + + } } if (getenv("AUTOTOKENS_CHANGE_MAX")) { change_max = atoi(getenv("AUTOTOKENS_CHANGE_MAX")); - if (change_max < 1 || change_max > 4096) { change_max = AUTOTOKENS_CHANGE_MAX; } + if (change_max < 1 || change_max > 4096) { + + change_max = AUTOTOKENS_CHANGE_MAX; + + } } @@ -1212,53 +966,49 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { // set common whitespace tokens // we deliberately do not put uncommon ones here to these will count as // identifier tokens. - if (!alternative_tokenize) { - - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t"] = current_id; - id_to_token[current_id] = "\t"; - ++current_id; - token_to_id["\n"] = current_id; - id_to_token[current_id] = "\n"; - ++current_id; - token_to_id["\r\n"] = current_id; - id_to_token[current_id] = "\r\n"; - ++current_id; - token_to_id[" \n"] = current_id; - id_to_token[current_id] = " \n"; - ++current_id; - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t\t"] = current_id; - id_to_token[current_id] = "\t\t"; - ++current_id; - token_to_id["\n\n"] = current_id; - id_to_token[current_id] = "\n\n"; - ++current_id; - token_to_id["\r\n\r\n"] = current_id; - id_to_token[current_id] = "\r\n\r\n"; - ++current_id; - token_to_id[" "] = current_id; - id_to_token[current_id] = " "; - ++current_id; - token_to_id["\t\t\t\t"] = current_id; - id_to_token[current_id] = "\t\t\t\t"; - ++current_id; - token_to_id["\n\n\n\n"] = current_id; - id_to_token[current_id] = "\n\n\n\n"; - ++current_id; - whitespace_ids = current_id; - token_to_id["\""] = current_id; - id_to_token[current_id] = "\""; - ++current_id; - token_to_id["'"] = current_id; - id_to_token[current_id] = "'"; - ++current_id; - - } + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t"] = current_id; + id_to_token[current_id] = "\t"; + ++current_id; + token_to_id["\n"] = current_id; + id_to_token[current_id] = "\n"; + ++current_id; + token_to_id["\r\n"] = current_id; + id_to_token[current_id] = "\r\n"; + ++current_id; + token_to_id[" \n"] = current_id; + id_to_token[current_id] = " \n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t"] = current_id; + id_to_token[current_id] = "\t\t"; + ++current_id; + token_to_id["\n\n"] = current_id; + id_to_token[current_id] = "\n\n"; + ++current_id; + token_to_id["\r\n\r\n"] = current_id; + id_to_token[current_id] = "\r\n\r\n"; + ++current_id; + token_to_id[" "] = current_id; + id_to_token[current_id] = " "; + ++current_id; + token_to_id["\t\t\t\t"] = current_id; + id_to_token[current_id] = "\t\t\t\t"; + ++current_id; + token_to_id["\n\n\n\n"] = current_id; + id_to_token[current_id] = "\n\n\n\n"; + ++current_id; + whitespace_ids = current_id; + token_to_id["\""] = current_id; + id_to_token[current_id] = "\""; + ++current_id; + token_to_id["'"] = current_id; + id_to_token[current_id] = "'"; + ++current_id; return data; From 240f6421d8240b4b4d4d5bd509c0c3277a083896 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 08:23:47 +0100 Subject: [PATCH 144/300] optimize performance --- custom_mutators/autotokens/autotokens.cpp | 80 +++++++---------------- 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index a027ac2b..ca738d0b 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -204,31 +204,6 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, ++m_size; DEBUGF(stderr, "INS: %u at %u\n", new_item, pos); - // if we insert an identifier or string we might need whitespace - if (id_to_token[new_item].size() > 1) { - - // need to insert before? - - if (pos && m[pos - 1] >= whitespace_ids && - id_to_token[m[pos - 1]].size() > 1) { - - m.insert(m.begin() + pos, good_whitespace_or_singleval()); - ++m_size; - - } - - if (pos + 1 < m_size && m[pos + 1] >= whitespace_ids && - id_to_token[m[pos + 1]].size() > 1) { - - // need to insert after? - - m.insert(m.begin() + pos + 1, good_whitespace_or_singleval()); - ++m_size; - - } - - } - break; } @@ -283,25 +258,6 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } - // do we need a whitespace/token at the beginning? - if (dst_off && id_to_token[m[dst_off - 1]].size() > 1 && - id_to_token[m[dst_off]].size() > 1) { - - m.insert(m.begin() + dst_off, good_whitespace_or_singleval()); - ++m_size; - - } - - // do we need a whitespace/token at the end? - if (dst_off + n < m_size && - id_to_token[m[dst_off + n - 1]].size() > 1 && - id_to_token[m[dst_off + n]].size() > 1) { - - m.insert(m.begin() + dst_off + n, good_whitespace_or_singleval()); - ++m_size; - - } - break; } @@ -319,19 +275,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } while (unlikely(m[pos] < whitespace_ids)); - // if what we delete will result in a missing whitespace/token, - // instead of deleting we switch the item to a whitespace or token. - if (pos && pos + 1 < m_size && id_to_token[m[pos - 1]].size() > 1 && - id_to_token[m[pos + 1]].size() > 1) { - - m[pos] = good_whitespace_or_singleval(); - - } else { - - m.erase(m.begin() + pos); - --m_size; - - } + m.erase(m.begin() + pos); + --m_size; } else { @@ -350,10 +295,31 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } + /* Now we create the output */ + output = ""; + u32 prev_size = 0; for (i = 0; i < m_size; ++i) { + if (likely(i + 1 < m_size)) { + + u32 this_size = id_to_token[m[i]].size(); + + /* The output we are generating might need repairing. + General rule: two items that have a size larger than 2 are strings + or identifizers and need a whitespace or an item of length 1 in + between. */ + if (unlikely(prev_size > 1 && this_size > 1)) { + + output += id_to_token[good_whitespace_or_singleval()]; + + } + + prev_size = this_size; + + } + output += id_to_token[m[i]]; } From 61439859cece05cd3e204af60bb5ff08556c490d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 08:26:30 +0100 Subject: [PATCH 145/300] cleanup --- custom_mutators/autotokens/README | 4 ---- custom_mutators/autotokens/autotokens.cpp | 8 -------- 2 files changed, 12 deletions(-) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index e9c48662..904b5fa3 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -29,7 +29,3 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! `AUTOTOKENS_CREATE_FROM_THIN_AIR` - if only one small start file is present and a dictionary loaded then create one initial structure based on the dictionary. -`AUTOTOKENS_ALTERNATIVE_TOKENIZE` - use an alternative tokenize implementation - (experimental) -`AUTOTOKENS_WHITESPACE` - whitespace string to use for ALTERNATIVE_TOKENIZE, - default is " " diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index ca738d0b..10afa2c2 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -24,7 +24,6 @@ extern "C" { #define AUTOTOKENS_ONLY_FAV 0 #define AUTOTOKENS_CHANGE_MIN 8 #define AUTOTOKENS_CHANGE_MAX 64 -#define AUTOTOKENS_WHITESPACE " " #define AUTOTOKENS_SIZE_MIN 8 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 @@ -75,7 +74,6 @@ static unordered_map *> file_mapping; static unordered_map *> id_mapping; static unordered_map token_to_id; static unordered_map id_to_token; -static string whitespace = AUTOTOKENS_WHITESPACE; static string output; static regex *regex_comment_custom; // multiline requires g++-11 libs :( @@ -913,12 +911,6 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { if (change_max < change_min) { change_max = change_min + 1; } - if (getenv("AUTOTOKENS_WHITESPACE")) { - - whitespace = getenv("AUTOTOKENS_WHITESPACE"); - - } - if (getenv("AUTOTOKENS_COMMENT")) { char buf[256]; From 54fa78d32ce6779117a656c72f5c630713e7033f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 09:52:57 +0100 Subject: [PATCH 146/300] autodisable and better performance --- custom_mutators/autotokens/Makefile | 12 +- custom_mutators/autotokens/TODO | 21 ---- custom_mutators/autotokens/autotokens.cpp | 143 +++++++++++++++++----- include/config.h | 4 + src/afl-fuzz-queue.c | 89 +++++++++----- 5 files changed, 179 insertions(+), 90 deletions(-) diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile index ab1da4b6..6ee7d324 100644 --- a/custom_mutators/autotokens/Makefile +++ b/custom_mutators/autotokens/Makefile @@ -1,16 +1,22 @@ ifdef debug - CFLAGS += -fsanitize=address -Wall + CPPLAGS += -fsanitize=address + CXXFLAGS += -Wall + CC := clang CXX := clang++ endif ifdef DEBUG - CFLAGS += -fsanitize=address -Wall + CPPFLAGS += -fsanitize=address + CXXFLAGS += -Wall + CC := clang CXX := clang++ endif all: autotokens.so autotokens.so: autotokens.cpp - $(CXX) -g -O3 $(CFLAGS) -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ../../src/afl-performance.o + $(CC) -D_STANDALONE_MODULE=1 -I../../include -g -O3 $(CPPFLAGS) -fPIC -c -o ./afl-fuzz-queue.o ../../src/afl-fuzz-queue.c + $(CC) -I../../include -g -O3 $(CPPFLAGS) -DBIN_PATH=\"dummy\" -Wno-pointer-sign -fPIC -c -o ./afl-common.o ../../src/afl-common.c + $(CXX) -Wno-deprecated -g -O3 $(CXXFLAGS) $(CPPFLAGS) -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ./afl-fuzz-queue.o ../../src/afl-performance.o ./afl-common.o clean: rm -f autotokens.so *~ core diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO index 496bfd45..2e99e147 100644 --- a/custom_mutators/autotokens/TODO +++ b/custom_mutators/autotokens/TODO @@ -1,24 +1,3 @@ -create from thin air if no good seed after a cycle and dict large enough? -(static u32 no_of_struct_inputs;) - -splicing -> check if whitespace/token is needed - -whitespace/token check only AFTER mutation - -analyse welche einen DICT haben, und welche davon rein ascii - -corpus analyse: - + libxml - - sqlite - - libpcap -min len, max len, % wenn 95/98/99/100 ascii - env für menge an per mutation run -AFL_TXT_MAX_LEN 65535 -AFL_TXT_MIN_LEN 16 -AFL_TXT_MIN_PERCENT=99 - --> KEIN FAV! - change_min/_max werte diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 10afa2c2..cda90a38 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -25,10 +25,12 @@ extern "C" { #define AUTOTOKENS_CHANGE_MIN 8 #define AUTOTOKENS_CHANGE_MAX 64 #define AUTOTOKENS_SIZE_MIN 8 +#define AUTOTOKENS_SIZE_MAX 65535 #define AUTOTOKENS_SPLICE_MIN 4 #define AUTOTOKENS_SPLICE_MAX 64 #define AUTOTOKENS_CREATE_FROM_THIN_AIR 0 #define AUTOTOKENS_FUZZ_COUNT_SHIFT 0 +#define AUTOTOKENS_AUTO_DISABLE 0 // 0 = no learning, 1 only from -x dict/autodict, 2 also from cmplog #define AUTOTOKENS_LEARN_DICT 1 #ifndef AUTOTOKENS_SPLICE_DISABLE @@ -56,6 +58,8 @@ typedef struct my_mutator { #define IFDEBUG if (unlikely(debug)) static afl_state *afl_ptr; +static int module_disabled = 0; +static int auto_disable = AUTOTOKENS_AUTO_DISABLE; static int debug = AUTOTOKENS_DEBUG; static int only_fav = AUTOTOKENS_ONLY_FAV; static int learn_dictionary_tokens = AUTOTOKENS_LEARN_DICT; @@ -93,6 +97,99 @@ static void first_run(void *data) { (void)(data); + /* For auto-loading this module we check here if we can analyze from the + input if the inputs look like text inputs and disable the module if + not. */ + + if (afl_ptr->custom_only || !auto_disable) { return; } + + if (unlikely(afl_ptr->active_items == 1 && + afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) { + + if (afl_ptr->extras_cnt > 8) { + + u32 valid = 0; + + while (extras_cnt < afl_ptr->extras_cnt) { + + u32 ok = 1, l = afl_ptr->extras[extras_cnt].len; + u8 *buf, *ptr = afl_ptr->extras[extras_cnt].data; + + for (u32 i = 0; i < l; ++i) { + + if (!isascii((int)ptr[i]) && !isprint((int)ptr[i])) { + + ok = 0; + break; + + } + + } + + if (ok) { + + buf = (u8 *)malloc(afl_ptr->extras[extras_cnt].len + 1); + memcpy(buf, afl_ptr->extras[extras_cnt].data, + afl_ptr->extras[extras_cnt].len); + buf[afl_ptr->extras[extras_cnt].len] = 0; + token_to_id[(char *)buf] = current_id; + id_to_token[current_id] = (char *)buf; + ++current_id; + ++valid; + + } + + ++extras_cnt; + + } + + if ((valid * 100) / afl_ptr->extras_cnt < 95) { module_disabled = 1; } + + } else { + + module_disabled = 1; + + } + + return; + + } + + u32 is_ascii = 0, valid = 0; + + for (u32 i = 0; i < afl_ptr->queued_items; ++i) { + + struct queue_entry *q; + + q = afl_ptr->queue_buf[i]; + + if (!q->disabled && q->len >= AUTOTOKENS_SIZE_MIN && + q->len <= AFL_TXT_MAX_LEN) { + + ++valid; + u8 *input = queue_testcase_get(afl_ptr, q); + + u32 valid_chars = 0; + for (u32 i = 0; i < q->len; ++i) { + + if (isascii((int)input[i]) || isprint((int)input[i])) { ++valid_chars; } + + } + + // we want at least 99% of text characters ... + if (((q->len * AFL_TXT_MIN_PERCENT) / 100) <= valid_chars) { + + ++is_ascii; + q->is_ascii = 1; + + } + + } + + } + + if ((is_ascii * 100) / valid < 70) { module_disabled = 1; } + } static u32 good_whitespace_or_singleval() { @@ -441,21 +538,25 @@ extern "C" unsigned char afl_custom_queue_get(void *data, is_first_run = 0; first_run(data); + if (module_disabled) { WARNF("Autotokens custom module is disabled."); } + } - if (unlikely(!afl_ptr->custom_only) && !create_from_thin_air && - ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || - (only_fav && !afl_ptr->queue_cur->favored))) { + if (likely(module_disabled) || + (unlikely(!afl_ptr->custom_only) && !create_from_thin_air && + ((afl_ptr->shm.cmplog_mode && !afl_ptr->queue_cur->is_ascii) || + (only_fav && !afl_ptr->queue_cur->favored)))) { s = NULL; - DEBUGF(stderr, "cmplog not ascii or only_fav and not favorite\n"); + DEBUGF(stderr, + "cmplog not ascii or only_fav and not favorite or disabled\n"); return 1; } // check if there are new dictionary entries and add them to the tokens - if (likely(valid_structures || create_from_thin_air) && - learn_state < learn_dictionary_tokens) { + if (unlikely(learn_state < learn_dictionary_tokens) && + likely(valid_structures || create_from_thin_air)) { if (unlikely(!learn_state)) { learn_state = 1; } @@ -569,21 +670,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (entry == file_mapping.end()) { // this input file was not analyzed for tokens yet, so let's do it! - - FILE *fp = fopen((char *)filename, "rb"); - if (!fp) { - - s = NULL; - return 1; - - } // should not happen - - fseek(fp, 0, SEEK_END); - size_t len = (size_t)ftell(fp); + size_t len = afl_ptr->queue_cur->len; if (len < AFL_TXT_MIN_LEN) { - fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again s = NULL; DEBUGF(stderr, "Too short (%lu) %s\n", len, filename); @@ -591,7 +681,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } else if (len > AFL_TXT_MAX_LEN) { - fclose(fp); file_mapping[fn] = structure; // NULL ptr so we don't read the file again s = NULL; DEBUGF(stderr, "Too long (%lu) %s\n", len, filename); @@ -599,19 +688,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - string input; - input.resize(len); - rewind(fp); - - if (fread((void *)input.data(), 1, len, fp) != len) { - - s = NULL; - DEBUGF(stderr, "Too short read %s\n", filename); - return 1; - - } - - fclose(fp); + u8 *input_buf = queue_testcase_get(afl_ptr, afl_ptr->queue_cur); + string input((char *)input_buf, afl_ptr->queue_cur->len); if (!afl_ptr->shm.cmplog_mode) { @@ -866,6 +944,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { } if (getenv("AUTOTOKENS_DEBUG")) { debug = 1; } + if (getenv("AUTOTOKENS_AUTO_DISABLE")) { auto_disable = 1; } if (getenv("AUTOTOKENS_ONLY_FAV")) { only_fav = 1; } if (getenv("AUTOTOKENS_CREATE_FROM_THIN_AIR")) { create_from_thin_air = 1; } diff --git a/include/config.h b/include/config.h index 49d09174..ad8b76a8 100644 --- a/include/config.h +++ b/include/config.h @@ -491,6 +491,10 @@ #define AFL_TXT_MIN_LEN 16 +/* Maximum length of a queue input to be evaluated for "is_ascii"? */ + +#define AFL_TXT_MAX_LEN 65535 + /* What is the minimum percentage of ascii characters present to be classifed as "is_ascii"? */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index e3faa392..3c8a3e46 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -27,6 +27,22 @@ #include #include +#ifdef _STANDALONE_MODULE +void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) { + + return; + +} + +void run_afl_custom_queue_new_entry(afl_state_t *afl, struct queue_entry *q, + u8 *a, u8 *b) { + + return; + +} + +#endif + /* select next queue entry based on alias algo - fast! */ inline u32 select_next_queue_entry(afl_state_t *afl) { @@ -78,8 +94,8 @@ void create_alias_table(afl_state_t *afl) { afl->alias_probability = (double *)afl_realloc( (void **)&afl->alias_probability, n * sizeof(double)); double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double)); - int *S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); - int *L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); + int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); + int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) { @@ -247,11 +263,11 @@ void create_alias_table(afl_state_t *afl) { void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { - u8 fn[PATH_MAX]; - s32 fd; + char fn[PATH_MAX]; + s32 fd; snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, - strrchr(q->fname, '/') + 1); + strrchr((char *)q->fname, '/') + 1); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (fd < 0) { PFATAL("Unable to create '%s'", fn); } @@ -266,10 +282,10 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { - u8 fn[PATH_MAX]; - u8 ldest[PATH_MAX]; + char fn[PATH_MAX]; + char ldest[PATH_MAX]; - u8 *fn_name = strrchr(q->fname, '/') + 1; + char *fn_name = strrchr((char *)q->fname, '/') + 1; sprintf(ldest, "../../%s", fn_name); sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name); @@ -293,12 +309,12 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { if (likely(state == q->fs_redundant)) { return; } - u8 fn[PATH_MAX]; + char fn[PATH_MAX]; q->fs_redundant = state; sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, - strrchr(q->fname, '/') + 1); + strrchr((char *)q->fname, '/') + 1); if (state) { @@ -409,7 +425,7 @@ u8 check_if_text_buf(u8 *buf, u32 len) { static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) { - if (q->len < AFL_TXT_MIN_LEN) return 0; + if (q->len < AFL_TXT_MIN_LEN || q->len < AFL_TXT_MAX_LEN) return 0; u8 *buf; int fd; @@ -417,8 +433,8 @@ static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) { ssize_t comp; if (len >= MAX_FILE) len = MAX_FILE - 1; - if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; - buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len + 1); + if ((fd = open((char *)q->fname, O_RDONLY)) < 0) return 0; + buf = (u8 *)afl_realloc(AFL_BUF_PARAM(in_scratch), len + 1); comp = read(fd, buf, len); close(fd); if (comp != (ssize_t)len) return 0; @@ -520,7 +536,8 @@ static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) { void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { - struct queue_entry *q = ck_alloc(sizeof(struct queue_entry)); + struct queue_entry *q = + (struct queue_entry *)ck_alloc(sizeof(struct queue_entry)); q->fname = fname; q->len = len; @@ -554,7 +571,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { afl->cycles_wo_finds = 0; - struct queue_entry **queue_buf = afl_realloc( + struct queue_entry **queue_buf = (struct queue_entry **)afl_realloc( AFL_BUF_PARAM(queue), afl->queued_items * sizeof(struct queue_entry *)); if (unlikely(!queue_buf)) { PFATAL("alloc"); } queue_buf[afl->queued_items - 1] = q; @@ -574,7 +591,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } /* only redqueen currently uses is_ascii */ - if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(afl, q); + if (unlikely(afl->shm.cmplog_mode && !q->is_ascii)) { + + q->is_ascii = check_if_text(afl, q); + + } } @@ -704,7 +725,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!q->trace_mini) { u32 len = (afl->fsrv.map_size >> 3); - q->trace_mini = ck_alloc(len); + q->trace_mini = (u8 *)ck_alloc(len); minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); } @@ -1090,19 +1111,19 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, if (len != old_len) { afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len; - q->testcase_buf = realloc(q->testcase_buf, len); + q->testcase_buf = (u8 *)realloc(q->testcase_buf, len); if (unlikely(!q->testcase_buf)) { - PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); } } - int fd = open(q->fname, O_RDONLY); + int fd = open((char *)q->fname, O_RDONLY); - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); } ck_read(fd, q->testcase_buf, len, q->fname); close(fd); @@ -1122,7 +1143,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, if (likely(len != old_len)) { - u8 *ptr = realloc(q->testcase_buf, len); + u8 *ptr = (u8 *)realloc(q->testcase_buf, len); if (likely(ptr)) { @@ -1154,23 +1175,23 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { if (unlikely(q == afl->queue_cur)) { - buf = afl_realloc((void **)&afl->testcase_buf, len); + buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len); } else { - buf = afl_realloc((void **)&afl->splicecase_buf, len); + buf = (u8 *)afl_realloc((void **)&afl->splicecase_buf, len); } if (unlikely(!buf)) { - PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); } - int fd = open(q->fname, O_RDONLY); + int fd = open((char *)q->fname, O_RDONLY); - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); } ck_read(fd, buf, len, q->fname); close(fd); @@ -1214,7 +1235,7 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { do_once = 1; // release unneeded memory - afl->q_testcase_cache = ck_realloc( + afl->q_testcase_cache = (struct queue_entry **)ck_realloc( afl->q_testcase_cache, (afl->q_testcase_max_cache_entries + 1) * sizeof(size_t)); @@ -1261,15 +1282,15 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { /* Map the test case into memory. */ - int fd = open(q->fname, O_RDONLY); + int fd = open((char *)q->fname, O_RDONLY); - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); } - q->testcase_buf = malloc(len); + q->testcase_buf = (u8 *)malloc(len); if (unlikely(!q->testcase_buf)) { - PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); } @@ -1332,11 +1353,11 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, /* Map the test case into memory. */ - q->testcase_buf = malloc(len); + q->testcase_buf = (u8 *)malloc(len); if (unlikely(!q->testcase_buf)) { - PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); } From 5a0100c6eece0d668c7040ec6e6ed3f59ef0d1ba Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 10:01:02 +0100 Subject: [PATCH 147/300] add to readme --- custom_mutators/autotokens/README | 2 ++ 1 file changed, 2 insertions(+) diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index 904b5fa3..295cd736 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -20,6 +20,8 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! removed. Default: `/* ... */` `AUTOTOKENS_FUZZ_COUNT_SHIFT` - reduce the number of fuzzing performed, shifting the value by this number set, e.g. 1. +`AUTOTOKENS_AUTO_DISABLE` - disable this module if the seeds are not ascii + (or no input and no (ascii) dictionary) `AUTOTOKENS_LEARN_DICT` - learn from dictionaries? 0 = none 1 = only -x or autodict From 80eabd6e8a30c2ffc0f084ab34df8b9d582419c3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Feb 2023 11:34:14 +0100 Subject: [PATCH 148/300] AFL_LLVM_DICT2FILE_NO_MAIN support --- TODO.md | 3 +-- docs/Changelog.md | 1 + docs/env_variables.md | 3 +++ docs/fuzzing_in_depth.md | 4 +++- include/envs.h | 1 + instrumentation/README.llvm.md | 4 ++++ instrumentation/SanitizerCoverageLTO.so.cc | 11 ++++++++++- instrumentation/afl-llvm-dict2file.so.cc | 17 ++++++++++++++--- src/afl-cc.c | 5 ++++- 9 files changed, 41 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 862224f0..187fa191 100644 --- a/TODO.md +++ b/TODO.md @@ -9,13 +9,12 @@ - afl-plot to support multiple plot_data - parallel builds for source-only targets - get rid of check_binary, replace with more forkserver communication - - first fuzzer should be a main automatically + - first fuzzer should be a main automatically? not sure. ## Maybe - forkserver tells afl-fuzz if cmplog is supported and if so enable it by default, with AFL_CMPLOG_NO=1 (?) set to skip? - - afl_custom_fuzz_splice_optin() - afl_custom_splice() - cmdline option from-to range for mutations diff --git a/docs/Changelog.md b/docs/Changelog.md index eee88a51..89c37912 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) - support llvm 15 native pcguard changes + - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support - better sanitizer default options support for all tools - unicorn_mode: updated and minor issues fixed - frida_mode: fix issue on MacOS diff --git a/docs/env_variables.md b/docs/env_variables.md index 0a57d190..61fb1e2b 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -129,6 +129,9 @@ subset of the settings discussed in section 1, with the exception of: write all constant string comparisons to this file to be used later with afl-fuzz' `-x` option. + - An option to `AFL_LLVM_DICT2FILE` is `AFL_LLVM_DICT2FILE_NO_MAIN=1` which + skill not parse `main()`. + - `TMPDIR` and `AFL_KEEP_ASSEMBLY`, since no temporary assembly files are created. diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 87f31a58..efab0633 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -534,6 +534,8 @@ dictionaries/FORMAT.dict`. * With `afl-clang-fast`, you can set `AFL_LLVM_DICT2FILE=/full/path/to/new/file.dic` to automatically generate a dictionary during target compilation. + Adding `AFL_LLVM_DICT2FILE_NO_MAIN=1` to not parse main (usually command line + parameter parsing) is often a good idea too. * You also have the option to generate a dictionary yourself during an independent run of the target, see [utils/libtokencap/README.md](../utils/libtokencap/README.md). @@ -935,7 +937,7 @@ phase and start fuzzing at once. 3. Also randomize the afl-fuzz runtime options, e.g.: * 65% for `AFL_DISABLE_TRIM` * 50% for `AFL_KEEP_TIMEOUTS` - * 50% use a dictionary generated by `AFL_LLVM_DICT2FILE` + * 50% use a dictionary generated by `AFL_LLVM_DICT2FILE` + `AFL_LLVM_DICT2FILE_NO_MAIN=1` * 40% use MOpt (`-L 0`) * 40% for `AFL_EXPAND_HAVOC_NOW` * 20% for old queue processing (`-Z`) diff --git a/include/envs.h b/include/envs.h index 0770f94d..5018b0f8 100644 --- a/include/envs.h +++ b/include/envs.h @@ -133,6 +133,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_CTX", "AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", + "AFL_LLVM_DICT2FILE_NO_MAIN", "AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT", diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index 9da1b0f6..c0677474 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -167,6 +167,10 @@ Just specify `AFL_LLVM_DICT2FILE=/absolute/path/file.txt` and during compilation all constant string compare parameters will be written to this file to be used with afl-fuzz' `-x` option. +Adding `AFL_LLVM_DICT2FILE_NO_MAIN=1` will skip parsing `main()` which often +does command line parsing which has string comparisons that are not helpful +for fuzzing. + ## 6) AFL++ Context Sensitive Branch Coverage ### What is this? diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 231151f5..f82224ed 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -236,6 +236,7 @@ class ModuleSanitizerCoverageLTO // const SpecialCaseList * Allowlist; // const SpecialCaseList * Blocklist; uint32_t autodictionary = 1; + uint32_t autodictionary_no_main = 0; uint32_t inst = 0; uint32_t afl_global_id = 0; uint32_t unhandled = 0; @@ -411,7 +412,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( /* Show a banner */ setvbuf(stdout, NULL, _IONBF, 0); - if (getenv("AFL_DEBUG")) debug = 1; + if (getenv("AFL_DEBUG")) { debug = 1; } + if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { autodictionary_no_main = 1; } if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { @@ -503,6 +505,13 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( if (!isInInstrumentList(&F, MNAME) || !F.size()) { continue; } + if (autodictionary_no_main && + (!F.getName().compare("main") || !F.getName().compare("_main"))) { + + continue; + + } + for (auto &BB : F) { for (auto &IN : BB) { diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index bbbbe32c..97f1d47f 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -182,7 +182,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { DenseMap valueMap; char *ptr; - int found = 0; + int found = 0, handle_main = 1; /* Show a banner */ setvbuf(stdout, NULL, _IONBF, 0); @@ -192,10 +192,14 @@ bool AFLdict2filePass::runOnModule(Module &M) { SAYF(cCYA "afl-llvm-dict2file" VERSION cRST " by Marc \"vanHauser\" Heuse \n"); - } else + } else { be_quiet = 1; + } + + if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { handle_main = 0; } + scanForDangerousFunctions(&M); ptr = getenv("AFL_LLVM_DICT2FILE"); @@ -210,7 +214,14 @@ bool AFLdict2filePass::runOnModule(Module &M) { for (auto &F : M) { - if (isIgnoreFunction(&F)) continue; + if (!handle_main && + (!F.getName().compare("main") || !F.getName().compare("_main"))) { + + continue; + + } + + if (isIgnoreFunction(&F)) { continue; } if (!isInInstrumentList(&F, MNAME) || !F.size()) { continue; } /* Some implementation notes. diff --git a/src/afl-cc.c b/src/afl-cc.c index 7c3682fb..7b059d40 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2041,6 +2041,8 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_DICT2FILE: generate an afl dictionary based on found " "comparisons\n" + " AFL_LLVM_DICT2FILE_NO_MAIN: skip parsing main() for the " + "dictionary\n" " AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" " AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" " AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" @@ -2128,7 +2130,8 @@ int main(int argc, char **argv, char **envp) { "defaults.\n" "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast " "with\n" - "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n"); + "AFL_LLVM_CMPLOG and " + "AFL_LLVM_DICT2FILE+AFL_LLVM_DICT2FILE_NO_MAIN.\n\n"); exit(1); From 8bc3fa1df286aac46a0a724f64e2e07010d2497e Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 13 Feb 2023 23:00:15 +0000 Subject: [PATCH 149/300] LLVM cmplog factoring custom Instruction iterator with added restriction --- instrumentation/afl-llvm-common.cc | 18 ++++++++++++++++++ instrumentation/afl-llvm-common.h | 2 ++ instrumentation/cmplog-instructions-pass.cc | 15 --------------- instrumentation/cmplog-switches-pass.cc | 15 --------------- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index dc34d191..b50269fe 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -582,6 +582,24 @@ bool isInInstrumentList(llvm::Function *F, std::string Filename) { } +template +Iterator Unique(Iterator first, Iterator last) { + static_assert(std::is_trivially_copyable< + typename std::iterator_traits + >::value_type, "Invalid underlying type"); + + while (first != last) { + + Iterator next(first); + last = std::remove(++next, last, *first); + first = next; + + } + + return last; + +} + // Calculate the number of average collisions that would occur if all // location IDs would be assigned randomly (like normal afl/afl++). // This uses the "balls in bins" algorithm. diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h index 0112c325..8b8dc756 100644 --- a/instrumentation/afl-llvm-common.h +++ b/instrumentation/afl-llvm-common.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "llvm/Config/llvm-config.h" @@ -53,6 +54,7 @@ void initInstrumentList(); bool isInInstrumentList(llvm::Function *F, std::string Filename); unsigned long long int calculateCollisions(uint32_t edges); void scanForDangerousFunctions(llvm::Module *M); +template Iterator Unique(Iterator, Iterator); #ifndef IS_EXTERN #define IS_EXTERN diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index bca1f927..c6fd7c56 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -138,21 +138,6 @@ llvmGetPassPluginInfo() { char CmpLogInstructions::ID = 0; #endif -template -Iterator Unique(Iterator first, Iterator last) { - - while (first != last) { - - Iterator next(first); - last = std::remove(++next, last, *first); - first = next; - - } - - return last; - -} - bool CmpLogInstructions::hookInstrs(Module &M) { std::vector icomps; diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index cd0ae76d..f4a9fbd7 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -131,21 +131,6 @@ llvmGetPassPluginInfo() { char CmplogSwitches::ID = 0; #endif -template -Iterator Unique(Iterator first, Iterator last) { - - while (first != last) { - - Iterator next(first); - last = std::remove(++next, last, *first); - first = next; - - } - - return last; - -} - bool CmplogSwitches::hookInstrs(Module &M) { std::vector switches; From a7c43484e1e3afe6d1db440927e72e0f103ba977 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 07:45:45 +0100 Subject: [PATCH 150/300] bettern custom mut warning --- src/afl-fuzz-mutators.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 22e5262e..f722374f 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -312,12 +312,18 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { if (notrim) { + if (mutator->afl_custom_init_trim || mutator->afl_custom_trim || + mutator->afl_custom_post_trim) { + + WARNF( + "Custom mutator does not implement all three trim APIs, standard " + "trimming will be used."); + + } + mutator->afl_custom_init_trim = NULL; mutator->afl_custom_trim = NULL; mutator->afl_custom_post_trim = NULL; - ACTF( - "Custom mutator does not implement all three trim APIs, standard " - "trimming will be used."); } From 668f5e1fa9c126bb8c751a6e4ef038ae60a442fa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 09:32:32 +0100 Subject: [PATCH 151/300] debug output --- custom_mutators/autotokens/Makefile | 8 ++++++-- custom_mutators/autotokens/autotokens.cpp | 17 ++++++++++++++++- docs/Changelog.md | 1 + docs/env_variables.md | 2 ++ include/afl-fuzz.h | 2 +- include/envs.h | 1 + src/afl-fuzz-init.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-state.c | 7 +++++++ 10 files changed, 37 insertions(+), 7 deletions(-) diff --git a/custom_mutators/autotokens/Makefile b/custom_mutators/autotokens/Makefile index 6ee7d324..0daba17d 100644 --- a/custom_mutators/autotokens/Makefile +++ b/custom_mutators/autotokens/Makefile @@ -13,10 +13,14 @@ endif all: autotokens.so -autotokens.so: autotokens.cpp +afl-fuzz-queue.o: ../../src/afl-fuzz-queue.c $(CC) -D_STANDALONE_MODULE=1 -I../../include -g -O3 $(CPPFLAGS) -fPIC -c -o ./afl-fuzz-queue.o ../../src/afl-fuzz-queue.c + +afl-common.o: ../../src/afl-common.c $(CC) -I../../include -g -O3 $(CPPFLAGS) -DBIN_PATH=\"dummy\" -Wno-pointer-sign -fPIC -c -o ./afl-common.o ../../src/afl-common.c + +autotokens.so: afl-fuzz-queue.o afl-common.o autotokens.cpp $(CXX) -Wno-deprecated -g -O3 $(CXXFLAGS) $(CPPFLAGS) -shared -fPIC -o autotokens.so -I../../include autotokens.cpp ./afl-fuzz-queue.o ../../src/afl-performance.o ./afl-common.o clean: - rm -f autotokens.so *~ core + rm -f autotokens.so *.o *~ core diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index cda90a38..043d9588 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -145,6 +145,9 @@ static void first_run(void *data) { if ((valid * 100) / afl_ptr->extras_cnt < 95) { module_disabled = 1; } + DEBUGF(stderr, "DICT: valid %u, total %u, %u < 95 == disable\n", valid, + afl_ptr->extras_cnt, (u32)((valid * 100) / afl_ptr->extras_cnt)); + } else { module_disabled = 1; @@ -190,6 +193,10 @@ static void first_run(void *data) { if ((is_ascii * 100) / valid < 70) { module_disabled = 1; } + DEBUGF(stderr, "seeds: total %u, valid %u, ascii %u, %u < 70 == disabled\n", + afl_ptr->active_items, valid, is_ascii, + (u32)((is_ascii * 100) / valid)); + } static u32 good_whitespace_or_singleval() { @@ -538,7 +545,15 @@ extern "C" unsigned char afl_custom_queue_get(void *data, is_first_run = 0; first_run(data); - if (module_disabled) { WARNF("Autotokens custom module is disabled."); } + if (module_disabled) { + + WARNF("Autotokens custom module is disabled."); + + } else if (auto_disable) { + + OKF("Autotokens custom module is enabled."); + + } } diff --git a/docs/Changelog.md b/docs/Changelog.md index 89c37912..5f253064 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -6,6 +6,7 @@ ### Version ++4.06a (dev) - afl-fuzz: - ensure temporary file descriptor is closed when not used + - added `AFL_NO_WARN_INSTABILITY` - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) diff --git a/docs/env_variables.md b/docs/env_variables.md index 61fb1e2b..7a574e59 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -482,6 +482,8 @@ checks or alter some of the more exotic semantics of the tool: - Setting `AFL_NO_STARTUP_CALIBRATION` will skip the initial calibration of all starting seeds, and start fuzzing at once. + - Setting `AFL_NO_WARN_INSTABILITY` will suppress instability warnings. + - In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for afl-qemu-trace and afl-frida-trace.so. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 229bc025..9bf91faf 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -399,7 +399,7 @@ typedef struct afl_env_vars { afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme, - afl_ignore_timeouts, afl_no_startup_calibration; + afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 5018b0f8..56675eda 100644 --- a/include/envs.h +++ b/include/envs.h @@ -172,6 +172,7 @@ static char *afl_environment_variables[] = { "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_STARTUP_CALIBRATION", + "AFL_NO_WARN_INSTABILITY", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_MAP_SIZE", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1182bd41..c20965b4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1120,7 +1120,7 @@ void perform_dry_run(afl_state_t *afl) { } - if (q->var_behavior) { + if (unlikely(q->var_behavior && !afl->afl_env.afl_no_warn_instability)) { WARNF("Instrumentation output varies across runs."); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2f016217..e97db273 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1988,7 +1988,7 @@ custom_mutator_stage: if (unlikely(!mutated_buf)) { - //FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size); + // FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size); break; } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 7dd83150..f5425011 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -523,7 +523,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } - if (unlikely(!var_detected)) { + if (unlikely(!var_detected && !afl->afl_env.afl_no_warn_instability)) { // note: from_queue seems to only be set during initialization if (afl->afl_env.afl_no_ui || from_queue) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 104b1e4b..6d8c8758 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -204,6 +204,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_no_affinity = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_WARN_INSTABILITY", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_warn_instability = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_TRY_AFFINITY", afl_environment_variable_len)) { From 2090f17a9bb9cc225c1d24e8b21ed0c993a2665f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 11:23:42 +0100 Subject: [PATCH 152/300] opt --- custom_mutators/autotokens/autotokens.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 043d9588..a2b2814f 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -143,9 +143,9 @@ static void first_run(void *data) { } - if ((valid * 100) / afl_ptr->extras_cnt < 95) { module_disabled = 1; } + if ((valid * 100) / afl_ptr->extras_cnt <= 70) { module_disabled = 1; } - DEBUGF(stderr, "DICT: valid %u, total %u, %u < 95 == disable\n", valid, + DEBUGF(stderr, "DICT: valid %u, total %u, %u <= 70 == disable\n", valid, afl_ptr->extras_cnt, (u32)((valid * 100) / afl_ptr->extras_cnt)); } else { @@ -191,9 +191,9 @@ static void first_run(void *data) { } - if ((is_ascii * 100) / valid < 70) { module_disabled = 1; } + if ((is_ascii * 100) / valid <= 70) { module_disabled = 1; } - DEBUGF(stderr, "seeds: total %u, valid %u, ascii %u, %u < 70 == disabled\n", + DEBUGF(stderr, "seeds: total %u, valid %u, ascii %u, %u <= 70 == disabled\n", afl_ptr->active_items, valid, is_ascii, (u32)((is_ascii * 100) / valid)); From 04356ecbbe2c6cb72d279081702a6044fcc3ae92 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 11:28:43 +0100 Subject: [PATCH 153/300] fix --- custom_mutators/autotokens/autotokens.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index a2b2814f..b1f1542e 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -145,8 +145,9 @@ static void first_run(void *data) { if ((valid * 100) / afl_ptr->extras_cnt <= 70) { module_disabled = 1; } - DEBUGF(stderr, "DICT: valid %u, total %u, %u <= 70 == disable\n", valid, - afl_ptr->extras_cnt, (u32)((valid * 100) / afl_ptr->extras_cnt)); + DEBUGF(stderr, "DICT: total %u, valid %u, %u <= 70 == disable\n", + afl_ptr->extras_cnt, valid, + (u32)((valid * 100) / afl_ptr->extras_cnt)); } else { From ae94499503596d1e7f45e1a93bc5f7148c6163b6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 11:48:49 +0100 Subject: [PATCH 154/300] fix --- custom_mutators/autotokens/autotokens.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index b1f1542e..e6b9931d 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -1078,6 +1078,8 @@ extern "C" void afl_custom_deinit(my_mutator_t *data) { /* we use this to print statistics at exit :-) needs to be stderr as stdout is filtered */ + if (module_disabled) { return; } + fprintf(stderr, "\n\nAutotoken mutator statistics:\n" " Number of all seen tokens: %u\n" From 7f2bafbb8b709720cd3703789071c08064e518bd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Feb 2023 11:54:39 +0100 Subject: [PATCH 155/300] remove some debug --- custom_mutators/autotokens/autotokens.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index e6b9931d..22c78a60 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -287,7 +287,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, ((whitespace_ids < new_item && whitespace_ids >= cur_item) || (whitespace_ids >= new_item && whitespace_ids < cur_item)))); - DEBUGF(stderr, "MUT: %u -> %u\n", cur_item, new_item); + // DEBUGF(stderr, "MUT: %u -> %u\n", cur_item, new_item); m[pos] = new_item; break; @@ -305,7 +305,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, u32 pos = rand_below(afl_ptr, m_size + 1); m.insert(m.begin() + pos, new_item); ++m_size; - DEBUGF(stderr, "INS: %u at %u\n", new_item, pos); + // DEBUGF(stderr, "INS: %u at %u\n", new_item, pos); break; @@ -334,7 +334,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, m.insert(m.begin() + dst_off, src->begin() + src_off, src->begin() + src_off + n); m_size += n; - DEBUGF(stderr, "SPLICE-INS: %u at %u\n", n, dst_off); + // DEBUGF(stderr, "SPLICE-INS: %u at %u\n", n, dst_off); break; @@ -354,7 +354,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, copy(src->begin() + src_off, src->begin() + src_off + n, m.begin() + dst_off); - DEBUGF(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); + // DEBUGF(stderr, "SPLICE-MUT: %u at %u\n", n, dst_off); break; } @@ -432,6 +432,7 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, if (unlikely(mutated_size > max_size)) { mutated_size = max_size; } + /* IFDEBUG { DEBUGF(stderr, "MUTATED to %u bytes:\n", mutated_size); @@ -440,6 +441,8 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, } + */ + *out_buf = mutated_out; ++fuzz_count; return mutated_size; @@ -633,7 +636,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } ++a_extras_cnt; - DEBUGF(stderr, "Added from auto dictionary: \"%s\"\n", ptr); } @@ -751,8 +753,10 @@ extern "C" unsigned char afl_custom_queue_get(void *data, u32 tabs = count(input.begin(), input.end(), '\t'); u32 linefeeds = count(input.begin(), input.end(), '\n'); bool ends_with_linefeed = input[input.length() - 1] == '\n'; + DEBUGF(stderr, "spaces=%u tabs=%u linefeeds=%u ends=%u\n", spaces, tabs, linefeeds, ends_with_linefeed); + all_spaces += spaces; all_tabs += tabs; all_lf += linefeeds; From 1faf6f67313e726c645ac3b9ecd2d8b5e65f605a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 Feb 2023 07:47:36 +0100 Subject: [PATCH 156/300] fix --- custom_mutators/autotokens/autotokens.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 22c78a60..8135aba1 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -401,25 +401,28 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, /* Now we create the output */ output = ""; - u32 prev_size = 0; + u32 prev_size = 1, was_whitespace = 1; for (i = 0; i < m_size; ++i) { if (likely(i + 1 < m_size)) { u32 this_size = id_to_token[m[i]].size(); + u32 is_whitespace = m[i] < whitespace_ids; /* The output we are generating might need repairing. General rule: two items that have a size larger than 2 are strings or identifizers and need a whitespace or an item of length 1 in between. */ - if (unlikely(prev_size > 1 && this_size > 1)) { + if (unlikely(!(prev_size == 1 || was_whitespace || this_size == 1 || + is_whitespace))) { output += id_to_token[good_whitespace_or_singleval()]; } prev_size = this_size; + was_whitespace = is_whitespace; } From 9da3a2ed4522d1a980ad7ddc7806f02833dd99fc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 Feb 2023 13:11:11 +0100 Subject: [PATCH 157/300] fixes --- src/afl-fuzz-redqueen.c | 2 ++ src/afl-gotcpu.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 8da1df13..290be881 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1624,6 +1624,8 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { } + if (cons_0 > 1 || cons_ff > 1) { return; } + } maybe_add_auto(afl, (u8 *)&v + off, size); diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index fd9e9f54..8988fd54 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -92,7 +92,7 @@ static u32 measure_preemption(u32 target_ms) { volatile u32 v1, v2 = 0; u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; - s32 loop_repeats = 0; + //s32 loop_repeats = 0; st_t = get_cur_time_us(); st_c = get_cpu_usage_us(); @@ -113,7 +113,7 @@ repeat_loop: if (en_t - st_t < target_ms * 1000) { - loop_repeats++; + //loop_repeats++; goto repeat_loop; } From ebaac23a514cd3950d4a6cb597bd921e13ab9baa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 20 Feb 2023 11:42:40 +0100 Subject: [PATCH 158/300] clarify AFL_NO_STARTUP_CALIBRATION --- docs/env_variables.md | 3 ++- docs/fuzzing_in_depth.md | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index 22a5c386..646db3f2 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -474,7 +474,8 @@ checks or alter some of the more exotic semantics of the tool: output from afl-fuzz is redirected to a file or to a pipe. - Setting `AFL_NO_STARTUP_CALIBRATION` will skip the initial calibration - of all starting seeds, and start fuzzing at once. + of all starting seeds, and start fuzzing at once. Use with care, this + degrades the fuzzing performance! - In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for afl-qemu-trace and afl-frida-trace.so. diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 87f31a58..2a088201 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -628,7 +628,8 @@ If you have a large corpus, a corpus from a previous run or are fuzzing in a CI, then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`. If the queue in the CI is huge and/or the execution time is slow then you can also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration -phase and start fuzzing at once. +phase and start fuzzing at once - but only do this if the calibration phase +would be too long for your fuzz run time. You can also use different fuzzers. If you are using AFL spinoffs or AFL conforming fuzzers, then just use the same -o directory and give it a unique @@ -914,7 +915,8 @@ normal fuzzing campaigns as these are much shorter runnings. If the queue in the CI is huge and/or the execution time is slow then you can also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration -phase and start fuzzing at once. +phase and start fuzzing at once. But only do that if the calibration time is +too long for your overall available fuzz run time. 1. Always: * LTO has a much longer compile time which is diametrical to short fuzzing - From b786558dea5fd5dca471a0e36a8b420ff6a65846 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 20 Feb 2023 15:43:54 +0100 Subject: [PATCH 159/300] Revert "LLVM cmplog factoring custom Instruction iterator with added restriction" This reverts commit 8bc3fa1df286aac46a0a724f64e2e07010d2497e. --- instrumentation/afl-llvm-common.cc | 18 ------------------ instrumentation/afl-llvm-common.h | 2 -- instrumentation/cmplog-instructions-pass.cc | 15 +++++++++++++++ instrumentation/cmplog-switches-pass.cc | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index b50269fe..dc34d191 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -582,24 +582,6 @@ bool isInInstrumentList(llvm::Function *F, std::string Filename) { } -template -Iterator Unique(Iterator first, Iterator last) { - static_assert(std::is_trivially_copyable< - typename std::iterator_traits - >::value_type, "Invalid underlying type"); - - while (first != last) { - - Iterator next(first); - last = std::remove(++next, last, *first); - first = next; - - } - - return last; - -} - // Calculate the number of average collisions that would occur if all // location IDs would be assigned randomly (like normal afl/afl++). // This uses the "balls in bins" algorithm. diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h index 8b8dc756..0112c325 100644 --- a/instrumentation/afl-llvm-common.h +++ b/instrumentation/afl-llvm-common.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "llvm/Config/llvm-config.h" @@ -54,7 +53,6 @@ void initInstrumentList(); bool isInInstrumentList(llvm::Function *F, std::string Filename); unsigned long long int calculateCollisions(uint32_t edges); void scanForDangerousFunctions(llvm::Module *M); -template Iterator Unique(Iterator, Iterator); #ifndef IS_EXTERN #define IS_EXTERN diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index c6fd7c56..bca1f927 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -138,6 +138,21 @@ llvmGetPassPluginInfo() { char CmpLogInstructions::ID = 0; #endif +template +Iterator Unique(Iterator first, Iterator last) { + + while (first != last) { + + Iterator next(first); + last = std::remove(++next, last, *first); + first = next; + + } + + return last; + +} + bool CmpLogInstructions::hookInstrs(Module &M) { std::vector icomps; diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index f4a9fbd7..cd0ae76d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -131,6 +131,21 @@ llvmGetPassPluginInfo() { char CmplogSwitches::ID = 0; #endif +template +Iterator Unique(Iterator first, Iterator last) { + + while (first != last) { + + Iterator next(first); + last = std::remove(++next, last, *first); + first = next; + + } + + return last; + +} + bool CmplogSwitches::hookInstrs(Module &M) { std::vector switches; From 91b7f1c9f2dc429b7d4beaafb7497203f456bcd3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 21 Feb 2023 01:05:46 +0100 Subject: [PATCH 160/300] fix regression --- src/afl-fuzz-one.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 76826945..0f237126 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5841,7 +5841,10 @@ u8 fuzz_one(afl_state_t *afl) { } - return (key_val_lv_1 == 0 || key_val_lv_2 == 0 ? 0 : 1 ); + if (key_val_lv_1 == -1) { key_val_lv_1 = 0; } + if (key_val_lv_2 == -1) { key_val_lv_2 = 0; } + + return (key_val_lv_1 | key_val_lv_2); } From 6f4b5ae0832774389b12c5a8cd3fb95821b438e5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 21 Feb 2023 01:07:02 +0100 Subject: [PATCH 161/300] nit --- src/afl-fuzz-one.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 0f237126..cce3d7cf 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5841,8 +5841,8 @@ u8 fuzz_one(afl_state_t *afl) { } - if (key_val_lv_1 == -1) { key_val_lv_1 = 0; } - if (key_val_lv_2 == -1) { key_val_lv_2 = 0; } + if (unlikely(key_val_lv_1 == -1)) { key_val_lv_1 = 0; } + if (likely(key_val_lv_2 == -1)) { key_val_lv_2 = 0; } return (key_val_lv_1 | key_val_lv_2); From 8a8e350f34fa4fe5eb862d1a71921be9b739e8bb Mon Sep 17 00:00:00 2001 From: lazymio Date: Wed, 22 Feb 2023 22:48:03 +0100 Subject: [PATCH 162/300] Also install libclang-rt-dev --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fd47a59f..59ce8778 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ RUN apt-get update && \ clang-${LLVM_VERSION} clang-tools-${LLVM_VERSION} libc++1-${LLVM_VERSION} \ libc++-${LLVM_VERSION}-dev libc++abi1-${LLVM_VERSION} libc++abi-${LLVM_VERSION}-dev \ libclang1-${LLVM_VERSION} libclang-${LLVM_VERSION}-dev \ - libclang-common-${LLVM_VERSION}-dev libclang-cpp${LLVM_VERSION} \ + libclang-common-${LLVM_VERSION}-dev libclang-rt-${LLVM_VERSION}-dev libclang-cpp${LLVM_VERSION} \ libclang-cpp${LLVM_VERSION}-dev liblld-${LLVM_VERSION} \ liblld-${LLVM_VERSION}-dev liblldb-${LLVM_VERSION} liblldb-${LLVM_VERSION}-dev \ libllvm${LLVM_VERSION} libomp-${LLVM_VERSION}-dev libomp5-${LLVM_VERSION} \ From 0c0a6c3bfabf0facaed33fae1aa5ad54a6a11b32 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Feb 2023 11:22:40 +0100 Subject: [PATCH 163/300] regression fix --- include/config.h | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-cmplog.c | 8 ++++++-- src/afl-fuzz.c | 3 ++- src/afl-gotcpu.c | 4 ++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/config.h b/include/config.h index ad8b76a8..e46f515a 100644 --- a/include/config.h +++ b/include/config.h @@ -489,7 +489,7 @@ /* Minimum length of a queue input to be evaluated for "is_ascii"? */ -#define AFL_TXT_MIN_LEN 16 +#define AFL_TXT_MIN_LEN 12 /* Maximum length of a queue input to be evaluated for "is_ascii"? */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 5aa4c2ff..50dc7a26 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -59,7 +59,7 @@ static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { - if (fsrv->qemu_mode || fsrv->cs_mode) { + if (fsrv->qemu_mode || fsrv->frida_mode || fsrv->cs_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 2bf26d19..229aef09 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -33,11 +33,15 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + if (fsrv->qemu_mode || fsrv->frida_mode || fsrv->cs_mode) { + + setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); + + } if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) { - argv[0] = fsrv->cmplog_binary; + fsrv->target_path = argv[0] = fsrv->cmplog_binary; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ea467401..4914ce0b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1298,7 +1298,8 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->is_main_node == 1 && afl->schedule != FAST && afl->schedule != EXPLORE) { + if (afl->is_main_node == 1 && afl->schedule != FAST && + afl->schedule != EXPLORE) { FATAL("-M is compatible only with fast and explore -p power schedules"); diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 8988fd54..4f851099 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -92,7 +92,7 @@ static u32 measure_preemption(u32 target_ms) { volatile u32 v1, v2 = 0; u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; - //s32 loop_repeats = 0; + // s32 loop_repeats = 0; st_t = get_cur_time_us(); st_c = get_cpu_usage_us(); @@ -113,7 +113,7 @@ repeat_loop: if (en_t - st_t < target_ms * 1000) { - //loop_repeats++; + // loop_repeats++; goto repeat_loop; } From eeccb2da69d7e6f32ee74c431e7c5053e8379dff Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Feb 2023 11:45:26 +0100 Subject: [PATCH 164/300] nits --- docs/Changelog.md | 1 + qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 5f253064..8f71fd83 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,7 @@ - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) - support llvm 15 native pcguard changes + - new custom module: autotoken, grammar free fuzzer for text inputs - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support - better sanitizer default options support for all tools - unicorn_mode: updated and minor issues fixed diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index a120c3fe..a8af9cbd 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit a120c3feb573d4cade292cdeb7c1f6b1ce109efe +Subproject commit a8af9cbde71e333ce72a46f15e655d0b82ed0939 From ffdb5ec9b1d92e9feb226d83c78d057cb613eeb0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Feb 2023 14:32:54 +0100 Subject: [PATCH 165/300] improve cmplog ci --- test/test-llvm.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test-llvm.sh b/test/test-llvm.sh index ce64d76c..52be04ef 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -257,12 +257,13 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { } rm -f test-compcov test.out instrumentlist.txt AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1 + ../afl-clang-fast -o test-c test-cmplog.c > /dev/null 2>&1 test -e test-cmplog && { $ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds" { mkdir -p in echo 00000000000000000000000000000000 > in/in - AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V60 -i in -o out -c./test-cmplog -- ./test-cmplog >>errors 2>&1 + AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V60 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" & { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog" @@ -277,7 +278,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { $ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present" INCOMPLETE=1 } - rm -rf errors test-cmplog in core.* + rm -rf errors test-cmplog test-c in core.* ../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { From add2eb42c0f0e2b590fcb17427e5fce29c2fdd54 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Feb 2023 15:26:41 +0100 Subject: [PATCH 166/300] nits --- .gitignore | 133 +++++++++++++++--------------- custom_mutators/autotokens/README | 7 +- custom_mutators/autotokens/TODO | 3 - 3 files changed, 72 insertions(+), 71 deletions(-) delete mode 100644 custom_mutators/autotokens/TODO diff --git a/.gitignore b/.gitignore index 45d8676c..c01750e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,104 +1,107 @@ -.test -.test2 -.sync_tmp -.vscode +!coresight_mode +!coresight_mode/coresight-trace +*.dSYM *.o +*.o.tmp +*.pyc *.so *.swp -*.pyc -*.dSYM -as -a.out -ld -in -out -core* -compile_commands.json +.sync_tmp +.test +.test2 +.vscode afl-analyze +afl-analyze.8 afl-as +afl-as.8 +afl-c++ +afl-c++.8 +afl-cc +afl-cc.8 afl-clang afl-clang++ afl-clang-fast afl-clang-fast++ -afl-clang-lto -afl-clang-lto++ -afl-fuzz -afl-g++ -afl-gcc -afl-gcc-fast -afl-g++-fast -afl-gotcpu -afl-ld -afl-ld-lto -afl-cs-proxy -afl-qemu-trace -afl-showmap -afl-tmin -afl-analyze.8 -afl-as.8 afl-clang-fast++.8 afl-clang-fast.8 -afl-clang-lto.8 +afl-clang-lto +afl-clang-lto++ afl-clang-lto++.8 +afl-clang-lto.8 afl-cmin.8 afl-cmin.bash.8 +afl-cs-proxy +afl-frida-trace.so +afl-fuzz afl-fuzz.8 -afl-c++.8 -afl-cc.8 -afl-gcc.8 +afl-g++ afl-g++.8 +afl-gcc +afl-gcc.8 +afl-gcc-fast afl-gcc-fast.8 +afl-g++-fast afl-g++-fast.8 +afl-gotcpu afl-gotcpu.8 -afl-plot.8 -afl-showmap.8 -afl-system-config.8 -afl-tmin.8 -afl-whatsup.8 -afl-persistent-config.8 -afl-c++ -afl-cc +afl-ld +afl-ld-lto afl-lto afl-lto++ afl-lto++.8 afl-lto.8 +afl-persistent-config.8 +afl-plot.8 +afl-qemu-trace +afl-showmap +afl-showmap.8 +afl-system-config.8 +afl-tmin +afl-tmin.8 +afl-whatsup.8 +a.out +as +compile_commands.json +core* +examples/afl_frida/afl-frida +examples/afl_frida/frida-gum-example.c +examples/afl_frida/frida-gum.h +examples/afl_frida/libtestinstr.so +examples/afl_network_proxy/afl-network-client +examples/afl_network_proxy/afl-network-server +examples/aflpp_driver/libAFLDriver.a +examples/aflpp_driver/libAFLQemuDriver.a +gmon.out +in +ld +libAFLDriver.a +libAFLQemuDriver.a +out qemu_mode/libcompcov/compcovtest qemu_mode/qemu-* qemu_mode/qemuafl -unicorn_mode/samples/*/\.test-* -unicorn_mode/samples/*/output/ -test/unittests/unit_maybe_alloc -test/unittests/unit_preallocable -test/unittests/unit_list -test/unittests/unit_rand -test/unittests/unit_hash -examples/afl_network_proxy/afl-network-server -examples/afl_network_proxy/afl-network-client -examples/afl_frida/afl-frida -examples/afl_frida/libtestinstr.so -examples/afl_frida/frida-gum-example.c -examples/afl_frida/frida-gum.h -examples/aflpp_driver/libAFLDriver.a -examples/aflpp_driver/libAFLQemuDriver.a -libAFLDriver.a -libAFLQemuDriver.a test/.afl_performance test-instr test/output +test/test-c +test/test-cmplog +test/test-compcov test/test-instr.ts test/test-persistent -gmon.out -afl-frida-trace.so +test/unittests/unit_hash +test/unittests/unit_list +test/unittests/unit_maybe_alloc +test/unittests/unit_preallocable +test/unittests/unit_rand +unicorn_mode/samples/*/output/ +unicorn_mode/samples/*/\.test-* utils/afl_network_proxy/afl-network-client utils/afl_network_proxy/afl-network-server -utils/plot_ui/afl-plot-ui -*.o.tmp utils/afl_proxy/afl-proxy utils/optimin/build utils/optimin/optimin utils/persistent_mode/persistent_demo utils/persistent_mode/persistent_demo_new utils/persistent_mode/test-instr -!coresight_mode -!coresight_mode/coresight-trace -vuln_prog \ No newline at end of file +utils/plot_ui/afl-plot-ui +vuln_prog diff --git a/custom_mutators/autotokens/README b/custom_mutators/autotokens/README index 295cd736..cca168fd 100644 --- a/custom_mutators/autotokens/README +++ b/custom_mutators/autotokens/README @@ -1,8 +1,9 @@ -# autotokens +# Autotokens This implements an improved autotoken grammar fuzzing idea presented in [Token-Level Fuzzing][https://www.usenix.org/system/files/sec21-salls.pdf]. -It is a grammar fuzzer without actually knowing the grammar. +It is a grammar fuzzer without actually knowing the grammar, but only works +with text based inputs. It is recommended to run with together in an instance with `CMPLOG`. @@ -19,7 +20,7 @@ Do **not** set `AFL_DISABLE_TRIM` with this custom mutator! `AUTOTOKENS_COMMENT` - what character or string starts a comment which will be removed. Default: `/* ... */` `AUTOTOKENS_FUZZ_COUNT_SHIFT` - reduce the number of fuzzing performed, shifting - the value by this number set, e.g. 1. + the value by this number, e.g. 1. `AUTOTOKENS_AUTO_DISABLE` - disable this module if the seeds are not ascii (or no input and no (ascii) dictionary) `AUTOTOKENS_LEARN_DICT` - learn from dictionaries? diff --git a/custom_mutators/autotokens/TODO b/custom_mutators/autotokens/TODO deleted file mode 100644 index 2e99e147..00000000 --- a/custom_mutators/autotokens/TODO +++ /dev/null @@ -1,3 +0,0 @@ -env für menge an per mutation run - -change_min/_max werte From 2bea77e28a969fcb62921862bef61cd751d7b9d5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 23 Feb 2023 17:09:06 +0100 Subject: [PATCH 167/300] fix custom python splice optout --- src/afl-fuzz-python.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 69c305f7..2799268b 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -231,8 +231,12 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "describe"); py_functions[PY_FUNC_FUZZ_COUNT] = PyObject_GetAttrString(py_module, "fuzz_count"); - if (!py_functions[PY_FUNC_FUZZ]) + if (!py_functions[PY_FUNC_FUZZ]) { + WARNF("fuzz function not found in python module"); + + } + py_functions[PY_FUNC_POST_PROCESS] = PyObject_GetAttrString(py_module, "post_process"); py_functions[PY_FUNC_INIT_TRIM] = @@ -250,6 +254,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "fuzz_send"); py_functions[PY_FUNC_SPLICE_OPTOUT] = PyObject_GetAttrString(py_module, "splice_optout"); + if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { afl->custom_splice_optout = 1; } py_functions[PY_FUNC_QUEUE_NEW_ENTRY] = PyObject_GetAttrString(py_module, "queue_new_entry"); py_functions[PY_FUNC_INTROSPECTION] = From 65d4d10762a14e2dab6b89962b0ccf0cbdc8de2e Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Fri, 24 Feb 2023 23:14:40 +0900 Subject: [PATCH 168/300] Update afl-fuzz-redqueen.c --- src/afl-fuzz-redqueen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 8da1df13..07736537 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1035,7 +1035,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } else { - diff = 0; + o_diff = 0; } From 86bf0097921bbe9867a0ec7e9b108c5d72907d6b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 27 Feb 2023 18:34:35 +0100 Subject: [PATCH 169/300] div hits --- src/afl-fuzz-queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 65446799..4eb55bb3 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -67,7 +67,7 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { u32 hits = afl->n_fuzz[q->n_fuzz_entry]; - if (likely(hits)) { weight *= (log10(hits) + 1); } + if (likely(hits)) { weight /= (log10(hits) + 1); } } From d8ba0caab3661ef045f6bc6d99481ab14d165262 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Feb 2023 11:03:09 +0100 Subject: [PATCH 170/300] update docs --- TODO.md | 1 + docs/ideas.md | 13 ++----------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/TODO.md b/TODO.md index 187fa191..e7789cf6 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## Should + - splicing selection weighted? - support afl_custom_{send,post_process}, persistent and deferred fork server in afl-showmap - better autodetection of shifting runtime timeout values diff --git a/docs/ideas.md b/docs/ideas.md index b5de637f..4e419b80 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -3,6 +3,8 @@ In the following, we describe a variety of ideas that could be implemented for future AFL++ versions. +**NOTE:** Our GSoC participation is concerning [libafl](https://github.com/AFLplusplus/libafl), not AFL++. + ## Analysis software Currently analysis is done by using afl-plot, which is rather outdated. A GTK or @@ -16,17 +18,6 @@ and Y axis, zoom factor, log scaling on-off, etc. Mentor: vanhauser-thc -## WASM Instrumentation - -Currently, AFL++ can be used for source code fuzzing and traditional binaries. -With the rise of WASM as a compile target, however, a novel way of -instrumentation needs to be implemented for binaries compiled to Webassembly. -This can either be done by inserting instrumentation directly into the WASM AST, -or by patching feedback into a WASM VM of choice, similar to the current Unicorn -instrumentation. - -Mentor: any - ## Support other programming languages Other programming languages also use llvm hence they could be (easily?) From 85fa17451d10e2a7de3cb6e02ff3f69bb1e20580 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Thu, 2 Mar 2023 17:04:43 +0300 Subject: [PATCH 171/300] Fix exit on time. --- src/afl-fuzz-stats.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bfd30845..606e2d66 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -669,9 +669,15 @@ void show_stats_normal(afl_state_t *afl) { /* AFL_EXIT_ON_TIME. */ - if (unlikely(afl->last_find_time && !afl->non_instrumented_mode && - afl->afl_env.afl_exit_on_time && - (cur_ms - afl->last_find_time) > afl->exit_on_time)) { + /* If no coverage was found yet, check whether run time is greater than + * exit_on_time. */ + + if (unlikely( + !afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && + ((afl->last_find_time && + (cur_ms - afl->last_find_time) > afl->exit_on_time) || + (!afl->last_find_time && (afl->prev_run_time + cur_ms - + afl->start_time) > afl->exit_on_time)))) { afl->stop_soon = 2; From 7c07437941765acbeb809d9ffc941d8bfea9be72 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Thu, 2 Mar 2023 17:42:34 +0300 Subject: [PATCH 172/300] Fix. --- src/afl-fuzz-stats.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 606e2d66..26e1a50e 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -676,8 +676,8 @@ void show_stats_normal(afl_state_t *afl) { !afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && ((afl->last_find_time && (cur_ms - afl->last_find_time) > afl->exit_on_time) || - (!afl->last_find_time && (afl->prev_run_time + cur_ms - - afl->start_time) > afl->exit_on_time)))) { + (!afl->last_find_time && (cur_ms - afl->start_time) + > afl->exit_on_time)))) { afl->stop_soon = 2; @@ -1480,8 +1480,8 @@ void show_stats_pizza(afl_state_t *afl) { !afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && ((afl->last_find_time && (cur_ms - afl->last_find_time) > afl->exit_on_time) || - (!afl->last_find_time && (afl->prev_run_time + cur_ms - - afl->start_time) > afl->exit_on_time)))) { + (!afl->last_find_time && (cur_ms - afl->start_time) + > afl->exit_on_time)))) { afl->stop_soon = 2; From bc61c90fb6e8d26d864aea7bd31f00485db4e942 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 4 Mar 2023 14:46:38 +0000 Subject: [PATCH 173/300] llvm instrumentation trying to delete all static data at module end of pass with llvm_shutdown and is concurrent safe. --- instrumentation/cmplog-instructions-pass.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 2 +- instrumentation/cmplog-switches-pass.cc | 2 +- instrumentation/split-compares-pass.so.cc | 2 +- instrumentation/split-switches-pass.so.cc | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index bca1f927..7dcf8bfa 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -66,7 +66,7 @@ namespace { #if LLVM_MAJOR >= 11 /* use new pass manager */ class CmpLogInstructions : public PassInfoMixin { - + llvm_shutdown_obj LSO; public: CmpLogInstructions() { diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 0498156d..c2c52874 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -63,7 +63,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class CmpLogRoutines : public PassInfoMixin { - + llvm_shutdown_obj LSO; public: CmpLogRoutines() { diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index cd0ae76d..d96c5a4f 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -64,7 +64,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class CmplogSwitches : public PassInfoMixin { - + llvm_shutdown_obj LSO; public: CmplogSwitches() { diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 8a07610c..a189c203 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -66,7 +66,7 @@ namespace { #if LLVM_MAJOR >= 11 class SplitComparesTransform : public PassInfoMixin { - + llvm_shutdown_obj LSO; public: // static char ID; SplitComparesTransform() : enableFPSplit(0) { diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index dcd89652..1028c5b0 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -65,7 +65,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class SplitSwitchesTransform : public PassInfoMixin { - + llvm_shutdown_obj LSO; public: SplitSwitchesTransform() { From 07cf27cddc6f0189ee9b21f888595c84549b5b93 Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:16:21 +0200 Subject: [PATCH 174/300] Added flag -u to allow custom interval to update fuzzer_stats file --- include/afl-fuzz.h | 1 + src/afl-fuzz-state.c | 1 + src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 17 ++++++++++++++--- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 9bf91faf..62d71968 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -693,6 +693,7 @@ typedef struct afl_state { /* statistics file */ double last_bitmap_cvg, last_stability, last_eps; + u64 stats_file_update_freq_msecs; /* Stats update frequency (msecs) */ /* plot file saves from last run */ u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 6d8c8758..e319c512 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -100,6 +100,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->hang_tmout = EXEC_TIMEOUT; afl->exit_on_time = 0; afl->stats_update_freq = 1; + afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000; afl->stats_avg_exec = 0; afl->skip_deterministic = 1; afl->sync_time = SYNC_TIME; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bfd30845..0e36227f 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -613,7 +613,7 @@ void show_stats_normal(afl_state_t *afl) { if (unlikely(!afl->non_instrumented_mode && (afl->force_ui_update || - cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) { + cur_ms - afl->stats_last_stats_ms > afl->stats_file_update_freq_msecs))) { afl->stats_last_stats_ms = cur_ms; write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 4914ce0b..efbab289 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -210,7 +210,10 @@ static void usage(u8 *argv0, int more_help) { " -b cpu_id - bind the fuzzing process to the specified CPU core " "(0-...)\n" " -e ext - file extension for the fuzz test input file (if " - "needed)\n\n", + "needed)\n" + " -u - interval to update fuzzer_stats file in seconds, " + "defaults to 60 sec\n" + "\n", argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); if (more_help > 1) { @@ -501,7 +504,7 @@ fail: int main(int argc, char **argv_orig, char **envp) { s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; - u64 prev_queued = 0; + u64 prev_queued = 0, stats_update_freq_sec = 0; u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1, map_size = get_map_size(); u8 *extras_dir[4]; @@ -553,7 +556,7 @@ int main(int argc, char **argv_orig, char **envp) { while ( (opt = getopt( argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:u:UV:WXx:YZ")) > 0) { switch (opt) { @@ -665,6 +668,14 @@ int main(int argc, char **argv_orig, char **envp) { break; + case 'u': + if (sscanf(optarg, "%llu", &stats_update_freq_sec) < 1) { + FATAL("Bad syntax used for -u"); + } + + afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000; + break; + case 'i': /* input dir */ if (afl->in_dir) { FATAL("Multiple -i options not supported"); } From 403d95d2d2c7a9bd72eca5ea91743f8d835845ef Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:21:35 +0200 Subject: [PATCH 175/300] auto code format fixes --- include/afl-fuzz.h | 2 +- src/afl-fuzz-stats.c | 7 ++++--- src/afl-fuzz.c | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 62d71968..6a8e8b5d 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -693,7 +693,7 @@ typedef struct afl_state { /* statistics file */ double last_bitmap_cvg, last_stability, last_eps; - u64 stats_file_update_freq_msecs; /* Stats update frequency (msecs) */ + u64 stats_file_update_freq_msecs; /* Stats update frequency (msecs) */ /* plot file saves from last run */ u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 0e36227f..db4bf24e 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -611,9 +611,10 @@ void show_stats_normal(afl_state_t *afl) { /* Roughly every minute, update fuzzer stats and save auto tokens. */ - if (unlikely(!afl->non_instrumented_mode && - (afl->force_ui_update || - cur_ms - afl->stats_last_stats_ms > afl->stats_file_update_freq_msecs))) { + if (unlikely( + !afl->non_instrumented_mode && + (afl->force_ui_update || cur_ms - afl->stats_last_stats_ms > + afl->stats_file_update_freq_msecs))) { afl->stats_last_stats_ms = cur_ms; write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index efbab289..9ca88b5b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -553,11 +553,9 @@ int main(int argc, char **argv_orig, char **envp) { afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - while ( - (opt = getopt( - argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:u:UV:WXx:YZ")) > - 0) { + while ((opt = getopt(argc, argv, + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:u:" + "UV:WXx:YZ")) > 0) { switch (opt) { @@ -670,7 +668,9 @@ int main(int argc, char **argv_orig, char **envp) { case 'u': if (sscanf(optarg, "%llu", &stats_update_freq_sec) < 1) { + FATAL("Bad syntax used for -u"); + } afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000; From 5e7f8a51e0f45780d9c8ff34ace6b03f8a7e1f71 Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Sun, 5 Mar 2023 18:27:07 +0200 Subject: [PATCH 176/300] Added minimum interval of 1 sec to avoid undefined behaviour in interval --- src/afl-fuzz.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9ca88b5b..78d9da71 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -212,7 +212,7 @@ static void usage(u8 *argv0, int more_help) { " -e ext - file extension for the fuzz test input file (if " "needed)\n" " -u - interval to update fuzzer_stats file in seconds, " - "defaults to 60 sec\n" + "defaults to 60 sec, minimum interval: 1 sec\n" "\n", argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); @@ -673,6 +673,8 @@ int main(int argc, char **argv_orig, char **envp) { } + if (stats_update_freq_sec < 1) { FATAL("-u interval must be >= 1"); } + afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000; break; From e9e440d7f33a61793c63f90f9555ff3c0f45b3b4 Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:25:39 +0200 Subject: [PATCH 177/300] Fixed according to PR comment, moved cli flag to an env variable --- docs/env_variables.md | 6 ++++++ include/envs.h | 1 + src/afl-fuzz-state.c | 20 ++++++++++++++++++++ src/afl-fuzz.c | 26 ++++++++------------------ 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index 6cd4104b..c9dc1bbd 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -584,6 +584,12 @@ checks or alter some of the more exotic semantics of the tool: - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to 0 to disable although it is 1st of April. + - If you need a specific interval to update fuzzer_stats file, you can + set `AFL_FUZZER_STATS_UPDATE_INTERVAL` to the interval in seconds you'd + the file to be updated. + Note that will not be exact and with slow targets it can take seconds + until there is a slice for the time test. + ## 5) Settings for afl-qemu-trace The QEMU wrapper used to instrument binary-only code supports several settings: diff --git a/include/envs.h b/include/envs.h index cf069a00..066921b9 100644 --- a/include/envs.h +++ b/include/envs.h @@ -91,6 +91,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_TRACEABLE", "AFL_FRIDA_VERBOSE", "AFL_FUZZER_ARGS", // oss-fuzz + "AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST", "AFL_GCC_DENYLIST", diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index e319c512..8964f38e 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -24,6 +24,7 @@ */ #include +#include #include "afl-fuzz.h" #include "envs.h" @@ -566,6 +567,25 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } + } else if (!strncmp(env, "AFL_FUZZER_STATS_UPDATE_INTERVAL", + + afl_environment_variable_len)) { + + u64 stats_update_freq_sec = + strtoull(get_afl_env(afl_environment_variables[i]), NULL, 0); + if (ULLONG_MAX == stats_update_freq_sec || + 0 == stats_update_freq_sec) { + + WARNF( + "Incorrect value given to AFL_FUZZER_STATS_UPDATE_INTERVAL, " + "using default of 60 seconds\n"); + + } else { + + afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000; + + } + } } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 78d9da71..d7708fdf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -211,8 +211,6 @@ static void usage(u8 *argv0, int more_help) { "(0-...)\n" " -e ext - file extension for the fuzz test input file (if " "needed)\n" - " -u - interval to update fuzzer_stats file in seconds, " - "defaults to 60 sec, minimum interval: 1 sec\n" "\n", argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); @@ -315,6 +313,8 @@ static void usage(u8 *argv0, int more_help) { " afl-clang-lto/afl-gcc-fast target\n" "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n" + "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in seconds, " + "(default: 60, minimum: 1)\n" "\n" ); @@ -504,7 +504,7 @@ fail: int main(int argc, char **argv_orig, char **envp) { s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; - u64 prev_queued = 0, stats_update_freq_sec = 0; + u64 prev_queued = 0; u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1, map_size = get_map_size(); u8 *extras_dir[4]; @@ -553,9 +553,11 @@ int main(int argc, char **argv_orig, char **envp) { afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - while ((opt = getopt(argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:u:" - "UV:WXx:YZ")) > 0) { + while ( + (opt = getopt( + argc, argv, + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > + 0) { switch (opt) { @@ -666,18 +668,6 @@ int main(int argc, char **argv_orig, char **envp) { break; - case 'u': - if (sscanf(optarg, "%llu", &stats_update_freq_sec) < 1) { - - FATAL("Bad syntax used for -u"); - - } - - if (stats_update_freq_sec < 1) { FATAL("-u interval must be >= 1"); } - - afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000; - break; - case 'i': /* input dir */ if (afl->in_dir) { FATAL("Multiple -i options not supported"); } From 7034348c577226f60fc6dbd912ec72d164cce829 Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:44:18 +0200 Subject: [PATCH 178/300] Changed warning message to use const instead of magic --- src/afl-fuzz-state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 8964f38e..58a69b60 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -578,7 +578,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) { WARNF( "Incorrect value given to AFL_FUZZER_STATS_UPDATE_INTERVAL, " - "using default of 60 seconds\n"); + "using default of %d seconds\n", + STATS_UPDATE_SEC); } else { From a30664c5639a924fd2bfd40bd9570f11ef09fd10 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Mar 2023 09:15:05 +0100 Subject: [PATCH 179/300] fix ci --- .github/workflows/ci.yml | 2 +- docs/fuzzing_binary-only_targets.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04cbaca8..b7d8b3b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - name: debug run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format- - name: update - run: sudo apt-get update && sudo apt-get upgrade -y + run: sudo apt-get purge -y "grub*" && sudo apt-get update && sudo apt-get upgrade -y - name: install packages run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build - name: compiler installed diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md index 266920e6..9d9d6bb6 100644 --- a/docs/fuzzing_binary-only_targets.md +++ b/docs/fuzzing_binary-only_targets.md @@ -201,10 +201,10 @@ afl-clang-fast's. ### RetroWrite RetroWrite is a static binary rewriter that can be combined with AFL++. If you -have an x86_64 binary that still has its symbols (i.e., not stripped binary), is -compiled with position independent code (PIC/PIE), and does not contain C++ -exceptions, then the RetroWrite solution might be for you. It decompiles to ASM -files which can then be instrumented with afl-gcc. +have an x86_64 or arm64 binary that does not contain C++ exceptions and - if +x86_64 - still has it's symbols and compiled with position independent code +(PIC/PIE), then the RetroWrite solution might be for you. +It decompiles to ASM files which can then be instrumented with afl-gcc. Binaries that are statically instrumented for fuzzing using RetroWrite are close in performance to compiler-instrumented binaries and outperform the QEMU-based From 6b75fe18315550bf72c4671a2be2bcc0286b031b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Mar 2023 09:16:32 +0100 Subject: [PATCH 180/300] fix ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7d8b3b7..9033de91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: - uses: actions/checkout@v3 - name: debug run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format- - - name: update - run: sudo apt-get purge -y "grub*" && sudo apt-get update && sudo apt-get upgrade -y + #- name: update + # run: sudo apt-get update && sudo apt-get upgrade -y - name: install packages run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build - name: compiler installed From cb8296bdb0a2f3f1115ecbe2ac9f1c5a86c94893 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Mar 2023 09:25:14 +0100 Subject: [PATCH 181/300] fix ci --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9033de91..a7601080 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,9 @@ jobs: - uses: actions/checkout@v3 - name: debug run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format- - #- name: update - # run: sudo apt-get update && sudo apt-get upgrade -y + - name: update + run: sudo apt-get update + # && sudo apt-get upgrade -y - name: install packages run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build - name: compiler installed From e6a05382b83817b245da51bcba16be5df56eb283 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Mar 2023 09:59:52 +0100 Subject: [PATCH 182/300] fix IGNORE_PROBLEMS and update qemuafl --- docs/Changelog.md | 2 ++ instrumentation/afl-compiler-rt.o.c | 39 +++++++++++++++++++---------- instrumentation/afl-llvm-common.h | 8 +++--- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- src/afl-fuzz-stats.c | 22 ++++++++-------- 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 8f71fd83..f4fa4382 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,8 @@ - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) - support llvm 15 native pcguard changes + - qemu_mode: + - fix _RANGES envs to allow hyphens in the filenames - new custom module: autotoken, grammar free fuzzer for text inputs - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support - better sanitizer default options support for all tools diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 9871d7f4..94022a65 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1539,12 +1539,16 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (start == stop || *start) return; x = getenv("AFL_INST_RATIO"); - if (x) { inst_ratio = (u32)atoi(x); } + if (x) { - if (!inst_ratio || inst_ratio > 100) { + inst_ratio = (u32)atoi(x); - fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); - abort(); + if (!inst_ratio || inst_ratio > 100) { + + fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); + abort(); + + } } @@ -1568,10 +1572,16 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { while (start < stop) { - if (likely(inst_ratio == 100) || R(100) < inst_ratio) - *start = offset; - else - *start = 0; // write to map[0] + if (likely(inst_ratio == 100) || R(100) < inst_ratio) { + + *(start++) = offset; + + } else { + + *(start++) = 0; // write to map[0] + + } + if (unlikely(++offset >= __afl_final_loc)) { offset = 4; } } @@ -1592,12 +1602,15 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { while (start < stop) { - if (likely(inst_ratio == 100) || R(100) < inst_ratio) - *start = ++__afl_final_loc; - else - *start = 0; // write to map[0] + if (likely(inst_ratio == 100) || R(100) < inst_ratio) { - start++; + *(start++) = ++__afl_final_loc; + + } else { + + *(start++) = 0; // write to map[0] + + } } diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h index 0112c325..16a13da5 100644 --- a/instrumentation/afl-llvm-common.h +++ b/instrumentation/afl-llvm-common.h @@ -37,10 +37,10 @@ typedef long double max_align_t; #define MNAME M.getSourceFileName() #define FMNAME F.getParent()->getSourceFileName() #if LLVM_VERSION_MAJOR >= 16 - // None becomes deprecated - // the standard std::nullopt_t is recommended instead - // from C++17 and onwards. - constexpr std::nullopt_t None = std::nullopt; +// None becomes deprecated +// the standard std::nullopt_t is recommended instead +// from C++17 and onwards. +constexpr std::nullopt_t None = std::nullopt; #endif #else #define MNAME std::string("") diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 9c68f02c..39e41f79 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -a8af9cbde7 +74c583b11a diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index a8af9cbd..74c583b1 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit a8af9cbde71e333ce72a46f15e655d0b82ed0939 +Subproject commit 74c583b11ac508b90660723da7ee9ff7ff77ee92 diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 26e1a50e..53ab8c77 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -672,12 +672,11 @@ void show_stats_normal(afl_state_t *afl) { /* If no coverage was found yet, check whether run time is greater than * exit_on_time. */ - if (unlikely( - !afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && - ((afl->last_find_time && - (cur_ms - afl->last_find_time) > afl->exit_on_time) || - (!afl->last_find_time && (cur_ms - afl->start_time) - > afl->exit_on_time)))) { + if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && + ((afl->last_find_time && + (cur_ms - afl->last_find_time) > afl->exit_on_time) || + (!afl->last_find_time && + (cur_ms - afl->start_time) > afl->exit_on_time)))) { afl->stop_soon = 2; @@ -1476,12 +1475,11 @@ void show_stats_pizza(afl_state_t *afl) { /* If no coverage was found yet, check whether run time is greater than * exit_on_time. */ - if (unlikely( - !afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && - ((afl->last_find_time && - (cur_ms - afl->last_find_time) > afl->exit_on_time) || - (!afl->last_find_time && (cur_ms - afl->start_time) - > afl->exit_on_time)))) { + if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && + ((afl->last_find_time && + (cur_ms - afl->last_find_time) > afl->exit_on_time) || + (!afl->last_find_time && + (cur_ms - afl->start_time) > afl->exit_on_time)))) { afl->stop_soon = 2; From 2f128e0dbd1b39f1d99a042f8813b93da1747731 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 6 Mar 2023 10:13:35 +0100 Subject: [PATCH 183/300] Revert "Merge pull request #1665 from devnexen/llvm_inst_mem_leaks" This reverts commit e5f8c7a6129e42d1798fac1131c912b2eca8159c, reversing changes made to e6a05382b83817b245da51bcba16be5df56eb283. --- instrumentation/cmplog-instructions-pass.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 2 +- instrumentation/cmplog-switches-pass.cc | 2 +- instrumentation/split-compares-pass.so.cc | 2 +- instrumentation/split-switches-pass.so.cc | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 7dcf8bfa..bca1f927 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -66,7 +66,7 @@ namespace { #if LLVM_MAJOR >= 11 /* use new pass manager */ class CmpLogInstructions : public PassInfoMixin { - llvm_shutdown_obj LSO; + public: CmpLogInstructions() { diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index c2c52874..0498156d 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -63,7 +63,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class CmpLogRoutines : public PassInfoMixin { - llvm_shutdown_obj LSO; + public: CmpLogRoutines() { diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index d96c5a4f..cd0ae76d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -64,7 +64,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class CmplogSwitches : public PassInfoMixin { - llvm_shutdown_obj LSO; + public: CmplogSwitches() { diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index a189c203..8a07610c 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -66,7 +66,7 @@ namespace { #if LLVM_MAJOR >= 11 class SplitComparesTransform : public PassInfoMixin { - llvm_shutdown_obj LSO; + public: // static char ID; SplitComparesTransform() : enableFPSplit(0) { diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index 1028c5b0..dcd89652 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -65,7 +65,7 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class SplitSwitchesTransform : public PassInfoMixin { - llvm_shutdown_obj LSO; + public: SplitSwitchesTransform() { From b571e88bd33ad7b5cf7dade93e6a1986cf8def56 Mon Sep 17 00:00:00 2001 From: Amit Elkabetz <12958411+amitelka@users.noreply.github.com> Date: Mon, 6 Mar 2023 12:40:54 +0200 Subject: [PATCH 184/300] Fixed according to CR --- src/afl-fuzz-state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 58a69b60..f9aa5cfe 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -573,7 +573,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) { u64 stats_update_freq_sec = strtoull(get_afl_env(afl_environment_variables[i]), NULL, 0); - if (ULLONG_MAX == stats_update_freq_sec || + if (stats_update_freq_sec >= UINT_MAX || 0 == stats_update_freq_sec) { WARNF( From e0866f51c7984c28866e7acdb153b5304c5cf7da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 13:57:03 +0100 Subject: [PATCH 185/300] support LLVMFuzzerTestOneInput -1 return --- docs/Changelog.md | 2 ++ test/test-cmplog.c | 2 +- utils/aflpp_driver/aflpp_driver.c | 13 ++++++++++++- utils/aflpp_driver/aflpp_driver_test.c | 19 +++++++++++-------- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index f4fa4382..5287d038 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,10 +7,12 @@ - afl-fuzz: - ensure temporary file descriptor is closed when not used - added `AFL_NO_WARN_INSTABILITY` + - added `AFL_FRIDA_STATS_INTERVAL` - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) - support llvm 15 native pcguard changes + - support for LLVMFuzzerTestOneInput -1 return - qemu_mode: - fix _RANGES envs to allow hyphens in the filenames - new custom module: autotoken, grammar free fuzzer for text inputs diff --git a/test/test-cmplog.c b/test/test-cmplog.c index d724ecaf..bd1b73e3 100644 --- a/test/test-cmplog.c +++ b/test/test-cmplog.c @@ -8,7 +8,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) { - if (i < 30) return 0; + if (i < 30) return -1; if (buf[0] != 'A') return 0; if (buf[1] != 'B') return 0; if (buf[2] != 'C') return 0; diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 03376b6a..f08c9864 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -58,10 +58,15 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out #include "hash.h" #endif +// AFL++ shared memory fuzz cases int __afl_sharedmem_fuzzing = 1; extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; +// AFL++ coverage map +extern unsigned char *__afl_area_ptr; +extern unsigned int __afl_map_size; + // libFuzzer interface is thin, so we don't include any libFuzzer headers. __attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); @@ -375,7 +380,13 @@ int LLVMFuzzerRunDriver(int *argcp, char ***argvp, } prev_length = length; - (void)callback(__afl_fuzz_ptr, length); + + if (unlikely(callback(__afl_fuzz_ptr, length) == -1)) { + + memset(__afl_area_ptr, 0, __afl_map_size); + __afl_area_ptr[0] = 1; + + } } diff --git a/utils/aflpp_driver/aflpp_driver_test.c b/utils/aflpp_driver/aflpp_driver_test.c index 527ba57b..7cffa4a1 100644 --- a/utils/aflpp_driver/aflpp_driver_test.c +++ b/utils/aflpp_driver/aflpp_driver_test.c @@ -2,9 +2,9 @@ #include #include -void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { +int __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { - if (Size < 5) return; + if (Size < 5) return -1; if (Data[0] == 'F') if (Data[1] == 'A') @@ -12,13 +12,16 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Data[3] == '$') if (Data[4] == '$') abort(); -} - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - - if (Size) crashme(Data, Size); - return 0; } +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + if (Size) + return crashme(Data, Size); + else + return -1; + +} + From cd5764170595e5bafa85b2d28c63135b1ab07146 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 14:25:45 +0100 Subject: [PATCH 186/300] fast schedules n_fuzz update after classify --- src/afl-fuzz-bitmap.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index b4e9537e..c65dd641 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -475,10 +475,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { only be used for special schedules */ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + classify_counts(&afl->fsrv); + classified = 1; + cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); /* Saturated increment */ - if (afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF) + if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) afl->n_fuzz[cksum % N_FUZZ_SIZE]++; } @@ -488,7 +491,15 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Keep only if there are new bits in the map, add to queue for future fuzzing, etc. */ - new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); + if (likely(classified)) { + + new_bits = has_new_bits(afl, afl->virgin_bits); + + } else { + + new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); + + } if (likely(!new_bits)) { @@ -497,8 +508,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - classified = new_bits; - save_to_queue: #ifndef SIMPLE_FILES @@ -556,21 +565,21 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - /* AFLFast schedule? update the new queue entry */ - if (cksum) { + if (unlikely(!classified && new_bits)) { - afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; - afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + /* due to classify counts we have to recalculate the checksum */ + afl->queue_top->exec_cksum = + hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + classified = 1; } - /* due to classify counts we have to recalculate the checksum */ - afl->queue_top->exec_cksum = - hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + /* For AFLFast schedules we update the new queue entry */ + afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; + afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; /* Try to calibrate inline; this also calls update_bitmap_score() when successful. */ - res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -604,7 +613,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (likely(!afl->non_instrumented_mode)) { - if (!classified) { + if (unlikely(!classified)) { classify_counts(&afl->fsrv); classified = 1; @@ -729,7 +738,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (likely(!afl->non_instrumented_mode)) { - if (!classified) { classify_counts(&afl->fsrv); } + if (unlikely(!classified)) { + + classify_counts(&afl->fsrv); + classified = 1; + + } simplify_trace(afl, afl->fsrv.trace_bits); From 1385c24a7d3baf31f91533ebdf4b43b02ce3b1b1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 14:41:24 +0100 Subject: [PATCH 187/300] fix qemuafl name range --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 39e41f79..3ee92cd5 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -74c583b11a +5d0a7434f7 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 74c583b1..5d0a7434 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 74c583b11ac508b90660723da7ee9ff7ff77ee92 +Subproject commit 5d0a7434f7ca9c45175492d5819c2594bac72087 From dc7ef967d8dd4a338ddc72b41dcf8840437aabc2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 14:56:38 +0100 Subject: [PATCH 188/300] fix attempt at lsan --- src/afl-common.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index d83130b4..b0df1994 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -66,23 +66,40 @@ void set_sanitizer_defaults() { u8 *have_msan_options = getenv("MSAN_OPTIONS"); u8 *have_lsan_options = getenv("LSAN_OPTIONS"); u8 have_san_options = 0; - if (have_asan_options || have_ubsan_options || have_msan_options || - have_lsan_options) - have_san_options = 1; - u8 default_options[1024] = + u8 default_options[1024] = "detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_" "size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" "handle_abort=0:handle_sigfpe=0:handle_sigill=0:"; - if (!have_lsan_options) strcat(default_options, "detect_leaks=0:"); + if (have_asan_options || have_ubsan_options || have_msan_options || + have_lsan_options) { + + have_san_options = 1; + + } + + /* LSAN does not support abort_on_error=1. (is this still true??) */ + + if (!have_lsan_options) { + + u8 buf[2048] = ""; + if (!have_san_options) { strcpy(buf, default_options); } + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:"); + setenv("LSAN_OPTIONS", buf, 1); + + } + + /* for everything not LSAN we disable detect_leaks */ + + if (!have_lsan_options) { strcat(default_options, "detect_leaks=0:"); } /* Set sane defaults for ASAN if nothing else is specified. */ - if (!have_san_options) setenv("ASAN_OPTIONS", default_options, 1); + if (!have_san_options) { setenv("ASAN_OPTIONS", default_options, 1); } /* Set sane defaults for UBSAN if nothing else is specified. */ - if (!have_san_options) setenv("UBSAN_OPTIONS", default_options, 1); + if (!have_san_options) { setenv("UBSAN_OPTIONS", default_options, 1); } /* MSAN is tricky, because it doesn't support abort_on_error=1 at this point. So, we do this in a very hacky way. */ @@ -90,25 +107,12 @@ void set_sanitizer_defaults() { if (!have_msan_options) { u8 buf[2048] = ""; - if (!have_san_options) strcpy(buf, default_options); + if (!have_san_options) { strcpy(buf, default_options); } strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:"); setenv("MSAN_OPTIONS", buf, 1); } - /* LSAN, too, does not support abort_on_error=1. (is this still true??) */ - - if (!have_lsan_options) { - - u8 buf[2048] = ""; - if (!have_san_options) strcpy(buf, default_options); - strcat(buf, - "exitcode=" STRINGIFY( - LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:"); - setenv("LSAN_OPTIONS", buf, 1); - - } - /* Envs for QASan */ setenv("QASAN_MAX_CALL_STACK", "0", 0); setenv("QASAN_SYMBOLIZE", "0", 0); From 5221938945cc5ff15af04b727c6a7e0085005044 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 17:36:13 +0100 Subject: [PATCH 189/300] various fixes --- docs/Changelog.md | 2 +- include/common.h | 3 +++ instrumentation/afl-compiler-rt.o.c | 18 +++++++++----- src/afl-analyze.c | 4 ++++ src/afl-common.c | 37 +++++++++++++++++++++++------ src/afl-fuzz-init.c | 19 +++++++++------ src/afl-fuzz-stats.c | 2 +- src/afl-showmap.c | 4 ++++ src/afl-tmin.c | 4 ++++ 9 files changed, 71 insertions(+), 22 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 5287d038..25c1f6bc 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,7 +20,7 @@ - better sanitizer default options support for all tools - unicorn_mode: updated and minor issues fixed - frida_mode: fix issue on MacOS - - more minor fixes + - more minor fixes and cross-platform support ### Version ++4.05c (release) - MacOS: libdislocator, libtokencap etc. do not work with modern diff --git a/include/common.h b/include/common.h index c5a32cdb..5d198468 100644 --- a/include/common.h +++ b/include/common.h @@ -143,5 +143,8 @@ FILE *create_ffile(u8 *fn); /* create a file */ s32 create_file(u8 *fn); +/* memmem implementation as not all platforms support this */ +void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); + #endif diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 94022a65..a88396d4 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1622,17 +1622,23 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } - if (__afl_already_initialized_shm && __afl_final_loc > __afl_map_size) { + if (__afl_already_initialized_shm) { - if (__afl_debug) { + if (__afl_final_loc > __afl_map_size) { - fprintf(stderr, "Reinit shm necessary (+%u)\n", - __afl_final_loc - __afl_map_size); + if (__afl_debug) { + + fprintf(stderr, "Reinit shm necessary (+%u)\n", + __afl_final_loc - __afl_map_size); + + } + + __afl_unmap_shm(); + __afl_map_shm(); } - __afl_unmap_shm(); - __afl_map_shm(); + __afl_map_size = __afl_final_loc + 1; } diff --git a/src/afl-analyze.c b/src/afl-analyze.c index d4a9aa91..9734f75c 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -725,7 +725,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; + #ifdef SA_RESTART sa.sa_flags = SA_RESTART; + #else + sa.sa_flags = 0; + #endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); diff --git a/src/afl-common.c b/src/afl-common.c index b0df1994..86226c9f 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -58,6 +58,25 @@ u8 last_intr = 0; #define AFL_PATH "/usr/local/lib/afl/" #endif +void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, + size_t needlelen) { + + if (unlikely(needlelen > haystacklen)) { return NULL; } + + for (u32 i = 0; i <= haystacklen - needlelen; ++i) { + + if (unlikely(memcmp(haystack + i, needle, needlelen) == 0)) { + + return (void *)(haystack + i); + + } + + } + + return (void *)NULL; + +} + void set_sanitizer_defaults() { /* Set sane defaults for ASAN if nothing else is specified. */ @@ -67,9 +86,9 @@ void set_sanitizer_defaults() { u8 *have_lsan_options = getenv("LSAN_OPTIONS"); u8 have_san_options = 0; u8 default_options[1024] = - "detect_odr_violation=0:abort_on_error=1:symbolize=0:malloc_context_" - "size=0:allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" - "handle_abort=0:handle_sigfpe=0:handle_sigill=0:"; + "detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_" + "return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_" + "sigfpe=0:handle_sigill=0:"; if (have_asan_options || have_ubsan_options || have_msan_options || have_lsan_options) { @@ -84,14 +103,18 @@ void set_sanitizer_defaults() { u8 buf[2048] = ""; if (!have_san_options) { strcpy(buf, default_options); } - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:"); + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); setenv("LSAN_OPTIONS", buf, 1); } /* for everything not LSAN we disable detect_leaks */ - if (!have_lsan_options) { strcat(default_options, "detect_leaks=0:"); } + if (!have_lsan_options) { + + strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + + } /* Set sane defaults for ASAN if nothing else is specified. */ @@ -130,7 +153,7 @@ u32 check_binary_signatures(u8 *fn) { if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); } setenv(PERSIST_ENV_VAR, "1", 1); @@ -155,7 +178,7 @@ u32 check_binary_signatures(u8 *fn) { } - if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + if (afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); } setenv(DEFER_ENV_VAR, "1", 1); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index c20965b4..3b441eee 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -24,7 +24,9 @@ */ #include "afl-fuzz.h" +#include "common.h" #include +#include #include "cmplog.h" #ifdef HAVE_AFFINITY @@ -2786,7 +2788,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { !afl->fsrv.nyx_mode && #endif !afl->fsrv.cs_mode && !afl->non_instrumented_mode && - !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + !afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST "Looks like the target binary is not instrumented! The fuzzer depends " @@ -2817,7 +2819,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) && - memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { + afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST "This program appears to be instrumented with afl-gcc, but is being " @@ -2830,9 +2832,9 @@ void check_binary(afl_state_t *afl, u8 *fname) { } - if (memmem(f_data, f_len, "__asan_init", 11) || - memmem(f_data, f_len, "__msan_init", 11) || - memmem(f_data, f_len, "__lsan_init", 11)) { + if (afl_memmem(f_data, f_len, "__asan_init", 11) || + afl_memmem(f_data, f_len, "__msan_init", 11) || + afl_memmem(f_data, f_len, "__lsan_init", 11)) { afl->fsrv.uses_asan = 1; @@ -2840,7 +2842,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { /* Detect persistent & deferred init signatures in the binary. */ - if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); @@ -2867,7 +2869,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } if (afl->fsrv.frida_mode || - memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { OKF(cPIN "Deferred forkserver binary detected."); setenv(DEFER_ENV_VAR, "1", 1); @@ -2923,8 +2925,11 @@ void setup_signal_handlers(void) { struct sigaction sa; + memset((void*)&sa, 0, sizeof(sa)); sa.sa_handler = NULL; +#ifdef SA_RESTART sa.sa_flags = SA_RESTART; +#endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 65caf5ee..f53fd610 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -62,7 +62,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { if (memchr(argv[i], '\'', strlen(argv[i]))) { #else - if (index(argv[i], '\'')) { + if (strchr(argv[i], '\'')) { #endif diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 1e281d08..32dd1c20 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -654,7 +654,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; + #ifdef SA_RESTART sa.sa_flags = SA_RESTART; + #else + sa.sa_flags = 0; + #endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 12c5e0c9..530578d9 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -743,7 +743,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; + #ifdef SA_RESTART sa.sa_flags = SA_RESTART; + #else + sa.sa_flags = 0; + #endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); From 30483919eb65f6301dbbba7762e28a6d21972571 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 9 Mar 2023 17:37:29 +0100 Subject: [PATCH 190/300] code format --- include/common.h | 3 ++- src/afl-analyze.c | 8 ++++---- src/afl-fuzz-init.c | 2 +- src/afl-showmap.c | 8 ++++---- src/afl-tmin.c | 8 ++++---- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/common.h b/include/common.h index 5d198468..0958b035 100644 --- a/include/common.h +++ b/include/common.h @@ -144,7 +144,8 @@ FILE *create_ffile(u8 *fn); s32 create_file(u8 *fn); /* memmem implementation as not all platforms support this */ -void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); +void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, + size_t needlelen); #endif diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 9734f75c..548956d8 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -725,11 +725,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; - #ifdef SA_RESTART +#ifdef SA_RESTART sa.sa_flags = SA_RESTART; - #else - sa.sa_flags = 0; - #endif +#else + sa.sa_flags = 0; +#endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 3b441eee..01d1e82e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2925,7 +2925,7 @@ void setup_signal_handlers(void) { struct sigaction sa; - memset((void*)&sa, 0, sizeof(sa)); + memset((void *)&sa, 0, sizeof(sa)); sa.sa_handler = NULL; #ifdef SA_RESTART sa.sa_flags = SA_RESTART; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 32dd1c20..29abeb13 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -654,11 +654,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; - #ifdef SA_RESTART +#ifdef SA_RESTART sa.sa_flags = SA_RESTART; - #else - sa.sa_flags = 0; - #endif +#else + sa.sa_flags = 0; +#endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 530578d9..c0087f5f 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -743,11 +743,11 @@ static void setup_signal_handlers(void) { struct sigaction sa; sa.sa_handler = NULL; - #ifdef SA_RESTART +#ifdef SA_RESTART sa.sa_flags = SA_RESTART; - #else - sa.sa_flags = 0; - #endif +#else + sa.sa_flags = 0; +#endif sa.sa_sigaction = NULL; sigemptyset(&sa.sa_mask); From aabfe781fd05fe7b0981cc933d10900d92655369 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 10:22:35 +0100 Subject: [PATCH 191/300] enhance tests for macos --- test/test-basic.sh | 101 +++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/test/test-basic.sh b/test/test-basic.sh index 538b6931..fdd1ed41 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -7,9 +7,10 @@ AFL_GCC=afl-gcc $ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin" test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "i386" && { test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && { - ../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1 - AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 - test -e test-instr.plain && { + ../${AFL_GCC} -v 2>&1 | grep -qi "gcc version" && { + ../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1 + AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 + test -e test-instr.plain && { $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded" echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 @@ -35,15 +36,15 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc } test "$TUPLES" -lt 3 && SKIP=1 true # this is needed because of the test above - } || { + } || { $ECHO "$RED[!] ${AFL_GCC} failed" echo CUT------------------------------------------------------------------CUT uname -a ../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c echo CUT------------------------------------------------------------------CUT CODE=1 - } - test -e test-compcov.harden && { + } + test -e test-compcov.harden && { nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working" } || { @@ -54,16 +55,16 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 } rm -f test-compcov.harden - } || { + } || { $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed" CODE=1 - } - # now we want to be sure that afl-fuzz is working - # make sure crash reporter is disabled on Mac OS X - (test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && { + } + # now we want to be sure that afl-fuzz is working + # make sure crash reporter is disabled on Mac OS X + (test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && { $ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET" true - }) || { + }) || { mkdir -p in echo 0 > in/in test -z "$SKIP" && { @@ -116,83 +117,89 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc } rm -rf in out errors in2 unset AFL_QUIET + } + rm -f test-instr.plain + } || { + $ECHO "$YELLOW[-] afl-gcc executes clang, cannot test!" + INCOMPLETE=1 } - rm -f test-instr.plain } || { - $ECHO "$YELLOW[-] afl is not compiled, cannot test" - INCOMPLETE=1 + $ECHO "$YELLOW[-] afl is not compiled, cannot test" + INCOMPLETE=1 } - if [ ${AFL_GCC} = "afl-gcc" ] ; then AFL_GCC=afl-clang ; else AFL_GCC=afl-gcc ; fi - $ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin" + + AFL_CLANG=afl-clang + $ECHO "$BLUE[*] Testing: ${AFL_CLANG}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin" SKIP= - test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && { - ../${AFL_GCC} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1 - AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 - test -e test-instr.plain && { - $ECHO "$GREEN[+] ${AFL_GCC} compilation succeeded" + test -e ../${AFL_CLANG} -a -e ../afl-showmap -a -e ../afl-fuzz && { + ../${AFL_CLANG} -v 2>&1 | grep -qi "clang version" && { + ../${AFL_CLANG} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1 + AFL_HARDEN=1 ../${AFL_CLANG} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 + test -e test-instr.plain && { + $ECHO "$GREEN[+] ${AFL_CLANG} compilation succeeded" echo 0 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.0 -r -- ./test-instr.plain > /dev/null 2>&1 AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-instr.plain.1 -r -- ./test-instr.plain < /dev/null > /dev/null 2>&1 test -e test-instr.plain.0 -a -e test-instr.plain.1 && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { - $ECHO "$RED[!] ${AFL_GCC} instrumentation should be different on different input but is not" + $ECHO "$RED[!] ${AFL_CLANG} instrumentation should be different on different input but is not" CODE=1 } || { - $ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly" + $ECHO "$GREEN[+] ${AFL_CLANG} instrumentation present and working correctly" } } || { - $ECHO "$RED[!] ${AFL_GCC} instrumentation failed" + $ECHO "$RED[!] ${AFL_CLANG} instrumentation failed" CODE=1 } rm -f test-instr.plain.0 test-instr.plain.1 TUPLES=`echo 1|AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 1 -a "$TUPLES" -lt 12 && { - $ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine" + $ECHO "$GREEN[+] ${AFL_CLANG} run reported $TUPLES instrumented locations which is fine" } || { - $ECHO "$RED[!] ${AFL_GCC} instrumentation produces weird numbers: $TUPLES" + $ECHO "$RED[!] ${AFL_CLANG} instrumentation produces weird numbers: $TUPLES" CODE=1 } test "$TUPLES" -lt 3 && SKIP=1 true # this is needed because of the test above - } || { - $ECHO "$RED[!] ${AFL_GCC} failed" + } || { + $ECHO "$RED[!] ${AFL_CLANG} failed" echo CUT------------------------------------------------------------------CUT uname -a - ../${AFL_GCC} -o test-instr.plain ../test-instr.c + ../${AFL_CLANG} -o test-instr.plain ../test-instr.c echo CUT------------------------------------------------------------------CUT CODE=1 - } - test -e test-compcov.harden && { + } + test -e test-compcov.harden && { nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { - $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working" + $ECHO "$GREEN[+] ${AFL_CLANG} hardened mode succeeded and is working" } || { - $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened" + $ECHO "$RED[!] ${AFL_CLANG} hardened mode is not hardened" CODE=1 } rm -f test-compcov.harden - } || { - $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed" + } || { + $ECHO "$RED[!] ${AFL_CLANG} hardened mode compilation failed" CODE=1 - } - # now we want to be sure that afl-fuzz is working - # make sure crash reporter is disabled on Mac OS X - (test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && { + } + # now we want to be sure that afl-fuzz is working + # make sure crash reporter is disabled on Mac OS X + (test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && { $ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET" true - }) || { + }) || { mkdir -p in echo 0 > in/in test -z "$SKIP" && { - $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds" + $ECHO "$GREY[*] running afl-fuzz for ${AFL_CLANG}, this will take approx 10 seconds" { ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { - $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}" + $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_CLANG}" } || { echo CUT------------------------------------------------------------------CUT cat errors echo CUT------------------------------------------------------------------CUT - $ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}" + $ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_CLANG}" CODE=1 } } @@ -247,8 +254,12 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc } rm -rf in out errors in2 unset AFL_QUIET + } + rm -f test-instr.plain + } && { + $ECHO "$YELLOW[-] afl-clang executes gcc, cannot test" + INCOMPLETE=1 } - rm -f test-instr.plain } || { $ECHO "$YELLOW[-] afl is not compiled, cannot test" INCOMPLETE=1 From 4c7c78d92648bd1c5ec1e2d5115d32872a2a5905 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 10:59:52 +0100 Subject: [PATCH 192/300] enhance tests for macos --- test/test-basic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-basic.sh b/test/test-basic.sh index fdd1ed41..067d8a47 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -256,7 +256,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc unset AFL_QUIET } rm -f test-instr.plain - } && { + } || { $ECHO "$YELLOW[-] afl-clang executes gcc, cannot test" INCOMPLETE=1 } From 1d4f779d4d5b1e20cb4b660676f92cd5db70589b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 11:10:09 +0100 Subject: [PATCH 193/300] debug macos ci --- GNUmakefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 6921cc85..81d392a6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -547,9 +547,13 @@ test_build: afl-cc afl-gcc afl-as afl-showmap @echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..." @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null - echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr + echo debug 0 + -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr + echo debug 1 @rm -f test-instr + echo debug 2 @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi + echo debug 3 @echo @echo "[+] All right, the instrumentation of afl-cc seems to be working!" # @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..." From af77dab66661b49c4082bfdf05d681a3a3f12e25 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 15:12:15 +0100 Subject: [PATCH 194/300] macos ci debug --- GNUmakefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index 81d392a6..80341b73 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -546,6 +546,9 @@ ifndef AFL_NO_X86 test_build: afl-cc afl-gcc afl-as afl-showmap @echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..." @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) + echo debug -1 + ls -l ./test-instr + -strings ./test-instr | grep afl ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null echo debug 0 -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr From c3cf918bcb6190bcce450acf96115dc03cd4ebfd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 15:16:55 +0100 Subject: [PATCH 195/300] macos ci debug --- GNUmakefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 80341b73..9be52806 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -547,9 +547,7 @@ test_build: afl-cc afl-gcc afl-as afl-showmap @echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..." @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) echo debug -1 - ls -l ./test-instr - -strings ./test-instr | grep afl - ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null + AFL_DEBUG=1 ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null echo debug 0 -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr echo debug 1 From e32e82537228c0e7060f1e6d98b40bf52c6d18c6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 10 Mar 2023 15:26:38 +0100 Subject: [PATCH 196/300] macos ci debug --- GNUmakefile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 9be52806..8d66e2f4 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -546,15 +546,10 @@ ifndef AFL_NO_X86 test_build: afl-cc afl-gcc afl-as afl-showmap @echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..." @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) - echo debug -1 - AFL_DEBUG=1 ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null - echo debug 0 + - ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr - echo debug 1 @rm -f test-instr - echo debug 2 @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi - echo debug 3 @echo @echo "[+] All right, the instrumentation of afl-cc seems to be working!" # @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..." From 7ab689ef0e3fa49a6c059ae1bfe46f77e6c79d12 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 13 Mar 2023 10:12:45 +0100 Subject: [PATCH 197/300] fix qemu_mode --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 3ee92cd5..43dc832b 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -5d0a7434f7 +249bf0c872 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 5d0a7434..249bf0c8 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 5d0a7434f7ca9c45175492d5819c2594bac72087 +Subproject commit 249bf0c8723671a1eebe400a9631d9e69306ff4c From ac4dd1605ed0bf25b2b4562da114f93f2852d200 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Mar 2023 09:44:11 +0100 Subject: [PATCH 198/300] fix ci --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7601080..aa5829a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,8 @@ jobs: run: gcc -v; echo; clang -v - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev + - name: install pip + run: sudo python3 -m ensurepip - name: build afl++ run: make distrib ASAN_BUILD=1 - name: run tests From 988028bb3b6b0a15cb9c601a4db6793f2e5291ad Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Mar 2023 09:45:49 +0100 Subject: [PATCH 199/300] fix ci --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa5829a8..9751c28d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,13 +26,11 @@ jobs: run: sudo apt-get update # && sudo apt-get upgrade -y - name: install packages - run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build + run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip - name: compiler installed run: gcc -v; echo; clang -v - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev - - name: install pip - run: sudo python3 -m ensurepip - name: build afl++ run: make distrib ASAN_BUILD=1 - name: run tests From 84274f2e5d7287c383f3b0f61f1f12366b694650 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Mar 2023 10:16:46 +0100 Subject: [PATCH 200/300] more ci repair attempts --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9751c28d..5139ee75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,8 @@ jobs: run: sudo apt-get update # && sudo apt-get upgrade -y - name: install packages - run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip + #run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip + run: sudo apt-get install -y -m -f build-essential git libtool libtool-bin automake flex bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip - name: compiler installed run: gcc -v; echo; clang -v - name: install gcc plugin From bd3855fe5dd653ef3bfc930dcfa2a8d9063fc1da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 15 Mar 2023 10:18:33 +0100 Subject: [PATCH 201/300] improve ci time --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5139ee75..ed1f3228 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev - name: build afl++ - run: make distrib ASAN_BUILD=1 + run: make distrib ASAN_BUILD=1 NO_NYX=1 - name: run tests run: sudo -E ./afl-system-config; make tests macos: From 5c5b73df8288d5e02aa3c2ab20aec51ae82f8a41 Mon Sep 17 00:00:00 2001 From: Dmitry Savintsev Date: Tue, 21 Mar 2023 13:32:59 +0100 Subject: [PATCH 202/300] nit: fix minor typos change "cannot be build" to "cannot be built" --- GNUmakefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 8d66e2f4..72da14ea 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -312,9 +312,9 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu @echo @echo Build Summary: @test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler" - @test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" - @test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" - @test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be build, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it" + @test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" + @test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" + @test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it" ifneq "$(SYS)" "Darwin" @test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this" endif @@ -732,9 +732,9 @@ endif @echo @echo Build Summary: @test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler" - @test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" - @test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be build, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" - @test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be build, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it" + @test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" + @test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md" + @test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it" ifneq "$(SYS)" "Darwin" test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this" endif From 478f0bbc1ed4bdb39d365dd9d6c69c10917c8073 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 21 Mar 2023 16:23:51 +0100 Subject: [PATCH 203/300] ci test --- test/test-all.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test-all.sh b/test/test-all.sh index 0c189727..3cb692ca 100755 --- a/test/test-all.sh +++ b/test/test-all.sh @@ -23,3 +23,5 @@ . ./test-unittests.sh . ./test-post.sh + +exit 0 \ No newline at end of file From 0f62e0b1674f19c41c5deb65354e832a0aa87bef Mon Sep 17 00:00:00 2001 From: yuawn Date: Sat, 25 Mar 2023 09:28:35 +0000 Subject: [PATCH 204/300] add check for n_fuzz update --- src/afl-fuzz-bitmap.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index c65dd641..fe90faf0 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -575,8 +575,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } /* For AFLFast schedules we update the new queue entry */ - afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; - afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + if (cksum) { + + afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; + afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + + } /* Try to calibrate inline; this also calls update_bitmap_score() when successful. */ From e24ae963614ecc0874ab5e8ff370419401292913 Mon Sep 17 00:00:00 2001 From: yuawn Date: Sat, 25 Mar 2023 09:45:02 +0000 Subject: [PATCH 205/300] add likely() to cksum check --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index fe90faf0..d9c792d1 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -575,7 +575,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } /* For AFLFast schedules we update the new queue entry */ - if (cksum) { + if (likely(cksum)) { afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; From 9bc5abc4eca13996fccc05b4ad08b7ac5a217e25 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 25 Mar 2023 12:14:08 +0100 Subject: [PATCH 206/300] reduce CI resources --- test/test-all.sh | 2 +- test/test-basic.sh | 4 ++-- test/test-custom-mutators.sh | 6 +++--- test/test-frida-mode.sh | 6 +++--- test/test-gcc-plugin.sh | 2 +- test/test-llvm.sh | 6 +++--- test/test-qemu-mode.sh | 8 ++++---- test/test-unicorn-mode.sh | 6 +++--- utils/aflpp_driver/aflpp_driver_test.c | 4 +++- 9 files changed, 23 insertions(+), 21 deletions(-) diff --git a/test/test-all.sh b/test/test-all.sh index 3cb692ca..c0bd1b63 100755 --- a/test/test-all.sh +++ b/test/test-all.sh @@ -14,7 +14,7 @@ . ./test-qemu-mode.sh -. ./test-frida-mode.sh +#. ./test-frida-mode.sh . ./test-unicorn-mode.sh diff --git a/test/test-basic.sh b/test/test-basic.sh index 067d8a47..53de8c64 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -70,7 +70,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for ${AFL_GCC}, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_GCC}" @@ -191,7 +191,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for ${AFL_CLANG}, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with ${AFL_CLANG}" diff --git a/test/test-custom-mutators.sh b/test/test-custom-mutators.sh index a4347068..49feedc0 100755 --- a/test/test-custom-mutators.sh +++ b/test/test-custom-mutators.sh @@ -38,7 +38,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS # Run afl-fuzz w/ the C mutator $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" { - AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 + AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 } >>errors 2>&1 # Check results @@ -58,7 +58,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS # Run afl-fuzz w/ multiple C mutators $ECHO "$GREY[*] running afl-fuzz with multiple custom C mutators, this will take approx 10 seconds" { - AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-multiple-mutators >>errors 2>&1 + AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-multiple-mutators >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:000000* 2>/dev/null )" && { # TODO: update here @@ -88,7 +88,7 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && { { export PYTHONPATH=${CUSTOM_MUTATOR_PATH} export AFL_PYTHON_MODULE=example - AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 + AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 unset PYTHONPATH unset AFL_PYTHON_MODULE } >>errors 2>&1 diff --git a/test/test-frida-mode.sh b/test/test-frida-mode.sh index 9e1f756d..3ae84656 100755 --- a/test/test-frida-mode.sh +++ b/test/test-frida-mode.sh @@ -22,7 +22,7 @@ test -e ../afl-frida-trace.so && { echo 00000 > in/in $ECHO "$GREY[*] running afl-fuzz for frida_mode, this will take approx 10 seconds" { - AFL_DEBUG=1 AFL_FRIDA_VERBOSE=1 ../afl-fuzz -m ${MEM_LIMIT} -V10 -O -i in -o out -- ./test-instr >>errors 2>&1 + AFL_DEBUG=1 AFL_FRIDA_VERBOSE=1 ../afl-fuzz -m ${MEM_LIMIT} -V07 -O -i in -o out -- ./test-instr >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with frida_mode" @@ -39,7 +39,7 @@ test -e ../afl-frida-trace.so && { test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && { $ECHO "$GREY[*] running afl-fuzz for frida_mode cmplog, this will take approx 10 seconds" { - ../afl-fuzz -m none -V10 -O -c 0 -i in -o out -- ./test-compcov >>errors 2>&1 + ../afl-fuzz -m none -V07 -O -c 0 -i in -o out -- ./test-compcov >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000003* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with frida_mode cmplog" @@ -67,7 +67,7 @@ test -e ../afl-frida-trace.so && { file test-instr export AFL_DEBUG_CHILD=1 export AFL_FRIDA_VERBOSE=1 - ../afl-fuzz -m ${MEM_LIMIT} -V10 -O -i in -o out -- ./test-instr + ../afl-fuzz -m ${MEM_LIMIT} -V07 -O -i in -o out -- ./test-instr nm test-instr | grep -i "main" unset AFL_FRIDA_PERSISTENT_ADDR } >>errors 2>&1 diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh index 95ae9c47..54e6987f 100755 --- a/test/test-gcc-plugin.sh +++ b/test/test-gcc-plugin.sh @@ -63,7 +63,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { echo 0 > in/in $ECHO "$GREY[*] running afl-fuzz for gcc_plugin, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain.gccpi >>errors 2>&1 + ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain.gccpi >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with gcc_plugin" diff --git a/test/test-llvm.sh b/test/test-llvm.sh index 52be04ef..68649c23 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -133,7 +133,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { test -z "$SKIP" && { $ECHO "$GREY[*] running afl-fuzz for llvm_mode, this will take approx 10 seconds" { - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -D -- ./test-instr.plain >>errors 2>&1 + ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode" @@ -228,7 +228,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { echo ZZZZ > in/in $ECHO "$GREY[*] running afl-fuzz with floating point splitting, this will take max. 45 seconds" { - AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -Z -s 123 -V50 -m ${MEM_LIMIT} -i in -o out -D -- ./test-floatingpoint >>errors 2>&1 + AFL_BENCH_UNTIL_CRASH=1 AFL_NO_UI=1 ../afl-fuzz -Z -s 123 -V15 -m ${MEM_LIMIT} -i in -o out -- ./test-floatingpoint >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:* 2>/dev/null )" && { $ECHO "$GREEN[+] llvm_mode laf-intel floatingpoint splitting feature works correctly" @@ -263,7 +263,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { { mkdir -p in echo 00000000000000000000000000000000 > in/in - AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V60 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1 + AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V15 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" & { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog" diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh index c7734217..9e268963 100755 --- a/test/test-qemu-mode.sh +++ b/test/test-qemu-mode.sh @@ -22,7 +22,7 @@ test -e ../afl-qemu-trace && { echo 00000 > in/in $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} -V07 -Q -i in -o out -- ./test-instr >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode" @@ -63,7 +63,7 @@ test -e ../afl-qemu-trace && { { export AFL_PRELOAD=../libcompcov.so export AFL_COMPCOV_LEVEL=2 - ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V07 -Q -i in -o out -- ./test-compcov >>errors 2>&1 unset AFL_PRELOAD unset AFL_COMPCOV_LEVEL } >>errors 2>&1 @@ -88,7 +88,7 @@ test -e ../afl-qemu-trace && { test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && { $ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds" { - ../afl-fuzz -m none -V10 -Q -c 0 -i in -o out -- ./test-compcov >>errors 2>&1 + ../afl-fuzz -m none -V07 -Q -c 0 -i in -o out -- ./test-compcov >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000001* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog" @@ -126,7 +126,7 @@ test -e ../afl-qemu-trace && { $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')" env|grep AFL_|sort file test-instr - ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-instr + ../afl-fuzz -m ${MEM_LIMIT} -V07 -Q -i in -o out -- ./test-instr unset AFL_QEMU_PERSISTENT_ADDR } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh index f8ff4190..338c5982 100755 --- a/test/test-unicorn-mode.sh +++ b/test/test-unicorn-mode.sh @@ -34,7 +34,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && cd ../unicorn_mode/samples/persistent make >>errors 2>&1 $ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds" - AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1 + AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V15 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)" } || { @@ -61,7 +61,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && { $ECHO "$GREY[*] running afl-fuzz for unicorn_mode in python, this will take approx 25 seconds" { - ../afl-fuzz -m ${MEM_LIMIT} -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/python_simple/simple_test_harness.py @@ >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V15 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/python_simple/simple_test_harness.py @@ >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode" @@ -80,7 +80,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && $ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 35 seconds" { export AFL_COMPCOV_LEVEL=2 - ../afl-fuzz -m ${MEM_LIMIT} -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1 + ../afl-fuzz -m ${MEM_LIMIT} -V15 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1 unset AFL_COMPCOV_LEVEL } >>errors 2>&1 test -n "$( ls out/default/queue/id:000001* 2>/dev/null )" && { diff --git a/utils/aflpp_driver/aflpp_driver_test.c b/utils/aflpp_driver/aflpp_driver_test.c index 7cffa4a1..32119485 100644 --- a/utils/aflpp_driver/aflpp_driver_test.c +++ b/utils/aflpp_driver/aflpp_driver_test.c @@ -2,6 +2,8 @@ #include #include +char *foo = NULL; + int __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Size < 5) return -1; @@ -10,7 +12,7 @@ int __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Data[1] == 'A') if (Data[2] == '$') if (Data[3] == '$') - if (Data[4] == '$') abort(); + if (Data[4] == '$') *foo = 1; return 0; From d95540917848ee3f21a73d70b10a5be76b28cbf4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 25 Mar 2023 20:37:08 +0100 Subject: [PATCH 207/300] disable frida in the ci for the moment it is working nowhere --- .github/workflows/ci.yml | 4 ++-- frida_mode/GNUmakefile | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed1f3228..0a085b3a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,5 +54,5 @@ jobs: run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake - name: run tests run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests - - name: force frida test for MacOS - run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr + #- name: force frida test for MacOS + # run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index dda267bc..c055fcbb 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -1,3 +1,4 @@ + PWD:=$(shell pwd)/ ROOT:=$(PWD)../ INC_DIR:=$(PWD)include/ @@ -164,7 +165,7 @@ ifndef OS $(error "Operating system unsupported") endif -GUM_DEVKIT_VERSION=16.0.6 +GUM_DEVKIT_VERSION=16.0.11 GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)" From 19f96129109c6394fdc45dfae3885c2d7e08977d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 26 Mar 2023 12:14:35 +0200 Subject: [PATCH 208/300] fix frida mode --- .github/workflows/ci.yml | 4 ++-- src/afl-forkserver.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- test/test-all.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a085b3a..ed1f3228 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,5 +54,5 @@ jobs: run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake - name: run tests run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests - #- name: force frida test for MacOS - # run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr + - name: force frida test for MacOS + run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 50dc7a26..5aa4c2ff 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -59,7 +59,7 @@ static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { - if (fsrv->qemu_mode || fsrv->frida_mode || fsrv->cs_mode) { + if (fsrv->qemu_mode || fsrv->cs_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 229aef09..3e6432ca 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -33,7 +33,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (fsrv->qemu_mode || fsrv->frida_mode || fsrv->cs_mode) { + if (fsrv->qemu_mode || fsrv->cs_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); diff --git a/test/test-all.sh b/test/test-all.sh index c0bd1b63..3cb692ca 100755 --- a/test/test-all.sh +++ b/test/test-all.sh @@ -14,7 +14,7 @@ . ./test-qemu-mode.sh -#. ./test-frida-mode.sh +. ./test-frida-mode.sh . ./test-unicorn-mode.sh From 2d3c5cc6d88c98af4bf5ecb57716d3c74bbf4c76 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Sun, 26 Mar 2023 20:44:57 -0400 Subject: [PATCH 209/300] Clarify confusing version message When running, the following gets printed in quick succession on startup: afl-fuzz++4.00c based on afl by Michal Zalewski and a large online community [...] [+] NOTE: This is v3.x which changes defaults and behaviours - see README.md Don't assert that this is v3, just that v3+ changes defaults and behaviours. --- src/afl-fuzz.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index d7708fdf..4e7679de 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1344,8 +1344,7 @@ int main(int argc, char **argv_orig, char **envp) { "Eißfeldt, Andrea Fioraldi and Dominik Maier"); OKF("afl++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); - OKF("NOTE: This is v3.x which changes defaults and behaviours - see " - "README.md"); + OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md"); #ifdef __linux__ if (afl->fsrv.nyx_mode) { From b1bfc1ae76bacbf48b81c81480a9f32e0c8919f6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 27 Mar 2023 17:51:53 +0200 Subject: [PATCH 210/300] time_wo_finds in fuzzer_stats --- docs/Changelog.md | 1 + docs/afl-fuzz_approach.md | 1 + include/afl-fuzz.h | 1 + src/afl-fuzz-queue.c | 19 ++++++++++++++++++- src/afl-fuzz-stats.c | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 25c1f6bc..3c06a785 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,6 +8,7 @@ - ensure temporary file descriptor is closed when not used - added `AFL_NO_WARN_INSTABILITY` - added `AFL_FRIDA_STATS_INTERVAL` + - added time_wo_finds to fuzzer_stats - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) diff --git a/docs/afl-fuzz_approach.md b/docs/afl-fuzz_approach.md index 6af39769..cb173f10 100644 --- a/docs/afl-fuzz_approach.md +++ b/docs/afl-fuzz_approach.md @@ -483,6 +483,7 @@ directory. This includes: - `fuzzer_pid` - PID of the fuzzer process - `cycles_done` - queue cycles completed so far - `cycles_wo_finds` - number of cycles without any new paths found +- `time_wo_finds` - longest time in seconds no new path was found - `execs_done` - number of execve() calls attempted - `execs_per_sec` - overall number of execs per second - `corpus_count` - total number of entries in the queue diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 6a8e8b5d..58d02af5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -591,6 +591,7 @@ typedef struct afl_state { last_find_time, /* Time for most recent path (ms) */ last_crash_time, /* Time for most recent crash (ms) */ last_hang_time, /* Time for most recent hang (ms) */ + longest_find_time, /* Longest time taken for a find */ exit_on_time, /* Delay to exit if no new paths */ sync_time; /* Sync time (ms) */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4eb55bb3..40184645 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -577,7 +577,24 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { queue_buf[afl->queued_items - 1] = q; q->id = afl->queued_items - 1; - afl->last_find_time = get_cur_time(); + u64 cur_time = get_cur_time(); + + if (likely(afl->start_time) && + unlikely(afl->longest_find_time < cur_time - afl->last_find_time)) { + + if (unlikely(!afl->last_find_time)) { + + afl->longest_find_time = cur_time - afl->start_time; + + } else { + + afl->longest_find_time = cur_time - afl->last_find_time; + + } + + } + + afl->last_find_time = cur_time; if (afl->custom_mutators_count) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index f53fd610..25ebe987 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -251,6 +251,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "fuzzer_pid : %u\n" "cycles_done : %llu\n" "cycles_wo_finds : %llu\n" + "time_wo_finds : %llu\n" "execs_done : %llu\n" "execs_per_sec : %0.02f\n" "execs_ps_last_min : %0.02f\n" @@ -291,6 +292,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, (afl->prev_run_time + cur_time - afl->start_time) / 1000, (u32)getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, + afl->longest_find_time > cur_time - afl->last_find_time + ? afl->longest_find_time / 1000 + : ((afl->start_time == 0 || afl->last_find_time == 0) + ? 0 + : (cur_time - afl->last_find_time) / 1000), afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(afl->prev_run_time + get_cur_time() - afl->start_time) / From 01236f47bcdf87e9c59d06f1ca3727711b5251b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Mar 2023 16:50:05 +0200 Subject: [PATCH 211/300] nits --- Dockerfile | 7 ++++++- src/afl-fuzz-one.c | 2 +- test/test-basic.sh | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 59ce8778..010d629b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,6 +59,9 @@ RUN apt-get update && \ # gcc-multilib is only used for -m32 support on x86 # libcapstone-dev is used for coresight_mode on arm64 +RUN apt-get install -y --no-install-recommends \ + wget software-properties-common gnupg + RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \ @@ -67,6 +70,8 @@ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 RUN wget -qO- https://sh.rustup.rs | CARGO_HOME=/etc/cargo sh -s -- -y -q --no-modify-path ENV PATH=$PATH:/etc/cargo/bin +RUN apt clean -y + ENV LLVM_CONFIG=llvm-config-${LLVM_VERSION} ENV AFL_SKIP_CPUFREQ=1 ENV AFL_TRY_AFFINITY=1 @@ -92,4 +97,4 @@ RUN sed -i.bak 's/^ -/ /g' GNUmakefile && \ RUN echo "set encoding=utf-8" > /root/.vimrc && \ echo ". /etc/bash_completion" >> ~/.bashrc && \ echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc && \ - echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc + echo "export PS1='"'[afl++ \h] \w \$ '"'" >> ~/.bashrc diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index be526dbd..070669c5 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2084,7 +2084,7 @@ havoc_stage: } - if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } + if (unlikely(afl->stage_max < HAVOC_MIN)) { afl->stage_max = HAVOC_MIN; } temp_len = len; diff --git a/test/test-basic.sh b/test/test-basic.sh index 53de8c64..5bb2ca28 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -133,7 +133,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc SKIP= test -e ../${AFL_CLANG} -a -e ../afl-showmap -a -e ../afl-fuzz && { ../${AFL_CLANG} -v 2>&1 | grep -qi "clang version" && { - ../${AFL_CLANG} -o test-instr.plain -O0 ../test-instr.c > /dev/null 2>&1 + ../${AFL_CLANG} -O0 -o test-instr.plain ../test-instr.c > /dev/null 2>&1 AFL_HARDEN=1 ../${AFL_CLANG} -o test-compcov.harden test-compcov.c > /dev/null 2>&1 test -e test-instr.plain && { $ECHO "$GREEN[+] ${AFL_CLANG} compilation succeeded" From c594a58583c16301606e79a536f04ea3c8263e56 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Tue, 28 Mar 2023 12:01:30 -0300 Subject: [PATCH 212/300] Stop using removed pipeline extensions LLVM commit 7ae6838defb21737963b1dd8ff9de7e87052c74f removed the following extensions: - PassManagerBuilder::EP_OptimizerLast - PassManagerBuilder::EP_EnabledOnOptLevel0 - PassManagerBuilder::EP_FullLinkTimeOptimizationLast --- instrumentation/SanitizerCoverageLTO.so.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index f82224ed..85f13c19 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1787,14 +1787,16 @@ static void registerLTOPass(const PassManagerBuilder &, } +#if LLVM_VERSION_MAJOR < 16 static RegisterStandardPasses RegisterCompTransPass( PassManagerBuilder::EP_OptimizerLast, registerLTOPass); static RegisterStandardPasses RegisterCompTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerLTOPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCompTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerLTOPass); + #endif #endif From 5d9c1bc3a39900724ed1bc08e500052f44043032 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Tue, 28 Mar 2023 12:06:23 -0300 Subject: [PATCH 213/300] [afs-as] Allow debugging arguments after the input file Clang may call as with extra debugging arguments after the input file, e.g. as --64 -o /tmp/hello-617ff5.o /tmp/hello-6b6f52.s -g -gdwarf-4 --- src/afl-as.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/afl-as.c b/src/afl-as.c index a0eb612f..772e31b3 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -93,7 +93,7 @@ static u8 use_64bit = 0; static void edit_params(int argc, char **argv) { u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); - u32 i; + u32 i, input_index; #ifdef __APPLE__ @@ -142,7 +142,23 @@ static void edit_params(int argc, char **argv) { as_params[argc] = 0; - for (i = 1; (s32)i < argc - 1; i++) { + /* Find the input file. It's usually located near the end. + Assume there won't be any arguments referring to files after the input + file, e.g. as input.s -o output.o */ + for (input_index = argc - 1; input_index > 0; input_index--) { + + input_file = argv[input_index]; + /* Clang may add debug arguments after the input file. */ + if (strncmp(input_file, "-g", 2)) break; + + } + + if (input_index == 0) + FATAL("Could not find input file (not called through afl-gcc?)"); + + for (i = 1; (s32)i < argc; i++) { + + if (i == input_index) continue; if (!strcmp(argv[i], "--64")) { @@ -194,8 +210,6 @@ static void edit_params(int argc, char **argv) { #endif /* __APPLE__ */ - input_file = argv[argc - 1]; - if (input_file[0] == '-') { if (!strcmp(input_file + 1, "-version")) { From 67e8c4f100903bf8111435f0ce574806d961cbad Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Tue, 28 Mar 2023 12:10:24 -0300 Subject: [PATCH 214/300] Fix unsupported operands in .custom-format.py Python 3.11 complains that int and str are unsupported operand types for operator +. --- .custom-format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.custom-format.py b/.custom-format.py index d07c26df..1295ce55 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -40,7 +40,7 @@ def check_clang_format_pip_version(): if importlib.util.find_spec('clang_format'): # Check if the installed version is the expected LLVM version if importlib.metadata.version('clang-format')\ - .startswith(CURRENT_LLVM+'.'): + .startswith(str(CURRENT_LLVM)+'.'): return True else: # Return False, because the clang-format version does not match From 214e24fff0e44704007e71dee8384f6382770381 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 28 Mar 2023 17:23:07 +0200 Subject: [PATCH 215/300] fix arm64 build --- Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 010d629b..4e53de40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,9 +59,6 @@ RUN apt-get update && \ # gcc-multilib is only used for -m32 support on x86 # libcapstone-dev is used for coresight_mode on arm64 -RUN apt-get install -y --no-install-recommends \ - wget software-properties-common gnupg - RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \ From 48816417eedd98c2afc270678a3996e9ffd77dd7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 29 Mar 2023 10:13:11 +0200 Subject: [PATCH 216/300] introspection --- src/afl-fuzz.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 4e7679de..3380fd90 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2496,10 +2496,22 @@ int main(int argc, char **argv_orig, char **envp) { } #ifdef INTROSPECTION - fprintf(afl->introspection_file, - "CYCLE cycle=%llu cycle_wo_finds=%llu expand_havoc=%u queue=%u\n", - afl->queue_cycle, afl->cycles_wo_finds, afl->expand_havoc, - afl->queued_items); + { + + u64 cur_time = get_cur_time(); + fprintf(afl->introspection_file, + "CYCLE cycle=%llu cycle_wo_finds=%llu time_wo_finds=%llu " + "expand_havoc=%u queue=%u\n", + afl->queue_cycle, afl->cycles_wo_finds, + afl->longest_find_time > cur_time - afl->last_find_time + ? afl->longest_find_time / 1000 + : ((afl->start_time == 0 || afl->last_find_time == 0) + ? 0 + : (cur_time - afl->last_find_time) / 1000), + afl->expand_havoc, afl->queued_items); + + } + #endif if (afl->cycle_schedules) { From dbdf2d79f235d475eb8e085a7dbace757c9ac361 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 29 Mar 2023 10:57:57 +0200 Subject: [PATCH 217/300] magma support --- utils/aflpp_driver/GNUmakefile | 4 ++++ utils/aflpp_driver/aflpp_driver.c | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile index b973f96a..409789cb 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -20,6 +20,10 @@ endif CFLAGS := -O3 -funroll-loops -g -fPIC +ifdef MAGMA_PATCH + CFLAGS += -DMAGMA_PATCH +endif + all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index f08c9864..b92e68e9 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -58,8 +58,12 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out #include "hash.h" #endif +#ifdef MAGMA_PATCH +int __afl_sharedmem_fuzzing = 0; +#else // AFL++ shared memory fuzz cases int __afl_sharedmem_fuzzing = 1; +#endif extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; @@ -97,10 +101,10 @@ __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size); // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -int __afl_persistent_loop(unsigned int); - // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; + +int __afl_persistent_loop(unsigned int); void __afl_manual_init(); // Use this optionally defined function to output sanitizer messages even if From a061e1304da4f300699b059fe200602457661e5e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 10:18:45 +0200 Subject: [PATCH 218/300] further magma adaption --- utils/aflpp_driver/aflpp_driver.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index b92e68e9..05e23642 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -59,10 +59,10 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out #endif #ifdef MAGMA_PATCH -int __afl_sharedmem_fuzzing = 0; +int __afl_sharedmem_fuzzing = 0; #else // AFL++ shared memory fuzz cases -int __afl_sharedmem_fuzzing = 1; +int __afl_sharedmem_fuzzing = 1; #endif extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; @@ -75,8 +75,8 @@ extern unsigned int __afl_map_size; __attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -int LLVMFuzzerRunDriver(int *argc, char ***argv, - int (*callback)(const uint8_t *data, size_t size)); +__attribute__((weak)) int LLVMFuzzerRunDriver( + int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size)); // Default nop ASan hooks for manual poisoning when not linking the ASan // runtime @@ -99,13 +99,15 @@ __attribute__((weak)) void __asan_unpoison_memory_region( __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size); +#ifndef MAGMA_PATCH // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; +#endif -int __afl_persistent_loop(unsigned int); -void __afl_manual_init(); +int __afl_persistent_loop(unsigned int); +void __afl_manual_init(); // Use this optionally defined function to output sanitizer messages even if // user asks to close stderr. @@ -200,7 +202,8 @@ static void maybe_close_fd_mask() { // Define LLVMFuzzerMutate to avoid link failures for targets that use it // with libFuzzer's LLVMFuzzerCustomMutator. -size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { +__attribute__((weak)) size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, + size_t MaxSize) { // assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); return 0; @@ -284,8 +287,9 @@ __attribute__((weak)) int main(int argc, char **argv) { } -int LLVMFuzzerRunDriver(int *argcp, char ***argvp, - int (*callback)(const uint8_t *data, size_t size)) { +__attribute__((weak)) int LLVMFuzzerRunDriver( + int *argcp, char ***argvp, + int (*callback)(const uint8_t *data, size_t size)) { int argc = *argcp; char **argv = *argvp; From 2d0d1e267eac4723c24997116c959472aae7027f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 30 Mar 2023 14:07:33 +0200 Subject: [PATCH 219/300] better aflpp driver --- utils/aflpp_driver/aflpp_driver.c | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 05e23642..5fef4730 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -1,12 +1,14 @@ -//===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===// -//===----------------------------------------------------------------------===// +// +// afl_driver.cpp - a glue between AFL++ and libFuzzer +// /* This file allows to fuzz libFuzzer-style target functions (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing. Usage: -################################################################################ -cat << EOF > test_fuzzer.cc + +# Example target: +$ cat << EOF > test_fuzzer.cc #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { @@ -20,16 +22,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } EOF -# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. -clang -c aflpp_driver.c -# Build afl-compiler-rt.o.c from the AFL distribution. -clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c -# Build this file, link it with afl-compiler-rt.o.o and the target code. -afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o + +# Build your target with afl-cc -fsanitize=fuzzer +$ afl-c++ -fsanitize=fuzzer -o test_fuzzer test_fuzzer.cc # Run AFL: -rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; -$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out -################################################################################ +$ rm -rf in out; mkdir in out; echo z > in/foo; +$ afl-fuzz -i in -o out -- ./test_fuzzer + */ #include @@ -58,12 +57,8 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out #include "hash.h" #endif -#ifdef MAGMA_PATCH -int __afl_sharedmem_fuzzing = 0; -#else // AFL++ shared memory fuzz cases -int __afl_sharedmem_fuzzing = 1; -#endif +int __afl_sharedmem_fuzzing = 1; extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; @@ -99,15 +94,13 @@ __attribute__((weak)) void __asan_unpoison_memory_region( __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size); -#ifndef MAGMA_PATCH // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; +int __afl_persistent_loop(unsigned int); + // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -#endif - -int __afl_persistent_loop(unsigned int); -void __afl_manual_init(); +void __afl_manual_init(); // Use this optionally defined function to output sanitizer messages even if // user asks to close stderr. From be96253f5293a0446aae8b2f1795119456c0d5d5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 31 Mar 2023 11:02:27 +0200 Subject: [PATCH 220/300] nits --- instrumentation/SanitizerCoverageLTO.so.cc | 2 ++ instrumentation/afl-compiler-rt.o.c | 11 ++++++----- src/afl-fuzz-bitmap.c | 10 +++++++--- src/afl-fuzz-one.c | 6 +++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 85f13c19..9691f17f 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -431,6 +431,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( if ((afl_global_id = atoi(ptr)) < 0) FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is negative\n", ptr); + if (afl_global_id < 4) { afl_global_id = 4; } + if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { dFile.open(ptr, std::ofstream::out | std::ofstream::app); diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index a88396d4..26fc7256 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1536,7 +1536,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } - if (start == stop || *start) return; + if (start == stop || *start) { return; } x = getenv("AFL_INST_RATIO"); if (x) { @@ -1563,12 +1563,13 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { "[-] FATAL: forkserver is already up, but an instrumented dlopen() " "library loaded afterwards. You must AFL_PRELOAD such libraries to " "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n" - "To ignore this set AFL_IGNORE_PROBLEMS=1.\n"); + "To ignore this set AFL_IGNORE_PROBLEMS=1 but this will be bad for " + "coverage.\n"); abort(); } else { - static u32 offset = 4; + static u32 offset = 5; while (start < stop) { @@ -1582,7 +1583,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } - if (unlikely(++offset >= __afl_final_loc)) { offset = 4; } + if (unlikely(++offset >= __afl_final_loc)) { offset = 5; } } @@ -1596,7 +1597,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { to avoid duplicate calls (which can happen as an artifact of the underlying implementation in LLVM). */ - if (__afl_final_loc < 3) __afl_final_loc = 3; // we skip the first 4 entries + if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries *(start++) = ++__afl_final_loc; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d9c792d1..556bb5d1 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -465,7 +465,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 fn[PATH_MAX]; u8 *queue_fn = ""; - u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0; + u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0, + need_hash = 1; s32 fd; u64 cksum = 0; @@ -477,6 +478,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { classify_counts(&afl->fsrv); classified = 1; + need_hash = 0; cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -499,6 +501,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); + if (unlikely(new_bits)) { classified = 1; } + } if (likely(!new_bits)) { @@ -565,12 +569,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - if (unlikely(!classified && new_bits)) { + if (unlikely(need_hash && new_bits)) { /* due to classify counts we have to recalculate the checksum */ afl->queue_top->exec_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - classified = 1; + need_hash = 0; } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 070669c5..eec5e4b5 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2071,7 +2071,7 @@ havoc_stage: afl->stage_short = "havoc"; afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) * perf_score / afl->havoc_div) >> - 7; + 8; } else { @@ -2080,7 +2080,7 @@ havoc_stage: snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle); afl->stage_name = afl->stage_name_buf; afl->stage_short = "splice"; - afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7; + afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8; } @@ -4640,7 +4640,7 @@ pacemaker_fuzzing: MOpt_globals.splice_stageformat, splice_cycle); afl->stage_name = afl->stage_name_buf; afl->stage_short = MOpt_globals.splice_stagenameshort; - afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7; + afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8; } From 4d02d8e43dd9b413ed819e27bb012e16022d85f6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Apr 2023 11:52:36 +0200 Subject: [PATCH 221/300] fix buffer overflow in pizza mode :( --- src/afl-fuzz-stats.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 25ebe987..88844322 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -753,20 +753,20 @@ void show_stats_normal(afl_state_t *afl) { #ifdef __linux__ if (afl->fsrv.nyx_mode) { - sprintf(banner + banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", - si, afl->use_banner, afl->power_name); + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); } else { #endif - sprintf(banner + banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", - si, afl->use_banner, afl->power_name); + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); #ifdef __linux__ @@ -1557,20 +1557,22 @@ void show_stats_pizza(afl_state_t *afl) { #ifdef __linux__ if (afl->fsrv.nyx_mode) { - sprintf(banner + banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", - afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system" - : cYEL "Mozzarbella Pizzeria management system", - si, afl->use_banner, afl->power_name); + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", + afl->crash_mode ? cPIN + "Mozzarbella Pizzeria table booking system" + : cYEL "Mozzarbella Pizzeria management system", + si, afl->use_banner, afl->power_name); } else { #endif - sprintf(banner + banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system" - : cYEL "Mozzarbella Pizzeria management system", - si, afl->use_banner, afl->power_name); + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN + "Mozzarbella Pizzeria table booking system" + : cYEL "Mozzarbella Pizzeria management system", + si, afl->use_banner, afl->power_name); #ifdef __linux__ From e46e0bce44f0799731f5e7724ba3dfacafd4c41a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Apr 2023 12:03:45 +0200 Subject: [PATCH 222/300] allow pizza mode to be disabled --- docs/Changelog.md | 3 +++ docs/env_variables.md | 2 +- include/afl-fuzz.h | 6 ++++-- src/afl-fuzz-state.c | 10 +++++++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 3c06a785..fbf50137 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,9 @@ - added `AFL_NO_WARN_INSTABILITY` - added `AFL_FRIDA_STATS_INTERVAL` - added time_wo_finds to fuzzer_stats + - fixed a crash in pizza (1st april easter egg) mode. Sorry for + everyone who was affected! + - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1 - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) diff --git a/docs/env_variables.md b/docs/env_variables.md index c9dc1bbd..a6a0ae44 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -581,7 +581,7 @@ checks or alter some of the more exotic semantics of the tool: constructors in your target, you can set `AFL_EARLY_FORKSERVER`. Note that this is not a compile time option but a runtime option :-) - - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to 0 + - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to -1 to disable although it is 1st of April. - If you need a specific interval to update fuzzer_stats file, you can diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 58d02af5..5fd393dd 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -398,8 +398,8 @@ typedef struct afl_env_vars { afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, - afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme, - afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability; + afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, + afl_no_startup_calibration, afl_no_warn_instability; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, @@ -408,6 +408,8 @@ typedef struct afl_env_vars { *afl_testcache_entries, *afl_child_kill_signal, *afl_fsrv_kill_signal, *afl_target_env, *afl_persistent_record, *afl_exit_on_time; + s32 afl_pizza_mode; + } afl_env_vars_t; struct afl_pass_stat { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index f9aa5cfe..46b67def 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -648,7 +648,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } - if (afl->afl_env.afl_pizza_mode) { afl->pizza_is_served = 1; } + if (afl->afl_env.afl_pizza_mode > 0) { + + afl->pizza_is_served = 1; + + } else if (afl->afl_env.afl_pizza_mode < 0) { + + OKF("Pizza easter egg mode is now disabled."); + + } if (issue_detected) { sleep(2); } From 319b2e8e6f64bd35c5395c8a9e5053f25875a86d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 2 Apr 2023 12:08:54 +0200 Subject: [PATCH 223/300] fix ui layout with slow targets in pizza mode --- src/afl-fuzz-stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 88844322..07157bf7 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1803,10 +1803,10 @@ void show_stats_pizza(afl_state_t *afl) { /* Show a warning about slow execution. */ - if (afl->stats_avg_exec < 100) { + if (afl->stats_avg_exec < 20) { sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec), - afl->stats_avg_exec < 20 ? "zzzz..." : "Gennarino is at it again!"); + "zzzz..."); SAYF(bV bSTOP " pizza making speed : " cLRD "%-22s ", From a01138e1c822b97cf187bfcad9938597bf3edc1e Mon Sep 17 00:00:00 2001 From: nj00001 <42004790+nj00001@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:32:52 +0800 Subject: [PATCH 224/300] fix getOperand out of range This commit fixes a sloppy function call that should normally check the number of insn's Operand before calling insn's getOperand method. The fix is that if it is 0 it should continue the loop. I solved problem https://github.com/AFLplusplus/AFLplusplus/issues/1688#issue-1648543691 using this modification --- instrumentation/afl-llvm-common.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index dc34d191..de334fb7 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -289,6 +289,9 @@ void scanForDangerousFunctions(llvm::Module *M) { StringRef ifunc_name = IF.getName(); Constant *r = IF.getResolver(); + if(r->getNumOperands() == 0){ + continue ; + } StringRef r_name = cast(r->getOperand(0))->getName(); if (!be_quiet) fprintf(stderr, From 36127fb1970746f53fec44f9394061f57a4e94c3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 12:59:20 +0200 Subject: [PATCH 225/300] add -z switch --- docs/Changelog.md | 1 + include/afl-fuzz.h | 3 ++- src/afl-fuzz-queue.c | 7 ++++++- src/afl-fuzz.c | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index fbf50137..8127e594 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,6 +12,7 @@ - fixed a crash in pizza (1st april easter egg) mode. Sorry for everyone who was affected! - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1 + - add -z switch to prefer new coverage findings in seed selection - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 5fd393dd..7ff3315b 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -501,7 +501,8 @@ typedef struct afl_state { custom_splice_optout, /* Custom mutator no splice buffer */ is_main_node, /* if this is the main node */ is_secondary_node, /* if this is a secondary instance */ - pizza_is_served; /* pizza mode */ + pizza_is_served, /* pizza mode */ + prefer_new; /* prefer new queue entries */ u32 stats_update_freq; /* Stats update frequency (execs) */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 40184645..1cdc8b54 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -74,9 +74,14 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); } weight *= (log(q->bitmap_size) / avg_bitmap_size); weight *= (1 + (q->tc_ref / avg_top_size)); - if (unlikely(weight < 1.0)) { weight = 1.0; } + if (unlikely(weight < 0.1)) { weight = 0.1; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } + if (unlikely(afl->prefer_new)) { + + weight *= (2.0 * (q->id / (afl->queued_items - 1))); + + } return weight; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3380fd90..0f01360e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -132,6 +132,7 @@ static void usage(u8 *argv0, int more_help) { " fast(default), explore, exploit, seek, rare, mmopt, " "coe, lin\n" " quad -- see docs/FAQ.md for more information\n" + " -z - prefer new coverage findings when fuzzing\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" " -t msec - timeout for each run (auto-scaled, default %u ms). " @@ -569,6 +570,10 @@ int main(int argc, char **argv_orig, char **envp) { afl->max_length = atoi(optarg); break; + case 'z': + afl->prefer_new = 1; + break; + case 'Z': afl->old_seed_selection = 1; break; From dba93705a79fb859ce0ede606f79dd4ed203725b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 13:07:22 +0200 Subject: [PATCH 226/300] better new weighting --- src/afl-fuzz-queue.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 1cdc8b54..3335e869 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -74,14 +74,16 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); } weight *= (log(q->bitmap_size) / avg_bitmap_size); weight *= (1 + (q->tc_ref / avg_top_size)); + + if (unlikely(afl->prefer_new)) { + + weight *= (2.0 * ((1 + q->id) / afl->queued_items)); + + } + if (unlikely(weight < 0.1)) { weight = 0.1; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } - if (unlikely(afl->prefer_new)) { - - weight *= (2.0 * (q->id / (afl->queued_items - 1))); - - } return weight; From d67ee1777859b55b1660cef15fc09219fb165140 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Apr 2023 13:30:06 +0200 Subject: [PATCH 227/300] fix --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0f01360e..c7eb985c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -557,7 +557,7 @@ int main(int argc, char **argv_orig, char **envp) { while ( (opt = getopt( argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YzZ")) > 0) { switch (opt) { From f9851dbfbbfbc013172f500099b5f4dc572c508b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 8 Apr 2023 13:00:57 +0200 Subject: [PATCH 228/300] hopefully better -z algorithm --- src/afl-fuzz-queue.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 3335e869..6fc3c743 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -75,12 +75,6 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q, weight *= (log(q->bitmap_size) / avg_bitmap_size); weight *= (1 + (q->tc_ref / avg_top_size)); - if (unlikely(afl->prefer_new)) { - - weight *= (2.0 * ((1 + q->id) / afl->queued_items)); - - } - if (unlikely(weight < 0.1)) { weight = 0.1; } if (unlikely(q->favored)) { weight *= 5; } if (unlikely(!q->was_fuzzed)) { weight *= 2; } @@ -155,6 +149,26 @@ void create_alias_table(afl_state_t *afl) { } + if (unlikely(afl->prefer_new) && afl->queued_discovered) { + + double avg_weight = sum / active; + + for (i = n - afl->queued_discovered; i < n; i++) { + + struct queue_entry *q = afl->queue_buf[i]; + + if (likely(!q->disabled) && q->weight > avg_weight) { + + double prev_weight = q->weight; + q->weight *= (2.0 * (i / n)); + sum += (q->weight - prev_weight); + + } + + } + + } + for (i = 0; i < n; i++) { // weight is always 0 for disabled entries From 75d7a094691550afe86519a1d669def0d698b5ce Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 8 Apr 2023 13:48:07 +0200 Subject: [PATCH 229/300] show custom mutator name in UI --- docs/Changelog.md | 1 + src/afl-fuzz-mutators.c | 16 ++++++++++++---- src/afl-fuzz-one.c | 1 + src/afl-fuzz-python.c | 13 ++++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 8127e594..40c328ec 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ everyone who was affected! - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1 - add -z switch to prefer new coverage findings in seed selection + - print name of custom mutator in UI - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 support (thanks to @devnexen!) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 9ea46e7a..64dbe7c6 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -179,11 +179,19 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) { void *dh; struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator)); - mutator->name = fn; - if (memchr(fn, '/', strlen(fn))) - mutator->name_short = strrchr(fn, '/') + 1; - else + if (memchr(fn, '/', strlen(fn))) { + + mutator->name_short = strdup(strrchr(fn, '/') + 1); + + } else { + mutator->name_short = strdup(fn); + + } + + if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; } + + mutator->name = fn; ACTF("Loading custom mutator library from '%s'...", fn); dh = dlopen(fn, RTLD_NOW); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index eec5e4b5..ee562f96 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1931,6 +1931,7 @@ custom_mutator_stage: if (el->afl_custom_fuzz) { afl->current_custom_fuzz = el; + afl->stage_name = el->name_short; if (el->afl_custom_fuzz_count) { diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 2799268b..673e5a6c 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -414,10 +414,21 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, struct custom_mutator *mutator; mutator = ck_alloc(sizeof(struct custom_mutator)); - mutator->name = module_name; ACTF("Loading Python mutator library from '%s'...", module_name); + if (memchr(module_name, '/', strlen(module_name))) { + + mutator->name_short = strdup(strrchr(module_name, '/') + 1); + + } else { + + mutator->name_short = strdup(module_name); + + } + + if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; } + py_mutator_t *py_mutator; py_mutator = init_py_module(afl, module_name); mutator->data = py_mutator; From 35151cefe8e96451da9a6a25cae2181178ef53d6 Mon Sep 17 00:00:00 2001 From: Hardik Shah Date: Sat, 8 Apr 2023 17:57:08 +0530 Subject: [PATCH 230/300] display instance name --- afl-whatsup | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/afl-whatsup b/afl-whatsup index 5546523a..2f5c9675 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -141,7 +141,8 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP" . "$TMP" - + DIR=$(dirname "$i") + DIR=${DIR##*/} RUN_UNIX=$run_time RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24)) RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24)) @@ -154,7 +155,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do if [ "$SUMMARY_ONLY" = "" ]; then - echo ">>> $afl_banner ($RUN_DAYS days, $RUN_HRS hrs) fuzzer PID: $fuzzer_pid <<<" + echo ">>> $afl_banner instance: $DIR ($RUN_DAYS days, $RUN_HRS hrs) fuzzer PID: $fuzzer_pid <<<" echo fi From c1af004451e2732b855aafb567fccbd615b5214e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 8 Apr 2023 15:29:43 +0200 Subject: [PATCH 231/300] afl-whatsup tput --- afl-whatsup | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/afl-whatsup b/afl-whatsup index 2f5c9675..cec1ae28 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -70,10 +70,10 @@ if [ -d queue ]; then fi -RED=`tput setaf 9 1 1` -GREEN=`tput setaf 2 1 1` -BLUE=`tput setaf 4 1 1` -YELLOW=`tput setaf 11 1 1` +RED=`tput setaf 9 1 1 2>/dev/null` +GREEN=`tput setaf 2 1 1 2>/dev/null` +BLUE=`tput setaf 4 1 1 2>/dev/null` +YELLOW=`tput setaf 11 1 1 2>/dev/null` NC=`tput sgr0` RESET="$NC" From 0eace0212e35e9ed6ba5d084f787402406fa440c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Sat, 8 Apr 2023 17:19:09 +0200 Subject: [PATCH 232/300] afl-cc: Avoid casts of string literals to char*, in definition of __AFL_INIT() etc. With the right -W options, compilers may complain about the cast of string literals (for PERSIST_SIG and DEFER_SIG) to (char*), and they're right to do so, because string literals are constant. Since some projects enable -Werror, this can lead to a broken build with afl-cc. Let's simply cast to (const char *), which preserves the constness of the string literal. --- src/afl-cc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index 7b059d40..35b90a5c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1171,8 +1171,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" - "({ static volatile char *_B __attribute__((used,unused)); " - " _B = (char*)\"" PERSIST_SIG + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG "\"; " "extern int __afl_connected;" #ifdef __APPLE__ @@ -1187,8 +1187,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-D__AFL_INIT()=" - "do { static volatile char *_A __attribute__((used,unused)); " - " _A = (char*)\"" DEFER_SIG + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG "\"; " #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " From 0782ed38414bed37168feafc971fd102b8294510 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Apr 2023 10:33:39 +0200 Subject: [PATCH 233/300] remove pointer to removed doc --- src/afl-fuzz.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c7eb985c..a0c322da 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -166,7 +166,6 @@ static void usage(u8 *argv0, int more_help) { " pacemaker mode (minutes of no new finds). 0 = " "immediately,\n" " -1 = immediately and together with normal mutation.\n" - " See docs/README.MOpt.md\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" " if using QEMU/FRIDA or the fuzzing target is " From a0818c4fceff67e2cff986432c98e3ac1211bdd8 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 10 Apr 2023 12:38:26 +0100 Subject: [PATCH 234/300] LLVM instrumentation disable build warning. Since clang 16 is the version for Ubuntu 23 04/Fedora 38 and is easy enough to fix.. --- instrumentation/SanitizerCoverageLTO.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 9691f17f..b024179a 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1781,6 +1781,7 @@ INITIALIZE_PASS_END(ModuleSanitizerCoverageLTOLegacyPass, "sancov-lto", "Pass for instrumenting coverage on functions", false, false) +#if LLVM_VERSION_MAJOR < 16 static void registerLTOPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1789,7 +1790,6 @@ static void registerLTOPass(const PassManagerBuilder &, } -#if LLVM_VERSION_MAJOR < 16 static RegisterStandardPasses RegisterCompTransPass( PassManagerBuilder::EP_OptimizerLast, registerLTOPass); From 9e3e1a5512acd44020430f24c9ec1260aeeda285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Mon, 10 Apr 2023 12:22:42 +0200 Subject: [PATCH 235/300] afl-cc: Don't offer __AFL_INIT() etc. in GCC/CLANG modes instrumentation/README.persistent_mode.md documents in the section about deferred forkserver initialization: > With the location selected, add this code in the appropriate spot: > > ```c > #ifdef __AFL_HAVE_MANUAL_CONTROL > __AFL_INIT(); > #endif > ``` > > You don't need the #ifdef guards, but including them ensures that the program > will keep working normally when compiled with a tool other than afl-clang-fast/ > afl-clang-lto/afl-gcc-fast. > > Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast > (afl-gcc or afl-clang will *not* generate a deferred-initialization binary) - > and you should be all set! This strongly implies that you can compile a program that uses __AFL_INIT() under an `#ifdef __AFL_HAVE_MANUAL_CONTROL` guard with afl-gcc/-clang. However, this currently fails: $ cat example.c #include int main(void) { #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif puts("Hello"); } $ afl-gcc example.c -o example afl-cc++4.06a by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: GCC-GCC [!] WARNING: You are using outdated instrumentation, install LLVM and/or gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast instead! afl-as++4.06a by Michal Zalewski [+] Instrumented 1 locations (64-bit, non-hardened mode, ratio 100%). /usr/bin/ld: /tmp/ccuJHcpt.o: in function `main': /home/jn/dev/fuzz/AFLplusplus/example.c:5: undefined reference to `__afl_manual_init' collect2: error: ld returned 1 exit status The issue here is an inconsistency in afl-gcc (i.e. afl-cc operating in GCC mode): - afl-cc defines __AFL_HAVE_MANUAL_CONTROL and __AFL_INIT unconditionally - __AFL_INIT relies on __afl_manual_init, which is defined in afl-compiler-rt.o - afl-cc doesn't link afl-compiler-rt in GCC or CLANG mode Since afl-gcc/-clang is documented as not supporting deferred forkserver initialization, this patch omits the definitions of __AFL_HAVE_MANUAL_CONTROL and related macros in GCC/CLANG mode. This restores the ability to compile a deferred-forkserver program under afl-gcc, if it can also be compiled under gcc. [ In case someone reads this an feels adventurous enough (as I did) to think about enabling deferred forkserver under afl-gcc: Whether the deferred forkserver actually works can be verified by placing a usleep(100000) or similar at the start of main (before __AFL_INIT()), and watching the execution speed. It doesn't work. ] --- src/afl-cc.c | 108 ++++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index 35b90a5c..7f15ad76 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1101,37 +1101,45 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; #endif - cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; - /* When the user tries to use persistent or deferred forkserver modes by - appending a single line to the program, we want to reliably inject a - signature into the binary (to be picked up by afl-fuzz) and we want - to call a function from the runtime .o file. This is unnecessarily - painful for three reasons: + /* As documented in instrumentation/README.persistent_mode.md, deferred + forkserver initialization and persistent mode are not available in afl-gcc + and afl-clang. */ + if (compiler_mode != GCC && compiler_mode != CLANG) { - 1) We need to convince the compiler not to optimize out the signature. - This is done with __attribute__((used)). + cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; - 2) We need to convince the linker, when called with -Wl,--gc-sections, - not to do the same. This is done by forcing an assignment to a - 'volatile' pointer. + /* When the user tries to use persistent or deferred forkserver modes by + appending a single line to the program, we want to reliably inject a + signature into the binary (to be picked up by afl-fuzz) and we want + to call a function from the runtime .o file. This is unnecessarily + painful for three reasons: - 3) We need to declare __afl_persistent_loop() in the global namespace, - but doing this within a method in a class is hard - :: and extern "C" - are forbidden and __attribute__((alias(...))) doesn't work. Hence the - __asm__ aliasing trick. + 1) We need to convince the compiler not to optimize out the signature. + This is done with __attribute__((used)). - */ + 2) We need to convince the linker, when called with -Wl,--gc-sections, + not to do the same. This is done by forcing an assignment to a + 'volatile' pointer. - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_INIT()=" - "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" - "unsigned char __afl_fuzz_alt[1048576];" - "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; + 3) We need to declare __afl_persistent_loop() in the global namespace, + but doing this within a method in a class is hard - :: and extern "C" + are forbidden and __attribute__((alias(...))) doesn't work. Hence the + __asm__ aliasing trick. + + */ + + cc_params[cc_par_cnt++] = + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int *__afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;" + "unsigned char __afl_fuzz_alt[1048576];" + "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; + + } if (plusplus_mode) { @@ -1169,35 +1177,39 @@ static void edit_params(u32 argc, char **argv, char **envp) { "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " "? 0 : *__afl_fuzz_len)"; - cc_params[cc_par_cnt++] = - "-D__AFL_LOOP(_A)=" - "({ static volatile const char *_B __attribute__((used,unused)); " - " _B = (const char*)\"" PERSIST_SIG - "\"; " - "extern int __afl_connected;" -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " -#else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " -#endif /* ^__APPLE__ */ - // if afl is connected, we run _A times, else once. - "_L(__afl_connected ? _A : 1); })"; + if (compiler_mode != GCC && compiler_mode != CLANG) { - cc_params[cc_par_cnt++] = - "-D__AFL_INIT()=" - "do { static volatile const char *_A __attribute__((used,unused)); " - " _A = (const char*)\"" DEFER_SIG - "\"; " + cc_params[cc_par_cnt++] = + "-D__AFL_LOOP(_A)=" + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG + "\"; " + "extern int __afl_connected;" #ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"___afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ - "_I(); } while (0)"; + // if afl is connected, we run _A times, else once. + "_L(__afl_connected ? _A : 1); })"; + + cc_params[cc_par_cnt++] = + "-D__AFL_INIT()=" + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG + "\"; " +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"___afl_manual_init\"); " +#else + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " +#endif /* ^__APPLE__ */ + "_I(); } while (0)"; + + } if (x_set) { From 743ae507756db0707a213cd8272b219b0de0f514 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Apr 2023 10:53:23 +0200 Subject: [PATCH 236/300] nits --- GNUmakefile | 2 +- instrumentation/afl-llvm-common.cc | 4 +--- utils/aflpp_driver/GNUmakefile | 4 ---- utils/aflpp_driver/aflpp_driver.c | 8 +++++--- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 72da14ea..208e965b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -196,7 +196,7 @@ ifeq "$(PYTHON_INCLUDE)" "" ifneq "$(shell command -v python3-config 2>/dev/null)" "" PYTHON_INCLUDE ?= $(shell python3-config --includes) PYTHON_VERSION ?= $(strip $(shell python3 --version 2>&1)) - # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag. + # Starting with python3.8, we need to pass the `embed` flag. Earlier versions didn't know this flag. ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1" PYTHON_LIB ?= $(shell python3-config --libs --embed --ldflags) else diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index de334fb7..5d82aa25 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -289,9 +289,7 @@ void scanForDangerousFunctions(llvm::Module *M) { StringRef ifunc_name = IF.getName(); Constant *r = IF.getResolver(); - if(r->getNumOperands() == 0){ - continue ; - } + if (r->getNumOperands() == 0) { continue; } StringRef r_name = cast(r->getOperand(0))->getName(); if (!be_quiet) fprintf(stderr, diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile index 409789cb..b973f96a 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -20,10 +20,6 @@ endif CFLAGS := -O3 -funroll-loops -g -fPIC -ifdef MAGMA_PATCH - CFLAGS += -DMAGMA_PATCH -endif - all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 5fef4730..ec304c8c 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -1,8 +1,10 @@ // -// afl_driver.cpp - a glue between AFL++ and libFuzzer +// afl_driver.cpp - a glue between AFL++ and LLVMFuzzerTestOneInput harnesses // -/* This file allows to fuzz libFuzzer-style target functions +/* + + This file allows to fuzz libFuzzer-style target functions (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing. Usage: @@ -26,7 +28,7 @@ EOF # Build your target with afl-cc -fsanitize=fuzzer $ afl-c++ -fsanitize=fuzzer -o test_fuzzer test_fuzzer.cc # Run AFL: -$ rm -rf in out; mkdir in out; echo z > in/foo; +$ mkdir -p in ; echo z > in/foo; $ afl-fuzz -i in -o out -- ./test_fuzzer */ From d304f4e4f190409e9b1cc6993355128673eb0c3b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Apr 2023 11:24:56 +0200 Subject: [PATCH 237/300] update lto doc --- instrumentation/README.lto.md | 126 ++++++++++++---------------------- 1 file changed, 43 insertions(+), 83 deletions(-) diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index a1c2f44a..df59cc2a 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -2,36 +2,37 @@ ## TL;DR: -This version requires a current llvm 11+ compiled from the GitHub master. +This version requires a LLVM 11 or newer. -1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better - coverage than anything else that is out there in the AFL world. +1. Use afl-clang-lto/afl-clang-lto++ because the resulting binaries run + slightly faster and give better coverage. -2. You can use it together with llvm_mode: laf-intel and the instrument file - listing features and can be combined with cmplog/Redqueen. +2. You can use it together with COMPCOV, COMPLOG and the instrument file + listing features. -3. It only works with llvm 11+. +3. It only works with LLVM 11 or newer. -4. AUTODICTIONARY feature (see below)! +4. AUTODICTIONARY feature (see below) -5. If any problems arise, be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`. Some - targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`. +5. If any problems arise, be sure to set `AR=llvm-ar RANLIB=llvm-ranlib AS=llvm-as`. + Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`. ## Introduction and problem description -A big issue with how AFL++ works is that the basic block IDs that are set during -compilation are random - and hence naturally the larger the number of -instrumented locations, the higher the number of edge collisions are in the map. -This can result in not discovering new paths and therefore degrade the +A big issue with how vanilla AFL worked was that the basic block IDs that are +set during compilation are random - and hence naturally the larger the number +of instrumented locations, the higher the number of edge collisions are in the +map. This can result in not discovering new paths and therefore degrade the efficiency of the fuzzing process. -*This issue is underestimated in the fuzzing community!* With a 2^16 = 64kb +*This issue is underestimated in the fuzzing community* With a 2^16 = 64kb standard map at already 256 instrumented blocks, there is on average one collision. On average, a target has 10.000 to 50.000 instrumented blocks, hence the real collisions are between 750-18.000! -To reach a solution that prevents any collisions took several approaches and -many dead ends until we got to this: +Note that PCGUARD (our own modified implementation and the SANCOV PCGUARD +implementation from libfuzzer) also provides collision free coverage. +It is a bit slower though and can a few targets with very early constructors. * We instrument at link time when we have all files pre-compiled. * To instrument at link time, we compile in LTO (link time optimization) mode. @@ -45,9 +46,9 @@ many dead ends until we got to this: The result: * 10-25% speed gain compared to llvm_mode -* guaranteed non-colliding edge coverage :-) +* guaranteed non-colliding edge coverage * The compile time, especially for binaries to an instrumented library, can be - much longer. + much (and sometimes much much) longer. Example build output from a libtiff build: @@ -59,71 +60,30 @@ AUTODICTIONARY: 11 strings found [+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode). ``` -## Getting llvm 11+ +## Getting LLVM 11+ -### Installing llvm version 11 or 12 +### Installing llvm -llvm 11 or even 12 should be available in all current Linux repositories. If you -use an outdated Linux distribution, read the next section. - -### Installing llvm from the llvm repository (version 12+) - -Installing the llvm snapshot builds is easy and mostly painless: - -In the following line, change `NAME` for your Debian or Ubuntu release name -(e.g., buster, focal, eon, etc.): +The best way to install LLVM is to follow [https://apt.llvm.org/](https://apt.llvm.org/) +e.g. for LLVM 15: ``` -echo deb http://apt.llvm.org/NAME/ llvm-toolchain-NAME NAME >> /etc/apt/sources.list +wget https://apt.llvm.org/llvm.sh +chmod +x llvm.sh +sudo ./llvm.sh 15 all ``` -Then add the pgp key of llvm and install the packages: +LLVM 11 to 16 should be available in all current Linux repositories. + +## How to build afl-clang-lto + +That part is easy. +Just set `LLVM_CONFIG` to the llvm-config-VERSION and build AFL++, e.g. for +LLVM 15: ``` -wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - -apt-get update && apt-get upgrade -y -apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \ - libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \ - libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \ - liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \ - libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools -``` - -### Building llvm yourself (version 12+) - -Building llvm from GitHub takes quite some time and is not painless: - -```sh -sudo apt install binutils-dev # this is *essential*! -git clone --depth=1 https://github.com/llvm/llvm-project -cd llvm-project -mkdir build -cd build - -# Add -G Ninja if ninja-build installed -# "Building with ninja significantly improves your build time, especially with -# incremental builds, and improves your memory usage." -cmake \ - -DCLANG_INCLUDE_DOCS="OFF" \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_BINUTILS_INCDIR=/usr/include/ \ - -DLLVM_BUILD_LLVM_DYLIB="ON" \ - -DLLVM_ENABLE_BINDINGS="OFF" \ - -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;libcxx;libcxxabi;libunwind;lld' \ - -DLLVM_ENABLE_WARNINGS="OFF" \ - -DLLVM_INCLUDE_BENCHMARKS="OFF" \ - -DLLVM_INCLUDE_DOCS="OFF" \ - -DLLVM_INCLUDE_EXAMPLES="OFF" \ - -DLLVM_INCLUDE_TESTS="OFF" \ - -DLLVM_LINK_LLVM_DYLIB="ON" \ - -DLLVM_TARGETS_TO_BUILD="host" \ - ../llvm/ -# NOTE: for llvm 16 this needs to be changed to: -# -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;lld' \ -# -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi' \ -cmake --build . -j4 -export LLVM_CONFIG="$(pwd)/bin/llvm-config" -cd /path/to/AFLplusplus/ +cd ~/AFLplusplus +export LLVM_CONFIG=llvm-config-15 make sudo make install ``` @@ -136,10 +96,10 @@ Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST -> [README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work. -Example: +Example (note that you might need to add the version, e.g. `llvm-ar-15`: ``` -CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar ./configure +CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure make ``` @@ -317,13 +277,13 @@ AS=llvm-as ... afl-clang-lto is still work in progress. Known issues: -* Anything that llvm 11+ cannot compile, afl-clang-lto cannot compile either - +* Anything that LLVM 11+ cannot compile, afl-clang-lto cannot compile either - obviously. * Anything that does not compile with LTO, afl-clang-lto cannot compile either - obviously. Hence, if building a target with afl-clang-lto fails, try to build it with -llvm12 and LTO enabled (`CC=clang-12`, `CXX=clang++-12`, `CFLAGS=-flto=full`, +LLVM 12 and LTO enabled (`CC=clang-12`, `CXX=clang++-12`, `CFLAGS=-flto=full`, and `CXXFLAGS=-flto=full`). If this succeeds, then there is an issue with afl-clang-lto. Please report at @@ -341,7 +301,7 @@ knows what this is doing. And the developer who implemented this didn't respond to emails.) In December then came the idea to implement this as a pass that is run via the -llvm "opt" program, which is performed via an own linker that afterwards calls +LLVM "opt" program, which is performed via an own linker that afterwards calls the real linker. This was first implemented in January and work ... kinda. The LTO time instrumentation worked, however, "how" the basic blocks were instrumented was a problem, as reducing duplicates turned out to be very, very @@ -353,13 +313,13 @@ dead-end too. The final idea to solve this came from domenukk who proposed to insert a block into an edge and then just use incremental counters ... and this worked! After some trials and errors to implement this vanhauser-thc found out that there is -actually an llvm function for this: SplitEdge() :-) +actually an LLVM function for this: SplitEdge() :-) -Still more problems came up though as this only works without bugs from llvm 9 +Still more problems came up though as this only works without bugs from LLVM 9 onwards, and with high optimization the link optimization ruins the instrumented control flow graph. -This is all now fixed with llvm 11+. The llvm's own linker is now able to load +This is all now fixed with LLVM 11+. The llvm's own linker is now able to load passes and this bypasses all problems we had. Happy end :) From 824385f52ce3133ecd033e587aa1a3b324adf76c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 12 Apr 2023 14:03:29 +0200 Subject: [PATCH 238/300] make llvm 17 work --- docs/Changelog.md | 2 +- instrumentation/SanitizerCoverageLTO.so.cc | 2 ++ instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 40c328ec..736deb30 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,7 +16,7 @@ - print name of custom mutator in UI - afl-cc: - add CFI sanitizer variant to gcc targets - - llvm 16 support (thanks to @devnexen!) + - llvm 16 + 17 support (thanks to @devnexen!) - support llvm 15 native pcguard changes - support for LLVMFuzzerTestOneInput -1 return - qemu_mode: diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index b024179a..5603c455 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -17,7 +17,9 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/Triple.h" +#endif #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index c4a564f7..5f23698b 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -13,7 +13,9 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/Triple.h" +#endif #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/CFG.h" From 6cc8d607fb24e060591ece4b42d83fc06de68fc6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 13 Apr 2023 11:44:39 +0200 Subject: [PATCH 239/300] remove -z option, use -p mmopt instead --- GNUmakefile | 2 +- docs/Changelog.md | 2 +- include/afl-fuzz.h | 3 +-- instrumentation/SanitizerCoverageLTO.so.cc | 2 +- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- src/afl-fuzz-queue.c | 14 ++++---------- src/afl-fuzz.c | 7 +------ 7 files changed, 10 insertions(+), 22 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 208e965b..85f164f5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -546,7 +546,7 @@ ifndef AFL_NO_X86 test_build: afl-cc afl-gcc afl-as afl-showmap @echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..." @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) - - ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null + -ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr @rm -f test-instr @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi diff --git a/docs/Changelog.md b/docs/Changelog.md index 736deb30..501300b1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,7 +12,7 @@ - fixed a crash in pizza (1st april easter egg) mode. Sorry for everyone who was affected! - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1 - - add -z switch to prefer new coverage findings in seed selection + - option `-p mmopt` now also selects new queue items more often - print name of custom mutator in UI - afl-cc: - add CFI sanitizer variant to gcc targets diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7ff3315b..5fd393dd 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -501,8 +501,7 @@ typedef struct afl_state { custom_splice_optout, /* Custom mutator no splice buffer */ is_main_node, /* if this is the main node */ is_secondary_node, /* if this is a secondary instance */ - pizza_is_served, /* pizza mode */ - prefer_new; /* prefer new queue entries */ + pizza_is_served; /* pizza mode */ u32 stats_update_freq; /* Stats update frequency (execs) */ diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 5603c455..e41f19b6 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -18,7 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #if LLVM_VERSION_MAJOR < 17 -#include "llvm/ADT/Triple.h" + #include "llvm/ADT/Triple.h" #endif #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 5f23698b..85b1ddd5 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -14,7 +14,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #if LLVM_VERSION_MAJOR < 17 -#include "llvm/ADT/Triple.h" + #include "llvm/ADT/Triple.h" #endif #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 6fc3c743..8ad7cd97 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -149,21 +149,15 @@ void create_alias_table(afl_state_t *afl) { } - if (unlikely(afl->prefer_new) && afl->queued_discovered) { + if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) { - double avg_weight = sum / active; + u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered; - for (i = n - afl->queued_discovered; i < n; i++) { + for (i = n - cnt; i < n; i++) { struct queue_entry *q = afl->queue_buf[i]; - if (likely(!q->disabled) && q->weight > avg_weight) { - - double prev_weight = q->weight; - q->weight *= (2.0 * (i / n)); - sum += (q->weight - prev_weight); - - } + if (likely(!q->disabled)) { q->weight *= 2.0; } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a0c322da..5ba54d0b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -132,7 +132,6 @@ static void usage(u8 *argv0, int more_help) { " fast(default), explore, exploit, seek, rare, mmopt, " "coe, lin\n" " quad -- see docs/FAQ.md for more information\n" - " -z - prefer new coverage findings when fuzzing\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" " -t msec - timeout for each run (auto-scaled, default %u ms). " @@ -556,7 +555,7 @@ int main(int argc, char **argv_orig, char **envp) { while ( (opt = getopt( argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YzZ")) > + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > 0) { switch (opt) { @@ -569,10 +568,6 @@ int main(int argc, char **argv_orig, char **envp) { afl->max_length = atoi(optarg); break; - case 'z': - afl->prefer_new = 1; - break; - case 'Z': afl->old_seed_selection = 1; break; From f756734ad2782c3ed56feadb4b7b23fc82a7a968 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 13 Apr 2023 12:07:27 +0200 Subject: [PATCH 240/300] fix attempt at post_process implementation --- docs/Changelog.md | 1 + docs/custom_mutators.md | 9 ++++++-- include/afl-fuzz.h | 9 ++++++-- src/afl-fuzz-python.c | 49 ++++++++--------------------------------- src/afl-fuzz-run.c | 7 +++++- 5 files changed, 30 insertions(+), 45 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 501300b1..9436fc9f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ everyone who was affected! - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1 - option `-p mmopt` now also selects new queue items more often + - fix bug in post_process custom mutator implementation - print name of custom mutator in UI - afl-cc: - add CFI sanitizer variant to gcc targets diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 82131c92..a1de479e 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -118,7 +118,7 @@ def deinit(): # optional for Python ### Custom Mutation -- `init`: +- `init` (optional in Python): This method is called when AFL++ starts up and is used to seed RNG and set up buffers and state. @@ -184,6 +184,11 @@ def deinit(): # optional for Python to the target, e.g. if it is too short, too corrupted, etc. If so, return a NULL buffer and zero length (or a 0 length string in Python). + NOTE: Do not make any random changes to the data in this function! + + PERFORMANCE for C/C++: If possible make the changes in-place (so modify + the `*data` directly, and return it as `*outbuf = data`. + - `fuzz_send` (optional): This method can be used if you want to send data to the target yourself, @@ -202,7 +207,7 @@ def deinit(): # optional for Python discovered if compiled with INTROSPECTION. The custom mutator can then return a string (const char *) that reports the exact mutations used. -- `deinit`: +- `deinit` (optional in Python): The last method to be called, deinitializing the state. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 5fd393dd..8b6502b4 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -885,14 +885,19 @@ struct custom_mutator { * A post-processing function to use right before AFL writes the test case to * disk in order to execute the target. * - * (Optional) If this functionality is not needed, simply don't define this + * NOTE: Do not do any random changes to the data in this function! + * + * PERFORMANCE: If you can modify the data in-place you will have a better + * performance. Modify *data and set `*out_buf = data`. + * + * (Optional) If this functionality is not needed, simply do not define this * function. * * @param[in] data pointer returned in afl_custom_init by this custom mutator * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case * @param[out] out_buf Pointer to the buffer storing the test case after - * processing. External library should allocate memory for out_buf. + * processing. The external library should allocate memory for out_buf. * It can chose to alter buf in-place, if the space is large enough. * @return Size of the output buffer. */ diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 673e5a6c..7dad0770 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -219,11 +219,14 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { if (py_module != NULL) { - u8 py_notrim = 0, py_idx; - /* init, required */ + u8 py_notrim = 0; py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init"); - if (!py_functions[PY_FUNC_INIT]) - FATAL("init function not found in python module"); + if (!py_functions[PY_FUNC_INIT]) { + + WARNF("init function not found in python module"); + + } + py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz"); if (!py_functions[PY_FUNC_FUZZ]) py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate"); @@ -231,12 +234,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "describe"); py_functions[PY_FUNC_FUZZ_COUNT] = PyObject_GetAttrString(py_module, "fuzz_count"); - if (!py_functions[PY_FUNC_FUZZ]) { - - WARNF("fuzz function not found in python module"); - - } - py_functions[PY_FUNC_POST_PROCESS] = PyObject_GetAttrString(py_module, "post_process"); py_functions[PY_FUNC_INIT_TRIM] = @@ -263,36 +260,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { if (!py_functions[PY_FUNC_DEINIT]) WARNF("deinit function not found in python module"); - for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) { - - if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) { - - if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) { - - // Implementing the trim API is optional for now - if (PyErr_Occurred()) { PyErr_Print(); } - py_notrim = 1; - - } else if (py_idx >= PY_OPTIONAL) { - - // Only _init and _deinit are not optional currently - - if (PyErr_Occurred()) { PyErr_Print(); } - - } else { - - fprintf(stderr, - "Cannot find/call function with index %d in external " - "Python module.\n", - py_idx); - return NULL; - - } - - } - - } - if (py_notrim) { py_functions[PY_FUNC_INIT_TRIM] = NULL; @@ -345,6 +312,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, (void)afl; + if (py_mutator->py_functions[PY_FUNC_INIT] == NULL) { return; } + PyObject *py_args, *py_value; /* Provide the init function a seed for the Python RNG */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index f5425011..26e8549d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -133,7 +133,12 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (new_mem != *mem) { *mem = new_mem; } + if (new_mem != *mem && new_mem != NULL && new_size > 0) { + + *mem = afl_realloc((void **)mem, new_size); + memmove(*mem, new_mem, new_size); + + } if (unlikely(afl->custom_mutators_count)) { From 2adf5aac0fcf9b9263bfe3dd93e4d860e3668ae4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 13 Apr 2023 15:32:06 +0200 Subject: [PATCH 241/300] libfuzzer driver nits --- dynamic_list.txt | 1 + utils/aflpp_driver/aflpp_driver.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/dynamic_list.txt b/dynamic_list.txt index d06eae4e..50c0c6b8 100644 --- a/dynamic_list.txt +++ b/dynamic_list.txt @@ -54,4 +54,5 @@ "__sanitizer_cov_trace_pc_guard"; "__sanitizer_cov_trace_pc_guard_init"; "__sanitizer_cov_trace_switch"; + "LLVMFuzzerTestOneInput"; }; diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index ec304c8c..19f0d9da 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -33,6 +33,11 @@ $ afl-fuzz -i in -o out -- ./test_fuzzer */ +#ifdef __cplusplus +extern "C" { + +#endif + #include #include #include @@ -260,6 +265,13 @@ static int ExecuteFilesOnyByOne(int argc, char **argv, __attribute__((weak)) int main(int argc, char **argv) { + if (!LLVMFuzzerTestOneInput) { + + fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n"); + abort(); + + } + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) printf( "============================== INFO ================================\n" @@ -409,3 +421,9 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( } +#ifdef __cplusplus + +} + +#endif + From eefd98f3741b5feca32c75b34a8d7b33e34044d0 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 02:25:33 +0200 Subject: [PATCH 242/300] add Nyx support in various tools (like afl-cmin) --- afl-cmin | 14 +++++-- include/common.h | 6 +++ include/forkserver.h | 3 ++ src/afl-analyze.c | 64 ++++++++++++++++++++++++++-- src/afl-common.c | 31 ++++++++++++++ src/afl-forkserver.c | 65 +++++++++++++++++++++++++++++ src/afl-fuzz.c | 63 ---------------------------- src/afl-showmap.c | 99 ++++++++++++++++++++++++++++++++++++++++++-- src/afl-tmin.c | 59 +++++++++++++++++++++++++- 9 files changed, 330 insertions(+), 74 deletions(-) diff --git a/afl-cmin b/afl-cmin index 15b61f89..12791584 100755 --- a/afl-cmin +++ b/afl-cmin @@ -109,6 +109,7 @@ function usage() { " -O - use binary-only instrumentation (FRIDA mode)\n" \ " -Q - use binary-only instrumentation (QEMU mode)\n" \ " -U - use unicorn-based instrumentation (unicorn mode)\n" \ +" -X - use Nyx mode\n" \ "\n" \ "Minimization settings:\n" \ " -A - allow crashes and timeouts (not recommended)\n" \ @@ -156,7 +157,7 @@ BEGIN { # process options Opterr = 1 # default is to diagnose Optind = 1 # skip ARGV[0] - while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQU?")) != -1) { + while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUX?")) != -1) { if (_go_c == "i") { if (!Optarg) usage() if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} @@ -217,6 +218,12 @@ BEGIN { extra_par = extra_par " -U" unicorn_mode = 1 continue + } else + if (_go_c == "X") { + if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} + extra_par = extra_par " -X" + nyx_mode = 1 + continue } else if (_go_c == "?") { exit 1 @@ -291,7 +298,8 @@ BEGIN { exit 1 } - if (target_bin && !exists_and_is_executable(target_bin)) { + + if (!nyx_mode && target_bin && !exists_and_is_executable(target_bin)) { "command -v "target_bin" 2>/dev/null" | getline tnew if (!tnew || !exists_and_is_executable(tnew)) { @@ -311,7 +319,7 @@ BEGIN { } } - if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) { + if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode && !nyx_mode) { if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) { print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr" exit 1 diff --git a/include/common.h b/include/common.h index 0958b035..279a5f47 100644 --- a/include/common.h +++ b/include/common.h @@ -147,5 +147,11 @@ s32 create_file(u8 *fn); void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); +#ifdef __linux__ +/* Nyx helper functions to create and remove tmp workdirs */ +char* create_nyx_tmp_workdir(void); +void remove_nyx_tmp_workdir(char* nyx_out_dir_path); +#endif + #endif diff --git a/include/forkserver.h b/include/forkserver.h index 50898a08..273a9255 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -75,6 +75,9 @@ typedef struct { } nyx_plugin_handler_t; +/* Imports helper functions to enable Nyx mode (Linux only )*/ +nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary); + #endif typedef struct afl_forkserver { diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 548956d8..0bdadfdc 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -121,9 +121,9 @@ static void kill_child() { } -static void classify_counts(u8 *mem) { +static void classify_counts(u8 *mem, u32 mem_size) { - u32 i = map_size; + u32 i = mem_size; if (edges_only) { @@ -222,7 +222,7 @@ static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) { } - classify_counts(fsrv.trace_bits); + classify_counts(fsrv.trace_bits, fsrv.map_size); total_execs++; if (stop_soon) { @@ -768,6 +768,7 @@ static void usage(u8 *argv0) { " -U - use unicorn-based instrumentation (Unicorn mode)\n" " -W - use qemu-based instrumentation with Wine (Wine " "mode)\n" + " -X - use Nyx mode\n" #endif "\n" @@ -814,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_init(&fsrv); - while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) { + while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXh")) > 0) { switch (opt) { @@ -965,6 +966,22 @@ int main(int argc, char **argv_orig, char **envp) { fsrv.mem_limit = mem_limit; break; + + #ifdef __linux__ + case 'X': /* NYX mode */ + + if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } + + fsrv.nyx_mode = 1; + fsrv.nyx_parent = true; + fsrv.nyx_standalone = true; + + break; + #else + case 'X': + FATAL("Nyx mode is only availabe on linux..."); + break; + #endif case 'h': usage(argv[0]); @@ -997,7 +1014,17 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(argv); +#ifdef __linux__ + if(!fsrv.nyx_mode){ + fsrv.target_path = find_binary(argv[optind]); + } + else{ + fsrv.target_path = ck_strdup(argv[optind]); + } +#else fsrv.target_path = find_binary(argv[optind]); +#endif + fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, fsrv.out_file, &use_stdin); signal(SIGALRM, kill_child); @@ -1020,6 +1047,23 @@ int main(int argc, char **argv_orig, char **envp) { use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind); +#ifdef __linux__ + } else if (fsrv.nyx_mode) { + + fsrv.nyx_id = 0; + + u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); + fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); + if (fsrv.nyx_handlers == NULL) { + FATAL("failed to initialize libnyx.so..."); + } + + fsrv.out_dir_path = create_nyx_tmp_workdir(); + fsrv.nyx_bind_cpu_id = 0; + + use_argv = argv + optind; +#endif + } else { use_argv = argv + optind; @@ -1045,7 +1089,13 @@ int main(int argc, char **argv_orig, char **envp) { &fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); read_initial_file(); +#ifdef __linux__ + if(!fsrv.nyx_mode){ + (void)check_binary_signatures(fsrv.target_path); + } +#else (void)check_binary_signatures(fsrv.target_path); +#endif ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); @@ -1069,6 +1119,12 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); +#ifdef __linux__ + if (fsrv.nyx_mode) { + remove_nyx_tmp_workdir(fsrv.out_dir_path); + } +#endif + afl_shm_deinit(&shm); afl_fsrv_deinit(&fsrv); if (fsrv.target_path) { ck_free(fsrv.target_path); } diff --git a/src/afl-common.c b/src/afl-common.c index 86226c9f..7dbf7129 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1359,3 +1359,34 @@ s32 create_file(u8 *fn) { } +#ifdef __linux__ + +/* Nyx requires a tmp workdir to access specific files (such as mmapped files, + * etc.). This helper function basically creates both a path to a tmp workdir + * and the workdir itself. If the environment variable TMPDIR is set, we use + * that as the base directory, otherwise we use /tmp. */ +char* create_nyx_tmp_workdir(void) { + + char *tmpdir = getenv("TMPDIR"); + + if (!tmpdir) { tmpdir = "/tmp"; } + + char* nyx_out_dir_path = alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid()); + + if (mkdir(nyx_out_dir_path, 0700)) { + PFATAL("Unable to create nyx workdir"); + } + + return nyx_out_dir_path; +} + +/* Vice versa, we remove the tmp workdir for nyx with this helper function. */ +void remove_nyx_tmp_workdir(char* nyx_out_dir_path) { + /* Fix me: This is not recursive, so it will always fail. Use a libnyx helper function instead + * to remove the workdir safely (and not risking to wipe the whole filesystem accidentally). */ + //if (rmdir(nyx_out_dir_path)) { + // PFATAL("Unable to remove nyx workdir"); + //} + free(nyx_out_dir_path); +} +#endif diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 5aa4c2ff..95328aa2 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -49,6 +49,71 @@ #include #include +#ifdef __linux__ +#include + +/* function to load nyx_helper function from libnyx.so */ + +nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { + + void *handle; + nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t)); + + ACTF("Trying to load libnyx.so plugin..."); + handle = dlopen((char *)libnyx_binary, RTLD_NOW); + if (!handle) { goto fail; } + + plugin->nyx_new = dlsym(handle, "nyx_new"); + if (plugin->nyx_new == NULL) { goto fail; } + + plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent"); + if (plugin->nyx_new_parent == NULL) { goto fail; } + + plugin->nyx_new_child = dlsym(handle, "nyx_new_child"); + if (plugin->nyx_new_child == NULL) { goto fail; } + + plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown"); + if (plugin->nyx_shutdown == NULL) { goto fail; } + + plugin->nyx_option_set_reload_mode = + dlsym(handle, "nyx_option_set_reload_mode"); + if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; } + + plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout"); + if (plugin->nyx_option_set_timeout == NULL) { goto fail; } + + plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply"); + if (plugin->nyx_option_apply == NULL) { goto fail; } + + plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input"); + if (plugin->nyx_set_afl_input == NULL) { goto fail; } + + plugin->nyx_exec = dlsym(handle, "nyx_exec"); + if (plugin->nyx_exec == NULL) { goto fail; } + + plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer"); + if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; } + + plugin->nyx_get_bitmap_buffer_size = + dlsym(handle, "nyx_get_bitmap_buffer_size"); + if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } + + plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string"); + if (plugin->nyx_get_aux_string == NULL) { goto fail; } + + OKF("libnyx plugin is ready!"); + return plugin; + +fail: + + FATAL("failed to load libnyx: %s\n", dlerror()); + free(plugin); + return NULL; + +} + +#endif + /** * The correct fds for reading and writing pipes */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a0c322da..8b4fe1e5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -436,69 +436,6 @@ static void fasan_check_afl_preload(char *afl_preload) { } - #ifdef __linux__ - #include - -nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { - - void *handle; - nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t)); - - ACTF("Trying to load libnyx.so plugin..."); - handle = dlopen((char *)libnyx_binary, RTLD_NOW); - if (!handle) { goto fail; } - - plugin->nyx_new = dlsym(handle, "nyx_new"); - if (plugin->nyx_new == NULL) { goto fail; } - - plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent"); - if (plugin->nyx_new_parent == NULL) { goto fail; } - - plugin->nyx_new_child = dlsym(handle, "nyx_new_child"); - if (plugin->nyx_new_child == NULL) { goto fail; } - - plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown"); - if (plugin->nyx_shutdown == NULL) { goto fail; } - - plugin->nyx_option_set_reload_mode = - dlsym(handle, "nyx_option_set_reload_mode"); - if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; } - - plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout"); - if (plugin->nyx_option_set_timeout == NULL) { goto fail; } - - plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply"); - if (plugin->nyx_option_apply == NULL) { goto fail; } - - plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input"); - if (plugin->nyx_set_afl_input == NULL) { goto fail; } - - plugin->nyx_exec = dlsym(handle, "nyx_exec"); - if (plugin->nyx_exec == NULL) { goto fail; } - - plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer"); - if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; } - - plugin->nyx_get_bitmap_buffer_size = - dlsym(handle, "nyx_get_bitmap_buffer_size"); - if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } - - plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string"); - if (plugin->nyx_get_aux_string == NULL) { goto fail; } - - OKF("libnyx plugin is ready!"); - return plugin; - -fail: - - FATAL("failed to load libnyx: %s\n", dlerror()); - free(plugin); - return NULL; - -} - - #endif - /* Main entry point */ int main(int argc, char **argv_orig, char **envp) { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 29abeb13..3ddebaad 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -434,6 +434,20 @@ static u32 read_file(u8 *in_file) { } +#ifdef __linux__ +/* Execute the target application with an empty input (in Nyx mode). */ +static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) { + + afl_fsrv_write_to_testcase(fsrv, NULL, 0); + + if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) == + FSRV_RUN_ERROR) { + + FATAL("Error running target in Nyx mode"); + } +} +#endif + /* Execute target application. */ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { @@ -797,6 +811,7 @@ static void usage(u8 *argv0) { " -W - use qemu-based instrumentation with Wine (Wine mode)\n" " (Not necessary, here for consistency with other afl-* " "tools)\n" + " -X - use Nyx mode\n" #endif "\n" "Other settings:\n" @@ -875,7 +890,7 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = true; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshX")) > 0) { switch (opt) { @@ -1063,6 +1078,22 @@ int main(int argc, char **argv_orig, char **envp) { break; + #ifdef __linux__ + case 'X': /* NYX mode */ + + if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); } + + fsrv->nyx_mode = 1; + fsrv->nyx_parent = true; + fsrv->nyx_standalone = true; + + break; + #else + case 'X': + FATAL("Nyx mode is only availabe on linux..."); + break; + #endif + case 'b': /* Secret undocumented mode. Writes output in raw binary format @@ -1134,7 +1165,17 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv, argv); +#ifdef __linux__ + if(!fsrv->nyx_mode){ + fsrv->target_path = find_binary(argv[optind]); + } + else{ + fsrv->target_path = ck_strdup(argv[optind]); + } +#else fsrv->target_path = find_binary(argv[optind]); +#endif + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); if (!quiet_mode) { @@ -1190,6 +1231,26 @@ int main(int argc, char **argv_orig, char **envp) { use_argv = get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); +#ifdef __linux__ + } else if (fsrv->nyx_mode) { + + use_argv = ck_alloc(sizeof(char *) * (1)); + use_argv[0] = argv[0]; + + fsrv->nyx_id = 0; + + u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so"); + fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); + if (fsrv->nyx_handlers == NULL) { + + FATAL("failed to initialize libnyx.so..."); + + } + + fsrv->out_dir_path = create_nyx_tmp_workdir(); + fsrv->nyx_bind_cpu_id = 0; +#endif + } else { use_argv = argv + optind; @@ -1226,7 +1287,13 @@ int main(int argc, char **argv_orig, char **envp) { } +#ifdef __linux__ + if(!fsrv->nyx_mode && in_dir){ + (void)check_binary_signatures(fsrv->target_path); + } +#else if (in_dir) { (void)check_binary_signatures(fsrv->target_path); } +#endif shm_fuzz = ck_alloc(sizeof(sharedmem_t)); @@ -1247,7 +1314,13 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz = map + sizeof(u32); configure_afl_kill_signals( - fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); + fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode + #ifdef __linux__ + || fsrv->nyx_mode + #endif + ) + ? SIGKILL + : SIGTERM); if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) { @@ -1370,6 +1443,12 @@ int main(int argc, char **argv_orig, char **envp) { if (execute_testcases(in_dir) == 0) { +#ifdef __linux__ + if (fsrv->nyx_mode) { + remove_nyx_tmp_workdir(fsrv->out_dir_path); + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } +#endif FATAL("could not read input testcases from %s", in_dir); } @@ -1390,7 +1469,15 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - showmap_run_target(fsrv, use_argv); +#ifdef __linux__ + if(!fsrv->nyx_mode){ +#endif + showmap_run_target(fsrv, use_argv); +#ifdef __linux__ + } else { + showmap_run_target_nyx_mode(fsrv); + } +#endif tcnt = write_results_to_file(fsrv, out_file); if (!quiet_mode) { @@ -1441,6 +1528,12 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->target_path) { ck_free(fsrv->target_path); } +#ifdef __linux__ + if (fsrv->nyx_mode) { + remove_nyx_tmp_workdir(fsrv->out_dir_path); + } +#endif + afl_fsrv_deinit(fsrv); if (stdin_file) { ck_free(stdin_file); } diff --git a/src/afl-tmin.c b/src/afl-tmin.c index c0087f5f..942525d4 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -789,6 +789,7 @@ static void usage(u8 *argv0) { "mode)\n" " (Not necessary, here for consistency with other afl-* " "tools)\n" + " -X - use Nyx mode\n" #endif "\n" @@ -845,7 +846,7 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXHh")) > 0) { switch (opt) { @@ -1003,6 +1004,22 @@ int main(int argc, char **argv_orig, char **envp) { break; + #ifdef __linux__ + case 'X': /* NYX mode */ + + if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); } + + fsrv->nyx_mode = 1; + fsrv->nyx_parent = true; + fsrv->nyx_standalone = true; + + break; + #else + case 'X': + FATAL("Nyx mode is only availabe on linux..."); + break; + #endif + case 'H': /* Hang Mode */ /* Minimizes a testcase to the minimum that still times out */ @@ -1068,7 +1085,17 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv, argv); +#ifdef __linux__ + if(!fsrv->nyx_mode){ + fsrv->target_path = find_binary(argv[optind]); + } + else{ + fsrv->target_path = ck_strdup(argv[optind]); + } +#else fsrv->target_path = find_binary(argv[optind]); +#endif + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, out_file, &fsrv->use_stdin); signal(SIGALRM, kill_child); @@ -1092,6 +1119,23 @@ int main(int argc, char **argv_orig, char **envp) { use_argv = get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); +#ifdef __linux__ + } else if (fsrv->nyx_mode) { + + fsrv->nyx_id = 0; + + u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); + fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); + if (fsrv->nyx_handlers == NULL) { + FATAL("failed to initialize libnyx.so..."); + } + + fsrv->out_dir_path = create_nyx_tmp_workdir(); + fsrv->nyx_bind_cpu_id = 0; + + use_argv = argv + optind; +#endif + } else { use_argv = argv + optind; @@ -1161,7 +1205,14 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz = map + sizeof(u32); read_initial_file(); + +#ifdef __linux__ + if(!fsrv->nyx_mode){ + (void)check_binary_signatures(fsrv->target_path); + } +#else (void)check_binary_signatures(fsrv->target_path); +#endif if (!fsrv->qemu_mode && !unicorn_mode) { @@ -1265,6 +1316,12 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); +#ifdef __linux__ + if (fsrv->nyx_mode) { + remove_nyx_tmp_workdir(fsrv->out_dir_path); + } +#endif + remove_shm = 0; afl_shm_deinit(&shm); if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); From afc47868ee06cf8e466fd88881b36d5a7c71f29a Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 04:39:15 +0200 Subject: [PATCH 243/300] bump QEMU-Nyx version The QEMU-Nyx compile script does not set "--enable-gtk" anymore. So it is no longer necessary to patch the compile_qemu_nyx.sh script manually. --- nyx_mode/QEMU-Nyx | 2 +- nyx_mode/QEMU_NYX_VERSION | 2 +- nyx_mode/build_nyx_support.sh | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx index 5c8cf793..60c216bc 160000 --- a/nyx_mode/QEMU-Nyx +++ b/nyx_mode/QEMU-Nyx @@ -1 +1 @@ -Subproject commit 5c8cf793ec615b0df5fa722878c8f6906ad7936f +Subproject commit 60c216bc9e4c79834716d4099993d8397a3a8fd9 diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION index f5888136..98cb134f 100644 --- a/nyx_mode/QEMU_NYX_VERSION +++ b/nyx_mode/QEMU_NYX_VERSION @@ -1 +1 @@ -5c8cf793ec +60c216bc9e diff --git a/nyx_mode/build_nyx_support.sh b/nyx_mode/build_nyx_support.sh index e7fca64f..581a8292 100755 --- a/nyx_mode/build_nyx_support.sh +++ b/nyx_mode/build_nyx_support.sh @@ -60,11 +60,6 @@ fi echo "[*] Checking QEMU-Nyx ..." if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then - - if ! dpkg -s gtk3-devel > /dev/null 2>&1; then - echo "[-] Disabling GTK because gtk3-devel is not installed." - sed -i 's/--enable-gtk//g' QEMU-Nyx/compile_qemu_nyx.sh - fi (cd QEMU-Nyx && ./compile_qemu_nyx.sh static) fi From e2fedce6ecfa690fa7037328b6432b80a72d5acf Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 04:40:26 +0200 Subject: [PATCH 244/300] bump libnyx version --- nyx_mode/LIBNYX_VERSION | 2 +- nyx_mode/libnyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION index 00165a63..461499ec 100644 --- a/nyx_mode/LIBNYX_VERSION +++ b/nyx_mode/LIBNYX_VERSION @@ -1 +1 @@ -acaf7f6 +2822aa1 diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx index acaf7f63..2822aa1b 160000 --- a/nyx_mode/libnyx +++ b/nyx_mode/libnyx @@ -1 +1 @@ -Subproject commit acaf7f6346eeb5f1e2cf043543316909fca43650 +Subproject commit 2822aa1b14c5e7e43343abf4c988c4b50f90faf9 From a96cdc649fbdf2ae6f40d4e966812c46083032a2 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 05:59:12 +0200 Subject: [PATCH 245/300] switch to latest libnyx API --- include/forkserver.h | 25 +++++++++++++------- src/afl-forkserver.c | 56 ++++++++++++++++++++++++++++---------------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/include/forkserver.h b/include/forkserver.h index 273a9255..7cbad8c8 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -51,16 +51,23 @@ typedef enum NyxReturnValue { } NyxReturnValue; +typedef enum NyxProcessRole { + StandAlone, + Parent, + Child, +} NyxProcessRole; + typedef struct { - void *(*nyx_new)(const char *sharedir, const char *workdir, uint32_t cpu_id, - uint32_t input_buffer_size, - bool input_buffer_write_protection); - void *(*nyx_new_parent)(const char *sharedir, const char *workdir, - uint32_t cpu_id, uint32_t input_buffer_size, - bool input_buffer_write_protection); - void *(*nyx_new_child)(const char *sharedir, const char *workdir, - uint32_t cpu_id, uint32_t worker_id); + void *(*nyx_config_load)(const char *sharedir); + void (*nyx_config_set_workdir_path)(void *config, const char *workdir); + void (*nyx_config_set_input_buffer_size)(void *config, uint32_t input_buffer_size); + void (*nyx_config_set_input_buffer_write_protection)(void *config, bool input_buffer_write_protection); + void (*nyx_config_set_hprintf_fd)(void *config, int32_t hprintf_fd); + void (*nyx_config_set_process_role)(void *config, enum NyxProcessRole role); + void (*nyx_config_set_reuse_snapshot_path)(void *config, const char *reuse_snapshot_path); + + void *(*nyx_new)(void *config, uint32_t worker_id); void (*nyx_shutdown)(void *qemu_process); void (*nyx_option_set_reload_mode)(void *qemu_process, bool enable); void (*nyx_option_set_timeout)(void *qemu_process, uint8_t timeout_sec, @@ -73,6 +80,8 @@ typedef struct { uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer, uint32_t size); + bool (*nyx_remove_work_dir)(const char *workdir); + } nyx_plugin_handler_t; /* Imports helper functions to enable Nyx mode (Linux only )*/ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 95328aa2..33c46b8c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -63,15 +63,30 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { handle = dlopen((char *)libnyx_binary, RTLD_NOW); if (!handle) { goto fail; } + plugin->nyx_config_load = dlsym(handle, "nyx_config_load"); + if (plugin->nyx_config_load == NULL) { goto fail; } + + plugin->nyx_config_set_workdir_path = dlsym(handle, "nyx_config_set_workdir_path"); + if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; } + + plugin->nyx_config_set_input_buffer_size = dlsym(handle, "nyx_config_set_input_buffer_size"); + if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; } + + plugin->nyx_config_set_input_buffer_write_protection = dlsym(handle, "nyx_config_set_input_buffer_write_protection"); + if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { goto fail; } + + plugin->nyx_config_set_hprintf_fd = dlsym(handle, "nyx_config_set_hprintf_fd"); + if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; } + + plugin->nyx_config_set_process_role = dlsym(handle, "nyx_config_set_process_role"); + if (plugin->nyx_config_set_process_role == NULL) { goto fail; } + + plugin->nyx_config_set_reuse_snapshot_path = dlsym(handle, "nyx_config_set_reuse_snapshot_path"); + if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; } + plugin->nyx_new = dlsym(handle, "nyx_new"); if (plugin->nyx_new == NULL) { goto fail; } - plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent"); - if (plugin->nyx_new_parent == NULL) { goto fail; } - - plugin->nyx_new_child = dlsym(handle, "nyx_new_child"); - if (plugin->nyx_new_child == NULL) { goto fail; } - plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown"); if (plugin->nyx_shutdown == NULL) { goto fail; } @@ -101,6 +116,10 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string"); if (plugin->nyx_get_aux_string == NULL) { goto fail; } + plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir"); + if (plugin->nyx_remove_work_dir == NULL) { goto fail; } + + OKF("libnyx plugin is ready!"); return plugin; @@ -474,27 +493,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); + + fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, x); + fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE); + fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true); + if (fsrv->nyx_standalone) { - - fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new( - fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true); - + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone); } else { - if (fsrv->nyx_parent) { - - fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_parent( - fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true); - + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent); } else { - - fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_child( - fsrv->target_path, x, fsrv->nyx_bind_cpu_id, fsrv->nyx_id); - + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child); } - } + fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); + ck_free(x); if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); } From 4f6ec6cb081bfee7a6e1d6ac211b33a820ec2f71 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 06:21:43 +0200 Subject: [PATCH 246/300] add NYX_REUSE_SNAPSHOT env-var option --- src/afl-forkserver.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 33c46b8c..7eb2155e 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -509,6 +509,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } } + if (getenv("NYX_REUSE_SNAPSHOT") != NULL){ + + if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) { + FATAL("NYX_REUSE_SNAPSHOT path does not exist"); + } + + /* stupid sanity check to avoid passing an empty or invalid snapshot directory */ + char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT")); + if (access(snapshot_file_path, R_OK) == -1) { + FATAL("NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); + } + free(snapshot_file_path); + + fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT")); + } + fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); ck_free(x); From c34c3e2f5f70d9a445bdbbb2e2f0937e98358607 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 14 Apr 2023 06:24:46 +0200 Subject: [PATCH 247/300] add some sanity checks and remove duplicate nyx_shutdown calls --- src/afl-forkserver.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 7eb2155e..ae2adc3d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -555,14 +555,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { case Abort: - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); FATAL("Error: Nyx abort occured..."); break; case IoError: FATAL("Error: QEMU-Nyx has died..."); break; case Error: - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); FATAL("Error: Nyx runtime error has occured..."); break; default: @@ -1293,8 +1291,14 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { #ifdef __linux__ if (fsrv->nyx_mode) { - free(fsrv->nyx_aux_string); - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + if (fsrv->nyx_aux_string){ + free(fsrv->nyx_aux_string); + } + + /* check if we actually got a valid nyx runner */ + if (fsrv->nyx_runner) { + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } } @@ -1474,7 +1478,6 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing"); break; case Abort: - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); FATAL("Error: Nyx abort occured..."); case IoError: if (*stop_soon_p) { From b5f7f42cd0a1bce83c8c6d4af9846e7c5da3cdd1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 14 Apr 2023 10:22:00 +0200 Subject: [PATCH 248/300] update qemuafl, info in afl-plot --- afl-plot | 4 ++-- docs/Changelog.md | 14 +++++++++----- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/afl-plot b/afl-plot index 90a46d24..230d3bfe 100755 --- a/afl-plot +++ b/afl-plot @@ -287,9 +287,9 @@ $PLOT_EG _EOF_ -) | gnuplot +) | gnuplot || echo "Note: if you see errors concerning 'unknown or ambiguous terminal type' then you need to use a gnuplot that has png support compiled in." -echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot-h\" to know more." +echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot -h\" to know more." fi diff --git a/docs/Changelog.md b/docs/Changelog.md index 9436fc9f..9f4a8653 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,7 +7,6 @@ - afl-fuzz: - ensure temporary file descriptor is closed when not used - added `AFL_NO_WARN_INSTABILITY` - - added `AFL_FRIDA_STATS_INTERVAL` - added time_wo_finds to fuzzer_stats - fixed a crash in pizza (1st april easter egg) mode. Sorry for everyone who was affected! @@ -15,18 +14,23 @@ - option `-p mmopt` now also selects new queue items more often - fix bug in post_process custom mutator implementation - print name of custom mutator in UI + - slight changes that improve fuzzer performance - afl-cc: - add CFI sanitizer variant to gcc targets - llvm 16 + 17 support (thanks to @devnexen!) - support llvm 15 native pcguard changes - support for LLVMFuzzerTestOneInput -1 return + - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support - qemu_mode: - fix _RANGES envs to allow hyphens in the filenames - - new custom module: autotoken, grammar free fuzzer for text inputs - - LTO autoken and llvm_mode: added AFL_LLVM_DICT2FILE_NO_MAIN support + - basic riscv support + - frida_mode: + - added `AFL_FRIDA_STATS_INTERVAL` + - fix issue on MacOS + - unicorn_mode: + - updated and minor issues fixed + - new custom module: autotoken, a grammar free fuzzer for text inputs - better sanitizer default options support for all tools - - unicorn_mode: updated and minor issues fixed - - frida_mode: fix issue on MacOS - more minor fixes and cross-platform support ### Version ++4.05c (release) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 43dc832b..fa44d173 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -249bf0c872 +0569eff8a1 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 249bf0c8..0569eff8 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 249bf0c8723671a1eebe400a9631d9e69306ff4c +Subproject commit 0569eff8a12dec73642b96757f6b5b51a618a03a From 0c4f0dd4c483ec3cf481958c6b22c2b43b365cef Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 14 Apr 2023 16:09:55 +0200 Subject: [PATCH 249/300] oss-fuzz fix for LLVMFuzzerTestOneInput driver --- utils/aflpp_driver/aflpp_driver.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 19f0d9da..00a94b9c 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -74,7 +74,10 @@ extern unsigned char *__afl_area_ptr; extern unsigned int __afl_map_size; // libFuzzer interface is thin, so we don't include any libFuzzer headers. -__attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t *Data, +/* Using the weak attributed on LLVMFuzzerTestOneInput() breaks oss-fuzz but + on the other hand this is what Google needs to make LLVMFuzzerRunDriver() + work. Choose your poison Google! */ +/*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); __attribute__((weak)) int LLVMFuzzerRunDriver( From 97644836935020b9f42688bb6530f08f536644a9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 14 Apr 2023 16:27:32 +0200 Subject: [PATCH 250/300] remove warning --- utils/aflpp_driver/aflpp_driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 00a94b9c..34294809 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -268,12 +268,15 @@ static int ExecuteFilesOnyByOne(int argc, char **argv, __attribute__((weak)) int main(int argc, char **argv) { +// Enable if LLVMFuzzerTestOneInput() has the weak attribute +/* if (!LLVMFuzzerTestOneInput) { fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n"); abort(); } +*/ if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) printf( From 50678ed36962eb9f4d26f50f860b07116290fe42 Mon Sep 17 00:00:00 2001 From: Yaakov Saxon Date: Fri, 14 Apr 2023 11:24:10 -0400 Subject: [PATCH 251/300] Fixing typo: & (background) to && (and) --- test/test-llvm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-llvm.sh b/test/test-llvm.sh index 68649c23..0e66cc97 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -265,7 +265,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { echo 00000000000000000000000000000000 > in/in AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V15 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1 } >>errors 2>&1 - test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" & { + test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog" } || { echo CUT------------------------------------------------------------------CUT From 8f6d9d66ef96286661dab876d9b57a36982b2a4d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 15 Apr 2023 08:33:50 +0200 Subject: [PATCH 252/300] fix post_process --- src/afl-fuzz-run.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 26e8549d..4d56f3a7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -135,8 +135,11 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { if (new_mem != *mem && new_mem != NULL && new_size > 0) { - *mem = afl_realloc((void **)mem, new_size); - memmove(*mem, new_mem, new_size); + u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + *mem = new_buf; + memcpy(*mem, new_mem, new_size); + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); } From e12acaa20367f335549c2db97b88ac5c8ffbeab7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 15 Apr 2023 10:12:20 +0200 Subject: [PATCH 253/300] fix custom mutator C examples --- .../examples/custom_mutator_helpers.h | 342 ------------------ custom_mutators/examples/custom_send.c | 8 +- custom_mutators/examples/example.c | 116 +++--- .../examples/post_library_gif.so.c | 53 +-- .../examples/post_library_png.so.c | 24 +- custom_mutators/examples/simple_example.c | 28 +- docs/Changelog.md | 1 + 7 files changed, 73 insertions(+), 499 deletions(-) delete mode 100644 custom_mutators/examples/custom_mutator_helpers.h diff --git a/custom_mutators/examples/custom_mutator_helpers.h b/custom_mutators/examples/custom_mutator_helpers.h deleted file mode 100644 index 62e6efba..00000000 --- a/custom_mutators/examples/custom_mutator_helpers.h +++ /dev/null @@ -1,342 +0,0 @@ -#ifndef CUSTOM_MUTATOR_HELPERS -#define CUSTOM_MUTATOR_HELPERS - -#include "config.h" -#include "types.h" -#include - -#define INITIAL_GROWTH_SIZE (64) - -#define RAND_BELOW(limit) (rand() % (limit)) - -/* Use in a struct: creates a name_buf and a name_size variable. */ -#define BUF_VAR(type, name) \ - type * name##_buf; \ - size_t name##_size; -/* this fills in `&structptr->something_buf, &structptr->something_size`. */ -#define BUF_PARAMS(struct, name) \ - (void **)&struct->name##_buf, &struct->name##_size - -typedef struct { - -} afl_t; - -static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { - - static s8 interesting_8[] = {INTERESTING_8}; - static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16}; - static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32}; - - switch (RAND_BELOW(12)) { - - case 0: { - - /* Flip a single bit somewhere. Spooky! */ - - s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8); - - out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7); - - break; - - } - - case 1: { - - /* Set byte to interesting value. */ - - u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))]; - out_buf[(RAND_BELOW(end - begin) + begin)] = val; - - break; - - } - - case 2: { - - /* Set word to interesting value, randomly choosing endian. */ - - if (end - begin < 2) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 1) break; - - switch (RAND_BELOW(2)) { - - case 0: - *(u16 *)(out_buf + byte_idx) = - interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]; - break; - case 1: - *(u16 *)(out_buf + byte_idx) = - SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]); - break; - - } - - break; - - } - - case 3: { - - /* Set dword to interesting value, randomly choosing endian. */ - - if (end - begin < 4) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 3) break; - - switch (RAND_BELOW(2)) { - - case 0: - *(u32 *)(out_buf + byte_idx) = - interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]; - break; - case 1: - *(u32 *)(out_buf + byte_idx) = - SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]); - break; - - } - - break; - - } - - case 4: { - - /* Set qword to interesting value, randomly choosing endian. */ - - if (end - begin < 8) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 7) break; - - switch (RAND_BELOW(2)) { - - case 0: - *(u64 *)(out_buf + byte_idx) = - (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]; - break; - case 1: - *(u64 *)(out_buf + byte_idx) = SWAP64( - (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]); - break; - - } - - break; - - } - - case 5: { - - /* Randomly subtract from byte. */ - - out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX); - - break; - - } - - case 6: { - - /* Randomly add to byte. */ - - out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX); - - break; - - } - - case 7: { - - /* Randomly subtract from word, random endian. */ - - if (end - begin < 2) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 1) break; - - if (RAND_BELOW(2)) { - - *(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX); - - } else { - - u16 num = 1 + RAND_BELOW(ARITH_MAX); - - *(u16 *)(out_buf + byte_idx) = - SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num); - - } - - break; - - } - - case 8: { - - /* Randomly add to word, random endian. */ - - if (end - begin < 2) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 1) break; - - if (RAND_BELOW(2)) { - - *(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX); - - } else { - - u16 num = 1 + RAND_BELOW(ARITH_MAX); - - *(u16 *)(out_buf + byte_idx) = - SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num); - - } - - break; - - } - - case 9: { - - /* Randomly subtract from dword, random endian. */ - - if (end - begin < 4) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 3) break; - - if (RAND_BELOW(2)) { - - *(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX); - - } else { - - u32 num = 1 + RAND_BELOW(ARITH_MAX); - - *(u32 *)(out_buf + byte_idx) = - SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num); - - } - - break; - - } - - case 10: { - - /* Randomly add to dword, random endian. */ - - if (end - begin < 4) break; - - s32 byte_idx = (RAND_BELOW(end - begin) + begin); - - if (byte_idx >= end - 3) break; - - if (RAND_BELOW(2)) { - - *(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX); - - } else { - - u32 num = 1 + RAND_BELOW(ARITH_MAX); - - *(u32 *)(out_buf + byte_idx) = - SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num); - - } - - break; - - } - - case 11: { - - /* Just set a random byte to a random value. Because, - why not. We use XOR with 1-255 to eliminate the - possibility of a no-op. */ - - out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255); - - break; - - } - - } - -} - -/* This function calculates the next power of 2 greater or equal its argument. - @return The rounded up power of 2 (if no overflow) or 0 on overflow. -*/ -static inline size_t next_pow2(size_t in) { - - if (in == 0 || in > (size_t)-1) - return 0; /* avoid undefined behaviour under-/overflow */ - size_t out = in - 1; - out |= out >> 1; - out |= out >> 2; - out |= out >> 4; - out |= out >> 8; - out |= out >> 16; - return out + 1; - -} - -/* This function makes sure *size is > size_needed after call. - It will realloc *buf otherwise. - *size will grow exponentially as per: - https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ - Will return NULL and free *buf if size_needed is <1 or realloc failed. - @return For convenience, this function returns *buf. - */ -static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { - - /* No need to realloc */ - if (likely(size_needed && *size >= size_needed)) return *buf; - - /* No initial size was set */ - if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; - - /* grow exponentially */ - size_t next_size = next_pow2(size_needed); - - /* handle overflow */ - if (!next_size) { next_size = size_needed; } - - /* alloc */ - *buf = realloc(*buf, next_size); - *size = *buf ? next_size : 0; - - return *buf; - -} - -/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ -static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2, - size_t *size2) { - - void * scratch_buf = *buf1; - size_t scratch_size = *size1; - *buf1 = *buf2; - *size1 = *size2; - *buf2 = scratch_buf; - *size2 = scratch_size; - -} - -#undef INITIAL_GROWTH_SIZE - -#endif - diff --git a/custom_mutators/examples/custom_send.c b/custom_mutators/examples/custom_send.c index 7de72819..9cc4b160 100644 --- a/custom_mutators/examples/custom_send.c +++ b/custom_mutators/examples/custom_send.c @@ -10,21 +10,21 @@ // afl-fuzz -i in -o out -- ./test-instr -f /tmp/foo // -#include "custom_mutator_helpers.h" - #include #include #include #include #include +#include "afl-fuzz.h" + typedef struct my_mutator { - afl_t *afl; + afl_state_t *afl; } my_mutator_t; -my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); if (!data) { diff --git a/custom_mutators/examples/example.c b/custom_mutators/examples/example.c index e680ec8e..42c7469c 100644 --- a/custom_mutators/examples/example.c +++ b/custom_mutators/examples/example.c @@ -7,7 +7,7 @@ */ // You need to use -I/path/to/AFLplusplus/include -I. -#include "custom_mutator_helpers.h" +#include "afl-fuzz.h" #include #include @@ -26,19 +26,14 @@ static const char *commands[] = { typedef struct my_mutator { - afl_t *afl; + afl_state_t *afl; // any additional data here! size_t trim_size_current; int trimmming_steps; int cur_step; - // Reused buffers: - BUF_VAR(u8, fuzz); - BUF_VAR(u8, data); - BUF_VAR(u8, havoc); - BUF_VAR(u8, trim); - BUF_VAR(u8, post_process); + u8 *mutated_out, *post_process_buf, *trim_buf; } my_mutator_t; @@ -53,7 +48,7 @@ typedef struct my_mutator { * There may be multiple instances of this mutator in one afl-fuzz run! * Return NULL on error. */ -my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { srand(seed); // needed also by surgical_havoc_mutate() @@ -65,6 +60,27 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { } + if ((data->mutated_out = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + + if ((data->post_process_buf = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + + if ((data->trim_buf = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + data->afl = afl; return data; @@ -96,31 +112,14 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, // the fuzzer size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size; - // maybe_grow is optimized to be quick for reused buffers. - u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size); - if (!mutated_out) { - - *out_buf = NULL; - perror("custom mutator allocation (maybe_grow)"); - return 0; /* afl-fuzz will very likely error out after this. */ - - } + memcpy(data->mutated_out, buf, buf_size); // Randomly select a command string to add as a header to the packet - memcpy(mutated_out, commands[rand() % 3], 3); + memcpy(data->mutated_out, commands[rand() % 3], 3); - // Mutate the payload of the packet - int i; - for (i = 0; i < 8; ++i) { + if (mutated_size > max_size) { mutated_size = max_size; } - // Randomly perform one of the (no len modification) havoc mutations - surgical_havoc_mutate(mutated_out, 3, mutated_size); - - } - - if (max_size > mutated_size) { mutated_size = max_size; } - - *out_buf = mutated_out; + *out_buf = data->mutated_out; return mutated_size; } @@ -144,24 +143,16 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, size_t afl_custom_post_process(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { - uint8_t *post_process_buf = - maybe_grow(BUF_PARAMS(data, post_process), buf_size + 5); - if (!post_process_buf) { + if (buf_size + 5 > MAX_FILE) { buf_size = MAX_FILE - 5; } - perror("custom mutator realloc failed."); - *out_buf = NULL; - return 0; + memcpy(data->post_process_buf + 5, buf, buf_size); + data->post_process_buf[0] = 'A'; + data->post_process_buf[1] = 'F'; + data->post_process_buf[2] = 'L'; + data->post_process_buf[3] = '+'; + data->post_process_buf[4] = '+'; - } - - memcpy(post_process_buf + 5, buf, buf_size); - post_process_buf[0] = 'A'; - post_process_buf[1] = 'F'; - post_process_buf[2] = 'L'; - post_process_buf[3] = '+'; - post_process_buf[4] = '+'; - - *out_buf = post_process_buf; + *out_buf = data->post_process_buf; return buf_size + 5; @@ -197,13 +188,6 @@ int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, data->cur_step = 0; - if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) { - - perror("init_trim grow"); - return -1; - - } - memcpy(data->trim_buf, buf, buf_size); data->trim_size_current = buf_size; @@ -284,27 +268,11 @@ int32_t afl_custom_post_trim(my_mutator_t *data, int success) { size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size, u8 **out_buf, size_t max_size) { - if (buf_size == 0) { + *out_buf = buf; // in-place mutation - *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1); - if (!*out_buf) { + if (buf_size <= sizeof(size_t)) { return buf_size; } - perror("custom havoc: maybe_grow"); - return 0; - - } - - **out_buf = rand() % 256; - buf_size = 1; - - } else { - - // We reuse buf here. It's legal and faster. - *out_buf = buf; - - } - - size_t victim = rand() % buf_size; + size_t victim = rand() % (buf_size - sizeof(size_t)); (*out_buf)[victim] += rand() % 10; return buf_size; @@ -371,9 +339,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data, void afl_custom_deinit(my_mutator_t *data) { free(data->post_process_buf); - free(data->havoc_buf); - free(data->data_buf); - free(data->fuzz_buf); + free(data->mutated_out); free(data->trim_buf); free(data); diff --git a/custom_mutators/examples/post_library_gif.so.c b/custom_mutators/examples/post_library_gif.so.c index 3cb018a6..6737c627 100644 --- a/custom_mutators/examples/post_library_gif.so.c +++ b/custom_mutators/examples/post_library_gif.so.c @@ -45,9 +45,8 @@ 1) If you don't want to modify the test case, simply set `*out_buf = in_buf` and return the original `len`. - NOTE: the following is currently NOT true, we abort in this case! 2) If you want to skip this test case altogether and have AFL generate a - new one, return 0 or set `*out_buf = NULL`. + new one, return 0. Use this sparingly - it's faster than running the target program with patently useless inputs, but still wastes CPU time. @@ -59,8 +58,6 @@ Note that the buffer will *not* be freed for you. To avoid memory leaks, you need to free it or reuse it on subsequent calls (as shown below). - *** Feel free to reuse the original 'in_buf' BUFFER and return it. *** - Alright. The example below shows a simple postprocessor that tries to make sure that all input files start with "GIF89a". @@ -72,7 +69,7 @@ #include #include #include -#include "alloc-inl.h" +#include "afl-fuzz.h" /* Header that must be present at the beginning of every test case: */ @@ -80,8 +77,7 @@ typedef struct post_state { - unsigned char *buf; - size_t size; + size_t size; } post_state_t; @@ -95,15 +91,6 @@ void *afl_custom_init(void *afl) { } - state->buf = calloc(sizeof(unsigned char), 4096); - if (!state->buf) { - - free(state); - perror("calloc"); - return NULL; - - } - return state; } @@ -113,6 +100,10 @@ void *afl_custom_init(void *afl) { size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf, unsigned int len, unsigned char **out_buf) { + /* we do in-place modification as we do not increase the size */ + + *out_buf = in_buf; + /* Skip execution altogether for buffers shorter than 6 bytes (just to show how it's done). We can trust len to be sane. */ @@ -120,34 +111,7 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf, /* Do nothing for buffers that already start with the expected header. */ - if (!memcmp(in_buf, HEADER, strlen(HEADER))) { - - *out_buf = in_buf; - return len; - - } - - /* Allocate memory for new buffer, reusing previous allocation if - possible. Note we have to use afl-fuzz's own realloc! - We use afl_realloc because it is effective. - You can also work within in_buf, and assign it to *out_buf. */ - - *out_buf = afl_realloc(out_buf, len); - - /* If we're out of memory, the most graceful thing to do is to return the - original buffer and give up on modifying it. Let AFL handle OOM on its - own later on. */ - - if (!*out_buf) { - - *out_buf = in_buf; - return len; - - } - - if (len > strlen(HEADER)) - memcpy(*out_buf + strlen(HEADER), in_buf + strlen(HEADER), - len - strlen(HEADER)); + if (!memcmp(in_buf, HEADER, strlen(HEADER))) { return len; } /* Insert the new header. */ @@ -162,7 +126,6 @@ size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf, /* Gets called afterwards */ void afl_custom_deinit(post_state_t *data) { - free(data->buf); free(data); } diff --git a/custom_mutators/examples/post_library_png.so.c b/custom_mutators/examples/post_library_png.so.c index cd65b1bc..652da497 100644 --- a/custom_mutators/examples/post_library_png.so.c +++ b/custom_mutators/examples/post_library_png.so.c @@ -30,7 +30,7 @@ #include #include #include -#include "alloc-inl.h" +#include "afl-fuzz.h" /* A macro to round an integer up to 4 kB. */ @@ -53,7 +53,7 @@ void *afl_custom_init(void *afl) { } - state->buf = calloc(sizeof(unsigned char), 4096); + state->buf = calloc(sizeof(unsigned char), MAX_FILE); if (!state->buf) { free(state); @@ -80,21 +80,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf, } - /* This is not a good way to do it, if you do not need to grow the buffer - then just work with in_buf instead for speed reasons. - But we want to show how to grow a buffer, so this is how it's done: */ - - unsigned int pos = 8; - unsigned char *new_buf = afl_realloc(out_buf, UP4K(len)); - - if (!new_buf) { - - *out_buf = in_buf; - return len; - - } - - memcpy(new_buf, in_buf, len); + unsigned int pos = 8; /* Minimum size of a zero-length PNG chunk is 12 bytes; if we don't have that, we can bail out. */ @@ -124,7 +110,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf, if (real_cksum != file_cksum) { - *(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum; + *(uint32_t *)(data->buf + pos + 8 + chunk_len) = real_cksum; } @@ -134,7 +120,7 @@ size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf, } - *out_buf = new_buf; + *out_buf = data->buf; return len; } diff --git a/custom_mutators/examples/simple_example.c b/custom_mutators/examples/simple_example.c index d888ec1f..2c0abe29 100644 --- a/custom_mutators/examples/simple_example.c +++ b/custom_mutators/examples/simple_example.c @@ -1,6 +1,6 @@ // This simple example just creates random buffer <= 100 filled with 'A' // needs -I /path/to/AFLplusplus/include -#include "custom_mutator_helpers.h" +#include "afl-fuzz.h" #include #include @@ -13,14 +13,14 @@ typedef struct my_mutator { - afl_t *afl; + afl_state_t *afl; // Reused buffers: - BUF_VAR(u8, fuzz); + u8 *fuzz_buf; } my_mutator_t; -my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { srand(seed); my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); @@ -31,6 +31,14 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { } + data->fuzz_buf = (u8 *)malloc(MAX_FILE); + if (!data->fuzz_buf) { + + perror("afl_custom_init malloc"); + return NULL; + + } + data->afl = afl; return data; @@ -44,18 +52,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, int size = (rand() % 100) + 1; if (size > max_size) size = max_size; - u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), size); - if (!mutated_out) { - *out_buf = NULL; - perror("custom mutator allocation (maybe_grow)"); - return 0; /* afl-fuzz will very likely error out after this. */ + memset(data->fuzz_buf, _FIXED_CHAR, size); - } - - memset(mutated_out, _FIXED_CHAR, size); - - *out_buf = mutated_out; + *out_buf = data->fuzz_buf; return size; } diff --git a/docs/Changelog.md b/docs/Changelog.md index 9f4a8653..3337feb9 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -30,6 +30,7 @@ - unicorn_mode: - updated and minor issues fixed - new custom module: autotoken, a grammar free fuzzer for text inputs + - fixed custom mutator C examples - better sanitizer default options support for all tools - more minor fixes and cross-platform support From 120d009e7d7c425019e984c29e027af710a0a7df Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 15 Apr 2023 11:36:58 +0200 Subject: [PATCH 254/300] wasm support --- GNUmakefile | 1 + GNUmakefile.llvm | 5 +++++ instrumentation/afl-compiler-rt.o.c | 2 +- instrumentation/afl-llvm-pass.so.cc | 10 +++++----- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 85f164f5..5bc3f9d5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -388,6 +388,7 @@ help: @echo NO_NYX - disable building nyx mode dependencies @echo "NO_CORESIGHT - disable building coresight (arm64 only)" @echo NO_UNICORN_ARM64 - disable building unicorn on arm64 + @echo "WAFL_MODE - enable for WASM fuzzing with https://github.com/fgsect/WAFL" @echo AFL_NO_X86 - if compiling on non-intel/amd platforms @echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)" @echo "==========================================" diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 09e9b5be..a053403b 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -294,6 +294,11 @@ endif CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS) +# wasm fuzzing: disable thread-local storage and unset LLVM debug flag +ifdef WAFL_MODE + $(info Compiling libraries for use with WAVM) + CLANG_CPPFL += -DNDEBUG -DNO_TLS +endif # User teor2345 reports that this is required to make things work on MacOS X. ifeq "$(SYS)" "Darwin" diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 26fc7256..e0e40983 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -113,7 +113,7 @@ int __afl_selective_coverage __attribute__((weak)); int __afl_selective_coverage_start_off __attribute__((weak)); static int __afl_selective_coverage_temp = 1; -#if defined(__ANDROID__) || defined(__HAIKU__) +#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; PREV_LOC_T __afl_prev_caller[CTX_MAX_K]; u32 __afl_prev_ctx; diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index e8d0b1e5..c59324fd 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -413,7 +413,7 @@ bool AFLCoverage::runOnModule(Module &M) { GlobalVariable *AFLContext = NULL; if (ctx_str || caller_str) -#if defined(__ANDROID__) || defined(__HAIKU__) +#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) AFLContext = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx"); #else @@ -424,7 +424,7 @@ bool AFLCoverage::runOnModule(Module &M) { #ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) - #if defined(__ANDROID__) || defined(__HAIKU__) + #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) AFLPrevLoc = new GlobalVariable( M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_loc"); @@ -437,7 +437,7 @@ bool AFLCoverage::runOnModule(Module &M) { #endif else #endif -#if defined(__ANDROID__) || defined(__HAIKU__) +#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) AFLPrevLoc = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); #else @@ -448,7 +448,7 @@ bool AFLCoverage::runOnModule(Module &M) { #ifdef AFL_HAVE_VECTOR_INTRINSICS if (ctx_k) - #if defined(__ANDROID__) || defined(__HAIKU__) + #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) AFLPrevCaller = new GlobalVariable( M, PrevCallerTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_caller"); @@ -461,7 +461,7 @@ bool AFLCoverage::runOnModule(Module &M) { #endif else #endif -#if defined(__ANDROID__) || defined(__HAIKU__) +#if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS) AFLPrevCaller = new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_caller"); From 2f6242d3f8b09bfbf9e2b172acd0c67015e6ef2b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 15 Apr 2023 12:28:39 +0200 Subject: [PATCH 255/300] update docs --- docs/third_party_tools.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/third_party_tools.md b/docs/third_party_tools.md index 97f2c362..02a40ce5 100644 --- a/docs/third_party_tools.md +++ b/docs/third_party_tools.md @@ -1,5 +1,10 @@ # Tools that help fuzzing with AFL++ +## AFL++ and other development languages + +* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST +* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM + ## Speeding up fuzzing * [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the From 47833bcf9e4b642e090f7cc0da25d1ed99688e5e Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 04:28:19 +0200 Subject: [PATCH 256/300] fix remove_nyx_tmp_workdir function --- include/common.h | 2 +- src/afl-common.c | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/common.h b/include/common.h index 279a5f47..e03566de 100644 --- a/include/common.h +++ b/include/common.h @@ -150,7 +150,7 @@ void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, #ifdef __linux__ /* Nyx helper functions to create and remove tmp workdirs */ char* create_nyx_tmp_workdir(void); -void remove_nyx_tmp_workdir(char* nyx_out_dir_path); +void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path); #endif #endif diff --git a/src/afl-common.c b/src/afl-common.c index 7dbf7129..fe0db94d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1381,12 +1381,22 @@ char* create_nyx_tmp_workdir(void) { } /* Vice versa, we remove the tmp workdir for nyx with this helper function. */ -void remove_nyx_tmp_workdir(char* nyx_out_dir_path) { - /* Fix me: This is not recursive, so it will always fail. Use a libnyx helper function instead - * to remove the workdir safely (and not risking to wipe the whole filesystem accidentally). */ - //if (rmdir(nyx_out_dir_path)) { - // PFATAL("Unable to remove nyx workdir"); - //} - free(nyx_out_dir_path); +void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) { + char* workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path); + + if (access(workdir_path, R_OK) == 0) { + if(fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) { + WARNF("Unable to remove nyx workdir (%s)", workdir_path); + } + } + + if (access(nyx_out_dir_path, R_OK) == 0) { + if (rmdir(nyx_out_dir_path)) { + WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path); + } + } + + ck_free(workdir_path); + ck_free(nyx_out_dir_path); } #endif From 059d470e8dd0a5339daefe0842f4ad5014717838 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 04:42:09 +0200 Subject: [PATCH 257/300] improved Nyx tmp dir handling (additional sanity checks) --- include/forkserver.h | 2 + src/afl-analyze.c | 7 +--- src/afl-forkserver.c | 97 ++++++++++++++++++++++++++++++-------------- src/afl-fuzz.c | 8 ---- src/afl-showmap.c | 13 +----- src/afl-tmin.c | 7 +--- 6 files changed, 71 insertions(+), 63 deletions(-) diff --git a/include/forkserver.h b/include/forkserver.h index 7cbad8c8..ba280d38 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -190,6 +190,8 @@ typedef struct afl_forkserver { u32 nyx_id; /* nyx runner id (0 -> master) */ u32 nyx_bind_cpu_id; /* nyx runner cpu id */ char *nyx_aux_string; + bool nyx_use_tmp_workdir; + char *nyx_tmp_workdir_path; #endif } afl_forkserver_t; diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 0bdadfdc..0a4e7fb5 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -1058,7 +1058,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("failed to initialize libnyx.so..."); } - fsrv.out_dir_path = create_nyx_tmp_workdir(); + fsrv.nyx_use_tmp_workdir = true; fsrv.nyx_bind_cpu_id = 0; use_argv = argv + optind; @@ -1119,11 +1119,6 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); -#ifdef __linux__ - if (fsrv.nyx_mode) { - remove_nyx_tmp_workdir(fsrv.out_dir_path); - } -#endif afl_shm_deinit(&shm); afl_fsrv_deinit(&fsrv); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ae2adc3d..0e705c63 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -126,11 +126,39 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { fail: FATAL("failed to load libnyx: %s\n", dlerror()); - free(plugin); + ck_free(plugin); return NULL; } +void afl_nyx_runner_kill(afl_forkserver_t *fsrv){ + if (fsrv->nyx_mode) { + + if (fsrv->nyx_aux_string){ + ck_free(fsrv->nyx_aux_string); + } + + /* check if we actually got a valid nyx runner */ + if (fsrv->nyx_runner) { + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } + + /* if we have use a tmp work dir we need to remove it */ + if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) { + remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path); + } + } +} + +/* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp + * files) before exiting. Used before "afl_fsrv_killall()" is registered as + * an atexit() handler. */ +#define NYX_PRE_FATAL(fsrv, x...) \ + do { \ + afl_nyx_runner_kill(fsrv); \ + FATAL(x); \ + } while (0) + #endif /** @@ -168,6 +196,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->nyx_runner = NULL; fsrv->nyx_id = 0xFFFFFFFF; fsrv->nyx_bind_cpu_id = 0xFFFFFFFF; + fsrv->nyx_use_tmp_workdir = false; + fsrv->nyx_tmp_workdir_path = NULL; #endif // this structure needs default so we initialize it if this was not done @@ -481,21 +511,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) { ACTF("Spinning up the NYX backend..."); } - if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); } + if (fsrv->nyx_use_tmp_workdir){ + fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir(); + fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path; + } else { + if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); } + } - char *x = alloc_printf("%s/workdir", fsrv->out_dir_path); + char *workdir_path = alloc_printf("%s/workdir", fsrv->out_dir_path); - if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); } + if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); } if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) { - - FATAL("Nyx CPU ID is not set..."); - + NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set..."); } void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); - fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, x); + fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path); fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE); fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true); @@ -512,22 +545,36 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (getenv("NYX_REUSE_SNAPSHOT") != NULL){ if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) { - FATAL("NYX_REUSE_SNAPSHOT path does not exist"); + NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist"); } /* stupid sanity check to avoid passing an empty or invalid snapshot directory */ char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT")); if (access(snapshot_file_path, R_OK) == -1) { - FATAL("NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); + NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); } - free(snapshot_file_path); + ck_free(snapshot_file_path); + + /* another sanity check to avoid passing a snapshot directory that is + * located in the current workdir (the workdir will be wiped by libnyx on startup) */ + char* outdir_path_real = realpath(fsrv->out_dir_path, NULL); + char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_real); + char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL); + + if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){ + NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path is located in current workdir (use another output directory)"); + } + + ck_free(reuse_snapshot_path_real); + ck_free(workdir_snapshot_path); + ck_free(outdir_path_real); fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT")); } fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); - ck_free(x); + ck_free(workdir_path); if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); } @@ -555,13 +602,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { case Abort: - FATAL("Error: Nyx abort occured..."); + NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured..."); break; case IoError: - FATAL("Error: QEMU-Nyx has died..."); + NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died..."); break; case Error: - FATAL("Error: Nyx runtime error has occured..."); + NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured..."); break; default: break; @@ -571,7 +618,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* autodict in Nyx mode */ if (!ignore_autodict) { - x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path); + char* x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path); int nyx_autodict_fd = open(x, O_RDONLY); ck_free(x); @@ -584,7 +631,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, u8 *dict = ck_alloc(f_len); if (dict == NULL) { - FATAL("Could not allocate %u bytes of autodictionary memory", + NYX_PRE_FATAL(fsrv, "Could not allocate %u bytes of autodictionary memory", f_len); } @@ -602,7 +649,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } else { - FATAL( + NYX_PRE_FATAL(fsrv, "Reading autodictionary fail at position %u with %u bytes " "left.", offset, len); @@ -1289,19 +1336,7 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { fsrv->child_pid = -1; #ifdef __linux__ - if (fsrv->nyx_mode) { - - if (fsrv->nyx_aux_string){ - free(fsrv->nyx_aux_string); - } - - /* check if we actually got a valid nyx runner */ - if (fsrv->nyx_runner) { - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); - } - - } - + afl_nyx_runner_kill(fsrv); #endif } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8b4fe1e5..0e380f73 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2191,14 +2191,6 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->pending_not_fuzzed || !valid_seeds) { - #ifdef __linux__ - if (afl->fsrv.nyx_mode) { - - afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner); - - } - - #endif FATAL("We need at least one valid input seed that does not crash!"); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 3ddebaad..832730fd 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -1247,7 +1247,7 @@ int main(int argc, char **argv_orig, char **envp) { } - fsrv->out_dir_path = create_nyx_tmp_workdir(); + fsrv->nyx_use_tmp_workdir = true; fsrv->nyx_bind_cpu_id = 0; #endif @@ -1443,12 +1443,6 @@ int main(int argc, char **argv_orig, char **envp) { if (execute_testcases(in_dir) == 0) { -#ifdef __linux__ - if (fsrv->nyx_mode) { - remove_nyx_tmp_workdir(fsrv->out_dir_path); - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); - } -#endif FATAL("could not read input testcases from %s", in_dir); } @@ -1528,11 +1522,6 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->target_path) { ck_free(fsrv->target_path); } -#ifdef __linux__ - if (fsrv->nyx_mode) { - remove_nyx_tmp_workdir(fsrv->out_dir_path); - } -#endif afl_fsrv_deinit(fsrv); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 942525d4..98403049 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1130,7 +1130,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("failed to initialize libnyx.so..."); } - fsrv->out_dir_path = create_nyx_tmp_workdir(); + fsrv->nyx_use_tmp_workdir = true; fsrv->nyx_bind_cpu_id = 0; use_argv = argv + optind; @@ -1316,11 +1316,6 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); -#ifdef __linux__ - if (fsrv->nyx_mode) { - remove_nyx_tmp_workdir(fsrv->out_dir_path); - } -#endif remove_shm = 0; afl_shm_deinit(&shm); From 6d4234b3056bec79376c45b8ab40e4d6fb64df04 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 05:14:32 +0200 Subject: [PATCH 258/300] bump libnyx version --- nyx_mode/LIBNYX_VERSION | 2 +- nyx_mode/libnyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION index 461499ec..86b32eec 100644 --- a/nyx_mode/LIBNYX_VERSION +++ b/nyx_mode/LIBNYX_VERSION @@ -1 +1 @@ -2822aa1 +2da7f08 diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx index 2822aa1b..2da7f08b 160000 --- a/nyx_mode/libnyx +++ b/nyx_mode/libnyx @@ -1 +1 @@ -Subproject commit 2822aa1b14c5e7e43343abf4c988c4b50f90faf9 +Subproject commit 2da7f08b6e0267ccfe64e1320b24cdb29223459c From d213071e13b1720d06e1a960015db198f363aab5 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 05:16:01 +0200 Subject: [PATCH 259/300] bump packer version --- nyx_mode/PACKER_VERSION | 2 +- nyx_mode/packer | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION index a8ebe13a..7db88233 100644 --- a/nyx_mode/PACKER_VERSION +++ b/nyx_mode/PACKER_VERSION @@ -1 +1 @@ -86b159b +202bace diff --git a/nyx_mode/packer b/nyx_mode/packer index 86b159ba..202bace8 160000 --- a/nyx_mode/packer +++ b/nyx_mode/packer @@ -1 +1 @@ -Subproject commit 86b159bafc0b2ba8feeaa8761a45b6201d34084f +Subproject commit 202bace888d237e4e8f4507d0eba6791a811554d From 61aeb4486310b4aab66558bd21ead8b6e35501e2 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 05:19:09 +0200 Subject: [PATCH 260/300] remove redundant access() call --- src/afl-common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index fe0db94d..5692e277 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1390,10 +1390,8 @@ void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) { } } - if (access(nyx_out_dir_path, R_OK) == 0) { - if (rmdir(nyx_out_dir_path)) { - WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path); - } + if (rmdir(nyx_out_dir_path)) { + WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path); } ck_free(workdir_path); From 0a699d885b513dab06e5be1b655ed03f6a8d592f Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 06:19:39 +0200 Subject: [PATCH 261/300] add some documentation --- nyx_mode/README.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/nyx_mode/README.md b/nyx_mode/README.md index 11698df9..878b2acf 100644 --- a/nyx_mode/README.md +++ b/nyx_mode/README.md @@ -116,11 +116,35 @@ afl-fuzz -i in -o out -Y -S 2 -- ./PACKAGE-DIRECTORY ## AFL++ companion tools (afl-showmap etc.) -Please note that AFL++ companion tools like afl-cmin, afl-showmap, etc. are -not supported with Nyx mode, only afl-fuzz. +AFL++ companion tools support Nyx mode and can be used to analyze or minimize one specific input or an entire output corpus. These tools work similarly to `afl-fuzz`. -For source based instrumentation just use these tools normally, for -binary-only targets use with -Q for qemu_mode. +To run a target with one of these tools, add the `-X` parameter to the command line to enable Nyx mode, and pass the path to a Nyx package directory: + +```shell +afl-tmin -i in_file -o out_file -X -- ./PACKAGE-DIRECTORY +``` + +```shell +afl-analyze -i in_file -X -- ./PACKAGE-DIRECTORY +``` + +```shell +afl-showmap -i in_dir -o out_file -X -- ./PACKAGE-DIRECTORY +``` + +```shell +afl-cmin -i in_dir -o out_dir -X -- ./PACKAGE-DIRECTORY +``` + +On each program startup of one the AFL++ tools in Nyx mode, a Nyx VM is spawned, and a bootstrapping procedure is performed inside the VM to prepare the target environment. As a consequence, due to the bootstrapping procedure, the launch performance is much slower compared to other modes. However, this can be optimized by reusing an existing fuzzing snapshot to avoid the slow re-execution of the bootstrap procedure. + +A fuzzing snapshot is automatically created and stored in the output directory at `out_dir/workdir/snapshot/` by the first parent process of `afl-fuzz` if parallel mode is used. To enable this feature, set the path to an existing snapshot directory in the `NYX_REUSE_SNAPSHOT` environment variable and use the tools as usual: + +```shell +afl-fuzz -i ./in_dir -o ./out_dir -Y -M 0 ./PACKAGE-DIRECTORY + +NYX_REUSE_SNAPSHOT=./out_dir/workdir/snapshot/ afl-analyze -i in_file -X -- ./PACKAGE-DIRECTORY +``` ## Real-world examples From d0b86bf05563dea686d27f14972f448b6f33023b Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Sun, 16 Apr 2023 06:23:38 +0200 Subject: [PATCH 262/300] pass absolute paths to libnyx --- src/afl-forkserver.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 0e705c63..fd4e213d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -518,7 +518,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); } } - char *workdir_path = alloc_printf("%s/workdir", fsrv->out_dir_path); + /* libnyx expects an absolute path */ + char* outdir_path_absolute = realpath(fsrv->out_dir_path, NULL); + if (outdir_path_absolute == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); } + + char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute); if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); } @@ -557,8 +561,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* another sanity check to avoid passing a snapshot directory that is * located in the current workdir (the workdir will be wiped by libnyx on startup) */ - char* outdir_path_real = realpath(fsrv->out_dir_path, NULL); - char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_real); + char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute); char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL); if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){ @@ -567,7 +570,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, ck_free(reuse_snapshot_path_real); ck_free(workdir_snapshot_path); - ck_free(outdir_path_real); fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT")); } @@ -575,6 +577,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); ck_free(workdir_path); + ck_free(outdir_path_absolute); if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); } From 56f7e3aa088e715b054f10c01b6b5a7e5acf8931 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 16 Apr 2023 12:42:32 +0200 Subject: [PATCH 263/300] hidden -Y option for nyx, code format --- afl-cmin | 10 +- afl-cmin.bash | 30 ++++-- include/common.h | 4 +- include/forkserver.h | 13 ++- src/afl-analyze.c | 29 +++--- src/afl-common.c | 26 +++-- src/afl-forkserver.c | 155 +++++++++++++++++++++--------- src/afl-showmap.c | 54 +++++++---- src/afl-tmin.c | 27 +++--- utils/aflpp_driver/aflpp_driver.c | 23 ++--- 10 files changed, 245 insertions(+), 126 deletions(-) diff --git a/afl-cmin b/afl-cmin index 12791584..c5e64410 100755 --- a/afl-cmin +++ b/afl-cmin @@ -124,9 +124,9 @@ function usage() { "AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \ "AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \ "AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \ -"AFL_FORK_SERVER_KILL_SIGNAL: Signal delivered to fork server processes on termination\n" \ -" (default: SIGTERM). If this is not set and AFL_KILL_SIGNAL is set,\n" \ -" this will be set to the same value as AFL_KILL_SIGNAL.\n" \ +"AFL_FORK_SERVER_KILL_SIGNAL: Signal delivered to fork server processes on\n" \ +" termination (default: SIGTERM). If this is not set and AFL_KILL_SIGNAL is\n" \ +" set, this will be set to the same value as AFL_KILL_SIGNAL.\n" \ "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" \ "AFL_CMIN_ALLOW_ANY: write tuples for crashing inputs also\n" \ "AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \ @@ -157,7 +157,7 @@ BEGIN { # process options Opterr = 1 # default is to diagnose Optind = 1 # skip ARGV[0] - while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUX?")) != -1) { + while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXY?")) != -1) { if (_go_c == "i") { if (!Optarg) usage() if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} @@ -219,7 +219,7 @@ BEGIN { unicorn_mode = 1 continue } else - if (_go_c == "X") { + if (_go_c == "X" || _go_c == "Y") { if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} extra_par = extra_par " -X" nyx_mode = 1 diff --git a/afl-cmin.bash b/afl-cmin.bash index 10c9477a..bcf62eba 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \ export AFL_QUIET=1 -while getopts "+i:o:f:m:t:eOQUACh" opt; do +while getopts "+i:o:f:m:t:eOQUAChXY" opt; do case "$opt" in @@ -94,6 +94,14 @@ while getopts "+i:o:f:m:t:eOQUACh" opt; do EXTRA_PAR="$EXTRA_PAR -Q" QEMU_MODE=1 ;; + "Y") + EXTRA_PAR="$EXTRA_PAR -X" + NYX_MODE=1 + ;; + "X") + EXTRA_PAR="$EXTRA_PAR -X" + NYX_MODE=1 + ;; "U") EXTRA_PAR="$EXTRA_PAR -U" UNICORN_MODE=1 @@ -128,6 +136,7 @@ Execution control settings: -O - use binary-only instrumentation (FRIDA mode) -Q - use binary-only instrumentation (QEMU mode) -U - use unicorn-based instrumentation (Unicorn mode) + -X - use Nyx mode Minimization settings: @@ -206,17 +215,20 @@ if [ ! "$TIMEOUT" = "none" ]; then fi -if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then +if [ "$NYX_MODE" = "" ]; then + if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then - TNEW="`which "$TARGET_BIN" 2>/dev/null`" + TNEW="`which "$TARGET_BIN" 2>/dev/null`" + + if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then + echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2 + exit 1 + fi + + TARGET_BIN="$TNEW" - if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then - echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2 - exit 1 fi - TARGET_BIN="$TNEW" - fi grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && { @@ -228,7 +240,7 @@ grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && { } } -if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then +if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" -a "$NYX_MODE" = "" ]; then if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2 diff --git a/include/common.h b/include/common.h index e03566de..8d85d201 100644 --- a/include/common.h +++ b/include/common.h @@ -149,8 +149,8 @@ void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, #ifdef __linux__ /* Nyx helper functions to create and remove tmp workdirs */ -char* create_nyx_tmp_workdir(void); -void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path); +char *create_nyx_tmp_workdir(void); +void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path); #endif #endif diff --git a/include/forkserver.h b/include/forkserver.h index ba280d38..f5069ce2 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -52,20 +52,25 @@ typedef enum NyxReturnValue { } NyxReturnValue; typedef enum NyxProcessRole { + StandAlone, Parent, Child, + } NyxProcessRole; typedef struct { void *(*nyx_config_load)(const char *sharedir); void (*nyx_config_set_workdir_path)(void *config, const char *workdir); - void (*nyx_config_set_input_buffer_size)(void *config, uint32_t input_buffer_size); - void (*nyx_config_set_input_buffer_write_protection)(void *config, bool input_buffer_write_protection); + void (*nyx_config_set_input_buffer_size)(void *config, + uint32_t input_buffer_size); + void (*nyx_config_set_input_buffer_write_protection)( + void *config, bool input_buffer_write_protection); void (*nyx_config_set_hprintf_fd)(void *config, int32_t hprintf_fd); void (*nyx_config_set_process_role)(void *config, enum NyxProcessRole role); - void (*nyx_config_set_reuse_snapshot_path)(void *config, const char *reuse_snapshot_path); + void (*nyx_config_set_reuse_snapshot_path)(void *config, + const char *reuse_snapshot_path); void *(*nyx_new)(void *config, uint32_t worker_id); void (*nyx_shutdown)(void *qemu_process); @@ -191,7 +196,7 @@ typedef struct afl_forkserver { u32 nyx_bind_cpu_id; /* nyx runner cpu id */ char *nyx_aux_string; bool nyx_use_tmp_workdir; - char *nyx_tmp_workdir_path; + char *nyx_tmp_workdir_path; #endif } afl_forkserver_t; diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 0a4e7fb5..5b122741 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -815,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_init(&fsrv); - while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXh")) > 0) { + while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXYh")) > 0) { switch (opt) { @@ -966,8 +966,9 @@ int main(int argc, char **argv_orig, char **envp) { fsrv.mem_limit = mem_limit; break; - - #ifdef __linux__ + + case 'Y': // fallthough +#ifdef __linux__ case 'X': /* NYX mode */ if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } @@ -977,11 +978,11 @@ int main(int argc, char **argv_orig, char **envp) { fsrv.nyx_standalone = true; break; - #else +#else case 'X': FATAL("Nyx mode is only availabe on linux..."); break; - #endif +#endif case 'h': usage(argv[0]); @@ -1015,12 +1016,16 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(argv); #ifdef __linux__ - if(!fsrv.nyx_mode){ + if (!fsrv.nyx_mode) { + fsrv.target_path = find_binary(argv[optind]); - } - else{ + + } else { + fsrv.target_path = ck_strdup(argv[optind]); + } + #else fsrv.target_path = find_binary(argv[optind]); #endif @@ -1048,6 +1053,7 @@ int main(int argc, char **argv_orig, char **envp) { use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind); #ifdef __linux__ + } else if (fsrv.nyx_mode) { fsrv.nyx_id = 0; @@ -1055,7 +1061,9 @@ int main(int argc, char **argv_orig, char **envp) { u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); if (fsrv.nyx_handlers == NULL) { + FATAL("failed to initialize libnyx.so..."); + } fsrv.nyx_use_tmp_workdir = true; @@ -1090,9 +1098,7 @@ int main(int argc, char **argv_orig, char **envp) { read_initial_file(); #ifdef __linux__ - if(!fsrv.nyx_mode){ - (void)check_binary_signatures(fsrv.target_path); - } + if (!fsrv.nyx_mode) { (void)check_binary_signatures(fsrv.target_path); } #else (void)check_binary_signatures(fsrv.target_path); #endif @@ -1119,7 +1125,6 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); - afl_shm_deinit(&shm); afl_fsrv_deinit(&fsrv); if (fsrv.target_path) { ck_free(fsrv.target_path); } diff --git a/src/afl-common.c b/src/afl-common.c index 5692e277..a5c48e80 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1365,36 +1365,46 @@ s32 create_file(u8 *fn) { * etc.). This helper function basically creates both a path to a tmp workdir * and the workdir itself. If the environment variable TMPDIR is set, we use * that as the base directory, otherwise we use /tmp. */ -char* create_nyx_tmp_workdir(void) { +char *create_nyx_tmp_workdir(void) { char *tmpdir = getenv("TMPDIR"); if (!tmpdir) { tmpdir = "/tmp"; } - char* nyx_out_dir_path = alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid()); + char *nyx_out_dir_path = + alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid()); - if (mkdir(nyx_out_dir_path, 0700)) { - PFATAL("Unable to create nyx workdir"); - } + if (mkdir(nyx_out_dir_path, 0700)) { PFATAL("Unable to create nyx workdir"); } return nyx_out_dir_path; + } /* Vice versa, we remove the tmp workdir for nyx with this helper function. */ -void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) { - char* workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path); +void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path) { + + char *workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path); if (access(workdir_path, R_OK) == 0) { - if(fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) { + + if (fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) { + WARNF("Unable to remove nyx workdir (%s)", workdir_path); + } + } if (rmdir(nyx_out_dir_path)) { + WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path); + } ck_free(workdir_path); ck_free(nyx_out_dir_path); + } + #endif + diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index fd4e213d..aa8c8622 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -50,7 +50,7 @@ #include #ifdef __linux__ -#include + #include /* function to load nyx_helper function from libnyx.so */ @@ -66,22 +66,32 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { plugin->nyx_config_load = dlsym(handle, "nyx_config_load"); if (plugin->nyx_config_load == NULL) { goto fail; } - plugin->nyx_config_set_workdir_path = dlsym(handle, "nyx_config_set_workdir_path"); + plugin->nyx_config_set_workdir_path = + dlsym(handle, "nyx_config_set_workdir_path"); if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; } - plugin->nyx_config_set_input_buffer_size = dlsym(handle, "nyx_config_set_input_buffer_size"); + plugin->nyx_config_set_input_buffer_size = + dlsym(handle, "nyx_config_set_input_buffer_size"); if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; } - plugin->nyx_config_set_input_buffer_write_protection = dlsym(handle, "nyx_config_set_input_buffer_write_protection"); - if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { goto fail; } + plugin->nyx_config_set_input_buffer_write_protection = + dlsym(handle, "nyx_config_set_input_buffer_write_protection"); + if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { - plugin->nyx_config_set_hprintf_fd = dlsym(handle, "nyx_config_set_hprintf_fd"); + goto fail; + + } + + plugin->nyx_config_set_hprintf_fd = + dlsym(handle, "nyx_config_set_hprintf_fd"); if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; } - plugin->nyx_config_set_process_role = dlsym(handle, "nyx_config_set_process_role"); + plugin->nyx_config_set_process_role = + dlsym(handle, "nyx_config_set_process_role"); if (plugin->nyx_config_set_process_role == NULL) { goto fail; } - plugin->nyx_config_set_reuse_snapshot_path = dlsym(handle, "nyx_config_set_reuse_snapshot_path"); + plugin->nyx_config_set_reuse_snapshot_path = + dlsym(handle, "nyx_config_set_reuse_snapshot_path"); if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; } plugin->nyx_new = dlsym(handle, "nyx_new"); @@ -119,7 +129,6 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir"); if (plugin->nyx_remove_work_dir == NULL) { goto fail; } - OKF("libnyx plugin is ready!"); return plugin; @@ -131,33 +140,40 @@ fail: } -void afl_nyx_runner_kill(afl_forkserver_t *fsrv){ +void afl_nyx_runner_kill(afl_forkserver_t *fsrv) { + if (fsrv->nyx_mode) { - if (fsrv->nyx_aux_string){ - ck_free(fsrv->nyx_aux_string); - } + if (fsrv->nyx_aux_string) { ck_free(fsrv->nyx_aux_string); } /* check if we actually got a valid nyx runner */ if (fsrv->nyx_runner) { + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } /* if we have use a tmp work dir we need to remove it */ if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) { + remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path); + } + } + } -/* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp - * files) before exiting. Used before "afl_fsrv_killall()" is registered as - * an atexit() handler. */ -#define NYX_PRE_FATAL(fsrv, x...) \ - do { \ - afl_nyx_runner_kill(fsrv); \ - FATAL(x); \ - } while (0) + /* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp + * files) before exiting. Used before "afl_fsrv_killall()" is registered as + * an atexit() handler. */ + #define NYX_PRE_FATAL(fsrv, x...) \ + do { \ + \ + afl_nyx_runner_kill(fsrv); \ + FATAL(x); \ + \ + } while (0) #endif @@ -511,70 +527,116 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) { ACTF("Spinning up the NYX backend..."); } - if (fsrv->nyx_use_tmp_workdir){ + if (fsrv->nyx_use_tmp_workdir) { + fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir(); fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path; + } else { - if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); } + + if (fsrv->out_dir_path == NULL) { + + NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); + + } + } /* libnyx expects an absolute path */ - char* outdir_path_absolute = realpath(fsrv->out_dir_path, NULL); - if (outdir_path_absolute == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); } + char *outdir_path_absolute = realpath(fsrv->out_dir_path, NULL); + if (outdir_path_absolute == NULL) { + + NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); + + } char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute); - if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); } + if (fsrv->nyx_id == 0xFFFFFFFF) { + + NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); - if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) { - NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set..."); } - void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); + if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) { + + NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set..."); + + } + + void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path); fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE); - fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true); + fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, + true); if (fsrv->nyx_standalone) { + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone); + } else { + if (fsrv->nyx_parent) { + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent); + } else { + fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child); + } + } - if (getenv("NYX_REUSE_SNAPSHOT") != NULL){ + if (getenv("NYX_REUSE_SNAPSHOT") != NULL) { if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) { + NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist"); + } - /* stupid sanity check to avoid passing an empty or invalid snapshot directory */ - char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT")); + /* stupid sanity check to avoid passing an empty or invalid snapshot + * directory */ + char *snapshot_file_path = + alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT")); if (access(snapshot_file_path, R_OK) == -1) { - NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); + + NYX_PRE_FATAL( + fsrv, + "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot"); + } + ck_free(snapshot_file_path); /* another sanity check to avoid passing a snapshot directory that is - * located in the current workdir (the workdir will be wiped by libnyx on startup) */ - char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute); - char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL); + * located in the current workdir (the workdir will be wiped by libnyx on + * startup) */ + char *workdir_snapshot_path = + alloc_printf("%s/workdir/snapshot", outdir_path_absolute); + char *reuse_snapshot_path_real = + realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL); + + if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) { + + NYX_PRE_FATAL(fsrv, + "NYX_REUSE_SNAPSHOT path is located in current workdir " + "(use another output directory)"); - if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){ - NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path is located in current workdir (use another output directory)"); } ck_free(reuse_snapshot_path_real); ck_free(workdir_snapshot_path); - fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT")); + fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path( + nyx_config, getenv("NYX_REUSE_SNAPSHOT")); + } - fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); + fsrv->nyx_runner = + fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id); ck_free(workdir_path); ck_free(outdir_path_absolute); @@ -621,7 +683,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* autodict in Nyx mode */ if (!ignore_autodict) { - char* x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path); + char *x = + alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path); int nyx_autodict_fd = open(x, O_RDONLY); ck_free(x); @@ -634,8 +697,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, u8 *dict = ck_alloc(f_len); if (dict == NULL) { - NYX_PRE_FATAL(fsrv, "Could not allocate %u bytes of autodictionary memory", - f_len); + NYX_PRE_FATAL( + fsrv, "Could not allocate %u bytes of autodictionary memory", + f_len); } @@ -652,7 +716,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } else { - NYX_PRE_FATAL(fsrv, + NYX_PRE_FATAL( + fsrv, "Reading autodictionary fail at position %u with %u bytes " "left.", offset, len); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 832730fd..df030672 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -444,8 +444,11 @@ static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) { FSRV_RUN_ERROR) { FATAL("Error running target in Nyx mode"); + } + } + #endif /* Execute target application. */ @@ -890,7 +893,7 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = true; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshX")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) { switch (opt) { @@ -1078,7 +1081,8 @@ int main(int argc, char **argv_orig, char **envp) { break; - #ifdef __linux__ + case 'Y': // fallthough +#ifdef __linux__ case 'X': /* NYX mode */ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); } @@ -1088,11 +1092,11 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->nyx_standalone = true; break; - #else +#else case 'X': FATAL("Nyx mode is only availabe on linux..."); break; - #endif +#endif case 'b': @@ -1166,12 +1170,16 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv, argv); #ifdef __linux__ - if(!fsrv->nyx_mode){ + if (!fsrv->nyx_mode) { + fsrv->target_path = find_binary(argv[optind]); - } - else{ + + } else { + fsrv->target_path = ck_strdup(argv[optind]); + } + #else fsrv->target_path = find_binary(argv[optind]); #endif @@ -1232,11 +1240,12 @@ int main(int argc, char **argv_orig, char **envp) { get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); #ifdef __linux__ + } else if (fsrv->nyx_mode) { use_argv = ck_alloc(sizeof(char *) * (1)); use_argv[0] = argv[0]; - + fsrv->nyx_id = 0; u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so"); @@ -1288,9 +1297,12 @@ int main(int argc, char **argv_orig, char **envp) { } #ifdef __linux__ - if(!fsrv->nyx_mode && in_dir){ + if (!fsrv->nyx_mode && in_dir) { + (void)check_binary_signatures(fsrv->target_path); + } + #else if (in_dir) { (void)check_binary_signatures(fsrv->target_path); } #endif @@ -1313,14 +1325,14 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz = map + sizeof(u32); - configure_afl_kill_signals( - fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode - #ifdef __linux__ - || fsrv->nyx_mode - #endif - ) - ? SIGKILL - : SIGTERM); + configure_afl_kill_signals(fsrv, NULL, NULL, + (fsrv->qemu_mode || unicorn_mode +#ifdef __linux__ + || fsrv->nyx_mode +#endif + ) + ? SIGKILL + : SIGTERM); if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) { @@ -1464,13 +1476,18 @@ int main(int argc, char **argv_orig, char **envp) { shm_fuzz = deinit_shmem(fsrv, shm_fuzz); #ifdef __linux__ - if(!fsrv->nyx_mode){ + if (!fsrv->nyx_mode) { + #endif showmap_run_target(fsrv, use_argv); #ifdef __linux__ + } else { + showmap_run_target_nyx_mode(fsrv); + } + #endif tcnt = write_results_to_file(fsrv, out_file); if (!quiet_mode) { @@ -1522,7 +1539,6 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->target_path) { ck_free(fsrv->target_path); } - afl_fsrv_deinit(fsrv); if (stdin_file) { ck_free(stdin_file); } diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 98403049..e7442d1d 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -846,7 +846,7 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXHh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) { switch (opt) { @@ -1004,7 +1004,8 @@ int main(int argc, char **argv_orig, char **envp) { break; - #ifdef __linux__ + case 'Y': // fallthough +#ifdef __linux__ case 'X': /* NYX mode */ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); } @@ -1014,11 +1015,11 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->nyx_standalone = true; break; - #else +#else case 'X': FATAL("Nyx mode is only availabe on linux..."); break; - #endif +#endif case 'H': /* Hang Mode */ @@ -1086,12 +1087,16 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv, argv); #ifdef __linux__ - if(!fsrv->nyx_mode){ + if (!fsrv->nyx_mode) { + fsrv->target_path = find_binary(argv[optind]); - } - else{ + + } else { + fsrv->target_path = ck_strdup(argv[optind]); + } + #else fsrv->target_path = find_binary(argv[optind]); #endif @@ -1120,6 +1125,7 @@ int main(int argc, char **argv_orig, char **envp) { get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); #ifdef __linux__ + } else if (fsrv->nyx_mode) { fsrv->nyx_id = 0; @@ -1127,7 +1133,9 @@ int main(int argc, char **argv_orig, char **envp) { u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); if (fsrv->nyx_handlers == NULL) { + FATAL("failed to initialize libnyx.so..."); + } fsrv->nyx_use_tmp_workdir = true; @@ -1207,9 +1215,7 @@ int main(int argc, char **argv_orig, char **envp) { read_initial_file(); #ifdef __linux__ - if(!fsrv->nyx_mode){ - (void)check_binary_signatures(fsrv->target_path); - } + if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); } #else (void)check_binary_signatures(fsrv->target_path); #endif @@ -1316,7 +1322,6 @@ int main(int argc, char **argv_orig, char **envp) { OKF("We're done here. Have a nice day!\n"); - remove_shm = 0; afl_shm_deinit(&shm); if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 34294809..4e8f466d 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -78,10 +78,10 @@ extern unsigned int __afl_map_size; on the other hand this is what Google needs to make LLVMFuzzerRunDriver() work. Choose your poison Google! */ /*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data, - size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -__attribute__((weak)) int LLVMFuzzerRunDriver( - int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size)); + size_t Size); +__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); +__attribute__((weak)) int LLVMFuzzerRunDriver( + int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size)); // Default nop ASan hooks for manual poisoning when not linking the ASan // runtime @@ -268,15 +268,16 @@ static int ExecuteFilesOnyByOne(int argc, char **argv, __attribute__((weak)) int main(int argc, char **argv) { -// Enable if LLVMFuzzerTestOneInput() has the weak attribute -/* - if (!LLVMFuzzerTestOneInput) { + // Enable if LLVMFuzzerTestOneInput() has the weak attribute + /* + if (!LLVMFuzzerTestOneInput) { - fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n"); - abort(); + fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n"); + abort(); - } -*/ + } + + */ if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) printf( From 4d29e484b7b2fcc4ff25774888c8fcbd1a1618c1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 16 Apr 2023 18:47:50 +0200 Subject: [PATCH 264/300] update nyx readme --- nyx_mode/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nyx_mode/README.md b/nyx_mode/README.md index 878b2acf..eee7d363 100644 --- a/nyx_mode/README.md +++ b/nyx_mode/README.md @@ -15,6 +15,7 @@ Underneath it is built upon KVM and QEMU and requires a modern Linux kernel requires an Intel processor (6th generation onwards) and a special 5.10 kernel (see [KVM-Nyx](https://github.com/nyx-fuzz/KVM-Nyx)). + ## Building Nyx mode 1. Install all the packages from [docs/INSTALL.md](../docs/INSTALL.md). @@ -41,6 +42,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel 5. Optionally, for binary-only fuzzing: set up the required 5.10 kernel, see [KVM-Nyx](https://github.com/nyx-fuzz/KVM-Nyx). + ## Preparing to fuzz a target with Nyx mode For source instrumented fuzzing you can use any afl-cc mode, with LTO even @@ -68,12 +70,21 @@ This will create a directory with all necessary files and the Nyx configuration. The name of the directory will be whatever you choose for `PACKAGE-DIRECTORY` above. -In the final step for the packaging we generate the Nyx configuration: +Note that if the target reads from a file then use the `-file /path/to/file` +parameter to the above command. + +Note that Nyx does **not** support the afl `@@` argument. Instead pass +something like `-file /foo.file -args "--file /foo.file --other-args"` to +the above command. + + +Then the final step: we generate the Nyx package configuration: ```shell python3 nyx_mode/packer/packer/nyx_config_gen.py PACKAGE-DIRECTORY Kernel ``` + ## Fuzzing with Nyx mode All the hard parts are done, fuzzing with Nyx mode is easy - just supply the @@ -114,6 +125,7 @@ afl-fuzz -i in -o out -Y -S 1 -- ./PACKAGE-DIRECTORY afl-fuzz -i in -o out -Y -S 2 -- ./PACKAGE-DIRECTORY ``` + ## AFL++ companion tools (afl-showmap etc.) AFL++ companion tools support Nyx mode and can be used to analyze or minimize one specific input or an entire output corpus. These tools work similarly to `afl-fuzz`. @@ -146,6 +158,7 @@ afl-fuzz -i ./in_dir -o ./out_dir -Y -M 0 ./PACKAGE-DIRECTORY NYX_REUSE_SNAPSHOT=./out_dir/workdir/snapshot/ afl-analyze -i in_file -X -- ./PACKAGE-DIRECTORY ``` + ## Real-world examples ### Fuzzing libxml2 with AFL++ in Nyx-mode From 7f734c96d187312868178e8ead95dc103c557c1f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 Apr 2023 10:25:10 +0200 Subject: [PATCH 265/300] v4.06c release --- README.md | 4 ++-- docs/Changelog.md | 5 +++-- include/config.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 821b8cb7..c012c400 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.05c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.06c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.06a +GitHub version: 4.07a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 3337feb9..587fb64c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,7 +3,7 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. -### Version ++4.06a (dev) +### Version ++4.06c (release) - afl-fuzz: - ensure temporary file descriptor is closed when not used - added `AFL_NO_WARN_INSTABILITY` @@ -29,9 +29,10 @@ - fix issue on MacOS - unicorn_mode: - updated and minor issues fixed + - nyx_mode support for all tools + - better sanitizer default options support for all tools - new custom module: autotoken, a grammar free fuzzer for text inputs - fixed custom mutator C examples - - better sanitizer default options support for all tools - more minor fixes and cross-platform support ### Version ++4.05c (release) diff --git a/include/config.h b/include/config.h index e46f515a..b6249a0f 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.06a" +#define VERSION "++4.06c" /****************************************************** * * From 02b9e583f2a5dd7d83bd4c02af8d2081532689ed Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 17 Apr 2023 14:41:05 +0200 Subject: [PATCH 266/300] v4.07a init --- docs/Changelog.md | 4 ++++ include/config.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 587fb64c..30e76f2c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,10 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. +### Version ++4.07a (dev) + - soon :) + + ### Version ++4.06c (release) - afl-fuzz: - ensure temporary file descriptor is closed when not used diff --git a/include/config.h b/include/config.h index b6249a0f..764c29dc 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.06c" +#define VERSION "++4.07a" /****************************************************** * * From 70e30958649f44e104330431cde31e80fbd8557f Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 267/300] added first dummy atnwalk.c file --- custom_mutators/atnwalk/atnwalk.c | 173 ++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 custom_mutators/atnwalk/atnwalk.c diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c new file mode 100644 index 00000000..483ae542 --- /dev/null +++ b/custom_mutators/atnwalk/atnwalk.c @@ -0,0 +1,173 @@ +#include "../../include/afl-fuzz.h" + +#include +#include +#include +#include +#include +#include + + +#define INIT_BUF_SIZE 4096 +#define SOCKET_NAME "/tmp/atnwalk.socket" + +// handshake constants +const uint8_t SERVER_ARE_YOU_ALIVE = 42; +const uint8_t SERVER_YES_I_AM_ALIVE = 213; + +// control bits +const uint8_t SERVER_DECODE_BIT = 0b00000001; +const uint8_t SERVER_ENCODE_BIT = 0b00000010; +const uint8_t SERVER_MUTATE_BIT = 0b00000100; +const uint8_t SERVER_CROSSOVER_BIT = 0b00001000; + + +typedef struct atnwalk_mutator { + uint8_t *decoded_buf; + size_t decoded_size; +} atnwalk_mutator_t; + + +int read_all(int fd, uint8_t *buf, size_t buf_size) { + int n; + size_t offset = 0; + while (offset < buf_size) { + n = read(fd, buf + offset, buf_size - offset); + if (n == -1) { + return 0; + } + offset += n; + } + return 1; +} + + +int write_all(int fd, uint8_t *buf, size_t buf_size) { + int n; + size_t offset = 0; + while (offset < buf_size) { + n = write(fd, buf + offset, buf_size - offset); + if (n == -1) { + return 0; + } + offset += n; + } + return 1; +} + + +/** + * Initialize this custom mutator + * + * @param[in] afl a pointer to the internal state object. Can be ignored for + * now. + * @param[in] seed A seed for this mutator - the same seed should always mutate + * in the same way. + * @return Pointer to the data object this custom mutator instance should use. + * There may be multiple instances of this mutator in one afl-fuzz run! + * Return NULL on error. + */ +atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { + srand(seed); + atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t)); + if (!data) { + perror("afl_custom_init alloc"); + return NULL; + } + data->decoded_buf = (uint8_t *) malloc(INIT_BUF_SIZE); + data->decoded_size = INIT_BUF_SIZE; + return data; +} + +// TODO: implement +/** + * Perform custom mutations on a given input + * + * (Optional for now. Required in the future) + * + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Pointer to input data to be mutated + * @param[in] buf_size Size of input data + * @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on + * error. + * @param[in] add_buf Buffer containing the additional test case + * @param[in] add_buf_size Size of the additional test case + * @param[in] max_size Maximum size of the mutated output. The mutation must not + * produce data larger than max_size. + * @return Size of the mutated output. + */ +size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf, + uint8_t *add_buf, size_t add_buf_size, size_t max_size) { + struct sockaddr_un addr; + int fd_socket; + ssize_t n; + uint8_t buffer[5]; + + // initialize the socket + fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd_socket == -1) { + perror("socket"); + *out_buf = NULL; + return 0; + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); + if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { + perror("atnwalk server is down"); + *out_buf = NULL; + return 0; + } + + if (!write_all(fd_socket, buffer, 5)) { + perror("write to atnwalk server failed"); + *out_buf = NULL; + return 0; + } + + if (read_all(fd_socket, buffer, 5)) { + perror("read to atnwalk server failed"); + exit(EXIT_FAILURE); + } + + close(fd_socket); +} + +// TODO: implement +/** + * A post-processing function to use right before AFL writes the test case to + * disk in order to execute the target. + * + * (Optional) If this functionality is not needed, simply don't define this + * function. + * + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Buffer containing the test case to be executed + * @param[in] buf_size Size of the test case + * @param[out] out_buf Pointer to the buffer containing the test case after + * processing. External library should allocate memory for out_buf. + * The buf pointer may be reused (up to the given buf_size); + * @return Size of the output buffer after processing or the needed amount. + * A return of 0 indicates an error. + */ +size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { + data->decoded_buf[0] = 'p'; + data->decoded_buf[1] = 'u'; + data->decoded_buf[2] = 't'; + data->decoded_buf[3] = 's'; + data->decoded_buf[4] = ' '; + data->decoded_buf[5] = ';'; + data->decoded_buf[6] = '\n'; + return 7; +} + +// TODO: implement +/** + * Deinitialize everything + * + * @param data The data ptr from afl_custom_init + */ +void afl_custom_deinit(atnwalk_mutator_t *data) { + free(data->decoded_buf); + free(data); +} From a3bc8d3440acefb7168c849337e4a4841bf11c3d Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 268/300] fixed wrong implementation of control bits in atnwalk.c --- custom_mutators/atnwalk/atnwalk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index 483ae542..cc9f9618 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -16,10 +16,10 @@ const uint8_t SERVER_ARE_YOU_ALIVE = 42; const uint8_t SERVER_YES_I_AM_ALIVE = 213; // control bits -const uint8_t SERVER_DECODE_BIT = 0b00000001; -const uint8_t SERVER_ENCODE_BIT = 0b00000010; -const uint8_t SERVER_MUTATE_BIT = 0b00000100; -const uint8_t SERVER_CROSSOVER_BIT = 0b00001000; +const uint8_t SERVER_CROSSOVER_BIT = 0b00000001; +const uint8_t SERVER_MUTATE_BIT = 0b00000010; +const uint8_t SERVER_DECODE_BIT = 0b00000100; +const uint8_t SERVER_ENCODE_BIT = 0b00001000; typedef struct atnwalk_mutator { From 450dbae8cd2ae278e0b381d172cb7694f40278cb Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 269/300] first version with unix domain sockets is ready for testing --- custom_mutators/atnwalk/atnwalk.c | 254 ++++++++++++++++++++++++++---- src/afl-fuzz-run.c | 11 +- 2 files changed, 232 insertions(+), 33 deletions(-) diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index cc9f9618..584add61 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -1,5 +1,4 @@ -#include "../../include/afl-fuzz.h" - +#include #include #include #include @@ -7,10 +6,10 @@ #include #include - #define INIT_BUF_SIZE 4096 #define SOCKET_NAME "/tmp/atnwalk.socket" + // handshake constants const uint8_t SERVER_ARE_YOU_ALIVE = 42; const uint8_t SERVER_YES_I_AM_ALIVE = 213; @@ -23,8 +22,10 @@ const uint8_t SERVER_ENCODE_BIT = 0b00001000; typedef struct atnwalk_mutator { - uint8_t *decoded_buf; - size_t decoded_size; + uint8_t *fuzz_buf; + size_t fuzz_size; + uint8_t *post_process_buf; + size_t post_process_size; } atnwalk_mutator_t; @@ -55,6 +56,32 @@ int write_all(int fd, uint8_t *buf, size_t buf_size) { return 1; } +void put_uint32(uint8_t *buf, uint32_t val) { + buf[0] = (uint8_t) (val >> 24); + buf[1] = (uint8_t) ((val & 0x00ff0000) >> 16); + buf[2] = (uint8_t) ((val & 0x0000ff00) >> 8); + buf[3] = (uint8_t) (val & 0x000000ff); +} + +uint32_t to_uint32(uint8_t *buf) { + uint32_t val = 0; + val |= (((uint32_t) buf[0]) << 24); + val |= (((uint32_t) buf[1]) << 16); + val |= (((uint32_t) buf[2]) << 8); + val |= ((uint32_t) buf[3]); + return val; +} + +void put_uint64(uint8_t *buf, uint64_t val) { + buf[0] = (uint8_t) (val >> 56); + buf[1] = (uint8_t) ((val & 0x00ff000000000000) >> 48); + buf[2] = (uint8_t) ((val & 0x0000ff0000000000) >> 40); + buf[3] = (uint8_t) ((val & 0x000000ff00000000) >> 32); + buf[4] = (uint8_t) ((val & 0x00000000ff000000) >> 24); + buf[5] = (uint8_t) ((val & 0x0000000000ff0000) >> 16); + buf[6] = (uint8_t) ((val & 0x000000000000ff00) >> 8); + buf[7] = (uint8_t) (val & 0x00000000000000ff); +} /** * Initialize this custom mutator @@ -67,19 +94,21 @@ int write_all(int fd, uint8_t *buf, size_t buf_size) { * There may be multiple instances of this mutator in one afl-fuzz run! * Return NULL on error. */ -atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { +atnwalk_mutator_t *afl_custom_init(void *afl, unsigned int seed) { srand(seed); atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t)); if (!data) { perror("afl_custom_init alloc"); return NULL; } - data->decoded_buf = (uint8_t *) malloc(INIT_BUF_SIZE); - data->decoded_size = INIT_BUF_SIZE; + data->fuzz_buf = (uint8_t *) malloc(INIT_BUF_SIZE); + data->fuzz_size = INIT_BUF_SIZE; + data->post_process_buf = (uint8_t *) malloc(INIT_BUF_SIZE); + data->post_process_size = INIT_BUF_SIZE; return data; } -// TODO: implement + /** * Perform custom mutations on a given input * @@ -100,13 +129,12 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u uint8_t *add_buf, size_t add_buf_size, size_t max_size) { struct sockaddr_un addr; int fd_socket; - ssize_t n; - uint8_t buffer[5]; + uint8_t ctrl_buf[8]; + uint8_t wanted; // initialize the socket fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); if (fd_socket == -1) { - perror("socket"); *out_buf = NULL; return 0; } @@ -114,26 +142,127 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { - perror("atnwalk server is down"); + close(fd_socket); *out_buf = NULL; return 0; } - if (!write_all(fd_socket, buffer, 5)) { - perror("write to atnwalk server failed"); + // TODO: how to set connection deadline? maybe not required if server already closes the connection? + + // TODO: there should be some kind of loop retrying with different seeds and ultimately giving up on that input? + // maybe this is not necessary, because we may also just return a single byte in case of failure? + + // ask whether the server is alive + ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; + if (!write_all(fd_socket, ctrl_buf, 1)) { + close(fd_socket); *out_buf = NULL; return 0; } - if (read_all(fd_socket, buffer, 5)) { - perror("read to atnwalk server failed"); - exit(EXIT_FAILURE); + // see whether the server replies as expected + if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // tell the server what we want to do + wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT; + + // 50% chance to perform a crossover if there is an additional buffer available + if ((add_buf_size > 0) && (rand() % 2)) { + wanted |= SERVER_CROSSOVER_BIT; + } + + // tell the server what we want and how much data will be sent + ctrl_buf[0] = wanted; + put_uint32(ctrl_buf + 1, (uint32_t) buf_size); + if (!write_all(fd_socket, ctrl_buf, 5)) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // send the data to mutate and encode + if (!write_all(fd_socket, buf, buf_size)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + if (wanted & SERVER_CROSSOVER_BIT) { + // since we requested crossover, we will first tell how much additional data is to be expected + put_uint32(ctrl_buf, (uint32_t) add_buf_size); + if (!write_all(fd_socket, ctrl_buf, 4)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + // send the additional data for crossover + if (!write_all(fd_socket, add_buf, add_buf_size)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + // lastly, a seed is required for crossover so send one + put_uint64(ctrl_buf, (uint64_t) rand()); + if (!write_all(fd_socket, ctrl_buf, 8)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + } + + // since we requested mutation, we need to provide a seed for that + put_uint64(ctrl_buf, (uint64_t) rand()); + if (!write_all(fd_socket, ctrl_buf, 8)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + // obtain the required buffer size for the data that will be returned + if (!read_all(fd_socket, ctrl_buf, 4)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + size_t new_size = (size_t) to_uint32(ctrl_buf); + + // if the data is too large then we ignore this round + if (new_size > max_size) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + if (new_size > buf_size) { + // buf is too small, need to use data->fuzz_buf, let's see whether we need to reallocate + if (new_size > data->fuzz_size) { + data->fuzz_size = new_size << 1; + data->fuzz_buf = (uint8_t *) realloc(data->fuzz_buf, data->fuzz_size); + } + *out_buf = data->fuzz_buf; + } else { + // new_size fits into buf, so re-use it + *out_buf = buf; + } + + // obtain the encoded data + if (!read_all(fd_socket, *out_buf, new_size)) { + close(fd_socket); + *out_buf = buf; + return buf_size; } close(fd_socket); + return new_size; } -// TODO: implement + /** * A post-processing function to use right before AFL writes the test case to * disk in order to execute the target. @@ -151,23 +280,90 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u * A return of 0 indicates an error. */ size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { - data->decoded_buf[0] = 'p'; - data->decoded_buf[1] = 'u'; - data->decoded_buf[2] = 't'; - data->decoded_buf[3] = 's'; - data->decoded_buf[4] = ' '; - data->decoded_buf[5] = ';'; - data->decoded_buf[6] = '\n'; - return 7; + struct sockaddr_un addr; + int fd_socket; + uint8_t ctrl_buf[8]; + + // initialize the socket + fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd_socket == -1) { + *out_buf = NULL; + return 0; + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); + if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // ask whether the server is alive + ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; + if (!write_all(fd_socket, ctrl_buf, 1)) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // see whether the server replies as expected + if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // tell the server what we want and how much data will be sent + ctrl_buf[0] = SERVER_DECODE_BIT; + put_uint32(ctrl_buf + 1, (uint32_t) buf_size); + if (!write_all(fd_socket, ctrl_buf, 5)) { + close(fd_socket); + *out_buf = NULL; + return 0; + } + + // send the data to decode + if (!write_all(fd_socket, buf, buf_size)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + // obtain the required buffer size for the data that will be returned + if (!read_all(fd_socket, ctrl_buf, 4)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + size_t new_size = (size_t) to_uint32(ctrl_buf); + + // need to use data->post_process_buf, let's see whether we need to reallocate + if (new_size > data->post_process_size) { + data->post_process_size = new_size << 1; + data->post_process_buf = (uint8_t *) realloc(data->post_process_buf, data->post_process_size); + } + *out_buf = data->post_process_buf; + + // obtain the decoded data + if (!read_all(fd_socket, *out_buf, new_size)) { + close(fd_socket); + *out_buf = buf; + return buf_size; + } + + close(fd_socket); + return new_size; } -// TODO: implement + /** * Deinitialize everything * * @param data The data ptr from afl_custom_init */ void afl_custom_deinit(atnwalk_mutator_t *data) { - free(data->decoded_buf); + free(data->fuzz_buf); + free(data->post_process_buf); free(data); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ee4a3298..26a1ea36 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -130,12 +130,15 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { new_size = afl->max_length; } - - if (new_mem != *mem) { *mem = new_mem; } + // TODO: think about how to enable the change without breaking other implementations + // if (new_mem != *mem) { *mem = new_mem; } /* everything as planned. use the potentially new data. */ - afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size); - len = new_size; + // TODO: think about how to enable the change without breaking other implementations + afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); + + // TODO: think about how to enable the change without breaking other implementations + // len = new_size; } else { From e55b5c54080698ee2efe317321c1f387c225115b Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 270/300] fixed the server handshake commands, works now --- custom_mutators/atnwalk/atnwalk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index 584add61..387d8b5d 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -11,8 +11,8 @@ // handshake constants -const uint8_t SERVER_ARE_YOU_ALIVE = 42; -const uint8_t SERVER_YES_I_AM_ALIVE = 213; +const uint8_t SERVER_ARE_YOU_ALIVE = 213; +const uint8_t SERVER_YES_I_AM_ALIVE = 42; // control bits const uint8_t SERVER_CROSSOVER_BIT = 0b00000001; From 529a51c16053125ff0ddce7c6bd149f4ebe65461 Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 271/300] implemented status screen and 50% havoc and 50% splice schedule with limited rounds per queue entry --- custom_mutators/atnwalk/atnwalk.c | 137 +++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 13 deletions(-) diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index 387d8b5d..0194ff18 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -1,3 +1,5 @@ +#include "../../include/afl-fuzz.h" + #include #include #include @@ -6,9 +8,14 @@ #include #include -#define INIT_BUF_SIZE 4096 +#define BUF_SIZE_INIT 4096 #define SOCKET_NAME "/tmp/atnwalk.socket" +// how many errors (e.g. timeouts) to tolerate until moving on to the next queue entry +#define ATNWALK_ERRORS_MAX 1 + +// how many execution timeouts to tolerate until moving on to the next queue entry +#define EXEC_TIMEOUT_MAX 2 // handshake constants const uint8_t SERVER_ARE_YOU_ALIVE = 213; @@ -22,6 +29,14 @@ const uint8_t SERVER_ENCODE_BIT = 0b00001000; typedef struct atnwalk_mutator { + afl_state_t *afl; + uint8_t atnwalk_error_count; + uint64_t prev_timeouts; + uint32_t prev_hits; + uint32_t stage_havoc_cur; + uint32_t stage_havoc_max; + uint32_t stage_splice_cur; + uint32_t stage_splice_max; uint8_t *fuzz_buf; size_t fuzz_size; uint8_t *post_process_buf; @@ -56,6 +71,7 @@ int write_all(int fd, uint8_t *buf, size_t buf_size) { return 1; } + void put_uint32(uint8_t *buf, uint32_t val) { buf[0] = (uint8_t) (val >> 24); buf[1] = (uint8_t) ((val & 0x00ff0000) >> 16); @@ -63,6 +79,7 @@ void put_uint32(uint8_t *buf, uint32_t val) { buf[3] = (uint8_t) (val & 0x000000ff); } + uint32_t to_uint32(uint8_t *buf) { uint32_t val = 0; val |= (((uint32_t) buf[0]) << 24); @@ -72,6 +89,7 @@ uint32_t to_uint32(uint8_t *buf) { return val; } + void put_uint64(uint8_t *buf, uint64_t val) { buf[0] = (uint8_t) (val >> 56); buf[1] = (uint8_t) ((val & 0x00ff000000000000) >> 48); @@ -83,6 +101,7 @@ void put_uint64(uint8_t *buf, uint64_t val) { buf[7] = (uint8_t) (val & 0x00000000000000ff); } + /** * Initialize this custom mutator * @@ -94,21 +113,48 @@ void put_uint64(uint8_t *buf, uint64_t val) { * There may be multiple instances of this mutator in one afl-fuzz run! * Return NULL on error. */ -atnwalk_mutator_t *afl_custom_init(void *afl, unsigned int seed) { +atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { srand(seed); atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t)); if (!data) { perror("afl_custom_init alloc"); return NULL; } - data->fuzz_buf = (uint8_t *) malloc(INIT_BUF_SIZE); - data->fuzz_size = INIT_BUF_SIZE; - data->post_process_buf = (uint8_t *) malloc(INIT_BUF_SIZE); - data->post_process_size = INIT_BUF_SIZE; + data->afl = afl; + data->prev_hits = 0; + data->fuzz_buf = (uint8_t *) malloc(BUF_SIZE_INIT); + data->fuzz_size = BUF_SIZE_INIT; + data->post_process_buf = (uint8_t *) malloc(BUF_SIZE_INIT); + data->post_process_size = BUF_SIZE_INIT; return data; } +unsigned int afl_custom_fuzz_count(atnwalk_mutator_t *data, const unsigned char *buf, size_t buf_size) { + // afl_custom_fuzz_count is called exactly once before entering the 'stage-loop' for the current queue entry + // thus, we use it to reset the error count and to initialize stage variables (somewhat not intended by the API, + // but still better than rewriting the whole thing to have a custom mutator stage) + data->atnwalk_error_count = 0; + data->prev_timeouts = data->afl->total_tmouts; + + // it might happen that on the last execution of the splice stage a new path is found + // we need to fix that here and count it + if (data->prev_hits) { + data->afl->stage_finds[STAGE_SPLICE] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; + } + data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; + data->stage_havoc_cur = 0; + data->stage_splice_cur = 0; + + // 50% havoc, 50% splice + data->stage_havoc_max = data->afl->stage_max >> 1; + if (data->stage_havoc_max < HAVOC_MIN) { + data->stage_havoc_max = HAVOC_MIN; + } + data->stage_splice_max = data->stage_havoc_max; + return data->stage_havoc_max + data->stage_splice_max; +} + /** * Perform custom mutations on a given input * @@ -132,6 +178,48 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u uint8_t ctrl_buf[8]; uint8_t wanted; + // let's display what's going on in a nice way + if (data->stage_havoc_cur == 0) { + data->afl->stage_name = (uint8_t *) "atnwalk - havoc"; + } + if (data->stage_havoc_cur == data->stage_havoc_max) { + data->afl->stage_name = (uint8_t *) "atnwalk - splice"; + } + + // increase the respective havoc or splice counters + if (data->stage_havoc_cur < data->stage_havoc_max) { + data->stage_havoc_cur++; + data->afl->stage_cycles[STAGE_HAVOC]++; + } else { + // if there is nothing to splice, continue with havoc and skip splicing this time + if (data->afl->ready_for_splicing_count < 1) { + data->stage_havoc_max = data->afl->stage_max; + data->stage_havoc_cur++; + data->afl->stage_cycles[STAGE_HAVOC]++; + } else { + data->stage_splice_cur++; + data->afl->stage_cycles[STAGE_SPLICE]++; + } + } + + // keep track of found new corpus seeds per stage and run the stage twice as long as initially planned + if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) { + if (data->stage_splice_cur <= 1) { + data->afl->stage_finds[STAGE_HAVOC] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; + } else { + data->afl->stage_finds[STAGE_SPLICE] += + data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; + } + } + data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; + + // check whether this input produces a lot of timeouts, if it does then abandon this queue entry + if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) { + data->afl->stage_max = data->afl->stage_cur; + *out_buf = buf; + return buf_size; + } + // initialize the socket fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); if (fd_socket == -1) { @@ -147,11 +235,6 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u return 0; } - // TODO: how to set connection deadline? maybe not required if server already closes the connection? - - // TODO: there should be some kind of loop retrying with different seeds and ultimately giving up on that input? - // maybe this is not necessary, because we may also just return a single byte in case of failure? - // ask whether the server is alive ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; if (!write_all(fd_socket, ctrl_buf, 1)) { @@ -170,8 +253,8 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // tell the server what we want to do wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT; - // 50% chance to perform a crossover if there is an additional buffer available - if ((add_buf_size > 0) && (rand() % 2)) { + // perform a crossover if we are splicing + if (data->stage_splice_cur > 0) { wanted |= SERVER_CROSSOVER_BIT; } @@ -196,6 +279,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u put_uint32(ctrl_buf, (uint32_t) add_buf_size); if (!write_all(fd_socket, ctrl_buf, 4)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -203,6 +290,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // send the additional data for crossover if (!write_all(fd_socket, add_buf, add_buf_size)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -211,6 +302,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u put_uint64(ctrl_buf, (uint64_t) rand()); if (!write_all(fd_socket, ctrl_buf, 8)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -220,6 +315,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u put_uint64(ctrl_buf, (uint64_t) rand()); if (!write_all(fd_socket, ctrl_buf, 8)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -227,6 +326,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // obtain the required buffer size for the data that will be returned if (!read_all(fd_socket, ctrl_buf, 4)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -235,6 +338,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // if the data is too large then we ignore this round if (new_size > max_size) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } @@ -254,6 +361,10 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // obtain the encoded data if (!read_all(fd_socket, *out_buf, new_size)) { close(fd_socket); + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } *out_buf = buf; return buf_size; } From 9ab902402cd33156257fc0355c0105e7e03f5ba3 Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:09:48 +0200 Subject: [PATCH 272/300] fixed code clones in atnwalk.c, introduced new environment variable AFL_POST_PROCESS_KEEP_ORIGINAL in AFL++ to integrate atnwalk without re-compiling afl-fuzz --- custom_mutators/atnwalk/atnwalk.c | 144 ++++++++++-------------------- include/afl-fuzz.h | 4 +- include/envs.h | 1 + src/afl-fuzz-run.c | 11 +-- src/afl-fuzz-state.c | 7 ++ src/afl-fuzz.c | 2 + 6 files changed, 66 insertions(+), 103 deletions(-) diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index 0194ff18..901b8a9e 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -1,4 +1,4 @@ -#include "../../include/afl-fuzz.h" +#include "afl-fuzz.h" #include #include @@ -9,7 +9,7 @@ #include #define BUF_SIZE_INIT 4096 -#define SOCKET_NAME "/tmp/atnwalk.socket" +#define SOCKET_NAME "./atnwalk.socket" // how many errors (e.g. timeouts) to tolerate until moving on to the next queue entry #define ATNWALK_ERRORS_MAX 1 @@ -155,6 +155,29 @@ unsigned int afl_custom_fuzz_count(atnwalk_mutator_t *data, const unsigned char return data->stage_havoc_max + data->stage_splice_max; } + +size_t fail_fatal(int fd_socket, uint8_t **out_buf) { + if (fd_socket != -1) { + close(fd_socket); + } + *out_buf = NULL; + return 0; +} + + +size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { + if (fd_socket != -1) { + close(fd_socket); + } + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + data->afl->stage_max = data->afl->stage_cur; + } + *out_buf = buf; + return buf_size; +} + + /** * Perform custom mutations on a given input * @@ -202,7 +225,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u } } - // keep track of found new corpus seeds per stage and run the stage twice as long as initially planned + // keep track of found new corpus seeds per stage if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) { if (data->stage_splice_cur <= 1) { data->afl->stage_finds[STAGE_HAVOC] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; @@ -216,38 +239,28 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // check whether this input produces a lot of timeouts, if it does then abandon this queue entry if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) { data->afl->stage_max = data->afl->stage_cur; - *out_buf = buf; - return buf_size; + return fail_gracefully(-1, data, buf, buf_size, out_buf); } // initialize the socket fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd_socket == -1) { - *out_buf = NULL; - return 0; - } + if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // ask whether the server is alive ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; if (!write_all(fd_socket, ctrl_buf, 1)) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // see whether the server replies as expected if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // tell the server what we want to do @@ -262,88 +275,48 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u ctrl_buf[0] = wanted; put_uint32(ctrl_buf + 1, (uint32_t) buf_size); if (!write_all(fd_socket, ctrl_buf, 5)) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // send the data to mutate and encode if (!write_all(fd_socket, buf, buf_size)) { - close(fd_socket); - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } if (wanted & SERVER_CROSSOVER_BIT) { // since we requested crossover, we will first tell how much additional data is to be expected put_uint32(ctrl_buf, (uint32_t) add_buf_size); if (!write_all(fd_socket, ctrl_buf, 4)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } // send the additional data for crossover if (!write_all(fd_socket, add_buf, add_buf_size)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } // lastly, a seed is required for crossover so send one put_uint64(ctrl_buf, (uint64_t) rand()); if (!write_all(fd_socket, ctrl_buf, 8)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } } // since we requested mutation, we need to provide a seed for that put_uint64(ctrl_buf, (uint64_t) rand()); if (!write_all(fd_socket, ctrl_buf, 8)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } // obtain the required buffer size for the data that will be returned if (!read_all(fd_socket, ctrl_buf, 4)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } size_t new_size = (size_t) to_uint32(ctrl_buf); // if the data is too large then we ignore this round if (new_size > max_size) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } if (new_size > buf_size) { @@ -360,13 +333,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u // obtain the encoded data if (!read_all(fd_socket, *out_buf, new_size)) { - close(fd_socket); - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } close(fd_socket); @@ -398,54 +365,41 @@ size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf // initialize the socket fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); if (fd_socket == -1) { - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // ask whether the server is alive ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; if (!write_all(fd_socket, ctrl_buf, 1)) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // see whether the server replies as expected if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_fatal(fd_socket, out_buf); } // tell the server what we want and how much data will be sent ctrl_buf[0] = SERVER_DECODE_BIT; put_uint32(ctrl_buf + 1, (uint32_t) buf_size); if (!write_all(fd_socket, ctrl_buf, 5)) { - close(fd_socket); - *out_buf = NULL; - return 0; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } // send the data to decode if (!write_all(fd_socket, buf, buf_size)) { - close(fd_socket); - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } // obtain the required buffer size for the data that will be returned if (!read_all(fd_socket, ctrl_buf, 4)) { - close(fd_socket); - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } size_t new_size = (size_t) to_uint32(ctrl_buf); @@ -458,9 +412,7 @@ size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf // obtain the decoded data if (!read_all(fd_socket, *out_buf, new_size)) { - close(fd_socket); - *out_buf = buf; - return buf_size; + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } close(fd_socket); diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 23c20cc4..5d9b17e7 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -386,8 +386,8 @@ typedef struct afl_env_vars { afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, - afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme, - afl_no_startup_calibration; + afl_keep_timeouts, afl_pizza_mode, afl_post_process_keep_original, + afl_no_crash_readme, afl_no_startup_calibration; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/envs.h b/include/envs.h index 2204a100..1527dfcb 100644 --- a/include/envs.h +++ b/include/envs.h @@ -177,6 +177,7 @@ static char *afl_environment_variables[] = { "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD", + "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV", "AFL_PYTHON_MODULE", diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 26a1ea36..3c3d4817 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -130,15 +130,16 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { new_size = afl->max_length; } - // TODO: think about how to enable the change without breaking other implementations - // if (new_mem != *mem) { *mem = new_mem; } /* everything as planned. use the potentially new data. */ - // TODO: think about how to enable the change without breaking other implementations afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); - // TODO: think about how to enable the change without breaking other implementations - // len = new_size; + if (likely(!afl->afl_env.afl_post_process_keep_original)) { + + if (new_mem != *mem) { *mem = new_mem; } + len = new_size; + + } } else { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 0576f84f..10bc2768 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -377,6 +377,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_statsd = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_POST_PROCESS_KEEP_ORIGINAL", + + afl_environment_variable_len)) { + + afl->afl_env.afl_post_process_keep_original = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_TMPDIR", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1f0fcab1..b83af257 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -284,6 +284,8 @@ static void usage(u8 *argv0, int more_help) { PERSISTENT_MSG + "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to the queue,\n" + " but execute the post-processed one\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" From 4e5f42cab6b8c501eeaf76ec7ca920089f6e0f3a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 20 Apr 2023 10:39:23 +0200 Subject: [PATCH 273/300] afl-showmap custom mutator support --- GNUmakefile | 2 +- TODO.md | 4 +- afl-cmin | 2 + afl-cmin.bash | 2 + docs/Changelog.md | 3 +- include/afl-fuzz.h | 8 +++- src/afl-showmap.c | 93 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 107 insertions(+), 7 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 5bc3f9d5..0f890308 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -453,7 +453,7 @@ afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/ $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS) diff --git a/TODO.md b/TODO.md index e7789cf6..dba75070 100644 --- a/TODO.md +++ b/TODO.md @@ -3,14 +3,14 @@ ## Should - splicing selection weighted? - - support afl_custom_{send,post_process}, persistent and deferred fork - server in afl-showmap + - support persistent and deferred fork server in afl-showmap? - better autodetection of shifting runtime timeout values - Update afl->pending_not_fuzzed for MOpt - afl-plot to support multiple plot_data - parallel builds for source-only targets - get rid of check_binary, replace with more forkserver communication - first fuzzer should be a main automatically? not sure. + - reload fuzz binary on signal ## Maybe diff --git a/afl-cmin b/afl-cmin index c5e64410..e2c26d91 100755 --- a/afl-cmin +++ b/afl-cmin @@ -133,6 +133,8 @@ function usage() { "AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \ "printed to stdout\n" \ "AFL_SKIP_BIN_CHECK: skip afl instrumentation checks for target binary\n" +"AFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send)\n" +"AFL_PYTHON_MODULE: custom mutator library (post_process and send)\n" exit 1 } diff --git a/afl-cmin.bash b/afl-cmin.bash index bcf62eba..5258758e 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -151,6 +151,8 @@ AFL_KEEP_TRACES: leave the temporary \.traces directory AFL_NO_FORKSRV: run target via execve instead of using the forkserver AFL_PATH: last resort location to find the afl-showmap binary AFL_SKIP_BIN_CHECK: skip check for target binary +AFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send) +AFL_PYTHON_MODULE: custom mutator library (post_process and send) _EOF_ exit 1 fi diff --git a/docs/Changelog.md b/docs/Changelog.md index 30e76f2c..5ed5ef2b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,7 +4,8 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.07a (dev) - - soon :) + - afl-showmap: + - added custom mutator post_process and send support ### Version ++4.06c (release) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 8b6502b4..ec69ba17 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1103,7 +1103,6 @@ u32 count_bits(afl_state_t *, u8 *); u32 count_bytes(afl_state_t *, u8 *); u32 count_non_255_bytes(afl_state_t *, u8 *); void simplify_trace(afl_state_t *, u8 *); -void classify_counts(afl_forkserver_t *); #ifdef WORD_SIZE_64 void discover_word(u8 *ret, u64 *current, u64 *virgin); #else @@ -1117,6 +1116,9 @@ u8 *describe_op(afl_state_t *, u8, size_t); u8 save_if_interesting(afl_state_t *, void *, u32, u8); u8 has_new_bits(afl_state_t *, u8 *); u8 has_new_bits_unclassified(afl_state_t *, u8 *); +#ifndef AFL_SHOWMAP +void classify_counts(afl_forkserver_t *); +#endif /* Extras */ @@ -1192,11 +1194,13 @@ void fix_up_sync(afl_state_t *); void check_asan_opts(afl_state_t *); void check_binary(afl_state_t *, u8 *); void check_if_tty(afl_state_t *); -void setup_signal_handlers(void); void save_cmdline(afl_state_t *, u32, char **); void read_foreign_testcases(afl_state_t *, int); void write_crash_readme(afl_state_t *afl); u8 check_if_text_buf(u8 *buf, u32 len); +#ifndef AFL_SHOWMAP +void setup_signal_handlers(void); +#endif /* CmpLog */ diff --git a/src/afl-showmap.c b/src/afl-showmap.c index df030672..b5a61de5 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -30,8 +30,10 @@ */ #define AFL_MAIN +#define AFL_SHOWMAP #include "config.h" +#include "afl-fuzz.h" #include "types.h" #include "debug.h" #include "alloc-inl.h" @@ -62,6 +64,8 @@ #include #include +static afl_state_t *afl; + static char *stdin_file; /* stdin file */ static u8 *in_dir = NULL, /* input folder */ @@ -308,12 +312,73 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { } +void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) { + + static u8 buf[MAX_FILE]; + u32 sent = 0; + + if (unlikely(afl->custom_mutators_count)) { + + ssize_t new_size = len; + u8 *new_mem = mem; + u8 *new_buf = NULL; + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_post_process) { + + new_size = + el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf); + + if (unlikely(!new_buf || new_size <= 0)) { + + return; + + } else { + + new_mem = new_buf; + len = new_size; + + } + + } + + }); + + if (new_mem != mem && new_mem != NULL) { + + mem = buf; + memcpy(mem, new_mem, new_size); + + } + + if (unlikely(afl->custom_mutators_count)) { + + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz_send) { + + el->afl_custom_fuzz_send(el->data, mem, len); + sent = 1; + + } + + }); + + } + + } + + if (likely(!sent)) { afl_fsrv_write_to_testcase(fsrv, mem, len); } + +} + /* Execute target application. */ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, u32 len) { - afl_fsrv_write_to_testcase(fsrv, mem, len); + pre_afl_fsrv_write_to_testcase(fsrv, mem, len); if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); } @@ -835,6 +900,10 @@ static void usage(u8 *argv0) { "This tool displays raw tuple data captured by AFL instrumentation.\n" "For additional help, consult %s/README.md.\n\n" + "If you use -i mode, then custom mutator post_process send send " + "functionality\n" + "is supported.\n\n" + "Environment variables used:\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing " @@ -1266,6 +1335,8 @@ int main(int argc, char **argv_orig, char **envp) { } + afl = calloc(1, sizeof(afl_state_t)); + if (getenv("AFL_FORKSRV_INIT_TMOUT")) { s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT")); @@ -1380,6 +1451,26 @@ int main(int argc, char **argv_orig, char **envp) { } + if (in_dir) { + + afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); + afl->afl_env.afl_custom_mutator_library = + getenv("AFL_CUSTOM_MUTATOR_LIBRARY"); + afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE"); + setup_custom_mutators(afl); + + } else { + + if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) { + + WARNF( + "Custom mutator environment detected, this is only supported in -i " + "mode!\n"); + + } + + } + if (in_dir) { DIR *dir_in, *dir_out = NULL; From 30495e6bfe4119c9be6597ad0def01e7e0cb8a67 Mon Sep 17 00:00:00 2001 From: eleguevel Date: Fri, 21 Apr 2023 12:00:56 +0200 Subject: [PATCH 274/300] frida mode: add dynamic loaded code exclusion Add the AFL_FRIDA_INST_NO_DYNAMIC_LOAD environment variable and its associated JS function setInstrumentNoDynamicLoad to prevent the instrumentation of late dynamic loaded code. Resolve #1708 --- docs/env_variables.md | 2 ++ frida_mode/README.md | 4 +++- frida_mode/Scripting.md | 6 ++++++ frida_mode/frida.map | 1 + frida_mode/include/ranges.h | 1 + frida_mode/src/js/api.js | 7 +++++++ frida_mode/src/js/js_api.c | 7 +++++++ frida_mode/src/ranges.c | 39 ++++++++++++++++++++++++++++++++++--- frida_mode/ts/lib/afl.ts | 12 ++++++++++++ include/envs.h | 1 + 10 files changed, 76 insertions(+), 4 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index a6a0ae44..c5995d13 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -677,6 +677,8 @@ support. * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled code. Code is considered to be JIT if the executable segment is not backed by a file. +* `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` - Don't instrument the code loaded late at + runtime. Strictly limits instrumentation to what has been included. * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use `AFL_FRIDA_INST_TRACE`. diff --git a/frida_mode/README.md b/frida_mode/README.md index aac13153..49a1fe38 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -178,11 +178,13 @@ Default is 256Mb. * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled code. Code is considered to be JIT if the executable segment is not backed by a file. +* `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` - Don't instrument the code loaded late at + runtime. Strictly limits instrumentation to what has been included. * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use + `AFL_FRIDA_INST_TRACE`. * `AFL_FRIDA_INST_REGS_FILE` - File to write raw register contents at the start of each block. - `AFL_FRIDA_INST_TRACE`. * `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to instrumented address block translations. * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will diff --git a/frida_mode/Scripting.md b/frida_mode/Scripting.md index 023e4a19..dfd09e7b 100644 --- a/frida_mode/Scripting.md +++ b/frida_mode/Scripting.md @@ -844,6 +844,12 @@ class Afl { static setInstrumentLibraries() { Afl.jsApiSetInstrumentLibraries(); } + /** + * See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` + */ + static setInstrumentNoDynamicLoad() { + Afl.jsApiSetInstrumentNoDynamicLoad(); + } /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ diff --git a/frida_mode/frida.map b/frida_mode/frida.map index baf067ab..a98c2096 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -19,6 +19,7 @@ js_api_set_instrument_jit; js_api_set_instrument_libraries; js_api_set_instrument_instructions; + js_api_set_instrument_no_dynamic_load; js_api_set_instrument_no_optimize; js_api_set_instrument_regs_file; js_api_set_instrument_seed; diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h index 3bd9eaa6..ca28acd9 100644 --- a/frida_mode/include/ranges.h +++ b/frida_mode/include/ranges.h @@ -6,6 +6,7 @@ extern gboolean ranges_debug_maps; extern gboolean ranges_inst_libs; extern gboolean ranges_inst_jit; +extern gboolean ranges_inst_dynamic_load; void ranges_config(void); void ranges_init(void); diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index f9ea1ffb..a65d32df 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -150,6 +150,12 @@ class Afl { static setInstrumentLibraries() { Afl.jsApiSetInstrumentLibraries(); } + /** + * See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` + */ + static setInstrumentNoDynamicLoad() { + Afl.jsApiSetInstrumentNoDynamicLoad(); + } /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -342,6 +348,7 @@ Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_de Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); +Afl.jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction("js_api_set_instrument_no_dynamic_load", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]); Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 2e996c1c..00278082 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -156,6 +156,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_instructions( } +__attribute__((visibility("default"))) void js_api_set_instrument_no_dynamic_load( + void) { + + ranges_inst_dynamic_load = FALSE; + +} + __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize( void) { diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 72cb9730..e9fc3b4e 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -18,6 +18,7 @@ typedef struct { gboolean ranges_debug_maps = FALSE; gboolean ranges_inst_libs = FALSE; gboolean ranges_inst_jit = FALSE; +gboolean ranges_inst_dynamic_load = TRUE; static GArray *module_ranges = NULL; static GArray *libs_ranges = NULL; @@ -25,6 +26,7 @@ static GArray *jit_ranges = NULL; static GArray *include_ranges = NULL; static GArray *exclude_ranges = NULL; static GArray *ranges = NULL; +static GArray *whole_memory_ranges = NULL; static void convert_address_token(gchar *token, GumMemoryRange *range) { @@ -387,6 +389,21 @@ static GArray *collect_jit_ranges(void) { } +static GArray *collect_whole_mem_ranges(void) { + + GArray *result; + GumMemoryRange range; + result = g_array_new(false, false, sizeof(GumMemoryRange)); + + range.base_address = 0; + range.size = G_MAXULONG; + + g_array_append_val(result, range); + + return result; + +} + static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra, GumMemoryRange *rb) { @@ -574,11 +591,17 @@ void ranges_config(void) { if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; } if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; } if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; } + if (getenv("AFL_FRIDA_INST_NO_DYNAMIC_LOAD") != NULL) { + + ranges_inst_dynamic_load = FALSE; + + } if (ranges_debug_maps) { ranges_print_debug_maps(); } include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES"); + whole_memory_ranges = collect_whole_mem_ranges(); } @@ -628,10 +651,20 @@ void ranges_init(void) { print_ranges("step4", step4); /* - * After step4, we have the total ranges to be instrumented, we now subtract - * that from the original ranges of the modules to configure stalker. + * After step 4 we have the total ranges to be instrumented, we now subtract + * that either from the original ranges of the modules or from the whole + * memory if AFL_INST_NO_DYNAMIC_LOAD to configure the stalker. */ - step5 = subtract_ranges(module_ranges, step4); + if (ranges_inst_dynamic_load) { + + step5 = subtract_ranges(module_ranges, step4); + + } else { + + step5 = subtract_ranges(whole_memory_ranges, step4); + + } + print_ranges("step5", step5); ranges = merge_ranges(step5); diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 6a2350e7..7d1fac6b 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -178,6 +178,13 @@ class Afl { Afl.jsApiSetInstrumentLibraries(); } + /** + * See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` + */ + public static setInstrumentNoDynamicLoad(): void { + Afl.jsApiSetInstrumentNoDynamicLoad(); + } + /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -443,6 +450,11 @@ class Afl { "void", []); + private static readonly jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction( + "js_api_set_instrument_no_dynamic_load", + "void", + []); + private static readonly jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction( "js_api_set_instrument_no_optimize", "void", diff --git a/include/envs.h b/include/envs.h index 066921b9..41eabf60 100644 --- a/include/envs.h +++ b/include/envs.h @@ -65,6 +65,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE", + "AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", From 0a297ed9ef48c1eaf69fdc13bd1016f8f29124be Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Apr 2023 15:09:35 +0200 Subject: [PATCH 275/300] dummy function for afl-showmap --- src/afl-showmap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index b5a61de5..affad7d6 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -140,6 +140,15 @@ static void kill_child() { } +/* dummy function */ +u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) { + + (void)afl; + (void)mem; + return a + b; + +} + static void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; From 369ec31f0e1a40f5e617265fc199676175d36814 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Apr 2023 15:15:34 +0200 Subject: [PATCH 276/300] debug output --- GNUmakefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 0f890308..23cae65d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -286,6 +286,8 @@ ifeq "$(shell command -v svn >/dev/null && svn proplist . 2>/dev/null && echo 1 IN_REPO=1 endif +CCVER=$(shell cc -v 2>&1|tail -n 1) + ifeq "$(shell echo 'int main() { return 0;}' | $(CC) $(CFLAGS) -fsanitize=address -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1" ASAN_CFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer -DASAN_BUILD ASAN_LDFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer @@ -431,7 +433,7 @@ endif .PHONY: ready ready: - @echo "[+] Everything seems to be working, ready to compile." + @echo "[+] Everything seems to be working, ready to compile. ($(CCVER))" afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS) From 7a8d0a10ce25d20bdd2021920b0b5ebbc0d3f3a6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Apr 2023 15:21:11 +0200 Subject: [PATCH 277/300] add dummy functions to afl-showmap for old gcc compilers --- src/afl-showmap.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index affad7d6..0b9fc211 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -140,7 +140,7 @@ static void kill_child() { } -/* dummy function */ +/* dummy functions */ u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) { (void)afl; @@ -149,7 +149,30 @@ u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) { } -static void classify_counts(afl_forkserver_t *fsrv) { +void show_stats(afl_state_t *afl) { + + (void)afl; + +} + +void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { + + (void)afl; + (void)q; + +} + +fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, + u32 i) { + + (void)afl; + (void)fsrv; + (void)i; + return 0; + +} + +void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; const u8 *map = binary_mode ? count_class_binary : count_class_human; From c49d346e3762fa06bf410d493f70411069d32590 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 21 Apr 2023 15:22:48 +0200 Subject: [PATCH 278/300] remove ubuntu 18.04 from ci, no resources for this on github --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed1f3228..03e4151d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: "${{ matrix.os }}" strategy: matrix: - os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04] + os: [ubuntu-22.04, ubuntu-20.04] env: AFL_SKIP_CPUFREQ: 1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 From 779a72ef8c2457430b824f7830eba731745fb6ee Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:46:15 +0200 Subject: [PATCH 279/300] fixed AFL_POST_PROCESS_KEEP_ORIGINAL for version 4.07a --- src/afl-fuzz-run.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2d53de93..ac4fb4a9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -133,14 +133,22 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (new_mem != *mem && new_mem != NULL && new_size > 0 - && !afl->afl_env.afl_post_process_keep_original) { + if (new_mem != *mem && new_mem != NULL && new_size > 0) { - u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size); - if (unlikely(!new_buf)) { PFATAL("alloc"); } - *mem = new_buf; - memcpy(*mem, new_mem, new_size); - afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + memcpy(new_buf, new_mem, new_size); + + /* if AFL_POST_PROCESS_KEEP_ORIGINAL is set then save the original memory + prior post-processing in new_mem to restore it later */ + if (unlikely(afl->afl_env.afl_post_process_keep_original)) { + + new_mem = *mem; + + } + + *mem = new_buf; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); } @@ -162,17 +170,19 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { if (likely(!sent)) { /* everything as planned. use the potentially new data. */ + afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size); if (likely(!afl->afl_env.afl_post_process_keep_original)) { - afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size); + len = new_size; } else { - afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); + /* restore the original memory which was saved in new_mem */ + *mem = new_mem; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); } - len = new_size; } From d7e6f8cb386a24b5ec090caa6befe27461cd2190 Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Fri, 21 Apr 2023 17:10:19 +0200 Subject: [PATCH 280/300] Create README.md --- custom_mutators/atnwalk/README.md | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 custom_mutators/atnwalk/README.md diff --git a/custom_mutators/atnwalk/README.md b/custom_mutators/atnwalk/README.md new file mode 100644 index 00000000..badb856f --- /dev/null +++ b/custom_mutators/atnwalk/README.md @@ -0,0 +1,45 @@ +# ATNwalk: Grammar-Based Fuzzing using Only Bit-Mutations + +This is a custom mutator integration of ATNwalk that works by communicating via UNIX domain sockets. + +Refer to [https://github.com/atnwalk/testbed](https://github.com/atnwalk/testbed) for detailed instructions on how to get ATNwalk running. + +## Build + +```bash +gcc -I ../../include/ -shared -fPIC -Wall -O3 atnwalk.c -o atnwalk.so +``` + +## Run + +**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed) + +```bash +# create the required a random seed first +mkdir -p ~/campaign/example/seeds +cd ~/campaign/example/seeds +head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded + +# create the required atnwalk directory and copy the seed +cd ../ +mkdir -p atnwalk/in +cp ./seeds/seed.encoded atnwalk/in/seed +cd atnwalk + +# assign to a single core when benchmarking it, change the CPU number as required +CPU_ID=0 + +# start the ATNwalk server +nohup taskset -c ${CPU_ID} ${HOME}/atnwalk/build/javascript/bin/server 100 > server.log 2>&1 & + +# start AFL++ with ATNwalk +AFL_SKIP_CPUFREQ=1 \ + AFL_DISABLE_TRIM=1 \ + AFL_CUSTOM_MUTATOR_ONLY=1 \ + AFL_CUSTOM_MUTATOR_LIBRARY=${HOME}/AFLplusplus/custom_mutators/atnwalk/atnwalk.so \ + AFL_POST_PROCESS_KEEP_ORIGINAL=1 \ + ~/AFLplusplus/afl-fuzz -t 100 -i in/ -o out -b ${CPU_ID} -- ~/jerryscript/build/bin/jerry + +# make sure to kill the ATNwalk server process after you're done +kill "$(cat atnwalk.pid)" +``` From 228e9527cb0c00644e9601afc0449c586b468576 Mon Sep 17 00:00:00 2001 From: Maik Betka <9078425+voidptr127@users.noreply.github.com> Date: Fri, 21 Apr 2023 17:19:37 +0200 Subject: [PATCH 281/300] fixed formatting with make code-format --- src/afl-fuzz-state.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index cccebeb9..5e736029 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -396,10 +396,10 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } else if (!strncmp(env, "AFL_POST_PROCESS_KEEP_ORIGINAL", - afl_environment_variable_len)) { + afl_environment_variable_len)) { - afl->afl_env.afl_post_process_keep_original = - get_afl_env(afl_environment_variables[i]) ? 1 : 0; + afl->afl_env.afl_post_process_keep_original = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; } else if (!strncmp(env, "AFL_TMPDIR", From 599b4631a3a40930e54e103f8ad1a69499fd1c8b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 22 Apr 2023 11:31:21 +0200 Subject: [PATCH 282/300] typo --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f6628851..394f33f9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -326,7 +326,7 @@ static void usage(u8 *argv0, int more_help) { } #ifdef USE_PYTHON - SAYF("Compiled with %s module support, see docs/custom_mutator.md\n", + SAYF("Compiled with %s module support, see docs/custom_mutators.md\n", (char *)PYTHON_VERSION); #else SAYF("Compiled without Python module support.\n"); From 6bd48a48cbed1f923ff0999ea24af1f548c2e2bc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 22 Apr 2023 11:39:44 +0200 Subject: [PATCH 283/300] code format --- custom_mutators/README.md | 59 ++- custom_mutators/atnwalk/atnwalk.c | 687 +++++++++++++++++------------- docs/Changelog.md | 4 + frida_mode/src/js/js_api.c | 4 +- 4 files changed, 439 insertions(+), 315 deletions(-) diff --git a/custom_mutators/README.md b/custom_mutators/README.md index 8d01856f..a5a572c0 100644 --- a/custom_mutators/README.md +++ b/custom_mutators/README.md @@ -11,29 +11,6 @@ The `./examples` folder contains examples for custom mutators in python and C. In `./rust`, you will find rust bindings, including a simple example in `./rust/example` and an example for structured fuzzing, based on lain, in`./rust/example_lain`. -## The AFL++ grammar agnostic grammar mutator - -In `./autotokens` you find a token-level fuzzer that does not need to know -anything about the grammar of an input as long as it is in ascii and allows -whitespace. -It is very fast and effective. - -If you are looking for an example of how to effectively create a custom -mutator take a look at this one. - -## The AFL++ Grammar Mutator - -If you use git to clone AFL++, then the following will incorporate our -excellent grammar custom mutator: - -```sh -git submodule update --init -``` - -Read the README in the [Grammar-Mutator] repository on how to use it. - -[Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator - ## Production-Ready Custom Mutators This directory holds ready to use custom mutators. @@ -47,6 +24,42 @@ and add `AFL_CUSTOM_MUTATOR_ONLY=1` if you only want to use the custom mutator. Multiple custom mutators can be used by separating their paths with `:` in the environment variable. +### The AFL++ grammar agnostic grammar mutator + +In `./autotokens` you find a token-level fuzzer that does not need to know +anything about the grammar of an input as long as it is in ascii and allows +whitespace. +It is very fast and effective. + +If you are looking for an example of how to effectively create a custom +mutator take a look at this one. + +### The AFL++ Grammar Mutator + +If you use git to clone AFL++, then the following will incorporate our +excellent grammar custom mutator: + +```sh +git submodule update --init +``` + +Read the README in the [Grammar-Mutator] repository on how to use it. + +[Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator + +Note that this custom mutator is not very good though! + +### Other Mutators + +atnwalk and gramatron are grammar custom mutators. Example grammars are +provided. + +honggfuzz, libfuzzer and libafl are partial implementations based on the +mutator implementations of the respective fuzzers. +More for playing than serious usage. + +radamsa is slow and not very good. + ## 3rd Party Custom Mutators ### Superion Mutators diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index 901b8a9e..c3a2cd95 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -11,10 +11,12 @@ #define BUF_SIZE_INIT 4096 #define SOCKET_NAME "./atnwalk.socket" -// how many errors (e.g. timeouts) to tolerate until moving on to the next queue entry +// how many errors (e.g. timeouts) to tolerate until moving on to the next queue +// entry #define ATNWALK_ERRORS_MAX 1 -// how many execution timeouts to tolerate until moving on to the next queue entry +// how many execution timeouts to tolerate until moving on to the next queue +// entry #define EXEC_TIMEOUT_MAX 2 // handshake constants @@ -27,80 +29,87 @@ const uint8_t SERVER_MUTATE_BIT = 0b00000010; const uint8_t SERVER_DECODE_BIT = 0b00000100; const uint8_t SERVER_ENCODE_BIT = 0b00001000; - typedef struct atnwalk_mutator { - afl_state_t *afl; - uint8_t atnwalk_error_count; - uint64_t prev_timeouts; - uint32_t prev_hits; - uint32_t stage_havoc_cur; - uint32_t stage_havoc_max; - uint32_t stage_splice_cur; - uint32_t stage_splice_max; - uint8_t *fuzz_buf; - size_t fuzz_size; - uint8_t *post_process_buf; - size_t post_process_size; + + afl_state_t *afl; + uint8_t atnwalk_error_count; + uint64_t prev_timeouts; + uint32_t prev_hits; + uint32_t stage_havoc_cur; + uint32_t stage_havoc_max; + uint32_t stage_splice_cur; + uint32_t stage_splice_max; + uint8_t *fuzz_buf; + size_t fuzz_size; + uint8_t *post_process_buf; + size_t post_process_size; + } atnwalk_mutator_t; - int read_all(int fd, uint8_t *buf, size_t buf_size) { - int n; - size_t offset = 0; - while (offset < buf_size) { - n = read(fd, buf + offset, buf_size - offset); - if (n == -1) { - return 0; - } - offset += n; - } - return 1; -} + int n; + size_t offset = 0; + while (offset < buf_size) { + + n = read(fd, buf + offset, buf_size - offset); + if (n == -1) { return 0; } + offset += n; + + } + + return 1; + +} int write_all(int fd, uint8_t *buf, size_t buf_size) { - int n; - size_t offset = 0; - while (offset < buf_size) { - n = write(fd, buf + offset, buf_size - offset); - if (n == -1) { - return 0; - } - offset += n; - } - return 1; -} + int n; + size_t offset = 0; + while (offset < buf_size) { + + n = write(fd, buf + offset, buf_size - offset); + if (n == -1) { return 0; } + offset += n; + + } + + return 1; + +} void put_uint32(uint8_t *buf, uint32_t val) { - buf[0] = (uint8_t) (val >> 24); - buf[1] = (uint8_t) ((val & 0x00ff0000) >> 16); - buf[2] = (uint8_t) ((val & 0x0000ff00) >> 8); - buf[3] = (uint8_t) (val & 0x000000ff); -} + buf[0] = (uint8_t)(val >> 24); + buf[1] = (uint8_t)((val & 0x00ff0000) >> 16); + buf[2] = (uint8_t)((val & 0x0000ff00) >> 8); + buf[3] = (uint8_t)(val & 0x000000ff); + +} uint32_t to_uint32(uint8_t *buf) { - uint32_t val = 0; - val |= (((uint32_t) buf[0]) << 24); - val |= (((uint32_t) buf[1]) << 16); - val |= (((uint32_t) buf[2]) << 8); - val |= ((uint32_t) buf[3]); - return val; -} + uint32_t val = 0; + val |= (((uint32_t)buf[0]) << 24); + val |= (((uint32_t)buf[1]) << 16); + val |= (((uint32_t)buf[2]) << 8); + val |= ((uint32_t)buf[3]); + return val; + +} void put_uint64(uint8_t *buf, uint64_t val) { - buf[0] = (uint8_t) (val >> 56); - buf[1] = (uint8_t) ((val & 0x00ff000000000000) >> 48); - buf[2] = (uint8_t) ((val & 0x0000ff0000000000) >> 40); - buf[3] = (uint8_t) ((val & 0x000000ff00000000) >> 32); - buf[4] = (uint8_t) ((val & 0x00000000ff000000) >> 24); - buf[5] = (uint8_t) ((val & 0x0000000000ff0000) >> 16); - buf[6] = (uint8_t) ((val & 0x000000000000ff00) >> 8); - buf[7] = (uint8_t) (val & 0x00000000000000ff); -} + buf[0] = (uint8_t)(val >> 56); + buf[1] = (uint8_t)((val & 0x00ff000000000000) >> 48); + buf[2] = (uint8_t)((val & 0x0000ff0000000000) >> 40); + buf[3] = (uint8_t)((val & 0x000000ff00000000) >> 32); + buf[4] = (uint8_t)((val & 0x00000000ff000000) >> 24); + buf[5] = (uint8_t)((val & 0x0000000000ff0000) >> 16); + buf[6] = (uint8_t)((val & 0x000000000000ff00) >> 8); + buf[7] = (uint8_t)(val & 0x00000000000000ff); + +} /** * Initialize this custom mutator @@ -114,70 +123,83 @@ void put_uint64(uint8_t *buf, uint64_t val) { * Return NULL on error. */ atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { - srand(seed); - atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t)); - if (!data) { - perror("afl_custom_init alloc"); - return NULL; - } - data->afl = afl; - data->prev_hits = 0; - data->fuzz_buf = (uint8_t *) malloc(BUF_SIZE_INIT); - data->fuzz_size = BUF_SIZE_INIT; - data->post_process_buf = (uint8_t *) malloc(BUF_SIZE_INIT); - data->post_process_size = BUF_SIZE_INIT; - return data; + + srand(seed); + atnwalk_mutator_t *data = + (atnwalk_mutator_t *)malloc(sizeof(atnwalk_mutator_t)); + if (!data) { + + perror("afl_custom_init alloc"); + return NULL; + + } + + data->afl = afl; + data->prev_hits = 0; + data->fuzz_buf = (uint8_t *)malloc(BUF_SIZE_INIT); + data->fuzz_size = BUF_SIZE_INIT; + data->post_process_buf = (uint8_t *)malloc(BUF_SIZE_INIT); + data->post_process_size = BUF_SIZE_INIT; + return data; + } +unsigned int afl_custom_fuzz_count(atnwalk_mutator_t *data, + const unsigned char *buf, size_t buf_size) { -unsigned int afl_custom_fuzz_count(atnwalk_mutator_t *data, const unsigned char *buf, size_t buf_size) { - // afl_custom_fuzz_count is called exactly once before entering the 'stage-loop' for the current queue entry - // thus, we use it to reset the error count and to initialize stage variables (somewhat not intended by the API, - // but still better than rewriting the whole thing to have a custom mutator stage) - data->atnwalk_error_count = 0; - data->prev_timeouts = data->afl->total_tmouts; + // afl_custom_fuzz_count is called exactly once before entering the + // 'stage-loop' for the current queue entry thus, we use it to reset the error + // count and to initialize stage variables (somewhat not intended by the API, + // but still better than rewriting the whole thing to have a custom mutator + // stage) + data->atnwalk_error_count = 0; + data->prev_timeouts = data->afl->total_tmouts; - // it might happen that on the last execution of the splice stage a new path is found - // we need to fix that here and count it - if (data->prev_hits) { - data->afl->stage_finds[STAGE_SPLICE] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; - } - data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; - data->stage_havoc_cur = 0; - data->stage_splice_cur = 0; + // it might happen that on the last execution of the splice stage a new path + // is found we need to fix that here and count it + if (data->prev_hits) { + + data->afl->stage_finds[STAGE_SPLICE] += + data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; + + } + + data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; + data->stage_havoc_cur = 0; + data->stage_splice_cur = 0; + + // 50% havoc, 50% splice + data->stage_havoc_max = data->afl->stage_max >> 1; + if (data->stage_havoc_max < HAVOC_MIN) { data->stage_havoc_max = HAVOC_MIN; } + data->stage_splice_max = data->stage_havoc_max; + return data->stage_havoc_max + data->stage_splice_max; - // 50% havoc, 50% splice - data->stage_havoc_max = data->afl->stage_max >> 1; - if (data->stage_havoc_max < HAVOC_MIN) { - data->stage_havoc_max = HAVOC_MIN; - } - data->stage_splice_max = data->stage_havoc_max; - return data->stage_havoc_max + data->stage_splice_max; } - size_t fail_fatal(int fd_socket, uint8_t **out_buf) { - if (fd_socket != -1) { - close(fd_socket); - } - *out_buf = NULL; - return 0; + + if (fd_socket != -1) { close(fd_socket); } + *out_buf = NULL; + return 0; + } +size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf, + size_t buf_size, uint8_t **out_buf) { + + if (fd_socket != -1) { close(fd_socket); } + data->atnwalk_error_count++; + if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { + + data->afl->stage_max = data->afl->stage_cur; + + } + + *out_buf = buf; + return buf_size; -size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { - if (fd_socket != -1) { - close(fd_socket); - } - data->atnwalk_error_count++; - if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) { - data->afl->stage_max = data->afl->stage_cur; - } - *out_buf = buf; - return buf_size; } - /** * Perform custom mutations on a given input * @@ -194,153 +216,215 @@ size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf, siz * produce data larger than max_size. * @return Size of the mutated output. */ -size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf, - uint8_t *add_buf, size_t add_buf_size, size_t max_size) { - struct sockaddr_un addr; - int fd_socket; - uint8_t ctrl_buf[8]; - uint8_t wanted; +size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, + uint8_t **out_buf, uint8_t *add_buf, size_t add_buf_size, + size_t max_size) { - // let's display what's going on in a nice way - if (data->stage_havoc_cur == 0) { - data->afl->stage_name = (uint8_t *) "atnwalk - havoc"; - } - if (data->stage_havoc_cur == data->stage_havoc_max) { - data->afl->stage_name = (uint8_t *) "atnwalk - splice"; - } + struct sockaddr_un addr; + int fd_socket; + uint8_t ctrl_buf[8]; + uint8_t wanted; + + // let's display what's going on in a nice way + if (data->stage_havoc_cur == 0) { + + data->afl->stage_name = (uint8_t *)"atnwalk - havoc"; + + } + + if (data->stage_havoc_cur == data->stage_havoc_max) { + + data->afl->stage_name = (uint8_t *)"atnwalk - splice"; + + } + + // increase the respective havoc or splice counters + if (data->stage_havoc_cur < data->stage_havoc_max) { + + data->stage_havoc_cur++; + data->afl->stage_cycles[STAGE_HAVOC]++; + + } else { + + // if there is nothing to splice, continue with havoc and skip splicing this + // time + if (data->afl->ready_for_splicing_count < 1) { + + data->stage_havoc_max = data->afl->stage_max; + data->stage_havoc_cur++; + data->afl->stage_cycles[STAGE_HAVOC]++; - // increase the respective havoc or splice counters - if (data->stage_havoc_cur < data->stage_havoc_max) { - data->stage_havoc_cur++; - data->afl->stage_cycles[STAGE_HAVOC]++; } else { - // if there is nothing to splice, continue with havoc and skip splicing this time - if (data->afl->ready_for_splicing_count < 1) { - data->stage_havoc_max = data->afl->stage_max; - data->stage_havoc_cur++; - data->afl->stage_cycles[STAGE_HAVOC]++; - } else { - data->stage_splice_cur++; - data->afl->stage_cycles[STAGE_SPLICE]++; - } + + data->stage_splice_cur++; + data->afl->stage_cycles[STAGE_SPLICE]++; + } - // keep track of found new corpus seeds per stage - if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) { - if (data->stage_splice_cur <= 1) { - data->afl->stage_finds[STAGE_HAVOC] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; - } else { - data->afl->stage_finds[STAGE_SPLICE] += - data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; - } - } - data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; + } + + // keep track of found new corpus seeds per stage + if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) { + + if (data->stage_splice_cur <= 1) { + + data->afl->stage_finds[STAGE_HAVOC] += + data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; + + } else { + + data->afl->stage_finds[STAGE_SPLICE] += + data->afl->queued_items + data->afl->saved_crashes - data->prev_hits; - // check whether this input produces a lot of timeouts, if it does then abandon this queue entry - if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) { - data->afl->stage_max = data->afl->stage_cur; - return fail_gracefully(-1, data, buf, buf_size, out_buf); } - // initialize the socket - fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); - if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { - return fail_fatal(fd_socket, out_buf); + } + + data->prev_hits = data->afl->queued_items + data->afl->saved_crashes; + + // check whether this input produces a lot of timeouts, if it does then + // abandon this queue entry + if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) { + + data->afl->stage_max = data->afl->stage_cur; + return fail_gracefully(-1, data, buf, buf_size, out_buf); + + } + + // initialize the socket + fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); + if (connect(fd_socket, (const struct sockaddr *)&addr, sizeof(addr)) == -1) { + + return fail_fatal(fd_socket, out_buf); + + } + + // ask whether the server is alive + ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; + if (!write_all(fd_socket, ctrl_buf, 1)) { + + return fail_fatal(fd_socket, out_buf); + + } + + // see whether the server replies as expected + if (!read_all(fd_socket, ctrl_buf, 1) || + ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { + + return fail_fatal(fd_socket, out_buf); + + } + + // tell the server what we want to do + wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT; + + // perform a crossover if we are splicing + if (data->stage_splice_cur > 0) { wanted |= SERVER_CROSSOVER_BIT; } + + // tell the server what we want and how much data will be sent + ctrl_buf[0] = wanted; + put_uint32(ctrl_buf + 1, (uint32_t)buf_size); + if (!write_all(fd_socket, ctrl_buf, 5)) { + + return fail_fatal(fd_socket, out_buf); + + } + + // send the data to mutate and encode + if (!write_all(fd_socket, buf, buf_size)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + if (wanted & SERVER_CROSSOVER_BIT) { + + // since we requested crossover, we will first tell how much additional data + // is to be expected + put_uint32(ctrl_buf, (uint32_t)add_buf_size); + if (!write_all(fd_socket, ctrl_buf, 4)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + } - // ask whether the server is alive - ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; - if (!write_all(fd_socket, ctrl_buf, 1)) { - return fail_fatal(fd_socket, out_buf); + // send the additional data for crossover + if (!write_all(fd_socket, add_buf, add_buf_size)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + } - // see whether the server replies as expected - if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { - return fail_fatal(fd_socket, out_buf); - } - - // tell the server what we want to do - wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT; - - // perform a crossover if we are splicing - if (data->stage_splice_cur > 0) { - wanted |= SERVER_CROSSOVER_BIT; - } - - // tell the server what we want and how much data will be sent - ctrl_buf[0] = wanted; - put_uint32(ctrl_buf + 1, (uint32_t) buf_size); - if (!write_all(fd_socket, ctrl_buf, 5)) { - return fail_fatal(fd_socket, out_buf); - } - - // send the data to mutate and encode - if (!write_all(fd_socket, buf, buf_size)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - - if (wanted & SERVER_CROSSOVER_BIT) { - // since we requested crossover, we will first tell how much additional data is to be expected - put_uint32(ctrl_buf, (uint32_t) add_buf_size); - if (!write_all(fd_socket, ctrl_buf, 4)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - - // send the additional data for crossover - if (!write_all(fd_socket, add_buf, add_buf_size)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - - // lastly, a seed is required for crossover so send one - put_uint64(ctrl_buf, (uint64_t) rand()); - if (!write_all(fd_socket, ctrl_buf, 8)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - } - - // since we requested mutation, we need to provide a seed for that - put_uint64(ctrl_buf, (uint64_t) rand()); + // lastly, a seed is required for crossover so send one + put_uint64(ctrl_buf, (uint64_t)rand()); if (!write_all(fd_socket, ctrl_buf, 8)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + } - // obtain the required buffer size for the data that will be returned - if (!read_all(fd_socket, ctrl_buf, 4)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - size_t new_size = (size_t) to_uint32(ctrl_buf); + } + + // since we requested mutation, we need to provide a seed for that + put_uint64(ctrl_buf, (uint64_t)rand()); + if (!write_all(fd_socket, ctrl_buf, 8)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + // obtain the required buffer size for the data that will be returned + if (!read_all(fd_socket, ctrl_buf, 4)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + size_t new_size = (size_t)to_uint32(ctrl_buf); + + // if the data is too large then we ignore this round + if (new_size > max_size) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + if (new_size > buf_size) { + + // buf is too small, need to use data->fuzz_buf, let's see whether we need + // to reallocate + if (new_size > data->fuzz_size) { + + data->fuzz_size = new_size << 1; + data->fuzz_buf = (uint8_t *)realloc(data->fuzz_buf, data->fuzz_size); - // if the data is too large then we ignore this round - if (new_size > max_size) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); } - if (new_size > buf_size) { - // buf is too small, need to use data->fuzz_buf, let's see whether we need to reallocate - if (new_size > data->fuzz_size) { - data->fuzz_size = new_size << 1; - data->fuzz_buf = (uint8_t *) realloc(data->fuzz_buf, data->fuzz_size); - } - *out_buf = data->fuzz_buf; - } else { - // new_size fits into buf, so re-use it - *out_buf = buf; - } + *out_buf = data->fuzz_buf; - // obtain the encoded data - if (!read_all(fd_socket, *out_buf, new_size)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } + } else { + + // new_size fits into buf, so re-use it + *out_buf = buf; + + } + + // obtain the encoded data + if (!read_all(fd_socket, *out_buf, new_size)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + close(fd_socket); + return new_size; - close(fd_socket); - return new_size; } - /** * A post-processing function to use right before AFL writes the test case to * disk in order to execute the target. @@ -357,76 +441,99 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u * @return Size of the output buffer after processing or the needed amount. * A return of 0 indicates an error. */ -size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { - struct sockaddr_un addr; - int fd_socket; - uint8_t ctrl_buf[8]; +size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, + size_t buf_size, uint8_t **out_buf) { - // initialize the socket - fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd_socket == -1) { - return fail_fatal(fd_socket, out_buf); - } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); - if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) { - return fail_fatal(fd_socket, out_buf); - } + struct sockaddr_un addr; + int fd_socket; + uint8_t ctrl_buf[8]; - // ask whether the server is alive - ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; - if (!write_all(fd_socket, ctrl_buf, 1)) { - return fail_fatal(fd_socket, out_buf); - } + // initialize the socket + fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1); + if (connect(fd_socket, (const struct sockaddr *)&addr, sizeof(addr)) == -1) { - // see whether the server replies as expected - if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { - return fail_fatal(fd_socket, out_buf); - } + return fail_fatal(fd_socket, out_buf); - // tell the server what we want and how much data will be sent - ctrl_buf[0] = SERVER_DECODE_BIT; - put_uint32(ctrl_buf + 1, (uint32_t) buf_size); - if (!write_all(fd_socket, ctrl_buf, 5)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } + } - // send the data to decode - if (!write_all(fd_socket, buf, buf_size)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } + // ask whether the server is alive + ctrl_buf[0] = SERVER_ARE_YOU_ALIVE; + if (!write_all(fd_socket, ctrl_buf, 1)) { - // obtain the required buffer size for the data that will be returned - if (!read_all(fd_socket, ctrl_buf, 4)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } - size_t new_size = (size_t) to_uint32(ctrl_buf); + return fail_fatal(fd_socket, out_buf); - // need to use data->post_process_buf, let's see whether we need to reallocate - if (new_size > data->post_process_size) { - data->post_process_size = new_size << 1; - data->post_process_buf = (uint8_t *) realloc(data->post_process_buf, data->post_process_size); - } - *out_buf = data->post_process_buf; + } - // obtain the decoded data - if (!read_all(fd_socket, *out_buf, new_size)) { - return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); - } + // see whether the server replies as expected + if (!read_all(fd_socket, ctrl_buf, 1) || + ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) { + + return fail_fatal(fd_socket, out_buf); + + } + + // tell the server what we want and how much data will be sent + ctrl_buf[0] = SERVER_DECODE_BIT; + put_uint32(ctrl_buf + 1, (uint32_t)buf_size); + if (!write_all(fd_socket, ctrl_buf, 5)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + // send the data to decode + if (!write_all(fd_socket, buf, buf_size)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + // obtain the required buffer size for the data that will be returned + if (!read_all(fd_socket, ctrl_buf, 4)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + size_t new_size = (size_t)to_uint32(ctrl_buf); + + // need to use data->post_process_buf, let's see whether we need to reallocate + if (new_size > data->post_process_size) { + + data->post_process_size = new_size << 1; + data->post_process_buf = + (uint8_t *)realloc(data->post_process_buf, data->post_process_size); + + } + + *out_buf = data->post_process_buf; + + // obtain the decoded data + if (!read_all(fd_socket, *out_buf, new_size)) { + + return fail_gracefully(fd_socket, data, buf, buf_size, out_buf); + + } + + close(fd_socket); + return new_size; - close(fd_socket); - return new_size; } - /** * Deinitialize everything * * @param data The data ptr from afl_custom_init */ void afl_custom_deinit(atnwalk_mutator_t *data) { - free(data->fuzz_buf); - free(data->post_process_buf); - free(data); + + free(data->fuzz_buf); + free(data->post_process_buf); + free(data); + } + diff --git a/docs/Changelog.md b/docs/Changelog.md index 5ed5ef2b..f33acff9 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,8 +4,12 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.07a (dev) + - afl-fuzz: + - new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal + data before post process on finds - afl-showmap: - added custom mutator post_process and send support + - a new grammar custom mutator atnwalk was submitted by @voidptr127 ! ### Version ++4.06c (release) diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 00278082..288aec95 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -156,8 +156,8 @@ __attribute__((visibility("default"))) void js_api_set_instrument_instructions( } -__attribute__((visibility("default"))) void js_api_set_instrument_no_dynamic_load( - void) { +__attribute__((visibility("default"))) void +js_api_set_instrument_no_dynamic_load(void) { ranges_inst_dynamic_load = FALSE; From 531380d6ab9d2467d174ae45dcfa64bbf12230c0 Mon Sep 17 00:00:00 2001 From: Keno Hassler <40292329+kenohassler@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:46:56 +0200 Subject: [PATCH 284/300] llvm-lto: allow skipping initialization --- instrumentation/SanitizerCoverageLTO.so.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index e41f19b6..42583f9e 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1005,7 +1005,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( // afl++ START if (dFile.is_open()) dFile.close(); - if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) { + if (!getenv("AFL_LLVM_LTO_SKIPINIT") && + (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr)) { // 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-lto.o From 8c228b0d23e303499dccf3df77c5d0b3a8b59b7b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 24 Apr 2023 18:08:27 +0200 Subject: [PATCH 285/300] afl-showmap -I option --- afl-cmin | 2 +- docs/Changelog.md | 1 + src/afl-showmap.c | 175 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 156 insertions(+), 22 deletions(-) diff --git a/afl-cmin b/afl-cmin index e2c26d91..6b36c261 100755 --- a/afl-cmin +++ b/afl-cmin @@ -234,7 +234,7 @@ BEGIN { } # while options if (!mem_limit) mem_limit = "none" - if (!timeout) timeout = "none" + if (!timeout) timeout = "5000" # get program args i = 0 diff --git a/docs/Changelog.md b/docs/Changelog.md index f33acff9..d4e68036 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,7 @@ data before post process on finds - afl-showmap: - added custom mutator post_process and send support + - add `-I filelist` option, an alternative to `-i in_dir` - a new grammar custom mutator atnwalk was submitted by @voidptr127 ! diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 0b9fc211..09a1d2dc 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -69,7 +69,9 @@ static afl_state_t *afl; static char *stdin_file; /* stdin file */ static u8 *in_dir = NULL, /* input folder */ - *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */ + *out_file = NULL, /* output file or directory */ + *at_file = NULL, /* Substitution string for @@ */ + *in_filelist = NULL; /* input file list */ static u8 outfile[PATH_MAX]; @@ -878,6 +880,104 @@ u32 execute_testcases(u8 *dir) { } +u32 execute_testcases_filelist(u8 *fn) { + + u32 done = 0; + u8 buf[4096]; + u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX]; + FILE *f; + + if (!be_quiet) { ACTF("Reading from '%s'...", fn); } + + if ((f = fopen(fn, "r")) == NULL) { FATAL("could not open '%s'", fn); } + + while (fgets(buf, sizeof(buf), f) != NULL) { + + struct stat st; + + u8 *fn2 = buf, *fn3; + ; + + while (*fn2 == ' ') { + + ++fn2; + + } + + if (*fn2) { + + while (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' || + fn2[strlen(fn2) - 1] == ' ') { + + fn2[strlen(fn2) - 1] = 0; + + } + + } + + if (debug) { printf("Getting coverage for '%s'\n", fn2); } + + if (!*fn2) { continue; } + + if (lstat(fn2, &st) || access(fn2, R_OK)) { + + WARNF("Unable to access '%s'", fn2); + continue; + + } + + if (!S_ISREG(st.st_mode) || !st.st_size) { continue; } + + if ((fn3 = strrchr(fn2, '/'))) { + + ++fn3; + + } else { + + fn3 = fn2; + + } + + if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) { + + WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2, + stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), + stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE)); + + } + + if (!collect_coverage) + snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3); + + if (read_file(fn2)) { + + if (wait_for_gdb) { + + fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid); + fprintf(stderr, "exec: kill -CONT %d\n", getpid()); + kill(0, SIGSTOP); + + } + + showmap_run_target_forkserver(fsrv, in_data, in_len); + ck_free(in_data); + ++done; + + if (child_crashed && debug) { WARNF("crashed: %s", fn2); } + + if (collect_coverage) + analyze_results(fsrv); + else + tcnt = write_results_to_file(fsrv, outfile); + + } + + } + + return done; + +} + /* Show banner. */ static void show_banner(void) { @@ -920,6 +1020,7 @@ static void usage(u8 *argv0) { " With -C, -o is a file, without -C it must be a " "directory\n" " and each bitmap will be written there individually.\n" + " -I filelist - alternatively to -i, -I is a list of files\n" " -C - collect coverage, writes all edges to -o and gives a " "summary\n" " Must be combined with -i.\n" @@ -932,7 +1033,7 @@ static void usage(u8 *argv0) { "This tool displays raw tuple data captured by AFL instrumentation.\n" "For additional help, consult %s/README.md.\n\n" - "If you use -i mode, then custom mutator post_process send send " + "If you use -i/-I mode, then custom mutator post_process send send " "functionality\n" "is supported.\n\n" @@ -994,7 +1095,7 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = true; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) { + while ((opt = getopt(argc, argv, "+i:I:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) { switch (opt) { @@ -1012,6 +1113,11 @@ int main(int argc, char **argv_orig, char **envp) { in_dir = optarg; break; + case 'I': + if (in_filelist) { FATAL("Multiple -I options not supported"); } + in_filelist = optarg; + break; + case 'o': if (out_file) { FATAL("Multiple -o options not supported"); } @@ -1234,10 +1340,12 @@ int main(int argc, char **argv_orig, char **envp) { if (optind == argc || !out_file) { usage(argv[0]); } - if (in_dir) { + if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); } + + if (in_dir || in_filelist) { if (!out_file && !collect_coverage) - FATAL("for -i you need to specify either -C and/or -o"); + FATAL("for -i/-I you need to specify either -C and/or -o"); } @@ -1294,7 +1402,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (in_dir) { + if (in_dir || in_filelist) { /* If we don't have a file name chosen yet, use a safe default. */ u8 *use_dir = "."; @@ -1400,7 +1508,7 @@ int main(int argc, char **argv_orig, char **envp) { } #ifdef __linux__ - if (!fsrv->nyx_mode && in_dir) { + if (!fsrv->nyx_mode && (in_dir || in_filelist)) { (void)check_binary_signatures(fsrv->target_path); @@ -1483,7 +1591,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (in_dir) { + if (in_dir || in_filelist) { afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); afl->afl_env.afl_custom_mutator_library = @@ -1496,33 +1604,46 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) { WARNF( - "Custom mutator environment detected, this is only supported in -i " - "mode!\n"); + "Custom mutator environment detected, this is only supported in " + "-i/-I mode!\n"); } } - if (in_dir) { + if (in_dir || in_filelist) { DIR *dir_in, *dir_out = NULL; + u8 *dn = NULL; if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true; fsrv->dev_null_fd = open("/dev/null", O_RDWR); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } - // if a queue subdirectory exists switch to that - u8 *dn = alloc_printf("%s/queue", in_dir); - if ((dir_in = opendir(dn)) != NULL) { + if (in_filelist) { - closedir(dir_in); - in_dir = dn; + if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist); - } else + } else { - ck_free(dn); - if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir); + // if a queue subdirectory exists switch to that + dn = alloc_printf("%s/queue", in_dir); + + if ((dir_in = opendir(dn)) != NULL) { + + closedir(dir_in); + in_dir = dn; + + } else { + + ck_free(dn); + + } + + if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir); + + } if (!collect_coverage) { @@ -1576,9 +1697,21 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - if (execute_testcases(in_dir) == 0) { + if (in_dir) { - FATAL("could not read input testcases from %s", in_dir); + if (execute_testcases(in_dir) == 0) { + + FATAL("could not read input testcases from %s", in_dir); + + } + + } else { + + if (execute_testcases_filelist(in_filelist) == 0) { + + FATAL("could not read input testcases from %s", in_filelist); + + } } From 46237c33322bbe92d35436718b37062f5c1a8cb6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 24 Apr 2023 19:20:52 +0200 Subject: [PATCH 286/300] makefile for atwalk --- custom_mutators/atnwalk/Makefile | 7 +++++++ custom_mutators/atnwalk/README.md | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 custom_mutators/atnwalk/Makefile diff --git a/custom_mutators/atnwalk/Makefile b/custom_mutators/atnwalk/Makefile new file mode 100644 index 00000000..bf83cae5 --- /dev/null +++ b/custom_mutators/atnwalk/Makefile @@ -0,0 +1,7 @@ +all: atnwalk.so + +atnwalk.so: atnwalk.c + $(CC) -I ../../include/ -shared -fPIC -O3 -o atnwalk.so atnwalk.c + +clean: + rm -f *.so *.o *~ core diff --git a/custom_mutators/atnwalk/README.md b/custom_mutators/atnwalk/README.md index badb856f..730349a3 100644 --- a/custom_mutators/atnwalk/README.md +++ b/custom_mutators/atnwalk/README.md @@ -6,9 +6,7 @@ Refer to [https://github.com/atnwalk/testbed](https://github.com/atnwalk/testbed ## Build -```bash -gcc -I ../../include/ -shared -fPIC -Wall -O3 atnwalk.c -o atnwalk.so -``` +Just type `make` to build `atnwalk.so`. ## Run From 7c3c0b26d1ae477fbae6944c0de18256621e1993 Mon Sep 17 00:00:00 2001 From: Keno Hassler <40292329+kenohassler@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:21:54 +0200 Subject: [PATCH 287/300] document new env var --- docs/env_variables.md | 6 ++++-- src/afl-cc.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index c5995d13..087ccdb7 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -156,7 +156,7 @@ Available options: - LTO - LTO instrumentation - NATIVE - clang's original pcguard based instrumentation - NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16) - - PCGUARD - our own pcgard based instrumentation (default) + - PCGUARD - our own pcguard based instrumentation (default) #### CMPLOG @@ -240,7 +240,9 @@ combined. the default `0x10000`. A value of 0 or empty sets the map address to be dynamic (the original AFL way, which is slower). - `AFL_LLVM_MAP_DYNAMIC` sets the shared memory address to be dynamic. - + - `AFL_LLVM_LTO_SKIPINIT` skips adding initialization code. Some global vars + (e.g. the highest location ID) are not injected. Needed to instrument with + [WAFL](https://github.com/fgsect/WAFL.git). For more information, see [instrumentation/README.lto.md](../instrumentation/README.lto.md). diff --git a/src/afl-cc.c b/src/afl-cc.c index 7f15ad76..d1001187 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2099,6 +2099,8 @@ int main(int argc, char **argv, char **envp) { "bb\n" " AFL_REAL_LD: use this lld linker instead of the compiled in " "path\n" + " AFL_LLVM_LTO_SKIPINIT: don't inject initialization code " + "(used in WAFL mode)\n" "If anything fails - be sure to read README.lto.md!\n"); #endif From 7b33148b7553f11dac7a382495a6829fa14f23fe Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 08:23:27 +0200 Subject: [PATCH 288/300] add AFL_LLVM_LTO_SKIPINIT to envs.h --- include/envs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/envs.h b/include/envs.h index 23599b26..5e68c80b 100644 --- a/include/envs.h +++ b/include/envs.h @@ -160,8 +160,9 @@ static char *afl_environment_variables[] = { "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_TRY_AFFINITY", - "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", + "AFL_LLVM_LTO_SKIPINIT" + "AFL_LLVM_LTO_STARTID", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN", From c0ecf7cf61fdca901b041d57e7e2bb78bc8fcf80 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 08:33:51 +0200 Subject: [PATCH 289/300] only reverse reading the queue on restart --- docs/Changelog.md | 4 ++++ src/afl-fuzz-init.c | 30 ++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index d4e68036..14323ae0 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,10 @@ - afl-fuzz: - new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal data before post process on finds + - reverse reading the seeds only on restarts + - afl-cc: + - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM + (https://github.com/fgsect/WAFL) project - afl-showmap: - added custom mutator post_process and send support - add `-I filelist` option, an alternative to `-i in_dir` diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 01d1e82e..002a26f8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -718,10 +718,21 @@ void read_testcases(afl_state_t *afl, u8 *directory) { if (nl_cnt) { - i = nl_cnt; + u32 done = 0; + + if (unlikely(afl->in_place_resume)) { + + i = nl_cnt; + + } else { + + i = 0; + + } + do { - --i; + if (unlikely(afl->in_place_resume)) { --i; } struct stat st; u8 dfn[PATH_MAX]; @@ -801,18 +812,17 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - /* - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->in_place_resume)) { - u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, - HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; - afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; + if (unlikely(i == 0)) { done = 1; } - } + } else { - */ + if (unlikely(++i == (u32)nl_cnt)) { done = 1; } - } while (i > 0); + } + + } while (!done); } From 7b877e2c1d96efa7486ef4ba7860bec58dd1cd5b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 09:30:25 +0200 Subject: [PATCH 290/300] afl-cmin.bash -T support --- afl-cmin.bash | 107 ++++++++++++++++++++++++++++++++++++++++------ docs/Changelog.md | 2 + 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/afl-cmin.bash b/afl-cmin.bash index 5258758e..ba7083fa 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -7,6 +7,8 @@ # # Copyright 2014, 2015 Google Inc. All rights reserved. # +# Copyright 2019-2023 AFLplusplus +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -36,7 +38,7 @@ # array sizes. # -echo "corpus minimization tool for afl-fuzz by Michal Zalewski" +echo "corpus minimization tool for afl-fuzz" echo ######### @@ -46,14 +48,14 @@ echo # Process command-line options... MEM_LIMIT=none -TIMEOUT=none +TIMEOUT=5000 -unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \ - AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE +unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN F_ARG \ + AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE T_ARG export AFL_QUIET=1 -while getopts "+i:o:f:m:t:eOQUAChXY" opt; do +while getopts "+i:o:f:m:t:T:eOQUAChXY" opt; do case "$opt" in @@ -69,6 +71,7 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do ;; "f") STDIN_FILE="$OPTARG" + F_ARG=1 ;; "m") MEM_LIMIT="$OPTARG" @@ -106,6 +109,9 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do EXTRA_PAR="$EXTRA_PAR -U" UNICORN_MODE=1 ;; + "T") + T_ARG="$OPTARG" + ;; "?") exit 1 ;; @@ -130,9 +136,10 @@ Required parameters: Execution control settings: - -f file - location read by the fuzzed program (stdin) - -m megs - memory limit for child process ($MEM_LIMIT MB) - -t msec - run time limit for child process (none) + -T tasks - how many parallel processes to create (default=1, "all"=nproc) + -f file - location read by the fuzzed program (default: stdin) + -m megs - memory limit for child process (default=$MEM_LIMIT MB) + -t msec - run time limit for child process (default: 5000ms) -O - use binary-only instrumentation (FRIDA mode) -Q - use binary-only instrumentation (QEMU mode) -U - use unicorn-based instrumentation (Unicorn mode) @@ -199,6 +206,11 @@ fi # Check for obvious errors. +if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" ]; then + echo "[-] Error: -T and -f can not be used together." 1>&2 + exit 1 +fi + if [ ! "$MEM_LIMIT" = "none" ]; then if [ "$MEM_LIMIT" -lt "5" ]; then @@ -233,7 +245,7 @@ if [ "$NYX_MODE" = "" ]; then fi -grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && { +grep -aq AFL_DUMP_MAP_SIZE "$TARGET_BIN" && { echo "[!] Trying to obtain the map size of the target ..." MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null` test -n "$MAPSIZE" && { @@ -299,14 +311,29 @@ if [ ! -x "$SHOWMAP" ]; then exit 1 fi +THREADS= +if [ ! "$T_ARG" = "" ]; then + if [ "$T_ARG" = "all" ]; then + THREADS=$(nproc) + else + if [ "$T_ARG" -gt 0 -a "$T_ARG" -le "$(nproc)" ]; then + THREADS=$T_ARG + else + echo "[-] Error: -T parameter must between 1 and $(nproc) or \"all\"." 1>&2 + fi + fi +fi + IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`)) if [ "$IN_COUNT" = "0" ]; then - echo "[+] Hmm, no inputs in the target directory. Nothing to be done." + echo "[-] Hmm, no inputs in the target directory. Nothing to be done." rm -rf "$TRACE_DIR" exit 1 fi +echo "[+] Found $IN_COUNT files for minimizing." + FIRST_FILE=`ls "$IN_DIR" | head -1` # Make sure that we're not dealing with a directory. @@ -355,6 +382,18 @@ else fi +TMPFILE=$OUT_DIR/.list.$$ +if [ ! "$THREADS" = "" ]; then + ls -- "$IN_DIR" > $TMPFILE 2>/dev/null + IN_COUNT=$(cat $TMPFILE | wc -l) + SPLIT=$(($IN_COUNT / $THREADS)) + if [ "$(($IN_COUNT % $THREADS))" -gt 0 ]; then + SPLIT=$(($SPLIT + 1)) + fi + echo "[+] Splitting workload into $THREADS tasks with $SPLIT items on average each." + split -l $SPLIT $TMPFILE $TMPFILE. +fi + # Let's roll! ############################# @@ -363,6 +402,7 @@ fi echo "[*] Obtaining traces for input files in '$IN_DIR'..." +if [ "$THREADS" = "" ]; then ( CUR=0 @@ -386,17 +426,58 @@ echo "[*] Obtaining traces for input files in '$IN_DIR'..." printf "\\r Processing file $CUR/$IN_COUNT... " cp "$IN_DIR/$fn" "$STDIN_FILE" - "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" Date: Tue, 25 Apr 2023 11:56:50 +0200 Subject: [PATCH 291/300] fixes --- afl-cmin.bash | 9 +++++++-- src/afl-fuzz-init.c | 7 ++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/afl-cmin.bash b/afl-cmin.bash index ba7083fa..0e2d973d 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -316,12 +316,16 @@ if [ ! "$T_ARG" = "" ]; then if [ "$T_ARG" = "all" ]; then THREADS=$(nproc) else - if [ "$T_ARG" -gt 0 -a "$T_ARG" -le "$(nproc)" ]; then + if [ "$T_ARG" -gt 1 -a "$T_ARG" -le "$(nproc)" ]; then THREADS=$T_ARG else - echo "[-] Error: -T parameter must between 1 and $(nproc) or \"all\"." 1>&2 + echo "[-] Error: -T parameter must between 2 and $(nproc) or \"all\"." 1>&2 fi fi +else + if [ "$F_ARG" = ""]; then + echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?" + fi fi IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`)) @@ -332,6 +336,7 @@ if [ "$IN_COUNT" = "0" ]; then exit 1 fi +echo "[*] Are you aware that afl-cmin is faster than this afl-cmin.bash script?" echo "[+] Found $IN_COUNT files for minimizing." FIRST_FILE=`ls "$IN_DIR" | head -1` diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 002a26f8..bd591c8f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -756,7 +756,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) { free(nl[i]); /* not tracked */ read_testcases(afl, fn2); ck_free(fn2); - continue; + goto next_entry; } @@ -765,7 +765,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) { if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { ck_free(fn2); - continue; + goto next_entry; } @@ -812,13 +812,14 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } + next_entry: if (unlikely(afl->in_place_resume)) { if (unlikely(i == 0)) { done = 1; } } else { - if (unlikely(++i == (u32)nl_cnt)) { done = 1; } + if (unlikely(++i >= (u32)nl_cnt)) { done = 1; } } From d822181467ec41f1ee2d840c3c5b1918c72ffc86 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 13:13:43 +0200 Subject: [PATCH 292/300] afl-cmin -T support --- afl-cmin | 145 ++++++++++++++++++++++++++++++++++++---------- docs/Changelog.md | 2 +- src/afl-showmap.c | 23 ++++---- 3 files changed, 125 insertions(+), 45 deletions(-) diff --git a/afl-cmin b/afl-cmin index 6b36c261..c8bbd8d7 100755 --- a/afl-cmin +++ b/afl-cmin @@ -103,9 +103,10 @@ function usage() { " -o dir - output directory for minimized files\n" \ "\n" \ "Execution control settings:\n" \ +" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \ " -f file - location read by the fuzzed program (stdin)\n" \ " -m megs - memory limit for child process ("mem_limit" MB)\n" \ -" -t msec - run time limit for child process (default: none)\n" \ +" -t msec - run time limit for child process (default: 5000)\n" \ " -O - use binary-only instrumentation (FRIDA mode)\n" \ " -Q - use binary-only instrumentation (QEMU mode)\n" \ " -U - use unicorn-based instrumentation (unicorn mode)\n" \ @@ -119,7 +120,6 @@ function usage() { "For additional tips, please consult README.md\n" \ "\n" \ "Environment variables used:\n" \ -"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \ "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \ "AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \ "AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \ @@ -159,13 +159,19 @@ BEGIN { # process options Opterr = 1 # default is to diagnose Optind = 1 # skip ARGV[0] - while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXY?")) != -1) { + while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXYT:?")) != -1) { if (_go_c == "i") { if (!Optarg) usage() if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} in_dir = Optarg continue } else + if (_go_c == "T") { + if (!Optarg) usage() + if (threads) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} + threads = Optarg + continue + } else if (_go_c == "o") { if (!Optarg) usage() if (out_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"} @@ -253,21 +259,30 @@ BEGIN { # Do a sanity check to discourage the use of /tmp, since we can't really # handle this safely from an awk script. - if (!ENVIRON["AFL_ALLOW_TMP"]) { - dirlist[0] = in_dir - dirlist[1] = target_bin - dirlist[2] = out_dir - dirlist[3] = stdin_file - "pwd" | getline dirlist[4] # current directory - for (dirind in dirlist) { - dir = dirlist[dirind] + #if (!ENVIRON["AFL_ALLOW_TMP"]) { + # dirlist[0] = in_dir + # dirlist[1] = target_bin + # dirlist[2] = out_dir + # dirlist[3] = stdin_file + # "pwd" | getline dirlist[4] # current directory + # for (dirind in dirlist) { + # dir = dirlist[dirind] + # + # if (dir ~ /^(\/var)?\/tmp/) { + # print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr" + # exit 1 + # } + # } + # delete dirlist + #} - if (dir ~ /^(\/var)?\/tmp/) { - print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr" - exit 1 - } - } - delete dirlist + if (threads && stdin_file) { + print "[-] Error: -T and -f cannot be used together." > "/dev/stderr" + exit 1 + } + + if (!threads && !stdin_file) { + print "[*] Are you aware of the '-T all' parallelize option that massively improves the speed for large corpuses?" } # If @@ is specified, but there's no -f, let's come up with a temporary input @@ -350,6 +365,18 @@ BEGIN { exit 1 } + if (threads) { + "nproc" | getline nproc + if (threads == "all") { + threads = nproc + } else { + if (!(threads > 1 && threads <= nproc)) { + print "[-] Error: -T option must be between 1 and "nproc" or \"all\"." > "/dev/stderr" + exit 1 + } + } + } + # Check for the more efficient way to copy files... if (0 != system("mkdir -p -m 0700 "trace_dir)) { print "[-] Error: Cannot create directory "trace_dir > "/dev/stderr" @@ -459,27 +486,81 @@ BEGIN { # STEP 1: Collecting traces # ############################# + if (threads) { + + inputsperfile = in_count / threads + if (in_count % threads) { + inputsperfile++; + } + + cnt = 0; + tmpfile=out_dir "/.filelist" + for (instance = 1; instance < threads; instance++) { + for (i = 0; i < inputsperfile; i++) { + print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."instance + cnt++ + } + } + for (; cnt < in_count; cnt++) { + print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."threads + } + + print "ls -l "tmpfile"*" + + } + print "[*] Obtaining traces for "in_count" input files in '"in_dir"'." cur = 0; - if (!stdin_file) { - print " Processing "in_count" files (forkserver mode)..." -# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string - retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string) - } else { - print " Processing "in_count" files (forkserver mode)..." -# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" 1) { - if (!ENVIRON["AFL_KEEP_TRACES"]) { - system("rm -rf "trace_dir" 2>/dev/null") - system("rmdir "out_dir) + print "[*] Creating " threads " parallel tasks with about " inputsperfile " each." + for (i = 1; i <= threads; i++) { + + if (!stdin_file) { +# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &" + retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &") + } else { + stdin_file=tmpfile"."i".stdin" +# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" "tmpfile"."i".done ; } &" + retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" "tmpfile"."i".done ; } &") + } } - exit retval + print "[*] Waiting for parallel tasks to complete ..." + # wait for all processes to finish + ok=0 + while (ok < threads) { + ok=0 + for (i = 1; i <= threads; i++) { + if (system("test -f "tmpfile"."i".done") == 0) { + ok++ + } + } + } + print "[*] Done!" + system("rm -f "tmpfile"*") + } else { + if (!stdin_file) { + print " Processing "in_count" files (forkserver mode)..." +# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string + retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string) + } else { + print " Processing "in_count" files (forkserver mode)..." +# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" /dev/null") + system("rmdir "out_dir) + } + exit retval + } + } ####################################################### diff --git a/docs/Changelog.md b/docs/Changelog.md index 816a864d..667fd634 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,7 +14,7 @@ - afl-showmap: - added custom mutator post_process and send support - add `-I filelist` option, an alternative to `-i in_dir` - - afl-cmin.bash: + - afl-cmin + afl-cmin.bash: - `-T threads` parallel task support, huge speedup! - a new grammar custom mutator atnwalk was submitted by @voidptr127 ! diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 09a1d2dc..d0e01cb1 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -894,9 +894,7 @@ u32 execute_testcases_filelist(u8 *fn) { while (fgets(buf, sizeof(buf), f) != NULL) { struct stat st; - - u8 *fn2 = buf, *fn3; - ; + u8 *fn2 = buf, *fn3; while (*fn2 == ' ') { @@ -904,14 +902,11 @@ u32 execute_testcases_filelist(u8 *fn) { } - if (*fn2) { + while (*fn2 && + (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' || + fn2[strlen(fn2) - 1] == ' ')) { - while (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' || - fn2[strlen(fn2) - 1] == ' ') { - - fn2[strlen(fn2) - 1] = 0; - - } + fn2[strlen(fn2) - 1] = 0; } @@ -926,6 +921,8 @@ u32 execute_testcases_filelist(u8 *fn) { } + ++done; + if (!S_ISREG(st.st_mode) || !st.st_size) { continue; } if ((fn3 = strrchr(fn2, '/'))) { @@ -946,9 +943,12 @@ u32 execute_testcases_filelist(u8 *fn) { } - if (!collect_coverage) + if (!collect_coverage) { + snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3); + } + if (read_file(fn2)) { if (wait_for_gdb) { @@ -961,7 +961,6 @@ u32 execute_testcases_filelist(u8 *fn) { showmap_run_target_forkserver(fsrv, in_data, in_len); ck_free(in_data); - ++done; if (child_crashed && debug) { WARNF("crashed: %s", fn2); } From f3dc56f59a25eca60666393b43e0eef4811ac825 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 14:54:38 +0200 Subject: [PATCH 293/300] update custom mutators --- custom_mutators/honggfuzz/honggfuzz.c | 18 +- custom_mutators/honggfuzz/mangle.c | 1269 ++++++++++++--------- custom_mutators/radamsa/radamsa-mutator.c | 11 +- 3 files changed, 722 insertions(+), 576 deletions(-) diff --git a/custom_mutators/honggfuzz/honggfuzz.c b/custom_mutators/honggfuzz/honggfuzz.c index d7b3c9c5..0dd59aee 100644 --- a/custom_mutators/honggfuzz/honggfuzz.c +++ b/custom_mutators/honggfuzz/honggfuzz.c @@ -3,14 +3,14 @@ #include #include -#include "custom_mutator_helpers.h" +#include "afl-fuzz.h" #include "mangle.h" #define NUMBER_OF_MUTATIONS 5 -uint8_t * queue_input; +uint8_t *queue_input; size_t queue_input_size; -afl_state_t * afl_struct; +afl_state_t *afl_struct; run_t run; honggfuzz_t global; struct _dynfile_t dynfile; @@ -18,8 +18,8 @@ struct _dynfile_t dynfile; typedef struct my_mutator { afl_state_t *afl; - run_t * run; - u8 * mutator_buf; + run_t *run; + u8 *mutator_buf; unsigned int seed; unsigned int extras_cnt, a_extras_cnt; @@ -65,9 +65,9 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { /* When a new queue entry is added we check if there are new dictionary entries to add to honggfuzz structure */ -uint8_t afl_custom_queue_new_entry(my_mutator_t * data, - const uint8_t *filename_new_queue, - const uint8_t *filename_orig_queue) { +void afl_custom_queue_new_entry(my_mutator_t *data, + const uint8_t *filename_new_queue, + const uint8_t *filename_orig_queue) { if (run.global->mutate.dictionaryCnt >= 1024) return; @@ -97,7 +97,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data, } - return 0; + return; } diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c index 637d428d..7b7ccb91 100644 --- a/custom_mutators/honggfuzz/mangle.c +++ b/custom_mutators/honggfuzz/mangle.c @@ -39,11 +39,16 @@ #include "libhfcommon/log.h" #include "libhfcommon/util.h" -static inline size_t mangle_LenLeft(run_t* run, size_t off) { - if (off >= run->dynfile->size) { - LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); - } - return (run->dynfile->size - off - 1); +static inline size_t mangle_LenLeft(run_t *run, size_t off) { + + if (off >= run->dynfile->size) { + + LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size); + + } + + return (run->dynfile->size - off - 1); + } /* @@ -51,196 +56,233 @@ static inline size_t mangle_LenLeft(run_t* run, size_t off) { * Based on an idea by https://twitter.com/gamozolabs */ static inline size_t mangle_getLen(size_t max) { - if (max > _HF_INPUT_MAX_SIZE) { - LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE); - } - if (max == 0) { - LOG_F("max == 0"); - } - if (max == 1) { - return 1; - } - /* Give 50% chance the the uniform distribution */ - if (util_rnd64() & 1) { - return (size_t)util_rndGet(1, max); - } + if (max > _HF_INPUT_MAX_SIZE) { + + LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, + (size_t)_HF_INPUT_MAX_SIZE); + + } + + if (max == 0) { LOG_F("max == 0"); } + if (max == 1) { return 1; } + + /* Give 50% chance the the uniform distribution */ + if (util_rnd64() & 1) { return (size_t)util_rndGet(1, max); } + + /* effectively exprand() */ + return (size_t)util_rndGet(1, util_rndGet(1, max)); - /* effectively exprand() */ - return (size_t)util_rndGet(1, util_rndGet(1, max)); } /* Prefer smaller values here, so use mangle_getLen() */ -static inline size_t mangle_getOffSet(run_t* run) { - return mangle_getLen(run->dynfile->size) - 1; +static inline size_t mangle_getOffSet(run_t *run) { + + return mangle_getLen(run->dynfile->size) - 1; + } /* Offset which can be equal to the file size */ -static inline size_t mangle_getOffSetPlus1(run_t* run) { - size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); - return mangle_getLen(reqlen) - 1; +static inline size_t mangle_getOffSetPlus1(run_t *run) { + + size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE); + return mangle_getLen(reqlen) - 1; + } -static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) { - if (off_from >= run->dynfile->size) { - return; - } - if (off_to >= run->dynfile->size) { - return; - } - if (off_from == off_to) { - return; - } +static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to, + size_t len) { - size_t len_from = run->dynfile->size - off_from; - len = HF_MIN(len, len_from); + if (off_from >= run->dynfile->size) { return; } + if (off_to >= run->dynfile->size) { return; } + if (off_from == off_to) { return; } - size_t len_to = run->dynfile->size - off_to; - len = HF_MIN(len, len_to); + size_t len_from = run->dynfile->size - off_from; + len = HF_MIN(len, len_from); + + size_t len_to = run->dynfile->size - off_to; + len = HF_MIN(len, len_to); + + memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len); - memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len); } -static inline void mangle_Overwrite( - run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) { - if (len == 0) { - return; - } - size_t maxToCopy = run->dynfile->size - off; - if (len > maxToCopy) { - len = maxToCopy; - } +static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src, + size_t len, bool printable) { + + if (len == 0) { return; } + size_t maxToCopy = run->dynfile->size - off; + if (len > maxToCopy) { len = maxToCopy; } + + memmove(&run->dynfile->data[off], src, len); + if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); } - memmove(&run->dynfile->data[off], src, len); - if (printable) { - util_turnToPrintable(&run->dynfile->data[off], len); - } } -static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) { - if (run->dynfile->size >= run->global->mutate.maxInputSz) { - return 0; - } - if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { - len = run->global->mutate.maxInputSz - run->dynfile->size; - } +static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len, + bool printable) { - input_setSize(run, run->dynfile->size + len); - mangle_Move(run, off, off + len, run->dynfile->size); - if (printable) { - memset(&run->dynfile->data[off], ' ', len); - } + if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; } + if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) { + + len = run->global->mutate.maxInputSz - run->dynfile->size; + + } + + input_setSize(run, run->dynfile->size + len); + mangle_Move(run, off, off + len, run->dynfile->size); + if (printable) { memset(&run->dynfile->data[off], ' ', len); } + + return len; - return len; } -static inline void mangle_Insert( - run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) { - len = mangle_Inflate(run, off, len, printable); +static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val, + size_t len, bool printable) { + + len = mangle_Inflate(run, off, len, printable); + mangle_Overwrite(run, off, val, len, printable); + +} + +static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len, + bool printable) { + + if (util_rnd64() & 1) { + + mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable); + + } else { + + mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable); + + } + +} + +static inline void mangle_UseValueAt(run_t *run, size_t off, const uint8_t *val, + size_t len, bool printable) { + + if (util_rnd64() & 1) { + mangle_Overwrite(run, off, val, len, printable); + + } else { + + mangle_Insert(run, off, val, len, printable); + + } + } -static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) { - if (util_rnd64() & 1) { - mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable); - } else { - mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable); - } +static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) { + + /* No big deal if those two are overlapping */ + size_t off1 = mangle_getOffSet(run); + size_t maxlen1 = run->dynfile->size - off1; + size_t off2 = mangle_getOffSet(run); + size_t maxlen2 = run->dynfile->size - off2; + size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); + + if (off1 == off2) { return; } + + for (size_t i = 0; i < (len / 2); i++) { + + /* + * First - from the head, next from the tail. Don't worry about layout of + * the overlapping part - there's no good solution to that, and it can be + * left somewhat scrambled, while still preserving the entropy + */ + const uint8_t tmp1 = run->dynfile->data[off2 + i]; + run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i]; + run->dynfile->data[off1 + i] = tmp1; + const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i]; + run->dynfile->data[off2 + (len - 1) - i] = + run->dynfile->data[off1 + (len - 1) - i]; + run->dynfile->data[off1 + (len - 1) - i] = tmp2; + + } + } -static inline void mangle_UseValueAt( - run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) { - if (util_rnd64() & 1) { - mangle_Overwrite(run, off, val, len, printable); - } else { - mangle_Insert(run, off, val, len, printable); - } +static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) { + + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + + /* Use a temp buf, as Insert/Inflate can change source bytes */ + uint8_t *tmpbuf = (uint8_t *)util_Malloc(len); + defer { + + free(tmpbuf); + + }; + + memmove(tmpbuf, &run->dynfile->data[off], len); + + mangle_UseValue(run, tmpbuf, len, printable); + } -static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) { - /* No big deal if those two are overlapping */ - size_t off1 = mangle_getOffSet(run); - size_t maxlen1 = run->dynfile->size - off1; - size_t off2 = mangle_getOffSet(run); - size_t maxlen2 = run->dynfile->size - off2; - size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2)); +static void mangle_Bytes(run_t *run, bool printable) { - if (off1 == off2) { - return; - } + uint16_t buf; + if (printable) { + + util_rndBufPrintable((uint8_t *)&buf, sizeof(buf)); + + } else { + + buf = util_rnd64(); + + } + + /* Overwrite with random 1-2-byte values */ + size_t toCopy = util_rndGet(1, 2); + mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable); - for (size_t i = 0; i < (len / 2); i++) { - /* - * First - from the head, next from the tail. Don't worry about layout of the overlapping - * part - there's no good solution to that, and it can be left somewhat scrambled, - * while still preserving the entropy - */ - const uint8_t tmp1 = run->dynfile->data[off2 + i]; - run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i]; - run->dynfile->data[off1 + i] = tmp1; - const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i]; - run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i]; - run->dynfile->data[off1 + (len - 1) - i] = tmp2; - } } -static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) { - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); +static void mangle_ByteRepeat(run_t *run, bool printable) { - /* Use a temp buf, as Insert/Inflate can change source bytes */ - uint8_t* tmpbuf = (uint8_t*)util_Malloc(len); - defer { - free(tmpbuf); - }; - memmove(tmpbuf, &run->dynfile->data[off], len); + size_t off = mangle_getOffSet(run); + size_t destOff = off + 1; + size_t maxSz = run->dynfile->size - destOff; + + /* No space to repeat */ + if (!maxSz) { + + mangle_Bytes(run, printable); + return; + + } + + size_t len = mangle_getLen(maxSz); + if (util_rnd64() & 0x1) { + + len = mangle_Inflate(run, destOff, len, printable); + + } + + memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); - mangle_UseValue(run, tmpbuf, len, printable); } -static void mangle_Bytes(run_t* run, bool printable) { - uint16_t buf; - if (printable) { - util_rndBufPrintable((uint8_t*)&buf, sizeof(buf)); - } else { - buf = util_rnd64(); - } +static void mangle_Bit(run_t *run, bool printable) { - /* Overwrite with random 1-2-byte values */ - size_t toCopy = util_rndGet(1, 2); - mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable); -} + size_t off = mangle_getOffSet(run); + run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); + if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); } -static void mangle_ByteRepeat(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - size_t destOff = off + 1; - size_t maxSz = run->dynfile->size - destOff; - - /* No space to repeat */ - if (!maxSz) { - mangle_Bytes(run, printable); - return; - } - - size_t len = mangle_getLen(maxSz); - if (util_rnd64() & 0x1) { - len = mangle_Inflate(run, destOff, len, printable); - } - memset(&run->dynfile->data[destOff], run->dynfile->data[off], len); -} - -static void mangle_Bit(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7)); - if (printable) { - util_turnToPrintable(&(run->dynfile->data[off]), 1); - } } static const struct { - const uint8_t val[8]; - const size_t size; + + const uint8_t val[8]; + const size_t size; + } mangleMagicVals[] = { + /* 1B - No endianness */ {"\x00\x00\x00\x00\x00\x00\x00\x00", 1}, {"\x01\x00\x00\x00\x00\x00\x00\x00", 1}, @@ -472,436 +514,543 @@ static const struct { {"\x00\x00\x00\x00\x00\x00\x00\x80", 8}, {"\x01\x00\x00\x00\x00\x00\x00\x80", 8}, {"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8}, + }; -static void mangle_Magic(run_t* run, bool printable) { - uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); - mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable); +static void mangle_Magic(run_t *run, bool printable) { + + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1); + mangle_UseValue(run, mangleMagicVals[choice].val, + mangleMagicVals[choice].size, printable); + } -static void mangle_StaticDict(run_t* run, bool printable) { - if (run->global->mutate.dictionaryCnt == 0) { - mangle_Bytes(run, printable); - return; - } - uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); - mangle_UseValue(run, run->global->mutate.dictionary[choice].val, - run->global->mutate.dictionary[choice].len, printable); +static void mangle_StaticDict(run_t *run, bool printable) { + + if (run->global->mutate.dictionaryCnt == 0) { + + mangle_Bytes(run, printable); + return; + + } + + uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1); + mangle_UseValue(run, run->global->mutate.dictionary[choice].val, + run->global->mutate.dictionary[choice].len, printable); + } -static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) { - if (!run->global->feedback.cmpFeedback) { - return NULL; - } - cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap; - uint32_t cnt = ATOMIC_GET(cmpf->cnt); - if (cnt == 0) { - return NULL; - } - if (cnt > ARRAYSIZE(cmpf->valArr)) { - cnt = ARRAYSIZE(cmpf->valArr); - } - uint32_t choice = util_rndGet(0, cnt - 1); - *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); - if (*len == 0) { - return NULL; - } - return cmpf->valArr[choice].val; +static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) { + + if (!run->global->feedback.cmpFeedback) { return NULL; } + cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap; + uint32_t cnt = ATOMIC_GET(cmpf->cnt); + if (cnt == 0) { return NULL; } + if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); } + uint32_t choice = util_rndGet(0, cnt - 1); + *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len); + if (*len == 0) { return NULL; } + return cmpf->valArr[choice].val; + } -static void mangle_ConstFeedbackDict(run_t* run, bool printable) { - size_t len; - const uint8_t* val = mangle_FeedbackDict(run, &len); - if (val == NULL) { - mangle_Bytes(run, printable); - return; - } - mangle_UseValue(run, val, len, printable); +static void mangle_ConstFeedbackDict(run_t *run, bool printable) { + + size_t len; + const uint8_t *val = mangle_FeedbackDict(run, &len); + if (val == NULL) { + + mangle_Bytes(run, printable); + return; + + } + + mangle_UseValue(run, val, len, printable); + } -static void mangle_MemSet(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX); +static void mangle_MemSet(run_t *run, bool printable) { - if (util_rnd64() & 1) { - len = mangle_Inflate(run, off, len, printable); - } + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + int val = + printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX); + + if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); } + + memset(&run->dynfile->data[off], val, len); - memset(&run->dynfile->data[off], val, len); } -static void mangle_MemClr(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); - int val = printable ? ' ' : 0; +static void mangle_MemClr(run_t *run, bool printable) { - if (util_rnd64() & 1) { - len = mangle_Inflate(run, off, len, printable); - } + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + int val = printable ? ' ' : 0; + + if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); } + + memset(&run->dynfile->data[off], val, len); - memset(&run->dynfile->data[off], val, len); } -static void mangle_RandomBuf(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - size_t len = mangle_getLen(run->dynfile->size - off); +static void mangle_RandomBuf(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + size_t len = mangle_getLen(run->dynfile->size - off); + + if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); } + + if (printable) { + + util_rndBufPrintable(&run->dynfile->data[off], len); + + } else { + + util_rndBuf(&run->dynfile->data[off], len); + + } + +} + +static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen, + uint64_t range, bool printable) { + + int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range; + + switch (varLen) { + + case 1: { + + run->dynfile->data[off] += delta; + break; - if (util_rnd64() & 1) { - len = mangle_Inflate(run, off, len, printable); } - if (printable) { - util_rndBufPrintable(&run->dynfile->data[off], len); + case 2: { + + int16_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap16(val); + val += delta; + val = __builtin_bswap16(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + case 4: { + + int32_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap32(val); + val += delta; + val = __builtin_bswap32(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + case 8: { + + int64_t val; + memcpy(&val, &run->dynfile->data[off], sizeof(val)); + if (util_rnd64() & 0x1) { + + val += delta; + + } else { + + /* Foreign endianess */ + val = __builtin_bswap64(val); + val += delta; + val = __builtin_bswap64(val); + + } + + mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable); + break; + + } + + default: { + + LOG_F("Unknown variable length size: %zu", varLen); + + } + + } + +} + +static void mangle_AddSub(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + + /* 1,2,4,8 */ + size_t varLen = 1U << util_rndGet(0, 3); + if ((run->dynfile->size - off) < varLen) { varLen = 1; } + + uint64_t range; + switch (varLen) { + + case 1: + range = 16; + break; + case 2: + range = 4096; + break; + case 4: + range = 1048576; + break; + case 8: + range = 268435456; + break; + default: + LOG_F("Invalid operand size: %zu", varLen); + + } + + mangle_AddSubWithRange(run, off, varLen, range, printable); + +} + +static void mangle_IncByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; + + } else { + + run->dynfile->data[off] += (uint8_t)1UL; + + } + +} + +static void mangle_DecByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; + + } else { + + run->dynfile->data[off] -= (uint8_t)1UL; + + } + +} + +static void mangle_NegByte(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + if (printable) { + + run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; + + } else { + + run->dynfile->data[off] = ~(run->dynfile->data[off]); + + } + +} + +static void mangle_Expand(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + size_t len; + if (util_rnd64() % 16) { + + len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); + + } else { + + len = mangle_getLen(run->global->mutate.maxInputSz - off); + + } + + mangle_Inflate(run, off, len, printable); + +} + +static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) { + + if (run->dynfile->size <= 2U) { return; } + + size_t off_start = mangle_getOffSet(run); + size_t len = mangle_LenLeft(run, off_start); + if (len == 0) { return; } + if (util_rnd64() % 16) { + + len = mangle_getLen(HF_MIN(16, len)); + + } else { + + len = mangle_getLen(len); + + } + + size_t off_end = off_start + len; + size_t len_to_move = run->dynfile->size - off_end; + + mangle_Move(run, off_end, off_start, len_to_move); + input_setSize(run, run->dynfile->size - len); + +} + +static void mangle_ASCIINum(run_t *run, bool printable) { + + size_t len = util_rndGet(2, 8); + + char buf[20]; + snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); + + mangle_UseValue(run, (const uint8_t *)buf, len, printable); + +} + +static void mangle_ASCIINumChange(run_t *run, bool printable) { + + size_t off = mangle_getOffSet(run); + + /* Find a digit */ + for (; off < run->dynfile->size; off++) { + + if (isdigit(run->dynfile->data[off])) { break; } + + } + + size_t left = run->dynfile->size - off; + if (left == 0) { return; } + + size_t len = 0; + uint64_t val = 0; + /* 20 is maximum lenght of a string representing a 64-bit unsigned value */ + for (len = 0; (len < 20) && (len < left); len++) { + + char c = run->dynfile->data[off + len]; + if (!isdigit(c)) { break; } + val *= 10; + val += (c - '0'); + + } + + switch (util_rndGet(0, 7)) { + + case 0: + val++; + break; + case 1: + val--; + break; + case 2: + val *= 2; + break; + case 3: + val /= 2; + break; + case 4: + val = util_rnd64(); + break; + case 5: + val += util_rndGet(1, 256); + break; + case 6: + val -= util_rndGet(1, 256); + break; + case 7: + val = ~(val); + break; + default: + LOG_F("Invalid choice"); + + }; + + char buf[20]; + snprintf(buf, sizeof(buf), "%-19" PRIu64, val); + + mangle_UseValueAt(run, off, (const uint8_t *)buf, len, printable); + +} + +static void mangle_Splice(run_t *run, bool printable) { + + if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) { + + mangle_Bytes(run, printable); + return; + + } + + size_t sz = 0; + const uint8_t *buf = input_getRandomInputAsBuf(run, &sz); + if (!buf) { + + LOG_E("input_getRandomInputAsBuf() returned no input"); + mangle_Bytes(run, printable); + return; + + } + + if (!sz) { + + mangle_Bytes(run, printable); + return; + + } + + size_t remoteOff = mangle_getLen(sz) - 1; + size_t len = mangle_getLen(sz - remoteOff); + mangle_UseValue(run, &buf[remoteOff], len, printable); + +} + +static void mangle_Resize(run_t *run, bool printable) { + + ssize_t oldsz = run->dynfile->size; + ssize_t newsz = 0; + + uint64_t choice = util_rndGet(0, 32); + switch (choice) { + + case 0: /* Set new size arbitrarily */ + newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); + break; + case 1 ... 4: /* Increase size by a small value */ + newsz = oldsz + (ssize_t)util_rndGet(0, 8); + break; + case 5: /* Increase size by a larger value */ + newsz = oldsz + (ssize_t)util_rndGet(9, 128); + break; + case 6 ... 9: /* Decrease size by a small value */ + newsz = oldsz - (ssize_t)util_rndGet(0, 8); + break; + case 10: /* Decrease size by a larger value */ + newsz = oldsz - (ssize_t)util_rndGet(9, 128); + break; + case 11 ... 32: /* Do nothing */ + newsz = oldsz; + break; + default: + LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); + break; + + } + + if (newsz < 1) { newsz = 1; } + if (newsz > (ssize_t)run->global->mutate.maxInputSz) { + + newsz = run->global->mutate.maxInputSz; + + } + + input_setSize(run, (size_t)newsz); + if (newsz > oldsz) { + + if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); } + + } + +} + +void mangle_mangleContent(run_t *run, int speed_factor) { + + static void (*const mangleFuncs[])(run_t * run, bool printable) = { + + mangle_Shrink, mangle_Expand, mangle_Bit, + mangle_IncByte, mangle_DecByte, mangle_NegByte, + mangle_AddSub, mangle_MemSet, mangle_MemClr, + mangle_MemSwap, mangle_MemCopy, mangle_Bytes, + mangle_ASCIINum, mangle_ASCIINumChange, mangle_ByteRepeat, + mangle_Magic, mangle_StaticDict, mangle_ConstFeedbackDict, + mangle_RandomBuf, mangle_Splice, + + }; + + if (run->mutationsPerRun == 0U) { return; } + if (run->dynfile->size == 0U) { + + mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); + + } + + uint64_t changesCnt = run->global->mutate.mutationsPerRun; + + if (speed_factor < 5) { + + changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); + + } else if (speed_factor < 10) { + + changesCnt = run->global->mutate.mutationsPerRun; + + } else { + + changesCnt = HF_MIN(speed_factor, 10); + changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5)); + + } + + /* If last coverage acquisition was more than 5 secs ago, use splicing more + * frequently */ + if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { + + if (util_rnd64() & 0x1) { + + mangle_Splice(run, run->global->cfg.only_printable); + + } + + } + + for (uint64_t x = 0; x < changesCnt; x++) { + + if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) { + + /* + * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback + * dictionary exists. If so, give it 50% chance of being used among all + * mangling functions. + */ + mangle_ConstFeedbackDict( + run, /* printable= */ run->global->cfg.only_printable); + } else { - util_rndBuf(&run->dynfile->data[off], len); + + uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); + mangleFuncs[choice](run, + /* printable= */ run->global->cfg.only_printable); + } + + } + + wmb(); + } -static inline void mangle_AddSubWithRange( - run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) { - int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range; - - switch (varLen) { - case 1: { - run->dynfile->data[off] += delta; - break; - } - case 2: { - int16_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - val += delta; - } else { - /* Foreign endianess */ - val = __builtin_bswap16(val); - val += delta; - val = __builtin_bswap16(val); - } - mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); - break; - } - case 4: { - int32_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - val += delta; - } else { - /* Foreign endianess */ - val = __builtin_bswap32(val); - val += delta; - val = __builtin_bswap32(val); - } - mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); - break; - } - case 8: { - int64_t val; - memcpy(&val, &run->dynfile->data[off], sizeof(val)); - if (util_rnd64() & 0x1) { - val += delta; - } else { - /* Foreign endianess */ - val = __builtin_bswap64(val); - val += delta; - val = __builtin_bswap64(val); - } - mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable); - break; - } - default: { - LOG_F("Unknown variable length size: %zu", varLen); - } - } -} - -static void mangle_AddSub(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - - /* 1,2,4,8 */ - size_t varLen = 1U << util_rndGet(0, 3); - if ((run->dynfile->size - off) < varLen) { - varLen = 1; - } - - uint64_t range; - switch (varLen) { - case 1: - range = 16; - break; - case 2: - range = 4096; - break; - case 4: - range = 1048576; - break; - case 8: - range = 268435456; - break; - default: - LOG_F("Invalid operand size: %zu", varLen); - } - - mangle_AddSubWithRange(run, off, varLen, range, printable); -} - -static void mangle_IncByte(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - if (printable) { - run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32; - } else { - run->dynfile->data[off] += (uint8_t)1UL; - } -} - -static void mangle_DecByte(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - if (printable) { - run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32; - } else { - run->dynfile->data[off] -= (uint8_t)1UL; - } -} - -static void mangle_NegByte(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - if (printable) { - run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32; - } else { - run->dynfile->data[off] = ~(run->dynfile->data[off]); - } -} - -static void mangle_Expand(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - size_t len; - if (util_rnd64() % 16) { - len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off)); - } else { - len = mangle_getLen(run->global->mutate.maxInputSz - off); - } - - mangle_Inflate(run, off, len, printable); -} - -static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) { - if (run->dynfile->size <= 2U) { - return; - } - - size_t off_start = mangle_getOffSet(run); - size_t len = mangle_LenLeft(run, off_start); - if (len == 0) { - return; - } - if (util_rnd64() % 16) { - len = mangle_getLen(HF_MIN(16, len)); - } else { - len = mangle_getLen(len); - } - size_t off_end = off_start + len; - size_t len_to_move = run->dynfile->size - off_end; - - mangle_Move(run, off_end, off_start, len_to_move); - input_setSize(run, run->dynfile->size - len); -} -static void mangle_ASCIINum(run_t* run, bool printable) { - size_t len = util_rndGet(2, 8); - - char buf[20]; - snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64()); - - mangle_UseValue(run, (const uint8_t*)buf, len, printable); -} - -static void mangle_ASCIINumChange(run_t* run, bool printable) { - size_t off = mangle_getOffSet(run); - - /* Find a digit */ - for (; off < run->dynfile->size; off++) { - if (isdigit(run->dynfile->data[off])) { - break; - } - } - size_t left = run->dynfile->size - off; - if (left == 0) { - return; - } - - size_t len = 0; - uint64_t val = 0; - /* 20 is maximum lenght of a string representing a 64-bit unsigned value */ - for (len = 0; (len < 20) && (len < left); len++) { - char c = run->dynfile->data[off + len]; - if (!isdigit(c)) { - break; - } - val *= 10; - val += (c - '0'); - } - - switch (util_rndGet(0, 7)) { - case 0: - val++; - break; - case 1: - val--; - break; - case 2: - val *= 2; - break; - case 3: - val /= 2; - break; - case 4: - val = util_rnd64(); - break; - case 5: - val += util_rndGet(1, 256); - break; - case 6: - val -= util_rndGet(1, 256); - break; - case 7: - val = ~(val); - break; - default: - LOG_F("Invalid choice"); - }; - - char buf[20]; - snprintf(buf, sizeof(buf), "%-19" PRIu64, val); - - mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable); -} - -static void mangle_Splice(run_t* run, bool printable) { - if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) { - mangle_Bytes(run, printable); - return; - } - - size_t sz = 0; - const uint8_t* buf = input_getRandomInputAsBuf(run, &sz); - if (!buf) { - LOG_E("input_getRandomInputAsBuf() returned no input"); - mangle_Bytes(run, printable); - return; - } - if (!sz) { - mangle_Bytes(run, printable); - return; - } - - size_t remoteOff = mangle_getLen(sz) - 1; - size_t len = mangle_getLen(sz - remoteOff); - mangle_UseValue(run, &buf[remoteOff], len, printable); -} - -static void mangle_Resize(run_t* run, bool printable) { - ssize_t oldsz = run->dynfile->size; - ssize_t newsz = 0; - - uint64_t choice = util_rndGet(0, 32); - switch (choice) { - case 0: /* Set new size arbitrarily */ - newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz); - break; - case 1 ... 4: /* Increase size by a small value */ - newsz = oldsz + (ssize_t)util_rndGet(0, 8); - break; - case 5: /* Increase size by a larger value */ - newsz = oldsz + (ssize_t)util_rndGet(9, 128); - break; - case 6 ... 9: /* Decrease size by a small value */ - newsz = oldsz - (ssize_t)util_rndGet(0, 8); - break; - case 10: /* Decrease size by a larger value */ - newsz = oldsz - (ssize_t)util_rndGet(9, 128); - break; - case 11 ... 32: /* Do nothing */ - newsz = oldsz; - break; - default: - LOG_F("Illegal value from util_rndGet: %" PRIu64, choice); - break; - } - if (newsz < 1) { - newsz = 1; - } - if (newsz > (ssize_t)run->global->mutate.maxInputSz) { - newsz = run->global->mutate.maxInputSz; - } - - input_setSize(run, (size_t)newsz); - if (newsz > oldsz) { - if (printable) { - memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); - } - } -} - -void mangle_mangleContent(run_t* run, int speed_factor) { - static void (*const mangleFuncs[])(run_t * run, bool printable) = { - mangle_Shrink, - mangle_Expand, - mangle_Bit, - mangle_IncByte, - mangle_DecByte, - mangle_NegByte, - mangle_AddSub, - mangle_MemSet, - mangle_MemClr, - mangle_MemSwap, - mangle_MemCopy, - mangle_Bytes, - mangle_ASCIINum, - mangle_ASCIINumChange, - mangle_ByteRepeat, - mangle_Magic, - mangle_StaticDict, - mangle_ConstFeedbackDict, - mangle_RandomBuf, - mangle_Splice, - }; - - if (run->mutationsPerRun == 0U) { - return; - } - if (run->dynfile->size == 0U) { - mangle_Resize(run, /* printable= */ run->global->cfg.only_printable); - } - - uint64_t changesCnt = run->global->mutate.mutationsPerRun; - - if (speed_factor < 5) { - changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun); - } else if (speed_factor < 10) { - changesCnt = run->global->mutate.mutationsPerRun; - } else { - changesCnt = HF_MIN(speed_factor, 10); - changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5)); - } - - /* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */ - if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) { - if (util_rnd64() & 0x1) { - mangle_Splice(run, run->global->cfg.only_printable); - } - } - - for (uint64_t x = 0; x < changesCnt; x++) { - if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) { - /* - * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary - * exists. If so, give it 50% chance of being used among all mangling functions. - */ - mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable); - } else { - uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1); - mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable); - } - } - - wmb(); -} diff --git a/custom_mutators/radamsa/radamsa-mutator.c b/custom_mutators/radamsa/radamsa-mutator.c index 624ace3d..466bb5c3 100644 --- a/custom_mutators/radamsa/radamsa-mutator.c +++ b/custom_mutators/radamsa/radamsa-mutator.c @@ -1,6 +1,5 @@ // This simple example just creates random buffer <= 100 filled with 'A' // needs -I /path/to/AFLplusplus/include -//#include "custom_mutator_helpers.h" #include #include @@ -8,19 +7,17 @@ #include #include "radamsa.h" -#include "custom_mutator_helpers.h" +#include "afl-fuzz.h" typedef struct my_mutator { - afl_t *afl; - - u8 *mutator_buf; - + afl_state_t *afl; + u8 *mutator_buf; unsigned int seed; } my_mutator_t; -my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { srand(seed); my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); From 2e23418a09e6c610288414d4ab6841b6f39513af Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 14:55:31 +0200 Subject: [PATCH 294/300] remove symlinks --- .../honggfuzz/custom_mutator_helpers.h | 22 ------------------- .../radamsa/custom_mutator_helpers.h | 1 - 2 files changed, 23 deletions(-) delete mode 100644 custom_mutators/honggfuzz/custom_mutator_helpers.h delete mode 120000 custom_mutators/radamsa/custom_mutator_helpers.h diff --git a/custom_mutators/honggfuzz/custom_mutator_helpers.h b/custom_mutators/honggfuzz/custom_mutator_helpers.h deleted file mode 100644 index 57754697..00000000 --- a/custom_mutators/honggfuzz/custom_mutator_helpers.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CUSTOM_MUTATOR_HELPERS -#define CUSTOM_MUTATOR_HELPERS - -#include "config.h" -#include "types.h" -#include "afl-fuzz.h" -#include - -#define INITIAL_GROWTH_SIZE (64) - -/* Use in a struct: creates a name_buf and a name_size variable. */ -#define BUF_VAR(type, name) \ - type * name##_buf; \ - size_t name##_size; -/* this filles in `&structptr->something_buf, &structptr->something_size`. */ -#define BUF_PARAMS(struct, name) \ - (void **)&struct->name##_buf, &struct->name##_size - -#undef INITIAL_GROWTH_SIZE - -#endif - diff --git a/custom_mutators/radamsa/custom_mutator_helpers.h b/custom_mutators/radamsa/custom_mutator_helpers.h deleted file mode 120000 index f7532ef9..00000000 --- a/custom_mutators/radamsa/custom_mutator_helpers.h +++ /dev/null @@ -1 +0,0 @@ -../examples/custom_mutator_helpers.h \ No newline at end of file From f94a7e88902f1589b105e74ec1a36e3e3bf01f9e Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Tue, 25 Apr 2023 16:03:21 +0200 Subject: [PATCH 295/300] Add env var to ignore coverage from dynamically loaded code after forkserver. When using TRACEPC instrumentation, loading code dynamically (e.g. through dlopen()) it can be useful to completely ignore the loaded code, esp. when it cannot be preloaded and is not the target to be tested. This patch allows setting AFL_LLVM_IGNORE_PROBLEMS_COVERAGE=1 to do so. --- instrumentation/afl-compiler-rt.o.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index e0e40983..74506e4c 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1563,17 +1563,27 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { "[-] FATAL: forkserver is already up, but an instrumented dlopen() " "library loaded afterwards. You must AFL_PRELOAD such libraries to " "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n" - "To ignore this set AFL_IGNORE_PROBLEMS=1 but this will be bad for " - "coverage.\n"); + "To ignore this set AFL_IGNORE_PROBLEMS=1 but this will lead to " + "ambiguous coverage data.\n" + "In addition, you can set AFL_LLVM_IGNORE_PROBLEMS_COVERAGE=1 to " + "ignore the additional coverage instead (use with caution!).\n"); abort(); } else { + u8 ignore_dso_after_fs = !!getenv("AFL_LLVM_IGNORE_PROBLEMS_COVERAGE"); + if (__afl_debug && ignore_dso_after_fs) { + + fprintf(stderr, "Ignoring coverage from dynamically loaded code\n"); + + } + static u32 offset = 5; while (start < stop) { - if (likely(inst_ratio == 100) || R(100) < inst_ratio) { + if (!ignore_dso_after_fs && + (likely(inst_ratio == 100) || R(100) < inst_ratio)) { *(start++) = offset; From 21865c622483d2e2285de3dfad4626c28ca27843 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 16:47:37 +0200 Subject: [PATCH 296/300] rename env to AFL_IGNORE_PROBLEMS_COVERAGE --- docs/FAQ.md | 3 ++- docs/env_variables.md | 3 ++- include/envs.h | 1 + instrumentation/afl-compiler-rt.o.c | 4 ++-- src/afl-fuzz.c | 2 ++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 4a9080f8..76350c79 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -229,7 +229,8 @@ If you find an interesting or important question missing, submit it via If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then the existing map will be used also for the newly loaded libraries, which allows it to work, however, the efficiency of the fuzzing will be partially - degraded. + degraded. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to + additionally tell AFL++ to ignore any coverage from the late loaded libaries.

diff --git a/docs/env_variables.md b/docs/env_variables.md index 087ccdb7..b1f23159 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -406,7 +406,8 @@ checks or alter some of the more exotic semantics of the tool: - If afl-fuzz encounters an incorrect fuzzing setup during a fuzzing session (not at startup), it will terminate. If you do not want this, then you can - set `AFL_IGNORE_PROBLEMS`. + set `AFL_IGNORE_PROBLEMS`. If you additionally want to also ignore coverage + from late loaded libraries, you can set `AFL_IGNORE_PROBLEMS_COVERAGE`. - When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the fuzzer to import test cases from other instances before doing anything else. diff --git a/include/envs.h b/include/envs.h index 5e68c80b..fe5ee0e3 100644 --- a/include/envs.h +++ b/include/envs.h @@ -106,6 +106,7 @@ static char *afl_environment_variables[] = { "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS", + "AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 74506e4c..0912e52b 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1565,13 +1565,13 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n" "To ignore this set AFL_IGNORE_PROBLEMS=1 but this will lead to " "ambiguous coverage data.\n" - "In addition, you can set AFL_LLVM_IGNORE_PROBLEMS_COVERAGE=1 to " + "In addition, you can set AFL_IGNORE_PROBLEMS_COVERAGE=1 to " "ignore the additional coverage instead (use with caution!).\n"); abort(); } else { - u8 ignore_dso_after_fs = !!getenv("AFL_LLVM_IGNORE_PROBLEMS_COVERAGE"); + u8 ignore_dso_after_fs = !!getenv("AFL_IGNORE_PROBLEMS_COVERAGE"); if (__afl_debug && ignore_dso_after_fs) { fprintf(stderr, "Ignoring coverage from dynamically loaded code\n"); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ebdbb3fa..c44144f5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -259,6 +259,8 @@ static void usage(u8 *argv0, int more_help) { "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_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n" + "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n + " ignore those libs for coverage\n" "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n" "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" From 96848398d45e08eaa69be245c986375808d2b3a7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 17:56:36 +0200 Subject: [PATCH 297/300] fix --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c44144f5..71d2afd8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -259,7 +259,7 @@ static void usage(u8 *argv0, int more_help) { "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_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n" - "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n + "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n" " ignore those libs for coverage\n" "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n" "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" From 432671449f98a675eaf37db52c6318e1edd2423f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Apr 2023 18:19:25 +0200 Subject: [PATCH 298/300] nits --- afl-cmin | 6 ++---- afl-cmin.bash | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/afl-cmin b/afl-cmin index c8bbd8d7..63cfdd7e 100755 --- a/afl-cmin +++ b/afl-cmin @@ -281,8 +281,8 @@ BEGIN { exit 1 } - if (!threads && !stdin_file) { - print "[*] Are you aware of the '-T all' parallelize option that massively improves the speed for large corpuses?" + if (!threads && !stdin_file && !nyx_mode) { + print "[*] Are you aware of the '-T all' parallelize option that improves the speed for large/slow corpuses?" } # If @@ is specified, but there's no -f, let's come up with a temporary input @@ -505,8 +505,6 @@ BEGIN { print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."threads } - print "ls -l "tmpfile"*" - } print "[*] Obtaining traces for "in_count" input files in '"in_dir"'." diff --git a/afl-cmin.bash b/afl-cmin.bash index 0e2d973d..d390ff65 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -206,7 +206,7 @@ fi # Check for obvious errors. -if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" ]; then +if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" -a ! "$NYX_MODE" == 1 ]; then echo "[-] Error: -T and -f can not be used together." 1>&2 exit 1 fi From b18bc7b98fa23ef805ed2ee3eec04dc1929afd49 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 26 Apr 2023 16:25:03 +0200 Subject: [PATCH 299/300] changelog updates --- TODO.md | 1 - docs/Changelog.md | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index dba75070..2efcefea 100644 --- a/TODO.md +++ b/TODO.md @@ -10,7 +10,6 @@ - parallel builds for source-only targets - get rid of check_binary, replace with more forkserver communication - first fuzzer should be a main automatically? not sure. - - reload fuzz binary on signal ## Maybe diff --git a/docs/Changelog.md b/docs/Changelog.md index 667fd634..20b915fa 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -5,9 +5,11 @@ ### Version ++4.07a (dev) - afl-fuzz: + - reverse reading the seeds only on restarts (increases performance) - new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal - data before post process on finds - - reverse reading the seeds only on restarts + data before post process on finds (for atnwalk custom mutator) + - new env `AFL_IGNORE_PROBLEMS_COVERAGE` to ignore coverage from + loaded libs after forkserver initialization (required by Mozilla) - afl-cc: - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM (https://github.com/fgsect/WAFL) project @@ -15,7 +17,7 @@ - added custom mutator post_process and send support - add `-I filelist` option, an alternative to `-i in_dir` - afl-cmin + afl-cmin.bash: - - `-T threads` parallel task support, huge speedup! + - `-T threads` parallel task support, can be a huge speedup! - a new grammar custom mutator atnwalk was submitted by @voidptr127 ! From 74be9ab5ce61d5b561faf688c245143da1a0141e Mon Sep 17 00:00:00 2001 From: vH Date: Fri, 28 Apr 2023 14:55:35 +0200 Subject: [PATCH 300/300] llvm 17 changes --- instrumentation/SanitizerCoverageLTO.so.cc | 6 ++++-- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- instrumentation/afl-llvm-common.h | 2 ++ instrumentation/afl-llvm-dict2file.so.cc | 4 +++- instrumentation/cmplog-routines-pass.cc | 4 +++- instrumentation/cmplog-switches-pass.cc | 4 +++- 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 42583f9e..e779bb79 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -19,8 +19,8 @@ #include "llvm/ADT/SmallVector.h" #if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/Triple.h" + #include "llvm/Analysis/EHPersonalities.h" #endif -#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" @@ -49,7 +49,9 @@ #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 85b1ddd5..8be9e329 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallVector.h" #if LLVM_VERSION_MAJOR < 17 #include "llvm/ADT/Triple.h" + #include "llvm/Analysis/EHPersonalities.h" #endif -#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constant.h" diff --git a/instrumentation/afl-llvm-common.h b/instrumentation/afl-llvm-common.h index 16a13da5..c9324460 100644 --- a/instrumentation/afl-llvm-common.h +++ b/instrumentation/afl-llvm-common.h @@ -22,7 +22,9 @@ typedef long double max_align_t; #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" +#if LLVM_VERSION_MAJOR < 17 #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #if LLVM_VERSION_MAJOR > 3 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 97f1d47f..97155cd6 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -53,7 +53,9 @@ #include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ValueTracking.h" diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 0498156d..39db5aa4 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -38,7 +38,9 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index cd0ae76d..38de669d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -39,7 +39,9 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h"