diff --git a/.custom-format.py b/.custom-format.py index 3521c05d14..c8075acec7 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -24,7 +24,7 @@ # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use -CURRENT_LLVM = os.getenv('LLVM_VERSION', 16) +CURRENT_LLVM = os.getenv('LLVM_VERSION', 17) CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") diff --git a/.gitignore b/.gitignore index c01750e131..f76a86fc00 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ .test .test2 .vscode +afl-addseeds.8 afl-analyze afl-analyze.8 afl-as diff --git a/afl-cmin b/afl-cmin index 23532b635a..566f157d92 100755 --- a/afl-cmin +++ b/afl-cmin @@ -259,22 +259,20 @@ BEGIN { # Do a sanity check to discourage the use of /tmp, since we can't really # handle this safely from an awk script. - #if (!ENVIRON["AFL_ALLOW_TMP"]) { - # dirlist[0] = in_dir - # dirlist[1] = target_bin - # dirlist[2] = out_dir - # dirlist[3] = stdin_file - # "pwd" | getline dirlist[4] # current directory - # for (dirind in dirlist) { - # dir = dirlist[dirind] - # - # if (dir ~ /^(\/var)?\/tmp/) { - # print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr" - # exit 1 - # } - # } - # delete dirlist - #} + if (!ENVIRON["AFL_ALLOW_TMP"]) { + dirlist[0] = in_dir + dirlist[1] = target_bin + dirlist[2] = out_dir + dirlist[3] = stdin_file + "pwd" | getline dirlist[4] # current directory + for (dirind in dirlist) { + dir = dirlist[dirind] + if (dir ~ /^(\/var)?\/tmp/) { + print "[-] Warning: do not use this script in /tmp or /var/tmp for security reasons." > "/dev/stderr" + } + } + delete dirlist + } if (threads && stdin_file) { print "[-] Error: -T and -f cannot be used together." > "/dev/stderr" @@ -430,7 +428,7 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r)" + cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" diff --git a/afl-cmin.bash b/afl-cmin.bash index b326bee891..fda48fb4c1 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -167,29 +167,28 @@ fi # Do a sanity check to discourage the use of /tmp, since we can't really # handle this safely from a shell script. -#if [ "$AFL_ALLOW_TMP" = "" ]; then -# -# echo "$IN_DIR" | grep -qE '^(/var)?/tmp/' -# T1="$?" -# -# echo "$TARGET_BIN" | grep -qE '^(/var)?/tmp/' -# T2="$?" -# -# echo "$OUT_DIR" | grep -qE '^(/var)?/tmp/' -# T3="$?" -# -# echo "$STDIN_FILE" | grep -qE '^(/var)?/tmp/' -# T4="$?" -# -# echo "$PWD" | grep -qE '^(/var)?/tmp/' -# T5="$?" -# -# if [ "$T1" = "0" -o "$T2" = "0" -o "$T3" = "0" -o "$T4" = "0" -o "$T5" = "0" ]; then -# echo "[-] Error: do not use this script in /tmp or /var/tmp." 1>&2 -# exit 1 -# fi -# -#fi +if [ "$AFL_ALLOW_TMP" = "" ]; then + + echo "$IN_DIR" | grep -qE '^(/var)?/tmp/' + T1="$?" + + echo "$TARGET_BIN" | grep -qE '^(/var)?/tmp/' + T2="$?" + + echo "$OUT_DIR" | grep -qE '^(/var)?/tmp/' + T3="$?" + + echo "$STDIN_FILE" | grep -qE '^(/var)?/tmp/' + T4="$?" + + echo "$PWD" | grep -qE '^(/var)?/tmp/' + T5="$?" + + if [ "$T1" = "0" -o "$T2" = "0" -o "$T3" = "0" -o "$T4" = "0" -o "$T5" = "0" ]; then + echo "[-] Warning: do not use this script in /tmp or /var/tmp for security reasons." 1>&2 + fi + +fi # If @@ is specified, but there's no -f, let's come up with a temporary input # file name. @@ -423,10 +422,14 @@ if [ "$THREADS" = "" ]; then ls "$IN_DIR" | while read -r fn; do - CUR=$((CUR+1)) - printf "\\r Processing file $CUR/$IN_COUNT... " + if [ -s "$IN_DIR/$fn" ]; then - "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn" + CUR=$((CUR+1)) + printf "\\r Processing file $CUR/$IN_COUNT... " + + "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn" + + fi done @@ -434,11 +437,15 @@ if [ "$THREADS" = "" ]; then ls "$IN_DIR" | while read -r fn; do - CUR=$((CUR+1)) - printf "\\r Processing file $CUR/$IN_COUNT... " + if [ -s "$IN_DIR/$fn" ]; then + + CUR=$((CUR+1)) + printf "\\r Processing file $CUR/$IN_COUNT... " + + cp "$IN_DIR/$fn" "$STDIN_FILE" + "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" ' echo echo $0 @@ -13,6 +13,10 @@ test "$1" = "-h" -o "$1" = "-hh" && { echo configuration options. exit 0 } +if [ $# -ne 0 ]; then + echo "ERROR: Unknown option(s): $@" + exit 1 +fi DONE= PLATFORM=`uname -s` diff --git a/docs/Changelog.md b/docs/Changelog.md index 101d380b76..c74a9ad7c1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,9 @@ - added AFL_IGNORE_SEED_PROBLEMS to skip over seeds that time out instead of exiting with an error message - allow -S/-M naming up to 50 characters (from 24) + - added scale support to CMPLOG (-l S) + - added --version and --help command line parameters + - fixed endless loop when reading malformed dictionaries - afl-whatsup: - detect instanced that are starting up and show them as such as not dead - now also shows coverage reached @@ -19,6 +22,7 @@ - fix for a few string compare transform functions for LAF - frida_mode: - fixes support for large map offsets + - afl-cmin/afl-cmin.bash: prevent unneeded file errors - 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/docs/custom_mutators.md b/docs/custom_mutators.md index c5a64622dc..1c4ab2cf1f 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -125,8 +125,9 @@ def deinit(): # optional for Python - `queue_get` (optional): - This method determines whether the custom fuzzer should fuzz the current - queue entry or not + This method determines whether AFL++ should fuzz the current + queue entry or not: all defined custom mutators as well as + all AFL++'s mutators. - `fuzz_count` (optional): diff --git a/docs/env_variables.md b/docs/env_variables.md index 3bb4e84470..a763651141 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -135,6 +135,12 @@ subset of the settings discussed in section 1, with the exception of: - `TMPDIR` and `AFL_KEEP_ASSEMBLY`, since no temporary assembly files are created. + - LLVM modes compiling C++ will normally set rpath in the binary if LLVM is + not in a usual location (/usr or /lib). Setting `AFL_LLVM_NO_RPATH=1` + disables this behaviour in case it isn't desired. For example, the compiling + toolchain might be in a custom location, but the target machine has LLVM + runtime libs in the search path. + Then there are a few specific features that are only available in instrumentation mode: diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index f11c4b2586..bd7b1351d3 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -49,10 +49,10 @@ extern void __libc_init(void *raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char **, char **), structors_array_t const *const structors); #else -extern int __libc_start_main(int (*main)(int, char **, char **), int argc, - char **ubp_av, void (*init)(void), - void (*fini)(void), void (*rtld_fini)(void), - void(*stack_end)); +extern int __libc_start_main(int (*main)(int, char **, char **), int argc, + char **ubp_av, void (*init)(void), + void (*fini)(void), void (*rtld_fini)(void), + void(*stack_end)); #endif typedef int (*main_fn_t)(int argc, char **argv, char **envp); diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 217a720ad5..8112d430e2 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -675,7 +675,7 @@ typedef struct afl_state { u32 cmplog_max_filesize; u32 cmplog_lvl; u32 colorize_success; - u8 cmplog_enable_arith, cmplog_enable_transform, + u8 cmplog_enable_arith, cmplog_enable_transform, cmplog_enable_scale, cmplog_enable_xtreme_transform, cmplog_random_colorization; struct afl_pass_stat *pass_stats; diff --git a/include/afl-mutations.h b/include/afl-mutations.h index 98ba6fcf56..d709b90d05 100644 --- a/include/afl-mutations.h +++ b/include/afl-mutations.h @@ -1854,7 +1854,7 @@ inline u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32 steps, for (u32 step = 0; step < steps; ++step) { - retry_havoc_step : { + retry_havoc_step: { u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item; diff --git a/include/envs.h b/include/envs.h index 734b1707ae..93e49e34c0 100644 --- a/include/envs.h +++ b/include/envs.h @@ -162,6 +162,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", + "AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_THREADSAFE_INST", diff --git a/include/xxhash.h b/include/xxhash.h index 7bc0a14eec..a8bd6f2709 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -365,7 +365,7 @@ typedef uint32_t XXH32_hash_t; (defined(__cplusplus) || \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)) #include -typedef uint32_t XXH32_hash_t; +typedef uint32_t XXH32_hash_t; #else #include @@ -1082,7 +1082,7 @@ struct XXH64_state_s { #include #define XXH_ALIGN(n) alignas(n) #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ - /* In C++ alignas() is a keyword */ + /* In C++ alignas() is a keyword */ #define XXH_ALIGN(n) alignas(n) #elif defined(__GNUC__) #define XXH_ALIGN(n) __attribute__((aligned(n))) @@ -3031,8 +3031,8 @@ XXH64_hashFromCanonical(const XXH64_canonical_t *src) { __STDC_VERSION__ >= 199901L /* >= C99 */ #define XXH_RESTRICT restrict #else - /* Note: it might be useful to define __restrict or __restrict__ for - * some C++ compilers */ + /* Note: it might be useful to define __restrict or __restrict__ for + * some C++ compilers */ #define XXH_RESTRICT /* disable */ #endif @@ -3492,8 +3492,8 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) { #define XXH_vec_mulo vec_mulo #define XXH_vec_mule vec_mule #elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) - /* Clang has a better way to control this, we can just use the builtin - * which doesn't swap. */ + /* Clang has a better way to control this, we can just use the builtin + * which doesn't swap. */ #define XXH_vec_mulo __builtin_altivec_vmulouw #define XXH_vec_mule __builtin_altivec_vmuleuw #else @@ -3604,15 +3604,15 @@ XXH_FORCE_INLINE xxh_u64 XXH_mult32to64(xxh_u64 x, xxh_u64 y) { #include #define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) #else - /* - * Downcast + upcast is usually better than masking on older compilers - * like GCC 4.2 (especially 32-bit ones), all without affecting newer - * compilers. - * - * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both - * operands and perform a full 64x64 multiply -- entirely redundant on - * 32-bit. - */ + /* + * Downcast + upcast is usually better than masking on older compilers + * like GCC 4.2 (especially 32-bit ones), all without affecting newer + * compilers. + * + * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both + * operands and perform a full 64x64 multiply -- entirely redundant on + * 32-bit. + */ #define XXH_mult32to64(x, y) \ ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) #endif diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c3197c8a34..d6b4d6b47e 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -872,7 +872,7 @@ static void __afl_start_snapshots(void) { if (__afl_debug) { - fprintf(stderr, "target forkserver recv: %08x\n", was_killed); + fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed); } @@ -1139,7 +1139,7 @@ static void __afl_start_forkserver(void) { if (__afl_debug) { - fprintf(stderr, "target forkserver recv: %08x\n", was_killed); + fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed); } @@ -1472,6 +1472,7 @@ __attribute__((constructor(1))) void __afl_auto_second(void) { __afl_debug = 1; fprintf(stderr, "DEBUG: debug enabled\n"); + fprintf(stderr, "DEBUG: AFL++ afl-compiler-rt" VERSION "\n"); } @@ -1700,11 +1701,12 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (__afl_debug) { - fprintf(stderr, - "Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges) " - "after_fs=%u\n", - start, stop, (unsigned long)(stop - start), - __afl_already_initialized_forkserver); + fprintf( + stderr, + "DEBUG: Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges) " + "after_fs=%u\n", + start, stop, (unsigned long)(stop - start), + __afl_already_initialized_forkserver); } @@ -1802,7 +1804,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { u8 ignore_dso_after_fs = !!getenv("AFL_IGNORE_PROBLEMS_COVERAGE"); if (__afl_debug && ignore_dso_after_fs) { - fprintf(stderr, "Ignoring coverage from dynamically loaded code\n"); + fprintf(stderr, + "DEBUG: Ignoring coverage from dynamically loaded code\n"); } @@ -1872,7 +1875,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (__afl_debug) { fprintf(stderr, - "Done __sanitizer_cov_trace_pc_guard_init: __afl_final_loc = %u\n", + "DEBUG: Done __sanitizer_cov_trace_pc_guard_init: __afl_final_loc " + "= %u\n", __afl_final_loc); } @@ -1883,7 +1887,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (__afl_debug) { - fprintf(stderr, "Reinit shm necessary (+%u)\n", + fprintf(stderr, "DEBUG: Reinit shm necessary (+%u)\n", __afl_final_loc - __afl_map_size); } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 8ee130107b..59b16ca052 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -206,7 +206,18 @@ bool AFLdict2filePass::runOnModule(Module &M) { ptr = getenv("AFL_LLVM_DICT2FILE"); - if (!ptr || *ptr != '/') + if (!ptr) { + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); + return PA; +#else + return true; +#endif + + } + + if (*ptr != '/') FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr); of.open(ptr, std::ofstream::out | std::ofstream::app); diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index bca1f92785..9cd1dc59cf 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -90,7 +90,7 @@ class CmpLogInstructions : public ModulePass { #if LLVM_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index c3fbed8dfa..54e9ddf3ed 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -85,7 +85,7 @@ class CmpLogRoutines : public ModulePass { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 38de669d3e..01da6da7f6 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -85,7 +85,7 @@ class CmplogSwitches : public ModulePass { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR < 4 const char *getPassName() const override { diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index dcd896529e..e3dfea0d0a 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -84,7 +84,7 @@ class SplitSwitchesTransform : public ModulePass { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index b459eb7b35..1919ae26bf 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -771,8 +771,8 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #include "/usr/include/malloc.h" #else /* HAVE_USR_INCLUDE_MALLOC_H */ #ifndef STRUCT_MALLINFO_DECLARED - /* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is - * defined */ + /* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is + * defined */ #define _STRUCT_MALLINFO #define STRUCT_MALLINFO_DECLARED 1 struct mallinfo { @@ -1660,10 +1660,10 @@ extern size_t getpagesize(); #define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) /* the number of bytes to offset an address to align it */ - #define align_offset(A) \ - ((((size_t)(A)&CHUNK_ALIGN_MASK) == 0) \ - ? 0 \ - : ((MALLOC_ALIGNMENT - ((size_t)(A)&CHUNK_ALIGN_MASK)) & \ + #define align_offset(A) \ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0) \ + ? 0 \ + : ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & \ CHUNK_ALIGN_MASK)) /* -------------------------- MMAP preliminaries ------------------------- */ @@ -1715,10 +1715,10 @@ static FORCEINLINE int unixmunmap(void *ptr, size_t size) { #define MUNMAP_DEFAULT(a, s) unixmunmap((a), (s)) #else /* MAP_ANONYMOUS */ - /* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. - */ + /* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. + */ #define MMAP_FLAGS (MAP_PRIVATE) static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ #define MMAP_DEFAULT(s) \ @@ -1965,7 +1965,7 @@ static FORCEINLINE void x86_clear_lock(int *sl) { #endif /* ... gcc spins locks ... */ - /* How to yield for a spin lock */ + /* How to yield for a spin lock */ #define SPINS_PER_YIELD 63 #if defined(_MSC_VER) #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ @@ -2008,11 +2008,11 @@ static MLOCK_T malloc_global_mutex = 0; #define CURRENT_THREAD GetCurrentThreadId() #define EQ_OWNER(X, Y) ((X) == (Y)) #else - /* - Note: the following assume that pthread_t is a type that can be - initialized to (casted) zero. If this is not the case, you will need - to somehow redefine these or not use spin locks. - */ + /* + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need + to somehow redefine these or not use spin locks. + */ #define THREAD_ID_T pthread_t #define CURRENT_THREAD pthread_self() #define EQ_OWNER(X, Y) pthread_equal(X, Y) @@ -2169,7 +2169,7 @@ static int pthread_init_lock(MLOCK_T *lk) { #endif /* ... lock types ... */ - /* Common code for all lock types */ + /* Common code for all lock types */ #define USE_LOCK_BIT (2U) #ifndef ACQUIRE_MALLOC_GLOBAL_LOCK @@ -3077,7 +3077,7 @@ static size_t traverse_and_check(mstate m); /* The size of the smallest chunk held in bin with index i */ #define minsize_for_tree_index(i) \ ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i)&SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) /* ------------------------ Operations on bin maps ----------------------- */ @@ -3245,7 +3245,7 @@ static size_t traverse_and_check(mstate m); #else /* FOOTERS */ - /* Set foot of inuse chunk to be xor of mstate and seed */ + /* Set foot of inuse chunk to be xor of mstate and seed */ #define mark_inuse_foot(M, p, s) \ (((mchunkptr)((char *)(p) + (s)))->prev_foot = \ ((size_t)(M) ^ mparams.magic)) diff --git a/qemu_mode/libqasan/malloc.c b/qemu_mode/libqasan/malloc.c index d2db3856a8..4448f480c2 100644 --- a/qemu_mode/libqasan/malloc.c +++ b/qemu_mode/libqasan/malloc.c @@ -80,8 +80,8 @@ static unsigned char __tmp_alloc_zone[TMP_ZONE_SIZE]; #else // From dlmalloc.c -void *dlmalloc(size_t); -void dlfree(void *); +void *dlmalloc(size_t); +void dlfree(void *); #define backend_malloc dlmalloc #define backend_free dlfree diff --git a/src/afl-cc.c b/src/afl-cc.c index 037a5c30cb..c3c677b47c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1144,19 +1144,23 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { + if (!getenv("AFL_LLVM_NO_RPATH")) { - cc_params[cc_par_cnt++] = "-Wl,-rpath"; - cc_params[cc_par_cnt++] = libdir; + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + u8 *libdir = strdup(LLVM_LIBDIR); + if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { - } else { + cc_params[cc_par_cnt++] = "-Wl,-rpath"; + cc_params[cc_par_cnt++] = libdir; + + } else { - free(libdir); + free(libdir); + + } } @@ -2289,7 +2293,9 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CTX: use full context sensitive coverage (for " "CLASSIC)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC)\n"); + "CLASSIC)\n" + " AFL_LLVM_NO_RPATH: disable rpath setting for custom LLVM " + "locations\n"); #ifdef AFL_CLANG_FLTO if (have_lto) diff --git a/src/afl-common.c b/src/afl-common.c index b4143a1b9e..ba498b3b04 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -98,12 +98,27 @@ void set_sanitizer_defaults() { } /* LSAN does not support abort_on_error=1. (is this still true??) */ + u8 should_detect_leaks = 0; if (!have_lsan_options) { u8 buf[2048] = ""; if (!have_san_options) { strcpy(buf, default_options); } - strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + if (have_asan_options) { + + if (NULL != strstr(have_asan_options, "detect_leaks=0")) { + + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); + + } else { + + should_detect_leaks = 1; + strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:"); + + } + + } + setenv("LSAN_OPTIONS", buf, 1); } @@ -112,7 +127,15 @@ void set_sanitizer_defaults() { if (!have_lsan_options) { - strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + if (should_detect_leaks) { + + strcat(default_options, "detect_leaks=1:malloc_context_size=30:"); + + } else { + + strcat(default_options, "detect_leaks=0:malloc_context_size=0:"); + + } } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d76158ced5..568c527442 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -866,7 +866,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( - afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, afl->fsrv.nyx_aux_string_len); + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, + afl->fsrv.nyx_aux_string_len); ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index f6de11ae50..905431d1e9 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -176,6 +176,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, afl->extras = afl_realloc((void **)&afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data)); + char *hexdigits = "0123456789abcdef"; + if (unlikely(!afl->extras)) { PFATAL("alloc"); } wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr); @@ -184,13 +186,12 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, while (*lptr) { - char *hexdigits = "0123456789abcdef"; - switch (*lptr) { case 1 ... 31: case 128 ... 255: WARNF("Non-printable characters in line %u.", cur_line); + ++lptr; continue; break; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2003be1ffd..67dafda8d0 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -577,13 +577,13 @@ u8 fuzz_one_original(afl_state_t *afl) { * SIMPLE BITFLIP (+dictionary construction) * *********************************************/ -#define FLIP_BIT(_ar, _b) \ - do { \ - \ - u8 *_arf = (u8 *)(_ar); \ - u32 _bf = (_b); \ - _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \ - \ +#define FLIP_BIT(_ar, _b) \ + do { \ + \ + u8 *_arf = (u8 *)(_ar); \ + u32 _bf = (_b); \ + _arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \ + \ } while (0) /* Single walking bit. */ @@ -1894,6 +1894,7 @@ u8 fuzz_one_original(afl_state_t *afl) { LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { if (el->afl_custom_fuzz) { + havoc_queued = afl->queued_items; afl->current_custom_fuzz = el; afl->stage_name = el->name_short; @@ -2216,7 +2217,7 @@ u8 fuzz_one_original(afl_state_t *afl) { } - retry_havoc_step : { + retry_havoc_step: { u32 r = rand_below(afl, rand_max), item; @@ -3703,13 +3704,13 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { * SIMPLE BITFLIP (+dictionary construction) * *********************************************/ -#define FLIP_BIT(_ar, _b) \ - do { \ - \ - u8 *_arf = (u8 *)(_ar); \ - u32 _bf = (_b); \ - _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \ - \ +#define FLIP_BIT(_ar, _b) \ + do { \ + \ + u8 *_arf = (u8 *)(_ar); \ + u32 _bf = (_b); \ + _arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \ + \ } while (0) /* Single walking bit. */ diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index db4991dbf8..86e7f1cf16 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -40,7 +40,7 @@ enum { IS_FP = 8, // is a floating point, not an integer /* --- below are internal settings, not from target cmplog */ IS_FP_MOD = 16, // arithemtic changed floating point - IS_INT_MOD = 32, // arithmetic changed interger + IS_INT_MOD = 32, // arithmetic changed integer IS_TRANSFORM = 64 // transformed integer }; @@ -775,6 +775,13 @@ static u32 to_base64(u8 *src, u8 *dst, u32 dst_len) { } +#ifdef WORD_SIZE_64 +static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, + u128 pattern, u128 repl, u128 o_pattern, + u128 changed_val, u8 attr, u32 idx, + u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, + u32 len, u8 do_reverse, u8 lvl, u8 *status); +#endif static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -807,6 +814,29 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, hshape, attr); */ + u8 bytes; + + switch (hshape) { + + case 0: + case 1: + bytes = 1; + break; + case 2: + bytes = 2; + break; + case 3: + case 4: + bytes = 4; + break; + default: + bytes = 8; + + } + + // necessary for preventing heap access overflow + bytes = MIN(bytes, len - idx); + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { @@ -895,29 +925,6 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) { u64 b_val, o_b_val, mask; - u8 bytes; - - switch (hshape) { - - case 0: - case 1: - bytes = 1; - break; - case 2: - bytes = 2; - break; - case 3: - case 4: - bytes = 4; - break; - default: - bytes = 8; - - } - - // necessary for preventing heap access overflow - bytes = MIN(bytes, len - idx); - switch (bytes) { case 0: // cannot happen @@ -1285,6 +1292,135 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + // If 'S' is set for cmplog mode then we try a scale encoding of the value. + // Currently we can only handle bytes up to 1 << 55 on 32 bit and 1 << 119 + // on 64 bit systems. + // Caveat: This implementation here works only on little endian systems. + + if (attr < IS_FP && (afl->cmplog_enable_scale || lvl >= LVL3) && + repl == changed_val) { + + u8 do_call = 1; + u64 new_val = repl << 2; + u32 ilen = 0; + + if (changed_val <= 255) { + + ilen = 1; + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + ilen = 2; + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + ilen = 4; + + } else { + +#ifndef WORD_SIZE_64 + if (repl <= 0x00ffffffffffffff { + + new_val = repl << 8; + u8 scale_len = 0; + u64 tmp_val = repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + ilen = scale_len + 5; + + } else { + + do_call = 0; + + } + +#else + { + + u128 new_vall = ((u128)repl) << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_vall += (scale_len << 2) + 3; + ilen = scale_len + 5; + + if (ilen <= its_len) { + + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_vall, ilen); + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_vall, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; + + do_call = 0; + + } + +#endif + + } + + if (do_call) { + + if (ilen <= its_len) { + + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } +#ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } +#endif + memcpy(buf + idx, tmpbuf, ilen); + + }; + + } + + } + // here we add and subract 1 from the value, but only if it is not an // == or != comparison // Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float @@ -1551,6 +1687,77 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h, } + // Scale encoding only works on little endian systems + + if (attr < IS_FP && attr < 32 && + (afl->cmplog_enable_scale || lvl >= LVL3)) { + + u128 new_val = repl << 2; + u128 max_scale = (u128)1 << 120; + u32 ilen = 0; + u8 do_call = 1; + + if (new_val <= 255) { + + ilen = 1; + + } else if (new_val <= 65535) { + + new_val += 1; // two byte mode + ilen = 2; + + } else if (new_val <= 4294967295) { + + new_val += 2; // four byte mode + ilen = 4; + + } else if (repl < max_scale) { + + new_val = (u128)repl << 8; + u8 scale_len = 0; + u128 tmp_val = (u128)repl; + while (tmp_val) { + + tmp_val >>= 8; + ++scale_len; + + } // scale_len will be >= 4; + + if (scale_len >= 4) { + + scale_len -= 4; + + } else { + + scale_len = 0; + + }; + + new_val += (scale_len << 2) + 3; + ilen = scale_len + 5; + + } else { + + do_call = 0; + + } + + if (do_call && ilen <= its_len) { + + u8 tmpbuf[32]; + memcpy(tmpbuf, buf + idx, ilen); + memcpy(buf + idx, (char *)&new_val, ilen); + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + #ifdef CMPLOG_COMBINE + if (*status == 1) { memcpy(cbuf + idx, (char *)&new_val, ilen); } + #endif + memcpy(buf + idx, tmpbuf, ilen); + + }; + + } + } return 0; @@ -1621,7 +1828,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) { for (k = 0; k < size; ++k) { #else - u32 off = 16 - size; + u32 off = 16 - size; for (k = 16 - size; k < 16; ++k) { #endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2538f4a4b6..becad3511f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -486,6 +486,22 @@ int main(int argc, char **argv_orig, char **envp) { struct timeval tv; struct timezone tz; + doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; + + if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) { + + printf("afl-fuzz" VERSION "\n"); + exit(0); + + } + + if (argc > 1 && strcmp(argv_orig[1], "--help") == 0) { + + usage(argv_orig[0], 1); + exit(0); + + } + #if defined USE_COLOR && defined ALWAYS_COLORED if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) { @@ -515,8 +531,6 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-fuzz" VERSION cRST " based on afl by Michal Zalewski and a large online community\n"); - doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; - gettimeofday(&tv, &tz); rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid()); @@ -1152,6 +1166,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'A': afl->cmplog_enable_arith = 1; break; + case 's': + case 'S': + afl->cmplog_enable_scale = 1; + break; case 't': case 'T': afl->cmplog_enable_transform = 1; diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index b21f30681d..f4024799c3 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -55,7 +55,7 @@ #elif defined __HAIKU__ #include #elif defined __sun - /* For map addresses the old struct is enough */ +/* For map addresses the old struct is enough */ #include #include #endif @@ -168,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__ @@ -209,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__