Compare commits

...

34 Commits

Author SHA1 Message Date
71918ae6ae no expand havoc 2025-01-14 12:45:08 +01:00
7ad694716b no splicing is the new default 2025-01-13 11:57:19 +01:00
e93ab23823 python 3.13+ support 2025-01-13 11:38:38 +01:00
79a24685b2 update unicorn mode 2025-01-06 20:26:32 +01:00
cad7536036 Mutation Chain Tool (#2281)
* Mutation Chain Tool

* Address comments domenukk

* Address comments domenukk 2
2025-01-05 12:35:50 +01:00
1ddfb1fec2 Merge pull request #2282 from vnc0/stable
Enhance compatibility in update_frida_version.sh
2025-01-03 11:28:09 +01:00
ae8df744ee Merge branch 'AFLplusplus:stable' into stable 2024-12-30 01:09:48 +01:00
aaaa96af6d Merge pull request #2280 from GAP-dev/dev
Fix macOS env optimization
2024-12-28 15:46:29 +01:00
2e2a3a2718 Fix macOS env optimization 2024-12-26 17:46:10 +09:00
eee4be90c1 Merge pull request #2279 from jschwartzentruber/upd-filter-docs
update dynamic covfilter readme
2024-12-24 21:12:25 +01:00
5fe21c3797 update dynamic covfilter readme 2024-12-24 10:49:33 -05:00
4eaacfb095 Merge pull request #2278 from AFLplusplus/dev
Push to stable
2024-12-24 14:08:20 +01:00
82b0cf0540 Fix fuzz targets killing on exit (#2277) 2024-12-24 11:11:10 +01:00
5a352adb19 Merge pull request #2276 from martinus/dev
Fix overflow in execs_ps_last_min calculation
2024-12-19 10:34:54 +01:00
9afba51ec1 renamed last_avg_execs -> last_avg_total_execs
This should make it a bit more clear that it stores the total number of executions from the previous update
2024-12-19 07:59:45 +01:00
99402aa31c Fix overflow in execs_ps_last_min calculation
last_avg_execs should be 64bit, same as total_execs, otherwise there is an overflow once total_execs reaches 2^32. Which can happen in practice for long-running fuzzing campaigns.
2024-12-19 07:56:15 +01:00
af11b80fda Enhance compatibility in update_frida_version.sh
Modify sed command to support FreeBSD and macOS
2024-12-18 17:50:55 +01:00
10db3a35cf Merge pull request #2274 from AFLplusplus/dev
Dev
2024-12-17 19:18:52 +01:00
af44b07b31 Merge pull request #2273 from vnc0/stable
Fix macro syntax error in config.h
2024-12-17 19:18:12 +01:00
9b433e2d8c Fix macro syntax error in config.h 2024-12-17 17:55:29 +01:00
85e14cf8d1 Merge pull request #2272 from AFLplusplus/dev
fix gcc plugin test
2024-12-15 18:07:00 +01:00
f2f417325f fix gcc plugin test 2024-12-15 18:06:02 +01:00
3e18b1a10c Merge pull request #2270 from AFLplusplus/dev
fix map size difference bug
2024-12-14 08:17:46 +01:00
1d3e885441 fix map size difference bug 2024-12-13 18:59:26 +01:00
0c69d0a0d8 Merge pull request #2269 from AFLplusplus/dev
push to stable
2024-12-13 12:28:39 +01:00
bbffece7d7 nit 2024-12-13 11:27:26 +01:00
2956b9cc4c support LLVMFuzzerTestOneInput archive targets 2024-12-13 11:05:17 +01:00
9160805f4a add __sanitizer_weak_hook_ support 2024-12-12 15:26:39 +01:00
50e2f9d46c loose file and shared memory permissions on Android and iPhone 2024-12-11 10:36:31 +01:00
223b14134c Merge pull request #2265 from AFLplusplus/dev
push to stable
2024-12-04 11:14:01 +01:00
f5a672f9d8 update makefile for llvm 2024-12-04 08:45:54 +01:00
9ce45665d7 Merge pull request #2264 from exoosh/bump-llvm-version-to-20
Bump LLVM version to 20 available in prerelease, 19 being latest stable
2024-12-04 08:43:12 +01:00
10883b1392 Bumping the upper version boundary for LLVM to 20, which is currently available in prerelease, 19 being latest stable 2024-12-03 15:57:50 +00:00
d206d5fc46 v4.31a 2024-12-03 15:53:01 +01:00
23 changed files with 471 additions and 130 deletions

View File

@ -41,10 +41,6 @@ ARCH = $(shell uname -m)
$(info [*] Compiling AFL++ for OS $(SYS) on ARCH $(ARCH))
ifdef NO_SPLICING
override CFLAGS_OPT += -DNO_SPLICING
endif
ifdef NO_UTF
override CFLAGS_OPT += -DFANCY_BOXES_NO_UTF
endif
@ -65,6 +61,10 @@ ifdef MSAN_BUILD
override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer
override LDFLAGS += -fsanitize=memory
endif
ifdef NO_SPLICING
$(info The NO_SPLICING parameter is deprecated)
endif
ifdef CODE_COVERAGE
override CFLAGS += -D__AFL_CODE_COVERAGE=1
@ -408,7 +408,6 @@ help:
@echo PROFILING - compile afl-fuzz with profiling information
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
@echo NO_PYTHON - disable python support
@echo NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
@echo "NO_UTF - do not use UTF-8 for line rendering in status screen (fallback to G1 box drawing, of vanilla AFL)"
@echo NO_NYX - disable building nyx mode dependencies
@echo "NO_CORESIGHT - disable building coresight (arm64 only)"

View File

@ -28,11 +28,11 @@ MAN_PATH ?= $(PREFIX)/share/man/man8
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
VERSION = $(shell grep '^ *$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
SYS = $(shell uname -s)
override LLVM_TOO_NEW_DEFAULT := 18
override LLVM_TOO_NEW_DEFAULT := 19
override LLVM_TOO_OLD_DEFAULT := 13
ifeq "$(SYS)" "OpenBSD"
@ -69,9 +69,9 @@ endif
LLVM_STDCXX := gnu++11
LLVM_LTO := 0
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.' && echo 1 || echo 0)
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.|^2[0-9]\.' && echo 1 || echo 0)
# Uncomment to see the values assigned above
# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
# $(foreach var,_CLANG_VERSIONS_TO_TEST LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
ifeq "$(LLVMVER)" ""
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
@ -335,7 +335,7 @@ else
endif
ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
CLANG_LFL += $(LLVM_LIBDIR)/libLLVM.so
CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline
# Needed for unwind symbols

View File

@ -3,6 +3,23 @@
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.31a (dev)
- afl-fuzz:
- Python 3.13+ support
- loose file and shared memory permissions on Android and iPhone
- splicing is now DISABLED by default because research showed
it is counterproductive. New command line parameter `-u` to enable
it. Splicing is auto-enabled if two cycles without finds happen.
- afl-cc:
- -fsanitize=fuzzer now inserts libAFLDriver.a addtionally early to help
compiling if LLVMFuzzerTestOneOnput is in an .a archive
- added __sanitizer_weak_hook_* functions (in case that is helpful in
weird setups)
- fix bug with large map sizes when multiple libraries are loaded after
the shared memory was obtained.
### Version ++4.30c (release)
! afl-gcc and afl-clang funcionality is now removed !
- afl-fuzz:

View File

@ -90,7 +90,6 @@ These build options exist:
* PROFILING - compile afl-fuzz with profiling information
* INTROSPECTION - compile afl-fuzz with mutation introspection
* NO_PYTHON - disable python support
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
* NO_UTF - do not use UTF-8 for line rendering in status screen (fallback to G1 box drawing, of vanilla AFL)
* NO_NYX - disable building nyx mode dependencies
* NO_CORESIGHT - disable building coresight (arm64 only)

View File

@ -9,5 +9,11 @@ echo Newest available version: $NEW
test -z "$OLD" -o -z "$NEW" -o "$OLD" = "$NEW" && { echo Nothing to be done. ; exit 0 ; }
sed -i "s/=$OLD/=$NEW/" GNUmakefile || exit 1
# Determine the correct sed command
case $(sed --help 2>&1) in
*GNU*) set sed -i;;
*) set sed -i '';;
esac
"$@" "s/=$OLD/=$NEW/" GNUmakefile || exit 1
echo Successfully updated GNUmakefile

View File

@ -747,7 +747,7 @@ typedef struct afl_state {
up to 256 */
unsigned long long int last_avg_exec_update;
u32 last_avg_execs;
u64 last_avg_total_execs;
double last_avg_execs_saved;
/* foreign sync */

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.30c"
#define VERSION "++4.31a"
/******************************************************
* *
@ -52,6 +52,18 @@
/* Default file permission umode when creating files (default: 0600) */
#define DEFAULT_PERMISSION 0600
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_IOS
#undef DEFAULT_PERMISSION
#define DEFAULT_PERMISSION 0666
#endif
#endif
#ifdef __ANDROID__
#undef DEFAULT_PERMISSION
#define DEFAULT_PERMISSION 0666
#endif
/* SkipDet's global configuration */
#define MINIMAL_BLOCK_SIZE 64

View File

@ -11,7 +11,6 @@
https://www.apache.org/licenses/LICENSE-2.0
*/
#ifdef __AFL_CODE_COVERAGE
@ -358,7 +357,7 @@ static void __afl_map_shm(void) {
if (__afl_final_loc) {
__afl_map_size = ++__afl_final_loc; // as we count starting 0
__afl_map_size = __afl_final_loc + 1; // as we count starting 0
if (getenv("AFL_DUMP_MAP_SIZE")) {
@ -601,9 +600,9 @@ static void __afl_map_shm(void) {
}
__afl_area_ptr_dummy = (u8 *)malloc(__afl_final_loc);
__afl_map_size = __afl_final_loc + 1;
__afl_area_ptr_dummy = (u8 *)malloc(__afl_map_size);
__afl_area_ptr = __afl_area_ptr_dummy;
__afl_map_size = __afl_final_loc;
if (!__afl_area_ptr_dummy) {
@ -2670,6 +2669,89 @@ void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
}
/* llvm weak hooks */
void __sanitizer_weak_hook_memcmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_n((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_memmem(void *pc, const void *s1, size_t len1,
const void *s2, size_t len2, void *result) {
__cmplog_rtn_hook_n((u8 *)s1, (u8 *)s2, len1 < len2 ? (u64)len1 : (u64)len2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncasecmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncasestr(void *pc, const void *s1, const void *s2,
size_t n, char *result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcasecmp(void *pc, const void *s1, const void *s2,
int result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcasestr(void *pc, const void *s1, const void *s2,
size_t n, char *result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcmp(void *pc, const void *s1, const void *s2,
int result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strstr(void *pc, const void *s1, const void *s2,
char *result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
/* COVERAGE manipulation features */
// this variable is then used in the shm setup to create an additional map

View File

@ -695,14 +695,18 @@ static void set_up_environment(char **argv) {
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
@ -710,7 +714,9 @@ static void set_up_environment(char **argv) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}

View File

@ -1764,6 +1764,41 @@ static u8 fsanitize_fuzzer_comma(char *string) {
}
/* Add params to link with libAFLDriver.a on request */
static void add_aflpplib(aflcc_state_t *aflcc) {
if (!aflcc->need_aflpplib) return;
u8 *afllib = find_object(aflcc, "libAFLDriver.a");
if (!be_quiet) {
OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
}
if (!afllib) {
if (!be_quiet) {
WARNF(
"Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
"the flags - this will fail!");
}
} else {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
}
/*
Parse and process possible -fsanitize related args, return PARAM_MISS
if nothing matched. We have 3 main tasks here for these args:
@ -1777,6 +1812,7 @@ static u8 fsanitize_fuzzer_comma(char *string) {
param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
param_st final_ = PARAM_MISS;
u8 insert = 0;
// MACRO START
#define HAVE_SANITIZER_SCAN_KEEP(v, k) \
@ -1822,6 +1858,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
if (scan) {
aflcc->need_aflpplib = 1;
insert = 1;
final_ = PARAM_SCAN;
} else {
@ -1842,6 +1879,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
if (fsanitize_fuzzer_comma(cur_argv_)) {
aflcc->need_aflpplib = 1;
insert = 1;
final_ = PARAM_SCAN;
}
@ -1882,7 +1920,8 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
}
if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv);
if (final_ == PARAM_KEEP) { insert_param(aflcc, cur_argv); }
if (insert) { add_aflpplib(aflcc); }
return final_;
@ -2352,41 +2391,6 @@ void add_lto_passes(aflcc_state_t *aflcc) {
}
/* Add params to link with libAFLDriver.a on request */
static void add_aflpplib(aflcc_state_t *aflcc) {
if (!aflcc->need_aflpplib) return;
u8 *afllib = find_object(aflcc, "libAFLDriver.a");
if (!be_quiet) {
OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
}
if (!afllib) {
if (!be_quiet) {
WARNF(
"Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
"the flags - this will fail!");
}
} else {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
}
/* Add params to link with runtimes depended by our instrumentation */
void add_runtime(aflcc_state_t *aflcc) {
@ -2479,7 +2483,7 @@ void add_runtime(aflcc_state_t *aflcc) {
#endif
add_aflpplib(aflcc);
add_aflpplib(aflcc); // double insertion helps compiling
#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__
insert_param(aflcc, "-Wl,-lrt");
@ -2614,6 +2618,7 @@ void add_misc_params(aflcc_state_t *aflcc) {
insert_param(aflcc, "-fno-builtin-strcasecmp");
insert_param(aflcc, "-fno-builtin-strncasecmp");
insert_param(aflcc, "-fno-builtin-memcmp");
insert_param(aflcc, "-fno-builtin-memmem");
insert_param(aflcc, "-fno-builtin-bcmp");
insert_param(aflcc, "-fno-builtin-strstr");
insert_param(aflcc, "-fno-builtin-strcasestr");

View File

@ -220,14 +220,60 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (py_module != NULL) {
u8 py_notrim = 0;
#if PY_MINOR_VERSION > 12 || PY_MAJOR_VERSION > 3
PyObject_GetOptionalAttrString(py_module, "init",
&py_functions[PY_FUNC_INIT]);
#else
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
#endif
if (!py_functions[PY_FUNC_INIT]) {
WARNF("init function not found in python module");
}
#if PY_MINOR_VERSION > 12 || PY_MAJOR_VERSION > 3
PyObject_GetOptionalAttrString(py_module, "fuzz",
&py_functions[PY_FUNC_FUZZ]);
#else
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
#endif
#if PY_MINOR_VERSION > 12 || PY_MAJOR_VERSION > 3
if (!py_functions[PY_FUNC_FUZZ])
PyObject_GetOptionalAttrString(py_module, "mutate",
&py_functions[PY_FUNC_FUZZ]);
PyObject_GetOptionalAttrString(py_module, "describe",
&py_functions[PY_FUNC_DESCRIBE]);
PyObject_GetOptionalAttrString(py_module, "fuzz_count",
&py_functions[PY_FUNC_FUZZ_COUNT]);
PyObject_GetOptionalAttrString(py_module, "post_process",
&py_functions[PY_FUNC_POST_PROCESS]);
PyObject_GetOptionalAttrString(py_module, "init_trim",
&py_functions[PY_FUNC_INIT_TRIM]);
PyObject_GetOptionalAttrString(py_module, "post_trim",
&py_functions[PY_FUNC_POST_TRIM]);
PyObject_GetOptionalAttrString(py_module, "trim",
&py_functions[PY_FUNC_TRIM]);
PyObject_GetOptionalAttrString(py_module, "havoc_mutation",
&py_functions[PY_FUNC_HAVOC_MUTATION]);
PyObject_GetOptionalAttrString(
py_module, "havoc_mutation_probability",
&py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]);
PyObject_GetOptionalAttrString(py_module, "queue_get",
&py_functions[PY_FUNC_QUEUE_GET]);
PyObject_GetOptionalAttrString(py_module, "fuzz_send",
&py_functions[PY_FUNC_FUZZ_SEND]);
PyObject_GetOptionalAttrString(py_module, "post_run",
&py_functions[PY_FUNC_POST_RUN]);
PyObject_GetOptionalAttrString(py_module, "splice_optout",
&py_functions[PY_FUNC_SPLICE_OPTOUT]);
PyObject_GetOptionalAttrString(py_module, "queue_new_entry",
&py_functions[PY_FUNC_QUEUE_NEW_ENTRY]);
PyObject_GetOptionalAttrString(py_module, "introspection",
&py_functions[PY_FUNC_INTROSPECTION]);
PyObject_GetOptionalAttrString(py_module, "deinit",
&py_functions[PY_FUNC_DEINIT]);
#else
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
py_functions[PY_FUNC_DESCRIBE] =
@ -253,12 +299,13 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "post_run");
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] =
PyObject_GetAttrString(py_module, "introspection");
py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
#endif
if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { afl->custom_splice_optout = 1; }
if (!py_functions[PY_FUNC_DEINIT])
WARNF("deinit function not found in python module");

View File

@ -104,9 +104,6 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->min_length = 1;
afl->max_length = MAX_FILE;
afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000;
#ifndef NO_SPLICING
afl->use_splicing = 1;
#endif
afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL;
afl->q_testcase_max_cache_entries = 64 * 1024;

View File

@ -340,9 +340,9 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
cur_time - afl->last_avg_exec_update >= 60000))) {
afl->last_avg_execs_saved =
(double)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) /
(double)(1000 * (afl->fsrv.total_execs - afl->last_avg_total_execs)) /
(double)(cur_time - afl->last_avg_exec_update);
afl->last_avg_execs = afl->fsrv.total_execs;
afl->last_avg_total_execs = afl->fsrv.total_execs;
afl->last_avg_exec_update = cur_time;
}

View File

@ -170,7 +170,7 @@ static void at_exit() {
if (pid2 > 0) {
pgrp = getpgid(pid1);
pgrp = getpgid(pid2);
if (pgrp > 0) { killpg(pgrp, kill_signal); }
kill(pid2, kill_signal);
@ -238,6 +238,7 @@ static void usage(u8 *argv0, int more_help) {
"immediately,\n"
" -1 = immediately and together with normal mutation.\n"
" Note: this option is usually not very effective\n"
" -u - enable testcase splicing\n"
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
" if using QEMU/FRIDA or the fuzzing target is "
@ -443,10 +444,6 @@ static void usage(u8 *argv0, int more_help) {
SAYF("Compiled with ASAN_BUILD.\n");
#endif
#ifdef NO_SPLICING
SAYF("Compiled with NO_SPLICING.\n");
#endif
#ifdef FANCY_BOXES_NO_UTF
SAYF("Compiled without UTF-8 support for line rendering in status screen.\n");
#endif
@ -611,7 +608,7 @@ int main(int argc, char **argv_orig, char **envp) {
// still available: HjJkKqruvwz
while ((opt = getopt(argc, argv,
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
"T:UV:WXx:YzZ")) > 0) {
"T:uUV:WXx:YzZ")) > 0) {
switch (opt) {
@ -699,6 +696,10 @@ int main(int argc, char **argv_orig, char **envp) {
afl->old_seed_selection = 1;
break;
case 'u':
afl->use_splicing = 1;
break;
case 'I':
afl->infoexec = optarg;
break;
@ -1965,7 +1966,9 @@ int main(int argc, char **argv_orig, char **envp) {
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
}
@ -1974,7 +1977,9 @@ int main(int argc, char **argv_orig, char **envp) {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
@ -1992,7 +1997,9 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
OKF("Injecting %s ...", frida_binary);
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}
@ -2957,67 +2964,59 @@ int main(int argc, char **argv_orig, char **envp) {
++afl->cycles_wo_finds;
if (afl->use_splicing) {
#if 0
if (unlikely(afl->shm.cmplog_mode &&
afl->cmplog_max_filesize < MAX_FILE)) {
if (unlikely(afl->shm.cmplog_mode &&
afl->cmplog_max_filesize < MAX_FILE)) {
afl->cmplog_max_filesize <<= 4;
}
switch (afl->expand_havoc) {
case 0:
// this adds extra splicing mutation options to havoc mode
afl->expand_havoc = 1;
break;
case 1:
// add MOpt mutator
/*
if (afl->limit_time_sig == 0 && !afl->custom_only &&
!afl->python_only) {
afl->limit_time_sig = -1;
afl->limit_time_puppet = 0;
}
*/
afl->expand_havoc = 2;
if (afl->cmplog_lvl && afl->cmplog_lvl < 2) afl->cmplog_lvl = 2;
break;
case 2:
// increase havoc mutations per fuzz attempt
afl->havoc_stack_pow2++;
afl->expand_havoc = 3;
break;
case 3:
// further increase havoc mutations per fuzz attempt
afl->havoc_stack_pow2++;
afl->expand_havoc = 4;
break;
case 4:
afl->expand_havoc = 5;
// if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl =
// 3;
break;
case 5:
// nothing else currently
break;
}
} else {
#ifndef NO_SPLICING
afl->use_splicing = 1;
#else
afl->use_splicing = 0;
#endif
afl->cmplog_max_filesize <<= 4;
}
switch (afl->expand_havoc) {
case 0:
// this adds extra splicing mutation options to havoc mode
afl->expand_havoc = 1;
break;
case 1:
// if we did not use splicing (default) then activate it
afl->use_splicing = 1;
// add MOpt mutator
/*
if (afl->limit_time_sig == 0 && !afl->custom_only &&
!afl->python_only) {
afl->limit_time_sig = -1;
afl->limit_time_puppet = 0;
}
*/
afl->expand_havoc = 2;
if (afl->cmplog_lvl && afl->cmplog_lvl < 2) afl->cmplog_lvl = 2;
break;
case 2:
// increase havoc mutations per fuzz attempt
afl->havoc_stack_pow2++;
afl->expand_havoc = 3;
break;
case 3:
// further increase havoc mutations per fuzz attempt
afl->havoc_stack_pow2++;
afl->expand_havoc = 4;
break;
case 4:
afl->expand_havoc = 5;
// if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl =
// 3;
break;
case 5:
// nothing else currently
break;
}
#endif
} else {
afl->cycles_wo_finds = 0;
@ -3430,7 +3429,7 @@ stop_fuzzing:
ZLIBCLOSE(fr_fd);
afl->var_byte_count = count_bytes(afl, afl->var_bytes);
OKF("Written fastresume.bin with %u bytes!", w);
OKF("fastresume.bin succesfully written with %u bytes.", w);
} else {

View File

@ -740,14 +740,18 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
@ -755,7 +759,9 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}

View File

@ -714,14 +714,18 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
@ -729,7 +733,9 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}

View File

@ -81,7 +81,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
# now for the special gcc_plugin things
echo foobar.c > instrumentlist.txt
AFL_COMPILER_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1
AFL_GCC_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1
test -x test-compcov && test_compcov_binary_functionality ./test-compcov && {
echo 1 | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 0 tuples" && {
$ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly"

View File

@ -1 +1 @@
2abdcd3c
fb3d2151

View File

@ -56,6 +56,10 @@ Here's a quick overview of the stuff you can find in this directory:
- libpng_no_checksum - a sample patch for removing CRC checks in libpng.
- mutation_chain - a tool that backtraces the mutation chain of AFL
crash files based on the crash/queue file naming
standards and outputs this in a json format.
- persistent_mode - an example of how to use the LLVM persistent process
mode to speed up certain fuzzing jobs.

View File

@ -233,7 +233,9 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
} else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}

View File

@ -16,7 +16,7 @@ Once you have built AFL++, you can choose out of two approaches:
## Simple Selection with `AFL_PC_FILTER`
This approach requires a build with `AFL_INSTRUMENTATION=llvmnative` or
This approach requires a build with `AFL_LLVM_INSTRUMENT=llvmnative` or
`llvmcodecov` as well as an AddressSanitizer build with debug information.
By setting the environment variable `AFL_PC_FILTER` to a string, the runtime
@ -52,7 +52,7 @@ PC. It also works well with Nyx, where symbolizing is usually disabled for the
target process to avoid delays with frequent crashes.
Similar to the previous method, This approach requires a build with
`AFL_INSTRUMENTATION=llvmnative` or `llvmcodecov` as well debug information.
`AFL_LLVM_INSTRUMENT=llvmnative` or `llvmcodecov` as well debug information.
However, it does not require the ASan runtime as it doesn't do the symbolizing
in process. Due to the way it maps PCs to symbols, it is less accurate when it
comes to includes and inlines (it assumes all PCs within a function belong to

View File

@ -0,0 +1,154 @@
#!/usr/bin/env python3
#
# MUTATION CHAIN COMPUTATION TOOL
#
# Ever wondered what the complete history of your AFL crash file looks like?
# Now you can!
#
# This tool is developed to support file structures for parallel fuzzing runs using the
# naming of main/secondary nodes as stated in the AFL docs (fuzzer01, fuzzer02 etc...)
# In case you want to use it for single node runs just recreate the directory structure
# which is used when parallel fuzzing is used (dump your results in a dir called fuzzer01).
#
# author: Maarten Dekker
# import required modules
import os, re, json
import argparse
crashes = {}
queues = {}
def fillDictWithFilenameKeys(dir):
dict = {}
for filename in os.listdir(dir):
if re.match("^id:\\d+", filename):
dict[filename] = None
return dict
# recusively compute the chain of queue items that led to the AFL crash file
def compute_mutation_chain(filename, current_fuzzer, n):
if re.match(".*src:(\\d+),", filename):
source_id = re.match(".*src:(\\d+),", filename).group(1)
file_we_look_for_rex = "^id:" + source_id + ","
fuzzer_queue = None
# determine if we need to look in the queue of another fuzzer instance
if re.match(".*sync:(fuzzer\\d+),", filename):
fuzzer_queue = re.match(".*sync:(fuzzer\\d+),", filename).group(1)
else:
fuzzer_queue = current_fuzzer
for k,v in queues[fuzzer_queue].items():
if re.match(file_we_look_for_rex, k):
retval = {}
retval[k] = compute_mutation_chain(k, fuzzer_queue, n+1)
return retval
# if the mutation result is a splice it thas 2 sources
elif re.match(".*src:(\\d+)\\+(\\d+)", filename):
sources = re.match(".*src:(\\d+)\\+(\\d+)", filename)
source_id_1 = sources.group(1)
source_id_2 = sources.group(2)
file_we_look_for_1_rex = "^id:" + source_id_1 + ","
file_we_look_for_2_rex = "^id:" + source_id_2 + ","
# for mutation with two sources, the sources are never synced form other queues
retval = {}
for k,v in queues[current_fuzzer].items():
if re.match(file_we_look_for_1_rex, k):
retval[k] = compute_mutation_chain(k, current_fuzzer, n+1)
elif re.match(file_we_look_for_2_rex, k):
retval[k] = compute_mutation_chain(k, current_fuzzer, n+1)
return retval
else:
return "seed"
def main():
parser = argparse.ArgumentParser(
prog='mutation_chain.py',
description='Compute the mutation chain of AFL crash files to visulise the mutation history from seed files to crash' +
'This tool just dump json data to the CLI, it is advised to echo them into a file for further analysis (i.e. [command] >> your_file.json)',
epilog='Greetings from old zealand'
)
parser.add_argument(
"-m", "--mode",
choices = ['single', 'all'],
help = 'compute chain for one file or all crash files in supplied directory. In single mode the -f argument is required',
required = True
)
parser.add_argument(
"-i", "--input",
action = 'store',
help = 'Input directory for the mutation chain tool (the fuzzer\'s output directory)',
required = True
)
parser.add_argument(
"-n", "--node",
action = 'store',
help = '[Only used in single mode; optinal] name of the fuzzer node that contains the crash file supplied in the --file argument (e.g. \'fuzzer03\'). Defaults to \'fuzzer01\' if not supplied',
required = False
)
parser.add_argument(
"-f", "--file",
action = 'store',
help = '[Only used in single mode; required] filename of specific crash file (e.g. \'id:000008,sig:06,src:000005,op:havoc,rep:8\')',
required = False
)
args = parser.parse_args()
if args.mode == "single":
if args.node == None:
args.node = "fuzzer01"
if args.file == None:
parser.error("'--mode single' requires the '--file' argument.")
crash_file_path = args.input + '/' + args.node + '/crashes/' + args.file
if not os.path.isfile(crash_file_path):
print("Error: \'" + crash_file_path + "\' does not exist.\nPlease verify whether the node and filename are correct.")
return
# Create the interal representation of the various queues of parallel fuzzing nodes
for dir in os.listdir(args.input):
if re.match("^fuzzer\\d+", dir):
queues[dir] = fillDictWithFilenameKeys(args.input + '/' + dir + '/queue')
if args.mode == "all":
for dir in os.listdir(args.input):
if re.match("^fuzzer\\d+", dir):
for filename in os.listdir(args.input + '/' + dir + "/crashes"):
if re.match("^id:\\d+", filename):
print(filename)
crashes[filename] = compute_mutation_chain(filename, dir, 0)
elif args.mode == "single":
crashes[args.file] = compute_mutation_chain(args.file, args.node, 0)
print(json.dumps(crashes, sort_keys=True, indent=4))
if __name__ == '__main__':
main()