about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--examples/defork/Makefile64
-rw-r--r--examples/defork/README.md11
-rw-r--r--examples/defork/defork.c52
-rwxr-xr-xexamples/defork/forking_targetbin0 -> 19520 bytes
-rw-r--r--examples/defork/forking_target.c46
5 files changed, 173 insertions, 0 deletions
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 <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;
+
+}
+
diff --git a/examples/defork/forking_target b/examples/defork/forking_target
new file mode 100755
index 00000000..0f7a04fc
--- /dev/null
+++ b/examples/defork/forking_target
Binary files differdiff --git a/examples/defork/forking_target.c b/examples/defork/forking_target.c
new file mode 100644
index 00000000..ff1d6e37
--- /dev/null
+++ b/examples/defork/forking_target.c
@@ -0,0 +1,46 @@
+#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;
+
+}