From f465a75b6592e4c30b0465f63beda166a8e09045 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 16 Jul 2020 02:17:05 +0200 Subject: [PATCH] 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 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 0000000000000000000000000000000000000000..0f7a04fc30700b545ddd404a197846735b5def6f GIT binary patch literal 19520 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 +#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; + +}