argvfuzz preload for fuzzing binaries' argv
MODIFY
Makefile
Makefile
@@ -316,6 +316,7 @@ clean:
-$(MAKE) -C gcc_plugin clean
$(MAKE) -C libdislocator clean
$(MAKE) -C libtokencap clean
+ $(MAKE) -C experimental/argv_fuzzing clean
$(MAKE) -C qemu_mode/unsigaction clean
$(MAKE) -C qemu_mode/libcompcov clean
$(MAKE) -C src/third_party/libradamsa/ clean
@@ -326,12 +327,14 @@ distrib: all radamsa
-$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
+ $(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_support.sh
binary-only: all radamsa
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
+ $(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_support.sh
@@ -382,6 +385,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/argv_fuzzing install
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi

ADD
experimental/argv_fuzzing/Makefile
+#
+# american fuzzy lop - argvfuzz
+# --------------------------------
+#
+# Copyright 2019 Kjell Braden <afflux@pentabarf.de>
+#
+# 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
+
+ifndef AFL_NO_X86
+PREFIX ?= /usr/local
+BIN_PATH = $(PREFIX)/bin
+HELPER_PATH = $(PREFIX)/lib/afl
+
+CFLAGS = -fPIC -Wall -Wextra
+LDFLAGS = -shared -ldl
+
+all: argvfuzz32.so argvfuzz64.so
+
+argvfuzz32.so: argvfuzz.c
+ $(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
+
+argvfuzz64.so: argvfuzz.c
+ $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
+
+install: argvfuzz32.so argvfuzz64.so
+ if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
+ install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/
+
+clean:
+ rm -f argvfuzz32.so argvfuzz64.so
+
+else
+
+all:
+ @echo "[!] Note: skipping compilation of argvfuzz (AFL_NO_X86 set)."
+
+install:
+
+clean:
+
+endif

ADD
experimental/argv_fuzzing/README.md
+# argvfuzz
+
+afl supports fuzzing file inputs or stdin. When source is available,
+`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin.
+
+`argvfuzz` tries to provide the same functionality for binaries. When loaded
+using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace
+argv using the same logic of `argv-fuzz-inl.h`.
+
+A few conditions need to be fulfilled for this mechanism to work correctly:
+
+1. As it relies on hooking the loader, it cannot work on static binaries.
+2. If the target binary does not use the default libc's `_start` implementation
+ (crt1.o), the hook may not run.
+3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the
+ target binary expects argv to be living on the stack, things may go wrong.

ADD
experimental/argv_fuzzing/argvfuzz.c
+/*
+ american fuzzy lop - LD_PRELOAD for fuzzing argv in binaries
+ ------------------------------------------------------------
+
+ Copyright 2019 Kjell Braden <afflux@pentabarf.de>
+
+ 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
+
+ */
+
+#define _GNU_SOURCE /* for RTLD_NEXT */
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "argv-fuzz-inl.h"
+
+int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
+ void (*init)(void), void (*fini)(void),
+ void (*rtld_fini)(void), void *stack_end) {
+
+ int (*orig)(int (*main)(int, char **, char **), int argc, char **argv,
+ void (*init)(void), void (*fini)(void), void (*rtld_fini)(void),
+ void *stack_end);
+ int sub_argc;
+ char **sub_argv;
+
+ (void)argc;
+ (void)argv;
+
+ orig = dlsym(RTLD_NEXT, __func__);
+
+ if (!orig) {
+
+ fprintf(stderr, "hook did not find original %s: %s\n", __func__, dlerror());
+ exit(EXIT_FAILURE);
+
+ }
+
+ sub_argv = afl_init_argv(&sub_argc);
+
+ return orig(main, sub_argc, sub_argv, init, fini, rtld_fini, stack_end);
+
+}
+

argvfuzz preload for fuzzing binaries' argv