mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 14:43:22 +00:00
Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
842cd9dec3 | |||
4b4effe343 | |||
c3bb0a3421 | |||
878a80de7f | |||
f7e1397d98 | |||
e90fa623d9 | |||
9829c5eb95 | |||
3f23f40a56 | |||
cd2cae720b | |||
65b4141cd3 | |||
58c7a0f8fe | |||
9a2f2f1ee9 | |||
c983e2c5b1 | |||
2eb88d31a4 | |||
0fb68cbbfa | |||
064cd3315c | |||
cc3bf762ec | |||
29bbe0aebe | |||
33ce5829c3 | |||
a05bd3e477 | |||
9ed4bfbca8 | |||
67b6298895 | |||
3122790295 | |||
5aa089d1b2 | |||
b0a2160c3a | |||
4f343e791a | |||
7db87ec74b | |||
8679f3d757 | |||
65bafe7192 | |||
49b3c9e0a0 | |||
e244f85c0b | |||
cc151388a1 | |||
5f0a252fae | |||
d8fb4a8e19 | |||
5e53d337db | |||
b91000fc9e | |||
ce3cd71dc0 | |||
c283487d94 | |||
fe74c68c42 | |||
a521bfdfd8 | |||
d7b6b810d1 | |||
7028c9b59d | |||
891f067051 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "unicorn_mode/unicorn"]
|
||||
path = unicorn_mode/unicorn
|
||||
url = https://github.com/vanhauser-thc/unicorn.git
|
21
Makefile
21
Makefile
@ -104,7 +104,7 @@ endif
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
|
||||
|
||||
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 )" "1"
|
||||
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
PYTHON_OK=1
|
||||
PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB)
|
||||
else
|
||||
@ -122,7 +122,7 @@ ifdef STATIC
|
||||
LDFLAGS += -lm -lrt -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -145,6 +145,7 @@ man: $(MANPAGES)
|
||||
|
||||
tests: source-only
|
||||
@cd test ; ./test.sh
|
||||
@rm -f test/errors
|
||||
|
||||
performance-tests: performance-test
|
||||
test-performance: performance-test
|
||||
@ -274,10 +275,14 @@ code-format:
|
||||
./.custom-format.py -i gcc_plugin/*.c
|
||||
#./.custom-format.py -i gcc_plugin/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i experimental/*/*.c
|
||||
./.custom-format.py -i experimental/*/*.h
|
||||
./.custom-format.py -i qemu_mode/patches/*.h
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.h
|
||||
./.custom-format.py -i qbdi_mode/*.c
|
||||
./.custom-format.py -i qbdi_mode/*.cpp
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
|
||||
@ -316,22 +321,28 @@ clean:
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C experimental/socket_fuzzing clean
|
||||
$(MAKE) -C experimental/argv_fuzzing clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C src/third_party/libradamsa/ clean
|
||||
$(MAKE) -C unicorn_mode/unicorn clean
|
||||
-rm -rf unicorn_mode/unicorn
|
||||
|
||||
distrib: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C experimental/socket_fuzzing
|
||||
$(MAKE) -C experimental/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
binary-only: all radamsa
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C experimental/socket_fuzzing
|
||||
$(MAKE) -C experimental/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
@ -361,7 +372,7 @@ source-only: all radamsa
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
install: all $(MANPAGES)
|
||||
mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
@ -382,6 +393,8 @@ endif
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
$(MAKE) -C experimental/socket_fuzzing install
|
||||
$(MAKE) -C experimental/argv_fuzzing install
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
|
||||
|
@ -124,7 +124,7 @@ afl++ binaries by passing the STATIC=1 argument to make:
|
||||
$ make all STATIC=1
|
||||
```
|
||||
|
||||
Note that afl++ is faster and better the newer the compilers used.
|
||||
Note that afl++ is faster and better the newer the compilers used are.
|
||||
Hence gcc-9 and especially llvm-9 should be the compilers of choice.
|
||||
If your distribution does not have them, you can use the Dockerfile:
|
||||
|
||||
|
@ -13,6 +13,20 @@ Want to stay in the loop on major new features? Join our mailing list by
|
||||
sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
|
||||
|
||||
--------------------------
|
||||
Version ++2.59d (develop):
|
||||
--------------------------
|
||||
|
||||
- fixed a critical bug in afl-tmin that was introduced during ++2.53d
|
||||
- added test cases for afl-cmin and afl-tmin to test/test.sh
|
||||
- added ./experimental/argv_fuzzing ld_preload library by Kjell Braden
|
||||
- added preeny's desock_dup ld_preload library as
|
||||
./experimental/socket_fuzzing for network fuzzing
|
||||
- added AFL_AS_FORCE_INSTRUMENT environment variable for afl-as - this is
|
||||
for the retrorewrite project
|
||||
- we now set QEMU_SET_ENV from AFL_PRELOAD when qemu_mode is used
|
||||
|
||||
|
||||
--------------------------
|
||||
Version ++2.59c (release):
|
||||
--------------------------
|
||||
|
@ -65,6 +65,10 @@ tools make fairly broad use of environmental variables:
|
||||
mkdir assembly_here
|
||||
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
|
||||
|
||||
- If you are a weird person that wants to compile and instrument asm
|
||||
text files then use the AFL_AS_FORCE_INSTRUMENT variable:
|
||||
AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo
|
||||
|
||||
- Setting AFL_QUIET will prevent afl-cc and afl-as banners from being
|
||||
displayed during compilation, in case you find them distracting.
|
||||
|
||||
|
37
experimental/argv_fuzzing/Makefile
Normal file
37
experimental/argv_fuzzing/Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# american fuzzy lop - argvfuzz
|
||||
# --------------------------------
|
||||
#
|
||||
# Copyright 2019 Kjell Braden <afflux@pentabarf.de>
|
||||
#
|
||||
# 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 -ldl
|
||||
|
||||
all: argvfuzz32.so argvfuzz64.so
|
||||
|
||||
argvfuzz32.so: argvfuzz.c
|
||||
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
|
||||
|
||||
argvfuzz64.so: argvfuzz.c
|
||||
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
install: argvfuzz32.so argvfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/
|
||||
|
||||
clean:
|
||||
rm -f argvfuzz32.so argvfuzz64.so
|
16
experimental/argv_fuzzing/README.md
Normal file
16
experimental/argv_fuzzing/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# argvfuzz
|
||||
|
||||
afl supports fuzzing file inputs or stdin. When source is available,
|
||||
`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin.
|
||||
|
||||
`argvfuzz` tries to provide the same functionality for binaries. When loaded
|
||||
using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace
|
||||
argv using the same logic of `argv-fuzz-inl.h`.
|
||||
|
||||
A few conditions need to be fulfilled for this mechanism to work correctly:
|
||||
|
||||
1. As it relies on hooking the loader, it cannot work on static binaries.
|
||||
2. If the target binary does not use the default libc's `_start` implementation
|
||||
(crt1.o), the hook may not run.
|
||||
3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the
|
||||
target binary expects argv to be living on the stack, things may go wrong.
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "/path/to/argv-fuzz-inl.h"
|
||||
|
||||
...to the file containing main(), ideally placing it after all the
|
||||
...to the file containing main(), ideally placing it after all the
|
||||
standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of
|
||||
main().
|
||||
|
||||
@ -36,12 +36,20 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0)
|
||||
|
||||
#define AFL_INIT_SET0(_p) do { \
|
||||
#define AFL_INIT_ARGV() \
|
||||
do { \
|
||||
\
|
||||
argv = afl_init_argv(&argc); \
|
||||
argv[0] = (_p); \
|
||||
if (!argc) argc = 1; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define AFL_INIT_SET0(_p) \
|
||||
do { \
|
||||
\
|
||||
argv = afl_init_argv(&argc); \
|
||||
argv[0] = (_p); \
|
||||
if (!argc) argc = 1; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define MAX_CMDLINE_LEN 100000
|
||||
@ -53,9 +61,9 @@ static char** afl_init_argv(int* argc) {
|
||||
static char* ret[MAX_CMDLINE_PAR];
|
||||
|
||||
char* ptr = in_buf;
|
||||
int rc = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0);
|
||||
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {}
|
||||
|
||||
while (*ptr) {
|
||||
|
||||
@ -63,7 +71,8 @@ static char** afl_init_argv(int* argc) {
|
||||
if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
|
||||
rc++;
|
||||
|
||||
while (*ptr) ptr++;
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
ptr++;
|
||||
|
||||
}
|
||||
@ -77,4 +86,5 @@ static char** afl_init_argv(int* argc) {
|
||||
#undef MAX_CMDLINE_LEN
|
||||
#undef MAX_CMDLINE_PAR
|
||||
|
||||
#endif /* !_HAVE_ARGV_FUZZ_INL */
|
||||
#endif /* !_HAVE_ARGV_FUZZ_INL */
|
||||
|
||||
|
49
experimental/argv_fuzzing/argvfuzz.c
Normal file
49
experimental/argv_fuzzing/argvfuzz.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
american fuzzy lop - LD_PRELOAD for fuzzing argv in binaries
|
||||
------------------------------------------------------------
|
||||
|
||||
Copyright 2019 Kjell Braden <afflux@pentabarf.de>
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* for RTLD_NEXT */
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "argv-fuzz-inl.h"
|
||||
|
||||
int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
|
||||
void (*init)(void), void (*fini)(void),
|
||||
void (*rtld_fini)(void), void *stack_end) {
|
||||
|
||||
int (*orig)(int (*main)(int, char **, char **), int argc, char **argv,
|
||||
void (*init)(void), void (*fini)(void), void (*rtld_fini)(void),
|
||||
void *stack_end);
|
||||
int sub_argc;
|
||||
char **sub_argv;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
orig = dlsym(RTLD_NEXT, __func__);
|
||||
|
||||
if (!orig) {
|
||||
|
||||
fprintf(stderr, "hook did not find original %s: %s\n", __func__, dlerror());
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
sub_argv = afl_init_argv(&sub_argc);
|
||||
|
||||
return orig(main, sub_argc, sub_argv, init, fini, rtld_fini, stack_end);
|
||||
|
||||
}
|
||||
|
@ -28,12 +28,11 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Main entry point. */
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
ssize_t len; /* how much input did we read? */
|
||||
ssize_t len; /* how much input did we read? */
|
||||
char buf[100]; /* Example-only buffer, you'd replace it with other global or
|
||||
local variables appropriate for your use case. */
|
||||
|
||||
@ -64,21 +63,28 @@ int main(int argc, char** argv) {
|
||||
We just have some trivial inline code that faults on 'foo!'. */
|
||||
|
||||
/* do we have enough data? */
|
||||
if (len < 4)
|
||||
return 0;
|
||||
if (len < 4) return 0;
|
||||
|
||||
if (buf[0] == 'f') {
|
||||
|
||||
printf("one\n");
|
||||
if (buf[1] == 'o') {
|
||||
|
||||
printf("two\n");
|
||||
if (buf[2] == 'o') {
|
||||
|
||||
printf("three\n");
|
||||
if (buf[3] == '!') {
|
||||
|
||||
printf("four\n");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*** END PLACEHOLDER CODE ***/
|
||||
@ -92,3 +98,4 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
in the targeted binary (as shown in ../libpng_no_checksum/). One possible
|
||||
exception is the process of fuzzing binary-only software in QEMU mode.
|
||||
|
||||
2) The use of postprocessors for anything other than checksums is questionable
|
||||
and may cause more harm than good. AFL is normally pretty good about
|
||||
dealing with length fields, magic values, etc.
|
||||
2) The use of postprocessors for anything other than checksums is
|
||||
questionable and may cause more harm than good. AFL is normally pretty good
|
||||
about dealing with length fields, magic values, etc.
|
||||
|
||||
3) Postprocessors that do anything non-trivial must be extremely robust to
|
||||
gracefully handle malformed data and other error conditions - otherwise,
|
||||
@ -77,10 +77,10 @@
|
||||
/* The actual postprocessor routine called by afl-fuzz: */
|
||||
|
||||
const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
unsigned int* len) {
|
||||
unsigned int* len) {
|
||||
|
||||
static unsigned char* saved_buf;
|
||||
unsigned char* new_buf;
|
||||
unsigned char* new_buf;
|
||||
|
||||
/* Skip execution altogether for buffers shorter than 6 bytes (just to
|
||||
show how it's done). We can trust *len to be sane. */
|
||||
@ -117,3 +117,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
return new_buf;
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,13 @@
|
||||
#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
|
||||
|
||||
const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
unsigned int* len) {
|
||||
unsigned int* len) {
|
||||
|
||||
static unsigned char* saved_buf;
|
||||
static unsigned int saved_len;
|
||||
|
||||
unsigned char* new_buf = (unsigned char*)in_buf;
|
||||
unsigned int pos = 8;
|
||||
unsigned int pos = 8;
|
||||
|
||||
/* Don't do anything if there's not enough room for the PNG header
|
||||
(8 bytes). */
|
||||
@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
return new_buf;
|
||||
|
||||
}
|
||||
|
||||
|
35
experimental/socket_fuzzing/Makefile
Normal file
35
experimental/socket_fuzzing/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# american fuzzy lop++ - socket_fuzz
|
||||
# ----------------------------------
|
||||
#
|
||||
# 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 -ldl
|
||||
|
||||
all: socketfuzz32.so socketfuzz64.so
|
||||
|
||||
socketfuzz32.so: socketfuzz.c
|
||||
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
|
||||
|
||||
socketfuzz64.so: socketfuzz.c
|
||||
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
install: socketfuzz32.so socketfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/
|
||||
|
||||
clean:
|
||||
rm -f socketfuzz32.so socketfuzz64.so
|
11
experimental/socket_fuzzing/README.md
Normal file
11
experimental/socket_fuzzing/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# socketfuzz
|
||||
|
||||
when you want to fuzz a network service and you can not/do not want to modify
|
||||
the source (or just have a binary), then this LD_PRELOAD library will allow
|
||||
for sending input to stdin which the target binary will think is coming from
|
||||
a network socket.
|
||||
|
||||
This is desock_dup.c from the amazing preeny project
|
||||
https://github.com/zardus/preeny
|
||||
|
||||
It is packaged in afl++ to have it at hand if needed
|
110
experimental/socket_fuzzing/socketfuzz.c
Normal file
110
experimental/socket_fuzzing/socketfuzz.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This is desock_dup.c from the amazing preeny project
|
||||
* https://github.com/zardus/preeny
|
||||
*
|
||||
* It is packaged in afl++ to have it at hand if needed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h> //
|
||||
#include <sys/socket.h> //
|
||||
#include <sys/stat.h> //
|
||||
#include <fcntl.h> //
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: "
|
||||
|
||||
//
|
||||
// originals
|
||||
//
|
||||
int (*original_close)(int);
|
||||
int (*original_dup2)(int, int);
|
||||
__attribute__((constructor)) void preeny_desock_dup_orig() {
|
||||
|
||||
original_close = dlsym(RTLD_NEXT, "close");
|
||||
original_dup2 = dlsym(RTLD_NEXT, "dup2");
|
||||
|
||||
}
|
||||
|
||||
int close(int sockfd) {
|
||||
|
||||
if (sockfd <= 2) {
|
||||
|
||||
fprintf(stderr, "Info: Disabling close on %d\n", sockfd);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
return original_close(sockfd);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int dup2(int old, int new) {
|
||||
|
||||
if (new <= 2) {
|
||||
|
||||
fprintf(stderr, "Info: Disabling dup from %d to %d\n", old, new);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
return original_dup2(old, new);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
fprintf(stderr, "Info: Emulating accept on %d\n", sockfd);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
fprintf(stderr, "Info: Emulating bind on port %d\n",
|
||||
ntohs(((struct sockaddr_in *)addr)->sin_port));
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int listen(int sockfd, int backlog) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)backlog;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int setsockopt(int sockfd, int level, int optid, const void *optdata,
|
||||
socklen_t optdatalen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)level;
|
||||
(void)optid;
|
||||
(void)optdata;
|
||||
(void)optdatalen;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ CXX ?= g++
|
||||
|
||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
|
||||
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -126,5 +126,5 @@ vpath % ..
|
||||
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||
rm -f $(PROGS) ../afl-g++-fast ../afl-g*-fast.8
|
||||
|
@ -271,6 +271,7 @@ extern u64 mem_limit; /* Memory cap for child (MB) */
|
||||
extern u8 cal_cycles, /* Calibration cycles defaults */
|
||||
cal_cycles_long, /* Calibration cycles defaults */
|
||||
no_unlink, /* do not unlink cur_input */
|
||||
use_stdin, /* use stdin for sending data */
|
||||
debug, /* Debug mode */
|
||||
custom_only, /* Custom mutator only mode */
|
||||
python_only; /* Python-only mode */
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
/* Version string: */
|
||||
|
||||
#define VERSION "++2.59c" // c = release, d = volatile github dev
|
||||
#define VERSION "++2.59d" // c = release, d = volatile github dev
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
|
@ -38,6 +38,7 @@ clean:
|
||||
rm -f ../libdislocator.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
|
||||
|
||||
|
@ -55,6 +55,7 @@ clean:
|
||||
rm -f ../libtokencap.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.tokencap.md $${DESTDIR}$(HELPER_PATH)
|
||||
|
||||
|
@ -687,6 +687,20 @@ bool strcsequal(const void* s1, const void* s2) {
|
||||
|
||||
}
|
||||
|
||||
/* bcmp/memcmp BSD flavors, similar to CRYPTO_memcmp */
|
||||
|
||||
int timingsafe_bcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
return bcmp(mem1, mem2, len);
|
||||
|
||||
}
|
||||
|
||||
int timingsafe_memcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
return memcmp(mem1, mem2, len);
|
||||
|
||||
}
|
||||
|
||||
/* Init code to open the output file (or default to stderr). */
|
||||
|
||||
__attribute__((constructor)) void __tokencap_init(void) {
|
||||
|
@ -115,7 +115,7 @@ endif
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
|
||||
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -136,8 +136,8 @@ else
|
||||
endif
|
||||
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
CC = $(shell llvm-config --bindir)/clang
|
||||
CXX = $(shell llvm-config --bindir)/clang++
|
||||
CC = $(shell $(LLVM_CONFIG) --bindir)/clang
|
||||
CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
|
||||
endif
|
||||
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
|
@ -49,7 +49,11 @@ static void find_obj(u8* argv0) {
|
||||
|
||||
if (afl_path) {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
|
||||
#else
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);
|
||||
#endif
|
||||
|
||||
if (!access(tmp, R_OK)) {
|
||||
|
||||
@ -73,7 +77,11 @@ static void find_obj(u8* argv0) {
|
||||
dir = ck_strdup(argv0);
|
||||
*slash = '/';
|
||||
|
||||
#ifdef __ANDROID__
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
|
||||
#else
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.o", dir);
|
||||
#endif
|
||||
|
||||
if (!access(tmp, R_OK)) {
|
||||
|
||||
@ -88,8 +96,14 @@ static void find_obj(u8* argv0) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (!access(AFL_PATH "/afl-llvm-rt.so", R_OK)) {
|
||||
|
||||
#else
|
||||
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
|
||||
|
||||
#endif
|
||||
|
||||
obj_path = AFL_PATH;
|
||||
return;
|
||||
|
||||
@ -358,7 +372,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
//#ifndef __ANDROID__ // not sure, we might need these ifdefs for Android
|
||||
#ifndef __ANDROID__
|
||||
switch (bit_mode) {
|
||||
|
||||
case 0:
|
||||
@ -383,7 +397,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -444,10 +458,9 @@ int main(int argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
//#ifndef __ANDROID__ // not sure this is needed for Android, so at the moment
|
||||
//we rather keep this out
|
||||
#ifndef __ANDROID__
|
||||
find_obj(argv[0]);
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
edit_params(argc, argv);
|
||||
|
||||
|
@ -470,7 +470,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLT) {
|
||||
|
||||
auto op0 = selectcmpInst->getOperand(0);
|
||||
@ -655,6 +657,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, m_e0, m_e1);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
Instruction *icmp_exponent;
|
||||
icmp_exponent =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
|
||||
@ -664,6 +667,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
icmp_exponent =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
|
||||
signequal_bb->getInstList().insert(
|
||||
@ -755,6 +759,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
Instruction *icmp_fraction;
|
||||
icmp_fraction =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
|
||||
@ -764,6 +769,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
icmp_fraction =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
|
||||
middle_bb->getInstList().insert(
|
||||
@ -802,6 +808,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
PN->addIncoming(icmp_fraction_result, middle_bb);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
/* if op1 is negative goto true branch,
|
||||
else go on comparing */
|
||||
PN->addIncoming(t_s1, bb);
|
||||
@ -809,6 +816,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
PN->addIncoming(icmp_fraction_result, middle_bb);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
/* if op0 is negative goto true branch,
|
||||
else go on comparing */
|
||||
PN->addIncoming(t_s0, bb);
|
||||
|
@ -114,7 +114,7 @@ void afl_maybe_log(unsigned long cur_loc) {
|
||||
|
||||
if (afl_area_ptr == NULL) { return; }
|
||||
unsigned long afl_idx = cur_loc ^ afl_prev_loc;
|
||||
afl_idx &= MAP_SIZE -1;
|
||||
afl_idx &= MAP_SIZE - 1;
|
||||
INC_AFL_AREA(afl_idx);
|
||||
afl_prev_loc = cur_loc >> 1;
|
||||
|
||||
@ -123,7 +123,7 @@ void afl_maybe_log(unsigned long cur_loc) {
|
||||
char *read_file(char *path, unsigned long *length) {
|
||||
|
||||
unsigned long len;
|
||||
char * buf;
|
||||
char * buf;
|
||||
|
||||
FILE *fp = fopen(path, "rb");
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
@ -44,7 +44,7 @@ echo "[*] Performing basic sanity checks..."
|
||||
if [ ! "`uname -s`" = "Linux" ]; then
|
||||
|
||||
echo "[-] Error: QEMU instrumentation is supported only on Linux."
|
||||
exit 1
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
@ -162,7 +162,7 @@ echo "[+] Patching done."
|
||||
if [ "$STATIC" = "1" ]; then
|
||||
|
||||
CFLAGS="-O3 -ggdb" ./configure --disable-bsd-user --disable-guest-agent --disable-strip --disable-werror \
|
||||
--disable-gcrypt --disable-debug-info --disable-debug-tcg --enable-docs --disable-tcg-interpreter \
|
||||
--disable-gcrypt --disable-debug-info --disable-debug-tcg --disable-tcg-interpreter \
|
||||
--enable-attr --disable-brlapi --disable-linux-aio --disable-bzip2 --disable-bluez --disable-cap-ng \
|
||||
--disable-curl --disable-fdt --disable-glusterfs --disable-gnutls --disable-nettle --disable-gtk \
|
||||
--disable-rdma --disable-libiscsi --disable-vnc-jpeg --enable-kvm --disable-lzo --disable-curses \
|
||||
|
@ -75,13 +75,15 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
static s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||
|
||||
static u8 edges_only, /* Ignore hit counts? */
|
||||
u8 edges_only, /* Ignore hit counts? */
|
||||
use_hex_offsets, /* Show hex offsets? */
|
||||
use_stdin = 1; /* Use stdin for program input? */
|
||||
|
||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
child_timed_out; /* Child timed out? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/* Constants used for describing byte behavior. */
|
||||
|
||||
#define RESP_NONE 0x00 /* Changing byte is a no-op. */
|
||||
@ -709,8 +711,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -834,9 +865,8 @@ static void find_binary(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
@ -208,8 +208,12 @@ static void edit_params(int argc, char** argv) {
|
||||
NSS. */
|
||||
|
||||
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
|
||||
strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/tmp/", 5))
|
||||
strncmp(input_file, "/var/tmp/", 9) &&
|
||||
strncmp(input_file, "/tmp/", 5) &&
|
||||
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL)
|
||||
pass_thru = 1;
|
||||
else if (getenv("AFL_AS_FORCE_INSTRUMENT"))
|
||||
unsetenv("AFL_AS_FORCE_INSTRUMENT");
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
u8* target_path; /* Path to target binary */
|
||||
u8* target_path; /* Path to target binary */
|
||||
extern u8 use_stdin;
|
||||
|
||||
void detect_file_args(char** argv, u8* prog_in) {
|
||||
|
||||
@ -78,6 +79,8 @@ void detect_file_args(char** argv, u8* prog_in) {
|
||||
else
|
||||
aa_subst = alloc_printf("%s/%s", cwd, prog_in);
|
||||
|
||||
use_stdin = 0;
|
||||
|
||||
/* Construct a replacement argv value. */
|
||||
|
||||
*aa_loc = 0;
|
||||
|
@ -43,6 +43,8 @@
|
||||
/* a program that includes afl-forkserver needs to define these */
|
||||
extern u8 uses_asan;
|
||||
extern u8 *trace_bits;
|
||||
extern u8 use_stdin;
|
||||
|
||||
extern s32 forksrv_pid, child_pid, fsrv_ctl_fd, fsrv_st_fd;
|
||||
extern s32 out_fd, out_dir_fd, dev_null_fd; /* initialize these with -1 */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
@ -211,7 +213,7 @@ void init_forkserver(char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (out_file) {
|
||||
if (!use_stdin) {
|
||||
|
||||
dup2(dev_null_fd, 0);
|
||||
|
||||
|
@ -86,6 +86,7 @@ u8 cal_cycles = CAL_CYCLES, /* Calibration cycles defaults */
|
||||
cal_cycles_long = CAL_CYCLES_LONG, /* Calibration cycles defaults */
|
||||
debug, /* Debug mode */
|
||||
no_unlink, /* do not unlink cur_input */
|
||||
use_stdin = 1, /* use stdin for sending data */
|
||||
custom_only, /* Custom mutator only mode */
|
||||
python_only; /* Python-only mode */
|
||||
|
||||
|
@ -345,7 +345,12 @@ u8 trim_case_python(char** argv, struct queue_entry* q, u8* in_buf) {
|
||||
fault = run_target(argv, exec_tmout);
|
||||
++trim_execs;
|
||||
|
||||
if (stop_soon || fault == FAULT_ERROR) goto abort_trimming;
|
||||
if (stop_soon || fault == FAULT_ERROR) {
|
||||
|
||||
free(retbuf);
|
||||
goto abort_trimming;
|
||||
|
||||
}
|
||||
|
||||
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
|
||||
|
||||
@ -381,6 +386,8 @@ u8 trim_case_python(char** argv, struct queue_entry* q, u8* in_buf) {
|
||||
|
||||
}
|
||||
|
||||
free(retbuf);
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % stats_update_freq)) show_stats();
|
||||
|
@ -576,15 +576,12 @@ void show_stats(void) {
|
||||
" imported : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, sync_id ? DI(queued_imported) : (u8*)"n/a");
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s, %s/%s",
|
||||
DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]),
|
||||
DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE]),
|
||||
DI(stage_finds[STAGE_PYTHON]), DI(stage_cycles[STAGE_PYTHON]),
|
||||
DI(stage_finds[STAGE_RADAMSA]), DI(stage_cycles[STAGE_RADAMSA]),
|
||||
DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(stage_finds[STAGE_HAVOC]),
|
||||
DI(stage_cycles[STAGE_HAVOC]), DI(stage_finds[STAGE_SPLICE]),
|
||||
DI(stage_cycles[STAGE_SPLICE]), DI(stage_finds[STAGE_RADAMSA]),
|
||||
DI(stage_cycles[STAGE_RADAMSA]));
|
||||
|
||||
SAYF(bV bSTOP "havoc/custom : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
|
||||
if (t_bytes)
|
||||
sprintf(tmp, "%0.02f%%", stab_ratio);
|
||||
@ -599,6 +596,13 @@ void show_stats(void) {
|
||||
: cRST),
|
||||
tmp);
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s", DI(stage_finds[STAGE_PYTHON]),
|
||||
DI(stage_cycles[STAGE_PYTHON]), DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
|
||||
SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
|
||||
tmp);
|
||||
|
||||
if (!bytes_trim_out) {
|
||||
|
||||
sprintf(tmp, "n/a, ");
|
||||
@ -634,15 +638,11 @@ void show_stats(void) {
|
||||
|
||||
sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB
|
||||
"\n" bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1,
|
||||
tmp);
|
||||
SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
|
||||
|
||||
} else {
|
||||
|
||||
SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB
|
||||
"\n" bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1,
|
||||
tmp);
|
||||
SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, tmp);
|
||||
|
||||
}
|
||||
|
||||
@ -689,6 +689,9 @@ void show_stats(void) {
|
||||
|
||||
SAYF("\r");
|
||||
|
||||
/* Last line */
|
||||
SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
|
||||
|
||||
/* Hallelujah! */
|
||||
|
||||
fflush(0);
|
||||
|
@ -304,6 +304,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (out_file) FATAL("Multiple -f options not supported");
|
||||
out_file = optarg;
|
||||
use_stdin = 0;
|
||||
break;
|
||||
|
||||
case 'x': /* dictionary */
|
||||
@ -705,10 +706,44 @@ int main(int argc, char** argv) {
|
||||
if (dumb_mode == 2 && no_forkserver)
|
||||
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
|
||||
|
||||
if (getenv("LD_PRELOAD"))
|
||||
WARNF(
|
||||
"LD_PRELOAD is set, are you sure that is want to you want to do "
|
||||
"instead of using AFL_PRELOAD?");
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -802,6 +837,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (aa_loc && !out_file) {
|
||||
|
||||
use_stdin = 0;
|
||||
|
||||
if (file_extension) {
|
||||
|
||||
out_file = alloc_printf("%s/.cur_input.%s", out_dir, file_extension);
|
||||
|
@ -72,17 +72,20 @@ static u32 total, highest; /* tuple content information */
|
||||
|
||||
static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
static u8 quiet_mode, /* Hide non-essential messages? */
|
||||
u8 quiet_mode, /* Hide non-essential messages? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
raw_instr_output, /* Do not apply AFL filters */
|
||||
cmin_mode, /* Generate output in afl-cmin mode? */
|
||||
binary_mode, /* Write output as a binary map */
|
||||
use_stdin = 1, /* use stdin - unused here */
|
||||
keep_cores; /* Allow coredumps? */
|
||||
|
||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
child_timed_out, /* Child timed out? */
|
||||
child_crashed; /* Child crashed? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/* Classify tuple counts. Instead of mapping to individual bits, as in
|
||||
afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */
|
||||
|
||||
@ -358,8 +361,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -497,15 +529,14 @@ static void find_binary(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
u32 tcnt = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
||||
while ((opt = getopt(argc, argv, "+o:m:t:A:eqZQUWbcrh")) > 0)
|
||||
while ((opt = getopt(argc, argv, "+o:f:m:t:A:eqZQUWbcrh")) > 0)
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -553,6 +584,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
break;
|
||||
|
||||
case 'f': // only in here to avoid a compiler warning for use_stdin
|
||||
|
||||
use_stdin = 0;
|
||||
FATAL("Option -f is not supported in afl-showmap");
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
if (timeout_given) FATAL("Multiple -t options not supported");
|
||||
|
@ -88,7 +88,7 @@ u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||
|
||||
static u8 crash_mode, /* Crash-centric mode? */
|
||||
u8 crash_mode, /* Crash-centric mode? */
|
||||
exit_crash, /* Treat non-zero exit as crash? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
exact_mode, /* Require path match for crashes? */
|
||||
@ -96,6 +96,8 @@ static u8 crash_mode, /* Crash-centric mode? */
|
||||
|
||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/*
|
||||
* forkserver section
|
||||
*/
|
||||
@ -882,8 +884,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1025,9 +1056,8 @@ static void read_bitmap(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
@ -27,6 +27,7 @@ int main(int argc, char** argv) {
|
||||
if (argc > 1) {
|
||||
|
||||
buf = argv[1];
|
||||
printf("Input %s - ", buf);
|
||||
|
||||
} else if (read(0, buf, sizeof(buf)) < 1) {
|
||||
|
||||
|
56
test/test.sh
56
test/test.sh
@ -25,6 +25,7 @@ $ECHO \\101 2>&1 | grep -qE '^A' || {
|
||||
test -z "$ECHO" && { printf Error: printf command does not support octal character codes ; exit 1 ; }
|
||||
|
||||
CODE=0
|
||||
INCOMPLETE=0
|
||||
|
||||
export AFL_EXIT_WHEN_DONE=1
|
||||
export AFL_SKIP_CPUFREQ=1
|
||||
@ -69,9 +70,9 @@ export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
|
||||
|
||||
$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
|
||||
|
||||
test -z "$SYS" && $ECHO "$YELLOW[!] uname -m did not succeed"
|
||||
test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
|
||||
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap and afl-fuzz"
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
|
||||
test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
@ -122,7 +123,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# make sure core_pattern is set to core on linux
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[!] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
@ -145,11 +146,28 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors
|
||||
echo 000000000000000000000000 > in/in2
|
||||
mkdir -p in2
|
||||
../afl-cmin -i in -o in2 -- ./test-instr.plain > /dev/null 2>&1
|
||||
CNT=`ls in2/ | wc -l`
|
||||
test "$CNT" = 1 && $ECHO "$GREEN[+] afl-cmin correctly minimized testcase numbers"
|
||||
test "$CNT" = 1 || {
|
||||
$ECHO "$RED[!] afl-cmin did not correctly minimize testcase numbers"
|
||||
CODE=1
|
||||
}
|
||||
../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
|
||||
SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`
|
||||
test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase"
|
||||
test "$SIZE" = 1 || {
|
||||
$ECHO "$RED[!] afl-tmin did incorrectly minimize the testcase to $SIZE"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors in2
|
||||
}
|
||||
rm -f test-instr.plain
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
|
||||
@ -206,7 +224,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[!] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
@ -290,6 +308,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
rm -f test-persistent
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] llvm_mode not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: gcc_plugin"
|
||||
@ -312,7 +331,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
$ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin instrumentation produces a weird number of instrumented locations: $TUPLES"
|
||||
$ECHO "$YELLOW[!] the gcc_plugin instrumentation issue is not flagged as an error because travis builds would all fail otherwise :-("
|
||||
$ECHO "$YELLOW[-] the gcc_plugin instrumentation issue is not flagged as an error because travis builds would all fail otherwise :-("
|
||||
#CODE=1
|
||||
}
|
||||
}
|
||||
@ -340,7 +359,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[!] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
@ -398,6 +417,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
rm -f test-persistent
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] gcc_plugin not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: shared library extensions"
|
||||
@ -413,6 +433,7 @@ test -e ../libtokencap.so && {
|
||||
rm -f token.out
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libtokencap is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
test -e ../libdislocator.so && {
|
||||
{
|
||||
@ -429,6 +450,7 @@ test -e ../libdislocator.so && {
|
||||
rm -f test.out core test-compcov.core core.test-compcov
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libdislocator is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -f test-compcov
|
||||
test -e ../libradamsa.so && {
|
||||
@ -454,9 +476,11 @@ test -e ../libradamsa.so && {
|
||||
rm -rf in out errors test-instr.plain
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] compilation of test target failed, cannot test libradamsa"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libradamsa is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: qemu_mode"
|
||||
@ -501,6 +525,7 @@ test -e ../afl-qemu-trace && {
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] we cannot test qemu_mode libcompcov because it is not present"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -f errors
|
||||
|
||||
@ -519,10 +544,10 @@ test -e ../afl-qemu-trace && {
|
||||
test "$SLOW" -lt "$FAST" && {
|
||||
$ECHO "$GREEN[+] persistent qemu_mode was noticeable faster than standard qemu_mode"
|
||||
} || {
|
||||
$ECHO "$YELLOW[?] persistent qemu_mode was not noticeable faster than standard qemu_mode"
|
||||
$ECHO "$YELLOW[-] persistent qemu_mode was not noticeable faster than standard qemu_mode"
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[?] we got no data on executions performed? weird!"
|
||||
$ECHO "$YELLOW[-] we got no data on executions performed? weird!"
|
||||
}
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
@ -532,17 +557,18 @@ test -e ../afl-qemu-trace && {
|
||||
CODE=1
|
||||
exit 1
|
||||
}
|
||||
$ECHO "$YELLOW[?] we need a test case for qemu_mode unsigaction library"
|
||||
$ECHO "$YELLOW[-] we need a test case for qemu_mode unsigaction library"
|
||||
rm -rf in out errors
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[-] gcc compilation of test targets failed - what is going on??"
|
||||
$ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
rm -f test-instr test-compcov
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: unicorn_mode"
|
||||
@ -557,6 +583,7 @@ test -d ../unicorn_mode/unicorn && {
|
||||
$ECHO "$GREY[*] Using python binary $PY"
|
||||
if ! $PY -c 'import unicornafl' 2> /dev/null ; then
|
||||
$ECHO "$YELLOW[-] we cannot test unicorn_mode because it is not present"
|
||||
INCOMPLETE=1
|
||||
else
|
||||
{
|
||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode, this will take approx 25 seconds"
|
||||
@ -596,15 +623,18 @@ test -d ../unicorn_mode/unicorn && {
|
||||
fi
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[-] missing sample binaries in unicorn_mode/samples/ - what is going on??"
|
||||
$ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$GREY[*] all test cases completed.$RESET"
|
||||
test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
|
||||
test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
|
||||
test "$CODE" = "0" && $ECHO "$GREEN[+] all tests were successful :-)$RESET"
|
||||
test "$CODE" = "0" || $ECHO "$RED[-] failure in tests :-($RESET"
|
||||
test "$CODE" = "0" || $ECHO "$RED[!] failure in tests :-($RESET"
|
||||
exit $CODE
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
The idea and much of the original implementation comes from Nathan Voss <njvoss299@gmail.com>.
|
||||
|
||||
The port to afl++ if by Dominik Maier <mail@dmnk.co>.
|
||||
The port to afl++ is by Dominik Maier <mail@dmnk.co>.
|
||||
|
||||
The CompareCoverage and NeverZero counters features by Andrea Fioraldi <andreafioraldi@gmail.com>.
|
||||
The CompareCoverage and NeverZero counters features are by Andrea Fioraldi <andreafioraldi@gmail.com>.
|
||||
|
||||
## 1) Introduction
|
||||
|
||||
@ -16,13 +16,13 @@ with afl-gcc or used in QEMU mode, or with other extensions such as
|
||||
TriforceAFL.
|
||||
|
||||
There is a significant performance penalty compared to native AFL,
|
||||
but at least we're able to use AFL on these binaries, right?
|
||||
but at least we're able to use AFL++ on these binaries, right?
|
||||
|
||||
## 2) How to use
|
||||
|
||||
Requirements: you need an installed python environment.
|
||||
|
||||
### Building AFL's Unicorn Mode
|
||||
### Building AFL++'s Unicorn Mode
|
||||
|
||||
First, make afl++ as usual.
|
||||
Once that completes successfully you need to build and add in the Unicorn Mode
|
||||
@ -35,7 +35,7 @@ NOTE: This script checks out a Unicorn Engine fork as submodule that has been te
|
||||
and is stable-ish, based on the unicorn engine master.
|
||||
|
||||
Building Unicorn will take a little bit (~5-10 minutes). Once it completes
|
||||
it automatically compiles a sample application and verify that it works.
|
||||
it automatically compiles a sample application and verifies that it works.
|
||||
|
||||
### Fuzzing with Unicorn Mode
|
||||
|
||||
@ -83,7 +83,7 @@ The 'helper_scripts' directory also contains several helper scripts that allow y
|
||||
to dump context from a running process, load it, and hook heap allocations. For details
|
||||
on how to use this check out the follow-up blog post to the one linked above.
|
||||
|
||||
A example use of AFL-Unicorn mode is discussed in the Paper Unicorefuzz:
|
||||
A example use of AFL-Unicorn mode is discussed in the paper Unicorefuzz:
|
||||
https://www.usenix.org/conference/woot19/presentation/maier
|
||||
|
||||
## 3) Options
|
||||
@ -91,7 +91,7 @@ https://www.usenix.org/conference/woot19/presentation/maier
|
||||
As for the QEMU-based instrumentation, the afl-unicorn twist of afl++
|
||||
comes with a sub-instruction based instrumentation similar in purpose to laf-intel.
|
||||
|
||||
The options that enables Unicorn CompareCoverage are the same used for QEMU.
|
||||
The options that enable Unicorn CompareCoverage are the same used for QEMU.
|
||||
AFL_COMPCOV_LEVEL=1 is to instrument comparisons with only immediate
|
||||
values. QEMU_COMPCOV_LEVEL=2 instruments all
|
||||
comparison instructions. Comparison instructions are currently instrumented only
|
||||
|
@ -73,23 +73,23 @@ if [ "$PLT" = "Linux" ]; then
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "Darwin" ]; then
|
||||
CORES=`sysctl hw.ncpu | cut -d' ' -f2`
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=tar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "FreeBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl hw.ncpu | cut -d' ' -f2`
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
|
||||
MAKECMD=gmake
|
||||
CORES=`sysctl hw.ncpu | cut -d'=' -f2`
|
||||
CORES=`sysctl -n hw.ncpu`
|
||||
TARCMD=gtar
|
||||
fi
|
||||
|
||||
for i in wget $PYTHONBIN automake autoconf $MAKECMD $TARCMD; do
|
||||
for i in wget $PYTHONBIN automake autoconf git $MAKECMD $TARCMD; do
|
||||
|
||||
T=`which "$i" 2>/dev/null`
|
||||
|
||||
@ -124,7 +124,8 @@ fi
|
||||
echo "[+] All checks passed!"
|
||||
|
||||
echo "[*] Making sure unicornafl is checked out"
|
||||
test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } }
|
||||
rm -rf unicorn # workaround for travis ... sadly ...
|
||||
#test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } }
|
||||
test -d unicorn || git clone https://github.com/vanhauser-thc/unicorn
|
||||
test -d unicorn || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||
echo "[+] Got unicornafl."
|
||||
|
@ -59,35 +59,17 @@ def unicorn_debug_mem_invalid_access(uc, access, address, size, value, user_data
|
||||
else:
|
||||
print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
|
||||
|
||||
def force_crash(uc_error):
|
||||
# This function should be called to indicate to AFL that a crash occurred during emulation.
|
||||
# Pass in the exception received from Uc.emu_start()
|
||||
mem_errors = [
|
||||
UC_ERR_READ_UNMAPPED, UC_ERR_READ_PROT, UC_ERR_READ_UNALIGNED,
|
||||
UC_ERR_WRITE_UNMAPPED, UC_ERR_WRITE_PROT, UC_ERR_WRITE_UNALIGNED,
|
||||
UC_ERR_FETCH_UNMAPPED, UC_ERR_FETCH_PROT, UC_ERR_FETCH_UNALIGNED,
|
||||
]
|
||||
if uc_error.errno in mem_errors:
|
||||
# Memory error - throw SIGSEGV
|
||||
os.kill(os.getpid(), signal.SIGSEGV)
|
||||
elif uc_error.errno == UC_ERR_INSN_INVALID:
|
||||
# Invalid instruction - throw SIGILL
|
||||
os.kill(os.getpid(), signal.SIGILL)
|
||||
else:
|
||||
# Not sure what happened - throw SIGABRT
|
||||
os.kill(os.getpid(), signal.SIGABRT)
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(description="Test harness for compcov_target.bin")
|
||||
parser.add_argument('input_file', type=str, help="Path to the file containing the mutated input to load")
|
||||
parser.add_argument('-d', '--debug', default=False, action="store_true", help="Enables debug tracing")
|
||||
parser.add_argument('-t', '--trace', default=False, action="store_true", help="Enables debug tracing")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Instantiate a MIPS32 big endian Unicorn Engine instance
|
||||
uc = Uc(UC_ARCH_X86, UC_MODE_64)
|
||||
|
||||
if args.debug:
|
||||
if args.trace:
|
||||
uc.hook_add(UC_HOOK_BLOCK, unicorn_debug_block)
|
||||
uc.hook_add(UC_HOOK_CODE, unicorn_debug_instruction)
|
||||
uc.hook_add(UC_HOOK_MEM_WRITE | UC_HOOK_MEM_READ, unicorn_debug_mem_access)
|
||||
@ -132,11 +114,6 @@ def main():
|
||||
"""
|
||||
Callback that loads the mutated input into memory.
|
||||
"""
|
||||
# Load the mutated input from disk
|
||||
input_file = open(args.input_file, 'rb')
|
||||
input = input_file.read()
|
||||
input_file.close()
|
||||
|
||||
# Apply constraints to the mutated input
|
||||
if len(input) > DATA_SIZE_MAX:
|
||||
return
|
||||
|
@ -5,8 +5,8 @@
|
||||
This loads the simple_target.bin binary (precompiled as MIPS code) into
|
||||
Unicorn's memory map for emulation, places the specified input into
|
||||
simple_target's buffer (hardcoded to be at 0x300000), and executes 'main()'.
|
||||
If any crashes occur during emulation, this script throws a matching signal
|
||||
to tell AFL that a crash occurred.
|
||||
If any crashes occur during emulation, unicornafl will
|
||||
tell AFL that a crash occurred.
|
||||
|
||||
Run under AFL as follows:
|
||||
|
||||
@ -59,35 +59,17 @@ def unicorn_debug_mem_invalid_access(uc, access, address, size, value, user_data
|
||||
else:
|
||||
print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
|
||||
|
||||
def force_crash(uc_error):
|
||||
# This function should be called to indicate to AFL that a crash occurred during emulation.
|
||||
# Pass in the exception received from Uc.emu_start()
|
||||
mem_errors = [
|
||||
UC_ERR_READ_UNMAPPED, UC_ERR_READ_PROT, UC_ERR_READ_UNALIGNED,
|
||||
UC_ERR_WRITE_UNMAPPED, UC_ERR_WRITE_PROT, UC_ERR_WRITE_UNALIGNED,
|
||||
UC_ERR_FETCH_UNMAPPED, UC_ERR_FETCH_PROT, UC_ERR_FETCH_UNALIGNED,
|
||||
]
|
||||
if uc_error.errno in mem_errors:
|
||||
# Memory error - throw SIGSEGV
|
||||
os.kill(os.getpid(), signal.SIGSEGV)
|
||||
elif uc_error.errno == UC_ERR_INSN_INVALID:
|
||||
# Invalid instruction - throw SIGILL
|
||||
os.kill(os.getpid(), signal.SIGILL)
|
||||
else:
|
||||
# Not sure what happened - throw SIGABRT
|
||||
os.kill(os.getpid(), signal.SIGABRT)
|
||||
|
||||
def main():
|
||||
|
||||
parser = argparse.ArgumentParser(description="Test harness for simple_target.bin")
|
||||
parser.add_argument('input_file', type=str, help="Path to the file containing the mutated input to load")
|
||||
parser.add_argument('-d', '--debug', default=False, action="store_true", help="Enables debug tracing")
|
||||
parser.add_argument('-t', '--trace', default=False, action="store_true", help="Enables debug tracing")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Instantiate a MIPS32 big endian Unicorn Engine instance
|
||||
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN)
|
||||
|
||||
if args.debug:
|
||||
if args.trace:
|
||||
uc.hook_add(UC_HOOK_BLOCK, unicorn_debug_block)
|
||||
uc.hook_add(UC_HOOK_CODE, unicorn_debug_instruction)
|
||||
uc.hook_add(UC_HOOK_MEM_WRITE | UC_HOOK_MEM_READ, unicorn_debug_mem_access)
|
||||
@ -129,11 +111,6 @@ def main():
|
||||
# We did not pass in any data and don't use persistent mode, so we can ignore these params.
|
||||
# Be sure to check out the docstrings for the uc.afl_* functions.
|
||||
def place_input_callback(uc, input, persistent_round, data):
|
||||
# Load the mutated input from disk
|
||||
input_file = open(args.input_file, 'rb')
|
||||
input = input_file.read()
|
||||
input_file.close()
|
||||
|
||||
# Apply constraints to the mutated input
|
||||
if len(input) > DATA_SIZE_MAX:
|
||||
#print("Test input is too long (> {} bytes)")
|
||||
|
Submodule unicorn_mode/unicorn deleted from aa5ebf5e16
Reference in New Issue
Block a user