added initial defork example
ADD
examples/defork/Makefile
+#
+# 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

ADD
examples/defork/README.md
+# 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.

ADD
examples/defork/defork.c
+#define __GNU_SOURCE
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#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;
+
+}
+

ADD
examples/defork/forking_target
examples/defork/forking_target
Binary files /dev/null and b/examples/defork/forking_target differ

ADD
examples/defork/forking_target.c
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+/* 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 <input>\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;
+
+}

added initial defork example