about summary refs log tree commit diff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/afl_network_proxy/GNUmakefile1
-rw-r--r--utils/afl_network_proxy/afl-network-client.c2
-rw-r--r--utils/afl_network_proxy/afl-network-server.c3
-rw-r--r--utils/afl_proxy/afl-proxy.c2
-rw-r--r--utils/afl_untracer/Makefile7
-rw-r--r--utils/afl_untracer/afl-untracer.c38
-rw-r--r--utils/afl_untracer/libtestinstr.c2
-rw-r--r--utils/aflpp_driver/aflpp_driver.c19
-rw-r--r--utils/argv_fuzzing/Makefile2
-rw-r--r--utils/argv_fuzzing/argvfuzz.c2
-rw-r--r--utils/bench/Makefile8
-rw-r--r--utils/bench/README.md2
-rw-r--r--utils/bench/hash.c53
-rwxr-xr-xutils/distributed_fuzzing/sync_script.sh2
-rw-r--r--utils/dynamic_covfilter/README.md60
-rw-r--r--utils/dynamic_covfilter/make_symbol_list.py73
-rw-r--r--utils/libdislocator/libdislocator.so.c2
-rw-r--r--utils/libtokencap/libtokencap.so.c14
-rw-r--r--utils/persistent_mode/Makefile2
-rw-r--r--utils/persistent_mode/test-instr.c2
-rwxr-xr-xutils/qbdi_mode/build.sh2
-rw-r--r--utils/replay_record/Makefile8
-rw-r--r--utils/replay_record/README.md10
-rw-r--r--utils/replay_record/persistent_demo_replay.c148
-rw-r--r--utils/socket_fuzzing/socketfuzz.c3
-rw-r--r--utils/target_intelligence/README.md61
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.