diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | docs/ChangeLog | 6 | ||||
-rw-r--r-- | experimental/argv_fuzzing/Makefile | 5 | ||||
-rw-r--r-- | experimental/argv_fuzzing/argv-fuzz-inl.h | 28 | ||||
-rw-r--r-- | experimental/persistent_demo/persistent_demo.c | 15 | ||||
-rw-r--r-- | experimental/post_library/post_library.so.c | 11 | ||||
-rw-r--r-- | experimental/post_library/post_library_png.so.c | 5 | ||||
-rw-r--r-- | experimental/socket_fuzzing/Makefile | 35 | ||||
-rw-r--r-- | experimental/socket_fuzzing/README.md | 11 | ||||
-rw-r--r-- | experimental/socket_fuzzing/socketfuzz.c | 90 | ||||
-rw-r--r-- | llvm_mode/afl-clang-fast.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 25 | ||||
-rw-r--r-- | src/afl-fuzz.c | 31 |
13 files changed, 229 insertions, 41 deletions
diff --git a/Makefile b/Makefile index f21b6879..1bef1e37 100644 --- a/Makefile +++ b/Makefile @@ -274,6 +274,8 @@ code-format: ./.custom-format.py -i gcc_plugin/*.c #./.custom-format.py -i gcc_plugin/*.h ./.custom-format.py -i gcc_plugin/*.cc + ./.custom-format.py -i experimental/*/*.c + ./.custom-format.py -i experimental/*/*.h ./.custom-format.py -i qemu_mode/patches/*.h ./.custom-format.py -i qemu_mode/libcompcov/*.c ./.custom-format.py -i qemu_mode/libcompcov/*.cc @@ -316,6 +318,7 @@ clean: -$(MAKE) -C gcc_plugin clean $(MAKE) -C libdislocator clean $(MAKE) -C libtokencap clean + $(MAKE) -C experimental/socket_fuzzing clean $(MAKE) -C experimental/argv_fuzzing clean $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean @@ -327,6 +330,7 @@ distrib: all radamsa -$(MAKE) -C gcc_plugin $(MAKE) -C libdislocator $(MAKE) -C libtokencap + $(MAKE) -C experimental/socket_fuzzing $(MAKE) -C experimental/argv_fuzzing cd qemu_mode && sh ./build_qemu_support.sh cd unicorn_mode && sh ./build_unicorn_support.sh @@ -334,6 +338,7 @@ distrib: all radamsa binary-only: all radamsa $(MAKE) -C libdislocator $(MAKE) -C libtokencap + $(MAKE) -C experimental/socket_fuzzing $(MAKE) -C experimental/argv_fuzzing cd qemu_mode && sh ./build_qemu_support.sh cd unicorn_mode && sh ./build_unicorn_support.sh @@ -385,6 +390,7 @@ endif if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi + $(MAKE) -C experimental/socket_fuzzing install $(MAKE) -C experimental/argv_fuzzing install set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++ diff --git a/docs/ChangeLog b/docs/ChangeLog index 5fd004b1..92fd08ec 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,8 +17,10 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. Version ++2.59d (develop): -------------------------- - - your patch? :-) - + - added ./experimental/argv_fuzzing ld_preload library by Kjell Braden + - added preeny's desock_dup ld_preload library as + ./experimental/socket_fuzzing for network fuzzing + - we now set QEMU_SET_ENV from AFL_PRELOAD when qemu_mode is used -------------------------- diff --git a/experimental/argv_fuzzing/Makefile b/experimental/argv_fuzzing/Makefile index a8858a39..25b6f1f6 100644 --- a/experimental/argv_fuzzing/Makefile +++ b/experimental/argv_fuzzing/Makefile @@ -23,12 +23,13 @@ LDFLAGS = -shared -ldl all: argvfuzz32.so argvfuzz64.so argvfuzz32.so: argvfuzz.c - $(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)" + -$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)" argvfuzz64.so: argvfuzz.c - $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ + -$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ install: argvfuzz32.so argvfuzz64.so + install -d -m 755 $(DESTDIR)$(HELPER_PATH)/ if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/ diff --git a/experimental/argv_fuzzing/argv-fuzz-inl.h b/experimental/argv_fuzzing/argv-fuzz-inl.h index 5d411046..6b9be654 100644 --- a/experimental/argv_fuzzing/argv-fuzz-inl.h +++ b/experimental/argv_fuzzing/argv-fuzz-inl.h @@ -17,7 +17,7 @@ #include "/path/to/argv-fuzz-inl.h" - ...to the file containing main(), ideally placing it after all the + ...to the file containing main(), ideally placing it after all the standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of main(). @@ -36,12 +36,20 @@ #include <unistd.h> -#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0) +#define AFL_INIT_ARGV() \ + do { \ + \ + argv = afl_init_argv(&argc); \ + \ + } while (0) -#define AFL_INIT_SET0(_p) do { \ +#define AFL_INIT_SET0(_p) \ + do { \ + \ argv = afl_init_argv(&argc); \ - argv[0] = (_p); \ - if (!argc) argc = 1; \ + argv[0] = (_p); \ + if (!argc) argc = 1; \ + \ } while (0) #define MAX_CMDLINE_LEN 100000 @@ -53,9 +61,9 @@ static char** afl_init_argv(int* argc) { static char* ret[MAX_CMDLINE_PAR]; char* ptr = in_buf; - int rc = 0; + int rc = 0; - if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0); + if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {} while (*ptr) { @@ -63,7 +71,8 @@ static char** afl_init_argv(int* argc) { if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; rc++; - while (*ptr) ptr++; + while (*ptr) + ptr++; ptr++; } @@ -77,4 +86,5 @@ static char** afl_init_argv(int* argc) { #undef MAX_CMDLINE_LEN #undef MAX_CMDLINE_PAR -#endif /* !_HAVE_ARGV_FUZZ_INL */ +#endif /* !_HAVE_ARGV_FUZZ_INL */ + diff --git a/experimental/persistent_demo/persistent_demo.c b/experimental/persistent_demo/persistent_demo.c index a94c8374..d8d59905 100644 --- a/experimental/persistent_demo/persistent_demo.c +++ b/experimental/persistent_demo/persistent_demo.c @@ -28,12 +28,11 @@ #include <signal.h> #include <string.h> - /* Main entry point. */ int main(int argc, char** argv) { - ssize_t len; /* how much input did we read? */ + ssize_t len; /* how much input did we read? */ char buf[100]; /* Example-only buffer, you'd replace it with other global or local variables appropriate for your use case. */ @@ -64,21 +63,28 @@ int main(int argc, char** argv) { We just have some trivial inline code that faults on 'foo!'. */ /* do we have enough data? */ - if (len < 4) - return 0; + if (len < 4) return 0; if (buf[0] == 'f') { + printf("one\n"); if (buf[1] == 'o') { + printf("two\n"); if (buf[2] == 'o') { + printf("three\n"); if (buf[3] == '!') { + printf("four\n"); abort(); + } + } + } + } /*** END PLACEHOLDER CODE ***/ @@ -92,3 +98,4 @@ int main(int argc, char** argv) { return 0; } + diff --git a/experimental/post_library/post_library.so.c b/experimental/post_library/post_library.so.c index 048eea70..90d45e3f 100644 --- a/experimental/post_library/post_library.so.c +++ b/experimental/post_library/post_library.so.c @@ -21,9 +21,9 @@ in the targeted binary (as shown in ../libpng_no_checksum/). One possible exception is the process of fuzzing binary-only software in QEMU mode. - 2) The use of postprocessors for anything other than checksums is questionable - and may cause more harm than good. AFL is normally pretty good about - dealing with length fields, magic values, etc. + 2) The use of postprocessors for anything other than checksums is + questionable and may cause more harm than good. AFL is normally pretty good + about dealing with length fields, magic values, etc. 3) Postprocessors that do anything non-trivial must be extremely robust to gracefully handle malformed data and other error conditions - otherwise, @@ -77,10 +77,10 @@ /* The actual postprocessor routine called by afl-fuzz: */ const unsigned char* afl_postprocess(const unsigned char* in_buf, - unsigned int* len) { + unsigned int* len) { static unsigned char* saved_buf; - unsigned char* new_buf; + unsigned char* new_buf; /* Skip execution altogether for buffers shorter than 6 bytes (just to show how it's done). We can trust *len to be sane. */ @@ -117,3 +117,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf, return new_buf; } + diff --git a/experimental/post_library/post_library_png.so.c b/experimental/post_library/post_library_png.so.c index 6ba95c1a..093c6022 100644 --- a/experimental/post_library/post_library_png.so.c +++ b/experimental/post_library/post_library_png.so.c @@ -36,13 +36,13 @@ #define UP4K(_i) ((((_i) >> 12) + 1) << 12) const unsigned char* afl_postprocess(const unsigned char* in_buf, - unsigned int* len) { + unsigned int* len) { static unsigned char* saved_buf; static unsigned int saved_len; unsigned char* new_buf = (unsigned char*)in_buf; - unsigned int pos = 8; + unsigned int pos = 8; /* Don't do anything if there's not enough room for the PNG header (8 bytes). */ @@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf, return new_buf; } + diff --git a/experimental/socket_fuzzing/Makefile b/experimental/socket_fuzzing/Makefile new file mode 100644 index 00000000..b4ed9456 --- /dev/null +++ b/experimental/socket_fuzzing/Makefile @@ -0,0 +1,35 @@ +# +# american fuzzy lop++ - socket_fuzz +# ---------------------------------- +# +# 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 -ldl + +all: socketfuzz32.so socketfuzz64.so + +socketfuzz32.so: socketfuzz.c + -$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)" + +socketfuzz64.so: socketfuzz.c + -$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ + +install: socketfuzz32.so socketfuzz64.so + install -d -m 755 $(DESTDIR)$(HELPER_PATH)/ + if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi + install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/ + +clean: + rm -f socketfuzz32.so socketfuzz64.so diff --git a/experimental/socket_fuzzing/README.md b/experimental/socket_fuzzing/README.md new file mode 100644 index 00000000..79f28bea --- /dev/null +++ b/experimental/socket_fuzzing/README.md @@ -0,0 +1,11 @@ +# socketfuzz + +when you want to fuzz a network service and you can not/do not want to modify +the source (or just have a binary), then this LD_PRELOAD library will allow +for sending input to stdin which the target binary will think is coming from +a network socket. + +This is desock_dup.c from the amazing preeny project +https://github.com/zardus/preeny + +It is packaged in afl++ to have it at hand if needed diff --git a/experimental/socket_fuzzing/socketfuzz.c b/experimental/socket_fuzzing/socketfuzz.c new file mode 100644 index 00000000..bd6b68ff --- /dev/null +++ b/experimental/socket_fuzzing/socketfuzz.c @@ -0,0 +1,90 @@ +/* + * This is desock_dup.c from the amazing preeny project + * https://github.com/zardus/preeny + * + * It is packaged in afl++ to have it at hand if needed + * + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> // +#include <sys/socket.h> // +#include <sys/stat.h> // +#include <fcntl.h> // +#include <netinet/in.h> +#include <pthread.h> +#include <signal.h> +#include <dlfcn.h> +#include <errno.h> +#include <stdio.h> +#include <poll.h> +//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: " + +// +// originals +// +int (*original_close)(int); +int (*original_dup2)(int, int); +__attribute__((constructor)) void preeny_desock_dup_orig() { + + original_close = dlsym(RTLD_NEXT, "close"); + original_dup2 = dlsym(RTLD_NEXT, "dup2"); + +} + +int close(int sockfd) { + + if (sockfd <= 2) { + + fprintf(stderr, "Info: Disabling close on %d\n", sockfd); + return 0; + + } else { + + return original_close(sockfd); + + } + +} + +int dup2(int old, int new) { + + if (new <= 2) { + + fprintf(stderr, "Info: Disabling dup from %d to %d\n", old, new); + return 0; + + } else { + + return original_dup2(old, new); + + } + +} + +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + + fprintf(stderr, "Info: Emulating accept on %d\n", sockfd); + return 0; + +} + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + + fprintf(stderr, "Info: Emulating bind on port %d\n", + ntohs(((struct sockaddr_in *)addr)->sin_port)); + return 0; + +} + +int listen(int sockfd, int backlog) { + + return 0; + +} + diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 6f6d55ed..fe91a01b 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -444,7 +444,7 @@ int main(int argc, char** argv) { } -#ifndef __ANDROID__ +#ifndef __ANDROID__ find_obj(argv[0]); #endif diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 485e2aaa..fa4be50f 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -576,10 +576,10 @@ void show_stats(void) { " imported : " cRST "%-10s" bSTG bV "\n", tmp, sync_id ? DI(queued_imported) : (u8*)"n/a"); - sprintf(tmp, "%s/%s, %s/%s, %s/%s", - DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), - DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE]), - DI(stage_finds[STAGE_RADAMSA]), DI(stage_cycles[STAGE_RADAMSA])); + sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(stage_finds[STAGE_HAVOC]), + DI(stage_cycles[STAGE_HAVOC]), DI(stage_finds[STAGE_SPLICE]), + DI(stage_cycles[STAGE_SPLICE]), DI(stage_finds[STAGE_RADAMSA]), + DI(stage_cycles[STAGE_RADAMSA])); SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp); @@ -596,13 +596,12 @@ void show_stats(void) { : cRST), tmp); - sprintf(tmp, "%s/%s, %s/%s", - DI(stage_finds[STAGE_PYTHON]), DI(stage_cycles[STAGE_PYTHON]), - DI(stage_finds[STAGE_CUSTOM_MUTATOR]), + sprintf(tmp, "%s/%s, %s/%s", DI(stage_finds[STAGE_PYTHON]), + DI(stage_cycles[STAGE_PYTHON]), DI(stage_finds[STAGE_CUSTOM_MUTATOR]), DI(stage_cycles[STAGE_CUSTOM_MUTATOR])); - SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB - "\n", tmp); + SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n", + tmp); if (!bytes_trim_out) { @@ -639,13 +638,11 @@ void show_stats(void) { sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]), DI(stage_cycles[STAGE_CUSTOM_MUTATOR])); - SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, - tmp); + SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp); } else { - SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, - tmp); + SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, tmp); } @@ -691,7 +688,7 @@ void show_stats(void) { } else SAYF("\r"); - + /* Last line */ SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 3a5b0b4e..54fdcc25 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -705,10 +705,37 @@ int main(int argc, char** argv) { if (dumb_mode == 2 && no_forkserver) FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); + if (getenv("LD_PRELOAD")) + WARNF( + "LD_PRELOAD is set, are you sure that is want to you want to do " + "instead of using AFL_PRELOAD?"); + if (getenv("AFL_PRELOAD")) { - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); + if (qemu_mode) { + + char* qemu_preload = getenv("QEMU_SET_ENV"); + char buf[4096]; + + if (qemu_preload) { + + snprintf(buf, sizeof(buf), "%s,LD_PRELOAD=%s", qemu_preload, + getenv("AFL_PRELOAD")); + + } else { + + snprintf(buf, sizeof(buf), "LD_PRELOAD=%s", getenv("AFL_PRELOAD")); + + } + + setenv("QEMU_SET_ENV", buf, 1); + + } else { + + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); + setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); + + } } |