diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/afl_network_proxy/afl-network-client.c | 2 | ||||
-rw-r--r-- | utils/afl_network_proxy/afl-network-server.c | 19 | ||||
-rw-r--r-- | utils/afl_proxy/afl-proxy.c | 2 | ||||
-rw-r--r-- | utils/afl_untracer/afl-untracer.c | 25 | ||||
-rw-r--r-- | utils/afl_untracer/libtestinstr.c | 2 | ||||
-rw-r--r-- | utils/aflpp_driver/GNUmakefile | 23 | ||||
-rw-r--r-- | utils/aflpp_driver/aflpp_driver.c | 85 | ||||
-rw-r--r-- | utils/aflpp_driver/aflpp_driver_test.c | 17 | ||||
-rw-r--r-- | utils/argv_fuzzing/Makefile | 17 | ||||
-rw-r--r-- | utils/argv_fuzzing/README.md | 41 | ||||
-rw-r--r-- | utils/argv_fuzzing/argv-fuzz-inl.h | 53 | ||||
-rw-r--r-- | utils/argv_fuzzing/argv_fuzz_demo.c | 28 | ||||
-rw-r--r-- | utils/argv_fuzzing/argv_fuzz_persistent_demo.c | 59 | ||||
-rw-r--r-- | utils/argv_fuzzing/argvfuzz.c | 2 | ||||
-rwxr-xr-x | utils/distributed_fuzzing/sync_script.sh | 2 | ||||
-rw-r--r-- | utils/libdislocator/libdislocator.so.c | 2 | ||||
-rw-r--r-- | utils/libtokencap/README.md | 2 | ||||
-rw-r--r-- | utils/libtokencap/libtokencap.so.c | 2 | ||||
-rw-r--r-- | utils/persistent_mode/test-instr.c | 2 |
19 files changed, 304 insertions, 81 deletions
diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index 89ca6c4e..0416f0f9 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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 8f0e9df9..04309ada 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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. @@ -194,7 +194,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - if (!strstr(x, "symbolize=0")) { + if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); @@ -213,7 +213,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - if (!strstr(x, "symbolize=0")) { + if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) { FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); @@ -221,18 +221,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - setenv("ASAN_OPTIONS", - "abort_on_error=1:" - "detect_leaks=0:" - "symbolize=0:" - "allocator_may_return_null=1", - 0); - - setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" - "symbolize=0:" - "abort_on_error=1:" - "allocator_may_return_null=1:" - "msan_track_origins=0", 0); + set_sanitizer_defaults(); if (get_afl_env("AFL_PRELOAD")) { diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index afd0e5d2..531a97a2 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index ed7047a4..a18e314e 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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. @@ -156,7 +156,7 @@ void read_library_information(void) { *e = 0; if (n[strlen(n) - 1] == '\n') n[strlen(n) - 1] = 0; - liblist[liblist_cnt].name = strdup(n); + liblist[liblist_cnt].name = (u8 *)strdup((char *)n); liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); if (debug) @@ -210,16 +210,17 @@ void read_library_information(void) { !(region->kve_protection & KVME_PROT_EXEC)) { liblist[liblist_cnt].name = - region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; + region->kve_path[0] != '\0' ? (u8 *)strdup(region->kve_path) : 0; liblist[liblist_cnt].addr_start = region->kve_start; liblist[liblist_cnt].addr_end = region->kve_end; if (debug) { - fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_end - 1); + 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)); } @@ -488,6 +489,12 @@ void setup_trap_instrumentation(void) { uint32_t bitmap_index = 0; #endif +#if defined(__FreeBSD__) && __FreeBSD_version >= 1301000 + // We try to allow W/X pages despite kern.elf32/64.allow_wx system settings + int allow_wx = PROC_WX_MAPPINGS_PERMIT; + (void)procctl(P_PID, 0, PROC_WXMAP_CTL, &allow_wx); +#endif + while ((nread = getline(&line, &len, patches)) != -1) { char *end = line + len; @@ -699,7 +706,7 @@ int main(int argc, char *argv[]) { if (argc > 1) { use_stdin = 0; - inputfile = argv[1]; + inputfile = (u8 *)argv[1]; } @@ -732,7 +739,7 @@ int main(int argc, char *argv[]) { if (pid) { u32 status; - if (waitpid(pid, &status, 0) < 0) exit(1); + if (waitpid(pid, (int *)&status, 0) < 0) exit(1); /* report the test case is done and wait for the next */ __afl_end_testcase(status); diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index a3f5acc8..b7afc325 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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/GNUmakefile b/utils/aflpp_driver/GNUmakefile index 234a1c31..b973f96a 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -8,9 +8,14 @@ ifeq "$(shell uname -s)" "Darwin" LDFLAGS += $(SDK_LD) endif +ifeq "" "$(LLVM_CONFIG)" + LLVM_CONFIG := llvm-config +endif LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) ifneq "" "$(LLVM_BINDIR)" - LLVM_BINDIR := $(LLVM_BINDIR)/ + ifeq "$(shell test -x $(LLVM_BINDIR)/clang && echo 1)" "1" + CC := $(LLVM_BINDIR)/clang + endif endif CFLAGS := -O3 -funroll-loops -g -fPIC @@ -18,31 +23,31 @@ CFLAGS := -O3 -funroll-loops -g -fPIC all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c - -$(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c + -$(CC) -I. -I../../include $(CFLAGS) -c aflpp_driver.c libAFLDriver.a: aflpp_driver.o @ar rc libAFLDriver.a aflpp_driver.o @cp -vf libAFLDriver.a ../../ debug: - $(LLVM_BINDIR)clang -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c - $(LLVM_BINDIR)clang -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c - #$(LLVM_BINDIR)clang -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c - #$(LLVM_BINDIR)clang -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + $(CC) -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c + $(CC) -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c + #$(CC) -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c + #$(CC) -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c ar rc libAFLDriver.a afl-performance.o aflpp_driver.o aflpp_qemu_driver.o: aflpp_qemu_driver.c - -$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c + -$(CC) $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c libAFLQemuDriver.a: aflpp_qemu_driver.o @-ar rc libAFLQemuDriver.a aflpp_qemu_driver.o @-cp -vf libAFLQemuDriver.a ../../ aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o - @-test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." + @-test -e aflpp_qemu_driver_hook.o && $(CC) $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." aflpp_qemu_driver_hook.o: aflpp_qemu_driver_hook.c - @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." + @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(CC) $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." test: debug #clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 03376b6a..4e8f466d 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -1,12 +1,16 @@ -//===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===// -//===----------------------------------------------------------------------===// +// +// afl_driver.cpp - a glue between AFL++ and LLVMFuzzerTestOneInput harnesses +// -/* This file allows to fuzz libFuzzer-style target functions +/* + + This file allows to fuzz libFuzzer-style target functions (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing. Usage: -################################################################################ -cat << EOF > test_fuzzer.cc + +# Example target: +$ cat << EOF > test_fuzzer.cc #include <stddef.h> #include <stdint.h> extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { @@ -20,18 +24,20 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } EOF -# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. -clang -c aflpp_driver.c -# Build afl-compiler-rt.o.c from the AFL distribution. -clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c -# Build this file, link it with afl-compiler-rt.o.o and the target code. -afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o + +# Build your target with afl-cc -fsanitize=fuzzer +$ afl-c++ -fsanitize=fuzzer -o test_fuzzer test_fuzzer.cc # Run AFL: -rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; -$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out -################################################################################ +$ mkdir -p in ; echo z > in/foo; +$ afl-fuzz -i in -o out -- ./test_fuzzer + */ +#ifdef __cplusplus +extern "C" { + +#endif + #include <assert.h> #include <errno.h> #include <stdarg.h> @@ -58,16 +64,24 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out #include "hash.h" #endif +// AFL++ shared memory fuzz cases int __afl_sharedmem_fuzzing = 1; extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; +// AFL++ coverage map +extern unsigned char *__afl_area_ptr; +extern unsigned int __afl_map_size; + // libFuzzer interface is thin, so we don't include any libFuzzer headers. -__attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t *Data, - size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -int LLVMFuzzerRunDriver(int *argc, char ***argv, - int (*callback)(const uint8_t *data, size_t size)); +/* Using the weak attributed on LLVMFuzzerTestOneInput() breaks oss-fuzz but + on the other hand this is what Google needs to make LLVMFuzzerRunDriver() + work. Choose your poison Google! */ +/*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data, + size_t Size); +__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); +__attribute__((weak)) int LLVMFuzzerRunDriver( + int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size)); // Default nop ASan hooks for manual poisoning when not linking the ASan // runtime @@ -191,7 +205,8 @@ static void maybe_close_fd_mask() { // Define LLVMFuzzerMutate to avoid link failures for targets that use it // with libFuzzer's LLVMFuzzerCustomMutator. -size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { +__attribute__((weak)) size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, + size_t MaxSize) { // assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); return 0; @@ -253,6 +268,17 @@ static int ExecuteFilesOnyByOne(int argc, char **argv, __attribute__((weak)) int main(int argc, char **argv) { + // Enable if LLVMFuzzerTestOneInput() has the weak attribute + /* + if (!LLVMFuzzerTestOneInput) { + + fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n"); + abort(); + + } + + */ + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) printf( "============================== INFO ================================\n" @@ -275,8 +301,9 @@ __attribute__((weak)) int main(int argc, char **argv) { } -int LLVMFuzzerRunDriver(int *argcp, char ***argvp, - int (*callback)(const uint8_t *data, size_t size)) { +__attribute__((weak)) int LLVMFuzzerRunDriver( + int *argcp, char ***argvp, + int (*callback)(const uint8_t *data, size_t size)) { int argc = *argcp; char **argv = *argvp; @@ -375,7 +402,13 @@ int LLVMFuzzerRunDriver(int *argcp, char ***argvp, } prev_length = length; - (void)callback(__afl_fuzz_ptr, length); + + if (unlikely(callback(__afl_fuzz_ptr, length) == -1)) { + + memset(__afl_area_ptr, 0, __afl_map_size); + __afl_area_ptr[0] = 1; + + } } @@ -395,3 +428,9 @@ int LLVMFuzzerRunDriver(int *argcp, char ***argvp, } +#ifdef __cplusplus + +} + +#endif + diff --git a/utils/aflpp_driver/aflpp_driver_test.c b/utils/aflpp_driver/aflpp_driver_test.c index 527ba57b..32119485 100644 --- a/utils/aflpp_driver/aflpp_driver_test.c +++ b/utils/aflpp_driver/aflpp_driver_test.c @@ -2,23 +2,28 @@ #include <stdlib.h> #include <stdint.h> -void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { +char *foo = NULL; - if (Size < 5) return; +int __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { + + if (Size < 5) return -1; if (Data[0] == 'F') if (Data[1] == 'A') if (Data[2] == '$') if (Data[3] == '$') - if (Data[4] == '$') abort(); + if (Data[4] == '$') *foo = 1; + + return 0; } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size) crashme(Data, Size); - - return 0; + if (Size) + return crashme(Data, Size); + else + return -1; } diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 183f6bf8..6786467a 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -2,7 +2,7 @@ # american fuzzy lop++ - argvfuzz # -------------------------------- # -# Copyright 2019-2022 Kjell Braden <afflux@pentabarf.de> +# Copyright 2019-2023 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. @@ -11,7 +11,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -.PHONY: all install clean +.PHONY: all install clean argv_fuzz_persistent_demo argv_fuzz_demo demo PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin @@ -41,7 +41,7 @@ __M32FLAG=$(_M32FLAG:00=-mbe32) ___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32) M32FLAG=$(___M32FLAG) -all: argvfuzz32.so argvfuzz64.so +all: argvfuzz32.so argvfuzz64.so demo argvfuzz32.so: argvfuzz.c -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)" @@ -54,5 +54,14 @@ install: argvfuzz32.so argvfuzz64.so if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi +argv_fuzz_persistent_demo: argv_fuzz_persistent_demo.c + ../../afl-cc -g -o $@ $^ + +argv_fuzz_demo: argv_fuzz_demo.c + ../../afl-cc -g -o $@ $^ + +demo: argv_fuzz_persistent_demo argv_fuzz_demo + clean: - rm -f argvfuzz32.so argvfuzz64.so + rm -f argvfuzz32.so argvfuzz64.so argv_fuzz_demo argv_fuzz_persistent_demo + diff --git a/utils/argv_fuzzing/README.md b/utils/argv_fuzzing/README.md index e9224995..a085c098 100644 --- a/utils/argv_fuzzing/README.md +++ b/utils/argv_fuzzing/README.md @@ -1,16 +1,45 @@ -# argvfuzz +# argv_fuzzing feature +AFL++ supports fuzzing file inputs or standard input. The argv_fuzzing feature +allows for the fuzzing of arguments passed to a program from the command line +interface rather than from STDIN. -AFL++ supports fuzzing file inputs or stdin. When source is available, -`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin. +## With source code +When the source code is available, a specific macro from the `argv-fuzz-inl.h` +header file can be used to change the program's behavior to build argv from STDIN. +### Without persistent mode +Conditions needed to use the argv_fuzzing feature: +1. Include `argv-fuzz-inl.h` header file (`#include "argv-fuzz-inl.h"`) +2. Identify your main function that parses arguments +(for example, `int main(int argc, char **argv)`) +3. Use one of the following macros (near the beginning of the main function) +to initialize argv with the fuzzer's input: + - `AFL_INIT_ARGV();` or + - `AFL_INIT_SET0("prog_name");` to preserve `argv[0]` + (the name of the program being executed) + +see: [argv_fuzz_demo.c](argv_fuzz_demo.c) + +### With persistent mode +Conditions needed to use the argv_fuzzing feature with persistent mode: +1. Ensure your target can handle persistent mode fuzzing +2. Follow instructions in the [llvm_mode persistent mode](https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md) +3. Use one of the following macros near the beginning of the main function and after +the buffer initialization (`unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF`): + - `AFL_INIT_ARGV_PERSISTENT(buf)`, if you want to + - `AFL_INIT_SET0_PERSISTENT("name_of_binary", buf)` + +see: [argv_fuzz_persistent_demo.c](argv_fuzz_persistent_demo.c) + +## Binary only `argvfuzz` tries to provide the same functionality for binaries. When loaded using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace argv using the same logic of `argv-fuzz-inl.h`. A few conditions need to be fulfilled for this mechanism to work correctly: -1. As it relies on hooking the loader, it cannot work on static binaries. +1. As it relies on hooking the loader, it cannot work on static binaries 2. If the target binary does not use the default libc's `_start` implementation (crt1.o), the hook may not run. -3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the - target binary expects argv to be living on the stack, things may go wrong. \ No newline at end of file +3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. +Things may go wrong if the target binary expects argv to live on the stack. diff --git a/utils/argv_fuzzing/argv-fuzz-inl.h b/utils/argv_fuzzing/argv-fuzz-inl.h index c15c0271..cb0af2bc 100644 --- a/utils/argv_fuzzing/argv-fuzz-inl.h +++ b/utils/argv_fuzzing/argv-fuzz-inl.h @@ -29,11 +29,17 @@ If you would like to always preserve argv[0], use this instead: AFL_INIT_SET0("prog_name"); + To enable persistent fuzzing, use the AFL_INIT_ARGV_PERSISTENT macro with + buf as argument, or use AFL_INIT_SET0_PERSISTENT("prog_name", buf) + to preserver argv[0]. buf is a pointer to a buffer containing + the input data for the current test case being processed defined as: + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; */ #ifndef _HAVE_ARGV_FUZZ_INL #define _HAVE_ARGV_FUZZ_INL +#include <stdlib.h> #include <unistd.h> #define AFL_INIT_ARGV() \ @@ -52,6 +58,22 @@ \ } while (0) +#define AFL_INIT_ARGV_PERSISTENT(persistent_buff) \ + do { \ + \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + \ + } while (0) + +#define AFL_INIT_SET0_PERSISTENT(_p, persistent_buff) \ + do { \ + \ + argv = afl_init_argv_persistent(&argc, persistent_buff); \ + argv[0] = (_p); \ + if (!argc) argc = 1; \ + \ + } while (0) + #define MAX_CMDLINE_LEN 100000 #define MAX_CMDLINE_PAR 50000 @@ -63,7 +85,10 @@ static char **afl_init_argv(int *argc) { char *ptr = in_buf; int rc = 0; - if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {} + ssize_t num = read(0, in_buf, MAX_CMDLINE_LEN - 2); + if (num < 1) { _exit(1); } + in_buf[num] = '\0'; + in_buf[num + 1] = '\0'; while (*ptr && rc < MAX_CMDLINE_PAR) { @@ -83,6 +108,32 @@ static char **afl_init_argv(int *argc) { } +static char **afl_init_argv_persistent(int *argc, + unsigned char *persistent_buff) { + + static char *ret[MAX_CMDLINE_PAR]; + + unsigned char *ptr = persistent_buff; + int rc = 0; + + while (*ptr && rc < MAX_CMDLINE_PAR) { + + ret[rc] = (char *)ptr; + if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; + rc++; + + while (*ptr) + ptr++; + ptr++; + + } + + *argc = rc; + + return ret; + +} + #undef MAX_CMDLINE_LEN #undef MAX_CMDLINE_PAR diff --git a/utils/argv_fuzzing/argv_fuzz_demo.c b/utils/argv_fuzzing/argv_fuzz_demo.c new file mode 100644 index 00000000..6ab1e2e5 --- /dev/null +++ b/utils/argv_fuzzing/argv_fuzz_demo.c @@ -0,0 +1,28 @@ +#include <stdio.h> +#include <string.h> +#include "argv-fuzz-inl.h" + +int main(int argc, char **argv) { + + // Initialize the argv array for use with the AFL (American Fuzzy Lop) tool + AFL_INIT_ARGV(); + + /* Check the number of command line arguments and + compare the values of the first two arguments to specific strings. + If the number of arguments is not correct or the values do not match, + an error message is printed. If the values do match, the program + calls the abort() function. */ + if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { + + if (strcmp(argv[2], "TEST2") == 0) { abort(); } + + } else { + + printf("Bad number of arguments!\n"); + + } + + return 0; + +} + diff --git a/utils/argv_fuzzing/argv_fuzz_persistent_demo.c b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c new file mode 100644 index 00000000..016c3d35 --- /dev/null +++ b/utils/argv_fuzzing/argv_fuzz_persistent_demo.c @@ -0,0 +1,59 @@ +/* +This file contains a simple fuzzer for testing command line argument parsing +using persistent mode. +*/ + +#include <stdio.h> +#include <string.h> +#include "argv-fuzz-inl.h" + +__AFL_FUZZ_INIT(); + +/* The main function is an entry point for a program. + The argc parameter is an integer that indicates the number of arguments + passed to the program. The argv parameter is an array of character pointers, + with each element pointing to a null-terminated string that represents + one of the arguments. + */ +int main(int argc, char **argv) { + +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; + + /* __AFL_LOOP() limits the maximum number of iterations before exiting + the loop and allowing the program to terminate. It protects against + accidental memory leaks and similar issues. */ + while (__AFL_LOOP(100000)) { + + int len = __AFL_FUZZ_TESTCASE_LEN; + + // Check that the length of the test case is at least 8 bytes + if (len < 8) continue; + + // Initialize the command line arguments using the testcase buffer + AFL_INIT_ARGV_PERSISTENT(buf); + + /* Check if the first argument is "XYZ" and the second argument is "TEST2" + If so, call the "abort" function to terminate the program. + Otherwise, print an error message. */ + if (argc > 1 && strcmp(argv[1], "XYZ") == 0) { + + if (strcmp(argv[2], "TEST2") == 0) { abort(); } + + } else { + + printf("Bad number of arguments!\n"); + + } + + } + + /* Exiting the loop allows the program to terminate normally. AFL will restart + the process with a clean slate for allocated memory, file descriptors, etc. + */ + return 0; + +} + diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c index e7cc6b72..41eead0c 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-2022 Kjell Braden <afflux@pentabarf.de> + Copyright 2019-2023 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/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index 251ae4e6..b22816f1 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-2022 AFLplusplus Project. All rights reserved. +# Copyright 2019-2023 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/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index c390d004..1cd7abc6 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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/README.md b/utils/libtokencap/README.md index 50104291..8705452c 100644 --- a/utils/libtokencap/README.md +++ b/utils/libtokencap/README.md @@ -47,9 +47,11 @@ by AFL++ in that earlier run. This demonstrates the basic principle: ``` export AFL_TOKEN_FILE=$PWD/temp_output.txt + timeout_sec="5" for i in <out_dir>/queue/id*; do LD_PRELOAD=/path/to/libtokencap.so \ + timeout -s SIGKILL ${timeout_sec} \ /path/to/target/program [...params, including $i...] done diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 07d81d59..299056ab 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 168aa429..4ead6577 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-2022 AFLplusplus Project. All rights reserved. + Copyright 2019-2023 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: |