mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-18 20:48:07 +00:00
added initial defork example
This commit is contained in:
64
examples/defork/Makefile
Normal file
64
examples/defork/Makefile
Normal 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
11
examples/defork/README.md
Normal 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
52
examples/defork/defork.c
Normal 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
BIN
examples/defork/forking_target
Executable file
Binary file not shown.
46
examples/defork/forking_target.c
Normal file
46
examples/defork/forking_target.c
Normal 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;
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user