added initial defork example

This commit is contained in:
Dominik Maier
2020-07-16 02:17:05 +02:00
parent 4314e59af9
commit f465a75b65
5 changed files with 173 additions and 0 deletions

64
examples/defork/Makefile Normal file
View File

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

11
examples/defork/README.md Normal file
View File

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

52
examples/defork/defork.c Normal file
View File

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

BIN
examples/defork/forking_target Executable file

Binary file not shown.

View File

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