qemu ld_preload support and added socket_fuzzing ld_preload library

This commit is contained in:
van Hauser
2019-12-24 20:56:10 +01:00
parent 3122790295
commit 67b6298895
13 changed files with 230 additions and 42 deletions

View File

@ -274,6 +274,8 @@ code-format:
./.custom-format.py -i gcc_plugin/*.c ./.custom-format.py -i gcc_plugin/*.c
#./.custom-format.py -i gcc_plugin/*.h #./.custom-format.py -i gcc_plugin/*.h
./.custom-format.py -i gcc_plugin/*.cc ./.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/patches/*.h
./.custom-format.py -i qemu_mode/libcompcov/*.c ./.custom-format.py -i qemu_mode/libcompcov/*.c
./.custom-format.py -i qemu_mode/libcompcov/*.cc ./.custom-format.py -i qemu_mode/libcompcov/*.cc
@ -316,6 +318,7 @@ clean:
-$(MAKE) -C gcc_plugin clean -$(MAKE) -C gcc_plugin clean
$(MAKE) -C libdislocator clean $(MAKE) -C libdislocator clean
$(MAKE) -C libtokencap clean $(MAKE) -C libtokencap clean
$(MAKE) -C experimental/socket_fuzzing clean
$(MAKE) -C experimental/argv_fuzzing clean $(MAKE) -C experimental/argv_fuzzing clean
$(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/unsigaction clean
$(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C qemu_mode/libcompcov clean
@ -327,6 +330,7 @@ distrib: all radamsa
-$(MAKE) -C gcc_plugin -$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator $(MAKE) -C libdislocator
$(MAKE) -C libtokencap $(MAKE) -C libtokencap
$(MAKE) -C experimental/socket_fuzzing
$(MAKE) -C experimental/argv_fuzzing $(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_support.sh cd unicorn_mode && sh ./build_unicorn_support.sh
@ -334,6 +338,7 @@ distrib: all radamsa
binary-only: all radamsa binary-only: all radamsa
$(MAKE) -C libdislocator $(MAKE) -C libdislocator
$(MAKE) -C libtokencap $(MAKE) -C libtokencap
$(MAKE) -C experimental/socket_fuzzing
$(MAKE) -C experimental/argv_fuzzing $(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_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 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 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 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 $(MAKE) -C experimental/argv_fuzzing install
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++ set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++

View File

@ -17,8 +17,10 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
Version ++2.59d (develop): 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
-------------------------- --------------------------

View File

@ -23,12 +23,13 @@ LDFLAGS = -shared -ldl
all: argvfuzz32.so argvfuzz64.so all: argvfuzz32.so argvfuzz64.so
argvfuzz32.so: argvfuzz.c 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 argvfuzz64.so: argvfuzz.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ -$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
install: argvfuzz32.so argvfuzz64.so 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 if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/ install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/

View File

@ -17,7 +17,7 @@
#include "/path/to/argv-fuzz-inl.h" #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 standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of
main(). main().
@ -36,12 +36,20 @@
#include <unistd.h> #include <unistd.h>
#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0) #define AFL_INIT_ARGV() \
do { \
#define AFL_INIT_SET0(_p) do { \ \
argv = afl_init_argv(&argc); \ argv = afl_init_argv(&argc); \
argv[0] = (_p); \ \
if (!argc) argc = 1; \ } while (0)
#define AFL_INIT_SET0(_p) \
do { \
\
argv = afl_init_argv(&argc); \
argv[0] = (_p); \
if (!argc) argc = 1; \
\
} while (0) } while (0)
#define MAX_CMDLINE_LEN 100000 #define MAX_CMDLINE_LEN 100000
@ -53,9 +61,9 @@ static char** afl_init_argv(int* argc) {
static char* ret[MAX_CMDLINE_PAR]; static char* ret[MAX_CMDLINE_PAR];
char* ptr = in_buf; 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) { while (*ptr) {
@ -63,7 +71,8 @@ static char** afl_init_argv(int* argc) {
if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++; if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
rc++; rc++;
while (*ptr) ptr++; while (*ptr)
ptr++;
ptr++; ptr++;
} }
@ -77,4 +86,5 @@ static char** afl_init_argv(int* argc) {
#undef MAX_CMDLINE_LEN #undef MAX_CMDLINE_LEN
#undef MAX_CMDLINE_PAR #undef MAX_CMDLINE_PAR
#endif /* !_HAVE_ARGV_FUZZ_INL */ #endif /* !_HAVE_ARGV_FUZZ_INL */

View File

@ -28,12 +28,11 @@
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
/* Main entry point. */ /* Main entry point. */
int main(int argc, char** argv) { 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 char buf[100]; /* Example-only buffer, you'd replace it with other global or
local variables appropriate for your use case. */ 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!'. */ We just have some trivial inline code that faults on 'foo!'. */
/* do we have enough data? */ /* do we have enough data? */
if (len < 4) if (len < 4) return 0;
return 0;
if (buf[0] == 'f') { if (buf[0] == 'f') {
printf("one\n"); printf("one\n");
if (buf[1] == 'o') { if (buf[1] == 'o') {
printf("two\n"); printf("two\n");
if (buf[2] == 'o') { if (buf[2] == 'o') {
printf("three\n"); printf("three\n");
if (buf[3] == '!') { if (buf[3] == '!') {
printf("four\n"); printf("four\n");
abort(); abort();
} }
} }
} }
} }
/*** END PLACEHOLDER CODE ***/ /*** END PLACEHOLDER CODE ***/
@ -92,3 +98,4 @@ int main(int argc, char** argv) {
return 0; return 0;
} }

View File

@ -21,9 +21,9 @@
in the targeted binary (as shown in ../libpng_no_checksum/). One possible in the targeted binary (as shown in ../libpng_no_checksum/). One possible
exception is the process of fuzzing binary-only software in QEMU mode. exception is the process of fuzzing binary-only software in QEMU mode.
2) The use of postprocessors for anything other than checksums is questionable 2) The use of postprocessors for anything other than checksums is
and may cause more harm than good. AFL is normally pretty good about questionable and may cause more harm than good. AFL is normally pretty good
dealing with length fields, magic values, etc. about dealing with length fields, magic values, etc.
3) Postprocessors that do anything non-trivial must be extremely robust to 3) Postprocessors that do anything non-trivial must be extremely robust to
gracefully handle malformed data and other error conditions - otherwise, gracefully handle malformed data and other error conditions - otherwise,
@ -77,10 +77,10 @@
/* The actual postprocessor routine called by afl-fuzz: */ /* The actual postprocessor routine called by afl-fuzz: */
const unsigned char* afl_postprocess(const unsigned char* in_buf, const unsigned char* afl_postprocess(const unsigned char* in_buf,
unsigned int* len) { unsigned int* len) {
static unsigned char* saved_buf; static unsigned char* saved_buf;
unsigned char* new_buf; unsigned char* new_buf;
/* Skip execution altogether for buffers shorter than 6 bytes (just to /* Skip execution altogether for buffers shorter than 6 bytes (just to
show how it's done). We can trust *len to be sane. */ 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; return new_buf;
} }

View File

@ -36,13 +36,13 @@
#define UP4K(_i) ((((_i) >> 12) + 1) << 12) #define UP4K(_i) ((((_i) >> 12) + 1) << 12)
const unsigned char* afl_postprocess(const unsigned char* in_buf, const unsigned char* afl_postprocess(const unsigned char* in_buf,
unsigned int* len) { unsigned int* len) {
static unsigned char* saved_buf; static unsigned char* saved_buf;
static unsigned int saved_len; static unsigned int saved_len;
unsigned char* new_buf = (unsigned char*)in_buf; 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 /* Don't do anything if there's not enough room for the PNG header
(8 bytes). */ (8 bytes). */
@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
return new_buf; return new_buf;
} }

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -444,7 +444,7 @@ int main(int argc, char** argv) {
} }
#ifndef __ANDROID__ #ifndef __ANDROID__
find_obj(argv[0]); find_obj(argv[0]);
#endif #endif

View File

@ -576,10 +576,10 @@ void show_stats(void) {
" imported : " cRST "%-10s" bSTG bV "\n", " imported : " cRST "%-10s" bSTG bV "\n",
tmp, sync_id ? DI(queued_imported) : (u8*)"n/a"); tmp, sync_id ? DI(queued_imported) : (u8*)"n/a");
sprintf(tmp, "%s/%s, %s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(stage_finds[STAGE_HAVOC]),
DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]), DI(stage_finds[STAGE_SPLICE]),
DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE]), DI(stage_finds[STAGE_RADAMSA]),
DI(stage_finds[STAGE_RADAMSA]), DI(stage_cycles[STAGE_RADAMSA])); DI(stage_cycles[STAGE_RADAMSA]));
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp); SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
@ -596,13 +596,12 @@ void show_stats(void) {
: cRST), : cRST),
tmp); tmp);
sprintf(tmp, "%s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s", DI(stage_finds[STAGE_PYTHON]),
DI(stage_finds[STAGE_PYTHON]), DI(stage_cycles[STAGE_PYTHON]), DI(stage_cycles[STAGE_PYTHON]), DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
DI(stage_cycles[STAGE_CUSTOM_MUTATOR])); DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
"\n", tmp); tmp);
if (!bytes_trim_out) { if (!bytes_trim_out) {
@ -639,13 +638,11 @@ void show_stats(void) {
sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]), sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
DI(stage_cycles[STAGE_CUSTOM_MUTATOR])); DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
tmp);
} else { } else {
SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, tmp);
tmp);
} }
@ -691,7 +688,7 @@ void show_stats(void) {
} else } else
SAYF("\r"); SAYF("\r");
/* Last line */ /* Last line */
SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);

View File

@ -705,10 +705,37 @@ int main(int argc, char** argv) {
if (dumb_mode == 2 && no_forkserver) if (dumb_mode == 2 && no_forkserver)
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); 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")) { if (getenv("AFL_PRELOAD")) {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); if (qemu_mode) {
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
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);
}
} }