diff options
Diffstat (limited to 'utils')
26 files changed, 506 insertions, 22 deletions
diff --git a/utils/afl_network_proxy/GNUmakefile b/utils/afl_network_proxy/GNUmakefile index 7c8c22ff..47d9a7d3 100644 --- a/utils/afl_network_proxy/GNUmakefile +++ b/utils/afl_network_proxy/GNUmakefile @@ -10,6 +10,7 @@ PROGRAMS = afl-network-client afl-network-server HASH=\# CFLAGS += -Wno-pointer-sign +LDFLAGS += -ldl ifdef STATIC CFLAGS += -static diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index 0416f0f9..1f04dd87 100644 --- a/utils/afl_network_proxy/afl-network-client.c +++ b/utils/afl_network_proxy/afl-network-client.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 04309ada..c4a700f4 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -173,6 +173,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } out_file = alloc_printf("%s/.afl-input-temp-%u", use_dir, getpid()); + fsrv->out_file = out_file; } diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index 531a97a2..6cf47636 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/Makefile b/utils/afl_untracer/Makefile index 14a09b41..264aebe5 100644 --- a/utils/afl_untracer/Makefile +++ b/utils/afl_untracer/Makefile @@ -3,11 +3,16 @@ ifdef DEBUG else OPT=-O3 endif +SYS = $(shell uname -s) +DL = +ifeq "$(SYS)" "Linux" + DL = -ldl +endif all: afl-untracer libtestinstr.so afl-untracer: afl-untracer.c - $(CC) $(OPT) -I../../include -g -o afl-untracer afl-untracer.c -ldl + $(CC) $(OPT) -I../../include -g -o afl-untracer afl-untracer.c $(DL) libtestinstr.so: libtestinstr.c $(CC) -g -O0 -fPIC -o libtestinstr.so -shared libtestinstr.c diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index a18e314e..e6a74518 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -53,7 +53,9 @@ #include <pthread.h> #include <sys/mman.h> -#include <sys/shm.h> +#if !defined(__HAIKU__) + #include <sys/shm.h> +#endif #include <sys/wait.h> #include <sys/types.h> @@ -66,6 +68,9 @@ #include <sys/sysctl.h> #include <sys/user.h> #include <sys/procctl.h> +#elif defined(__HAIKU__) + #include <kernel/OS.h> + #include <kernel/image.h> #else #error "Unsupported platform" #endif @@ -232,6 +237,30 @@ void read_library_information(void) { } +#elif defined(__HAIKU__) + image_info ii; + int32 c = 0; + + while (get_next_image_info(0, &c, &ii) == B_OK) { + + liblist[liblist_cnt].name = (u8 *)strdup(ii.name); + liblist[liblist_cnt].addr_start = (u64)ii.text; + liblist[liblist_cnt].addr_end = (u64)((char *)ii.text + ii.text_size); + + if (debug) { + + fprintf(stderr, "%s:%lx (%lx-%lx)\n", liblist[liblist_cnt].name, + (unsigned long)(liblist[liblist_cnt].addr_end - + liblist[liblist_cnt].addr_start), + (unsigned long)liblist[liblist_cnt].addr_start, + (unsigned long)(liblist[liblist_cnt].addr_end - 1)); + + } + + liblist_cnt++; + + } + #endif } @@ -288,7 +317,7 @@ library_list_t *find_library(char *name) { #pragma GCC optimize("O0") void breakpoint(void) { - if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n"); + if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n"); } @@ -655,6 +684,9 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { #elif defined(__FreeBSD__) && defined(__LP64__) ctx->uc_mcontext.mc_rip -= 1; addr = ctx->uc_mcontext.mc_rip; +#elif defined(__HAIKU__) && defined(__x86_64__) + ctx->uc_mcontext.rip -= 1; + addr = ctx->uc_mcontext.rip; #else #error "Unsupported platform" #endif diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index b7afc325..0a98778a 100644 --- a/utils/afl_untracer/libtestinstr.c +++ b/utils/afl_untracer/libtestinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 4e8f466d..9ffb2383 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -279,7 +279,9 @@ __attribute__((weak)) int main(int argc, char **argv) { */ - if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0 || + strcmp(argv[1], "--help") == 0) { + printf( "============================== INFO ================================\n" "This binary is built for afl++.\n" @@ -290,12 +292,21 @@ __attribute__((weak)) int main(int argc, char **argv) { "afl-fuzz will run N iterations before re-spawning the process " "(default: " "INT_MAX)\n" + "You can also use AFL_FUZZER_LOOPCOUNT to set N\n" "For stdin input processing, pass '-' as single command line option.\n" "For file input processing, pass '@@' as single command line option.\n" "To use with afl-cmin or afl-cmin.bash pass '-' as single command line " "option\n" "===================================================================\n", argv[0], argv[0]); + if (argc == 2 && + (strncmp(argv[1], "-h", 2) == 0 || strcmp(argv[1], "--help") == 0)) { + + exit(0); + + } + + } return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput); @@ -369,6 +380,12 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( } + if (getenv("AFL_FUZZER_LOOPCOUNT")) { + + N = atoi(getenv("AFL_FUZZER_LOOPCOUNT")); + + } + assert(N > 0); __afl_manual_init(); diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 6786467a..ba977e5f 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -2,7 +2,7 @@ # american fuzzy lop++ - argvfuzz # -------------------------------- # -# Copyright 2019-2023 Kjell Braden <afflux@pentabarf.de> +# Copyright 2019-2024 Kjell Braden <afflux@pentabarf.de> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c index 41eead0c..47383138 100644 --- a/utils/argv_fuzzing/argvfuzz.c +++ b/utils/argv_fuzzing/argvfuzz.c @@ -2,7 +2,7 @@ american fuzzy lop++ - LD_PRELOAD for fuzzing argv in binaries ------------------------------------------------------------ - Copyright 2019-2023 Kjell Braden <afflux@pentabarf.de> + Copyright 2019-2024 Kjell Braden <afflux@pentabarf.de> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/bench/Makefile b/utils/bench/Makefile new file mode 100644 index 00000000..e7d2f3a1 --- /dev/null +++ b/utils/bench/Makefile @@ -0,0 +1,8 @@ +all: hash + +hash: hash.c + gcc -O3 -mavx2 -march=native -I../../include -o hash hash.c + +clean: + rm -f hash + diff --git a/utils/bench/README.md b/utils/bench/README.md new file mode 100644 index 00000000..772c117b --- /dev/null +++ b/utils/bench/README.md @@ -0,0 +1,2 @@ +# Internal AFL++ benchmarking + diff --git a/utils/bench/hash.c b/utils/bench/hash.c new file mode 100644 index 00000000..d4be0ab4 --- /dev/null +++ b/utils/bench/hash.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdint.h> +#include <time.h> + +#define T1HA0_AESNI_AVAILABLE 1 +#define T1HA_USE_FAST_ONESHOT_READ 1 +#define T1HA_USE_INDIRECT_FUNCTIONS 1 +#define T1HA_IA32AES_NAME t1ha0_ia32aes +#include "t1ha0_ia32aes_b.h" + +#define XXH_INLINE_ALL +#include "xxhash.h" +#undef XXH_INLINE_ALL + +int main() { + + char *data = malloc(4097); + struct timespec start, end; + long long duration; + int i; + uint64_t res; + + clock_gettime(CLOCK_MONOTONIC, &start); + for (i = 0; i < 100000000; ++i) { + + res = XXH3_64bits(data, 4097); + memcpy(data + 16, (char *)&res, 8); + + } + + clock_gettime(CLOCK_MONOTONIC, &end); + duration = (end.tv_sec - start.tv_sec) * 1000000000LL + + (end.tv_nsec - start.tv_nsec); + printf("xxh3 duration: %lld ns\n", duration); + + memset(data, 0, 4097); + clock_gettime(CLOCK_MONOTONIC, &start); + for (i = 0; i < 100000000; ++i) { + + res = t1ha0_ia32aes(data, 4097); + memcpy(data + 16, (char *)&res, 8); + + } + + clock_gettime(CLOCK_MONOTONIC, &end); + duration = (end.tv_sec - start.tv_sec) * 1000000000LL + + (end.tv_nsec - start.tv_nsec); + printf("t1ha0_ia32aes duration: %lld ns\n", duration); + + return 0; + +} + diff --git a/utils/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index b22816f1..861b65c8 100755 --- a/utils/distributed_fuzzing/sync_script.sh +++ b/utils/distributed_fuzzing/sync_script.sh @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2014 Google Inc. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/dynamic_covfilter/README.md b/utils/dynamic_covfilter/README.md new file mode 100644 index 00000000..381e0855 --- /dev/null +++ b/utils/dynamic_covfilter/README.md @@ -0,0 +1,60 @@ +# Dynamic Instrumentation Filter + +Sometimes it can be beneficial to limit the instrumentation feedback to +specific code locations. It is possible to do so at compile-time by simply +not instrumenting any undesired locations. However, there are situations +where doing this dynamically without requiring a new build can be beneficial. +Especially when dealing with larger builds, it is much more convenient to +select the target code locations at runtime instead of doing so at build time. + +There are two ways of doing this in AFL++. Both approaches require a build of +AFL++ with `CODE_COVERAGE=1`, so make sure to build AFL++ first by invoking + +`CODE_COVERAGE=1 make` + +Once you have built AFL++, you can choose out of two approaches: + +## Simple Selection with `AFL_PC_FILTER` + +This approach requires a build with `AFL_INSTRUMENTATION=llvmnative` or +`llvmcodecov` as well as an AddressSanitizer build with debug information. + +By setting the environment variable `AFL_PC_FILTER` to a string, the runtime +symbolizer is enabled in the AFL++ runtime. At startup, the runtime will call +the `__sanitizer_symbolize_pc` API to resolve every PC in every loaded module. +The runtime then matches the result using `strstr` and disables the PC guard +if the symbolized PC does not contain the specified string. + +This approach has the benefit of being very easy to use. The downside is that +it causes significant startup delays with large binaries and that it requires +an AddressSanitizer build. + +This method has no additional runtime overhead after startup. + +## Selection using pre-symbolized data file with `AFL_PC_FILTER_FILE` + +To avoid large startup time delays, a specific module can be pre-symbolized +using the `make_symbol_list.py` script. This script outputs a sorted list of +functions with their respective relative offsets and lengths in the target +binary: + +`python3 make_symbol_list.py libxul.so > libxul.symbols.txt` + +The resulting list can be filtered, e.g. using grep: + +`grep -i "webgl" libxul.symbols.txt > libxul.webgl.symbols.txt` + +Finally, you can run with `AFL_PC_FILTER_FILE=libxul.webgl.symbols.txt` to +restrict instrumentation feedback to the given locations. This approach only +has a minimal startup time delay due to the implementation only using binary +search on the given file per PC rather than reading debug information for every +PC. It also works well with Nyx, where symbolizing is usually disabled for the +target process to avoid delays with frequent crashes. + +Similar to the previous method, This approach requires a build with +`AFL_INSTRUMENTATION=llvmnative` or `llvmcodecov` as well debug information. +However, it does not require the ASan runtime as it doesn't do the symbolizing +in process. Due to the way it maps PCs to symbols, it is less accurate when it +comes to includes and inlines (it assumes all PCs within a function belong to +that function and originate from the same file). For most purposes, this should +be a reasonable simplification to quickly process even the largest binaries. diff --git a/utils/dynamic_covfilter/make_symbol_list.py b/utils/dynamic_covfilter/make_symbol_list.py new file mode 100644 index 00000000..d1dd6ab3 --- /dev/null +++ b/utils/dynamic_covfilter/make_symbol_list.py @@ -0,0 +1,73 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Written by Christian Holler <decoder at mozilla dot com> + +import json +import os +import sys +import subprocess + +if len(sys.argv) != 2: + print("Usage: %s binfile" % os.path.basename(sys.argv[0])) + sys.exit(1) + +binfile = sys.argv[1] + +addr2len = {} +addrs = [] + +output = subprocess.check_output(["objdump", "-t", binfile]).decode("utf-8") +for line in output.splitlines(): + line = line.replace("\t", " ") + components = [x for x in line.split(" ") if x] + if not components: + continue + try: + start_addr = int(components[0], 16) + except ValueError: + continue + + # Length has variable position in objdump output + length = None + for comp in components[1:]: + if len(comp) == 16: + try: + length = int(comp, 16) + break + except: + continue + + if length is None: + print("ERROR: Couldn't determine function section length: %s" % line) + + func = components[-1] + + addrs.append(start_addr) + addr2len[str(hex(start_addr))] = str(length) + +# The search implementation in the AFL runtime expects everything sorted. +addrs.sort() +addrs = [str(hex(addr)) for addr in addrs] + +# We symbolize in one go to speed things up with large binaries. +output = subprocess.check_output([ + "llvm-addr2line", + "--output-style=JSON", + "-f", "-C", "-a", "-e", + binfile], + input="\n".join(addrs).encode("utf-8")).decode("utf-8") + +output = output.strip().splitlines() +for line in output: + output = json.loads(line) + if "Symbol" in output and output["Address"] in addr2len: + final_output = [ + output["Address"], + addr2len[output["Address"]], + os.path.basename(output["ModuleName"]), + output["Symbol"][0]["FileName"], + output["Symbol"][0]["FunctionName"] + ] + print("\t".join(final_output)) diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index 1cd7abc6..b80be1a1 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 299056ab..cc499150 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ #elif defined __HAIKU__ #include <kernel/image.h> #elif defined __sun - /* For map addresses the old struct is enough */ +/* For map addresses the old struct is enough */ #include <sys/procfs.h> #include <limits.h> #endif @@ -81,7 +81,11 @@ void *(*__libc_memmem)(const void *haystack, size_t haystack_len, #define MAX_MAPPINGS 1024 -static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS]; +static struct mapping { + + void *st, *en; + +} __tokencap_ro[MAX_MAPPINGS]; static u32 __tokencap_ro_cnt; static u8 __tokencap_ro_loaded; @@ -164,7 +168,7 @@ static void __tokencap_load_mappings(void) { #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ #if defined __FreeBSD__ - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __OpenBSD__ int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __NetBSD__ @@ -205,7 +209,7 @@ static void __tokencap_load_mappings(void) { #if defined __FreeBSD__ || defined __NetBSD__ #if defined __FreeBSD__ - size_t size = region->kve_structsize; + size_t size = region->kve_structsize; if (size == 0) break; #elif defined __NetBSD__ diff --git a/utils/persistent_mode/Makefile b/utils/persistent_mode/Makefile index e348c46c..498aa3f8 100644 --- a/utils/persistent_mode/Makefile +++ b/utils/persistent_mode/Makefile @@ -7,4 +7,4 @@ document: AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c clean: - rm -f persistent_demo persistent_demo_new test-instr + rm -f persistent_demo persistent_demo_new persistent_demo_new_compat test-instr diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 4ead6577..72e26e93 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/qbdi_mode/build.sh b/utils/qbdi_mode/build.sh index 29fe0ee4..a92d81bd 100755 --- a/utils/qbdi_mode/build.sh +++ b/utils/qbdi_mode/build.sh @@ -52,6 +52,6 @@ ${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g echo "[+] Building afl-fuzz for Android" # build afl-fuzz cd ../.. -${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz*.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c src/afl-performance.c -o utils/qbdi_mode/afl-fuzz -ldl -lm -w +${compiler_prefix}${CC} -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz*.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c src/afl-performance.c -o utils/qbdi_mode/afl-fuzz -ldl -lm -w echo "[+] All done. Enjoy!" diff --git a/utils/replay_record/Makefile b/utils/replay_record/Makefile new file mode 100644 index 00000000..0d1cba92 --- /dev/null +++ b/utils/replay_record/Makefile @@ -0,0 +1,8 @@ +all: + test `grep '//[\s\t ]*#define[\s\t ]*AFL_PERSISTENT_RECORD' ../../include/config.h | wc -l` -eq 0 || (echo "AFL_PERSISTENT_RECORD must be enabled in config.h"; exit 1) + ../../afl-clang-fast -o persistent_demo_replay persistent_demo_replay.c + ${CC} -I ../../include -o persistent_demo_replay_compat persistent_demo_replay.c + ${CC} -g -I ../../include -DAFL_PERSISTENT_REPLAY_ARGPARSE -o persistent_demo_replay_argparse persistent_demo_replay.c + +clean: + rm -f persistent_demo_replay persistent_demo_replay_argparse persistent_demo_replay_compat diff --git a/utils/replay_record/README.md b/utils/replay_record/README.md new file mode 100644 index 00000000..6d72ca97 --- /dev/null +++ b/utils/replay_record/README.md @@ -0,0 +1,10 @@ +# AFL++ persistent record replay + +This persistent record replay demo showcases the `AFL_PERSISTENT_RECORD` replay functionality. + +The [Makefile](Makefile) will produce three binaries: + + persistent_demo_replay: uses afl-cc and makes use of the replay functionality included in the compiler runtime library + + persistent_demo_replay_compat: uses the [afl-record-compat.h](../../include/afl-record-compat.h) compatibility header to compile the same example without `afl-cc` + + persistent_demo_replay_argparse: makes use of `afl-record-compat.h`, and the Makefile defines `AFL_PERSISTENT_REPLAY_ARGPARSE` to test the replay functionality but parses the input file via a command-line argument (`@@`-style harness). + +For more information see [README.persistent_mode.md](../../instrumentation/README.persistent_mode.md). \ No newline at end of file diff --git a/utils/replay_record/persistent_demo_replay.c b/utils/replay_record/persistent_demo_replay.c new file mode 100644 index 00000000..6f6648f1 --- /dev/null +++ b/utils/replay_record/persistent_demo_replay.c @@ -0,0 +1,148 @@ +/* + american fuzzy lop++ - persistent mode example + -------------------------------------------- + + Originally written by Michal Zalewski + + Copyright 2015 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This file demonstrates the high-performance "persistent mode" that may be + suitable for fuzzing certain fast and well-behaved libraries, provided that + they are stateless or that their internal state can be easily reset + across runs. + + To make this work, the library and this shim need to be compiled in LLVM + mode using afl-clang-fast (other compiler wrappers will *not* work). + + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <limits.h> + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + #include <sys/stat.h> + #include <fcntl.h> +#endif + +/* this lets the source compile without afl-clang-fast/lto */ +#ifndef __AFL_FUZZ_TESTCASE_LEN + #include "afl-record-compat.h" +#endif + +__AFL_FUZZ_INIT(); + +/* Main entry point. */ + +/* To ensure checks are not optimized out it is recommended to disable + code optimization for the fuzzer harness main() */ +#pragma clang optimize off +#pragma GCC optimize("O0") + +int main(int argc, char **argv) { + + ssize_t len; /* how much input did we read? */ + unsigned char *buf; /* test case buffer pointer */ + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + int fd; + + if (argc < 2) { printf("Need an input file!"); } +#endif + + /* The number passed to __AFL_LOOP() controls the maximum number of + iterations before the loop exits and the program is allowed to + terminate normally. This limits the impact of accidental memory leaks + and similar hiccups. */ + + __AFL_INIT(); + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + buf = malloc(1000); +#else + buf = __AFL_FUZZ_TESTCASE_BUF; // this must be assigned before __AFL_LOOP! +#endif + + while (__AFL_LOOP(UINT_MAX)) { // increase if you have good stability + +#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE + fd = open(argv[1], O_RDONLY); + len = read(fd, buf, 1000); + close(fd); +#else + len = __AFL_FUZZ_TESTCASE_LEN; // do not use the macro directly in a call! +#endif + + // fprintf(stderr, "input: %zd \"%s\"\n", len, buf); + + /* do we have enough data? */ + if (len < 8) continue; + + if (strcmp((char *)buf, "thisisateststring") == 0) printf("teststring\n"); + + if (buf[0] == 'f') { + + printf("one\n"); + if (buf[1] == 'o') { + + printf("two\n"); + if (buf[2] == 'o') { + + printf("three\n"); + if (buf[3] == '!') { + + printf("four\n"); + if (buf[4] == '!') { + + printf("five\n"); + if (buf[5] == '!') { + + printf("six\n"); + abort(); + + } else { + + if (buf[5] == 'O') { + + // hang + while (1) { + + continue; + + }; + + } + + } + + } + + } + + } + + } + + } + + /*** END PLACEHOLDER CODE ***/ + + } + + /* Once the loop is exited, terminate normally - AFL will restart the process + when this happens, with a clean slate when it comes to allocated memory, + leftover file descriptors, etc. */ + + return 0; + +} + diff --git a/utils/socket_fuzzing/socketfuzz.c b/utils/socket_fuzzing/socketfuzz.c index 3ec8383b..7497519e 100644 --- a/utils/socket_fuzzing/socketfuzz.c +++ b/utils/socket_fuzzing/socketfuzz.c @@ -23,7 +23,8 @@ #include <errno.h> #include <stdio.h> #include <poll.h> -//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: " +// #include "logging.h" // switched from preeny_info() to fprintf(stderr, "Info: +// " // // originals diff --git a/utils/target_intelligence/README.md b/utils/target_intelligence/README.md new file mode 100644 index 00000000..086c9e20 --- /dev/null +++ b/utils/target_intelligence/README.md @@ -0,0 +1,61 @@ +# Target Intelligence + +These are some ideas you can do so that your target that you are fuzzing can +give helpful feedback to AFL++. + +## Add to the AFL++ dictionary from your target + +For this you target must be compiled for CMPLOG (`AFL_LLVM_CMPLOG=1`). + +Add in your source code: + +``` +__attribute__((weak)) void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len); +__attribute__((weak)) void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr); +__attribute__((weak)) void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr); +__attribute__((weak)) void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr); +__attribute__((weak)) void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr); + +int in_your_function(...) { + + // to add two strings to the AFL++ dictionary: + if (__cmplog_rtn_hook_strn) + __cmplog_rtn_hook_strn(string1, length_of_string1, string2, length_of_string2); + + // to add two 32 bit integers to the AFL++ dictionary: + if (__cmplog_ins_hook4) + __cmplog_ins_hook4(first_32_bit_var, second_32_bit_var, 0); + +} +``` + +Note that this only makes sense if these values are in-depth processed in the +target in a way that AFL++ CMPLOG cannot uncover these, e.g. if these values +are transformed by a matrix computation. + +Fixed values are always better to give to afl-fuzz via a `-x dictionary`. + +## Add inputs to AFL++ dictionary from your target + +If for whatever reason you want your target to propose new inputs to AFL++, +then this is actually very easy. +The environment variable `AFL_CUSTOM_INFO_OUT` contains the output directory +of this run - including the fuzzer instance name (e.g. `default`), so if you +run `afl-fuzz -o out -S foobar`, the value would be `out/foobar`). + +To show afl-fuzz an input it should consider just do the following: + +1. create the directory `$AFL_CUSTOM_INFO_OUT/../target/queue` +2. create any new inputs you want afl-fuzz to notice in that directory with the + following naming convention: `id:NUMBER-OF-LENGTH-SIX-WITH-LEADING-ZEROES,whatever` + where that number has to be increasing. + e.g.: +``` + id:000000,first_file + id:000001,second_file + id:000002,third_file + etc. +``` + +Note that this will not work in nyx_mode because afl-fuzz cannot see inside the +virtual machine. |