diff options
-rw-r--r-- | TODO.md | 1 | ||||
-rw-r--r-- | docs/Changelog.md | 2 | ||||
-rw-r--r-- | docs/fuzzing_expert.md | 2 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 4 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm32.c | 2 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm64.c | 1 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x64.c | 54 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x86.c | 1 | ||||
-rw-r--r-- | frida_mode/src/main.c | 7 | ||||
-rw-r--r-- | frida_mode/src/prefetch.c | 6 | ||||
-rw-r--r-- | frida_mode/src/seccomp/seccomp_callback.c | 32 | ||||
-rw-r--r-- | frida_mode/src/seccomp/seccomp_filter.c | 6 | ||||
-rw-r--r-- | include/envs.h | 1 | ||||
-rw-r--r-- | instrumentation/SanitizerCoverageLTO.so.cc | 3 | ||||
-rw-r--r-- | instrumentation/SanitizerCoveragePCGUARD.so.cc | 3 | ||||
-rw-r--r-- | instrumentation/afl-llvm-pass.so.cc | 3 | ||||
-rw-r--r-- | qemu_mode/libcompcov/libcompcov.so.c | 25 | ||||
-rw-r--r-- | src/afl-as.c | 1 | ||||
-rw-r--r-- | src/afl-cc.c | 9 | ||||
-rw-r--r-- | utils/aflpp_driver/aflpp_qemu_driver.c | 2 |
20 files changed, 106 insertions, 59 deletions
diff --git a/TODO.md b/TODO.md index 1d4270b4..30676312 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## TODO + - AFL_USE_TSAN to docs/env_variables.md after work over - screen update during input2stage - better autodetection of shifting runtime timeout values - Update afl->pending_not_fuzzed for MOpt diff --git a/docs/Changelog.md b/docs/Changelog.md index 04b2fb2e..cfeb8cc1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,7 +26,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - Prevent accidently killing non-afl/fuzz services when aborting afl-showmap and other tools. - afl-cc: + - support llvm IR select instrumentation for default PCGUARD and LTO - fix for shared linking on MacOS + - added AFL_USE_TSAN thread sanitizer support - llvm and LTO mode modified to work with new llvm 14-dev (again) - added the very good grammar mutator "GramaTron" to the custom_mutators diff --git a/docs/fuzzing_expert.md b/docs/fuzzing_expert.md index 96193f88..44ebade4 100644 --- a/docs/fuzzing_expert.md +++ b/docs/fuzzing_expert.md @@ -149,6 +149,8 @@ The following sanitizers have built-in support in AFL++: vulnerabilities - which is however one of the most important and dangerous C++ memory corruption classes! Enabled with `export AFL_USE_CFISAN=1` before compiling. + * TSAN = Thread SANitizer, finds thread race conditions. + Enabled with `export AFL_USE_TSAN=1` before compiling. * LSAN = Leak SANitizer, finds memory leaks in a program. This is not really a security issue, but for developers this can be very valuable. Note that unlike the other sanitizers above this needs diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 81d85aa1..eeebe545 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -347,8 +347,8 @@ void instrument_init(void) { #else tid = syscall(SYS_gettid); #endif - instrument_hash_seed = g_get_monotonic_time() ^ - (((guint64)getpid()) << 32) ^ tid; + instrument_hash_seed = + g_get_monotonic_time() ^ (((guint64)getpid()) << 32) ^ tid; } diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 4b0a648e..395d56c1 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -23,7 +23,9 @@ void instrument_coverage_optimize(const cs_insn * instr, } void instrument_coverage_optimize_init(void) { + WARNF("Optimized coverage not supported on this architecture"); + } void instrument_flush(GumStalkerOutput *output) { diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 80d1d845..358e8e6b 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -96,6 +96,7 @@ void instrument_coverage_optimize(const cs_insn * instr, } void instrument_coverage_optimize_init(void) { + } void instrument_flush(GumStalkerOutput *output) { diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index a7eb650a..19ec81b2 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -4,12 +4,12 @@ #include <sys/shm.h> #if defined(__linux__) -#if !defined(__ANDROID__) -#include <asm/prctl.h> -#include <sys/syscall.h> -#else -#include <linux/ashmem.h> -#endif + #if !defined(__ANDROID__) + #include <asm/prctl.h> + #include <sys/syscall.h> + #else + #include <linux/ashmem.h> + #endif #endif #include "frida-gumjs.h" @@ -22,13 +22,13 @@ #if defined(__x86_64__) -#ifndef MAP_FIXED_NOREPLACE - #ifdef MAP_EXCL - #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED - #else - #define MAP_FIXED_NOREPLACE MAP_FIXED + #ifndef MAP_FIXED_NOREPLACE + #ifdef MAP_EXCL + #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED + #else + #define MAP_FIXED_NOREPLACE MAP_FIXED + #endif #endif -#endif gboolean instrument_is_coverage_optimize_supported(void) { @@ -53,15 +53,12 @@ typedef struct { // 0x7ffff6cfb08b: pushf // 0x7ffff6cfb08c: push rsi // 0x7ffff6cfb08d: mov rsi,0x228 - // 0x7ffff6cfb094: xchg QWORD PTR [rip+0x3136a5],rsi # 0x7ffff700e740 - // 0x7ffff6cfb09b: xor rsi,0x451 - // 0x7ffff6cfb0a2: add BYTE PTR [rsi+0x10000],0x1 - // 0x7ffff6cfb0a9: adc BYTE PTR [rsi+0x10000],0x0 - // 0x7ffff6cfb0b0: pop rsi - // 0x7ffff6cfb0b1: popf + // 0x7ffff6cfb094: xchg QWORD PTR [rip+0x3136a5],rsi # + // 0x7ffff700e740 0x7ffff6cfb09b: xor rsi,0x451 0x7ffff6cfb0a2: add + // BYTE PTR [rsi+0x10000],0x1 0x7ffff6cfb0a9: adc BYTE PTR + // [rsi+0x10000],0x0 0x7ffff6cfb0b0: pop rsi 0x7ffff6cfb0b1: popf // 0x7ffff6cfb0b2: lea rsp,[rsp+0x80] - uint8_t lea_rsp_rsp_sub_rz[5]; uint8_t push_fq; uint8_t push_rsi; @@ -160,16 +157,25 @@ static void instrument_coverage_optimize_map_mmap(char * shm_file_path, __afl_area_ptr = NULL; -#if !defined(__ANDROID__) + #if !defined(__ANDROID__) shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); if (shm_fd == -1) { FATAL("shm_open() failed\n"); } -#else + #else shm_fd = open("/dev/ashmem", O_RDWR); if (shm_fd == -1) { FATAL("open() failed\n"); } - if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { FATAL("ioctl(ASHMEM_SET_NAME) failed"); } - if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { FATAL("ioctl(ASHMEM_SET_SIZE) failed"); } + if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { -#endif + FATAL("ioctl(ASHMEM_SET_NAME) failed"); + + } + + if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { + + FATAL("ioctl(ASHMEM_SET_SIZE) failed"); + + } + + #endif __afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0); diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index 1ff5c920..f90c01c2 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -84,6 +84,7 @@ void instrument_coverage_optimize(const cs_insn * instr, } void instrument_coverage_optimize_init(void) { + } void instrument_flush(GumStalkerOutput *output) { diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index c8183d8f..3599143b 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -126,15 +126,16 @@ static void afl_print_cmdline(void) { g_free(fname); g_free(buffer); #elif defined(__APPLE__) - int idx; + int idx; char **argv = *_NSGetArgv(); - int nargv = *_NSGetArgc(); + int nargv = *_NSGetArgc(); - for (idx = 0; idx < nargv; idx ++) { + for (idx = 0; idx < nargv; idx++) { OKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]); } + #endif } diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index c30ca65c..1ddbd5ed 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -44,8 +44,8 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self, sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size; if (sizeof(gsize) + size > remaining) { return; } - gsize *dst_backpatch_size = (gsize *) - &prefetch_data->backpatch_data[prefetch_data->backpatch_size]; + gsize *dst_backpatch_size = + (gsize *)&prefetch_data->backpatch_data[prefetch_data->backpatch_size]; *dst_backpatch_size = size; prefetch_data->backpatch_size += sizeof(gsize); @@ -117,7 +117,7 @@ static void prefetch_read_patches(void) { remaining = prefetch_data->backpatch_size - offset) { gsize *src_backpatch_data = (gsize *)&prefetch_data->backpatch_data[offset]; - gsize size = *src_backpatch_data; + gsize size = *src_backpatch_data; offset += sizeof(gsize); if (prefetch_data->backpatch_size - offset < size) { diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c index 4232d842..ac0fb8bb 100644 --- a/frida_mode/src/seccomp/seccomp_callback.c +++ b/frida_mode/src/seccomp/seccomp_callback.c @@ -1,8 +1,8 @@ #if defined(__linux__) && !defined(__ANDROID__) -#if !defined(__MUSL__) - #include <execinfo.h> -#endif + #if !defined(__MUSL__) + #include <execinfo.h> + #endif #include <fcntl.h> #include "seccomp.h" @@ -16,12 +16,13 @@ static void seccomp_callback_filter(struct seccomp_notif * req, GumDebugSymbolDetails details = {0}; if (req->data.nr == SYS_OPENAT) { -#if UINTPTR_MAX == 0xffffffffffffffffu + #if UINTPTR_MAX == 0xffffffffffffffffu seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]); -#endif -#if UINTPTR_MAX == 0xffffffff + #endif + #if UINTPTR_MAX == 0xffffffff seccomp_print("SYS_OPENAT: (%s)\n", (char *)(__u32)req->data.args[1]); -#endif + #endif + } seccomp_print( @@ -31,7 +32,7 @@ static void seccomp_callback_filter(struct seccomp_notif * req, req->data.args[0], req->data.args[1], req->data.args[2], req->data.args[3], req->data.args[4], req->data.args[5]); -#if !defined(__MUSL__) + #if !defined(__MUSL__) seccomp_print("FRAMES: (%u)\n", frames->len); char **syms = backtrace_symbols(frames->items, frames->len); if (syms == NULL) { FATAL("Failed to get symbols"); } @@ -52,23 +53,24 @@ static void seccomp_callback_filter(struct seccomp_notif * req, } free(syms); -#else + #else void **syms = (void **)__builtin_frame_address(0); - void *framep = __builtin_frame_address(1); - int i = 0; + void * framep = __builtin_frame_address(1); + int i = 0; syms = framep; while (syms) { - - framep = *syms; + + framep = *syms; syms = framep; if (!syms) break; - seccomp_print("\%3d. %s\n", i ++, (char *)framep); + seccomp_print("\%3d. %s\n", i++, (char *)framep); } -#endif + + #endif resp->error = 0; resp->val = 0; diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c index 7ee5ead1..0dcc4cbb 100644 --- a/frida_mode/src/seccomp/seccomp_filter.c +++ b/frida_mode/src/seccomp/seccomp_filter.c @@ -2,9 +2,9 @@ #include <alloca.h> #include <errno.h> -#if !defined(__MUSL__) - #include <execinfo.h> -#endif + #if !defined(__MUSL__) + #include <execinfo.h> + #endif #include <linux/filter.h> #include <sys/ioctl.h> #include <sys/prctl.h> diff --git a/include/envs.h b/include/envs.h index 61267a0d..25d05539 100644 --- a/include/envs.h +++ b/include/envs.h @@ -203,6 +203,7 @@ static char *afl_environment_variables[] = { "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", + "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index ee8c317e..4e25221a 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1142,10 +1142,11 @@ bool ModuleSanitizerCoverage::instrumentModule( else { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %u locations (%u selects) without collisions (%llu " diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index be3f4f49..76bb2448 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -547,10 +547,11 @@ bool ModuleSanitizerCoverage::instrumentModule( else { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %u locations with no collisions (%s mode) of which are " diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index ecf28f31..9b7e625e 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -956,11 +956,12 @@ bool AFLCoverage::runOnModule(Module &M) { else { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", + getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %d locations (%s mode, ratio %u%%).", inst_blocks, modeline, inst_ratio); diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index 24867cda..eba3d80a 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -42,10 +42,10 @@ #endif /* !__linux__ */ #ifndef likely -# define likely(x) __builtin_expect((!!(x)),1) + #define likely(x) __builtin_expect((!!(x)), 1) #endif #ifndef unlikely -# define unlikely(x) __builtin_expect((!!(x)),0) + #define unlikely(x) __builtin_expect((!!(x)), 0) #endif /* Change this value to tune the compare coverage */ @@ -235,7 +235,12 @@ int strcmp(const char *str1, const char *str2) { int strncmp(const char *str1, const char *str2, size_t len) { - if (unlikely(!__libc_strncmp)) { __libc_strncmp = dlsym(RTLD_NEXT, "strncmp"); } + if (unlikely(!__libc_strncmp)) { + + __libc_strncmp = dlsym(RTLD_NEXT, "strncmp"); + + } + void *retaddr = __builtin_return_address(0); if (__compcov_is_in_bound(retaddr) && @@ -265,7 +270,12 @@ int strncmp(const char *str1, const char *str2, size_t len) { int strcasecmp(const char *str1, const char *str2) { - if (unlikely(!__libc_strcasecmp)) { __libc_strncasecmp = dlsym(RTLD_NEXT, "strcasecmp"); } + if (unlikely(!__libc_strcasecmp)) { + + __libc_strncasecmp = dlsym(RTLD_NEXT, "strcasecmp"); + + } + void *retaddr = __builtin_return_address(0); if (__compcov_is_in_bound(retaddr) && @@ -296,7 +306,12 @@ int strcasecmp(const char *str1, const char *str2) { int strncasecmp(const char *str1, const char *str2, size_t len) { - if (unlikely(!__libc_strncasecmp)) { __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp"); } + if (unlikely(!__libc_strncasecmp)) { + + __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp"); + + } + void *retaddr = __builtin_return_address(0); if (__compcov_is_in_bound(retaddr) && diff --git a/src/afl-as.c b/src/afl-as.c index 7119d630..774340ac 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -521,6 +521,7 @@ static void add_instrumentation(void) { getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : "", getenv("AFL_USE_LSAN") ? ", LSAN" : ""); diff --git a/src/afl-cc.c b/src/afl-cc.c index e7f08aac..3837459b 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -857,6 +857,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-fsanitize=undefined"; cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error"; cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all"; + cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + + } + + if (getenv("AFL_USE_TSAN")) { + + cc_params[cc_par_cnt++] = "-fsanitize=thread"; + cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; } @@ -1814,6 +1822,7 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_CFISAN: activate control flow sanitizer\n" " AFL_USE_MSAN: activate memory sanitizer\n" " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" + " AFL_USE_TSAN: activate thread sanitizer\n" " AFL_USE_LSAN: activate leak-checker sanitizer\n"); if (have_gcc_plugin) diff --git a/utils/aflpp_driver/aflpp_qemu_driver.c b/utils/aflpp_driver/aflpp_qemu_driver.c index 99a4c9a8..e47df1e6 100644 --- a/utils/aflpp_driver/aflpp_qemu_driver.c +++ b/utils/aflpp_driver/aflpp_qemu_driver.c @@ -22,7 +22,7 @@ int main(int argc, char **argv) { if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv); // Do any other expensive one-time initialization here. - if (getenv("AFL_QEMU_DRIVER_NO_HOOK")) { + if (getenv("AFL_QEMU_DRIVER_NO_HOOK") || getenv("AFL_FRIDA_DRIVER_NO_HOOK")) { afl_qemu_driver_stdin_input(); |