aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/afl_network_proxy/afl-network-client.c2
-rw-r--r--utils/afl_network_proxy/afl-network-server.c19
-rw-r--r--utils/afl_proxy/README.md5
-rw-r--r--utils/afl_proxy/afl-proxy.c2
-rw-r--r--utils/afl_untracer/afl-untracer.c25
-rw-r--r--utils/afl_untracer/libtestinstr.c2
-rw-r--r--utils/aflpp_driver/GNUmakefile23
-rw-r--r--utils/aflpp_driver/aflpp_driver.c130
-rw-r--r--utils/aflpp_driver/aflpp_driver_test.c17
-rwxr-xr-xutils/analysis_scripts/queue2csv.sh4
-rw-r--r--utils/argv_fuzzing/Makefile17
-rw-r--r--utils/argv_fuzzing/README.md41
-rw-r--r--utils/argv_fuzzing/argv-fuzz-inl.h53
-rw-r--r--utils/argv_fuzzing/argv_fuzz_demo.c28
-rw-r--r--utils/argv_fuzzing/argv_fuzz_persistent_demo.c59
-rw-r--r--utils/argv_fuzzing/argvfuzz.c2
-rwxr-xr-xutils/distributed_fuzzing/sync_script.sh2
-rw-r--r--utils/libdislocator/README.md4
-rw-r--r--utils/libdislocator/libdislocator.so.c37
-rw-r--r--utils/libtokencap/README.md2
-rw-r--r--utils/libtokencap/libtokencap.so.c18
-rw-r--r--utils/persistent_mode/test-instr.c2
22 files changed, 386 insertions, 108 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/README.md b/utils/afl_proxy/README.md
index 3c768a19..7965659d 100644
--- a/utils/afl_proxy/README.md
+++ b/utils/afl_proxy/README.md
@@ -7,3 +7,8 @@ You only need to change the while() loop of the main() to send the
data of buf[] with length len to the target and write the coverage
information to __afl_area_ptr[__afl_map_size]
+UPDATE: you can also use [custom mutators](../../docs/custom_mutators.md) with
+afl_custom_fuzz_send to send data to a target, which is much more efficient!
+But you can only use this feature if you start the target via afl-fuzz and
+a forkserver is active (e.g. via -Q qemu_mode or source compiled).
+
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 4e4ea129..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,21 +24,24 @@ 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>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,15 +64,26 @@ $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;
-// libFuzzer interface is thin, so we don't include any libFuzzer headers.
-int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+// AFL++ coverage map
+extern unsigned char *__afl_area_ptr;
+extern unsigned int __afl_map_size;
-// Default nop ASan hooks for manual posisoning when not linking the ASan
+// libFuzzer interface is thin, so we don't include any libFuzzer headers.
+/* 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
// https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning
__attribute__((weak)) void __asan_poison_memory_region(
@@ -187,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;
@@ -195,7 +214,9 @@ size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
}
// Execute any files provided as parameters.
-static int ExecuteFilesOnyByOne(int argc, char **argv) {
+static int ExecuteFilesOnyByOne(int argc, char **argv,
+ int (*callback)(const uint8_t *data,
+ size_t size)) {
unsigned char *buf = (unsigned char *)malloc(MAX_FILE);
@@ -231,7 +252,7 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
prev_length = length;
printf("Reading %zu bytes from %s\n", length, argv[i]);
- LLVMFuzzerTestOneInput(buf, length);
+ callback(buf, length);
printf("Execution successful.\n");
}
@@ -245,7 +266,18 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
}
-int main(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(
@@ -265,6 +297,17 @@ int main(int argc, char **argv) {
"===================================================================\n",
argv[0], argv[0]);
+ return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput);
+
+}
+
+__attribute__((weak)) int LLVMFuzzerRunDriver(
+ int *argcp, char ***argvp,
+ int (*callback)(const uint8_t *data, size_t size)) {
+
+ int argc = *argcp;
+ char **argv = *argvp;
+
if (getenv("AFL_GDB")) {
char cmd[64];
@@ -275,6 +318,12 @@ int main(int argc, char **argv) {
}
+ bool in_afl = !(!getenv(SHM_FUZZ_ENV_VAR) || !getenv(SHM_ENV_VAR) ||
+ fcntl(FORKSRV_FD, F_GETFD) == -1 ||
+ fcntl(FORKSRV_FD + 1, F_GETFD) == -1);
+
+ if (!in_afl) { __afl_sharedmem_fuzzing = 0; }
+
output_file = stderr;
maybe_duplicate_stderr();
maybe_close_fd_mask();
@@ -295,27 +344,28 @@ int main(int argc, char **argv) {
int N = INT_MAX;
- if (argc == 2 && !strcmp(argv[1], "-")) {
+ if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {
- __afl_sharedmem_fuzzing = 0;
__afl_manual_init();
- return ExecuteFilesOnyByOne(argc, argv);
+ return ExecuteFilesOnyByOne(argc, argv, callback);
- } else if (argc == 2 && argv[1][0] == '-') {
+ } else if (argc == 2 && argv[1][0] == '-' && argv[1][1]) {
N = atoi(argv[1] + 1);
- } else if (argc == 2 && (N = atoi(argv[1])) > 0) {
+ } else if (argc == 2 && argv[1][0] != '-' && (N = atoi(argv[1])) > 0) {
printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
- } else if (argc > 1) {
-
- __afl_sharedmem_fuzzing = 0;
+ } else if (!in_afl && argc > 1 && argv[1][0] != '-') {
if (argc == 2) { __afl_manual_init(); }
- return ExecuteFilesOnyByOne(argc, argv);
+ return ExecuteFilesOnyByOne(argc, argv, callback);
+
+ } else {
+
+ N = INT_MAX;
}
@@ -325,7 +375,7 @@ int main(int argc, char **argv) {
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
// on the first execution of LLVMFuzzerTestOneInput is ignored.
- LLVMFuzzerTestOneInput(dummy_input, 4);
+ callback(dummy_input, 4);
__asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE);
size_t prev_length = 0;
@@ -352,7 +402,13 @@ int main(int argc, char **argv) {
}
prev_length = length;
- LLVMFuzzerTestOneInput(__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;
+
+ }
}
@@ -362,7 +418,7 @@ int main(int argc, char **argv) {
while (__afl_persistent_loop(N)) {
- LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len);
+ callback(__afl_fuzz_ptr, *__afl_fuzz_len);
}
@@ -372,3 +428,9 @@ int main(int argc, char **argv) {
}
+#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/analysis_scripts/queue2csv.sh b/utils/analysis_scripts/queue2csv.sh
index 2528b438..47141efe 100755
--- a/utils/analysis_scripts/queue2csv.sh
+++ b/utils/analysis_scripts/queue2csv.sh
@@ -92,14 +92,14 @@ mkdir "$DIR" || exit 1
if [ -n "$3" -a -s "$DIR/../edges.txt" ]; then
- cat "$DIR/"* | sed 's/:.*//' | sort -n | uniq -c | egrep '^[ \t]*1 ' | awk '{print$2}' > $DIR/../unique.txt
+ cat "$DIR/"* | sed 's/:.*//' | sort -n | uniq -c | grep -E '^[ \t]*1 ' | awk '{print$2}' > $DIR/../unique.txt
if [ -s "$DIR/../unique.txt" ]; then
ls "$DIR/id:"* | grep -v ",sync:" |sed 's/.*\/id:/id:/g' | while read file; do
CNT=$(sed 's/:.*//' "$DIR/$file" | tee "$DIR/../tmp.txt" | wc -l)
- DIFF=$(diff -u "$DIR/../tmp.txt" "$DIR/../unique.txt" | egrep '^-[0-9]' | wc -l)
+ DIFF=$(diff -u "$DIR/../tmp.txt" "$DIR/../unique.txt" | grep -E '^-[0-9]' | wc -l)
UNIQUE=$(($CNT - $DIFF))
sed -i "s/;UNIQUE$file/;$UNIQUE/" "$DIR/../queue.csv" "$2"
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/README.md b/utils/libdislocator/README.md
index e4934b5d..d0e45fff 100644
--- a/utils/libdislocator/README.md
+++ b/utils/libdislocator/README.md
@@ -34,8 +34,8 @@ heap-related security bugs in several ways:
- Size alignment to `max_align_t` can be enforced with `AFL_ALIGNED_ALLOC=1`. In
this case, a tail canary is inserted in the padding bytes at the end of the
- allocated zone. This reduce the ability of libdislocator to detect
- off-by-one bugs but also it make slibdislocator compliant to the C standard.
+ allocated zone. This reduces the ability of libdislocator to detect
+ off-by-one bugs but also it makes libdislocator compliant to the C standard.
Basically, it is inspired by some of the non-default options available for the
OpenBSD allocator - see malloc.conf(5) on that platform for reference. It is
diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c
index 149b910e..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.
@@ -304,7 +304,8 @@ static void *__dislocator_alloc(size_t len) {
/* The "user-facing" wrapper for calloc(). This just checks for overflows and
displays debug messages if requested. */
-void *calloc(size_t elem_len, size_t elem_cnt) {
+__attribute__((malloc)) __attribute__((alloc_size(1, 2))) void *calloc(
+ size_t elem_len, size_t elem_cnt) {
void *ret;
@@ -339,7 +340,8 @@ void *calloc(size_t elem_len, size_t elem_cnt) {
memory (unlike calloc(), malloc() is not guaranteed to return zeroed
memory). */
-void *malloc(size_t len) {
+__attribute__((malloc)) __attribute__((alloc_size(1))) void *malloc(
+ size_t len) {
void *ret;
@@ -398,7 +400,7 @@ void free(void *ptr) {
/* Realloc is pretty straightforward, too. We forcibly reallocate the buffer,
move data, and then free (aka mprotect()) the original one. */
-void *realloc(void *ptr, size_t len) {
+__attribute__((alloc_size(2))) void *realloc(void *ptr, size_t len) {
void *ret;
@@ -450,7 +452,8 @@ int posix_memalign(void **ptr, size_t align, size_t len) {
/* just the non-posix fashion */
-void *memalign(size_t align, size_t len) {
+__attribute__((malloc)) __attribute__((alloc_size(2))) void *memalign(
+ size_t align, size_t len) {
void *ret = NULL;
@@ -466,7 +469,8 @@ void *memalign(size_t align, size_t len) {
/* sort of C11 alias of memalign only more severe, alignment-wise */
-void *aligned_alloc(size_t align, size_t len) {
+__attribute__((malloc)) __attribute__((alloc_size(2))) void *aligned_alloc(
+ size_t align, size_t len) {
void *ret = NULL;
@@ -484,7 +488,8 @@ void *aligned_alloc(size_t align, size_t len) {
/* specific BSD api mainly checking possible overflow for the size */
-void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) {
+__attribute__((alloc_size(2, 3))) void *reallocarray(void *ptr, size_t elem_len,
+ size_t elem_cnt) {
const size_t elem_lim = 1UL << (sizeof(size_t) * 4);
const size_t elem_tot = elem_len * elem_cnt;
@@ -505,6 +510,24 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) {
}
+int reallocarr(void *ptr, size_t elem_len, size_t elem_cnt) {
+
+ void *ret = NULL;
+ const size_t elem_tot = elem_len * elem_cnt;
+
+ if (elem_tot == 0) {
+
+ void **h = &ptr;
+ *h = ret;
+ return 0;
+
+ }
+
+ ret = reallocarray(ptr, elem_len, elem_cnt);
+ return ret ? 0 : -1;
+
+}
+
#if defined(__APPLE__)
size_t malloc_size(const void *ptr) {
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 5dcb8f4c..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.
@@ -378,7 +378,8 @@ __attribute__((hot)) int strcmp(const char *str1, const char *str2) {
#undef strncmp
-__attribute__((hot)) int strncmp(const char *str1, const char *str2, size_t len) {
+__attribute__((hot)) int strncmp(const char *str1, const char *str2,
+ size_t len) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
@@ -428,7 +429,8 @@ __attribute__((hot)) int strcasecmp(const char *str1, const char *str2) {
#undef strncasecmp
-__attribute__((hot)) int strncasecmp(const char *str1, const char *str2, size_t len) {
+__attribute__((hot)) int strncasecmp(const char *str1, const char *str2,
+ size_t len) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
@@ -454,7 +456,8 @@ __attribute__((hot)) int strncasecmp(const char *str1, const char *str2, size_t
#undef memcmp
-__attribute__((hot)) int memcmp(const void *mem1, const void *mem2, size_t len) {
+__attribute__((hot)) int memcmp(const void *mem1, const void *mem2,
+ size_t len) {
if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
@@ -537,7 +540,8 @@ __attribute__((hot)) char *strstr(const char *haystack, const char *needle) {
#undef strcasestr
-__attribute__((hot)) char *strcasestr(const char *haystack, const char *needle) {
+__attribute__((hot)) char *strcasestr(const char *haystack,
+ const char *needle) {
if (__tokencap_is_ro(haystack))
__tokencap_dump(haystack, strlen(haystack), 1);
@@ -566,8 +570,8 @@ __attribute__((hot)) char *strcasestr(const char *haystack, const char *needle)
#undef memmem
-__attribute__((hot)) void *memmem(const void *haystack, size_t haystack_len, const void *needle,
- size_t needle_len) {
+__attribute__((hot)) void *memmem(const void *haystack, size_t haystack_len,
+ const void *needle, size_t needle_len) {
if (__tokencap_is_ro(haystack)) __tokencap_dump(haystack, haystack_len, 1);
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: