diff --git a/GNUmakefile b/GNUmakefile
index fadf20bd..5fd37147 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -32,7 +32,7 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f
# PROGS intentionally omit afl-as, which gets installed elsewhere.
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
-SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config afl-persistent-config afl-cc
+SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-addseeds afl-system-config afl-persistent-config afl-cc
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
ASAN_OPTIONS=detect_leaks=0
diff --git a/afl-addseeds b/afl-addseeds
new file mode 100755
index 00000000..bb2843a8
--- /dev/null
+++ b/afl-addseeds
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+test -z "$1" -o "$1" = "-h" -o "$1" = "--help" && {
+ echo Syntax: afl-addseeds -o afl-out-dir [-i seed_file_or_dir] seed_file_or_seed_dir seed_file_or_seed_dir ...
+ echo
+ echo Options:
+ echo " -o afl-out-dir the output directory being used in the fuzzing campaign"
+ echo " -i seed_file_or_dir file or directory of files to add"
+ echo
+ echo Adds new seeds to an existing AFL++ fuzzing campaign.
+ exit 0
+}
+
+for TOOL in find ls; do
+ X=`which $TOOL`
+ test -n "$X" || { echo "Error: required tool '$TOOL' not found."; exit 1; }
+done
+
+TEST=`printf %06d 123 2>/dev/null`
+test "$TEST" = "000123" || { echo "Error: required tool 'printf' not found."; exit 1; }
+
+OUT=
+NEXT=
+for i in $*; do
+ test -n "$NEXT" && { OUT=$i ; NEXT=""; }
+ test "$i" = "-o" && { NEXT=1; }
+done
+
+test -d "$OUT" || { echo Error: $OUT is not an existing directory; exit 1; }
+OK=`ls $OUT/*/fuzzer_stats 2>/dev/null`
+test -n "$OK" || { echo "Error: $OUT is not an 'afl-fuzz -o ... ' output directory" ; exit 1; }
+
+OUTDIR=$OUT/addseeds/queue
+mkdir -p "$OUTDIR" 2>/dev/null
+test -d "$OUTDIR" || { echo Error: could not create $OUTDIR ; exit 1 ; }
+
+echo Adding seeds ...
+NEXTID=0
+for i in $*; do
+ test -z "$i" -o "$i" = "$OUT" -o "$i" = "-i" -o "$i" = "-o" || {
+ find "$i" -type f | while read FILE; do
+ N=xxx
+ while [ -n "$N" ]; do
+ ID=$NEXTID
+ N=`ls "$OUTDIR/id:$(printf %06d $ID),"* 2>/dev/null`
+ NEXTID=$(($NEXTID + 1))
+ done
+ FN=`echo "$FILE" | sed 's/.*\///'`
+ cp -v "$FILE" "$OUTDIR/id:$(printf %06d $ID),time:0,execs:0,orig:$FN"
+ done
+ }
+done
+
+echo Done.
diff --git a/docs/Changelog.md b/docs/Changelog.md
index dfbadea3..101d380b 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -19,6 +19,7 @@
- fix for a few string compare transform functions for LAF
- frida_mode:
- fixes support for large map offsets
+ - added new tool afl-addseeds that adds new seeds to a running campaign
- added benchmark/benchmark.sh if you want to see how good your fuzzing
speed is in comparison to other setups.
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index dd9aae77..85ee9f71 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -666,8 +666,8 @@ static void __afl_map_shm(void) {
}
if (id_str) {
-
- if ((__afl_dummy_fd[1] = open("/dev/null", O_WRONLY)) < 0) {
+ // /dev/null doesn't work so we use /dev/urandom
+ if ((__afl_dummy_fd[1] = open("/dev/urandom", O_WRONLY)) < 0) {
if (pipe(__afl_dummy_fd) < 0) { __afl_dummy_fd[1] = 1; }
@@ -2294,7 +2294,7 @@ void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len) {
int len1 = strnlen(ptr1, len0);
if (len1 < 31) len1 = area_is_valid(ptr1, len1 + 1);
int len2 = strnlen(ptr2, len0);
- if (len2 < 31) len2 = area_is_valid(ptr1, len2 + 1);
+ if (len2 < 31) len2 = area_is_valid(ptr2, len2 + 1);
int l = MAX(len1, len2);
if (l < 2) return;
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
index 874fa033..92ed7cef 160000
--- a/nyx_mode/QEMU-Nyx
+++ b/nyx_mode/QEMU-Nyx
@@ -1 +1 @@
-Subproject commit 874fa033d117a3e9931245cb9e82836a4abc0425
+Subproject commit 92ed7cefc1bd043a1230ca74b263b484825c2655
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 3d0a9b9a..adf04420 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -778,10 +778,29 @@ void show_stats_normal(afl_state_t *afl) {
if (unlikely(!banner[0])) {
char *si = "";
+ char *fuzzer_name;
+
if (afl->sync_id) { si = afl->sync_id; }
memset(banner, 0, sizeof(banner));
- banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
- strlen(afl->power_name) + 4 + 6;
+
+ banner_len = strlen(VERSION) + strlen(si) + strlen(afl->power_name) + 4 + 6;
+
+ if (afl->crash_mode) {
+
+ fuzzer_name = "peruvian were-rabbit";
+
+ } else {
+
+ fuzzer_name = "american fuzzy lop";
+ if (banner_len + strlen(fuzzer_name) + strlen(afl->use_banner) > 75) {
+
+ fuzzer_name = "AFL";
+
+ }
+
+ }
+
+ banner_len += strlen(fuzzer_name);
if (strlen(afl->use_banner) + banner_len > 75) {
@@ -798,18 +817,16 @@ void show_stats_normal(afl_state_t *afl) {
if (afl->fsrv.nyx_mode) {
snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
+ "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN : cYEL, fuzzer_name,
si, afl->use_banner, afl->power_name);
} else {
#endif
snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
+ "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN : cYEL, fuzzer_name,
si, afl->use_banner, afl->power_name);
#ifdef __linux__
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 86c05223..2538f4a4 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1346,6 +1346,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) {
+
+ FATAL("-M/-S name 'addseeds' is a reserved name, choose something else");
+
+ }
+
if (afl->is_main_node == 1 && afl->schedule != FAST &&
afl->schedule != EXPLORE) {
@@ -2826,7 +2832,9 @@ int main(int argc, char **argv_orig, char **envp) {
if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 &&
!afl->non_instrumented_mode) &&
- unlikely(cur_time > afl->last_find_time + afl->switch_fuzz_mode)) {
+ unlikely(cur_time > (likely(afl->last_find_time) ? afl->last_find_time
+ : afl->start_time) +
+ afl->switch_fuzz_mode)) {
if (afl->afl_env.afl_no_ui) {
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 04507410..07c1b527 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -1,24 +1,3 @@
-/*
- Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
-
- To the extent possible under law, the author has dedicated all copyright
- and related and neighboring rights to this software to the public domain
- worldwide. This software is distributed without any warranty.
-
- See .
-
- This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
- It has excellent (sub-ns) speed, a state (256 bits) that is large
- enough for any parallel application, and it passes all tests we are
- aware of.
-
- For generating just floating-point numbers, xoshiro256+ is even faster.
-
- The state must be seeded so that it is not everywhere zero. If you have
- a 64-bit seed, we suggest to seed a splitmix64 generator and use its
- output to fill s[].
-*/
-
#include
#include "afl-fuzz.h"
#include "types.h"
diff --git a/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py b/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
index eccbc8bf..7e97f6a7 100644
--- a/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
+++ b/unicorn_mode/helper_scripts/unicorn_dumper_pwndbg.py
@@ -40,10 +40,10 @@ import gdb
pwndbg_loaded = False
try:
- import pwndbg.arch
- import pwndbg.regs
- import pwndbg.vmmap
- import pwndbg.memory
+ import pwndbg.gdblib.arch
+ import pwndbg.gdblib.regs
+ import pwndbg.gdblib.vmmap
+ import pwndbg.gdblib.memory
pwndbg_loaded = True
@@ -64,7 +64,7 @@ INDEX_FILE_NAME = "_index.json"
def map_arch():
- arch = pwndbg.arch.current # from PWNDBG
+ arch = pwndbg.gdblib.arch.current # from PWNDBG
if "x86_64" in arch or "x86-64" in arch:
return "x64"
elif "x86" in arch or "i386" in arch:
@@ -74,9 +74,9 @@ def map_arch():
elif "aarch64_be" in arch:
return "arm64be"
elif "arm" in arch:
- cpsr = pwndbg.regs["cpsr"]
+ cpsr = pwndbg.gdblib.regs["cpsr"]
# check endianess
- if pwndbg.arch.endian == "big":
+ if pwndbg.gdblib.arch.endian == "big":
# check for THUMB mode
if cpsr & (1 << 5):
return "armbethumb"
@@ -89,7 +89,7 @@ def map_arch():
else:
return "armle"
elif "mips" in arch:
- if pwndbg.arch.endian == "little":
+ if pwndbg.gdblib.arch.endian == "little":
return "mipsel"
else:
return "mips"
@@ -109,8 +109,8 @@ def dump_arch_info():
def dump_regs():
reg_state = {}
- for reg in pwndbg.regs.all:
- reg_val = pwndbg.regs[reg]
+ for reg in pwndbg.gdblib.regs.all:
+ reg_val = pwndbg.gdblib.regs[reg]
# current dumper script looks for register values to be hex strings
# reg_str = "0x{:08x}".format(reg_val)
# if "64" in get_arch():
@@ -125,7 +125,7 @@ def dump_process_memory(output_dir):
final_segment_list = []
# PWNDBG:
- vmmap = pwndbg.vmmap.get()
+ vmmap = pwndbg.gdblib.vmmap.get()
# Pointer to end of last dumped memory segment
segment_last_addr = 0x0
@@ -165,7 +165,7 @@ def dump_process_memory(output_dir):
if entry.read and not "(deleted)" in entry.objfile:
try:
# Compress and dump the content to a file
- seg_content = pwndbg.memory.read(start, end - start)
+ seg_content = pwndbg.gdblib.memory.read(start, end - start)
if seg_content == None:
print(
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(
@@ -181,7 +181,7 @@ def dump_process_memory(output_dir):
repr(seg_info["permissions"]),
)
)
- compressed_seg_content = zlib.compress(str(seg_content))
+ compressed_seg_content = zlib.compress(bytes(seg_content))
md5_sum = hashlib.md5(compressed_seg_content).hexdigest() + ".bin"
seg_info["content_file"] = md5_sum