From 64293cdc82e4b313532e46788782cd43cdbefc2c Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Thu, 30 May 2024 11:13:56 +0300 Subject: [PATCH 01/30] Create make_dict.sh --- utils/libtokencap/make_dict.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 utils/libtokencap/make_dict.sh diff --git a/utils/libtokencap/make_dict.sh b/utils/libtokencap/make_dict.sh new file mode 100644 index 00000000..92c383fa --- /dev/null +++ b/utils/libtokencap/make_dict.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +LD_PRELOAD_PATH="/path/to/libtokencap.so" +AFL_TOKEN_FILE=${PWD}/temp_output.txt +AFL_DICT_FILE=$(basename ${target_output}) +target_bin="/path/to/target/program" +target_output="/path/to/target/output" +timeout_sec="5" + +{ +touch $AFL_TOKEN_FILE +for i in $(find ${target_output} -type f -name "id*"); do + LD_PRELOAD=${LD_PRELOAD_PATH} \ + timeout -s SIGKILL ${timeout_sec} \ + ${target_bin} ${i} +done +} >${AFL_TOKEN_FILE} + +sort -u ${AFL_TOKEN_FILE} >${AFL_DICT_FILE}.dict From eecbdd99e177698c93873db351299467a910fc0e Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Thu, 30 May 2024 22:26:24 +0300 Subject: [PATCH 02/30] Update and rename make_dict.sh to make_dict_v2.sh --- utils/libtokencap/make_dict.sh | 19 ------------ utils/libtokencap/make_dict_v2.sh | 51 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 19 deletions(-) delete mode 100644 utils/libtokencap/make_dict.sh create mode 100644 utils/libtokencap/make_dict_v2.sh diff --git a/utils/libtokencap/make_dict.sh b/utils/libtokencap/make_dict.sh deleted file mode 100644 index 92c383fa..00000000 --- a/utils/libtokencap/make_dict.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -LD_PRELOAD_PATH="/path/to/libtokencap.so" -AFL_TOKEN_FILE=${PWD}/temp_output.txt -AFL_DICT_FILE=$(basename ${target_output}) -target_bin="/path/to/target/program" -target_output="/path/to/target/output" -timeout_sec="5" - -{ -touch $AFL_TOKEN_FILE -for i in $(find ${target_output} -type f -name "id*"); do - LD_PRELOAD=${LD_PRELOAD_PATH} \ - timeout -s SIGKILL ${timeout_sec} \ - ${target_bin} ${i} -done -} >${AFL_TOKEN_FILE} - -sort -u ${AFL_TOKEN_FILE} >${AFL_DICT_FILE}.dict diff --git a/utils/libtokencap/make_dict_v2.sh b/utils/libtokencap/make_dict_v2.sh new file mode 100644 index 00000000..98dfc7fe --- /dev/null +++ b/utils/libtokencap/make_dict_v2.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +#default values +timeout_sec=5 +LD_PRELOAD_PATH="/home/${USER}/AFLplusplus/utils/libtokencap/libtokencap.so" + +#help +usage() { + echo "Usage: $0 -o -b [-t ] [-p ]" + echo "Options:" + echo " -o Path to target output directory" + echo " -b Path to target program binary" + echo " -t Timeout in seconds (default: 5)" + echo " -p Path to LD_PRELOAD library (default: ${LD_PRELOAD_PATH})" + exit 1 +} + +#parse cli options +while getopts ":o:b:t:p:" opt; do + case $opt in + o) target_output="$OPTARG" ;; + b) target_bin="$OPTARG" ;; + t) timeout_sec="$OPTARG" ;; + p) LD_PRELOAD_PATH="$OPTARG" ;; + \?) echo "Invalid option: -$OPTARG" >&2; usage ;; + :) echo "Option -$OPTARG requires an args" >&2; usage ;; + esac +done + +#check options +if [ -z "$target_output" ] || [ -z "$target_bin" ]; then + echo "Error: Missing mandatory opts" >&2 + usage +fi + +# initialize vars +AFL_TOKEN_FILE="${PWD}/temp_output.txt" +AFL_DICT_FILE="$(basename "$target_output").dict" + +#generate token-file +{ + touch "$AFL_TOKEN_FILE" + for i in $(find "$target_output" -type f -name "id*"); do + LD_PRELOAD="$LD_PRELOAD_PATH" \ + timeout -s SIGKILL "$timeout_sec" \ + "$target_bin" "$i" + done +} >"$AFL_TOKEN_FILE" + +# sort & remove duplicates +sort -u "$AFL_TOKEN_FILE" >"$AFL_DICT_FILE" From c202d80dea287c9aaaa6c0dd3eba49398e0b247c Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Thu, 30 May 2024 22:38:37 +0300 Subject: [PATCH 03/30] Update make_dict_v2.sh --- utils/libtokencap/make_dict_v2.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/utils/libtokencap/make_dict_v2.sh b/utils/libtokencap/make_dict_v2.sh index 98dfc7fe..0e8ca531 100644 --- a/utils/libtokencap/make_dict_v2.sh +++ b/utils/libtokencap/make_dict_v2.sh @@ -1,5 +1,3 @@ -#!/bin/bash - #default values timeout_sec=5 LD_PRELOAD_PATH="/home/${USER}/AFLplusplus/utils/libtokencap/libtokencap.so" From 5e708b23c60e0d95f1d12897e5a47a08b1ade1c0 Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:18:03 +0300 Subject: [PATCH 04/30] Update make_dict_v2.sh (-) removed default vars ; (+) added LD_PRELOAD_PATH check --- utils/libtokencap/make_dict_v2.sh | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/utils/libtokencap/make_dict_v2.sh b/utils/libtokencap/make_dict_v2.sh index 0e8ca531..1ddec06b 100644 --- a/utils/libtokencap/make_dict_v2.sh +++ b/utils/libtokencap/make_dict_v2.sh @@ -1,32 +1,28 @@ -#default values -timeout_sec=5 -LD_PRELOAD_PATH="/home/${USER}/AFLplusplus/utils/libtokencap/libtokencap.so" - #help usage() { - echo "Usage: $0 -o -b [-t ] [-p ]" + echo "Usage: $0 -o -b -p [-t ]" echo "Options:" echo " -o Path to target output directory" echo " -b Path to target program binary" - echo " -t Timeout in seconds (default: 5)" - echo " -p Path to LD_PRELOAD library (default: ${LD_PRELOAD_PATH})" + echo " -p Path to LD_PRELOAD library" + echo " -t Timeout in seconds" exit 1 } #parse cli options -while getopts ":o:b:t:p:" opt; do +while getopts ":o:b:p:t:" opt; do case $opt in o) target_output="$OPTARG" ;; b) target_bin="$OPTARG" ;; - t) timeout_sec="$OPTARG" ;; p) LD_PRELOAD_PATH="$OPTARG" ;; + t) timeout_sec="$OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2; usage ;; - :) echo "Option -$OPTARG requires an args" >&2; usage ;; + :) echo "Option -$OPTARG requires an argument." >&2; usage ;; esac done #check options -if [ -z "$target_output" ] || [ -z "$target_bin" ]; then +if [ -z "$target_output" ] || [ -z "$target_bin" ] || [ -z "$LD_PRELOAD_PATH" ]; then echo "Error: Missing mandatory opts" >&2 usage fi From 4cf358b58920ea843a9e7e38309fe7df37fcb81f Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Sat, 1 Jun 2024 02:06:20 +0300 Subject: [PATCH 05/30] Update README.md --- utils/libtokencap/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md index 8705452c..0e8b7ce1 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -69,3 +69,21 @@ need to be changed for other OSes. Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen) +Also, the following example (make_dict_v2.sh) shows how to use a script to capture tokens from the +files in the target output directory, +and then generate a dictionary file from those tokens. + +#### usage: +```bash +./make_dict_v2.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 +``` +#### description opts: +- ```-o``` : Path to target output directory ; +- ```-b``` : Path to target program binary ; +- ```-p``` : Path to LD_PRELOAD library ; +- ```-t``` : Timeout in seconds + +#### output: +The script generates a temporary token file (```temp_output.txt```) in the current working directory, +containing tokens captured during the execution of the target binary. +A sorted and unique token dictionary file is created in the same directory as the target output, with a ```*.dict``` extension. From d2700c7525254e9400227afe2010d366bea2aabf Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Sat, 1 Jun 2024 13:03:22 +0300 Subject: [PATCH 06/30] Update README.md --- utils/libtokencap/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md index 0e8b7ce1..d1c1b8b3 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -69,13 +69,13 @@ need to be changed for other OSes. Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen) -Also, the following example (make_dict_v2.sh) shows how to use a script to capture tokens from the +Also, the following example (generate_libtoken_dict.sh) shows how to use a script to capture tokens from the files in the target output directory, and then generate a dictionary file from those tokens. #### usage: ```bash -./make_dict_v2.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 +./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 ``` #### description opts: - ```-o``` : Path to target output directory ; From 5fb657f56945dcc7bc2ed2817fac863b69315ac7 Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Sat, 1 Jun 2024 13:03:55 +0300 Subject: [PATCH 07/30] Rename make_dict_v2.sh to generate_libtoken_dict.sh --- utils/libtokencap/{make_dict_v2.sh => generate_libtoken_dict.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename utils/libtokencap/{make_dict_v2.sh => generate_libtoken_dict.sh} (100%) diff --git a/utils/libtokencap/make_dict_v2.sh b/utils/libtokencap/generate_libtoken_dict.sh similarity index 100% rename from utils/libtokencap/make_dict_v2.sh rename to utils/libtokencap/generate_libtoken_dict.sh From 1db82f3303551a604e9d7d22a9159da0dfff1aa0 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 3 Jun 2024 09:23:43 +0200 Subject: [PATCH 08/30] update grammar mutator --- custom_mutators/grammar_mutator/GRAMMAR_VERSION | 2 +- custom_mutators/grammar_mutator/grammar_mutator | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION index 3a019448..02119caf 100644 --- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION +++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION @@ -1 +1 @@ -5ed4f8d +95a6857 diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator index 5ed4f8d6..95a68577 160000 --- a/custom_mutators/grammar_mutator/grammar_mutator +++ b/custom_mutators/grammar_mutator/grammar_mutator @@ -1 +1 @@ -Subproject commit 5ed4f8d6e6524df9670af6b411b13031833d67d2 +Subproject commit 95a685773e571620cb6e2788dbbdba333e1b9bfd From b8536ced093ca46f004bea76adbd1ad484d8a8d7 Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:01:50 +0300 Subject: [PATCH 09/30] Update generate_libtoken_dict.sh --- utils/libtokencap/generate_libtoken_dict.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/utils/libtokencap/generate_libtoken_dict.sh b/utils/libtokencap/generate_libtoken_dict.sh index 1ddec06b..cc8c5de7 100644 --- a/utils/libtokencap/generate_libtoken_dict.sh +++ b/utils/libtokencap/generate_libtoken_dict.sh @@ -1,6 +1,6 @@ #help usage() { - echo "Usage: $0 -o -b -p [-t ]" + echo "Usage: $0 -o -b -p [-t ] -- [target_args]" echo "Options:" echo " -o Path to target output directory" echo " -b Path to target program binary" @@ -21,6 +21,9 @@ while getopts ":o:b:p:t:" opt; do esac done +#shift away the parsed opts +shift $((OPTIND - 1)) + #check options if [ -z "$target_output" ] || [ -z "$target_bin" ] || [ -z "$LD_PRELOAD_PATH" ]; then echo "Error: Missing mandatory opts" >&2 @@ -29,7 +32,7 @@ fi # initialize vars AFL_TOKEN_FILE="${PWD}/temp_output.txt" -AFL_DICT_FILE="$(basename "$target_output").dict" +AFL_DICT_FILE="${PWD}/$(basename "$target_bin")_tokens.dict" #generate token-file { @@ -37,9 +40,16 @@ AFL_DICT_FILE="$(basename "$target_output").dict" for i in $(find "$target_output" -type f -name "id*"); do LD_PRELOAD="$LD_PRELOAD_PATH" \ timeout -s SIGKILL "$timeout_sec" \ - "$target_bin" "$i" + "$target_bin" "$@" "$i" done } >"$AFL_TOKEN_FILE" # sort & remove duplicates sort -u "$AFL_TOKEN_FILE" >"$AFL_DICT_FILE" + +# delete temp-file +rm "$AFL_TOKEN_FILE" + +# print done-message +echo "Token dictionary created: $AFL_DICT_FILE" +echo "Script completed successfully" From bc2ccf464ff966adb2cbb17c0ff9957cf35ab513 Mon Sep 17 00:00:00 2001 From: Alexander Shvedov <60114847+a-shvedov@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:14:04 +0300 Subject: [PATCH 10/30] Update README.md --- utils/libtokencap/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md index d1c1b8b3..29225835 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -75,15 +75,15 @@ and then generate a dictionary file from those tokens. #### usage: ```bash -./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 +./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 -- [-program_args] ``` #### description opts: - ```-o``` : Path to target output directory ; - ```-b``` : Path to target program binary ; - ```-p``` : Path to LD_PRELOAD library ; -- ```-t``` : Timeout in seconds +- ```-t``` : Timeout in seconds ; +- ```-- [-program_args]```: Any additional arguments required by the target binary can be specified after ```--```. #### output: -The script generates a temporary token file (```temp_output.txt```) in the current working directory, -containing tokens captured during the execution of the target binary. -A sorted and unique token dictionary file is created in the same directory as the target output, with a ```*.dict``` extension. +A sorted and unique token dictionary file with the extension ``*.dict`` +is created in the same directory as the target output containing tokens captured during the execution of the target binary. From 2d9b793dbbe9288a1caa4459c280678179bb46c9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Jun 2024 14:47:58 +0200 Subject: [PATCH 11/30] AFL_NO_SYNC --- docs/Changelog.md | 2 ++ docs/env_variables.md | 3 +++ include/afl-fuzz.h | 2 +- include/envs.h | 9 ++++----- src/afl-fuzz-run.c | 2 ++ src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz-stats.c | 6 +++--- src/afl-fuzz.c | 1 + 8 files changed, 23 insertions(+), 9 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index ba7eb6a3..1f6a940e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ three times faster. The reason for this is unknown. - added AFL_DISABLE_REDUNDANT for huge queues - fix AFL_PERSISTENT_RECORD + - added `AFL_NO_SYNC` environment variable that does what you think it does - run custom_post_process after standard trimming - prevent filenames in the queue that have spaces - minor fix for FAST schedules @@ -32,6 +33,7 @@ * afl-showmap - fix memory leak on shmem testcase usage (thanks to @ndrewh) - minor fix to collect coverage -C (thanks to @bet4it) + * libtokencap: script generate_libtoken_dict.sh added by @a-shvedov * enhanced the ASAN configuration diff --git a/docs/env_variables.md b/docs/env_variables.md index b3519107..22e0ce0f 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -588,6 +588,9 @@ checks or alter some of the more exotic semantics of the tool: between fuzzing instances synchronization. Default sync time is 30 minutes, note that time is halved for -M main nodes. + - `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all + other syncing parameters. + - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 74b04fdb..65304d19 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -457,7 +457,7 @@ typedef struct afl_env_vars { afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant, - afl_sha1_filenames; + afl_sha1_filenames, afl_no_sync; 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 5b516905..45b080cb 100644 --- a/include/envs.h +++ b/include/envs.h @@ -81,14 +81,13 @@ static char *afl_environment_variables[] = { "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", - "AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", - "AFL_LLVM_LTO_SKIPINIT" - "AFL_LLVM_LTO_STARTID", - "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN", + "AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT", + "AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", + "AFL_NO_AUTODICT", "AFL_NO_BUILTIN", #if defined USE_COLOR && !defined ALWAYS_COLORED "AFL_NO_COLOR", "AFL_NO_COLOUR", #endif - "AFL_NO_CPU_RED", + "AFL_NO_CPU_RED", "AFL_NO_SYNC", "AFL_NO_CFG_FUZZING", // afl.rs rust crate option "AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY", diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 4e2cceff..6a0da6ab 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -666,6 +666,8 @@ abort_calibration: void sync_fuzzers(afl_state_t *afl) { + if (unlikely(afl->afl_env.afl_no_sync)) { return; } + DIR *sd; struct dirent *sd_ent; u32 sync_cnt = 0, synced = 0, entries = 0; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 333d57b2..a1c1e30c 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -279,6 +279,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_final_sync = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_SYNC", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_sync = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index eafeebba..609b11e4 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -2487,7 +2487,7 @@ void show_init_stats(afl_state_t *afl) { } -void update_calibration_time(afl_state_t *afl, u64 *time) { +inline void update_calibration_time(afl_state_t *afl, u64 *time) { u64 cur = get_cur_time_us(); afl->calibration_time_us += cur - *time; @@ -2495,7 +2495,7 @@ void update_calibration_time(afl_state_t *afl, u64 *time) { } -void update_trim_time(afl_state_t *afl, u64 *time) { +inline void update_trim_time(afl_state_t *afl, u64 *time) { u64 cur = get_cur_time_us(); afl->trim_time_us += cur - *time; @@ -2503,7 +2503,7 @@ void update_trim_time(afl_state_t *afl, u64 *time) { } -void update_sync_time(afl_state_t *afl, u64 *time) { +inline void update_sync_time(afl_state_t *afl, u64 *time) { u64 cur = get_cur_time_us(); afl->sync_time_us += cur - *time; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 70ab983c..0f6216c4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -335,6 +335,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" " suported formats: dogstatsd, librato, signalfx, influxdb\n" + "AFL_NO_SYNC: disables all syncing\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n" "AFL_NO_CRASH_README: do not create a README in the crashes directory\n" From 2806d6be2f1d26eed7b42ae580f5bf7a29713a01 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Jun 2024 09:20:30 +0200 Subject: [PATCH 12/30] optimize syncing --- include/config.h | 4 ++-- src/afl-fuzz.c | 27 +++++++++------------------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/include/config.h b/include/config.h index 3727dab1..ebe40022 100644 --- a/include/config.h +++ b/include/config.h @@ -324,9 +324,9 @@ #define SYNC_INTERVAL 8 /* Sync time (minimum time between syncing in ms, time is halfed for -M main - nodes) - default is 30 minutes: */ + nodes) - default is 20 minutes: */ -#define SYNC_TIME (30 * 60 * 1000) +#define SYNC_TIME (20 * 60 * 1000) /* Output directory reuse grace period (minutes): */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0f6216c4..49d25d5a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2943,26 +2943,13 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->stop_soon && afl->sync_id)) { - if (likely(afl->skip_deterministic)) { + if (unlikely(afl->is_main_node)) { - if (unlikely(afl->is_main_node)) { + if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) { - if (unlikely(cur_time > - (afl->sync_time >> 1) + afl->last_sync_time)) { + if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { - if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { - - sync_fuzzers(afl); - - } - - } - - } else { - - if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) { - - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + sync_fuzzers(afl); } @@ -2970,7 +2957,11 @@ int main(int argc, char **argv_orig, char **envp) { } else { - sync_fuzzers(afl); + if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) { + + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } + + } } From 12a87cfacbe2015e378ebae9cca0923a220d1605 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Jun 2024 10:40:12 +0200 Subject: [PATCH 13/30] nits --- src/afl-fuzz.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 49d25d5a..bc564300 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2587,7 +2587,7 @@ 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) { + if (unlikely(!afl->queue_cycle && afl->afl_env.afl_import_first)) { OKF("Syncing queues from other fuzzer instances first ..."); @@ -2598,6 +2598,12 @@ int main(int argc, char **argv_orig, char **envp) { } ++afl->queue_cycle; + if (afl->afl_env.afl_no_ui) { + + ACTF("Entering queue cycle %llu\n", afl->queue_cycle); + + } + runs_in_current_cycle = (u32)-1; afl->cur_skipped_items = 0; @@ -2606,7 +2612,7 @@ int main(int argc, char **argv_orig, char **envp) { // queue is fully cycled. time_t cursec = time(NULL); struct tm *curdate = localtime(&cursec); - if (likely(!afl->afl_env.afl_pizza_mode)) { + if (unlikely(!afl->afl_env.afl_pizza_mode)) { if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) { @@ -2651,13 +2657,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (unlikely(afl->not_on_tty)) { - - ACTF("Entering queue cycle %llu.", afl->queue_cycle); - fflush(stdout); - - } - /* If we had a full queue cycle with no new finds, try recombination strategies next. */ From e8d098335b24dfd96f88b840617fbb539a6077ab Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Jun 2024 19:33:02 +0200 Subject: [PATCH 14/30] Fix cmplog shared memory size when USEMMAP=1 --- src/afl-sharedmem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 8f685633..1dea83f9 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -239,15 +239,15 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); } /* configure the size of the shared memory segment */ - if (ftruncate(shm->cmplog_g_shm_fd, map_size)) { + if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) { PFATAL("setup_shm(): cmplog ftruncate() failed"); } /* map the shared memory segment to the address space of the process */ - shm->cmp_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, - shm->cmplog_g_shm_fd, 0); + shm->cmp_map = mmap(0, sizeof(struct cmp_map), PROT_READ | PROT_WRITE, + MAP_SHARED, shm->cmplog_g_shm_fd, 0); if (shm->cmp_map == MAP_FAILED) { close(shm->cmplog_g_shm_fd); From f8767c397bbc97a8729bacdd5f40ee00031742c4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 5 Jun 2024 18:43:20 +0100 Subject: [PATCH 15/30] Fix issue for setrlimit --- frida_mode/src/instrument/instrument_x64_cache.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frida_mode/src/instrument/instrument_x64_cache.c b/frida_mode/src/instrument/instrument_x64_cache.c index ef10e133..90a7045d 100644 --- a/frida_mode/src/instrument/instrument_x64_cache.c +++ b/frida_mode/src/instrument/instrument_x64_cache.c @@ -49,14 +49,23 @@ void instrument_cache_init(void) { if (setrlimit(RLIMIT_AS, &data_limit) != 0) { - FFATAL("Failed to setrlimit: %d", errno); + FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE", + errno); } map_base = gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size, GUM_PAGE_READ | GUM_PAGE_WRITE); - if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); } + if (map_base == MAP_FAILED) { + + FFATAL( + "Failed to map segment: %d. This can be caused by failure to setrlimit." + "Disabling or reducing the size of the allocation using " + "AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help", + errno); + + } FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]", GUM_ADDRESS(map_base)); From e46c106b890404fbeb2d0e6120510ddf83113da6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 6 Jun 2024 10:25:19 +0200 Subject: [PATCH 16/30] new seed selection algorithm --- docs/Changelog.md | 6 ++++- src/afl-fuzz-queue.c | 59 +++++++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 1f6a940e..633e7071 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,9 +8,12 @@ - fixed a regression in afl-fuzz that resulted in a 5-10% performace loss do a switch from gettimeofday() to clock_gettime() which should be rather three times faster. The reason for this is unknown. + - new queue selection algorithm based on 2 core years of queue data + analysis. gives a noticable improvement on coverage although the results + seem counterintuitive :-) - added AFL_DISABLE_REDUNDANT for huge queues - - fix AFL_PERSISTENT_RECORD - added `AFL_NO_SYNC` environment variable that does what you think it does + - fix AFL_PERSISTENT_RECORD - run custom_post_process after standard trimming - prevent filenames in the queue that have spaces - minor fix for FAST schedules @@ -33,6 +36,7 @@ * afl-showmap - fix memory leak on shmem testcase usage (thanks to @ndrewh) - minor fix to collect coverage -C (thanks to @bet4it) + * Fixed a shmem mmap bug (that rarely came up on MacOS) * libtokencap: script generate_libtoken_dict.sh added by @a-shvedov * enhanced the ASAN configuration diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 784b377a..d19dd51a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -60,9 +60,9 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { } -double compute_weight(afl_state_t *afl, struct queue_entry *q, - double avg_exec_us, double avg_bitmap_size, - double avg_top_size) { +inline double compute_weight(afl_state_t *afl, struct queue_entry *q, + double avg_exec_us, double avg_bitmap_size, + double avg_len) { double weight = 1.0; @@ -73,14 +73,45 @@ 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 (likely(afl->schedule < RARE)) { - if (unlikely(weight < 0.1)) { weight = 0.1; } - if (unlikely(q->favored)) { weight *= 5; } - if (unlikely(!q->was_fuzzed)) { weight *= 2; } - if (unlikely(q->fs_redundant)) { weight *= 0.8; } + double t = q->exec_us / avg_exec_us; + if (likely(t < 0.1)) { + + // nothing + + } else if (likely(t <= 0.25)) + + weight *= 0.9; + else if (likely(t <= 0.5)) { + + // nothing + + } else if (likely(t < 1.0)) + + weight *= 1.15; + else if (unlikely(t > 2.5 && t < 5.0)) + weight *= 1.1; + // else nothing + + } + + double l = q->len / avg_len; + if (likely(l < 0.1)) + weight *= 0.75; + else if (likely(l < 0.25)) + weight *= 1.1; + else if (unlikely(l >= 10)) + weight *= 1.1; + + double bms = q->bitmap_size / avg_bitmap_size; + if (likely(bms < 0.5)) + weight *= (1.0 + ((bms - 0.5) / 2)); + else if (unlikely(bms > 1.33)) + weight *= 1.1; + + if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } + if (unlikely(q->fs_redundant)) { weight *= 0.75; } return weight; @@ -117,7 +148,7 @@ void create_alias_table(afl_state_t *afl) { double avg_exec_us = 0.0; double avg_bitmap_size = 0.0; - double avg_top_size = 0.0; + double avg_len = 0.0; u32 active = 0; for (i = 0; i < n; i++) { @@ -129,7 +160,7 @@ void create_alias_table(afl_state_t *afl) { avg_exec_us += q->exec_us; avg_bitmap_size += log(q->bitmap_size); - avg_top_size += q->tc_ref; + avg_len += q->len; ++active; } @@ -138,7 +169,7 @@ void create_alias_table(afl_state_t *afl) { avg_exec_us /= active; avg_bitmap_size /= active; - avg_top_size /= active; + avg_len /= active; for (i = 0; i < n; i++) { @@ -147,7 +178,7 @@ void create_alias_table(afl_state_t *afl) { if (likely(!q->disabled)) { q->weight = - compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size); + compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_len); q->perf_score = calculate_score(afl, q); sum += q->weight; From 477063e9ee88da5feb73b38b27a1241e8b77e002 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 6 Jun 2024 17:52:21 +0200 Subject: [PATCH 17/30] memory adjustments --- TODO.md | 1 + docs/Changelog.md | 1 + src/afl-fuzz-queue.c | 112 +++++++++++++++++++--------------------- src/afl-fuzz-redqueen.c | 34 ++++++------ src/afl-fuzz-skipdet.c | 9 ++-- 5 files changed, 78 insertions(+), 79 deletions(-) diff --git a/TODO.md b/TODO.md index ace07434..000c78dd 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## Must + - review: queue_testcase_store_mem and queue_testcase_get - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds - cmplog max items env? diff --git a/docs/Changelog.md b/docs/Changelog.md index 633e7071..cf5d2500 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -23,6 +23,7 @@ - -V timing is now accurately the fuzz time (without syncing), before long calibration times and syncing could result in now fuzzing being made when the time was already run out until then, thanks to @eqv! + - make afl-fuzz use less memory with cmplog and fix a memleak * afl-cc: - re-enable i386 support that was accidently disabled - fixes for LTO and outdated afl-gcc mode for i386 diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index d19dd51a..cbdfd5b0 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -60,63 +60,6 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { } -inline double compute_weight(afl_state_t *afl, struct queue_entry *q, - double avg_exec_us, double avg_bitmap_size, - double avg_len) { - - double weight = 1.0; - - 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(afl->schedule < RARE)) { - - double t = q->exec_us / avg_exec_us; - if (likely(t < 0.1)) { - - // nothing - - } else if (likely(t <= 0.25)) - - weight *= 0.9; - else if (likely(t <= 0.5)) { - - // nothing - - } else if (likely(t < 1.0)) - - weight *= 1.15; - else if (unlikely(t > 2.5 && t < 5.0)) - weight *= 1.1; - // else nothing - - } - - double l = q->len / avg_len; - if (likely(l < 0.1)) - weight *= 0.75; - else if (likely(l < 0.25)) - weight *= 1.1; - else if (unlikely(l >= 10)) - weight *= 1.1; - - double bms = q->bitmap_size / avg_bitmap_size; - if (likely(bms < 0.5)) - weight *= (1.0 + ((bms - 0.5) / 2)); - else if (unlikely(bms > 1.33)) - weight *= 1.1; - - if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } - if (unlikely(q->fs_redundant)) { weight *= 0.75; } - - return weight; - -} - /* create the alias table that allows weighted random selection - expensive */ void create_alias_table(afl_state_t *afl) { @@ -177,8 +120,59 @@ void create_alias_table(afl_state_t *afl) { if (likely(!q->disabled)) { - q->weight = - compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_len); + double weight = 1.0; + { // inline does result in a compile error with LTO, weird + + 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(afl->schedule < RARE)) { + + double t = q->exec_us / avg_exec_us; + if (likely(t < 0.1)) { + + // nothing + + } else if (likely(t <= 0.25)) + + weight *= 0.9; + else if (likely(t <= 0.5)) { + + // nothing + + } else if (likely(t < 1.0)) + + weight *= 1.15; + else if (unlikely(t > 2.5 && t < 5.0)) + weight *= 1.1; + // else nothing + + } + + double l = q->len / avg_len; + if (likely(l < 0.1)) + weight *= 0.75; + else if (likely(l < 0.25)) + weight *= 1.1; + else if (unlikely(l >= 10)) + weight *= 1.1; + + double bms = q->bitmap_size / avg_bitmap_size; + if (likely(bms < 0.5)) + weight *= (1.0 + ((bms - 0.5) / 2)); + else if (unlikely(bms > 1.33)) + weight *= 1.1; + + if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } + if (unlikely(q->fs_redundant)) { weight *= 0.75; } + + } + + q->weight = weight; q->perf_score = calculate_score(afl, q); sum += q->weight; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9316da71..6c3582f2 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -322,7 +322,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, memcpy(backup, buf, len); memcpy(changed, buf, len); - if (afl->cmplog_random_colorization) { + if (likely(afl->cmplog_random_colorization)) { random_replace(afl, changed, len); @@ -402,6 +402,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 i = 1; u32 positions = 0; + while (i) { restart: @@ -2996,15 +2997,16 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { struct tainted *t = taint; +#ifdef _DEBUG while (t) { -#ifdef _DEBUG fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len); -#endif t = t->next; } +#endif + #if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION) u64 start_time = get_cur_time(); u32 cmp_locations = 0; @@ -3148,27 +3150,27 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { exit_its: - if (afl->cmplog_lvl == CMPLOG_LVL_MAX) { + // if (afl->cmplog_lvl == CMPLOG_LVL_MAX) { - afl->queue_cur->colorized = CMPLOG_LVL_MAX; + afl->queue_cur->colorized = CMPLOG_LVL_MAX; - if (afl->queue_cur->cmplog_colorinput) { + if (afl->queue_cur->cmplog_colorinput) { - ck_free(afl->queue_cur->cmplog_colorinput); + ck_free(afl->queue_cur->cmplog_colorinput); - } + } - while (taint) { + while (taint) { - t = taint->next; - ck_free(taint); - taint = t; + t = taint->next; + ck_free(taint); + taint = t; - } + } - afl->queue_cur->taint = NULL; + afl->queue_cur->taint = NULL; - } else { + /*} else { afl->queue_cur->colorized = LVL2; @@ -3182,7 +3184,7 @@ exit_its: } - } + }*/ #ifdef CMPLOG_COMBINE if (afl->queued_items + afl->saved_crashes > orig_hit_cnt + 1) { diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c index e52d59a3..8a927292 100644 --- a/src/afl-fuzz-skipdet.c +++ b/src/afl-fuzz-skipdet.c @@ -33,15 +33,15 @@ u8 is_det_timeout(u64 cur_ms, u8 is_flip) { u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) { - if (!afl->skipdet_g->virgin_det_bits) { + if (unlikely(!afl->skipdet_g->virgin_det_bits)) { afl->skipdet_g->virgin_det_bits = (u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size); } - if (!q->favored || q->passed_det) return 0; - if (!q->trace_mini) return 0; + if (likely(!q->favored || q->passed_det)) return 0; + if (unlikely(!q->trace_mini)) return 0; if (!afl->skipdet_g->last_cov_undet) afl->skipdet_g->last_cov_undet = get_cur_time(); @@ -122,7 +122,8 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, afl->stage_cur = 0; orig_hit_cnt = afl->queued_items + afl->saved_crashes; - u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + static u8 *inf_eff_map; + inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len); memset(inf_eff_map, 1, sizeof(u8) * len); if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } From bdfd38771abe9641db08b7569a0cc6a38f1ecf4a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 09:47:29 +0200 Subject: [PATCH 18/30] add cmplog_time measurement --- include/afl-fuzz.h | 1 + src/afl-fuzz-redqueen.c | 19 +++++++++++++++++-- src/afl-fuzz-stats.c | 25 +++++++++++++++++++++---- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 65304d19..1e670702 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -656,6 +656,7 @@ typedef struct afl_state { switch_fuzz_mode, /* auto or fixed fuzz mode */ calibration_time_us, /* Time spend on calibration */ sync_time_us, /* Time spend on sync */ + cmplog_time_us, /* Time spend on cmplog */ trim_time_us; /* Time spend on trimming */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 6c3582f2..954e5671 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2938,7 +2938,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, // afl->queue_cur->exec_cksum u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { - u8 r = 1; + u64 cmplog_start_us = get_cur_time_us(); + u8 r = 1; if (unlikely(!afl->pass_stats)) { afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W); @@ -2966,7 +2967,12 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) { - if (unlikely(colorization(afl, buf, len, &taint))) { return 1; } + if (unlikely(colorization(afl, buf, len, &taint))) { + + update_cmplog_time(afl, &cmplog_start_us); + return 1; + + } // no taint? still try, create a dummy to prevent again colorization if (!taint) { @@ -2975,6 +2981,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { fprintf(stderr, "TAINT FAILED\n"); #endif afl->queue_cur->colorized = CMPLOG_LVL_MAX; + update_cmplog_time(afl, &cmplog_start_us); return 0; } @@ -2995,6 +3002,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } + update_cmplog_time(afl, &cmplog_start_us); + struct tainted *t = taint; #ifdef _DEBUG @@ -3027,6 +3036,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } + update_cmplog_time(afl, &cmplog_start_us); return 1; } @@ -3050,6 +3060,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } + update_cmplog_time(afl, &cmplog_start_us); return 1; } @@ -3068,6 +3079,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { u64 orig_hit_cnt, new_hit_cnt; u64 orig_execs = afl->fsrv.total_execs; orig_hit_cnt = afl->queued_items + afl->saved_crashes; + update_cmplog_time(afl, &cmplog_start_us); afl->stage_name = "input-to-state"; afl->stage_short = "its"; @@ -3144,6 +3156,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } + update_cmplog_time(afl, &cmplog_start_us); + } r = 0; @@ -3272,6 +3286,7 @@ exit_its: #endif + update_cmplog_time(afl, &cmplog_start_us); return r; } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 609b11e4..3a71e158 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -207,6 +207,12 @@ void load_stats_file(afl_state_t *afl) { } + if (starts_with("cmplog_time", keystring)) { + + afl->cmplog_time_us = strtoull(lptr, &nptr, 10) * 1000000; + + } + if (starts_with("trim_time", keystring)) { afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; @@ -322,8 +328,9 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } #endif u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time; - u64 overhead_ms = - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000; + u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us + + afl->trim_time_us + afl->cmplog_time_us) / + 1000; if (!runtime_ms) { runtime_ms = 1; } fprintf( @@ -337,6 +344,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "time_wo_finds : %llu\n" "fuzz_time : %llu\n" "calibration_time : %llu\n" + "cmplog_time : %llu\n" "sync_time : %llu\n" "trim_time : %llu\n" "execs_done : %llu\n" @@ -385,8 +393,9 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, ? 0 : (cur_time - afl->last_find_time) / 1000), (runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000, - afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, - afl->trim_time_us / 1000000, afl->fsrv.total_execs, + afl->calibration_time_us / 1000000, afl->cmplog_time_us / 1000000, + afl->sync_time_us / 1000000, afl->trim_time_us / 1000000, + afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime_ms) / 1000), afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->queued_variable, @@ -2511,3 +2520,11 @@ inline void update_sync_time(afl_state_t *afl, u64 *time) { } +inline void update_cmplog_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->cmplog_time_us += cur - *time; + *time = cur; + +} + From 0618bfd4ae6a31ce44fcad13bbf6f5a41bb265d1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 09:58:27 +0200 Subject: [PATCH 19/30] fix --- include/afl-fuzz.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1e670702..d3501e8d 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1227,6 +1227,7 @@ void show_init_stats(afl_state_t *); void update_calibration_time(afl_state_t *afl, u64 *time); void update_trim_time(afl_state_t *afl, u64 *time); void update_sync_time(afl_state_t *afl, u64 *time); +void update_cmplog_time(afl_state_t *afl, u64 *time); /* StatsD */ From fe36ceaa552569be66447aba11885259ca700d85 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 11:16:42 +0200 Subject: [PATCH 20/30] minor testcache optimizations --- TODO.md | 1 - src/afl-fuzz-queue.c | 205 ++++++++++++++++++++++--------------------- 2 files changed, 106 insertions(+), 100 deletions(-) diff --git a/TODO.md b/TODO.md index 000c78dd..ace07434 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,6 @@ ## Must - - review: queue_testcase_store_mem and queue_testcase_get - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds - cmplog max items env? diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index cbdfd5b0..f4cb930d 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -621,6 +621,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { q->trace_mini = NULL; q->testcase_buf = NULL; q->mother = afl->queue_cur; + q->weight = 1.0; + q->perf_score = 100; #ifdef INTROSPECTION q->bitsmap_size = afl->bitsmap_size; @@ -1226,9 +1228,11 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, u32 len = q->len; - if (len != old_len) { + // only realloc if necessary or useful + // (a custom trim can make the testcase larger) + if (unlikely(len > old_len || len < old_len + 1024)) { - afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len; + afl->q_testcase_cache_size += len - old_len; q->testcase_buf = (u8 *)realloc(q->testcase_buf, len); if (unlikely(!q->testcase_buf)) { @@ -1257,41 +1261,48 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, if (likely(q->testcase_buf)) { - u32 is_same = in == q->testcase_buf; + if (likely(in != q->testcase_buf)) { - if (likely(len != old_len)) { + // only realloc if we save memory + if (unlikely(len < old_len + 1024)) { - u8 *ptr = (u8 *)realloc(q->testcase_buf, len); + u8 *ptr = (u8 *)realloc(q->testcase_buf, len); - if (likely(ptr)) { + if (likely(ptr)) { - q->testcase_buf = ptr; - afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len; + q->testcase_buf = ptr; + afl->q_testcase_cache_size += len - old_len; + + } } - } + memcpy(q->testcase_buf, in, len); - if (unlikely(!is_same)) { memcpy(q->testcase_buf, in, len); } + } } } /* Returns the testcase buf from the file behind this queue entry. - Increases the refcount. */ + Increases the refcount. */ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { - u32 len = q->len; + if (likely(q->testcase_buf)) { return q->testcase_buf; } - /* first handle if no testcase cache is configured */ + u32 len = q->len; + double weight = q->weight; - if (unlikely(!afl->q_testcase_max_cache_size)) { + // first handle if no testcase cache is configured, or if the + // weighting of the testcase is below average. + + if (unlikely(weight < 1.0 || !afl->q_testcase_max_cache_size)) { u8 *buf; - if (unlikely(q == afl->queue_cur)) { + if (likely(q == afl->queue_cur)) { buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len); @@ -1317,118 +1328,113 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { } - /* now handle the testcase cache */ + /* now handle the testcase cache and we know it is an interesting one */ - if (unlikely(!q->testcase_buf)) { + /* Buf not cached, let's load it */ + u32 tid = afl->q_testcase_max_cache_count; + static u32 do_once = 0; // because even threaded we would want this. WIP - /* Buf not cached, let's load it */ - u32 tid = afl->q_testcase_max_cache_count; - static u32 do_once = 0; // because even threaded we would want this. WIP + while (unlikely( + (afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size && + afl->q_testcase_cache_count > 1) || + afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) { - while (unlikely( - (afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size && - afl->q_testcase_cache_count > 1) || - afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) { + /* We want a max number of entries to the cache that we learn. + Very simple: once the cache is filled by size - that is the max. */ - /* We want a max number of entries to the cache that we learn. - Very simple: once the cache is filled by size - that is the max. */ + if (unlikely( + afl->q_testcase_cache_size + len >= + afl->q_testcase_max_cache_size && + (afl->q_testcase_cache_count < afl->q_testcase_max_cache_entries && + afl->q_testcase_max_cache_count < + afl->q_testcase_max_cache_entries) && + !do_once)) { - if (unlikely(afl->q_testcase_cache_size + len >= - afl->q_testcase_max_cache_size && - (afl->q_testcase_cache_count < - afl->q_testcase_max_cache_entries && - afl->q_testcase_max_cache_count < - afl->q_testcase_max_cache_entries) && - !do_once)) { + if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) { - if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) { + afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_count + 1; - afl->q_testcase_max_cache_entries = - afl->q_testcase_max_cache_count + 1; + } else { - } else { - - afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1; - - } - - do_once = 1; - // release unneeded memory - afl->q_testcase_cache = (struct queue_entry **)ck_realloc( - afl->q_testcase_cache, - (afl->q_testcase_max_cache_entries + 1) * sizeof(size_t)); + afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1; } - /* Cache full. We neet to evict one or more to map one. - Get a random one which is not in use */ - - do { - - // if the cache (MB) is not enough for the queue then this gets - // undesirable because q_testcase_max_cache_count grows sometimes - // although the number of items in the cache will not change hence - // more and more loops - tid = rand_below(afl, afl->q_testcase_max_cache_count); - - } while (afl->q_testcase_cache[tid] == NULL || - - afl->q_testcase_cache[tid] == afl->queue_cur); - - struct queue_entry *old_cached = afl->q_testcase_cache[tid]; - free(old_cached->testcase_buf); - old_cached->testcase_buf = NULL; - afl->q_testcase_cache_size -= old_cached->len; - afl->q_testcase_cache[tid] = NULL; - --afl->q_testcase_cache_count; - ++afl->q_testcase_evictions; - if (tid < afl->q_testcase_smallest_free) - afl->q_testcase_smallest_free = tid; + do_once = 1; + // release unneeded memory + afl->q_testcase_cache = (struct queue_entry **)ck_realloc( + afl->q_testcase_cache, + (afl->q_testcase_max_cache_entries + 1) * sizeof(size_t)); } - if (unlikely(tid >= afl->q_testcase_max_cache_entries)) { + /* Cache full. We neet to evict one or more to map one. + Get a random one which is not in use */ - // uh we were full, so now we have to search from start - tid = afl->q_testcase_smallest_free; + do { - } + // if the cache (MB) is not enough for the queue then this gets + // undesirable because q_testcase_max_cache_count grows sometimes + // although the number of items in the cache will not change hence + // more and more loops + tid = rand_below(afl, afl->q_testcase_max_cache_count); - // we need this while loop in case there were ever previous evictions but - // not in this call. - while (unlikely(afl->q_testcase_cache[tid] != NULL)) - ++tid; + } while (afl->q_testcase_cache[tid] == NULL || - /* Map the test case into memory. */ + afl->q_testcase_cache[tid] == afl->queue_cur); - int fd = open((char *)q->fname, O_RDONLY); + struct queue_entry *old_cached = afl->q_testcase_cache[tid]; + free(old_cached->testcase_buf); + old_cached->testcase_buf = NULL; + afl->q_testcase_cache_size -= old_cached->len; + afl->q_testcase_cache[tid] = NULL; + --afl->q_testcase_cache_count; + ++afl->q_testcase_evictions; + if (tid < afl->q_testcase_smallest_free) + afl->q_testcase_smallest_free = tid; - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); } + } - q->testcase_buf = (u8 *)malloc(len); + if (unlikely(tid >= afl->q_testcase_max_cache_entries)) { - if (unlikely(!q->testcase_buf)) { + // uh we were full, so now we have to search from start + tid = afl->q_testcase_smallest_free; - PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); + } - } + // we need this while loop in case there were ever previous evictions but + // not in this call. + while (unlikely(afl->q_testcase_cache[tid] != NULL)) + ++tid; - ck_read(fd, q->testcase_buf, len, q->fname); - close(fd); + /* Map the test case into memory. */ - /* Register testcase as cached */ - afl->q_testcase_cache[tid] = q; - afl->q_testcase_cache_size += len; - ++afl->q_testcase_cache_count; - if (likely(tid >= afl->q_testcase_max_cache_count)) { + int fd = open((char *)q->fname, O_RDONLY); - afl->q_testcase_max_cache_count = tid + 1; + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); } - } else if (unlikely(tid == afl->q_testcase_smallest_free)) { + q->testcase_buf = (u8 *)malloc(len); - afl->q_testcase_smallest_free = tid + 1; + if (unlikely(!q->testcase_buf)) { - } + PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len); + + } + + ck_read(fd, q->testcase_buf, len, q->fname); + close(fd); + + /* Register testcase as cached */ + afl->q_testcase_cache[tid] = q; + afl->q_testcase_cache_size += len; + ++afl->q_testcase_cache_count; + if (likely(tid >= afl->q_testcase_max_cache_count)) { + + afl->q_testcase_max_cache_count = tid + 1; + + } else if (unlikely(tid == afl->q_testcase_smallest_free)) { + + afl->q_testcase_smallest_free = tid + 1; } @@ -1443,12 +1449,13 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u32 len = q->len; - if (unlikely(afl->q_testcase_cache_size + len >= + if (unlikely(q->weight < 1.0 || + afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size || afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) { - // no space? will be loaded regularly later. + // no space or uninteresting? will be loaded regularly later. return; } From 92cbdb9f45f4d0b6ed146f01142aafc1e8b94f7f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 11:41:35 +0200 Subject: [PATCH 21/30] update unicorn --- unicorn_mode/unicornafl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 764b66b2..4b4fdab1 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 764b66b21cd4a8124a5b6c9cc98d1214b2037196 +Subproject commit 4b4fdab161c15529affcc1e785d779e318b882ab From f0937f96d49fdb23865e2025576ab5c0049ef5b5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 11:48:58 +0200 Subject: [PATCH 22/30] target hash --- TODO.md | 1 + include/afl-fuzz.h | 1 + src/afl-common.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/TODO.md b/TODO.md index ace07434..aba3cf81 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## Must + - fast restart of afl-fuzz if cmdline + target hash is the same - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds - cmplog max items env? diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d3501e8d..e3e4e246 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1278,6 +1278,7 @@ void get_core_count(afl_state_t *); void fix_up_sync(afl_state_t *); void check_asan_opts(afl_state_t *); void check_binary(afl_state_t *, u8 *); +u64 get_binary_hash(u8 *fn); void check_if_tty(afl_state_t *); void save_cmdline(afl_state_t *, u32, char **); void read_foreign_testcases(afl_state_t *, int); diff --git a/src/afl-common.c b/src/afl-common.c index efdb5d60..4250fb36 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -51,6 +51,8 @@ #include #include +#include "hash.h" + u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; @@ -167,6 +169,22 @@ void set_sanitizer_defaults() { } +u64 get_binary_hash(u8 *fn) { + + int fd = open(fn, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s'", fn); } + struct stat st; + if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } + u32 f_len = st.st_size; + u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } + close(fd); + u64 hash = hash64(f_data, f_len, 0); + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } + return hash; + +} + u32 check_binary_signatures(u8 *fn) { int ret = 0, fd = open(fn, O_RDONLY); From 74e264a20a3af709a3546f7a3823e9788feb45f3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 7 Jun 2024 13:46:15 +0200 Subject: [PATCH 23/30] move function --- src/afl-common.c | 18 ------------------ src/afl-performance.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index 4250fb36..efdb5d60 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -51,8 +51,6 @@ #include #include -#include "hash.h" - u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; @@ -169,22 +167,6 @@ void set_sanitizer_defaults() { } -u64 get_binary_hash(u8 *fn) { - - int fd = open(fn, O_RDONLY); - if (fd < 0) { PFATAL("Unable to open '%s'", fn); } - struct stat st; - if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } - u32 f_len = st.st_size; - u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); - if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } - close(fd); - u64 hash = hash64(f_data, f_len, 0); - if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } - return hash; - -} - u32 check_binary_signatures(u8 *fn) { int ret = 0, fd = open(fn, O_RDONLY); diff --git a/src/afl-performance.c b/src/afl-performance.c index 6c6e3c8b..e8ece6b5 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -95,6 +95,24 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { } +/* Hash a file */ + +u64 get_binary_hash(u8 *fn) { + + int fd = open(fn, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s'", fn); } + struct stat st; + if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } + u32 f_len = st.st_size; + u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } + close(fd); + u64 hash = hash64(f_data, f_len, 0); + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } + return hash; + +} + // Public domain SHA1 implementation copied from: // https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c From 5331eca5d935e9d5faef06fe6b5a38f411109fde Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 12:02:59 +0200 Subject: [PATCH 24/30] allow multiple -m --- src/afl-fuzz.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bc564300..9ebe0c76 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -915,8 +915,15 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 'M'; - if (mem_limit_given) { FATAL("Multiple -m options not supported"); } - mem_limit_given = 1; + if (mem_limit_given) { + + WARNF("Overriding previous -m option."); + + } else { + + mem_limit_given = 1; + + } if (!optarg) { FATAL("Wrong usage of -m"); } From 4bb4d4ad0060a16b08bb29533863e71f45bc3c97 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 12:16:32 +0200 Subject: [PATCH 25/30] fix -n --- docs/Changelog.md | 1 + src/afl-fuzz-state.c | 3 ++- src/afl-fuzz.c | 15 ++++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index cf5d2500..0f4b2d8a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -23,6 +23,7 @@ - -V timing is now accurately the fuzz time (without syncing), before long calibration times and syncing could result in now fuzzing being made when the time was already run out until then, thanks to @eqv! + - fix -n uninstrumented mode when ending fuzzing - make afl-fuzz use less memory with cmplog and fix a memleak * afl-cc: - re-enable i386 support that was accidently disabled diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index a1c1e30c..fbe6d32a 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -769,8 +769,9 @@ void afl_states_stop(void) { if (el->fsrv.fsrv_pid > 0) { kill(el->fsrv.fsrv_pid, el->fsrv.fsrv_kill_signal); + usleep(100); /* Make sure the forkserver does not end up as zombie. */ - waitpid(el->fsrv.fsrv_pid, NULL, 0); + waitpid(el->fsrv.fsrv_pid, NULL, WNOHANG); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9ebe0c76..fefab1c0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1469,15 +1469,16 @@ int main(int argc, char **argv_orig, char **envp) { #endif - configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal, - afl->afl_env.afl_fsrv_kill_signal, - (afl->fsrv.qemu_mode || afl->unicorn_mode + configure_afl_kill_signals( + &afl->fsrv, afl->afl_env.afl_child_kill_signal, + afl->afl_env.afl_fsrv_kill_signal, + (afl->fsrv.qemu_mode || afl->unicorn_mode || afl->non_instrumented_mode #ifdef __linux__ - || afl->fsrv.nyx_mode + || afl->fsrv.nyx_mode #endif - ) - ? SIGKILL - : SIGTERM); + ) + ? SIGKILL + : SIGTERM); setup_signal_handlers(); check_asan_opts(afl); From 31652eeb2aad9dbab26d3e70699a932b57e9d80d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 12:19:58 +0200 Subject: [PATCH 26/30] nit --- 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 fefab1c0..a7ddef6e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1472,7 +1472,7 @@ int main(int argc, char **argv_orig, char **envp) { configure_afl_kill_signals( &afl->fsrv, afl->afl_env.afl_child_kill_signal, afl->afl_env.afl_fsrv_kill_signal, - (afl->fsrv.qemu_mode || afl->unicorn_mode || afl->non_instrumented_mode + (afl->fsrv.qemu_mode || afl->unicorn_mode || afl->fsrv.use_fauxsrv #ifdef __linux__ || afl->fsrv.nyx_mode #endif From 44b5e1f4888cf6ce17a516f4d21e66f11c429bc1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 12:26:48 +0200 Subject: [PATCH 27/30] fix no_forkserver mode --- src/afl-forkserver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a082982c..71d8570d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1655,7 +1655,8 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal); - waitpid(fsrv->fsrv_pid, NULL, 0); + usleep(25); + waitpid(fsrv->fsrv_pid, NULL, WNOHANG); } From 5014b86c3c3974000f41cde1dc39a1f5b9cf9605 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 15:44:10 +0200 Subject: [PATCH 28/30] fix AFL_FRIDA_DEBUG_MAPS --- frida_mode/src/ranges.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 269ba59b..714fd9be 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details, if (details->file == NULL) { - FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER - "X %c%c%c", - details->range->base_address, - details->range->base_address + details->range->size, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-'); + OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c", + details->range->base_address, + details->range->base_address + details->range->size, + details->protection & GUM_PAGE_READ ? 'R' : '-', + details->protection & GUM_PAGE_WRITE ? 'W' : '-', + details->protection & GUM_PAGE_EXECUTE ? 'X' : '-'); } else { - FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER - "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", - details->range->base_address, - details->range->base_address + details->range->size, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', - details->file->path, details->file->offset); + OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER + "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", + details->range->base_address, + details->range->base_address + details->range->size, + details->protection & GUM_PAGE_READ ? 'R' : '-', + details->protection & GUM_PAGE_WRITE ? 'W' : '-', + details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path, + details->file->offset); } @@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) { void ranges_print_debug_maps(void) { - FVERBOSE("Maps"); + OKF("Maps"); gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL); } From 0c81982e67f6d637722a9ced1c50d91d7493d410 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 18:32:36 +0200 Subject: [PATCH 29/30] nit --- instrumentation/afl-compiler-rt.o.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index e450dc45..c08e6380 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1849,7 +1849,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 < 5) __afl_final_loc = 5; // we skip the first 5 entries + if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries *(start++) = ++__afl_final_loc; From ec0b83f127702fe23da72f4d424bc13a5bacfae9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 9 Jun 2024 18:39:56 +0200 Subject: [PATCH 30/30] 4.21c --- README.md | 4 ++-- TODO.md | 2 +- docs/Changelog.md | 4 ++-- include/config.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 34d73890..1b255a2a 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.21a +GitHub version: 4.21c Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/TODO.md b/TODO.md index aba3cf81..b36269b4 100644 --- a/TODO.md +++ b/TODO.md @@ -3,6 +3,7 @@ ## Must - fast restart of afl-fuzz if cmdline + target hash is the same + - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds - cmplog max items env? @@ -12,7 +13,6 @@ - afl-showmap -f support - afl-fuzz multicore wrapper script - when trimming then perform crash detection - - cyclomatic complexity: 2 + calls + edges - blocks ## Should diff --git a/docs/Changelog.md b/docs/Changelog.md index 0f4b2d8a..50494acc 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.21a (dev) +### Version ++4.21c (release) * afl-fuzz - fixed a regression in afl-fuzz that resulted in a 5-10% performace loss do a switch from gettimeofday() to clock_gettime() which should be rather @@ -24,6 +24,7 @@ long calibration times and syncing could result in now fuzzing being made when the time was already run out until then, thanks to @eqv! - fix -n uninstrumented mode when ending fuzzing + - enhanced the ASAN configuration - make afl-fuzz use less memory with cmplog and fix a memleak * afl-cc: - re-enable i386 support that was accidently disabled @@ -40,7 +41,6 @@ - minor fix to collect coverage -C (thanks to @bet4it) * Fixed a shmem mmap bug (that rarely came up on MacOS) * libtokencap: script generate_libtoken_dict.sh added by @a-shvedov - * enhanced the ASAN configuration ### Version ++4.20c (release) diff --git a/include/config.h b/include/config.h index ebe40022..c4acf8db 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.21a" +#define VERSION "++4.21c" /****************************************************** * *