From fced3e00cedf1fe4a100c20dc64ee7e4f3bc3223 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 29 Apr 2020 20:44:30 +0200 Subject: wip: afl-untracer --- examples/afl_untracer/afl-untracer.c | 581 +++++++++++++++++++++++++++++++++++ 1 file changed, 581 insertions(+) create mode 100644 examples/afl_untracer/afl-untracer.c (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c new file mode 100644 index 00000000..112573e2 --- /dev/null +++ b/examples/afl_untracer/afl-untracer.c @@ -0,0 +1,581 @@ +/* + american fuzzy lop++ - afl-untracer skeleton example + --------------------------------------------------- + + Written by Marc Heuse + + Copyright 2019-2020 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: + + http://www.apache.org/licenses/LICENSE-2.0 + + + HOW-TO + ====== + + You only need to change the following: + + 1. decide if you want to receive data from stdin [DEFAULT] or file(name) + -> use_stdin = 0 if via file, and what the maximum input size is + 2. dl load the library you want to fuzz, lookup the functions you need + and setup the calls to these + 3. in the while loop you call the functions in the necessary order - + incl the cleanup. the cleanup is important! + + Just look these steps up in the code, look for "// STEP x:" + + +*/ + +#define __USE_GNU +#define _GNU_SOURCE + +#ifdef __ANDROID__ +#include "android-ashmem.h" +#endif +#include "config.h" +#include "types.h" +#include "debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(__linux__) +#include +#elif defined(__APPLE__) && defined(__LP64__) +#include +#else +#error "Unsupproted platform" +#endif + +#define MEMORY_MAP_DECREMENT 0x200000000000 +#define MAX_LIB_COUNT 128 + +#ifdef __ANDROID__ +u32 __afl_map_size = MAP_SIZE; +#else +__thread u32 __afl_map_size = MAP_SIZE; +#endif + +u8 __afl_dummy[MAP_SIZE]; +u8 *__afl_area_ptr = __afl_dummy; + +typedef struct library_list { + + u8 *name; + u64 addr_start, addr_end; + +} library_list_t; + +library_list_t liblist[MAX_LIB_COUNT]; +u32 liblist_cnt; +u32 use_stdin = 1; + +static void sigtrap_handler(int signum, siginfo_t *si, void *context); + +/* read the library information */ +void read_library_information() { + +#if defined(__linux__) + FILE *f; + u8 buf[1024], *b, *m, *e, *n; + + if ((f = fopen("/proc/self/maps", "r")) == NULL) + FATAL("cannot open /proc/self/maps"); + + fprintf(stderr, "Library list:\n"); + while (fgets(buf, sizeof(buf), f)) { + + if (strstr(buf, " r-xp ")) { + + if (liblist_cnt >= MAX_LIB_COUNT) { + + WARNF("too many libraries to old, maximum count of %d reached", + liblist_cnt); + return; + + } + + b = buf; + m = index(buf, '-'); + e = index(buf, ' '); + if ((n = rindex(buf, '/')) == NULL) n = rindex(buf, ' '); + if (n && + ((*n >= '0' && *n <= '9') || *n == '[' || *n == '{' || *n == '(')) + n = NULL; + else + n++; + if (b && m && e && n && *n) { + + *m++ = 0; + *e = 0; + if (n[strlen(n) - 1] == '\n') n[strlen(n) - 1] = 0; + + liblist[liblist_cnt].name = strdup(n); + liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); + liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); + fprintf(stderr, "%s:%x (%x-%x)\n", liblist[liblist_cnt].name, + liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end); + liblist_cnt++; + + } + + } + + } + + fprintf(stderr, "\n"); + +#endif + +} + +library_list_t *find_library(char *name) { + +#if defined(__linux__) + u32 i; + + for (i = 0; i < liblist_cnt; i++) + if (strncmp(liblist[i].name, name, strlen(name)) == 0) return &liblist[i]; +#elif defined(__APPLE__) && defined(__LP64__) + kern_return_t err; + static library_list_t lib; + + // get the list of all loaded modules from dyld + // the task_info mach API will get the address of the dyld all_image_info + // struct for the given task from which we can get the names and load + // addresses of all modules + task_dyld_info_data_t task_dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + err = task_info(mach_task_self(), TASK_DYLD_INFO, + (task_info_t)&task_dyld_info, &count); + + const struct dyld_all_image_infos *all_image_infos = + (const struct dyld_all_image_infos *)task_dyld_info.all_image_info_addr; + const struct dyld_image_info *image_infos = all_image_infos->infoArray; + + for (size_t i = 0; i < all_image_infos->infoArrayCount; i++) { + + const char * image_name = image_infos[i].imageFilePath; + mach_vm_address_t image_load_address = + (mach_vm_address_t)image_infos[i].imageLoadAddress; + if (strstr(image_name, name)) { + + lib.name = name; + lib.addr_start = (u64)image_load_address; + lib.addr_end = 0; + return &lib; + + } + + } + +#endif + + return NULL; + +} + +/* Error reporting to forkserver controller */ + +void send_forkserver_error(int error) { + + u32 status; + if (!error || error > 0xffff) return; + status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error)); + if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return; + +} + +/* SHM setup. */ + +static void __afl_map_shm(void) { + + char *id_str = getenv(SHM_ENV_VAR); + char *ptr; + + if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { + + u32 val = atoi(ptr); + if (val > 0) __afl_map_size = val; + + } + + if (__afl_map_size > MAP_SIZE) { + + if (__afl_map_size > FS_OPT_MAX_MAPSIZE) { + + fprintf(stderr, + "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to " + "be able to run this instrumented program!\n", + __afl_map_size); + if (id_str) { + + send_forkserver_error(FS_ERROR_MAP_SIZE); + exit(-1); + + } + + } else { + + fprintf(stderr, + "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to " + "be able to run this instrumented program!\n", + __afl_map_size); + + } + + } + + if (id_str) { + +#ifdef USEMMAP + const char * shm_file_path = id_str; + int shm_fd = -1; + unsigned char *shm_base = NULL; + + /* create the shared memory segment as if it was a file */ + shm_fd = shm_open(shm_file_path, O_RDWR, 0600); + if (shm_fd == -1) { + + fprintf(stderr, "shm_open() failed\n"); + send_forkserver_error(FS_ERROR_SHM_OPEN); + exit(1); + + } + + /* map the shared memory segment to the address space of the process */ + shm_base = + mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + + if (shm_base == MAP_FAILED) { + + close(shm_fd); + shm_fd = -1; + + fprintf(stderr, "mmap() failed\n"); + send_forkserver_error(FS_ERROR_MMAP); + exit(2); + + } + + __afl_area_ptr = shm_base; +#else + u32 shm_id = atoi(id_str); + + __afl_area_ptr = shmat(shm_id, 0, 0); + +#endif + + if (__afl_area_ptr == (void *)-1) { + + send_forkserver_error(FS_ERROR_SHMAT); + exit(1); + + } + + /* Write something into the bitmap so that the parent doesn't give up */ + + __afl_area_ptr[0] = 1; + + } + +} + +/* Fork server logic. */ + +static void __afl_start_forkserver(void) { + + u8 tmp[4] = {0, 0, 0, 0}; + u32 status = 0; + + if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) + status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); + if (status) status |= (FS_OPT_ENABLED); + memcpy(tmp, &status, 4); + + /* Phone home and tell the parent that we're OK. */ + + if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; + +} + +static u32 __afl_next_testcase(u8 *buf, u32 max_len) { + + s32 status, res = 0xffffff; + + /* Wait for parent by reading from the pipe. Abort if read fails. */ + if (read(FORKSRV_FD, &status, 4) != 4) return 0; + + /* we have a testcase - read it if we read from stdin */ + if (use_stdin) status = read(0, buf, max_len); + + /* report that we are starting the target */ + if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0; + + if (status < 1) + return 0; + else + return status; + +} + +static void __afl_end_testcase(void) { + + int status = 0xffffff; + + if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1); + +} + +#define SHADOW(addr) \ + ((uint32_t *)(((uintptr_t)addr & 0xfffffffffffffffc) - \ + MEMORY_MAP_DECREMENT - \ + ((uintptr_t)addr & 0x3) * 0x10000000000)) + +void setup_trap_instrumentation() { + + library_list_t *lib_base = NULL; + size_t lib_size = 0; + u8 * lib_addr; + char * line = NULL; + size_t nread, len = 0; + char * filename = getenv("AFL_UNTRACER_FILE"); + if (!filename) filename = getenv("TRAPFUZZ_FILE"); + if (!filename) FATAL("AFL_UNTRACER_FILE environment variable not set"); + + FILE *patches = fopen(filename, "r"); + if (!patches) FATAL("Couldn't open AFL_UNTRACER_FILE file %s", filename); + + // Index into the coverage bitmap for the current trap instruction. + int bitmap_index = -1; + + while ((nread = getline(&line, &len, patches)) != -1) { + + char *end = line + len; + + char *col = strchr(line, ':'); + if (col) { + + // It's a library:size pair + *col++ = 0; + + lib_base = find_library(line); + if (!lib_base) FATAL("Library %s does not appear to be loaded", line); + + // we ignore the defined lib_size + lib_size = strtoul(col, NULL, 16); +#if (__linux__) + if (lib_size < lib_base->addr_end - lib_base->addr_start) + lib_size = lib_base->addr_end - lib_base->addr_start; +#endif + if (lib_size % 0x1000 != 0) + WARNF("Invalid library size 0x%zx. Must be multiple of 0x1000", + lib_size); + + lib_addr = (u8 *)lib_base->addr_start; + + // Make library code writable. + if (mprotect((void *)lib_addr, lib_size, + PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + FATAL("Failed to mprotect library %s writable", line); + + // Create shadow memory. + for (int i = 0; i < 4; i++) { + + void *shadow_addr = SHADOW(lib_addr + i); + void *shadow = mmap(shadow_addr, lib_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0); + fprintf(stderr, "Shadow: %s %d = %p-%p for %p\n", line, i, shadow, + shadow + lib_size - 1, lib_addr); + if (shadow == MAP_FAILED) FATAL("Failed to mmap shadow memory"); + + } + + // Done, continue with next line. + continue; + + } + + // It's an offset, parse it and do the patching. + unsigned long offset = strtoul(line, NULL, 16); + if (offset > lib_size) + FATAL("Invalid offset: 0x%lx. Current library is 0x%zx bytes large", + offset, lib_size); + + bitmap_index++; + + if (bitmap_index >= __afl_map_size) + FATAL("Too many basic blocks to instrument"); + + uint32_t *shadow = SHADOW(lib_addr + offset); + if (*shadow != 0) FATAL("Potentially duplicate patch entry: 0x%lx", offset); + + // Make lookup entry in shadow memory. +#if ((defined(__APPLE__) && defined(__LP64__)) || defined(__x86_64__)) + // this is for Intel x64 + + uint8_t orig_byte = lib_addr[offset]; + *shadow = (bitmap_index << 8) | orig_byte; + lib_addr[offset] = 0xcc; // replace instruction with debug trap + fprintf(stderr, + "Patch entry: %p[%x] = %p = %02x -> SHADOW(%p) #%d -> %08x\n", + lib_addr, offset, lib_addr + offset, orig_byte, shadow, + bitmap_index, *shadow); + +#else + // this will be ARM and AARCH64 + // for ARM we will need to identify if the code is in thumb or ARM +#error "non x86_64 not supported yet" + //__arm__ + // linux thumb: 0xde01 + // linux thumb2: 0xf7f0a000 + // linux arm: 0xe7f001f0 + //__aarch64__ + // linux aarch64: 0xd4200000 +#endif + + } + + free(line); + fclose(patches); + + // Install signal handler for SIGTRAP. + struct sigaction s; + s.sa_flags = SA_SIGINFO; + s.sa_sigaction = sigtrap_handler; + sigemptyset(&s.sa_mask); + sigaction(SIGTRAP, &s, 0); + + fprintf(stderr, "Patched %u locations.\n", bitmap_index); + __afl_map_size = bitmap_index; + if (__afl_map_size % 8) __afl_map_size = (((__afl_map_size + 7) >> 3) << 3); + +} + +static void sigtrap_handler(int signum, siginfo_t *si, void *context) { + + uint64_t addr; + // Must re-execute the instruction, so decrement PC by one instruction. + ucontext_t *ctx = (ucontext_t *)context; +#if defined(__APPLE__) && defined(__LP64__) + ctx->uc_mcontext->__ss.__rip -= 1; + addr = ctx->uc_mcontext->__ss.__rip; +#elif defined(__linux__) + ctx->uc_mcontext.gregs[REG_RIP] -= 1; + addr = ctx->uc_mcontext.gregs[REG_RIP]; +#else +#error "Unsupported platform" +#endif + + fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, + si->si_addr); + + // If the trap didn't come from our instrumentation, then we probably will + // just segfault here + uint8_t *faultaddr; + if (si->si_addr) + faultaddr = (u8 *)si->si_addr - 1; + else + faultaddr = (u8 *)addr; + // u8 *loc = SHADOW(faultaddr); + fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); + uint32_t shadow = *SHADOW(faultaddr); + uint8_t orig_byte = shadow & 0xff; + uint32_t index = shadow >> 8; + + fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, + orig_byte, index); + + // Index zero is invalid so that it is still possible to catch actual trap + // instructions in instrumented libraries. + if (index == 0) abort(); + + // Restore original instruction + *faultaddr = orig_byte; + + __afl_area_ptr[index] = 128; + +} + +/* here you need to specify the parameter for the target function */ +static void *(*o_TIFFOpen)(char *filename, char *mode); +static void *(*o_TIFFClose)(u8 *file); + +int main(int argc, char *argv[]) { + + // STEP 1: use stdin or filename via commandline and set the maximum + // size for a test case + + /* by default we use stdin, but also a filename can be passed, in this + case the input is argv[1] and we have to disable stdin */ + if (argc > 1) use_stdin = 0; + + /* This is were the testcase data is written into */ + u8 buf[10000]; // this is the maximum size for a test case! set it! + + // END STEP 1 + + // STEP 2: load the library you want to fuzz and lookup the functions, + // inclusive of the cleanup functions + // NOTE: above the main() you have to define the functions! + + /* setup the target */ + void *dl = dlopen("/prg/tests/libtiff.so", RTLD_LAZY); + if (!dl) FATAL("could not find target library"); + o_TIFFOpen = dlsym(dl, "TIFFOpen"); + if (!o_TIFFOpen) FATAL("could not resolve target function from library"); + o_TIFFClose = dlsym(dl, "TIFFClose"); + if (!o_TIFFClose) FATAL("could not resolve target function from library"); + + // END STEP 2 + + /* setup instrumentation, shared memory and forkserver */ + u32 len; + read_library_information(); + setup_trap_instrumentation(); + __afl_map_shm(); + __afl_start_forkserver(); + + while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { + +// -> this still needs threading otherwise fuzzing stops when we crash + + // STEP 3: call the function to fuzz, also the functions you might + // need to call to prepare the function and - important! - + // to clean everything up + + // in this example we use the input file, not stdin! + u8 *file (*o_function)(argv[1], "wl"); + + // we have to release memory + if (file) (void)(*o_TIFFClose)(file); + + // END STEP 3 + + /* report the test case is done and wait for the next */ + __afl_end_testcase(); + + } + + return 0; + +} + -- cgit 1.4.1 From a37eca9df538a4184551244d435e027ca86ccb25 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 30 Apr 2020 16:27:31 +0200 Subject: afl-untracer - next step --- examples/afl_untracer/Makefile | 7 +- examples/afl_untracer/afl-untracer.c | 238 +++++++++++++++++++++++------------ examples/afl_untracer/libtestinstr.c | 35 ++++++ src/afl-common.c | 2 +- 4 files changed, 199 insertions(+), 83 deletions(-) create mode 100644 examples/afl_untracer/libtestinstr.c (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/Makefile b/examples/afl_untracer/Makefile index ea20ebc0..bfef8fa8 100644 --- a/examples/afl_untracer/Makefile +++ b/examples/afl_untracer/Makefile @@ -1,7 +1,10 @@ -all: afl-untracer +all: afl-untracer libtestinstr.so afl-untracer: afl-untracer.c - $(CC) -I../../include -g -o afl-untracer afl-untracer.c -ldl + $(CC) -I../../include -g -o afl-untracer afl-untracer.c -ldl -pthread + +libtestinstr.so: libtestinstr.c + $(CC) -fPIC -o libtestinstr.so -shared libtestinstr.c clean: rm -f afl-untracer *~ core diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 112573e2..420f09a2 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -67,14 +68,26 @@ #define MEMORY_MAP_DECREMENT 0x200000000000 #define MAX_LIB_COUNT 128 -#ifdef __ANDROID__ -u32 __afl_map_size = MAP_SIZE; -#else -__thread u32 __afl_map_size = MAP_SIZE; -#endif +// STEP 1: + +/* use stdin (1) or a file on the commandline (0) */ +static u32 use_stdin = 1; + +/* This is were the testcase data is written into */ +static u8 buf[10000]; // this is the maximum size for a test case! set it! -u8 __afl_dummy[MAP_SIZE]; -u8 *__afl_area_ptr = __afl_dummy; +/* if you want to use fork() then uncomment the following line. Otherwise + threads are used. The differences: + fork() pthread() + speed slow fast + coverage detailed minimal + memory leaks no problem an issue */ +//#define USE_FORK + +/* If you want to have debug output set this to 1 */ +static u32 debug = 1; + +// END STEP 1 typedef struct library_list { @@ -83,11 +96,26 @@ typedef struct library_list { } library_list_t; -library_list_t liblist[MAX_LIB_COUNT]; -u32 liblist_cnt; -u32 use_stdin = 1; +#ifdef __ANDROID__ +u32 __afl_map_size = MAP_SIZE; +u32 do_exit; +#else +__thread u32 __afl_map_size = MAP_SIZE; +__thread u32 do_exit; +#endif + +static pid_t pid = 65537; +static pthread_t __afl_thread; +static u8 __afl_dummy[MAP_SIZE]; +static u8 * __afl_area_ptr = __afl_dummy; +static u8 * inputfile; // this will point to argv[1] +static u32 len; + +static library_list_t liblist[MAX_LIB_COUNT]; +static u32 liblist_cnt; static void sigtrap_handler(int signum, siginfo_t *si, void *context); +static void fuzz(); /* read the library information */ void read_library_information() { @@ -99,7 +127,7 @@ void read_library_information() { if ((f = fopen("/proc/self/maps", "r")) == NULL) FATAL("cannot open /proc/self/maps"); - fprintf(stderr, "Library list:\n"); + if (debug) fprintf(stderr, "Library list:\n"); while (fgets(buf, sizeof(buf), f)) { if (strstr(buf, " r-xp ")) { @@ -130,9 +158,10 @@ void read_library_information() { liblist[liblist_cnt].name = strdup(n); liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); - fprintf(stderr, "%s:%x (%x-%x)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end); + if (debug) + fprintf(stderr, "%s:%x (%x-%x)\n", liblist[liblist_cnt].name, + liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end); liblist_cnt++; } @@ -141,7 +170,7 @@ void read_library_information() { } - fprintf(stderr, "\n"); + if (debug) fprintf(stderr, "\n"); #endif @@ -300,7 +329,6 @@ static void __afl_map_shm(void) { } /* Fork server logic. */ - static void __afl_start_forkserver(void) { u8 tmp[4] = {0, 0, 0, 0}; @@ -312,36 +340,46 @@ static void __afl_start_forkserver(void) { memcpy(tmp, &status, 4); /* Phone home and tell the parent that we're OK. */ - - if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; + if (write(FORKSRV_FD + 1, tmp, 4) != 4) do_exit = 1; + // fprintf(stderr, "write0 %d\n", do_exit); } static u32 __afl_next_testcase(u8 *buf, u32 max_len) { - s32 status, res = 0xffffff; + s32 status; /* Wait for parent by reading from the pipe. Abort if read fails. */ - if (read(FORKSRV_FD, &status, 4) != 4) return 0; + if (read(FORKSRV_FD, &status, 4) != 4) do_exit = 1; + // fprintf(stderr, "read %d\n", do_exit); /* we have a testcase - read it if we read from stdin */ - if (use_stdin) status = read(0, buf, max_len); + if (use_stdin) { + + if ((status = read(0, buf, max_len)) <= 0) exit(-1); + + } else + + status = 1; + // fprintf(stderr, "stdin: %d %d\n", use_stdin, status); /* report that we are starting the target */ - if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0; + if (write(FORKSRV_FD + 1, &pid, 4) != 4) do_exit = 1; + // fprintf(stderr, "write1 %d\n", do_exit); - if (status < 1) - return 0; - else - return status; + if (!do_exit) + __afl_area_ptr[0] = 1; // otherwise afl-fuzz will exit with NOINST + return status; } static void __afl_end_testcase(void) { - int status = 0xffffff; - - if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1); + s32 res = 0xffffff; + if (write(FORKSRV_FD + 1, &res, 4) != 4) do_exit = 1; + // if (write(FORKSRV_FD + 1, &pid, 4) != 4) do_exit = 1; + // fprintf(stderr, "write2 %d\n", do_exit); + if (do_exit) exit(0); } @@ -365,7 +403,7 @@ void setup_trap_instrumentation() { if (!patches) FATAL("Couldn't open AFL_UNTRACER_FILE file %s", filename); // Index into the coverage bitmap for the current trap instruction. - int bitmap_index = -1; + int bitmap_index = 0; while ((nread = getline(&line, &len, patches)) != -1) { @@ -403,8 +441,9 @@ void setup_trap_instrumentation() { void *shadow_addr = SHADOW(lib_addr + i); void *shadow = mmap(shadow_addr, lib_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0); - fprintf(stderr, "Shadow: %s %d = %p-%p for %p\n", line, i, shadow, - shadow + lib_size - 1, lib_addr); + if (debug) + fprintf(stderr, "Shadow: %s %d = %p-%p for %p\n", line, i, shadow, + shadow + lib_size - 1, lib_addr); if (shadow == MAP_FAILED) FATAL("Failed to mmap shadow memory"); } @@ -420,38 +459,39 @@ void setup_trap_instrumentation() { FATAL("Invalid offset: 0x%lx. Current library is 0x%zx bytes large", offset, lib_size); - bitmap_index++; - if (bitmap_index >= __afl_map_size) FATAL("Too many basic blocks to instrument"); uint32_t *shadow = SHADOW(lib_addr + offset); - if (*shadow != 0) FATAL("Potentially duplicate patch entry: 0x%lx", offset); + if (*shadow != 0) FATAL("Duplicate patch entry: 0x%lx", offset); - // Make lookup entry in shadow memory. + // Make lookup entry in shadow memory. #if ((defined(__APPLE__) && defined(__LP64__)) || defined(__x86_64__)) // this is for Intel x64 uint8_t orig_byte = lib_addr[offset]; *shadow = (bitmap_index << 8) | orig_byte; lib_addr[offset] = 0xcc; // replace instruction with debug trap - fprintf(stderr, - "Patch entry: %p[%x] = %p = %02x -> SHADOW(%p) #%d -> %08x\n", - lib_addr, offset, lib_addr + offset, orig_byte, shadow, - bitmap_index, *shadow); + if (debug) + fprintf(stderr, + "Patch entry: %p[%x] = %p = %02x -> SHADOW(%p) #%d -> %08x\n", + lib_addr, offset, lib_addr + offset, orig_byte, shadow, + bitmap_index, *shadow); #else - // this will be ARM and AARCH64 - // for ARM we will need to identify if the code is in thumb or ARM + // this will be ARM and AARCH64 + // for ARM we will need to identify if the code is in thumb or ARM #error "non x86_64 not supported yet" - //__arm__ - // linux thumb: 0xde01 - // linux thumb2: 0xf7f0a000 - // linux arm: 0xe7f001f0 - //__aarch64__ - // linux aarch64: 0xd4200000 + //__arm__ + // linux thumb: 0xde01 + // linux thumb2: 0xf7f0a000 + // linux arm: 0xe7f001f0 + //__aarch64__ + // linux aarch64: 0xd4200000 #endif + bitmap_index++; + } free(line); @@ -464,7 +504,7 @@ void setup_trap_instrumentation() { sigemptyset(&s.sa_mask); sigaction(SIGTRAP, &s, 0); - fprintf(stderr, "Patched %u locations.\n", bitmap_index); + if (debug) fprintf(stderr, "Patched %u locations.\n", bitmap_index); __afl_map_size = bitmap_index; if (__afl_map_size % 8) __afl_map_size = (((__afl_map_size + 7) >> 3) << 3); @@ -485,8 +525,9 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { #error "Unsupported platform" #endif - fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, - si->si_addr); + if (debug) + fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, + si->si_addr); // If the trap didn't come from our instrumentation, then we probably will // just segfault here @@ -496,13 +537,15 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { else faultaddr = (u8 *)addr; // u8 *loc = SHADOW(faultaddr); - fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); + if (debug) + fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); uint32_t shadow = *SHADOW(faultaddr); uint8_t orig_byte = shadow & 0xff; uint32_t index = shadow >> 8; - fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, - orig_byte, index); + if (debug) + fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, + orig_byte, index); // Index zero is invalid so that it is still possible to catch actual trap // instructions in instrumented libraries. @@ -516,62 +559,77 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { } /* here you need to specify the parameter for the target function */ -static void *(*o_TIFFOpen)(char *filename, char *mode); -static void *(*o_TIFFClose)(u8 *file); +static void *(*o_function)(u8 *buf, int len); int main(int argc, char *argv[]) { - // STEP 1: use stdin or filename via commandline and set the maximum - // size for a test case + pid = getpid(); + if (getenv("AFL_DEBUG")) debug = 1; /* by default we use stdin, but also a filename can be passed, in this case the input is argv[1] and we have to disable stdin */ - if (argc > 1) use_stdin = 0; + if (argc > 1) { - /* This is were the testcase data is written into */ - u8 buf[10000]; // this is the maximum size for a test case! set it! + use_stdin = 0; + inputfile = argv[1]; - // END STEP 1 + } // STEP 2: load the library you want to fuzz and lookup the functions, // inclusive of the cleanup functions // NOTE: above the main() you have to define the functions! /* setup the target */ - void *dl = dlopen("/prg/tests/libtiff.so", RTLD_LAZY); + void *dl = dlopen("./libtestinstr.so", RTLD_LAZY); if (!dl) FATAL("could not find target library"); - o_TIFFOpen = dlsym(dl, "TIFFOpen"); - if (!o_TIFFOpen) FATAL("could not resolve target function from library"); - o_TIFFClose = dlsym(dl, "TIFFClose"); - if (!o_TIFFClose) FATAL("could not resolve target function from library"); + o_function = dlsym(dl, "testinstr"); + if (!o_function) FATAL("could not resolve target function from library"); // END STEP 2 /* setup instrumentation, shared memory and forkserver */ - u32 len; read_library_information(); setup_trap_instrumentation(); __afl_map_shm(); __afl_start_forkserver(); - while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { + while (1) { -// -> this still needs threading otherwise fuzzing stops when we crash +#ifdef USE_FORK + if ((pid = fork()) == -1) PFATAL("fork failed"); + if (pid) { - // STEP 3: call the function to fuzz, also the functions you might - // need to call to prepare the function and - important! - - // to clean everything up + u32 status; + if (waitpid(pid, &status, 0) < 0) exit(1); - // in this example we use the input file, not stdin! - u8 *file (*o_function)(argv[1], "wl"); + } else { - // we have to release memory - if (file) (void)(*o_TIFFClose)(file); +#endif - // END STEP 3 + pid = getpid(); + while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { - /* report the test case is done and wait for the next */ - __afl_end_testcase(); +#ifdef USE_FORK + fuzz(); +#else + if (pthread_create(&__afl_thread, NULL, (void *)fuzz, NULL) != 0) + PFATAL("cannot create thread"); + pthread_join(__afl_thread, NULL); +#endif + + /* report the test case is done and wait for the next */ + __afl_end_testcase(); +#ifdef USE_FORK + exit(0); +#endif + + } + +#ifdef USE_FORK + + } + +#endif } @@ -579,3 +637,23 @@ int main(int argc, char *argv[]) { } +static void fuzz() { + + // STEP 3: call the function to fuzz, also the functions you might + // need to call to prepare the function and - important! - + // to clean everything up + + // in this example we use the input file, not stdin! + (*o_function)(buf, len); + + // normally you also need to cleanup + //(*o_LibFree)(foo); + + // END STEP 3 + +#ifndef USE_FORK + pthread_exit(NULL); +#endif + +} + diff --git a/examples/afl_untracer/libtestinstr.c b/examples/afl_untracer/libtestinstr.c new file mode 100644 index 00000000..b21c3db5 --- /dev/null +++ b/examples/afl_untracer/libtestinstr.c @@ -0,0 +1,35 @@ +/* + american fuzzy lop++ - a trivial program to test the build + -------------------------------------------------------- + Originally written by Michal Zalewski + Copyright 2014 Google Inc. All rights reserved. + Copyright 2019-2020 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: + http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +void testinstr(char *buf, int len) { + + if (len < 1) + return; + buf[len] = 0; + + // we support three input cases + if (buf[0] == '0') + printf("Looks like a zero to me!\n"); + else if (buf[0] == '1') + printf("Pretty sure that is a one!\n"); + else + printf("Neither one or zero? How quaint!\n"); + +} diff --git a/src/afl-common.c b/src/afl-common.c index dda62219..8f21ad94 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -71,7 +71,7 @@ char *afl_environment_variables[] = { "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", - "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1 From efa9df24c2a5f97c212a5a22dda19dcbbab0b5de Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 30 Apr 2020 17:59:59 +0200 Subject: afl-untracer completed --- docs/Changelog.md | 2 + examples/afl_network_proxy/README.md | 11 +++ examples/afl_network_proxy/afl-network-client.c | 23 +++--- examples/afl_network_proxy/afl-network-server.c | 2 + examples/afl_untracer/Makefile | 2 +- examples/afl_untracer/README.md | 7 +- examples/afl_untracer/afl-untracer.c | 96 +++++++++++-------------- examples/afl_untracer/patches.txt | 23 ++++++ include/forkserver.h | 1 + src/afl-forkserver.c | 14 ++-- 10 files changed, 106 insertions(+), 75 deletions(-) create mode 100644 examples/afl_untracer/patches.txt (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index faf015c6..565bee72 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -31,6 +31,8 @@ sending a mail to . - added examples/afl_network_proxy which allows to fuzz a target over the network (not fuzzing tcp/ip services but running afl-fuzz on one system and the target being on an embedded device) + - added examples/afl_untracer which does a binary-only fuzzing with the + modifications done in memory - added examples/afl_proxy which can be easily used to fuzz and instrument non-standard things - all: diff --git a/examples/afl_network_proxy/README.md b/examples/afl_network_proxy/README.md index 65012601..c33096be 100644 --- a/examples/afl_network_proxy/README.md +++ b/examples/afl_network_proxy/README.md @@ -20,6 +20,7 @@ e.g.: ``` $ afl-network-server -i 1111 -m 25M -t 1000 -- /bin/target -f @@ ``` + ### on the fuzzing master Just run afl-fuzz with your normal options, however the target should be @@ -42,3 +43,13 @@ either. Note that also the outgoing interface can be specified with a '%' for ## how to compile and install `make && sudo make install` + +## Future + +It would be much faster and more effective if `afl-network-server` does not +send the map data back (64kb or more) but the checksum that `afl-fuzz` would +generate. This change however would make it incompatible with existing +afl spinoffs. + +But in the future this will be implemented and supported as a compile option. + diff --git a/examples/afl_network_proxy/afl-network-client.c b/examples/afl_network_proxy/afl-network-client.c index ede2ff8d..53512286 100644 --- a/examples/afl_network_proxy/afl-network-client.c +++ b/examples/afl_network_proxy/afl-network-client.c @@ -175,7 +175,7 @@ static void __afl_start_forkserver(void) { static u32 __afl_next_testcase(u8 *buf, u32 max_len) { - s32 status, res = 0xffffff; + s32 status, res = 0x0fffffff; // res is a dummy pid /* Wait for parent by reading from the pipe. Abort if read fails. */ if (read(FORKSRV_FD, &status, 4) != 4) return 0; @@ -193,9 +193,7 @@ static u32 __afl_next_testcase(u8 *buf, u32 max_len) { } -static void __afl_end_testcase(void) { - - int status = 0xffffff; +static void __afl_end_testcase(int status) { if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1); @@ -273,7 +271,7 @@ int main(int argc, char *argv[]) { __afl_map_shm(); __afl_start_forkserver(); - int i = 1, j; + int i = 1, j, status, ret; // fprintf(stderr, "Waiting for first testcase\n"); while ((len = __afl_next_testcase(buf, max_len)) > 0) { @@ -281,17 +279,25 @@ int main(int argc, char *argv[]) { if (send(s, &len, 4, 0) != 4) PFATAL("sending size data %d failed", len); if (send(s, buf, len, 0) != len) PFATAL("sending test data failed"); - int received = 0, ret; + int received = 0; + while (received < 4 && + (ret = recv(s, &status + received, 4 - received, 0)) > 0) + received += ret; + if (received != 4) + FATAL("did not receive waitpid data (%d, %d)", received, ret); + // fprintf(stderr, "Received status\n"); + + int received = 0; while (received < __afl_map_size && (ret = recv(s, __afl_area_ptr + received, __afl_map_size - received, 0)) > 0) received += ret; if (received != __afl_map_size) - FATAL("did not receive valid data (%d, %d)", received, ret); + FATAL("did not receive coverage data (%d, %d)", received, ret); // fprintf(stderr, "Received coverage\n"); /* report the test case is done and wait for the next */ - __afl_end_testcase(); + __afl_end_testcase(status); // fprintf(stderr, "Waiting for next testcase %d\n", ++i); } @@ -299,4 +305,3 @@ int main(int argc, char *argv[]) { return 0; } - diff --git a/examples/afl_network_proxy/afl-network-server.c b/examples/afl_network_proxy/afl-network-server.c index 1bd37560..2f9f8c8e 100644 --- a/examples/afl_network_proxy/afl-network-server.c +++ b/examples/afl_network_proxy/afl-network-server.c @@ -579,6 +579,8 @@ int main(int argc, char **argv_orig, char **envp) { // fprintf(stderr, "received %u\n", in_len); run_target(fsrv, use_argv, in_data, in_len, 1); + if (send(s, fsrv->child_status, 4, 0) != 4) + FATAL("could not send waitpid data"); if (send(s, fsrv->trace_bits, fsrv->map_size, 0) != fsrv->map_size) FATAL("could not send coverage data"); // fprintf(stderr, "sent result\n"); diff --git a/examples/afl_untracer/Makefile b/examples/afl_untracer/Makefile index bfef8fa8..5c525877 100644 --- a/examples/afl_untracer/Makefile +++ b/examples/afl_untracer/Makefile @@ -7,4 +7,4 @@ libtestinstr.so: libtestinstr.c $(CC) -fPIC -o libtestinstr.so -shared libtestinstr.c clean: - rm -f afl-untracer *~ core + rm -f afl-untracer libtestinstr.so *~ core diff --git a/examples/afl_untracer/README.md b/examples/afl_untracer/README.md index 90798028..d3af0ceb 100644 --- a/examples/afl_untracer/README.md +++ b/examples/afl_untracer/README.md @@ -3,9 +3,14 @@ afl-untracer is an example skeleton file which can easily be used to fuzz a closed source library. -It is faster and requires less memory than qemu_mode however it is way +It requires less memory than qemu_mode however it is way more course grained and does not provide interesting features like compcov or cmplog. Read and modify afl-untracer.c then `make` and use it as the afl-fuzz target (or even remote via afl-network-proxy). + +This idea is based on [UnTracer](https://github.com/FoRTE-Research/UnTracer-AFL) +and modified by [Trapfuzz](https://github.com/googleprojectzero/p0tools/tree/master/TrapFuzz). +This implementation is slower because the traps are not patched out with each +run, but on the other hand gives much better coverage information. diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 420f09a2..4d512356 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -76,16 +76,9 @@ static u32 use_stdin = 1; /* This is were the testcase data is written into */ static u8 buf[10000]; // this is the maximum size for a test case! set it! -/* if you want to use fork() then uncomment the following line. Otherwise - threads are used. The differences: - fork() pthread() - speed slow fast - coverage detailed minimal - memory leaks no problem an issue */ -//#define USE_FORK - -/* If you want to have debug output set this to 1 */ -static u32 debug = 1; +/* If you want to have debug output set this to 1, can also be set with + AFL_DEBUG */ +static u32 debug = 0; // END STEP 1 @@ -130,7 +123,7 @@ void read_library_information() { if (debug) fprintf(stderr, "Library list:\n"); while (fgets(buf, sizeof(buf), f)) { - if (strstr(buf, " r-xp ")) { + if (strstr(buf, " r-x")) { if (liblist_cnt >= MAX_LIB_COUNT) { @@ -159,9 +152,9 @@ void read_library_information() { liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); if (debug) - fprintf(stderr, "%s:%x (%x-%x)\n", liblist[liblist_cnt].name, + fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end); + liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end - 1); liblist_cnt++; } @@ -367,17 +360,13 @@ static u32 __afl_next_testcase(u8 *buf, u32 max_len) { if (write(FORKSRV_FD + 1, &pid, 4) != 4) do_exit = 1; // fprintf(stderr, "write1 %d\n", do_exit); - if (!do_exit) - __afl_area_ptr[0] = 1; // otherwise afl-fuzz will exit with NOINST return status; } -static void __afl_end_testcase(void) { +static void __afl_end_testcase(int status) { - s32 res = 0xffffff; - if (write(FORKSRV_FD + 1, &res, 4) != 4) do_exit = 1; - // if (write(FORKSRV_FD + 1, &pid, 4) != 4) do_exit = 1; + if (write(FORKSRV_FD + 1, &status, 4) != 4) do_exit = 1; // fprintf(stderr, "write2 %d\n", do_exit); if (do_exit) exit(0); @@ -455,6 +444,19 @@ void setup_trap_instrumentation() { // It's an offset, parse it and do the patching. unsigned long offset = strtoul(line, NULL, 16); + + // I dont know what it is. /proc//maps shows the right start address + // and the offsets generated by the python scripts are fine as well. + // And loading the library into gdb also shows the offsets generated + // by the script are correct. However when loaded via dlopen the first + // 0x1000 are skipped ... +#if defined(__linux__) + if (offset >= 0x1000) + offset -= 0x1000; + else + fprintf(stderr, "Warning: offset is < 0x1000: %x\n", offset); +#endif + if (offset > lib_size) FATAL("Invalid offset: 0x%lx. Current library is 0x%zx bytes large", offset, lib_size); @@ -482,11 +484,10 @@ void setup_trap_instrumentation() { // this will be ARM and AARCH64 // for ARM we will need to identify if the code is in thumb or ARM #error "non x86_64 not supported yet" - //__arm__ + //__arm__: // linux thumb: 0xde01 - // linux thumb2: 0xf7f0a000 // linux arm: 0xe7f001f0 - //__aarch64__ + //__aarch64__: // linux aarch64: 0xd4200000 #endif @@ -510,6 +511,8 @@ void setup_trap_instrumentation() { } +/* the signal handler for the traps / debugging interrupts + No debug output here because this would cost speed */ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { uint64_t addr; @@ -525,31 +528,25 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { #error "Unsupported platform" #endif - if (debug) - fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, - si->si_addr); + //fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, si->si_addr); // If the trap didn't come from our instrumentation, then we probably will // just segfault here uint8_t *faultaddr; - if (si->si_addr) + if (unlikely(si->si_addr)) faultaddr = (u8 *)si->si_addr - 1; else faultaddr = (u8 *)addr; - // u8 *loc = SHADOW(faultaddr); - if (debug) - fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); + //if (debug) fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); uint32_t shadow = *SHADOW(faultaddr); uint8_t orig_byte = shadow & 0xff; uint32_t index = shadow >> 8; - if (debug) - fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, - orig_byte, index); + //if (debug) fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, orig_byte, index); // Index zero is invalid so that it is still possible to catch actual trap // instructions in instrumented libraries. - if (index == 0) abort(); + if (unlikely(index == 0)) abort(); // Restore original instruction *faultaddr = orig_byte; @@ -561,6 +558,7 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { /* here you need to specify the parameter for the target function */ static void *(*o_function)(u8 *buf, int len); +/* the MAIN function */ int main(int argc, char *argv[]) { pid = getpid(); @@ -579,11 +577,11 @@ int main(int argc, char *argv[]) { // inclusive of the cleanup functions // NOTE: above the main() you have to define the functions! - /* setup the target */ void *dl = dlopen("./libtestinstr.so", RTLD_LAZY); if (!dl) FATAL("could not find target library"); o_function = dlsym(dl, "testinstr"); if (!o_function) FATAL("could not resolve target function from library"); + if (debug) fprintf(stderr, "Function address: %p\n", o_function); // END STEP 2 @@ -595,42 +593,33 @@ int main(int argc, char *argv[]) { while (1) { -#ifdef USE_FORK if ((pid = fork()) == -1) PFATAL("fork failed"); + if (pid) { u32 status; if (waitpid(pid, &status, 0) < 0) exit(1); + /* report the test case is done and wait for the next */ + __afl_end_testcase(status); } else { -#endif pid = getpid(); while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { -#ifdef USE_FORK + // in this function the fuzz magic happens, this is STEP 3 fuzz(); -#else - if (pthread_create(&__afl_thread, NULL, (void *)fuzz, NULL) != 0) - PFATAL("cannot create thread"); - pthread_join(__afl_thread, NULL); -#endif - /* report the test case is done and wait for the next */ - __afl_end_testcase(); -#ifdef USE_FORK - exit(0); -#endif + // we can use _exit which is faster because our target library + // was loaded via dlopen and there cannot have deconstructors + // registered. + _exit(0); } -#ifdef USE_FORK - } -#endif - } return 0; @@ -651,9 +640,4 @@ static void fuzz() { // END STEP 3 -#ifndef USE_FORK - pthread_exit(NULL); -#endif - } - diff --git a/examples/afl_untracer/patches.txt b/examples/afl_untracer/patches.txt new file mode 100644 index 00000000..b3063e3a --- /dev/null +++ b/examples/afl_untracer/patches.txt @@ -0,0 +1,23 @@ +libtestinstr.so:0x2000L +0x1050L +0x1063L +0x106fL +0x1078L +0x1080L +0x10a4L +0x10b0L +0x10b8L +0x10c0L +0x10c9L +0x10d7L +0x10e3L +0x10f8L +0x1100L +0x1105L +0x111aL +0x1135L +0x1143L +0x114eL +0x115cL +0x116aL +0x116bL diff --git a/include/forkserver.h b/include/forkserver.h index 3c473572..7e7784f5 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -43,6 +43,7 @@ typedef struct afl_forkserver { s32 fsrv_pid, /* PID of the fork server */ child_pid, /* PID of the fuzzed program */ + child_status, /* waitpid result for the child */ out_dir_fd; /* FD of the lock file */ s32 out_fd, /* Persistent fd for fsrv->out_file */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index d5a60077..a9e2175d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -790,8 +790,6 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, s32 res; u32 exec_ms; - int status = 0; - /* After this memset, fsrv->trace_bits[] are effectively volatile, so we must prevent any earlier operations from venturing into that territory. */ @@ -821,7 +819,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); } - exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p); + exec_ms = read_timed(fsrv->fsrv_st_fd, &fsrv->child_status, 4, timeout, stop_soon_p); if (exec_ms > timeout) { @@ -830,7 +828,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, kill(fsrv->child_pid, SIGKILL); fsrv->last_run_timed_out = 1; - if (read(fsrv->fsrv_st_fd, &status, 4) < 4) { exec_ms = 0; } + if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } } @@ -862,7 +860,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (!WIFSTOPPED(status)) { fsrv->child_pid = 0; } + if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; } fsrv->total_execs++; @@ -874,9 +872,9 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, /* Report outcome to caller. */ - if (WIFSIGNALED(status) && !*stop_soon_p) { + if (WIFSIGNALED(fsrv->child_status) && !*stop_soon_p) { - fsrv->last_kill_signal = WTERMSIG(status); + fsrv->last_kill_signal = WTERMSIG(fsrv->child_status); if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) { @@ -891,7 +889,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and must use a special exit code. */ - if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { + if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) { fsrv->last_kill_signal = 0; return FSRV_RUN_CRASH; -- cgit 1.4.1 From 59043b24ccdb15c2af3281570551990bc58e162e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 30 Apr 2020 21:29:30 +0100 Subject: afl-untracer raw freebsd support. --- examples/afl_untracer/afl-untracer.c | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 4d512356..275df320 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -61,6 +61,9 @@ #include #elif defined(__APPLE__) && defined(__LP64__) #include +#elif defined(__FreeBSD__) +#include +#include #else #error "Unsupproted platform" #endif @@ -165,6 +168,67 @@ void read_library_information() { if (debug) fprintf(stderr, "\n"); +#elif defined(__FreeBSD__) + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, -1}; + char *buf, *start, *end; + size_t miblen = sizeof(mib) / sizeof(mib[0]); + size_t len; + + if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { + + return; + + } + + len = len * 4 / 3; + + buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + if (buf == MAP_FAILED) { + + return; + + } + + if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) { + + munmap(buf, len); + return; + + } + + start = buf; + end = buf + len; + + while (start < end) { + + struct kinfo_vmentry *region = (struct kinfo_vmentry *)start; + size_t size = region->kve_structsize; + + if (size == 0) { + + break; + + } + + if ((region->kve_protection & KVME_PROT_READ) && + !(region->kve_protection & KVME_PROT_EXEC)) { + + liblist[liblist_cnt].name = region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; + liblist[liblist_cnt].addr_start = region->kve_start; + liblist[liblist_cnt].addr_end = region->kve_end; + + if (debug) { + fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, + liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end - 1); + } + + liblist_cnt++; + } + + start += size; + + } #endif } @@ -524,6 +588,9 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { #elif defined(__linux__) ctx->uc_mcontext.gregs[REG_RIP] -= 1; addr = ctx->uc_mcontext.gregs[REG_RIP]; +#elif defined(__FreeBSD__) && defined(__LP64__) + ctx->uc_mcontext.mc_rip -= 1; + addr = ctx->uc_mcontext.mc_rip; #else #error "Unsupported platform" #endif -- cgit 1.4.1 From 3cf4529f3ca50479f1f91b49be8a5e9c54d4588e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 30 Apr 2020 23:01:46 +0100 Subject: afl-untracer little change to display libraries mapping on FreeBSD. --- examples/afl_untracer/afl-untracer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 275df320..9f9ea3f1 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -169,11 +169,12 @@ void read_library_information() { if (debug) fprintf(stderr, "\n"); #elif defined(__FreeBSD__) - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, -1}; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; char *buf, *start, *end; size_t miblen = sizeof(mib) / sizeof(mib[0]); size_t len; + if (debug) fprintf(stderr, "Library list:\n"); if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { return; -- cgit 1.4.1 From cc78fb721b9abbafadde81068b8a98ffd3ef9ed2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 1 May 2020 01:11:54 +0200 Subject: code format --- examples/afl_network_proxy/afl-network-client.c | 3 +- examples/afl_untracer/afl-untracer.c | 78 ++++++++++++------------- examples/afl_untracer/libtestinstr.c | 4 +- src/afl-forkserver.c | 3 +- 4 files changed, 44 insertions(+), 44 deletions(-) (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_network_proxy/afl-network-client.c b/examples/afl_network_proxy/afl-network-client.c index b510aa14..b9cd88f0 100644 --- a/examples/afl_network_proxy/afl-network-client.c +++ b/examples/afl_network_proxy/afl-network-client.c @@ -175,7 +175,7 @@ static void __afl_start_forkserver(void) { static u32 __afl_next_testcase(u8 *buf, u32 max_len) { - s32 status, res = 0x0fffffff; // res is a dummy pid + s32 status, res = 0x0fffffff; // res is a dummy pid /* Wait for parent by reading from the pipe. Abort if read fails. */ if (read(FORKSRV_FD, &status, 4) != 4) return 0; @@ -305,3 +305,4 @@ int main(int argc, char *argv[]) { return 0; } + diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 9f9ea3f1..5338bfd5 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -155,9 +155,11 @@ void read_library_information() { liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); if (debug) - fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end - 1); + fprintf( + stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, + liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_end - 1); liblist_cnt++; } @@ -170,25 +172,17 @@ void read_library_information() { #elif defined(__FreeBSD__) int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; - char *buf, *start, *end; + char * buf, *start, *end; size_t miblen = sizeof(mib) / sizeof(mib[0]); size_t len; if (debug) fprintf(stderr, "Library list:\n"); - if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { - - return; - - } + if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) { return; } len = len * 4 / 3; buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); - if (buf == MAP_FAILED) { - - return; - - } + if (buf == MAP_FAILED) { return; } if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) { @@ -205,31 +199,33 @@ void read_library_information() { struct kinfo_vmentry *region = (struct kinfo_vmentry *)start; size_t size = region->kve_structsize; - if (size == 0) { - - break; - - } + if (size == 0) { break; } if ((region->kve_protection & KVME_PROT_READ) && !(region->kve_protection & KVME_PROT_EXEC)) { - liblist[liblist_cnt].name = region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; - liblist[liblist_cnt].addr_start = region->kve_start; - liblist[liblist_cnt].addr_end = region->kve_end; + liblist[liblist_cnt].name = + region->kve_path[0] != '\0' ? strdup(region->kve_path) : 0; + liblist[liblist_cnt].addr_start = region->kve_start; + liblist[liblist_cnt].addr_end = region->kve_end; - if (debug) { - fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, - liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, - liblist[liblist_cnt].addr_start, liblist[liblist_cnt].addr_end - 1); - } + if (debug) { + + fprintf(stderr, "%s:%x (%lx-%lx)\n", liblist[liblist_cnt].name, + liblist[liblist_cnt].addr_end - liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_start, + liblist[liblist_cnt].addr_end - 1); + + } + + liblist_cnt++; - liblist_cnt++; } start += size; } + #endif } @@ -532,7 +528,7 @@ void setup_trap_instrumentation() { uint32_t *shadow = SHADOW(lib_addr + offset); if (*shadow != 0) FATAL("Duplicate patch entry: 0x%lx", offset); - // Make lookup entry in shadow memory. + // Make lookup entry in shadow memory. #if ((defined(__APPLE__) && defined(__LP64__)) || defined(__x86_64__)) // this is for Intel x64 @@ -546,14 +542,14 @@ void setup_trap_instrumentation() { bitmap_index, *shadow); #else - // this will be ARM and AARCH64 - // for ARM we will need to identify if the code is in thumb or ARM + // this will be ARM and AARCH64 + // for ARM we will need to identify if the code is in thumb or ARM #error "non x86_64 not supported yet" - //__arm__: - // linux thumb: 0xde01 - // linux arm: 0xe7f001f0 - //__aarch64__: - // linux aarch64: 0xd4200000 + //__arm__: + // linux thumb: 0xde01 + // linux arm: 0xe7f001f0 + //__aarch64__: + // linux aarch64: 0xd4200000 #endif bitmap_index++; @@ -596,7 +592,8 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { #error "Unsupported platform" #endif - //fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, si->si_addr); + // fprintf(stderr, "TRAP at context addr = %lx, fault addr = %lx\n", addr, + // si->si_addr); // If the trap didn't come from our instrumentation, then we probably will // just segfault here @@ -605,12 +602,13 @@ static void sigtrap_handler(int signum, siginfo_t *si, void *context) { faultaddr = (u8 *)si->si_addr - 1; else faultaddr = (u8 *)addr; - //if (debug) fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); + // if (debug) fprintf(stderr, "Shadow location: %p\n", SHADOW(faultaddr)); uint32_t shadow = *SHADOW(faultaddr); uint8_t orig_byte = shadow & 0xff; uint32_t index = shadow >> 8; - //if (debug) fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", shadow, orig_byte, index); + // if (debug) fprintf(stderr, "shadow data: %x, orig_byte %02x, index %d\n", + // shadow, orig_byte, index); // Index zero is invalid so that it is still possible to catch actual trap // instructions in instrumented libraries. @@ -672,7 +670,6 @@ int main(int argc, char *argv[]) { } else { - pid = getpid(); while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { @@ -709,3 +706,4 @@ static void fuzz() { // END STEP 3 } + diff --git a/examples/afl_untracer/libtestinstr.c b/examples/afl_untracer/libtestinstr.c index b21c3db5..96b1cf21 100644 --- a/examples/afl_untracer/libtestinstr.c +++ b/examples/afl_untracer/libtestinstr.c @@ -20,8 +20,7 @@ void testinstr(char *buf, int len) { - if (len < 1) - return; + if (len < 1) return; buf[len] = 0; // we support three input cases @@ -33,3 +32,4 @@ void testinstr(char *buf, int len) { printf("Neither one or zero? How quaint!\n"); } + diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a9e2175d..c1623f22 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -819,7 +819,8 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); } - exec_ms = read_timed(fsrv->fsrv_st_fd, &fsrv->child_status, 4, timeout, stop_soon_p); + exec_ms = read_timed(fsrv->fsrv_st_fd, &fsrv->child_status, 4, timeout, + stop_soon_p); if (exec_ms > timeout) { -- cgit 1.4.1 From 33ddf6ea0e090ec2ef18dfa7c53b4dfe8130de26 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 1 May 2020 17:07:44 +0200 Subject: add ghidra script and workaround ghidra/linux/ida weirdness --- examples/afl_untracer/README.md | 4 ++ examples/afl_untracer/afl-untracer.c | 16 +---- examples/afl_untracer/ghidra_get_patchpoints.java | 84 +++++++++++++++++++++++ examples/afl_untracer/ida_get_patchpoints.py | 9 ++- 4 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 examples/afl_untracer/ghidra_get_patchpoints.java (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/README.md b/examples/afl_untracer/README.md index d3af0ceb..4ff96423 100644 --- a/examples/afl_untracer/README.md +++ b/examples/afl_untracer/README.md @@ -10,6 +10,10 @@ or cmplog. Read and modify afl-untracer.c then `make` and use it as the afl-fuzz target (or even remote via afl-network-proxy). +To generate the `patches.txt` file for your target library use the +`ida_get_patchpoints.py` script for IDA Pro or +`ghidra_get_patchpoints.java` for Ghidra. + This idea is based on [UnTracer](https://github.com/FoRTE-Research/UnTracer-AFL) and modified by [Trapfuzz](https://github.com/googleprojectzero/p0tools/tree/master/TrapFuzz). This implementation is slower because the traps are not patched out with each diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 5338bfd5..f812958c 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -506,18 +506,6 @@ void setup_trap_instrumentation() { // It's an offset, parse it and do the patching. unsigned long offset = strtoul(line, NULL, 16); - // I dont know what it is. /proc//maps shows the right start address - // and the offsets generated by the python scripts are fine as well. - // And loading the library into gdb also shows the offsets generated - // by the script are correct. However when loaded via dlopen the first - // 0x1000 are skipped ... -#if defined(__linux__) - if (offset >= 0x1000) - offset -= 0x1000; - else - fprintf(stderr, "Warning: offset is < 0x1000: %x\n", offset); -#endif - if (offset > lib_size) FATAL("Invalid offset: 0x%lx. Current library is 0x%zx bytes large", offset, lib_size); @@ -526,10 +514,12 @@ void setup_trap_instrumentation() { FATAL("Too many basic blocks to instrument"); uint32_t *shadow = SHADOW(lib_addr + offset); - if (*shadow != 0) FATAL("Duplicate patch entry: 0x%lx", offset); + if (*shadow != 0) continue; // skip duplicates // Make lookup entry in shadow memory. + #if ((defined(__APPLE__) && defined(__LP64__)) || defined(__x86_64__)) + // this is for Intel x64 uint8_t orig_byte = lib_addr[offset]; diff --git a/examples/afl_untracer/ghidra_get_patchpoints.java b/examples/afl_untracer/ghidra_get_patchpoints.java new file mode 100644 index 00000000..d341bea4 --- /dev/null +++ b/examples/afl_untracer/ghidra_get_patchpoints.java @@ -0,0 +1,84 @@ +/* ### + * IP: GHIDRA + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Find patch points for untracer tools (e.g. afl++ examples/afl_untracer) +// +// Copy to ..../Ghidra/Features/Search/ghidra_scripts/ +// Writes the results to ~/Desktop/patches.txt +// +// This is my very first Ghidra script. I am sure this could be done better. +// +//@category Search + +import ghidra.app.script.GhidraScript; +import ghidra.program.model.address.*; +import ghidra.program.model.block.*; +import ghidra.program.model.listing.*; +import ghidra.program.model.symbol.*; +import ghidra.program.model.mem.*; + +import java.io.*; + +public class ghidra_get_patchpoints extends GhidraScript { + + @Override + public void run() throws Exception { + + long segment_start = 0; + Memory memory = currentProgram.getMemory(); + MultEntSubModel model = new MultEntSubModel(currentProgram); + CodeBlockIterator subIter = model.getCodeBlocks(monitor); + BufferedWriter out = new BufferedWriter(new FileWriter(System.getProperty("user.home") + File.separator + "Desktop" + File.separator + "patches.txt")); + + while (subIter.hasNext()) { + + CodeBlock multiEntryBlock = subIter.next(); + SimpleBlockModel basicBlockModel = new SimpleBlockModel(currentProgram); + CodeBlockIterator bbIter = basicBlockModel.getCodeBlocksContaining(multiEntryBlock, monitor); + + while (bbIter.hasNext()) { + + CodeBlock basicBlock = bbIter.next(); + + if (segment_start == 0) { + + Address firstAddr = basicBlock.getFirstStartAddress(); + long firstBlockAddr = firstAddr.getAddressableWordOffset(); + MemoryBlock mb = memory.getBlock(firstAddr); + Address startAddr = mb.getStart(); + Address endAddr = mb.getEnd(); + segment_start = startAddr.getAddressableWordOffset(); + if ((firstBlockAddr - segment_start) >= 0x1000) + segment_start += 0x1000; + long segment_end = endAddr.getAddressableWordOffset(); + long segment_size = segment_end - segment_start; + if ((segment_size % 0x1000) > 0) + segment_size = (((segment_size / 0x1000) + 1) * 0x1000); + out.write(currentProgram.getName() + ":0x" + Long.toHexString(segment_size) + "\n"); + //println("Start: " + Long.toHexString(segment_start)); + //println("End: " + Long.toHexString(segment_end)); + + } + + if (basicBlock.getFirstStartAddress().getAddressableWordOffset() - segment_start > 0) + out.write("0x" + Long.toHexString(basicBlock.getFirstStartAddress().getAddressableWordOffset() - segment_start) + "\n"); + + } + } + + out.close(); + + } +} diff --git a/examples/afl_untracer/ida_get_patchpoints.py b/examples/afl_untracer/ida_get_patchpoints.py index 5a79658d..c7e8f899 100644 --- a/examples/afl_untracer/ida_get_patchpoints.py +++ b/examples/afl_untracer/ida_get_patchpoints.py @@ -24,6 +24,8 @@ for seg_ea in idautils.Segments(): start = idc.get_segm_start(seg_ea) end = idc.get_segm_end(seg_ea) + first = 0 + subtract_addr = 0 #print("Start: " + hex(start) + " End: " + hex(end)) for func_ea in idautils.Functions(start, end): f = idaapi.get_func(func_ea) @@ -31,8 +33,13 @@ for seg_ea in idautils.Segments(): continue for block in idaapi.FlowChart(f): if start <= block.start_ea < end: + if first == 0: + if block.start_ea >= 0x1000: + subtract_addr = 0x1000 + first = 1 + max_offset = max(max_offset, block.start_ea) - patchpoints.add(block.start_ea) + patchpoints.add(block.start_ea - subtract_addr) #else: # print("Warning: broken CFG?") -- cgit 1.4.1 From 128e4d55651731a876cd33bee900021cf61ab39b Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 5 May 2020 20:23:16 +0200 Subject: more typos fixed --- examples/afl_untracer/afl-untracer.c | 4 ++-- llvm_mode/afl-clang-fast.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'examples/afl_untracer/afl-untracer.c') diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index f812958c..d319b530 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -65,7 +65,7 @@ #include #include #else -#error "Unsupproted platform" +#error "Unsupported platform" #endif #define MEMORY_MAP_DECREMENT 0x200000000000 @@ -667,7 +667,7 @@ int main(int argc, char *argv[]) { fuzz(); // we can use _exit which is faster because our target library - // was loaded via dlopen and there cannot have deconstructors + // was loaded via dlopen and therefore cannot have deconstructors // registered. _exit(0); diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 4b9999a6..2d1b427c 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -717,7 +717,7 @@ int main(int argc, char **argv, char **envp) { if (instrument_mode == INSTRUMENT_LTO) FATAL( "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11)"); + "(requires LLVM 11 or higher)"); #endif if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC && -- cgit 1.4.1