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/*.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++

View File

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

View File

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

View File

@ -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; \
\
} while (0)
#define MAX_CMDLINE_LEN 100000
@ -55,7 +63,7 @@ static char** afl_init_argv(int* argc) {
char* ptr = in_buf;
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++;
}
@ -78,3 +87,4 @@ static char** afl_init_argv(int* argc) {
#undef MAX_CMDLINE_PAR
#endif /* !_HAVE_ARGV_FUZZ_INL */

View File

@ -28,7 +28,6 @@
#include <signal.h>
#include <string.h>
/* Main entry point. */
int main(int argc, char** argv) {
@ -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;
}

View File

@ -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,
@ -117,3 +117,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
return new_buf;
}

View File

@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_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

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

View File

@ -705,13 +705,40 @@ 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")) {
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);
}
}
if (getenv("AFL_LD_PRELOAD"))
FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");