From 9607d1db06ebfc2fe1ba565a0ef0123ab3f3e76c Mon Sep 17 00:00:00 2001 From: marc Date: Thu, 10 Aug 2023 10:56:20 +0200 Subject: v4.09a init --- README.md | 2 +- docs/Changelog.md | 4 ++++ include/config.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 951efe59..322ebcf2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Release version: [4.08c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.08c +GitHub version: 4.09a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 2c747e42..94b4c502 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,10 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. +### Version ++4.09a (dev) + - something cool :-) + + ### Version ++4.08c (release) - afl-fuzz: - new mutation engine: mutations that favor discovery more paths are diff --git a/include/config.h b/include/config.h index 5a81c4e2..6a75737f 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.08c" +#define VERSION "++4.09a" /****************************************************** * * -- cgit 1.4.1 From 1cd9258768253e082baa1cc453c578b373839dbc Mon Sep 17 00:00:00 2001 From: marc Date: Thu, 10 Aug 2023 14:46:37 +0200 Subject: update tritondse script --- custom_mutators/aflpp_tritondse/aflpp_tritondse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py index 58b506b6..58739696 100644 --- a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py +++ b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py @@ -164,7 +164,7 @@ def init(seed): format = SeedFormat.COMPOSITE # Now set up TritonDSE config = Config(coverage_strategy = CoverageStrategy.PATH, - debug = is_debug, + # debug = is_debug, pipe_stdout = is_debug, pipe_stderr = is_debug, execution_timeout = 1, -- cgit 1.4.1 From 8823f22a9c87123c1bfcc5bff10044de4c7a4a1f Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 11 Aug 2023 11:22:18 +0200 Subject: add AFL_FINAL_SYNC --- docs/Changelog.md | 7 +++---- docs/env_variables.md | 13 +++++++++---- include/afl-fuzz.h | 3 ++- include/envs.h | 1 + src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 9 +++++++++ 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 94b4c502..8f2b2545 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,7 +4,9 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.09a (dev) - - something cool :-) + - afl-fuzz: + - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) + before terminating. ### Version ++4.08c (release) @@ -22,7 +24,6 @@ - -l X option to enable base64 transformation solving - allow to disable CMPLOG with '-c -' (e.g. afl.rs enforces '-c 0' on every instance which is counterproductive). - - afl-cmin/afl-cmin.bash: - fixed a bug inherited from vanilla AFL where a coverage of map[123] = 11 would be the same as map[1123] = 1 @@ -40,7 +41,6 @@ - qemu_mode: - added qemu_mode/utils/qemu_get_symbol_addr.sh - ### Version ++4.07c (release) - afl-fuzz: - reverse reading the seeds only on restarts (increases performance) @@ -69,7 +69,6 @@ - TritonDSE in custom_mutators/aflpp_tritondse - SymQEMU in custom_mutators/symqemu - ### Version ++4.06c (release) - afl-fuzz: - ensure temporary file descriptor is closed when not used diff --git a/docs/env_variables.md b/docs/env_variables.md index affc9e3c..2ce274d3 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -412,10 +412,15 @@ checks or alter some of the more exotic semantics of the tool: set `AFL_IGNORE_PROBLEMS`. If you additionally want to also ignore coverage from late loaded libraries, you can set `AFL_IGNORE_PROBLEMS_COVERAGE`. - - When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the - fuzzer to import test cases from other instances before doing anything else. - This makes the "own finds" counter in the UI more accurate. Beyond counter - aesthetics, not much else should change. + - When running with multiple afl-fuzz or with `-F`, setting `AFL_IMPORT_FIRST` + causes the fuzzer to import test cases from other instances before doing + anything else. This makes the "own finds" counter in the UI more accurate. + + - When running with multiple afl-fuzz or with `-F`, setting `AFL_FINAL_SYNC` + will cause the fuzzer to perform a final import of test cases when + terminating. This is beneficial for `-M` main fuzzers to ensure it has all + unique test cases and hence you only need to `afl-cmin` this single + queue. - Setting `AFL_INPUT_LEN_MIN` and `AFL_INPUT_LEN_MAX` are an alternative to the afl-fuzz -g/-G command line option to control the minimum/maximum diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index ef84a18c..1f89bbd8 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -402,7 +402,8 @@ typedef struct afl_env_vars { afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability, - afl_post_process_keep_original, afl_crashing_seeds_as_new_crash; + afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, + afl_final_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 0007d5a8..3f5a9e1c 100644 --- a/include/envs.h +++ b/include/envs.h @@ -59,6 +59,7 @@ static char *afl_environment_variables[] = { "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", + "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DRIVER_NO_HOOK", diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 5a6b95cf..97e00415 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -269,6 +269,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_import_first = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_FINAL_SYNC", + + afl_environment_variable_len)) { + + afl->afl_env.afl_final_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.c b/src/afl-fuzz.c index cdb3f996..c2ec4a1d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2899,6 +2899,15 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif + if (afl->afl_env.afl_final_sync) { + + SAYF(cYEL "[!] " cRST "\nPerforming final sync, this make take some time ...\n"); + sync_fuzzers(afl); + write_bitmap(afl); + SAYF(cYEL "[!] " cRST "Done!\n\n"); + + } + if (afl->is_main_node) { u8 path[PATH_MAX]; -- cgit 1.4.1 From 030799638ddb7bd42d97fea81951c7cb246e263b Mon Sep 17 00:00:00 2001 From: chinggg <24590067+chinggg@users.noreply.github.com> Date: Sun, 13 Aug 2023 00:24:44 +0800 Subject: Remove redundant comparison of `fav_factor` in `update_bitmap_score` `top_rated_fav_factor` was actually calculated twice, but only one calculation and comparison is needed. Since `fav_factor` > `top_rated_fav_factor` will always cause skip of current iteration, `else if (fuzz_p2 == top_rated_fuzz_p2)` is also redundant. --- src/afl-fuzz-queue.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 48fd33ec..20973f51 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -746,30 +746,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } - if (fuzz_p2 > top_rated_fuzz_p2) { + if (fuzz_p2 > top_rated_fuzz_p2) continue; - continue; - - } else if (fuzz_p2 == top_rated_fuzz_p2) { - - if (fav_factor > top_rated_fav_factor) { continue; } - - } - - if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { - - if (fav_factor > afl->top_rated[i]->len << 2) { continue; } - - } else { - - if (fav_factor > - afl->top_rated[i]->exec_us * afl->top_rated[i]->len) { - - continue; - - } - - } + if (fav_factor > top_rated_fav_factor) continue; /* Looks like we're going to win. Decrease ref count for the previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ -- cgit 1.4.1 From 26f29fd485efaa08824c27501f82caeea525b5e3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 13 Aug 2023 10:18:33 +0200 Subject: nits --- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-queue.c | 27 ++++++++++++++++++++------- src/afl-fuzz.c | 3 ++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 87157cad..0429db34 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -474,7 +474,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Generating a hash on every input is super expensive. Bad idea and should only be used for special schedules */ - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); classified = 1; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 20973f51..14ba1ace 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -701,13 +701,20 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fav_factor; u64 fuzz_p2; - if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) + if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + fuzz_p2 = 0; // Skip the fuzz_p2 comparison - else if (unlikely(afl->schedule == RARE)) + + } else if (unlikely(afl->schedule == RARE)) { + fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]); - else + + } else { + fuzz_p2 = q->fuzz_level; + } + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { fav_factor = q->len << 2; @@ -729,12 +736,18 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { /* Faster-executing or smaller test cases are favored. */ u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) + + if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + top_rated_fuzz_p2 = next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); - else + + } else { + top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level; + } + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { top_rated_fav_factor = afl->top_rated[i]->len << 2; @@ -746,9 +759,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } - if (fuzz_p2 > top_rated_fuzz_p2) continue; + if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; } - if (fav_factor > top_rated_fav_factor) continue; + if (likely(fav_factor > top_rated_fav_factor)) { continue; } /* Looks like we're going to win. Decrease ref count for the previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c2ec4a1d..93bcdccf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2901,7 +2901,8 @@ stop_fuzzing: if (afl->afl_env.afl_final_sync) { - SAYF(cYEL "[!] " cRST "\nPerforming final sync, this make take some time ...\n"); + SAYF(cYEL "[!] " cRST + "\nPerforming final sync, this make take some time ...\n"); sync_fuzzers(afl); write_bitmap(afl); SAYF(cYEL "[!] " cRST "Done!\n\n"); -- cgit 1.4.1 From 4d8d8633ff39cda2f1d48b66c45e5ae6cd2af477 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 13 Aug 2023 11:44:37 +0200 Subject: update faq --- docs/FAQ.md | 40 ++++++++++++++++++++++++++++++++++++++-- include/afl-fuzz.h | 9 ++++----- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 9275eb94..242a379b 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -29,8 +29,8 @@ If you find an interesting or important question missing, submit it via which then implemented their own research and features, making it now by far the most flexible and feature rich guided fuzzer available as open source. And in independent fuzzing benchmarks it is one of the best fuzzers available, - e.g., [Fuzzbench - Report](https://www.fuzzbench.com/reports/2020-08-03/index.html). + e.g., + [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html).

@@ -103,6 +103,42 @@ If you find an interesting or important question missing, submit it via to itself, this too would be an edge.

+
+ Should you ever stop afl-fuzz, minimize the corpus and restart?

+ + To stop afl-fuzz, minimize it's corpus and restart you would usually do: + + ``` + Control-C # to terminate afl-fuzz + $ afl-cmin -T nproc -i out/default/queue -o minimized_queue -- ./target + $ AFL_FAST_CAL=1 AFL_CMPLOG_ONLY_NEW=1 afl-fuzz -i minimized_queue -o out2 [other options] -- ./target + ``` + + If this improves fuzzing or not is debated and no consensus has been reached + or in-depth analysis been performed. + + On the pro side: + * The queue/corpus is reduced (up to 20%) by removing intermediate paths + that are maybe not needed anymore. + + On the con side: + * Fuzzing time is lost for the time the fuzzing is stopped, minimized and + restarted. + + The the big question: + * Does a minimized queue/corpus improve finding new coverage or does it + hinder it? + + The AFL++ team's own limited analysis seem to to show that keeping + intermediate paths help to find more coverage, at least for afl-fuzz. + + For honggfuzz in comparison it is a good idea to restart it from time to + time if you have other fuzzers (e.g: AFL++) running in parallel to sync + the finds of other fuzzers to honggfuzz as it has no syncing feature like + AFL++ or libfuzzer. + +

+ ## Targets
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1f89bbd8..3dfd2b2c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -158,6 +158,7 @@ struct queue_entry { u8 colorized, /* Do not run redqueen stage again */ cal_failed; /* Calibration failed? */ + bool trim_done, /* Trimmed? */ was_fuzzed, /* historical, but needed for MOpt */ passed_det, /* Deterministic stages passed? */ @@ -169,17 +170,15 @@ struct queue_entry { disabled; /* Is disabled from fuzz selection */ u32 bitmap_size, /* Number of bits set in bitmap */ - fuzz_level, /* Number of fuzzing iterations */ - n_fuzz_entry /* offset in n_fuzz */ #ifdef INTROSPECTION - , stats_selected, /* stats: how often selected */ stats_skipped, /* stats: how often skipped */ stats_finds, /* stats: # of saved finds */ stats_crashes, /* stats: # of saved crashes */ - stats_tmouts /* stats: # of saved timeouts */ + stats_tmouts, /* stats: # of saved timeouts */ #endif - ; + fuzz_level, /* Number of fuzzing iterations */ + n_fuzz_entry; /* offset in n_fuzz */ u64 exec_us, /* Execution time (us) */ handicap, /* Number of queue cycles behind */ -- cgit 1.4.1 From fdb4ed2131347b78ae2904978a331d87333f8f3f Mon Sep 17 00:00:00 2001 From: echel0nn Date: Sun, 13 Aug 2023 19:41:43 +0300 Subject: added an example of ELF Header mutator --- custom_mutators/examples/elf_header_mutator.c | 684 ++++++++++++++++++++++++++ 1 file changed, 684 insertions(+) create mode 100644 custom_mutators/examples/elf_header_mutator.c diff --git a/custom_mutators/examples/elf_header_mutator.c b/custom_mutators/examples/elf_header_mutator.c new file mode 100644 index 00000000..32980d12 --- /dev/null +++ b/custom_mutators/examples/elf_header_mutator.c @@ -0,0 +1,684 @@ +/* + AFL++ Custom Mutator for ELF Headers + Written by @echel0n + based on libgolf.h by @xcellerator + $ gcc -O3 -fPIC -shared -o elf_mutator.so -I ~/AFLplusplus/include/ + */ +#include "afl-fuzz.h" +#include +#include +#include +#include +#include +#include + +/* EI_ABIVERSION isn't used anymore and elf.h defines EI_PAD to be 0x09 */ +#define EI_ABIVERSION 0x08 +#define EI_PAD 0x09 +/* Define the Architecture and ISA constants to match those in */ +#define X86_64 EM_X86_64 +#define ARM32 EM_ARM +#define AARCH64 EM_AARCH64 +#define uchar unsigned char +#define DATA_SIZE 0x100 + +/* + * The ELF and Program headers are different sizes depending on 32- and 64-bit + * architectures + * taken from libgolf.h + */ +#define EHDR_T(x) Elf##x##_Ehdr +#define PHDR_T(x) Elf##x##_Phdr +#define EHDR(x) ehdr##x +#define PHDR(x) phdr##x +#define GET_EHDR(x) (&(elf_ptr->EHDR(x))); +#define GET_PHDR(x) (&(elf_ptr->PHDR(x))); +#define REF_EHDR(b, x) ((Elf##b##_Ehdr *)ehdr)->x +#define REF_PHDR(b, x) ((Elf##b##_Phdr *)phdr)->x +int ehdr_size; +int phdr_size; +/* + * This struct holds the bytes that will be executed, and the size. + */ +typedef struct text_segment { + + size_t text_size; + unsigned char *text_segment; + +} TextSegment; + +// example shellcode that exits +// taken from libgolf.h +unsigned char buf[] = {0xb0, 0x3c, 0x31, 0xff, 0x0f, 0x05}; + +/* + * This is the raw ELF file + * - EHDR(xx) is the ELF header + * - PHDR(xx) is the program header + * - text is the text segment + * - filename is the name of the golf'd binary + * - isa is the target architecture (X86_64, ARM32, AARCH64) + * taken from libgolf.h + */ +typedef struct rawbinary_t { + + EHDR_T(32) EHDR(32); + PHDR_T(32) PHDR(32); + EHDR_T(64) EHDR(64); + PHDR_T(64) PHDR(64); + TextSegment text; + char *filename; + int isa; + +} RawBinary; + +/* + * Copy an E_IDENT array into the corresponding fields in the ELF header + * Called by populate_ehdr() + * taken from libgolf.h + */ +int populate_e_ident(RawBinary *elf_ptr, unsigned char e_ident[]) { + + int i; + /* Depending on whether the target ISA is 32- or 64-bit, set e_ident */ + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + for (i = 0; i < EI_NIDENT; i++) + elf_ptr->EHDR(64).e_ident[i] = e_ident[i]; + break; + case ARM32: + for (i = 0; i < EI_NIDENT; i++) + elf_ptr->EHDR(32).e_ident[i] = e_ident[i]; + break; + default: + exit(1); + + } + + return 0; + +} + +/* + * Copy bytes from buf[] array into text_segment in ELF struct + * taken from libgolf.h + */ +int copy_text_segment(RawBinary *elf_ptr, unsigned char buf[], int text_size) { + + int i; + + /* Set size of text segment and allocate the buffer */ + elf_ptr->text.text_size = text_size; + elf_ptr->text.text_segment = + malloc(elf_ptr->text.text_size * sizeof(unsigned char)); + + /* Copy the bytes into the text segment buffer */ + for (i = 0; i < elf_ptr->text.text_size; i++) { + + elf_ptr->text.text_segment[i] = buf[i]; + + } + +} + +/* + * Populate the ELF Header with sane values + * Returns a pointer to an EHDR struct + * taken from libgolf.h + */ +void *populate_ehdr(RawBinary *elf_ptr) { + + /* + * Set ehdr_size and phdr_size. Determined by whether target ISA is 32- or + * 64-bit. + */ + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + ehdr_size = sizeof(EHDR_T(64)); + phdr_size = sizeof(PHDR_T(64)); + break; + case ARM32: + ehdr_size = sizeof(EHDR_T(32)); + phdr_size = sizeof(PHDR_T(32)); + break; + default: + exit(1); + + }; + + /* Start with the E_IDENT area at the top of the file */ + unsigned char e_ident[EI_NIDENT] = {0}; + + /* Magic Bytes */ + e_ident[EI_MAG0] = 0x7F; + e_ident[EI_MAG1] = 0x45; // E + e_ident[EI_MAG2] = 0x4C; // L + e_ident[EI_MAG3] = 0x46; // F + + /* + * EI_CLASS denotes the architecture: + * ELFCLASS32: 0x01 + * ELFCLASS64: 0x02 + */ + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + e_ident[EI_CLASS] = ELFCLASS64; + break; + case ARM32: + e_ident[EI_CLASS] = ELFCLASS32; + break; + default: + exit(1); + + } + + /* + * EI_DATA denotes the endianness: + * ELFDATA2LSB: 0x01 + * ELFDATA2MSB: 0x02 + */ + e_ident[EI_DATA] = ELFDATA2LSB; + + /* EI_VERSION is always 0x01 */ + e_ident[EI_VERSION] = EV_CURRENT; + + /* + * EI_OSABI defines the target OS. Ignored by most modern ELF parsers. + */ + e_ident[EI_OSABI] = ELFOSABI_NONE; + + /* EI_ABIVERSION was for sub-classification. Un-defined since Linux 2.6 */ + e_ident[EI_ABIVERSION] = 0x00; + + /* EI_PAD is currently unused */ + e_ident[EI_PAD] = 0x00; + + /* Copy the E_IDENT section to the ELF struct */ + populate_e_ident(elf_ptr, e_ident); + + /* + * The remainder of the ELF header following E_IDENT follows. + * + * ehdr is a pointer to either an Elf32_Edhr, or Elf64_Ehdr struct. + */ + void *ehdr = NULL; + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + ehdr = (&(elf_ptr->EHDR(64))); + break; + case ARM32: + ehdr = (&(elf_ptr->EHDR(32))); + break; + default: + exit(1); + + } + + /* + * Depending on whether the ISA is 32- or 64-bit determines the size of + * many of the fields in the ELF Header. This switch case deals with it. + */ + switch (elf_ptr->isa) { + + // 64-Bit ISAs + case X86_64: + case AARCH64: + /* + * e_type specifies what kind of ELF file this is: + * ET_NONE: 0x00 // Unknown Type + * ET_REL: 0x01 // Relocatable + * ET_EXEC: 0x02 // Executable File + * ET_DYN: 0x03 // Shared Object + * ET_CORE: 0x04 // Core Dump + */ + REF_EHDR(64, e_type) = ET_EXEC; // 0x0002 + + /* e_machine specifies the target ISA */ + REF_EHDR(64, e_machine) = elf_ptr->isa; + + /* e_version is always set of 0x01 for the original ELF spec */ + REF_EHDR(64, e_version) = EV_CURRENT; // 0x00000001 + + /* + * e_entry is the memory address of the entry point + * Set by set_entry_point() after p_vaddr is set in the phdr + */ + REF_EHDR(64, e_entry) = 0x0; + + /* + * e_phoff points to the start of the program header, which + * immediately follows the ELF header + */ + REF_EHDR(64, e_phoff) = ehdr_size; + + /* e_shoff points to the start of the section header table */ + REF_EHDR(64, e_shoff) = 0x00; + + /* e_flags is architecture dependent */ + REF_EHDR(64, e_flags) = 0x0; + + /* e_ehsize contains the size of the ELF header */ + REF_EHDR(64, e_ehsize) = ehdr_size; + + /* e_phentsize is the size of the program header */ + REF_EHDR(64, e_phentsize) = phdr_size; + + /* + * e_phnum contains the number of entries in the program header + * e_phnum * e_phentsize = size of program header table + */ + REF_EHDR(64, e_phnum) = 0x1; + + /* e_shentsize contains the size of a section header entry */ + REF_EHDR(64, e_shentsize) = 0x0; + + /* + * e_shnum contains the number of entries in the section header + * e_shnum * e_shentsize = size of section header table + */ + REF_EHDR(64, e_shnum) = 0x0; + + /* + * e_shstrndx contains the index of the section header table that + * contains the section names + */ + REF_EHDR(64, e_shstrndx) = 0x0; + + break; + // 32-Bit ISAs + case ARM32: + /* + * e_type specifies what kind of ELF file this is: + * ET_NONE: 0x00 // Unknown Type + * ET_REL: 0x01 // Relocatable + * ET_EXEC: 0x02 // Executable File + * ET_DYN: 0x03 // Shared Object + * ET_CORE: 0x04 // Core Dump + */ + REF_EHDR(32, e_type) = ET_EXEC; // 0x0002 + + /* e_machine specifies the target ISA */ + REF_EHDR(32, e_machine) = elf_ptr->isa; + + /* e_version is always set of 0x01 for the original ELF spec */ + REF_EHDR(32, e_version) = EV_CURRENT; // 0x00000001 + + /* + * e_entry is the memory address of the entry point + * Set by set_entry_point() after p_vaddr is set in the phdr + */ + REF_EHDR(32, e_entry) = 0x0; + + /* + * e_phoff points to the start of the program header, which + * immediately follows the ELF header + */ + REF_EHDR(32, e_phoff) = ehdr_size; + + /* e_shoff points to the start of the section header table */ + REF_EHDR(32, e_shoff) = 0x0i; + + /* e_flags is architecture dependent */ + REF_EHDR(32, e_flags) = 0x0; + + /* e_ehsize contains the size of the ELF header */ + REF_EHDR(32, e_ehsize) = ehdr_size; + + /* e_phentsize is the size of the program header */ + REF_EHDR(32, e_phentsize) = phdr_size; + + /* + * e_phnum contains the number of entries in the program header + * e_phnum * e_phentsize = size of program header table + */ + REF_EHDR(32, e_phnum) = 0x1; + + /* e_shentsize contains the size of a section header entry */ + REF_EHDR(32, e_shentsize) = 0x0; + + /* + * e_shnum contains the number of entries in the section header + * e_shnum * e_shentsize = size of section header table + */ + REF_EHDR(32, e_shnum) = 0x0; + + /* + * e_shstrndx contains the index of the section header table that + * contains the section names + */ + REF_EHDR(32, e_shnum) = 0x0; + + break; + + } + + return ehdr; + +} + +/* + * Populate the program headers with sane values + * Returns a pointer to a PHDR struct + * taken from libgolf.h + */ +void *populate_phdr(RawBinary *elf_ptr) { + + /* + * All offsets are relative to the start of the program header (0x40) + * + * phdr is a pointer to either an Elf32_Phdr, or Elf64_Phdr struct. + */ + void *phdr = NULL; + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + phdr = (&(elf_ptr->PHDR(64))); + break; + case ARM32: + phdr = (&(elf_ptr->PHDR(32))); + break; + default: + exit(1); + + } + + /* + * Depending on whether the ISA is 32- or 64-bit determines the size of + * many of the fields in the Progra Header. This switch case deals with it. + */ + switch (elf_ptr->isa) { + + // 64-Bit ISAs + case X86_64: + case AARCH64: + /* + * p_type identifies what type of segment this is + * PT_NULL: 0x0 // Unused + * PT_LOAD: 0x1 // Loadable Segment + * PT_DYNAMIC: 0x2 // Dynamic Linker Information + * PT_INTERP: 0x3 // Interpreter Information + * PT_NOTE: 0x4 // Auxiliary Information + * PT_SHLIB: 0x5 // Reserved + * PT_PHDR: 0x6 // Segment with Program Header + * PT_TLS: 0x7 // Thread Local Storage + */ + REF_PHDR(64, p_type) = PT_LOAD; // 0x1 + + /* + * p_flags defines permissions for this section + * PF_R: 0x4 // Read + * PF_W: 0x2 // Write + * PF_X: 0x1 // Execute + */ + REF_PHDR(64, p_flags) = PF_R | PF_X; // 0x5 + + /* + * p_offset is the offset in the file image (relative to the start + * of the program header) for this segment. + */ + REF_PHDR(64, p_offset) = 0x0; + + /* + * p_vaddr is the virtual address where this segment should be loaded + * p_paddr is for the physical address (unused by System V) + */ + REF_PHDR(64, p_vaddr) = 0x400000; + REF_PHDR(64, p_paddr) = 0x400000; + + /* + * p_filesz is the size of the segment in the file image + * p_memsz is the size of the segment in memory + * + * Note: p_filesz doesn't have to equal p_memsz + */ + REF_PHDR(64, p_filesz) = elf_ptr->text.text_size; + REF_PHDR(64, p_memsz) = elf_ptr->text.text_size; + + break; + // 32-Bit ISAs + case ARM32: + /* + * p_type identifies what type of segment this is + * PT_NULL: 0x0 // Unused + * PT_LOAD: 0x1 // Loadable Segment + * PT_DYNAMIC: 0x2 // Dynamic Linker Information + * PT_INTERP: 0x3 // Interpreter Information + * PT_NOTE: 0x4 // Auxiliary Information + * PT_SHLIB: 0x5 // Reserved + * PT_PHDR: 0x6 // Segment with Program Header + * PT_TLS: 0x7 // Thread Local Storage + */ + REF_PHDR(32, p_type) = PT_LOAD; // 0x1 + + /* + * p_flags defines permissions for this section + * PF_R: 0x4 // Read + * PF_W: 0x2 // Write + * PF_X: 0x1 // Execute + */ + REF_PHDR(32, p_flags) = PF_R | PF_X; // 0x5 + + /* + * p_offset is the offset in the file image (relative to the start + * of the program header) for this segment. + */ + REF_PHDR(32, p_offset) = 0x0; + + /* + * p_vaddr is the virtual address where this segment should be loaded + * p_paddr is for the physical address (unused by System V) + */ + REF_PHDR(32, p_vaddr) = 0x10000; + REF_PHDR(32, p_paddr) = 0x10000; + + /* + * p_filesz is the size of the segment in the file image + * p_memsz is the size of the segment in memory + * + * Note: p_filesz doesn't have to equal p_memsz + */ + REF_PHDR(32, p_filesz) = elf_ptr->text.text_size; + REF_PHDR(32, p_memsz) = elf_ptr->text.text_size; + + break; + default: + exit(1); + + } + + /* + * p_align is the memory alignment + * + * Note: p_vaddr = p_offset % p_align + */ + switch (elf_ptr->isa) { + + case X86_64: + REF_PHDR(64, p_align) = 0x400000; + break; + case ARM32: + REF_PHDR(32, p_align) = 0x10000; + break; + case AARCH64: + REF_PHDR(64, p_align) = 0x400000; + break; + + } + + return phdr; + +} + +/* + * e_entry depends on p_vaddr, so has to be set after populate_ehdr() + * and populate_phdr() have been called. + * taken from libgolf.h + */ +int set_entry_point(RawBinary *elf_ptr) { + + /* + * Once the whole ELF file is copied into memory, control is handed to + * e_entry. Relative to the process's virtual memory address, the .text + * segment will be located immediately after the ELF and program header. + * + * ehdr and phdr are pointers to the ELF and Program headers respectively. + * The switch case casts and assigns them to the correct fields of the ELF + * struct, then sets ehdr->e_entry. + */ + void *ehdr, *phdr; + + switch (elf_ptr->isa) { + + case X86_64: + case AARCH64: + ehdr = GET_EHDR(64); + phdr = GET_PHDR(64); + REF_EHDR(64, e_entry) = REF_PHDR(64, p_vaddr) + ehdr_size + phdr_size; + break; + case ARM32: + ehdr = GET_EHDR(32); + phdr = GET_PHDR(32); + REF_EHDR(32, e_entry) = REF_PHDR(32, p_vaddr) + ehdr_size + phdr_size; + break; + default: + exit(1); + + } + + return 0; + +} + +typedef struct my_mutator { + + afl_state_t *afl; + size_t trim_size_current; + int trimmming_steps; + int cur_step; + u8 *mutated_out, *post_process_buf, *trim_buf; + +} my_mutator_t; + +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { + + srand(seed); // needed also by surgical_havoc_mutate() + my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); + if (!data) { + + perror("afl_custom_init alloc"); + return NULL; + + } + + if ((data->mutated_out = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + + if ((data->post_process_buf = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + + if ((data->trim_buf = (u8 *)malloc(MAX_FILE)) == NULL) { + + perror("afl_custom_init malloc"); + return NULL; + + } + + data->afl = afl; + return data; + +} + +size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *in_buf, size_t buf_size, + u8 **out_buf, uint8_t *add_buf, + size_t add_buf_size, // add_buf can be NULL + size_t max_size) { + + RawBinary elf_obj; + RawBinary *elf = &elf_obj; + elf->isa = 62; + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdr; + copy_text_segment(elf, buf, sizeof(buf)); + ehdr = populate_ehdr(elf); + phdr = populate_phdr(elf); + set_entry_point(elf); + + size_t mutated_size = ehdr_size + phdr_size + elf->text.text_size; + int pos = 0; + // example fields + ehdr->e_ident[EI_CLASS] = (uint8_t *)(in_buf + pos); + pos = pos + 1; + ehdr->e_ident[EI_DATA] = (uint8_t *)(in_buf + pos); + pos = pos + 1; + ehdr->e_ident[EI_VERSION] = (uint8_t *)(in_buf + pos); + pos = pos + 1; + ehdr->e_ident[EI_OSABI] = (uint8_t *)(in_buf + pos); + pos = pos + 1; + for (int i = 0x8; i < 0x10; ++i) { + + (ehdr->e_ident)[i] = (uint8_t *)(in_buf + pos); + pos = pos + 1; + + } + + ehdr->e_version = (uint32_t *)(in_buf + pos); + pos = pos + 4; + // sections headers + ehdr->e_shoff = (uint64_t *)(in_buf + pos); + pos = pos + 8; + ehdr->e_shentsize = (uint16_t *)(in_buf + pos); + pos = pos + 2; + ehdr->e_shnum = (uint16_t *)(in_buf + pos); + pos = pos + 2; + ehdr->e_shstrndx = (uint16_t *)(in_buf + pos); + pos = pos + 2; + ehdr->e_flags = (uint32_t *)(in_buf + pos); + pos = pos + 4; + // physical addr + phdr->p_paddr = (uint64_t *)(in_buf + pos); + pos = pos + 8; + phdr->p_align = (uint64_t *)(in_buf + pos); + pos = pos + 8; + + /* mimic GEN_ELF() + * Write: + * - ELF Header + * - Program Header + * - Text Segment + */ + memcpy(data->mutated_out, ehdr, ehdr_size); + memcpy(data->mutated_out + ehdr_size, phdr, phdr_size); + memcpy(data->mutated_out + ehdr_size + phdr_size, elf->text.text_segment, + elf->text.text_size); + + *out_buf = data->mutated_out; + return mutated_size; + +} + +void afl_custom_deinit(my_mutator_t *data) { + + free(data->post_process_buf); + free(data->mutated_out); + free(data->trim_buf); + free(data); + +} + -- cgit 1.4.1 From ca82b65d6c10482aee9cedbea43a5078011b1ce2 Mon Sep 17 00:00:00 2001 From: echel0nn Date: Sun, 13 Aug 2023 21:59:00 +0300 Subject: added README description & shortened pos defs --- custom_mutators/examples/README.md | 3 +++ custom_mutators/examples/elf_header_mutator.c | 31 +++++++++++---------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/custom_mutators/examples/README.md b/custom_mutators/examples/README.md index 655f7a5e..112db243 100644 --- a/custom_mutators/examples/README.md +++ b/custom_mutators/examples/README.md @@ -33,3 +33,6 @@ like surgical_havoc_mutate() that allow to perform a randomly chosen mutation from a subset of the havoc mutations. If you do so, you have to specify -I /path/to/AFLplusplus/include when compiling. + +elf_header_mutator.c - example ELF header mutator based on + [LibGolf](https://github.com/xcellerator/libgolf/) diff --git a/custom_mutators/examples/elf_header_mutator.c b/custom_mutators/examples/elf_header_mutator.c index 32980d12..b985257a 100644 --- a/custom_mutators/examples/elf_header_mutator.c +++ b/custom_mutators/examples/elf_header_mutator.c @@ -623,39 +623,34 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *in_buf, size_t buf_size, size_t mutated_size = ehdr_size + phdr_size + elf->text.text_size; int pos = 0; // example fields - ehdr->e_ident[EI_CLASS] = (uint8_t *)(in_buf + pos); - pos = pos + 1; - ehdr->e_ident[EI_DATA] = (uint8_t *)(in_buf + pos); - pos = pos + 1; - ehdr->e_ident[EI_VERSION] = (uint8_t *)(in_buf + pos); - pos = pos + 1; - ehdr->e_ident[EI_OSABI] = (uint8_t *)(in_buf + pos); - pos = pos + 1; + ehdr->e_ident[EI_CLASS] = (uint8_t *)(in_buf + pos++); + ehdr->e_ident[EI_DATA] = (uint8_t *)(in_buf + pos++); + ehdr->e_ident[EI_VERSION] = (uint8_t *)(in_buf + pos++); + ehdr->e_ident[EI_OSABI] = (uint8_t *)(in_buf + pos++); for (int i = 0x8; i < 0x10; ++i) { - (ehdr->e_ident)[i] = (uint8_t *)(in_buf + pos); - pos = pos + 1; + (ehdr->e_ident)[i] = (uint8_t *)(in_buf + pos++); } ehdr->e_version = (uint32_t *)(in_buf + pos); - pos = pos + 4; + pos += 4; // sections headers ehdr->e_shoff = (uint64_t *)(in_buf + pos); - pos = pos + 8; + pos += 8; ehdr->e_shentsize = (uint16_t *)(in_buf + pos); - pos = pos + 2; + pos += 2; ehdr->e_shnum = (uint16_t *)(in_buf + pos); - pos = pos + 2; + pos += 2; ehdr->e_shstrndx = (uint16_t *)(in_buf + pos); - pos = pos + 2; + pos += 2; ehdr->e_flags = (uint32_t *)(in_buf + pos); - pos = pos + 4; + pos += 4; // physical addr phdr->p_paddr = (uint64_t *)(in_buf + pos); - pos = pos + 8; + pos += 8; phdr->p_align = (uint64_t *)(in_buf + pos); - pos = pos + 8; + pos += 8; /* mimic GEN_ELF() * Write: -- cgit 1.4.1 From c2c8e780a5d10fe7500ec9add0aa5b2cb081fe71 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 16 Aug 2023 10:50:07 +0200 Subject: add benchmark --- benchmark/COMPARISON | 4 ++++ benchmark/benchmark.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ docs/Changelog.md | 2 ++ 3 files changed, 48 insertions(+) create mode 100644 benchmark/COMPARISON create mode 100755 benchmark/benchmark.sh diff --git a/benchmark/COMPARISON b/benchmark/COMPARISON new file mode 100644 index 00000000..55ab94b4 --- /dev/null +++ b/benchmark/COMPARISON @@ -0,0 +1,4 @@ +CPU | Mz | exec/s | afl-*-config | +========================================|======|========|==============| +CPU 12th Gen Intel(R) Core(TM) i7-1270P | 4200 | 12750 | both | +AMD EPYC 7282 16-Core Processor | 3190 | 10060 | both | diff --git a/benchmark/benchmark.sh b/benchmark/benchmark.sh new file mode 100755 index 00000000..3318adce --- /dev/null +++ b/benchmark/benchmark.sh @@ -0,0 +1,42 @@ +#!/bin/sh +test -x ../afl-fuzz -a -x ../afl-cc -a -e ../SanitizerCoveragePCGUARD.so || { + echo Error: you need to compile AFL++ first, we need afl-fuzz, afl-clang-fast and SanitizerCoveragePCGUARD.so built. + exit 1 +} + +echo Preparing environment + +env | grep AFL_ | sed 's/=.*//' | while read e; do + unset $e +done + +AFL_PATH=`pwd`/.. +export PATH=$AFL_PATH:$PATH + +AFL_LLVM_INSTRUMENT=PCGUARD afl-cc -o test-instr ../test-instr.c > afl.log 2>&1 || { + echo Error: afl-cc is unable to compile + exit 1 +} + +{ +mkdir in +dd if=/dev/zero of=in/in.txt bs=10K count=1 +} > /dev/null 2>&1 + +echo Ready, starting benchmark - this will take approx 20-30 seconds ... + +AFL_DISABLE_TRIM=1 AFL_NO_UI=1 AFL_TRY_AFFINITY=1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_BENCH_JUST_ONE=1 time afl-fuzz -i in -o out -s 123 -D ./test-instr >> afl.log 2>&1 + +echo Analysis: + +CPUID=$(grep 'try binding to' afl.log | tail -n 1 | sed 's/.*#//' | sed 's/\..*//') +grep 'model name' /proc/cpuinfo | head -n 1 | sed 's/.*:/ CPU:/' +test -n "$CPUID" && grep -E '^processor|^cpu MHz' /proc/cpuinfo | grep -A1 -w "$CPUID" | grep 'cpu MHz' | head -n 1 | sed 's/.*:/ Mhz:/' +test -z "$CPUID" && grep 'cpu MHz' /proc/cpuinfo | head -n 1 | sed 's/.*:/ Mhz:/' +grep execs_per_sec out/default/fuzzer_stats | sed 's/.*:/ execs\/s:/' + +echo +echo "Comparison: (note that values can change by 10-15% per run)" +cat COMPARISON + +rm -rf in out test-instr afl.log diff --git a/docs/Changelog.md b/docs/Changelog.md index 8f2b2545..b809559e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,8 @@ - afl-fuzz: - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) before terminating. + - added benchmark/benchmark.sh if you want to see how good your fuzzing + speed is in comparison to other setups. ### Version ++4.08c (release) -- cgit 1.4.1 From 8cf6a13eb7f0d56495baf92745fae3084dc2fb67 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Aug 2023 11:47:12 +0200 Subject: add env var to help output --- src/afl-fuzz.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 93bcdccf..43834172 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -299,6 +299,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n" "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n" + "AFL_NO_WARN_INSTABILITY: no warn about instability issues on startup calibration\n" "AFL_NO_UI: switch status screen off\n" "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n" " Increase this value in case the crash reports are truncated.\n" -- cgit 1.4.1 From 53c26d086b94c4e5f31dddac0dd212cbff89e957 Mon Sep 17 00:00:00 2001 From: "Samuel E. Moelius III" Date: Sat, 19 Aug 2023 08:17:23 -0400 Subject: Loosen `ReportCrash` check --- afl-system-config | 2 +- src/afl-fuzz-init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/afl-system-config b/afl-system-config index b50bb06e..e3eb8527 100755 --- a/afl-system-config +++ b/afl-system-config @@ -110,7 +110,7 @@ if [ "$PLATFORM" = "Darwin" ] ; then sysctl kern.sysv.shmall=131072000 echo Settings applied. echo - if $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ; then + if $(launchctl list 2>/dev/null | grep -q '\.ReportCrash\>') ; then echo echo Unloading the default crash reporter SL=/System/Library; PL=com.apple.ReportCrash diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 5a530821..4c09fab7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2270,7 +2270,7 @@ void check_crash_handling(void) { reporting the awful way. */ #if !TARGET_OS_IPHONE - if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return; + if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'")) return; SAYF( "\n" cLRD "[-] " cRST -- cgit 1.4.1 From 80f74934dd413c35fe71c27214d18cfd16de3cce Mon Sep 17 00:00:00 2001 From: "Samuel E. Moelius III" Date: Sat, 19 Aug 2023 08:43:47 -0400 Subject: Don't hide errors --- afl-system-config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/afl-system-config b/afl-system-config index e3eb8527..07d509ff 100755 --- a/afl-system-config +++ b/afl-system-config @@ -114,8 +114,8 @@ if [ "$PLATFORM" = "Darwin" ] ; then echo echo Unloading the default crash reporter SL=/System/Library; PL=com.apple.ReportCrash - launchctl unload -w ${SL}/LaunchAgents/${PL}.plist >/dev/null 2>&1 - sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1 + launchctl unload -w ${SL}/LaunchAgents/${PL}.plist + sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist echo fi echo It is recommended to disable System Integrity Protection for increased performance. -- cgit 1.4.1 From 71f9999f292ba524a4c67a124c00db4205111350 Mon Sep 17 00:00:00 2001 From: "Samuel E. Moelius III" Date: Sat, 19 Aug 2023 11:08:01 -0400 Subject: Adjust use of `sudo` --- afl-system-config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/afl-system-config b/afl-system-config index 07d509ff..e64857eb 100755 --- a/afl-system-config +++ b/afl-system-config @@ -114,8 +114,8 @@ if [ "$PLATFORM" = "Darwin" ] ; then echo echo Unloading the default crash reporter SL=/System/Library; PL=com.apple.ReportCrash - launchctl unload -w ${SL}/LaunchAgents/${PL}.plist - sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist + sudo -u "$SUDO_USER" launchctl unload -w ${SL}/LaunchAgents/${PL}.plist + launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist echo fi echo It is recommended to disable System Integrity Protection for increased performance. -- cgit 1.4.1 From 213298fe5939df730d2341e2d2f75cd6daf77df7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 21 Aug 2023 16:38:48 +0200 Subject: afl-whatsup add coverage output --- afl-whatsup | 12 ++++++++++++ docs/Changelog.md | 1 + 2 files changed, 13 insertions(+) diff --git a/afl-whatsup b/afl-whatsup index 6f29ab24..c1f0abaa 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -70,6 +70,8 @@ if [ -d queue ]; then fi +BC=`which bc 2>/dev/null` + RED=`tput setaf 9 1 1 2>/dev/null` GREEN=`tput setaf 2 1 1 2>/dev/null` BLUE=`tput setaf 4 1 1 2>/dev/null` @@ -91,6 +93,7 @@ TOTAL_CRASHES=0 TOTAL_HANGS=0 TOTAL_PFAV=0 TOTAL_PENDING=0 +TOTAL_COVERAGE= # Time since last find / crash / hang, formatted as string FMT_TIME="0 days 0 hours" @@ -147,6 +150,13 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do RUN_UNIX=$run_time RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24)) RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24)) + COVERAGE=$(echo $bitmap_cvg|tr -d %) + if [ -n "$TOTAL_COVERAGE" -a -n "$B" ]; then + if [ "$(echo "$TOTAL_COVERAGE < $COVERAGE" | bc)" -eq 1 ]; then + TOTAL_COVERAGE=$COVERAGE + fi + fi + if [ -z "$TOTAL_COVERAGE" ]; then TOTAL_COVERAGE=$COVERAGE ; fi test -n "$cycles_wo_finds" && { test -z "$FIRST" && TOTAL_WCOP="${TOTAL_WCOP}/" @@ -227,6 +237,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do echo " last_crash : $FMT_CRASH" echo " last_hang : $FMT_HANG" echo " cycles_wo_finds : $FMT_CWOP" + echo " coverage : $COVERAGE%" CPU_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $3}') MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}') @@ -302,6 +313,7 @@ if [ "$ALIVE_CNT" -gt "1" ]; then echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" fi +echo " Coverage reached : ${TOTAL_COVERAGE}%" echo " Crashes saved : $TOTAL_CRASHES" echo " Hangs saved : $TOTAL_HANGS" echo "Cycles without finds : $TOTAL_WCOP" diff --git a/docs/Changelog.md b/docs/Changelog.md index b809559e..dfb5afa1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,7 @@ - afl-fuzz: - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) before terminating. + - afl-whatsup: now also shows coverage reached - added benchmark/benchmark.sh if you want to see how good your fuzzing speed is in comparison to other setups. -- cgit 1.4.1 From f41d121f0767d929e34bbac7cb8d09ba4731730c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 22 Aug 2023 10:03:03 +0200 Subject: afl-whatsup -m -n --- afl-whatsup | 89 +++++++++++++++++++++++++++++++++++++++---------------- docs/Changelog.md | 5 +++- 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/afl-whatsup b/afl-whatsup index c1f0abaa..47133a13 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -24,38 +24,60 @@ test "$1" = "-h" -o "$1" = "-hh" && { echo "Usage: $0 [-s] [-d] afl_output_directory" echo echo Options: - echo " -s - skip details and output summary results only" echo " -d - include dead fuzzer stats" + echo " -m - just show minimal stats" + echo " -n - no color output" + echo " -s - skip details and output summary results only" echo exit 1 } -unset SUMMARY_ONLY +unset MINIMAL_ONLY +unset NO_COLOR unset PROCESS_DEAD +unset SUMMARY_ONLY +unset RED +unset GREEN +unset YELLOW +unset BLUE +unset NC +unset RESET -while [ "$1" = "-s" -o "$1" = "-d" ]; do +if [ -z "$TERM" ]; then export TERM=vt220; fi - if [ "$1" = "-s" ]; then - SUMMARY_ONLY=1 - fi +while [ "$1" = "-d" -o "$1" = "-m" -o "$1" = "-n" -o "$1" = "-s" ]; do if [ "$1" = "-d" ]; then PROCESS_DEAD=1 fi + if [ "$1" = "-m" ]; then + MINIMAL_ONLY=1 + fi + + if [ "$1" = "-n" ]; then + NO_COLOR=1 + fi + + if [ "$1" = "-s" ]; then + SUMMARY_ONLY=1 + fi + shift done DIR="$1" -if [ "$DIR" = "" ]; then +if [ "$DIR" = "" -o "$DIR" = "-h" -o "$DIR" = "--help" ]; then - echo "Usage: $0 [-s] [-d] afl_output_directory" 1>&2 + echo "Usage: $0 [-d] [-m] [-n] [-s] afl_output_directory" 1>&2 echo 1>&2 echo Options: 1>&2 - echo " -s - skip details and output summary results only" 1>&2 echo " -d - include dead fuzzer stats" 1>&2 + echo " -m - just show minimal stats" 1>&2 + echo " -n - no color output" 1>&2 + echo " -s - skip details and output summary results only" 1>&2 echo 1>&2 exit 1 @@ -72,12 +94,14 @@ fi BC=`which bc 2>/dev/null` -RED=`tput setaf 9 1 1 2>/dev/null` -GREEN=`tput setaf 2 1 1 2>/dev/null` -BLUE=`tput setaf 4 1 1 2>/dev/null` -YELLOW=`tput setaf 11 1 1 2>/dev/null` -NC=`tput sgr0` -RESET="$NC" +if [ -z "$NO_COLOR" ]; then + RED=`tput setaf 9 1 1 2>/dev/null` + GREEN=`tput setaf 2 1 1 2>/dev/null` + BLUE=`tput setaf 4 1 1 2>/dev/null` + YELLOW=`tput setaf 11 1 1 2>/dev/null` + NC=`tput sgr0` + RESET="$NC" +fi CUR_TIME=`date +%s` @@ -235,14 +259,21 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do echo " last_find : $FMT_FIND" echo " last_crash : $FMT_CRASH" - echo " last_hang : $FMT_HANG" - echo " cycles_wo_finds : $FMT_CWOP" + if [ -z "$MINIMAL_ONLY" ]; then + echo " last_hang : $FMT_HANG" + echo " cycles_wo_finds : $FMT_CWOP" + fi echo " coverage : $COVERAGE%" - CPU_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $3}') - MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}') + if [ -z "$MINIMAL_ONLY" ]; then + + CPU_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $3}') + MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}') + + echo " cpu usage $CPU_USAGE%, memory usage $MEM_USAGE%" + + fi - echo " cpu usage $CPU_USAGE%, memory usage $MEM_USAGE%" echo " cycles $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, items $cur_item/$corpus_count (${PATH_PERC}%)" if [ "$saved_crashes" = "0" ]; then @@ -302,21 +333,27 @@ if [ ! "$DEAD_CNT" = "0" ]; then fi echo " Total run time : $FMT_TIME" -echo " Total execs : $FMT_EXECS" -echo " Cumulative speed : $TOTAL_EPS execs/sec" +if [ -z "$MINIMAL_ONLY" ]; then + echo " Total execs : $FMT_EXECS" + echo " Cumulative speed : $TOTAL_EPS execs/sec" +fi if [ "$ALIVE_CNT" -gt "0" ]; then echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec" fi -echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total" +if [ -z "$MINIMAL_ONLY" ]; then + echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total" +fi -if [ "$ALIVE_CNT" -gt "1" ]; then +if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" fi echo " Coverage reached : ${TOTAL_COVERAGE}%" echo " Crashes saved : $TOTAL_CRASHES" -echo " Hangs saved : $TOTAL_HANGS" -echo "Cycles without finds : $TOTAL_WCOP" +if [ -z "$MINIMAL_ONLY" ]; then + echo " Hangs saved : $TOTAL_HANGS" + echo "Cycles without finds : $TOTAL_WCOP" +fi echo " Time without finds : $TOTAL_LAST_FIND" echo diff --git a/docs/Changelog.md b/docs/Changelog.md index dfb5afa1..fa9099c0 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,7 +7,10 @@ - afl-fuzz: - added `AFL_FINAL_SYNC` which forces a final fuzzer sync (also for `-F`) before terminating. - - afl-whatsup: now also shows coverage reached + - afl-whatsup: + - now also shows coverage reached + - option -m shows only very relevant stats + - option -n will not use color in the output - added benchmark/benchmark.sh if you want to see how good your fuzzing speed is in comparison to other setups. -- cgit 1.4.1 From 959b75358971c41956346636ce84d46dbe1bf286 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 22 Aug 2023 10:09:49 +0200 Subject: fix --- afl-whatsup | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/afl-whatsup b/afl-whatsup index 47133a13..bbb73e47 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -18,9 +18,9 @@ # instances of afl-fuzz. # -echo "$0 status check tool for afl-fuzz by Michal Zalewski" -echo test "$1" = "-h" -o "$1" = "-hh" && { + echo "$0 status check tool for afl-fuzz by Michal Zalewski" + echo echo "Usage: $0 [-s] [-d] afl_output_directory" echo echo Options: @@ -71,6 +71,8 @@ DIR="$1" if [ "$DIR" = "" -o "$DIR" = "-h" -o "$DIR" = "--help" ]; then + echo "$0 status check tool for afl-fuzz by Michal Zalewski" 1>&2 + echo 1>&2 echo "Usage: $0 [-d] [-m] [-n] [-s] afl_output_directory" 1>&2 echo 1>&2 echo Options: 1>&2 @@ -83,6 +85,11 @@ if [ "$DIR" = "" -o "$DIR" = "-h" -o "$DIR" = "--help" ]; then fi +if [ -z "$MINIMAL_ONLY" ]; then + echo "$0 status check tool for afl-fuzz by Michal Zalewski" + echo +fi + cd "$DIR" || exit 1 if [ -d queue ]; then @@ -325,7 +332,10 @@ fi echo "Summary stats" echo "=============" -echo +if [ -z "$SUMMARY_ONLY" -o -z "$MINIMAL_ONLY" ]; then + echo +fi + echo " Fuzzers alive : $ALIVE_CNT" if [ ! "$DEAD_CNT" = "0" ]; then @@ -345,7 +355,9 @@ if [ -z "$MINIMAL_ONLY" ]; then fi if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then - echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" + if [ "$ALIVE_CNT" -gt "0" ]; then + echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" + fi fi echo " Coverage reached : ${TOTAL_COVERAGE}%" -- cgit 1.4.1