From abb0d47985d22d8090540e987b2173d80c574439 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 12 Jul 2020 23:53:29 +0200 Subject: little untracer enhancements --- examples/afl_untracer/TODO | 2 ++ examples/afl_untracer/afl-untracer.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 examples/afl_untracer/TODO (limited to 'examples') diff --git a/examples/afl_untracer/TODO b/examples/afl_untracer/TODO new file mode 100644 index 00000000..fffffacf --- /dev/null +++ b/examples/afl_untracer/TODO @@ -0,0 +1,2 @@ + * add shmem fuzzing + * add snapshot feature? diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index 664e691c..dc2cd378 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -56,6 +56,7 @@ #include #include #include +#include #if defined(__linux__) #include @@ -395,7 +396,7 @@ static void __afl_map_shm(void) { } /* Fork server logic. */ -static void __afl_start_forkserver(void) { +inline static void __afl_start_forkserver(void) { u8 tmp[4] = {0, 0, 0, 0}; u32 status = 0; @@ -411,7 +412,7 @@ static void __afl_start_forkserver(void) { } -static u32 __afl_next_testcase(u8 *buf, u32 max_len) { +inline static u32 __afl_next_testcase(u8 *buf, u32 max_len) { s32 status; @@ -437,7 +438,7 @@ static u32 __afl_next_testcase(u8 *buf, u32 max_len) { } -static void __afl_end_testcase(int status) { +inline static void __afl_end_testcase(int status) { if (write(FORKSRV_FD + 1, &status, 4) != 4) do_exit = 1; // fprintf(stderr, "write2 %d\n", do_exit); @@ -673,6 +674,8 @@ static void *(*o_function)(u8 *buf, int len); /* the MAIN function */ int main(int argc, char *argv[]) { + (void) personality(ADDR_NO_RANDOMIZE); // disable ASLR + pid = getpid(); if (getenv("AFL_DEBUG")) debug = 1; @@ -706,6 +709,9 @@ int main(int argc, char *argv[]) { while (1) { + // instead of fork() we could also use the snapshot lkm or do our own mini + // snapshot feature like in https://github.com/marcinguy/fuzzer + // -> snapshot.c if ((pid = fork()) == -1) PFATAL("fork failed"); if (pid) { @@ -738,6 +744,9 @@ int main(int argc, char *argv[]) { } +#ifndef _DEBUG +inline +#endif static void fuzz() { // STEP 3: call the function to fuzz, also the functions you might @@ -753,4 +762,3 @@ static void fuzz() { // END STEP 3 } - -- cgit 1.4.1 From 4d929f80fbf22eeb09612a575bcd1a4141b9a8a9 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 13 Jul 2020 17:57:02 +0200 Subject: fix for laf intel float split not enabled if not not on a tty --- .custom-format.py | 3 ++- docs/Changelog.md | 3 ++- examples/afl_untracer/README.md | 1 + examples/afl_untracer/afl-untracer.c | 14 ++++++++------ llvm_mode/split-compares-pass.so.cc | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/.custom-format.py b/.custom-format.py index 6f1b0bfa..60f6d9c3 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -32,7 +32,8 @@ if CLANG_FORMAT_BIN is None: p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE) o, _ = p.communicate() o = str(o, "utf-8") - o = o[len("clang-format version "):].strip() + o = re.sub(r".*ersion ", "", o) + #o = o[len("clang-format version "):].strip() o = o[:o.find(".")] o = int(o) except: diff --git a/docs/Changelog.md b/docs/Changelog.md index b0bda6dc..8fb85ce6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,7 +13,8 @@ sending a mail to . - afl-fuzz: - eliminated CPU affinity race condition for -S/-M runs - llvm_mode: - - fix for laf-intel float splitting + - fixes for laf-intel float splitting (thanks to mark-griffin for + reporting) - LTO: autodictionary mode is a default - LTO: instrim instrumentation disabled, only classic support used as it is always better diff --git a/examples/afl_untracer/README.md b/examples/afl_untracer/README.md index e59792cb..9cb13527 100644 --- a/examples/afl_untracer/README.md +++ b/examples/afl_untracer/README.md @@ -32,6 +32,7 @@ To easily run the scripts without needing to run the GUI with Ghidra: /opt/ghidra/support/analyzeHeadless /tmp/ tmp$$ -import libtestinstr.so -postscript ./ghidra_get_patchpoints.java rm -rf /tmp/tmp$$ ``` +The file is created at `~/Desktop/patches.txt` ### Fuzzing diff --git a/examples/afl_untracer/afl-untracer.c b/examples/afl_untracer/afl-untracer.c index dc2cd378..68658bfd 100644 --- a/examples/afl_untracer/afl-untracer.c +++ b/examples/afl_untracer/afl-untracer.c @@ -74,6 +74,9 @@ // STEP 1: +/* here you need to specify the parameter for the target function */ +static void *(*o_function)(u8 *buf, int len); + /* use stdin (1) or a file on the commandline (0) */ static u32 use_stdin = 1; @@ -668,13 +671,10 @@ 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[]) { - (void) personality(ADDR_NO_RANDOMIZE); // disable ASLR + (void)personality(ADDR_NO_RANDOMIZE); // disable ASLR pid = getpid(); if (getenv("AFL_DEBUG")) debug = 1; @@ -745,9 +745,10 @@ int main(int argc, char *argv[]) { } #ifndef _DEBUG -inline +inline #endif -static void fuzz() { + static void + fuzz() { // STEP 3: call the function to fuzz, also the functions you might // need to call to prepare the function and - important! - @@ -762,3 +763,4 @@ static void fuzz() { // END STEP 3 } + diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index 0681fbd6..55128ca2 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -1263,8 +1263,6 @@ bool SplitComparesTransform::runOnModule(Module &M) { if (enableFPSplit) { - simplifyFPCompares(M); - errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M) << " FP comparisons splitted\n"; @@ -1274,6 +1272,8 @@ bool SplitComparesTransform::runOnModule(Module &M) { be_quiet = 1; + if (enableFPSplit) simplifyFPCompares(M); + simplifyCompares(M); simplifyIntSignedness(M); -- cgit 1.4.1 From e137b40eb5a2b66a356c32e410cf676ede3f6f0d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 13 Jul 2020 16:22:18 +0000 Subject: Haiku build fix. librt is necessary for Linux primarly and SunOS --- GNUmakefile | 8 ++++---- examples/afl_network_proxy/afl-network-client.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/GNUmakefile b/GNUmakefile index 748cd73c..f44ef95e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -65,7 +65,7 @@ endif ifeq "$(shell uname)" "SunOS" CFLAGS_OPT += -Wno-format-truncation - LDFLAGS=-lkstat + LDFLAGS=-lkstat -lrt endif ifdef STATIC @@ -196,7 +196,7 @@ else endif ifneq "$(filter Linux GNU%,$(shell uname))" "" - LDFLAGS += -ldl + LDFLAGS += -ldl -lrt endif ifneq "$(findstring FreeBSD, $(shell uname))" "" @@ -254,13 +254,13 @@ ifeq "$(shell echo '$(HASH)include @$(HASH)include @int ma else SHMAT_OK=0 override CFLAGS+=-DUSEMMAP=1 - LDFLAGS += -Wno-deprecated-declarations -lrt + LDFLAGS += -Wno-deprecated-declarations endif ifdef TEST_MMAP SHMAT_OK=0 override CFLAGS += -DUSEMMAP=1 - LDFLAGS += -Wno-deprecated-declarations -lrt + LDFLAGS += -Wno-deprecated-declarations endif all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done diff --git a/examples/afl_network_proxy/afl-network-client.c b/examples/afl_network_proxy/afl-network-client.c index 5af41055..7c4d8b35 100644 --- a/examples/afl_network_proxy/afl-network-client.c +++ b/examples/afl_network_proxy/afl-network-client.c @@ -34,7 +34,9 @@ #include #include #include +#ifndef USEMMAP #include +#endif #include #include #include -- cgit 1.4.1 From 383b280531a92a8b81d112a9acb4e44c08987be0 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 14 Jul 2020 23:26:11 +0200 Subject: added frida gum extension --- examples/afl_frida/Makefile | 23 ++ examples/afl_frida/README.md | 38 +++ examples/afl_frida/afl-frida.c | 312 ++++++++++++++++++++++++ examples/afl_frida/afl-frida.h | 53 ++++ examples/afl_frida/libtestinstr.c | 35 +++ examples/afl_network_proxy/afl-network-client.c | 2 +- src/afl-fuzz.c | 5 +- test/test-floatingpoint.c | 24 +- test/test-fp_cases.c | 73 ++++-- 9 files changed, 525 insertions(+), 40 deletions(-) create mode 100644 examples/afl_frida/Makefile create mode 100644 examples/afl_frida/README.md create mode 100644 examples/afl_frida/afl-frida.c create mode 100644 examples/afl_frida/afl-frida.h create mode 100644 examples/afl_frida/libtestinstr.c (limited to 'examples') diff --git a/examples/afl_frida/Makefile b/examples/afl_frida/Makefile new file mode 100644 index 00000000..5d482e54 --- /dev/null +++ b/examples/afl_frida/Makefile @@ -0,0 +1,23 @@ +ifdef DEBUG + OPT=-O0 -D_DEBUG=\"1\" +else + OPT=-O3 -funroll-loops +endif + +all: afl-frida libtestinstr.so + +libfrida-gum.a: + @echo Download and extract frida-gum-devkit-VERSION-PLATFORM.tar.xz for your platform from https://github.com/frida/frida/releases/latest + @exit 1 + +afl-frida: afl-frida.c libfrida-gum.a + $(CC) -g $(OPT) -o afl-frida -I. -fpermissive -fPIC afl-frida.c ../../afl-llvm-rt.o libfrida-gum.a -ldl -lresolv -pthread + +libtestinstr.so: libtestinstr.c + $(CC) -g -O0 -fPIC -o libtestinstr.so -shared libtestinstr.c + +clean: + rm -f afl-frida *~ core *.o libtestinstr.so + +deepclean: clean + rm -f libfrida-gum.a frida-gum* diff --git a/examples/afl_frida/README.md b/examples/afl_frida/README.md new file mode 100644 index 00000000..93e8f35a --- /dev/null +++ b/examples/afl_frida/README.md @@ -0,0 +1,38 @@ +# afl-frida - faster fuzzing of binary-only libraries + +## Introduction + +afl-frida is an example skeleton file which can easily be used to fuzz +a closed source library. + +It requires less memory and is x5-10 faster than qemu_mode but does not +provide interesting features like compcov or cmplog. + +## How-to + +### Modify afl-frida.c + +Read and modify afl-frida.c then `make`. +To adapt afl-frida.c to your needs, read the header of the file and then +search and edit the `STEP 1`, `STEP 2` and `STEP 3` locations. + +### Fuzzing + +Example (after modifying afl-frida.c to your needs and compile it): +``` +afl-fuzz -i in -o out -- ./afl-frida +``` +(or even remote via afl-network-proxy). + +### Testing and debugging + +For testing/debugging you can try: +``` +make DEBUG=1 +AFL_DEBUG=1 gdb ./afl-frida +``` +and then you can easily set breakpoints to "breakpoint" and "fuzz". + +# Background + +This code ist copied for a larger part from https://github.com/meme/hotwax diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c new file mode 100644 index 00000000..c24e05b7 --- /dev/null +++ b/examples/afl_frida/afl-frida.c @@ -0,0 +1,312 @@ +/* + american fuzzy lop++ - afl-frida skeleton example + ------------------------------------------------- + + Copyright 2020 AFLplusplus Project. All rights reserved. + + Written mostly by meme -> https://github.com/meme/hotwax + + Modificationy by Marc Heuse + + 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. set the defines and function call parameters. + 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:" + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __APPLE__ + #include +#endif + + +// STEP 1: + +// The presets are for the example libtestinstr.so: + +/* What is the name of the library to fuzz */ +#define TARGET_LIBRARY "libtestinstr.so" + +/* What is the name of the function to fuzz */ +#define TARGET_FUNCTION "testinstr" + +/* here you need to specify the parameter for the target function */ +static void *(*o_function)(uint8_t *, int); + +// END STEP 1 + + +#include "frida-gum.h" + +G_BEGIN_DECLS + +#define GUM_TYPE_FAKE_EVENT_SINK (gum_fake_event_sink_get_type()) +G_DECLARE_FINAL_TYPE(GumFakeEventSink, gum_fake_event_sink, GUM, + FAKE_EVENT_SINK, GObject) + +struct _GumFakeEventSink { + + GObject parent; + GumEventType mask; + +}; + +GumEventSink *gum_fake_event_sink_new(void); +void gum_fake_event_sink_reset(GumFakeEventSink *self); + +G_END_DECLS + +static void gum_fake_event_sink_iface_init(gpointer g_iface, + gpointer iface_data); +static void gum_fake_event_sink_finalize(GObject *obj); +static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink); +static void gum_fake_event_sink_process(GumEventSink *sink, const GumEvent *ev); +void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, + gpointer user_data); +void afl_setup(void); +void afl_start_forkserver(void); +int __afl_persistent_loop(unsigned int max_cnt); + +static void gum_fake_event_sink_class_init(GumFakeEventSinkClass *klass) { + + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = gum_fake_event_sink_finalize; + +} + +static void gum_fake_event_sink_iface_init(gpointer g_iface, + gpointer iface_data) { + + GumEventSinkInterface *iface = (GumEventSinkInterface *) g_iface; + iface->query_mask = gum_fake_event_sink_query_mask; + iface->process = gum_fake_event_sink_process; + +} + +G_DEFINE_TYPE_EXTENDED(GumFakeEventSink, gum_fake_event_sink, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE(GUM_TYPE_EVENT_SINK, + gum_fake_event_sink_iface_init)) + +#include "../../config.h" + +// Shared memory fuzzing. +int __afl_sharedmem_fuzzing = 1; +extern unsigned int *__afl_fuzz_len; +extern unsigned char *__afl_fuzz_ptr; + +// Notify AFL about persistent mode. +static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; +int __afl_persistent_loop(unsigned int); + +// Notify AFL about deferred forkserver. +static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; +void __afl_manual_init(); + +// Because we do our own logging. +extern uint8_t * __afl_area_ptr; + +// Frida stuff below. +typedef struct { + + GumAddress base_address; + guint64 code_start, code_end; + +} range_t; + +inline static void afl_maybe_log(guint64 current_pc) { + + static __thread guint64 previous_pc; + + current_pc = (current_pc >> 4) ^ (current_pc << 8); + current_pc &= MAP_SIZE - 1; + + __afl_area_ptr[current_pc ^ previous_pc]++; + previous_pc = current_pc >> 1; + +} + +static void on_basic_block(GumCpuContext *context, gpointer user_data) { + + afl_maybe_log((guint64)user_data); + +} + +void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, + gpointer user_data) { + + range_t *range = (range_t *)user_data; + + const cs_insn *instr; + gboolean begin = TRUE; + while (gum_stalker_iterator_next(iterator, &instr)) { + + if (begin) { + + guint64 current_pc = instr->address - range->base_address; + gum_stalker_iterator_put_callout(iterator, on_basic_block, + (gpointer)current_pc, NULL); + begin = FALSE; + + } + + gum_stalker_iterator_keep(iterator); + + } + +} + +static void gum_fake_event_sink_init(GumFakeEventSink *self) { } + +static void gum_fake_event_sink_finalize(GObject *obj) { + + G_OBJECT_CLASS(gum_fake_event_sink_parent_class)->finalize(obj); + +} + +GumEventSink *gum_fake_event_sink_new(void) { + + GumFakeEventSink *sink; + sink = (GumFakeEventSink *) g_object_new(GUM_TYPE_FAKE_EVENT_SINK, NULL); + return GUM_EVENT_SINK(sink); + +} + +void gum_fake_event_sink_reset(GumFakeEventSink *self) { } + +static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink) { + + return 0; + +} + +static void gum_fake_event_sink_process(GumEventSink * sink, + const GumEvent *ev) { } + +/* Because this CAN be called more than once, it will return the LAST range */ +static int enumerate_ranges(const GumRangeDetails *details, + gpointer user_data) { + + GumMemoryRange *code_range = (GumMemoryRange *)user_data; + memcpy(code_range, details->range, sizeof(*code_range)); + return 0; + +} + +int main() { + + // STEP 2: load the library you want to fuzz and lookup the functions, + // inclusive of the cleanup functions. + // If there is just one function, then there is nothing to change + // or add here. + + void *dl = dlopen(TARGET_LIBRARY, RTLD_LAZY); + if (!dl) { + + fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY); + exit(-1); + + } + + if (!(o_function = dlsym(dl, TARGET_FUNCTION))) { + + fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION); + exit(-1); + + } + + // END STEP 2 + + gum_init_embedded(); + if (!gum_stalker_is_supported()) { + + gum_deinit_embedded(); + return 1; + + } + + GumStalker *stalker = gum_stalker_new(); + + GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY); + + GumMemoryRange code_range; + gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges, + &code_range); + guint64 code_start = code_range.base_address - base_address; + guint64 code_end = (code_range.base_address + code_range.size) - base_address; + + range_t instr_range = {base_address, code_start, code_end}; + + GumStalkerTransformer *transformer = + gum_stalker_transformer_make_from_callback(instr_basic_block, + &instr_range, NULL); + + GumEventSink *event_sink = gum_fake_event_sink_new(); + + __afl_manual_init(); + + // + // any expensive target library initialization that has to be done just once + // - put that here + // + + gum_stalker_follow_me(stalker, transformer, event_sink); + + while (__afl_persistent_loop(UINT32_MAX) != 0) { + +#ifdef _DEBUG + fprintf(stderr, "CLIENT crc: %016llx len: %u\n", hash64(__afl_fuzz_ptr, *__a + fprintf(stderr, "RECV:"); + for (int i = 0; i < *__afl_fuzz_len; i++) + fprintf(stderr, "%02x", __afl_fuzz_ptr[i]); + fprintf(stderr,"\n"); +#endif + + // STEP 3: ensure the minimum length is present and setup the target + // function to fuzz. + + if (*__afl_fuzz_len > 0) { + + __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate + (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len); + + } + + // END STEP 3 + + } + + gum_stalker_unfollow_me(stalker); + + while (gum_stalker_garbage_collect(stalker)) + g_usleep(10000); + + g_object_unref(stalker); + g_object_unref(transformer); + g_object_unref(event_sink); + gum_deinit_embedded(); + + return 0; + +} diff --git a/examples/afl_frida/afl-frida.h b/examples/afl_frida/afl-frida.h new file mode 100644 index 00000000..efa3440f --- /dev/null +++ b/examples/afl_frida/afl-frida.h @@ -0,0 +1,53 @@ +extern int is_persistent; + +G_BEGIN_DECLS + +#define GUM_TYPE_FAKE_EVENT_SINK (gum_fake_event_sink_get_type()) + +G_DECLARE_FINAL_TYPE(GumFakeEventSink, gum_fake_event_sink, GUM, + FAKE_EVENT_SINK, GObject) + +struct _GumFakeEventSink { + + GObject parent; + GumEventType mask; + +}; + +GumEventSink *gum_fake_event_sink_new(void); +void gum_fake_event_sink_reset(GumFakeEventSink *self); + +G_END_DECLS + +typedef struct { + + GumAddress base_address; + guint64 code_start, code_end; + +} range_t; + +void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, + gpointer user_data); +#pragma once + +void afl_setup(void); +void afl_start_forkserver(void); +int __afl_persistent_loop(unsigned int max_cnt); + +inline static inline void afl_maybe_log(guint64 current_pc) { + + extern unsigned int afl_instr_rms; + extern uint8_t * afl_area_ptr; + + static __thread guint64 previous_pc; + + current_pc = (current_pc >> 4) ^ (current_pc << 8); + current_pc &= MAP_SIZE - 1; + + if (current_pc >= afl_instr_rms) return; + + afl_area_ptr[current_pc ^ previous_pc]++; + previous_pc = current_pc >> 1; + +} + diff --git a/examples/afl_frida/libtestinstr.c b/examples/afl_frida/libtestinstr.c new file mode 100644 index 00000000..96b1cf21 --- /dev/null +++ b/examples/afl_frida/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/examples/afl_network_proxy/afl-network-client.c b/examples/afl_network_proxy/afl-network-client.c index 7c4d8b35..a2451fdc 100644 --- a/examples/afl_network_proxy/afl-network-client.c +++ b/examples/afl_network_proxy/afl-network-client.c @@ -35,7 +35,7 @@ #include #include #ifndef USEMMAP -#include + #include #endif #include #include diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f7f247f3..872ed9ae 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -266,6 +266,8 @@ int main(int argc, char **argv_orig, char **envp) { gettimeofday(&tv, &tz); rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid()); + afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing + while ((opt = getopt(argc, argv, "+c:i:I:o:f:m:t:T:dDnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) { @@ -563,7 +565,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); } afl->fsrv.qemu_mode = 1; - afl->shmem_testcase_mode = 1; if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; } @@ -580,7 +581,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); } afl->unicorn_mode = 1; - afl->shmem_testcase_mode = 1; if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; } @@ -591,7 +591,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->use_wine) { FATAL("Multiple -W options not supported"); } afl->fsrv.qemu_mode = 1; afl->use_wine = 1; - afl->shmem_testcase_mode = 1; if (!mem_limit_given) { afl->fsrv.mem_limit = 0; } diff --git a/test/test-floatingpoint.c b/test/test-floatingpoint.c index f78b5d9f..76cdccf0 100644 --- a/test/test-floatingpoint.c +++ b/test/test-floatingpoint.c @@ -1,18 +1,20 @@ #include #include -int main(void) -{ - long double magic; +int main(void) { - ssize_t bytes_read = read(STDIN_FILENO, &magic, sizeof(magic)); - if (bytes_read < (ssize_t)sizeof(magic)) { - return 1; - } + long double magic; - if( (-magic == 15.0 + 0.5 + 0.125 + 0.03125 + 0.0078125) ){ /* 15 + 1/2 + 1/8 + 1/32 + 1/128 */ - abort(); - } + ssize_t bytes_read = read(STDIN_FILENO, &magic, sizeof(magic)); + if (bytes_read < (ssize_t)sizeof(magic)) { return 1; } + + if ((-magic == 15.0 + 0.5 + 0.125 + 0.03125 + + 0.0078125)) { /* 15 + 1/2 + 1/8 + 1/32 + 1/128 */ + abort(); + + } + + return 0; - return 0; } + diff --git a/test/test-fp_cases.c b/test/test-fp_cases.c index 006ae32f..b0f792bc 100644 --- a/test/test-fp_cases.c +++ b/test/test-fp_cases.c @@ -4,13 +4,14 @@ * or -DFLOAT_TYPE="long double" */ - #include int main() { - volatile FLOAT_TYPE a,b; + + volatile FLOAT_TYPE a, b; /* different values */ - a = -2.1; b = -2; /* signs equal, exp equal, mantissa > */ + a = -2.1; + b = -2; /* signs equal, exp equal, mantissa > */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -18,7 +19,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 1.8; b = 2.1; /* signs equal, exp differ, mantissa > */ + a = 1.8; + b = 2.1; /* signs equal, exp differ, mantissa > */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -26,7 +28,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 2; b = 2.1; /* signs equal, exp equal, mantissa < */ + a = 2; + b = 2.1; /* signs equal, exp equal, mantissa < */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -34,7 +37,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -2; b = -1.8; /* signs equal, exp differ, mantissa < */ + a = -2; + b = -1.8; /* signs equal, exp differ, mantissa < */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -42,7 +46,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -1; b = 1; /* signs differ, exp equal, mantissa equal */ + a = -1; + b = 1; /* signs differ, exp equal, mantissa equal */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -50,7 +55,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -1; b = 0; /* signs differ, exp differ, mantissa equal */ + a = -1; + b = 0; /* signs differ, exp differ, mantissa equal */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -58,7 +64,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -2; b = 2.8; /* signs differ, exp equal, mantissa < */ + a = -2; + b = 2.8; /* signs differ, exp equal, mantissa < */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -66,7 +73,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -2; b = 1.8; /* signs differ, exp differ, mantissa < */ + a = -2; + b = 1.8; /* signs differ, exp differ, mantissa < */ assert((a < b)); assert((a <= b)); assert(!(a > b)); @@ -74,8 +82,8 @@ int main() { assert((a != b)); assert(!(a == b)); - - a = -2; b = -2.1; /* signs equal, exp equal, mantissa > */ + a = -2; + b = -2.1; /* signs equal, exp equal, mantissa > */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -83,7 +91,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 2.1; b = 1.8; /* signs equal, exp differ, mantissa > */ + a = 2.1; + b = 1.8; /* signs equal, exp differ, mantissa > */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -91,7 +100,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 2.1; b = 2; /* signs equal, exp equal, mantissa < */ + a = 2.1; + b = 2; /* signs equal, exp equal, mantissa < */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -99,7 +109,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = -1.8; b = -2; /* signs equal, exp differ, mantissa < */ + a = -1.8; + b = -2; /* signs equal, exp differ, mantissa < */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -107,7 +118,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 1; b = -1; /* signs differ, exp equal, mantissa equal */ + a = 1; + b = -1; /* signs differ, exp equal, mantissa equal */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -115,7 +127,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 0; b = -1; /* signs differ, exp differ, mantissa equal */ + a = 0; + b = -1; /* signs differ, exp differ, mantissa equal */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -123,7 +136,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 2.8; b = -2; /* signs differ, exp equal, mantissa < */ + a = 2.8; + b = -2; /* signs differ, exp equal, mantissa < */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -131,7 +145,8 @@ int main() { assert((a != b)); assert(!(a == b)); - a = 1.8; b = -2; /* signs differ, exp differ, mantissa < */ + a = 1.8; + b = -2; /* signs differ, exp differ, mantissa < */ assert((a > b)); assert((a >= b)); assert(!(a < b)); @@ -140,7 +155,8 @@ int main() { assert(!(a == b)); /* equal values */ - a = 0; b = 0; + a = 0; + b = 0; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); @@ -148,7 +164,8 @@ int main() { assert(!(a != b)); assert((a == b)); - a = -0; b = 0; + a = -0; + b = 0; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); @@ -156,7 +173,8 @@ int main() { assert(!(a != b)); assert((a == b)); - a = 1; b = 1; + a = 1; + b = 1; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); @@ -164,7 +182,8 @@ int main() { assert(!(a != b)); assert((a == b)); - a = 0.5; b = 0.5; + a = 0.5; + b = 0.5; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); @@ -172,7 +191,8 @@ int main() { assert(!(a != b)); assert((a == b)); - a = -1; b = -1; + a = -1; + b = -1; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); @@ -180,11 +200,14 @@ int main() { assert(!(a != b)); assert((a == b)); - a = -0.5; b = -0.5; + a = -0.5; + b = -0.5; assert(!(a < b)); assert((a <= b)); assert(!(a > b)); assert((a >= b)); assert(!(a != b)); assert((a == b)); + } + -- cgit 1.4.1 From a8726b8254f2f8c429c8b3e1c2d30b9f7baa6e93 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 15 Jul 2020 00:08:38 +0200 Subject: ensure afl-frida uses persistent mode --- docs/Changelog.md | 2 ++ examples/afl_frida/README.md | 10 +++------- examples/afl_frida/afl-frida.c | 8 ++++++++ 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'examples') diff --git a/docs/Changelog.md b/docs/Changelog.md index 8fb85ce6..50f5629f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -18,6 +18,8 @@ sending a mail to . - LTO: autodictionary mode is a default - LTO: instrim instrumentation disabled, only classic support used as it is always better + - added afl-frida gum solution to examples/afl_frida (mostly imported + from https://github.com/meme/hotwax/) - small fixes to afl-plot, afl-whatsup and man page creation diff --git a/examples/afl_frida/README.md b/examples/afl_frida/README.md index 93e8f35a..33bd67c8 100644 --- a/examples/afl_frida/README.md +++ b/examples/afl_frida/README.md @@ -24,14 +24,10 @@ afl-fuzz -i in -o out -- ./afl-frida ``` (or even remote via afl-network-proxy). -### Testing and debugging +# Speed and stability -For testing/debugging you can try: -``` -make DEBUG=1 -AFL_DEBUG=1 gdb ./afl-frida -``` -and then you can easily set breakpoints to "breakpoint" and "fuzz". +The speed is very good, about x12 of fork() qemu_mode. +However the stability is low. Reason is currently unknown. # Background diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c index c24e05b7..ff10ffb7 100644 --- a/examples/afl_frida/afl-frida.c +++ b/examples/afl_frida/afl-frida.c @@ -39,6 +39,7 @@ #ifndef __APPLE__ #include + #include #endif @@ -216,6 +217,10 @@ static int enumerate_ranges(const GumRangeDetails *details, int main() { +#ifndef __APPLE__ + (void)personality(ADDR_NO_RANDOMIZE); // disable ASLR +#endif + // STEP 2: load the library you want to fuzz and lookup the functions, // inclusive of the cleanup functions. // If there is just one function, then there is nothing to change @@ -264,6 +269,9 @@ int main() { GumEventSink *event_sink = gum_fake_event_sink_new(); + // to ensure that the signatures are not optimized out + memcpy(__afl_area_ptr, (void*)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1); + memcpy(__afl_area_ptr + 32, (void*)AFL_DEFER_FORKSVR, sizeof(AFL_DEFER_FORKSVR) + 1); __afl_manual_init(); // -- cgit 1.4.1 From 133dfc8b69ece83bd7b1e59e81f09815ff5b8e44 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 15 Jul 2020 10:32:07 +0200 Subject: update documentation --- examples/afl_frida/README.md | 2 +- examples/afl_untracer/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/afl_frida/README.md b/examples/afl_frida/README.md index 33bd67c8..1ee19a68 100644 --- a/examples/afl_frida/README.md +++ b/examples/afl_frida/README.md @@ -20,7 +20,7 @@ search and edit the `STEP 1`, `STEP 2` and `STEP 3` locations. Example (after modifying afl-frida.c to your needs and compile it): ``` -afl-fuzz -i in -o out -- ./afl-frida +LD_LIBRARY_PATH=/path/to/the/target/library afl-fuzz -i in -o out -- ./afl-frida ``` (or even remote via afl-network-proxy). diff --git a/examples/afl_untracer/README.md b/examples/afl_untracer/README.md index 9cb13527..ada0c916 100644 --- a/examples/afl_untracer/README.md +++ b/examples/afl_untracer/README.md @@ -39,7 +39,7 @@ The file is created at `~/Desktop/patches.txt` Example (after modifying afl-untracer.c to your needs, compiling and creating patches.txt): ``` -AFL_UNTRACER_FILE=./patches.txt afl-fuzz -i in -o out -- ./afl-untracer +LD_LIBRARY_PATH=/path/to/target/library AFL_UNTRACER_FILE=./patches.txt afl-fuzz -i in -o out -- ./afl-untracer ``` (or even remote via afl-network-proxy). -- cgit 1.4.1 From 08d3169df4950458a8b401f6140c8e98fdb3cd81 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 15 Jul 2020 16:58:40 +0200 Subject: fix afl-frida --- examples/afl_frida/Makefile | 2 +- examples/afl_frida/afl-frida.c | 260 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 241 insertions(+), 21 deletions(-) (limited to 'examples') diff --git a/examples/afl_frida/Makefile b/examples/afl_frida/Makefile index 5d482e54..c154f3a4 100644 --- a/examples/afl_frida/Makefile +++ b/examples/afl_frida/Makefile @@ -11,7 +11,7 @@ libfrida-gum.a: @exit 1 afl-frida: afl-frida.c libfrida-gum.a - $(CC) -g $(OPT) -o afl-frida -I. -fpermissive -fPIC afl-frida.c ../../afl-llvm-rt.o libfrida-gum.a -ldl -lresolv -pthread + $(CC) -g $(OPT) -o afl-frida -Wno-format -Wno-pointer-sign -I. -fpermissive -fPIC afl-frida.c ../../afl-llvm-rt.o libfrida-gum.a -ldl -lresolv -pthread libtestinstr.so: libtestinstr.c $(CC) -g -O0 -fPIC -o libtestinstr.so -shared libtestinstr.c diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c index ff10ffb7..76732aeb 100644 --- a/examples/afl_frida/afl-frida.c +++ b/examples/afl_frida/afl-frida.c @@ -42,6 +42,7 @@ #include #endif +int debug = 0; // STEP 1: @@ -58,7 +59,6 @@ static void *(*o_function)(uint8_t *, int); // END STEP 1 - #include "frida-gum.h" G_BEGIN_DECLS @@ -100,7 +100,7 @@ static void gum_fake_event_sink_class_init(GumFakeEventSinkClass *klass) { static void gum_fake_event_sink_iface_init(gpointer g_iface, gpointer iface_data) { - GumEventSinkInterface *iface = (GumEventSinkInterface *) g_iface; + GumEventSinkInterface *iface = (GumEventSinkInterface *)g_iface; iface->query_mask = gum_fake_event_sink_query_mask; iface->process = gum_fake_event_sink_process; @@ -113,20 +113,20 @@ G_DEFINE_TYPE_EXTENDED(GumFakeEventSink, gum_fake_event_sink, G_TYPE_OBJECT, 0, #include "../../config.h" // Shared memory fuzzing. -int __afl_sharedmem_fuzzing = 1; -extern unsigned int *__afl_fuzz_len; +int __afl_sharedmem_fuzzing = 1; +extern unsigned int * __afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -int __afl_persistent_loop(unsigned int); +int __afl_persistent_loop(unsigned int); // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -void __afl_manual_init(); +void __afl_manual_init(); // Because we do our own logging. -extern uint8_t * __afl_area_ptr; +extern uint8_t *__afl_area_ptr; // Frida stuff below. typedef struct { @@ -140,6 +140,8 @@ inline static void afl_maybe_log(guint64 current_pc) { static __thread guint64 previous_pc; + // fprintf(stderr, "PC: %p\n", current_pc); + current_pc = (current_pc >> 4) ^ (current_pc << 8); current_pc &= MAP_SIZE - 1; @@ -165,10 +167,14 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, if (begin) { - guint64 current_pc = instr->address - range->base_address; - gum_stalker_iterator_put_callout(iterator, on_basic_block, - (gpointer)current_pc, NULL); - begin = FALSE; + if (instr->address >= range->code_start && + instr->address <= range->code_end) { + + gum_stalker_iterator_put_callout(iterator, on_basic_block, + (gpointer)instr->address, NULL); + begin = FALSE; + + } } @@ -178,7 +184,9 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, } -static void gum_fake_event_sink_init(GumFakeEventSink *self) { } +static void gum_fake_event_sink_init(GumFakeEventSink *self) { + +} static void gum_fake_event_sink_finalize(GObject *obj) { @@ -189,12 +197,14 @@ static void gum_fake_event_sink_finalize(GObject *obj) { GumEventSink *gum_fake_event_sink_new(void) { GumFakeEventSink *sink; - sink = (GumFakeEventSink *) g_object_new(GUM_TYPE_FAKE_EVENT_SINK, NULL); + sink = (GumFakeEventSink *)g_object_new(GUM_TYPE_FAKE_EVENT_SINK, NULL); return GUM_EVENT_SINK(sink); } -void gum_fake_event_sink_reset(GumFakeEventSink *self) { } +void gum_fake_event_sink_reset(GumFakeEventSink *self) { + +} static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink) { @@ -202,8 +212,201 @@ static GumEventType gum_fake_event_sink_query_mask(GumEventSink *sink) { } +typedef struct library_list { + + uint8_t *name; + uint64_t addr_start, addr_end; + +} library_list_t; + +#define MAX_LIB_COUNT 256 +static library_list_t liblist[MAX_LIB_COUNT]; +static u32 liblist_cnt; + +void read_library_information() { + +#if defined(__linux__) + FILE *f; + u8 buf[1024], *b, *m, *e, *n; + + if ((f = fopen("/proc/self/maps", "r")) == NULL) { + + fprintf(stderr, "Error: cannot open /proc/self/maps\n"); + exit(-1); + + } + + if (debug) fprintf(stderr, "Library list:\n"); + while (fgets(buf, sizeof(buf), f)) { + + if (strstr(buf, " r-x")) { + + if (liblist_cnt >= MAX_LIB_COUNT) { + + fprintf( + stderr, + "Warning: too many libraries to old, maximum count of %d reached\n", + 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; + + if (rindex(n, '/') != NULL) { + + n = rindex(n, '/'); + n++; + + } + + liblist[liblist_cnt].name = strdup(n); + liblist[liblist_cnt].addr_start = strtoull(b, NULL, 16); + liblist[liblist_cnt].addr_end = strtoull(m, NULL, 16); + if (debug) + fprintf( + stderr, "%s:%llx (%llx-%llx)\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++; + + } + + } + + } + + if (debug) fprintf(stderr, "\n"); + +#elif defined(__FreeBSD__) + 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; } + + 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 + +} + +library_list_t *find_library(char *name) { + + char *filename = rindex(name, '/'); + + if (filename) + filename++; + else + filename = name; + +#if defined(__linux__) + u32 i; + for (i = 0; i < liblist_cnt; i++) + if (strcmp(liblist[i].name, filename) == 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; + +} + static void gum_fake_event_sink_process(GumEventSink * sink, - const GumEvent *ev) { } + const GumEvent *ev) { + +} /* Because this CAN be called more than once, it will return the LAST range */ static int enumerate_ranges(const GumRangeDetails *details, @@ -243,6 +446,16 @@ int main() { // END STEP 2 + read_library_information(); + library_list_t *lib = find_library(TARGET_LIBRARY); + + if (lib == NULL) { + + fprintf(stderr, "Could not find target library\n"); + exit(-1); + + } + gum_init_embedded(); if (!gum_stalker_is_supported()) { @@ -253,15 +466,20 @@ int main() { GumStalker *stalker = gum_stalker_new(); - GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY); + /* + This does not work here as we load a shared library. pretty sure this + would also be easily solvable with frida gum, but I already have all the + code I need from afl-untracer + GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY); GumMemoryRange code_range; gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges, &code_range); guint64 code_start = code_range.base_address - base_address; guint64 code_end = (code_range.base_address + code_range.size) - base_address; - range_t instr_range = {base_address, code_start, code_end}; + */ + range_t instr_range = {0, lib->addr_start, lib->addr_end}; GumStalkerTransformer *transformer = gum_stalker_transformer_make_from_callback(instr_basic_block, @@ -270,8 +488,9 @@ int main() { GumEventSink *event_sink = gum_fake_event_sink_new(); // to ensure that the signatures are not optimized out - memcpy(__afl_area_ptr, (void*)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1); - memcpy(__afl_area_ptr + 32, (void*)AFL_DEFER_FORKSVR, sizeof(AFL_DEFER_FORKSVR) + 1); + memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1); + memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR, + sizeof(AFL_DEFER_FORKSVR) + 1); __afl_manual_init(); // @@ -296,7 +515,7 @@ int main() { if (*__afl_fuzz_len > 0) { - __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate + __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len); } @@ -318,3 +537,4 @@ int main() { return 0; } + -- cgit 1.4.1 From 2077309c8d84f2f18c773b4e1b1638cff333a88e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 16 Jul 2020 00:24:37 +0200 Subject: fix afl-frida --- examples/afl_frida/afl-frida.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c index 76732aeb..7038e1bd 100644 --- a/examples/afl_frida/afl-frida.c +++ b/examples/afl_frida/afl-frida.c @@ -127,6 +127,7 @@ void __afl_manual_init(); // Because we do our own logging. extern uint8_t *__afl_area_ptr; + static __thread guint64 previous_pc; // Frida stuff below. typedef struct { @@ -138,9 +139,7 @@ typedef struct { inline static void afl_maybe_log(guint64 current_pc) { - static __thread guint64 previous_pc; - - // fprintf(stderr, "PC: %p\n", current_pc); + // fprintf(stderr, "PC: %p ^ %p\n", current_pc, previous_pc); current_pc = (current_pc >> 4) ^ (current_pc << 8); current_pc &= MAP_SIZE - 1; @@ -502,6 +501,8 @@ int main() { while (__afl_persistent_loop(UINT32_MAX) != 0) { + previous_pc = 0; // Required! + #ifdef _DEBUG fprintf(stderr, "CLIENT crc: %016llx len: %u\n", hash64(__afl_fuzz_ptr, *__a fprintf(stderr, "RECV:"); -- cgit 1.4.1 From 1ec2615a3ed98b991315a40217407136514b53f1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 16 Jul 2020 00:53:08 +0200 Subject: tiny fixes --- .gitignore | 4 ++++ examples/afl_frida/afl-frida.c | 4 ++-- src/afl-gcc.c | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/.gitignore b/.gitignore index 1000cc6f..1b7904ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ .test .test2 +.sync_tmp *.o *.so *.pyc +*.dSYM afl-analyze afl-as afl-clang @@ -55,3 +57,5 @@ test/unittests/unit_rand test/unittests/unit_hash examples/afl_network_proxy/afl-network-server examples/afl_network_proxy/afl-network-client +in +out diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c index 7038e1bd..2ad5a72a 100644 --- a/examples/afl_frida/afl-frida.c +++ b/examples/afl_frida/afl-frida.c @@ -126,8 +126,8 @@ static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; void __afl_manual_init(); // Because we do our own logging. -extern uint8_t *__afl_area_ptr; - static __thread guint64 previous_pc; +extern uint8_t * __afl_area_ptr; +static __thread guint64 previous_pc; // Frida stuff below. typedef struct { diff --git a/src/afl-gcc.c b/src/afl-gcc.c index 8d91164b..22e6be8e 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -132,6 +132,9 @@ static void edit_params(u32 argc, char **argv) { name = argv[0]; + /* This should never happen but fixes a scan-build warning */ + if (!name) { FATAL("Empty argv set"); } + } else { ++name; -- cgit 1.4.1 From f465a75b6592e4c30b0465f63beda166a8e09045 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 16 Jul 2020 02:17:05 +0200 Subject: added initial defork example --- examples/defork/Makefile | 64 +++++++++++++++++++++++++++++++++++++++ examples/defork/README.md | 11 +++++++ examples/defork/defork.c | 52 +++++++++++++++++++++++++++++++ examples/defork/forking_target | Bin 0 -> 19520 bytes examples/defork/forking_target.c | 46 ++++++++++++++++++++++++++++ 5 files changed, 173 insertions(+) create mode 100644 examples/defork/Makefile create mode 100644 examples/defork/README.md create mode 100644 examples/defork/defork.c create mode 100755 examples/defork/forking_target create mode 100644 examples/defork/forking_target.c (limited to 'examples') diff --git a/examples/defork/Makefile b/examples/defork/Makefile new file mode 100644 index 00000000..e8240dba --- /dev/null +++ b/examples/defork/Makefile @@ -0,0 +1,64 @@ +# +# american fuzzy lop++ - defork +# ---------------------------------- +# +# 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 +# + +.PHONY: all install clean + +PREFIX ?= /usr/local +BIN_PATH = $(PREFIX)/bin +HELPER_PATH = $(PREFIX)/lib/afl + +CFLAGS = -fPIC -Wall -Wextra +LDFLAGS = -shared + +UNAME_SAYS_LINUX=$(shell uname | grep -E '^Linux|^GNU' >/dev/null; echo $$?) +UNAME_SAYS_LINUX:sh=uname | grep -E '^Linux|^GNU' >/dev/null; echo $$? + +_LDFLAGS_ADD=$(UNAME_SAYS_LINUX:1=) +LDFLAGS_ADD=$(_LDFLAGS_ADD:0=-ldl) +LDFLAGS += $(LDFLAGS_ADD) + +# on gcc for arm there is no -m32, but -mbe32 +M32FLAG = -m32 +M64FLAG = -m64 + +CC_IS_GCC=$(shell $(CC) --version 2>/dev/null | grep -q gcc; echo $$?) +CC_IS_GCC:sh=$(CC) --version 2>/dev/null | grep -q gcc; echo $$? +CC_IS_ARMCOMPILER=$(shell $(CC) -v 2>&1 >/dev/null | grep -q arm; echo $$?) +CC_IS_ARMCOMPILER:sh=$(CC) -v 2>&1 >/dev/null | grep -q arm; echo $$? + +_M32FLAG=$(CC_IS_GCC)$(CC_IS_ARMCOMPILER) +__M32FLAG=$(_M32FLAG:00=-mbe32) +___M32FLAG=$(__M32FLAG:$(CC_IS_GCC)$(CC_IS_ARMCOMPILER)=-m32) +M32FLAG=$(___M32FLAG) +#ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" +# ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)")) +# M32FLAG = -mbe32 +# endif +#endif + +all: defork32.so defork64.so + +defork32.so: defork.c + -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "defork32 build failure (that's fine)" + +defork64.so: defork.c + -@$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "defork64 build failure (that's fine)" + +install: defork32.so defork64.so + install -d -m 755 $(DESTDIR)$(HELPER_PATH)/ + if [ -f defork32.so ]; then set -e; install -m 755 defork32.so $(DESTDIR)$(HELPER_PATH)/; fi + if [ -f defork64.so ]; then set -e; install -m 755 defork64.so $(DESTDIR)$(HELPER_PATH)/; fi + +target: + ../../afl-clang forking_target.c -o forking_target -Wall -Wextra -Werror + +clean: + rm -f defork32.so defork64.so forking_target diff --git a/examples/defork/README.md b/examples/defork/README.md new file mode 100644 index 00000000..7e950323 --- /dev/null +++ b/examples/defork/README.md @@ -0,0 +1,11 @@ +# defork + +when the target forks, this breaks all normal fuzzing runs. +Sometimes, though, it is enough to just run the child process. +If this is the case, then this LD_PRELOAD library will always return 0 on fork, +the target will belive it is running as the child, post-fork. + +This is defork.c from the amazing preeny project +https://github.com/zardus/preeny + +It is altered for afl++ to work with its fork-server: the initial fork will go through, the second fork will be blocked. diff --git a/examples/defork/defork.c b/examples/defork/defork.c new file mode 100644 index 00000000..46810326 --- /dev/null +++ b/examples/defork/defork.c @@ -0,0 +1,52 @@ +#define __GNU_SOURCE +#include +#include +#include +#include + +#include "../../include/config.h" + +/* we want to fork once (for the afl++ forkserver), + then immediately return as child on subsequent forks. */ +static bool forked = 0; + +pid_t (*original_fork)(void); + +/* In case we are not running in afl, we use a dummy original_fork */ +static pid_t nop(void) { + + return 0; + +} + +__attribute__((constructor)) void preeny_fork_orig() { + + if (getenv(SHM_ENV_VAR)) { + + printf("defork: running in AFL++. Allowing forkserver.\n"); + original_fork = dlsym(RTLD_NEXT, "socket"); + + } else { + + printf("defork: no AFL++ detected. Disabling fork from the start.\n"); + original_fork = &nop; + + } + +} + +pid_t fork(void) { + + printf("called fork. forked state is %d\n", (int) forked); + fflush(stdout); + /* If we forked before, or if we're in the child (pid==0), + we don't want to fork anymore, else, we are still in the forkserver. + The forkserver parent needs to fork infinite times, each child should never + fork again. This can be written without branches and I hate myself for it. + */ + pid_t ret = !forked && original_fork(); + forked = !ret; + return ret; + +} + diff --git a/examples/defork/forking_target b/examples/defork/forking_target new file mode 100755 index 00000000..0f7a04fc Binary files /dev/null and b/examples/defork/forking_target differ diff --git a/examples/defork/forking_target.c b/examples/defork/forking_target.c new file mode 100644 index 00000000..ff1d6e37 --- /dev/null +++ b/examples/defork/forking_target.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +/* This is an example target for defork.c - fuzz using +``` +mkdir in; echo a > ./in/a +AFL_PRELOAD=./defork64.so ../../afl-fuzz -i in -o out -- ./forking_target @@ +``` +*/ + +int main(int argc, char **argv) { + + if (argc < 2) { + + printf("Example tool to test defork.\nUsage ./forking_target \n"); + return -1; + + } + + pid_t pid = fork(); + if (pid == 0) { + + printf("We're in the child.\n"); + FILE *f = fopen(argv[1], "r"); + char buf[4096]; + fread(buf, 1, 4096, f); + uint32_t offset = buf[100] + (buf[101] << 8); + char test_val = buf[offset]; + return test_val < 100; + + } else if (pid < 0) { + + perror("fork"); + return -1; + + } else { + + printf("We are in the parent - defork didn't work! :( (pid=%d)\n", (int) pid); + + } + + return 0; + +} -- cgit 1.4.1 From 0b0366d9b4bc7ddea154174a81934dcc9911af12 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 16 Jul 2020 02:27:07 +0200 Subject: removed debug print and code format --- examples/defork/defork.c | 2 -- examples/defork/forking_target.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/defork/defork.c b/examples/defork/defork.c index 46810326..f71d1124 100644 --- a/examples/defork/defork.c +++ b/examples/defork/defork.c @@ -37,8 +37,6 @@ __attribute__((constructor)) void preeny_fork_orig() { pid_t fork(void) { - printf("called fork. forked state is %d\n", (int) forked); - fflush(stdout); /* If we forked before, or if we're in the child (pid==0), we don't want to fork anymore, else, we are still in the forkserver. The forkserver parent needs to fork infinite times, each child should never diff --git a/examples/defork/forking_target.c b/examples/defork/forking_target.c index ff1d6e37..98f6365a 100644 --- a/examples/defork/forking_target.c +++ b/examples/defork/forking_target.c @@ -37,10 +37,12 @@ int main(int argc, char **argv) { } else { - printf("We are in the parent - defork didn't work! :( (pid=%d)\n", (int) pid); + printf("We are in the parent - defork didn't work! :( (pid=%d)\n", + (int)pid); } return 0; } + -- cgit 1.4.1 From 6513bca07e590024480a95de8c57c9547987032d Mon Sep 17 00:00:00 2001 From: Sergio Paganoni Date: Thu, 16 Jul 2020 11:47:36 +0200 Subject: Update post_library_gif.so.c (#454) --- examples/custom_mutators/post_library_gif.so.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/custom_mutators/post_library_gif.so.c b/examples/custom_mutators/post_library_gif.so.c index 9b76ead5..2d72400c 100644 --- a/examples/custom_mutators/post_library_gif.so.c +++ b/examples/custom_mutators/post_library_gif.so.c @@ -83,7 +83,7 @@ typedef struct post_state { } post_state_t; -void *afl afl_custom_init(void *afl) { +void *afl_custom_init(void *afl) { post_state_t *state = malloc(sizeof(post_state_t)); if (!state) { -- cgit 1.4.1