diff options
-rw-r--r-- | .github/workflows/ci.yml | 42 | ||||
-rw-r--r-- | CONTRIBUTING.md | 4 | ||||
-rw-r--r-- | benchmark/COMPARISON.md | 1 | ||||
-rw-r--r-- | docs/env_variables.md | 2 | ||||
-rw-r--r-- | docs/fuzzing_in_depth.md | 2 | ||||
-rw-r--r-- | include/forkserver.h | 11 | ||||
-rw-r--r-- | nyx_mode/LIBNYX_VERSION | 2 | ||||
-rw-r--r-- | nyx_mode/PACKER_VERSION | 2 | ||||
m--------- | nyx_mode/libnyx | 0 | ||||
m--------- | nyx_mode/packer | 0 | ||||
-rw-r--r-- | qemu_mode/QEMUAFL_VERSION | 2 | ||||
-rw-r--r-- | qemu_mode/README.persistent.md | 15 | ||||
m--------- | qemu_mode/qemuafl | 0 | ||||
-rw-r--r-- | src/afl-forkserver.c | 16 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 47 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 11 | ||||
-rw-r--r-- | src/afl-fuzz.c | 19 | ||||
-rwxr-xr-x | test/test-llvm.sh | 8 |
18 files changed, 125 insertions, 59 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed382fbb..187ed011 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,23 +34,25 @@ jobs: run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 distrib - name: run tests run: sudo -E ./afl-system-config; make tests - # macos: - # runs-on: macOS-latest - # env: - # AFL_MAP_SIZE: 65536 - # AFL_SKIP_CPUFREQ: 1 - # AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 - # steps: - # - uses: actions/checkout@v3 - # - name: install - # run: brew install make gcc llvm - # - name: fix install - # run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v - # - name: build - # run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 - # - name: frida - # run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake - # - name: run tests - # run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests - # - name: force frida test for MacOS - # run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr + macos: + runs-on: macOS-latest + env: + AFL_MAP_SIZE: 65536 + AFL_SKIP_CPUFREQ: 1 + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 + steps: + - uses: actions/checkout@v3 + - name: install + run: brew install make gcc llvm +# - name: fix install +# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v +# - name: build +# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz + - name: build + run: sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz +# - name: frida +# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake +# - name: run tests +# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests +# - name: force frida test for MacOS +# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b4dcb6d..40f11ce8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ When working on the docs, please keep the following guidelines in mind: * Don't: fuzzing-network-service.md * Use a maximum of 80 characters per line to make reading in a console easier. * Make all pull requests against `dev`, see - [#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl). + [#how-to-submit-a-pull-request](#how-to-submit-a-pull-request). And finally, here are some best practices for writing docs content: @@ -57,4 +57,4 @@ And finally, here are some best practices for writing docs content: * Use bulleted lists to present similar content in a way that makes it easy to scan. * Use numbered lists for procedures or prioritizing. -* Link to related content, for example, prerequisites or in-depth discussions. \ No newline at end of file +* Link to related content, for example, prerequisites or in-depth discussions. diff --git a/benchmark/COMPARISON.md b/benchmark/COMPARISON.md index e16ef213..92b6be28 100644 --- a/benchmark/COMPARISON.md +++ b/benchmark/COMPARISON.md @@ -11,3 +11,4 @@ |AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both | |AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system | |AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both | +|Ampere Altra Q80-30 | 0 | 80 | 54477 | 1604482 | system | diff --git a/docs/env_variables.md b/docs/env_variables.md index 8c2d5848..3db46b36 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -610,7 +610,7 @@ checks or alter some of the more exotic semantics of the tool: see [rpc_statsd.md](rpc_statsd.md). - `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes) - between fuzzing instances synchronization. Default sync time is 30 minutes, + between fuzzing instances synchronization. Default sync time is 20 minutes, note that time is halved for -M main nodes. - `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 82437807..79d0500d 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -632,7 +632,7 @@ crash or timeout during startup. Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases from other fuzzers in the campaign first. But note that can slow down the start -of the first fuzz by quite a lot of you have many fuzzers and/or many seeds. +of the first fuzz by quite a lot if you have many fuzzers and/or many seeds. If you have a large corpus, a corpus from a previous run or are fuzzing in a CI, then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`. diff --git a/include/forkserver.h b/include/forkserver.h index 6c649528..db1832c4 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -89,11 +89,14 @@ typedef struct { bool (*nyx_config_set_aux_buffer_size)(void *config, uint32_t aux_buffer_size); + uint64_t (*nyx_get_target_hash64)(void *config); + + void (*nyx_config_free)(void *config); + } nyx_plugin_handler_t; /* Imports helper functions to enable Nyx mode (Linux only )*/ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary); - #endif typedef struct afl_forkserver { @@ -204,6 +207,7 @@ typedef struct afl_forkserver { bool nyx_use_tmp_workdir; char *nyx_tmp_workdir_path; s32 nyx_log_fd; + u64 nyx_target_hash64; #endif #ifdef __AFL_CODE_COVERAGE @@ -241,6 +245,11 @@ void afl_fsrv_killall(void); void afl_fsrv_deinit(afl_forkserver_t *fsrv); void afl_fsrv_kill(afl_forkserver_t *fsrv); +#ifdef __linux__ +void nyx_load_target_hash(afl_forkserver_t *fsrv); +#endif + + #ifdef __APPLE__ #define MSG_FORK_ON_APPLE \ " - On MacOS X, the semantics of fork() syscalls are non-standard and " \ diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION index 9aae19be..5f7c9a5b 100644 --- a/nyx_mode/LIBNYX_VERSION +++ b/nyx_mode/LIBNYX_VERSION @@ -1 +1 @@ -6833d23 +ea6ceb9 \ No newline at end of file diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION index cc20a3b6..0b9e5d4e 100644 --- a/nyx_mode/PACKER_VERSION +++ b/nyx_mode/PACKER_VERSION @@ -1 +1 @@ -bcf3e24 +6067e5c diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx -Subproject 6833d236dfe785a8a23d8c8d79e74c99fa63500 +Subproject ea6ceb994ab975b81aea0daaf64b92a3066c1e8 diff --git a/nyx_mode/packer b/nyx_mode/packer -Subproject bcf3e248b660764f48af54232a3388389a2dfc2 +Subproject 6067e5c0ffb3e9aec35aa3aef29b3e390dd313b diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 9a62db20..ecff1e72 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -847b43acb1 +d40bcd8965 diff --git a/qemu_mode/README.persistent.md b/qemu_mode/README.persistent.md index ef8fb71b..e89823b5 100644 --- a/qemu_mode/README.persistent.md +++ b/qemu_mode/README.persistent.md @@ -99,10 +99,7 @@ be lost at the second execution of the loop. ### 2.5) Resetting the memory state -This option restores the memory state using the AFL++ Snapshot LKM if loaded. -Otherwise, all the writeable pages are restored. - -To enable this option, set `AFL_QEMU_PERSISTENT_MEM=1`. +(obsolete chapter) ### 2.6) Reset on exit() @@ -113,15 +110,7 @@ The environment variable is `AFL_QEMU_PERSISTENT_EXITS`. ### 2.7) Snapshot -`AFL_QEMU_SNAPSHOT=address` is just a "syntactical sugar" environment variable -that is equivalent to the following set of variables: - -``` -AFL_QEMU_PERSISTENT_ADDR=address -AFL_QEMU_PERSISTENT_GPR=1 -AFL_QEMU_PERSISTENT_MEM=1 -AFL_QEMU_PERSISTENT_EXITS=1 -``` +obsolete ## 3) Optional parameters diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl -Subproject 847b43acb11530e775013dc24b54c6e27406179 +Subproject d40bcd896521e5a1f0c9939d020fe6291dbdd37 diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c7c493cf..ae3c7ccc 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -136,6 +136,12 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { dlsym(handle, "nyx_config_set_aux_buffer_size"); if (plugin->nyx_config_set_aux_buffer_size == NULL) { goto fail; } + plugin->nyx_get_target_hash64 = dlsym(handle, "nyx_get_target_hash64"); + if (plugin->nyx_get_target_hash64 == NULL) { goto fail; } + + plugin->nyx_config_free = dlsym(handle, "nyx_config_free"); + if (plugin->nyx_get_target_hash64 == NULL) { goto fail; } + OKF("libnyx plugin is ready!"); return plugin; @@ -224,6 +230,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->nyx_use_tmp_workdir = false; fsrv->nyx_tmp_workdir_path = NULL; fsrv->nyx_log_fd = -1; + fsrv->nyx_target_hash64 = 0; #endif // this structure needs default so we initialize it if this was not done @@ -527,6 +534,15 @@ static void report_error_and_exit(int error) { } +#ifdef __linux__ +void nyx_load_target_hash(afl_forkserver_t *fsrv) { + void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path); + fsrv->nyx_target_hash64 = fsrv->nyx_handlers->nyx_get_target_hash64(nyx_config); + fsrv->nyx_handlers->nyx_config_free(nyx_config); +} +#endif + + /* Spins up fork server. The idea is explained here: https://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d3085d42..9eaa661d 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1231,6 +1231,25 @@ void perform_dry_run(afl_state_t *afl) { ck_write(fd, use_mem, read_len, crash_fn); close(fd); +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + u8 crash_log_fn[PATH_MAX]; + + snprintf(crash_log_fn, PATH_MAX, "%s.log", crash_fn); + fd = open(crash_log_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_log_fn); } + + u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, + afl->fsrv.nyx_aux_string_len); + + ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, crash_log_fn); + close(fd); + + } +#endif + afl->last_crash_time = get_cur_time(); afl->last_crash_execs = afl->fsrv.total_execs; @@ -2443,21 +2462,20 @@ void check_crash_handling(void) { if (read(fd, &fchar, 1) == 1 && fchar == '|') { - SAYF( - "\n" cLRD "[-] " cRST - "Your system is configured to send core dump notifications to an\n" - " external utility. This will cause issues: there will be an " - "extended delay\n" - " between stumbling upon a crash and having this information " - "relayed to the\n" - " fuzzer via the standard waitpid() API.\n" - " If you're just experimenting, set " - "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n" + SAYF("\n" cLRD "[-] " cRST + "Your system is configured to send core dump notifications to an\n" + " external utility. This will cause issues: there will be an " + "extended delay\n" + " between stumbling upon a crash and having this information " + "relayed to the\n" + " fuzzer via the standard waitpid() API.\n" + " If you're just experimenting, set " + "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n" - " To avoid having crashes misinterpreted as timeouts, please \n" - " temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" + " To avoid having crashes misinterpreted as timeouts, please \n" + " temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" - " echo core | sudo tee /proc/sys/kernel/core_pattern\n"); + " echo core | sudo tee /proc/sys/kernel/core_pattern\n"); if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) { @@ -2866,6 +2884,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { afl->fsrv.target_path = ck_strdup(fname); + #ifdef __linux__ if (afl->fsrv.nyx_mode) { @@ -2886,8 +2905,8 @@ void check_binary(afl_state_t *afl, u8 *fname) { afl->fsrv.target_path); } - #endif + if (stat(afl->fsrv.target_path, &st) || !S_ISREG(st.st_mode) || !(st.st_mode & 0111) || (f_len = st.st_size) < 4) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 9f5f59c0..b1a84cb6 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -80,7 +80,18 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); FILE *f2 = create_ffile(fn2); + +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + nyx_load_target_hash(&afl->fsrv); + fprintf(f2, "%llx\n", afl->fsrv.nyx_target_hash64); + } + else { + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); + } +#else fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); +#endif fclose(f2); snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 726a2260..a2fd4b76 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1505,7 +1505,7 @@ int main(int argc, char **argv_orig, char **envp) { #ifdef __linux__ if (afl->fsrv.nyx_mode) { - OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)"); + OKF("AFL++ Nyx mode is enabled (developed and maintained by Sergej Schumilo)"); OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz"); } @@ -2225,9 +2225,24 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { +#ifdef __linux__ + u64 target_hash = 0; + if (afl->fsrv.nyx_mode) { + nyx_load_target_hash(&afl->fsrv); + target_hash = afl->fsrv.nyx_target_hash64; + } + else { + target_hash = get_binary_hash(afl->fsrv.target_path); + } +#else u64 target_hash = get_binary_hash(afl->fsrv.target_path); +#endif - if (!target_hash || prev_target_hash != target_hash) { + if ((!target_hash || prev_target_hash != target_hash) +#ifdef __linux__ + || (afl->fsrv.nyx_mode && target_hash == 0) +#endif + ) { ACTF("Target binary is different, cannot perform FAST RESUME!"); diff --git a/test/test-llvm.sh b/test/test-llvm.sh index 4dd35e6e..8236d138 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -269,9 +269,9 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { { mkdir -p in echo 00000000000000000000000000000000 > in/in - AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1 + AFL_BENCH_UNTIL_CRASH=1 AFL_NO_CRASH_README=1 AFL_SHA1_FILENAMES=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1 } >>errors 2>&1 - test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && { + test -n "$( ls out/default/crashes/* out/default/hangs/* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog" } || { echo CUT------------------------------------------------------------------CUT @@ -280,6 +280,10 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode cmplog" CODE=1 } + test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && { + $ECHO "$RED[!] filenames are not SHA1" + CODE=1 + } || true } || { $ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present" INCOMPLETE=1 |