mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-09 08:41:32 +00:00
Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev
This commit is contained in:
commit
ad29eef271
@ -29,7 +29,7 @@ CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
|
|||||||
if CLANG_FORMAT_BIN is None:
|
if CLANG_FORMAT_BIN is None:
|
||||||
o = 0
|
o = 0
|
||||||
try:
|
try:
|
||||||
p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE)
|
p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
|
||||||
o, _ = p.communicate()
|
o, _ = p.communicate()
|
||||||
o = str(o, "utf-8")
|
o = str(o, "utf-8")
|
||||||
o = re.sub(r".*ersion ", "", o)
|
o = re.sub(r".*ersion ", "", o)
|
||||||
@ -37,7 +37,7 @@ if CLANG_FORMAT_BIN is None:
|
|||||||
o = o[:o.find(".")]
|
o = o[:o.find(".")]
|
||||||
o = int(o)
|
o = int(o)
|
||||||
except:
|
except:
|
||||||
print ("clang-format-10 is needed. Aborted.")
|
print ("clang-format-11 is needed. Aborted.")
|
||||||
exit(1)
|
exit(1)
|
||||||
#if o < 7:
|
#if o < 7:
|
||||||
# if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
|
# if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
|
||||||
@ -46,13 +46,13 @@ if CLANG_FORMAT_BIN is None:
|
|||||||
# CLANG_FORMAT_BIN = 'clang-format-8'
|
# CLANG_FORMAT_BIN = 'clang-format-8'
|
||||||
# elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0:
|
# elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0:
|
||||||
# CLANG_FORMAT_BIN = 'clang-format-9'
|
# CLANG_FORMAT_BIN = 'clang-format-9'
|
||||||
# elif subprocess.call(['which', 'clang-format-10'], stdout=subprocess.PIPE) == 0:
|
# elif subprocess.call(['which', 'clang-format-11'], stdout=subprocess.PIPE) == 0:
|
||||||
# CLANG_FORMAT_BIN = 'clang-format-10'
|
# CLANG_FORMAT_BIN = 'clang-format-11'
|
||||||
# else:
|
# else:
|
||||||
# print ("clang-format 7 or above is needed. Aborted.")
|
# print ("clang-format 7 or above is needed. Aborted.")
|
||||||
# exit(1)
|
# exit(1)
|
||||||
else:
|
else:
|
||||||
CLANG_FORMAT_BIN = 'clang-format-10'
|
CLANG_FORMAT_BIN = 'clang-format-11'
|
||||||
|
|
||||||
COLUMN_LIMIT = 80
|
COLUMN_LIMIT = 80
|
||||||
for line in fmt.split("\n"):
|
for line in fmt.split("\n"):
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.dSYM
|
*.dSYM
|
||||||
as
|
as
|
||||||
|
a.out
|
||||||
ld
|
ld
|
||||||
in
|
in
|
||||||
out
|
out
|
||||||
|
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -1,9 +1,8 @@
|
|||||||
[submodule "unicorn_mode/unicornafl"]
|
[submodule "unicorn_mode/unicornafl"]
|
||||||
path = unicorn_mode/unicornafl
|
path = unicorn_mode/unicornafl
|
||||||
url = https://github.com/AFLplusplus/unicornafl
|
url = https://github.com/AFLplusplus/unicornafl
|
||||||
|
[submodule "custom_mutators/grammar_mutator"]
|
||||||
[submodule "custom_mutators/Grammar-Mutator"]
|
path = custom_mutators/grammar_mutator/grammar_mutator
|
||||||
path = custom_mutators/Grammar-Mutator
|
|
||||||
url = https://github.com/AFLplusplus/Grammar-Mutator
|
url = https://github.com/AFLplusplus/Grammar-Mutator
|
||||||
[submodule "qemu_mode/qemuafl"]
|
[submodule "qemu_mode/qemuafl"]
|
||||||
path = qemu_mode/qemuafl
|
path = qemu_mode/qemuafl
|
||||||
|
@ -16,9 +16,9 @@ project, or added a file in a directory we already format, otherwise run:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Regarding the coding style, please follow the AFL style.
|
Regarding the coding style, please follow the AFL style.
|
||||||
No camel case at all and use the AFL's macros wherever possible
|
No camel case at all and use AFL's macros wherever possible
|
||||||
(e.g. WARNF, FATAL, MAP_SIZE, ...).
|
(e.g. WARNF, FATAL, MAP_SIZE, ...).
|
||||||
|
|
||||||
Remember that AFLplusplus has to build and run on many platforms, so
|
Remember that AFLplusplus has to build and run on many platforms, so
|
||||||
generalize your Makefiles/GNUmakefile (or your patches to our pre-existing
|
generalize your Makefiles/GNUmakefile (or your patches to our pre-existing
|
||||||
Makefiles) to be as much generic as possible.
|
Makefiles) to be as generic as possible.
|
||||||
|
48
GNUmakefile
48
GNUmakefile
@ -85,8 +85,10 @@ ifneq "$(shell uname)" "Darwin"
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
# OS X does not like _FORTIFY_SOURCE=2
|
# OS X does not like _FORTIFY_SOURCE=2
|
||||||
|
ifndef DEBUG
|
||||||
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq "$(shell uname)" "SunOS"
|
ifeq "$(shell uname)" "SunOS"
|
||||||
CFLAGS_OPT += -Wno-format-truncation
|
CFLAGS_OPT += -Wno-format-truncation
|
||||||
@ -232,7 +234,9 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||||
|
ifndef DEBUG
|
||||||
override CFLAGS += -D_FORTIFY_SOURCE=2
|
override CFLAGS += -D_FORTIFY_SOURCE=2
|
||||||
|
endif
|
||||||
LDFLAGS += -ldl -lrt -lm
|
LDFLAGS += -ldl -lrt -lm
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -417,7 +421,7 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
|||||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||||
|
|
||||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||||
|
|
||||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||||
@ -496,8 +500,8 @@ code-format:
|
|||||||
./.custom-format.py -i instrumentation/*.c
|
./.custom-format.py -i instrumentation/*.c
|
||||||
@#./.custom-format.py -i custom_mutators/*/*.c* # destroys libfuzzer :-(
|
@#./.custom-format.py -i custom_mutators/*/*.c* # destroys libfuzzer :-(
|
||||||
@#./.custom-format.py -i custom_mutators/*/*.h # destroys honggfuzz :-(
|
@#./.custom-format.py -i custom_mutators/*/*.h # destroys honggfuzz :-(
|
||||||
./.custom-format.py -i examples/*/*.c*
|
./.custom-format.py -i utils/*/*.c*
|
||||||
./.custom-format.py -i examples/*/*.h
|
./.custom-format.py -i utils/*/*.h
|
||||||
./.custom-format.py -i test/*.c
|
./.custom-format.py -i test/*.c
|
||||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||||
@ -512,7 +516,7 @@ code-format:
|
|||||||
ifndef AFL_NO_X86
|
ifndef AFL_NO_X86
|
||||||
test_build: afl-cc afl-as afl-showmap
|
test_build: afl-cc afl-as afl-showmap
|
||||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||||
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
||||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||||
@rm -f test-instr
|
@rm -f test-instr
|
||||||
@ -538,14 +542,14 @@ all_done: test_build
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ test/unittests/unit_hash test/unittests/unit_rand
|
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand
|
||||||
-$(MAKE) -f GNUmakefile.llvm clean
|
-$(MAKE) -f GNUmakefile.llvm clean
|
||||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||||
$(MAKE) -C libdislocator clean
|
$(MAKE) -C libdislocator clean
|
||||||
$(MAKE) -C libtokencap clean
|
$(MAKE) -C libtokencap clean
|
||||||
$(MAKE) -C examples/afl_network_proxy clean
|
$(MAKE) -C utils/afl_network_proxy clean
|
||||||
$(MAKE) -C examples/socket_fuzzing clean
|
$(MAKE) -C utils/socket_fuzzing clean
|
||||||
$(MAKE) -C examples/argv_fuzzing clean
|
$(MAKE) -C utils/argv_fuzzing clean
|
||||||
$(MAKE) -C qemu_mode/unsigaction clean
|
$(MAKE) -C qemu_mode/unsigaction clean
|
||||||
$(MAKE) -C qemu_mode/libcompcov clean
|
$(MAKE) -C qemu_mode/libcompcov clean
|
||||||
ifeq "$(IN_REPO)" "1"
|
ifeq "$(IN_REPO)" "1"
|
||||||
@ -568,10 +572,10 @@ distrib: all
|
|||||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||||
$(MAKE) -C libdislocator
|
$(MAKE) -C libdislocator
|
||||||
$(MAKE) -C libtokencap
|
$(MAKE) -C libtokencap
|
||||||
$(MAKE) -C examples/aflpp_driver
|
$(MAKE) -C utils/aflpp_driver
|
||||||
$(MAKE) -C examples/afl_network_proxy
|
$(MAKE) -C utils/afl_network_proxy
|
||||||
$(MAKE) -C examples/socket_fuzzing
|
$(MAKE) -C utils/socket_fuzzing
|
||||||
$(MAKE) -C examples/argv_fuzzing
|
$(MAKE) -C utils/argv_fuzzing
|
||||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
|
||||||
@ -579,9 +583,9 @@ distrib: all
|
|||||||
binary-only: all
|
binary-only: all
|
||||||
$(MAKE) -C libdislocator
|
$(MAKE) -C libdislocator
|
||||||
$(MAKE) -C libtokencap
|
$(MAKE) -C libtokencap
|
||||||
$(MAKE) -C examples/afl_network_proxy
|
$(MAKE) -C utils/afl_network_proxy
|
||||||
$(MAKE) -C examples/socket_fuzzing
|
$(MAKE) -C utils/socket_fuzzing
|
||||||
$(MAKE) -C examples/argv_fuzzing
|
$(MAKE) -C utils/argv_fuzzing
|
||||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||||
|
|
||||||
@ -591,7 +595,7 @@ source-only: all
|
|||||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||||
$(MAKE) -C libdislocator
|
$(MAKE) -C libdislocator
|
||||||
$(MAKE) -C libtokencap
|
$(MAKE) -C libtokencap
|
||||||
$(MAKE) -C examples/aflpp_driver
|
$(MAKE) -C utils/aflpp_driver
|
||||||
|
|
||||||
%.8: %
|
%.8: %
|
||||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||||
@ -624,15 +628,17 @@ install: all $(MANPAGES)
|
|||||||
@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||||
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
|
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
|
||||||
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
|
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
|
||||||
@if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
|
@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
|
||||||
@if [ -f examples/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 examples/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||||
@if [ -f examples/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 examples/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||||
-$(MAKE) -f GNUmakefile.llvm install
|
-$(MAKE) -f GNUmakefile.llvm install
|
||||||
-$(MAKE) -f GNUmakefile.gcc_plugin install
|
-$(MAKE) -f GNUmakefile.gcc_plugin install
|
||||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc
|
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc
|
||||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
|
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||||
|
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
|
||||||
|
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang++
|
||||||
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
#
|
||||||
|
#TEST_MMAP=1
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
HELPER_PATH ?= $(PREFIX)/lib/afl
|
||||||
BIN_PATH ?= $(PREFIX)/bin
|
BIN_PATH ?= $(PREFIX)/bin
|
||||||
|
@ -34,7 +34,7 @@ ifeq "$(shell uname)" "OpenBSD"
|
|||||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||||
ifeq "$(HAS_OPT)" "1"
|
ifeq "$(HAS_OPT)" "1"
|
||||||
$(warn llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
|
$(warning llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
LLVM_CONFIG ?= llvm-config
|
LLVM_CONFIG ?= llvm-config
|
||||||
@ -361,6 +361,8 @@ instrumentation/afl-common.o: ./src/afl-common.c
|
|||||||
@ln -sf afl-cc ./afl-c++
|
@ln -sf afl-cc ./afl-c++
|
||||||
@ln -sf afl-cc ./afl-gcc
|
@ln -sf afl-cc ./afl-gcc
|
||||||
@ln -sf afl-cc ./afl-g++
|
@ln -sf afl-cc ./afl-g++
|
||||||
|
@ln -sf afl-cc ./afl-clang
|
||||||
|
@ln -sf afl-cc ./afl-clang++
|
||||||
@ln -sf afl-cc ./afl-clang-fast
|
@ln -sf afl-cc ./afl-clang-fast
|
||||||
@ln -sf afl-cc ./afl-clang-fast++
|
@ln -sf afl-cc ./afl-clang-fast++
|
||||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||||
|
22
README.md
22
README.md
@ -22,8 +22,8 @@
|
|||||||
afl++ is a superior fork to Google's afl - more speed, more and better
|
afl++ is a superior fork to Google's afl - more speed, more and better
|
||||||
mutations, more and better instrumentation, custom module support, etc.
|
mutations, more and better instrumentation, custom module support, etc.
|
||||||
|
|
||||||
If you want to use afl++ for you academic work, check the [papers page](https://aflplus.plus/papers/)
|
If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
|
||||||
in the website.
|
on the website.
|
||||||
|
|
||||||
## Major changes in afl++ 3.0
|
## Major changes in afl++ 3.0
|
||||||
|
|
||||||
@ -55,6 +55,7 @@ behaviours and defaults:
|
|||||||
* a caching of testcases can now be performed and can be modified by
|
* a caching of testcases can now be performed and can be modified by
|
||||||
editing config.h for TESTCASE_CACHE or by specifying the env variable
|
editing config.h for TESTCASE_CACHE or by specifying the env variable
|
||||||
`AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500 (default: 50).
|
`AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500 (default: 50).
|
||||||
|
* examples/ got renamed to utils/
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
@ -273,7 +274,7 @@ anything below 9 is not recommended.
|
|||||||
v
|
v
|
||||||
+---------------------------------+
|
+---------------------------------+
|
||||||
| clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
|
| clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
|
||||||
+---------------------------------+ see [instrumentation/README.md](instrumentation/README.md)
|
+---------------------------------+ see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
|
||||||
|
|
|
|
||||||
| if not, or if the target fails with LLVM afl-clang-fast/++
|
| if not, or if the target fails with LLVM afl-clang-fast/++
|
||||||
|
|
|
|
||||||
@ -292,7 +293,7 @@ anything below 9 is not recommended.
|
|||||||
Clickable README links for the chosen compiler:
|
Clickable README links for the chosen compiler:
|
||||||
|
|
||||||
* [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
|
* [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
|
||||||
* [LLVM mode - afl-clang-fast](instrumentation/README.md)
|
* [LLVM mode - afl-clang-fast](instrumentation/README.llvm.md)
|
||||||
* [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
|
* [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
|
||||||
* GCC mode (afl-gcc) has no README as it has no own features
|
* GCC mode (afl-gcc) has no README as it has no own features
|
||||||
|
|
||||||
@ -525,7 +526,7 @@ as test data in there.
|
|||||||
|
|
||||||
If you do not want anything special, the defaults are already usually best,
|
If you do not want anything special, the defaults are already usually best,
|
||||||
hence all you need is to specify the seed input directory with the result of
|
hence all you need is to specify the seed input directory with the result of
|
||||||
step [2. Collect inputs](#a)a-collect-inputs)):
|
step [2a. Collect inputs](#a-collect-inputs):
|
||||||
`afl-fuzz -i input -o output -- bin/target -d @@`
|
`afl-fuzz -i input -o output -- bin/target -d @@`
|
||||||
Note that the directory specified with -o will be created if it does not exist.
|
Note that the directory specified with -o will be created if it does not exist.
|
||||||
|
|
||||||
@ -541,7 +542,7 @@ that it could not connect to the forkserver), then you can increase this
|
|||||||
with the `-m` option, the value is in MB. To disable any memory limits
|
with the `-m` option, the value is in MB. To disable any memory limits
|
||||||
(beware!) set `-m none` - which is usually required for ASAN compiled targets.
|
(beware!) set `-m none` - which is usually required for ASAN compiled targets.
|
||||||
|
|
||||||
Adding a dictionary is helpful. See the [dictionaries/](dictionaries/) if
|
Adding a dictionary is helpful. See the directory [dictionaries/](dictionaries/) if
|
||||||
something is already included for your data format, and tell afl-fuzz to load
|
something is already included for your data format, and tell afl-fuzz to load
|
||||||
that dictionary by adding `-x dictionaries/FORMAT.dict`. With afl-clang-lto
|
that dictionary by adding `-x dictionaries/FORMAT.dict`. With afl-clang-lto
|
||||||
you have an autodictionary generation for which you need to do nothing except
|
you have an autodictionary generation for which you need to do nothing except
|
||||||
@ -760,10 +761,10 @@ cd unicorn_mode
|
|||||||
|
|
||||||
If the goal is to fuzz a dynamic library then there are two options available.
|
If the goal is to fuzz a dynamic library then there are two options available.
|
||||||
For both you need to write a small hardness that loads and calls the library.
|
For both you need to write a small hardness that loads and calls the library.
|
||||||
Faster is the frida solution: [examples/afl_frida/README.md](examples/afl_frida/README.md)
|
Faster is the frida solution: [utils/afl_frida/README.md](utils/afl_frida/README.md)
|
||||||
|
|
||||||
Another, less precise and slower option is using ptrace with debugger interrupt
|
Another, less precise and slower option is using ptrace with debugger interrupt
|
||||||
instrumentation: [examples/afl_untracer/README.md](examples/afl_untracer/README.md)
|
instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md)
|
||||||
|
|
||||||
### More
|
### More
|
||||||
|
|
||||||
@ -1037,7 +1038,7 @@ Here are some of the most important caveats for AFL:
|
|||||||
wholly wrap the actual data format to be tested.
|
wholly wrap the actual data format to be tested.
|
||||||
|
|
||||||
To work around this, you can comment out the relevant checks (see
|
To work around this, you can comment out the relevant checks (see
|
||||||
examples/libpng_no_checksum/ for inspiration); if this is not possible,
|
utils/libpng_no_checksum/ for inspiration); if this is not possible,
|
||||||
you can also write a postprocessor, one of the hooks of custom mutators.
|
you can also write a postprocessor, one of the hooks of custom mutators.
|
||||||
See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
|
See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
|
||||||
`AFL_CUSTOM_MUTATOR_LIBRARY`
|
`AFL_CUSTOM_MUTATOR_LIBRARY`
|
||||||
@ -1109,7 +1110,8 @@ without feedback, bug reports, or patches from:
|
|||||||
Andrea Biondo Vincent Le Garrec
|
Andrea Biondo Vincent Le Garrec
|
||||||
Khaled Yakdan Kuang-che Wu
|
Khaled Yakdan Kuang-che Wu
|
||||||
Josephine Calliotte Konrad Welc
|
Josephine Calliotte Konrad Welc
|
||||||
David Carlier Ruben ten Hove
|
Thomas Rooijakkers David Carlier
|
||||||
|
Ruben ten Hove
|
||||||
```
|
```
|
||||||
|
|
||||||
Thank you!
|
Thank you!
|
||||||
|
9
afl-cmin
9
afl-cmin
@ -113,14 +113,15 @@ function usage() {
|
|||||||
" -C - keep crashing inputs, reject everything else\n" \
|
" -C - keep crashing inputs, reject everything else\n" \
|
||||||
" -e - solve for edge coverage only, ignore hit counts\n" \
|
" -e - solve for edge coverage only, ignore hit counts\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"For additional tips, please consult docs/README.md\n" \
|
"For additional tips, please consult README.md\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Environment variables used:\n" \
|
"Environment variables used:\n" \
|
||||||
|
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
|
||||||
|
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
|
||||||
|
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
|
||||||
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
|
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
|
||||||
"AFL_PATH: path for the afl-showmap binary\n" \
|
"AFL_PATH: path for the afl-showmap binary\n" \
|
||||||
"AFL_SKIP_BIN_CHECK: skip check for target binary\n" \
|
"AFL_SKIP_BIN_CHECK: skip check for target binary\n"
|
||||||
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n"
|
|
||||||
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n"
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ Minimization settings:
|
|||||||
-C - keep crashing inputs, reject everything else
|
-C - keep crashing inputs, reject everything else
|
||||||
-e - solve for edge coverage only, ignore hit counts
|
-e - solve for edge coverage only, ignore hit counts
|
||||||
|
|
||||||
For additional tips, please consult docs/README.md.
|
For additional tips, please consult README.md.
|
||||||
|
|
||||||
Environment variables used:
|
Environment variables used:
|
||||||
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
|
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
|
||||||
|
@ -7,15 +7,13 @@ For further information and documentation on how to write your own, read [the do
|
|||||||
|
|
||||||
If you use git to clone afl++, then the following will incorporate our
|
If you use git to clone afl++, then the following will incorporate our
|
||||||
excellent grammar custom mutator:
|
excellent grammar custom mutator:
|
||||||
```
|
```sh
|
||||||
git submodule init
|
git submodule update --init
|
||||||
git submodule update
|
|
||||||
```
|
```
|
||||||
|
|
||||||
otherwise just use the script: `grammar_mutator/build_grammar_mutator.sh`
|
Read the README in the [Grammar-Mutator] repository on how to use it.
|
||||||
|
|
||||||
Read the [Grammar-Mutator/README.md](Grammar-Mutator/README.md) on how to use
|
[Grammar-Mutator]: https://github.com/AFLplusplus/Grammar-Mutator
|
||||||
it.
|
|
||||||
|
|
||||||
## Production-Ready Custom Mutators
|
## Production-Ready Custom Mutators
|
||||||
|
|
||||||
|
1
custom_mutators/grammar_mutator/GRAMMAR_VERSION
Normal file
1
custom_mutators/grammar_mutator/GRAMMAR_VERSION
Normal file
@ -0,0 +1 @@
|
|||||||
|
b3c4fcf
|
@ -1,17 +1,140 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# american fuzzy lop++ - unicorn mode build script
|
||||||
|
# ------------------------------------------------
|
||||||
|
#
|
||||||
|
# Originally written by Nathan Voss <njvoss99@gmail.com>
|
||||||
|
#
|
||||||
|
# Adapted from code by Andrew Griffiths <agriffiths@google.com> and
|
||||||
|
# Michal Zalewski
|
||||||
|
#
|
||||||
|
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
||||||
|
#
|
||||||
|
# CompareCoverage and NeverZero counters by Andrea Fioraldi
|
||||||
|
# <andreafioraldi@gmail.com>
|
||||||
|
#
|
||||||
|
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||||
|
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# This script downloads, patches, and builds a version of Unicorn with
|
||||||
|
# minor tweaks to allow Unicorn-emulated binaries to be run under
|
||||||
|
# afl-fuzz.
|
||||||
|
#
|
||||||
|
# The modifications reside in patches/*. The standalone Unicorn library
|
||||||
|
# will be written to /usr/lib/libunicornafl.so, and the Python bindings
|
||||||
|
# will be installed system-wide.
|
||||||
|
#
|
||||||
|
# You must make sure that Unicorn Engine is not already installed before
|
||||||
|
# running this script. If it is, please uninstall it first.
|
||||||
|
|
||||||
test -d Grammar-Mutator || git clone --depth=1 https://github.com/AFLplusplus/Grammar-Mutator
|
GRAMMAR_VERSION="$(cat ./GRAMMAR_VERSION)"
|
||||||
|
GRAMMAR_REPO="https://github.com/AFLplusplus/grammar-mutator"
|
||||||
|
|
||||||
cd Grammar-Mutator || exit 1
|
echo "================================================="
|
||||||
git stash ; git pull
|
echo "Grammar Mutator build script"
|
||||||
|
echo "================================================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "[*] Performing basic sanity checks..."
|
||||||
|
|
||||||
|
PLT=`uname -s`
|
||||||
|
|
||||||
|
if [ ! -f "../../config.h" ]; then
|
||||||
|
|
||||||
|
echo "[-] Error: key files not found - wrong working directory?"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
PYTHONBIN=`command -v python3 || command -v python || command -v python2 || echo python3`
|
||||||
|
MAKECMD=make
|
||||||
|
TARCMD=tar
|
||||||
|
|
||||||
|
if [ "$PLT" = "Darwin" ]; then
|
||||||
|
CORES=`sysctl -n hw.ncpu`
|
||||||
|
TARCMD=tar
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PLT" = "FreeBSD" ]; then
|
||||||
|
MAKECMD=gmake
|
||||||
|
CORES=`sysctl -n hw.ncpu`
|
||||||
|
TARCMD=gtar
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
|
||||||
|
MAKECMD=gmake
|
||||||
|
CORES=`sysctl -n hw.ncpu`
|
||||||
|
TARCMD=gtar
|
||||||
|
fi
|
||||||
|
|
||||||
|
PREREQ_NOTFOUND=
|
||||||
|
for i in git $MAKECMD $TARCMD; do
|
||||||
|
|
||||||
|
T=`command -v "$i" 2>/dev/null`
|
||||||
|
|
||||||
|
if [ "$T" = "" ]; then
|
||||||
|
|
||||||
|
echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar."
|
||||||
|
PREREQ_NOTFOUND=1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
if echo "$CC" | grep -qF /afl-; then
|
||||||
|
|
||||||
|
echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
|
||||||
|
PREREQ_NOTFOUND=1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PREREQ_NOTFOUND" = "1" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[+] All checks passed!"
|
||||||
|
|
||||||
|
echo "[*] Making sure grammar mutator is checked out"
|
||||||
|
|
||||||
|
git status 1>/dev/null 2>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "[*] initializing grammar mutator submodule"
|
||||||
|
git submodule init || exit 1
|
||||||
|
git submodule update ./grammar-mutator 2>/dev/null # ignore errors
|
||||||
|
else
|
||||||
|
echo "[*] cloning grammar mutator"
|
||||||
|
test -d grammar-mutator || {
|
||||||
|
CNT=1
|
||||||
|
while [ '!' -d grammar-mutator -a "$CNT" -lt 4 ]; do
|
||||||
|
echo "Trying to clone grammar-mutator (attempt $CNT/3)"
|
||||||
|
git clone "$GRAMMAR_REPO"
|
||||||
|
CNT=`expr "$CNT" + 1`
|
||||||
|
done
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -d grammar-mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||||
|
echo "[+] Got grammar mutator."
|
||||||
|
|
||||||
|
cd "grammar-mutator" || exit 1
|
||||||
|
echo "[*] Checking out $GRAMMAR_VERSION"
|
||||||
|
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
||||||
|
git checkout "$GRAMMAR_VERSION" || exit 1
|
||||||
|
echo "[*] Downloading antlr..."
|
||||||
wget -c https://www.antlr.org/download/antlr-4.8-complete.jar
|
wget -c https://www.antlr.org/download/antlr-4.8-complete.jar
|
||||||
|
cd ..
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo
|
echo
|
||||||
echo "All successfully prepared!"
|
echo "[+] All successfully prepared!"
|
||||||
echo "To build for your grammar just do:"
|
echo "[!] To build for your grammar just do:"
|
||||||
echo " cd Grammar_Mutator"
|
echo " cd grammar-mutator"
|
||||||
echo " make GRAMMAR_FILE=/path/to/your/grammar"
|
echo " make GRAMMAR_FILE=/path/to/your/grammar"
|
||||||
echo "You will find a JSON and RUBY grammar in Grammar_Mutator/grammars to play with."
|
echo "[+] You will find a JSON and RUBY grammar in grammar-mutator/grammars to play with."
|
||||||
echo
|
echo
|
||||||
|
1
custom_mutators/grammar_mutator/grammar_mutator
Submodule
1
custom_mutators/grammar_mutator/grammar_mutator
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit b3c4fcfa6ae28918bc410f7747135eafd4fb7263
|
50
custom_mutators/grammar_mutator/update_grammar_ref.sh
Executable file
50
custom_mutators/grammar_mutator/update_grammar_ref.sh
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# AFL++ tool to update a git ref.
|
||||||
|
# Usage: ./<script>.sh <new commit hash>
|
||||||
|
# If no commit hash was provided, it'll take HEAD.
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
TOOL="grammar mutator"
|
||||||
|
VERSION_FILE='./GRAMMAR_VERSION'
|
||||||
|
REPO_FOLDER='./grammar_mutator'
|
||||||
|
THIS_SCRIPT=`basename $0`
|
||||||
|
BRANCH="stable"
|
||||||
|
|
||||||
|
NEW_VERSION="$1"
|
||||||
|
|
||||||
|
if [ "$NEW_VERSION" = "-h" ]; then
|
||||||
|
echo "Internal script to update bound $TOOL version."
|
||||||
|
echo
|
||||||
|
echo "Usage: $THIS_SCRIPT <new commit hash>"
|
||||||
|
echo "If no commit hash is provided, will use HEAD."
|
||||||
|
echo "-h to show this help screen."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git submodule init && git submodule update ./grammar_mutator || exit 1
|
||||||
|
cd "$REPO_FOLDER" || exit 1
|
||||||
|
git fetch origin $BRANCH 1>/dev/null || exit 1
|
||||||
|
git stash 1>/dev/null 2>/dev/null
|
||||||
|
git stash drop 1>/dev/null 2>/dev/null
|
||||||
|
git checkout $BRANCH
|
||||||
|
|
||||||
|
if [ -z "$NEW_VERSION" ]; then
|
||||||
|
# No version provided, take HEAD.
|
||||||
|
NEW_VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$NEW_VERSION" ]; then
|
||||||
|
echo "Error getting version."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git checkout "$NEW_VERSION" || exit 1
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
rm "$VERSION_FILE"
|
||||||
|
echo "$NEW_VERSION" > "$VERSION_FILE"
|
||||||
|
|
||||||
|
echo "Done. New $TOOL version is $NEW_VERSION."
|
@ -1,7 +1,10 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "afl-fuzz.h"
|
#include "afl-fuzz.h"
|
||||||
@ -21,6 +24,7 @@ typedef struct my_mutator {
|
|||||||
afl_state_t *afl;
|
afl_state_t *afl;
|
||||||
u8 * mutator_buf;
|
u8 * mutator_buf;
|
||||||
u8 * out_dir;
|
u8 * out_dir;
|
||||||
|
u8 * tmp_dir;
|
||||||
u8 * target;
|
u8 * target;
|
||||||
uint32_t seed;
|
uint32_t seed;
|
||||||
|
|
||||||
@ -55,10 +59,11 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
|||||||
if (!(data->out_dir = getenv("SYMCC_OUTPUT_DIR"))) {
|
if (!(data->out_dir = getenv("SYMCC_OUTPUT_DIR"))) {
|
||||||
|
|
||||||
data->out_dir = alloc_printf("%s/symcc", afl->out_dir);
|
data->out_dir = alloc_printf("%s/symcc", afl->out_dir);
|
||||||
setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->tmp_dir = alloc_printf("%s/tmp", data->out_dir);
|
||||||
|
setenv("SYMCC_OUTPUT_DIR", data->tmp_dir, 1);
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
|
|
||||||
if (pid == -1) return NULL;
|
if (pid == -1) return NULL;
|
||||||
@ -84,6 +89,10 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
|||||||
|
|
||||||
if (mkdir(data->out_dir, 0755))
|
if (mkdir(data->out_dir, 0755))
|
||||||
PFATAL("Could not create directory %s", data->out_dir);
|
PFATAL("Could not create directory %s", data->out_dir);
|
||||||
|
|
||||||
|
if (mkdir(data->tmp_dir, 0755))
|
||||||
|
PFATAL("Could not create directory %s", data->tmp_dir);
|
||||||
|
|
||||||
DBG("out_dir=%s, target=%s\n", data->out_dir, data->target);
|
DBG("out_dir=%s, target=%s\n", data->out_dir, data->target);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -96,33 +105,119 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
|
|||||||
const uint8_t *filename_new_queue,
|
const uint8_t *filename_new_queue,
|
||||||
const uint8_t *filename_orig_queue) {
|
const uint8_t *filename_orig_queue) {
|
||||||
|
|
||||||
|
int pipefd[2];
|
||||||
|
struct stat st;
|
||||||
|
ACTF("Queueing to symcc: %s", filename_new_queue);
|
||||||
|
u8 *fn = alloc_printf("%s", filename_new_queue);
|
||||||
|
if (!(stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size)) {
|
||||||
|
|
||||||
|
ck_free(fn);
|
||||||
|
PFATAL("Couldn't find enqueued file: %s", fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (afl_struct->fsrv.use_stdin) {
|
||||||
|
|
||||||
|
if (pipe(pipefd) == -1) {
|
||||||
|
|
||||||
|
ck_free(fn);
|
||||||
|
PFATAL("Couldn't create a pipe for interacting with symcc child process");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
|
|
||||||
if (pid == -1) return;
|
if (pid == -1) return;
|
||||||
|
|
||||||
if (pid) pid = waitpid(pid, NULL, 0);
|
if (pid) {
|
||||||
|
|
||||||
if (pid == 0) {
|
|
||||||
|
|
||||||
setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
|
|
||||||
|
|
||||||
if (afl_struct->fsrv.use_stdin) {
|
if (afl_struct->fsrv.use_stdin) {
|
||||||
|
|
||||||
u8 *fn = alloc_printf("%s/%s", afl_struct->out_dir, filename_new_queue);
|
close(pipefd[0]);
|
||||||
int fd = open(fn, O_RDONLY);
|
int fd = open(fn, O_RDONLY);
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
|
|
||||||
ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
|
ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
|
||||||
close(fd);
|
|
||||||
DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r);
|
DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r);
|
||||||
if (r <= 0) return;
|
|
||||||
close(0);
|
|
||||||
ck_write(0, data->mutator_buf, r, fn);
|
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
close(fd);
|
||||||
|
if (r <= 0) {
|
||||||
|
|
||||||
|
close(pipefd[1]);
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r > fcntl(pipefd[1], F_GETPIPE_SZ))
|
||||||
|
fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
|
||||||
|
ck_write(pipefd[1], data->mutator_buf, r, filename_new_queue);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ck_free(fn);
|
||||||
|
close(pipefd[1]);
|
||||||
|
PFATAL(
|
||||||
|
"Something happened to the enqueued file before sending its "
|
||||||
|
"contents to symcc binary");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close(pipefd[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = waitpid(pid, NULL, 0);
|
||||||
|
|
||||||
|
// At this point we need to transfer files to output dir, since their names
|
||||||
|
// collide and symcc will just overwrite them
|
||||||
|
|
||||||
|
struct dirent **nl;
|
||||||
|
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
|
||||||
|
u8 * origin_name = basename(filename_new_queue);
|
||||||
|
int32_t i;
|
||||||
|
if (items > 0) {
|
||||||
|
|
||||||
|
for (i = 0; i < (u32)items; ++i) {
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
u8 *source_name = alloc_printf("%s/%s", data->tmp_dir, nl[i]->d_name);
|
||||||
|
DBG("test=%s\n", fn);
|
||||||
|
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||||
|
|
||||||
|
u8 *destination_name =
|
||||||
|
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
|
||||||
|
rename(source_name, destination_name);
|
||||||
|
ck_free(destination_name);
|
||||||
|
DBG("found=%s\n", source_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_free(source_name);
|
||||||
|
free(nl[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(nl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
|
||||||
|
if (afl_struct->fsrv.use_stdin) {
|
||||||
|
|
||||||
|
unsetenv("SYMCC_INPUT_FILE");
|
||||||
|
close(pipefd[1]);
|
||||||
|
dup2(pipefd[0], 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG("exec=%s\n", data->target);
|
DBG("exec=%s\n", data->target);
|
||||||
@ -130,6 +225,7 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
|
|||||||
close(2);
|
close(2);
|
||||||
dup2(afl_struct->fsrv.dev_null_fd, 1);
|
dup2(afl_struct->fsrv.dev_null_fd, 1);
|
||||||
dup2(afl_struct->fsrv.dev_null_fd, 2);
|
dup2(afl_struct->fsrv.dev_null_fd, 2);
|
||||||
|
|
||||||
execvp(data->target, afl_struct->argv);
|
execvp(data->target, afl_struct->argv);
|
||||||
DBG("exec=FAIL\n");
|
DBG("exec=FAIL\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -180,7 +276,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
|||||||
|
|
||||||
struct dirent **nl;
|
struct dirent **nl;
|
||||||
int32_t i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL);
|
int32_t i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL);
|
||||||
size_t size = 0;
|
ssize_t size = 0;
|
||||||
|
|
||||||
if (items <= 0) return 0;
|
if (items <= 0) return 0;
|
||||||
|
|
||||||
@ -199,6 +295,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
|||||||
|
|
||||||
size = read(fd, data->mutator_buf, max_size);
|
size = read(fd, data->mutator_buf, max_size);
|
||||||
*out_buf = data->mutator_buf;
|
*out_buf = data->mutator_buf;
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
@ -217,7 +314,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
|||||||
|
|
||||||
free(nl);
|
free(nl);
|
||||||
DBG("FUZZ size=%lu\n", size);
|
DBG("FUZZ size=%lu\n", size);
|
||||||
return size;
|
return (uint32_t)size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
custom_mutators/symcc/test_examples/file_test.c
Normal file
36
custom_mutators/symcc/test_examples/file_test.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
|
||||||
|
printf("Need a file argument\n");
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = open(argv[1], O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
|
||||||
|
printf("Couldn't open file\n");
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
read(fd, &value, sizeof(value));
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
value = value ^ 0xffffffff;
|
||||||
|
if (value == 0x11223344) printf("Value one\n");
|
||||||
|
if (value == 0x44332211) printf("Value two\n");
|
||||||
|
if (value != 0x0) printf("Not zero\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
28
custom_mutators/symcc/test_examples/stdin_test.c
Normal file
28
custom_mutators/symcc/test_examples/stdin_test.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
char input_buffer[16];
|
||||||
|
uint32_t comparisonValue;
|
||||||
|
size_t bytesRead;
|
||||||
|
bytesRead = read(STDIN_FILENO, input_buffer, sizeof(input_buffer));
|
||||||
|
if (bytesRead < 0) exit(-1);
|
||||||
|
comparisonValue = *(uint32_t *)input_buffer;
|
||||||
|
comparisonValue = comparisonValue ^ 0xff112233;
|
||||||
|
if (comparisonValue == 0x66554493) {
|
||||||
|
|
||||||
|
printf("First value\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (comparisonValue == 0x84444415) printf("Second value\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
# AFL dictionaries
|
# AFL dictionaries
|
||||||
|
|
||||||
(See [../docs/README.md](../docs/README.md) for the general instruction manual.)
|
(See [../README.md](../README.md) for the general instruction manual.)
|
||||||
|
|
||||||
This subdirectory contains a set of dictionaries that can be used in
|
This subdirectory contains a set of dictionaries that can be used in
|
||||||
conjunction with the -x option to allow the fuzzer to effortlessly explore the
|
conjunction with the -x option to allow the fuzzer to effortlessly explore the
|
||||||
|
@ -11,6 +11,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
|
|
||||||
### Version ++3.00a (develop)
|
### Version ++3.00a (develop)
|
||||||
- llvm_mode/ and gcc_plugin/ moved to instrumentation/
|
- llvm_mode/ and gcc_plugin/ moved to instrumentation/
|
||||||
|
- examples/ renamed to utils/
|
||||||
- all compilers combined to afl-cc which emulates the previous ones
|
- all compilers combined to afl-cc which emulates the previous ones
|
||||||
- afl-llvm/gcc-rt.o merged into afl-compiler-rt.o
|
- afl-llvm/gcc-rt.o merged into afl-compiler-rt.o
|
||||||
- afl-fuzz
|
- afl-fuzz
|
||||||
@ -21,40 +22,50 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
a schedule performance score, which is much better that the previous
|
a schedule performance score, which is much better that the previous
|
||||||
walk the whole queue approach. Select the old mode with -Z (auto enabled
|
walk the whole queue approach. Select the old mode with -Z (auto enabled
|
||||||
with -M)
|
with -M)
|
||||||
- rpc.statsd support by Edznux, thanks a lot!
|
- rpc.statsd support, for stats and charts, by Edznux, thanks a lot!
|
||||||
- Marcel Boehme submitted a patch that improves all AFFast schedules :)
|
- Marcel Boehme submitted a patch that improves all AFFast schedules :)
|
||||||
- not specifying -M or -S will now auto-set "-S default"
|
- not specifying -M or -S will now auto-set "-S default"
|
||||||
- reading testcases from -i now descends into subdirectories
|
- reading testcases from -i now descends into subdirectories
|
||||||
- allow up to 4 times the -x command line option
|
- allow the -x command line option up to 4 times
|
||||||
- loaded extras now have a duplicate protection
|
- loaded extras now have a duplication protection
|
||||||
- If test cases are too large we do a partial read on the maximum
|
- If test cases are too large we do a partial read on the maximum
|
||||||
supported size
|
supported size
|
||||||
- longer seeds with the same trace information will now be ignored
|
- longer seeds with the same trace information will now be ignored
|
||||||
for fuzzing but still be used for splicing
|
for fuzzing but still be used for splicing
|
||||||
- crashing seeds are now not prohibiting a run anymore but are
|
- crashing seeds are now not prohibiting a run anymore but are
|
||||||
skipped. They are used for splicing though.
|
skipped - they are used for splicing, though
|
||||||
- update MOpt for expanded havoc modes
|
- update MOpt for expanded havoc modes
|
||||||
|
- setting the env var AFL_NO_AUTODICT will not load an LTO autodictionary
|
||||||
- added NO_SPLICING compile option and makefile define
|
- added NO_SPLICING compile option and makefile define
|
||||||
- added INTROSPECTION make target that writes all mutations to
|
- added INTROSPECTION make target that writes all mutations to
|
||||||
out/NAME/introspection.txt
|
out/NAME/introspection.txt
|
||||||
- added INTROSPECTION support for custom modules
|
|
||||||
- print special compile time options used in help output
|
- print special compile time options used in help output
|
||||||
|
- when using -c cmplog, one of the childs was not killed, fixed
|
||||||
|
- somewhere we broke -n dumb fuzzing, fixed
|
||||||
|
- added afl_custom_describe to the custom mutator API to allow for easy
|
||||||
|
mutation reproduction on crashing inputs
|
||||||
- instrumentation
|
- instrumentation
|
||||||
- We received an enhanced gcc_plugin module from AdaCore, thank you
|
- We received an enhanced gcc_plugin module from AdaCore, thank you
|
||||||
very much!!
|
very much!!
|
||||||
- not overriding -Ox or -fno-unroll-loops anymore
|
- not overriding -Ox or -fno-unroll-loops anymore
|
||||||
- we now have our own trace-pc-guard implementation. It is the same as
|
- we now have our own trace-pc-guard implementation. It is the same as
|
||||||
-fsanitize-coverage=trace-pc-guard from llvm 12, but: it is a) inline
|
-fsanitize-coverage=trace-pc-guard from llvm 12, but: it is a) inline
|
||||||
and b) works from llvm 10+ on :)
|
and b) works from llvm 10.0.1 + onwards :)
|
||||||
- new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
|
- new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
|
||||||
-x dictionary of string comparisons found during compilation
|
-x dictionary of string comparisons found during compilation
|
||||||
- LTO autodict now also collects interesting cmp comparisons,
|
- LTO autodict now also collects interesting cmp comparisons,
|
||||||
std::string compare + find + ==, bcmp
|
std::string compare + find + ==, bcmp
|
||||||
- fix crash in dict2file for integers > 64 bit
|
- fix crash in dict2file for integers > 64 bit
|
||||||
- unicornafl synced with upstream (arm64 fix, better rust bindings)
|
- custom mutators
|
||||||
- added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
|
- added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
|
||||||
- added a new custom mutator: libfuzzer that integrates libfuzzer mutations
|
- added a new custom mutator: libfuzzer that integrates libfuzzer mutations
|
||||||
- Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
|
- Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
|
||||||
|
- added INTROSPECTION support for custom modules
|
||||||
|
- python fuzz function was not optional, fixed
|
||||||
|
- some python mutator speed improvements
|
||||||
|
- unicornafl synced with upstream version 1.02 (fixes, better rust bindings)
|
||||||
|
- renamed AFL_DEBUG_CHILD_OUTPUT to AFL_DEBUG_CHILD
|
||||||
|
- added AFL_CRASH_EXITCODE env variable to treat a child exitcode as crash
|
||||||
|
|
||||||
|
|
||||||
### Version ++2.68c (release)
|
### Version ++2.68c (release)
|
||||||
|
@ -63,7 +63,7 @@ x10 - that is a x100 difference!).
|
|||||||
If modifying the source is not an option (e.g. because you only have a binary
|
If modifying the source is not an option (e.g. because you only have a binary
|
||||||
and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD
|
and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD
|
||||||
to emulate the network. This is also much faster than the real network would be.
|
to emulate the network. This is also much faster than the real network would be.
|
||||||
See [examples/socket_fuzzing/](../examples/socket_fuzzing/).
|
See [utils/socket_fuzzing/](../utils/socket_fuzzing/).
|
||||||
|
|
||||||
There is an outdated afl++ branch that implements networking if you are
|
There is an outdated afl++ branch that implements networking if you are
|
||||||
desperate though: [https://github.com/AFLplusplus/AFLplusplus/tree/networking](https://github.com/AFLplusplus/AFLplusplus/tree/networking) -
|
desperate though: [https://github.com/AFLplusplus/AFLplusplus/tree/networking](https://github.com/AFLplusplus/AFLplusplus/tree/networking) -
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../README.md
|
|
@ -15,7 +15,7 @@
|
|||||||
high enough. Otherwise try retrowrite, afl-dyninst and if these
|
high enough. Otherwise try retrowrite, afl-dyninst and if these
|
||||||
fail too then try standard qemu_mode with AFL_ENTRYPOINT to where you need it.
|
fail too then try standard qemu_mode with AFL_ENTRYPOINT to where you need it.
|
||||||
|
|
||||||
If your target is a library use examples/afl_frida/.
|
If your target is a library use utils/afl_frida/.
|
||||||
|
|
||||||
If your target is non-linux then use unicorn_mode/.
|
If your target is non-linux then use unicorn_mode/.
|
||||||
|
|
||||||
@ -65,14 +65,14 @@
|
|||||||
## AFL FRIDA
|
## AFL FRIDA
|
||||||
|
|
||||||
If you want to fuzz a binary-only shared library then you can fuzz it with
|
If you want to fuzz a binary-only shared library then you can fuzz it with
|
||||||
frida-gum via examples/afl_frida/, you will have to write a harness to
|
frida-gum via utils/afl_frida/, you will have to write a harness to
|
||||||
call the target function in the library, use afl-frida.c as a template.
|
call the target function in the library, use afl-frida.c as a template.
|
||||||
|
|
||||||
|
|
||||||
## AFL UNTRACER
|
## AFL UNTRACER
|
||||||
|
|
||||||
If you want to fuzz a binary-only shared library then you can fuzz it with
|
If you want to fuzz a binary-only shared library then you can fuzz it with
|
||||||
examples/afl_untracer/, use afl-untracer.c as a template.
|
utils/afl_untracer/, use afl-untracer.c as a template.
|
||||||
It is slower than AFL FRIDA (see above).
|
It is slower than AFL FRIDA (see above).
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ C/C++:
|
|||||||
void *afl_custom_init(afl_state_t *afl, unsigned int seed);
|
void *afl_custom_init(afl_state_t *afl, unsigned int seed);
|
||||||
unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size);
|
unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size);
|
||||||
size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size);
|
size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size);
|
||||||
|
const char *afl_custom_describe(void *data, size_t max_description_len);
|
||||||
size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf);
|
size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf);
|
||||||
int afl_custom_init_trim(void *data, unsigned char *buf, size_t buf_size);
|
int afl_custom_init_trim(void *data, unsigned char *buf, size_t buf_size);
|
||||||
size_t afl_custom_trim(void *data, unsigned char **out_buf);
|
size_t afl_custom_trim(void *data, unsigned char **out_buf);
|
||||||
@ -57,6 +58,9 @@ def fuzz_count(buf, add_buf, max_size):
|
|||||||
def fuzz(buf, add_buf, max_size):
|
def fuzz(buf, add_buf, max_size):
|
||||||
return mutated_out
|
return mutated_out
|
||||||
|
|
||||||
|
def describe(max_description_length):
|
||||||
|
return "description_of_current_mutation"
|
||||||
|
|
||||||
def post_process(buf):
|
def post_process(buf):
|
||||||
return out_buf
|
return out_buf
|
||||||
|
|
||||||
@ -102,7 +106,7 @@ def introspection():
|
|||||||
of fuzzing attempts with this input based on a few factors.
|
of fuzzing attempts with this input based on a few factors.
|
||||||
If however the custom mutator wants to set this number instead on how often
|
If however the custom mutator wants to set this number instead on how often
|
||||||
it is called for a specific queue entry, use this function.
|
it is called for a specific queue entry, use this function.
|
||||||
This function in mostly useful if **not** `AFL_CUSTOM_MUTATOR_ONLY` is used.
|
This function is most useful if `AFL_CUSTOM_MUTATOR_ONLY` is **not** used.
|
||||||
|
|
||||||
- `fuzz` (optional):
|
- `fuzz` (optional):
|
||||||
|
|
||||||
@ -110,12 +114,19 @@ def introspection():
|
|||||||
additional test case.
|
additional test case.
|
||||||
Note that this function is optional - but it makes sense to use it.
|
Note that this function is optional - but it makes sense to use it.
|
||||||
You would only skip this if `post_process` is used to fix checksums etc.
|
You would only skip this if `post_process` is used to fix checksums etc.
|
||||||
so you are using it e.g. as a post processing library.
|
so if you are using it e.g. as a post processing library.
|
||||||
|
|
||||||
|
- `describe` (optional):
|
||||||
|
|
||||||
|
When this function is called, it shall describe the current testcase,
|
||||||
|
generated by the last mutation. This will be called, for example,
|
||||||
|
to name the written testcase file after a crash occurred.
|
||||||
|
Using it can help to reproduce crashing mutations.
|
||||||
|
|
||||||
- `havoc_mutation` and `havoc_mutation_probability` (optional):
|
- `havoc_mutation` and `havoc_mutation_probability` (optional):
|
||||||
|
|
||||||
`havoc_mutation` performs a single custom mutation on a given input. This
|
`havoc_mutation` performs a single custom mutation on a given input. This
|
||||||
mutation is stacked with the other mutations in havoc. The other method,
|
mutation is stacked with other mutations in havoc. The other method,
|
||||||
`havoc_mutation_probability`, returns the probability that `havoc_mutation`
|
`havoc_mutation_probability`, returns the probability that `havoc_mutation`
|
||||||
is called in havoc. By default, it is 6%.
|
is called in havoc. By default, it is 6%.
|
||||||
|
|
||||||
@ -130,6 +141,9 @@ def introspection():
|
|||||||
`post_process` function. This function is then transforming the data into the
|
`post_process` function. This function is then transforming the data into the
|
||||||
format expected by the API before executing the target.
|
format expected by the API before executing the target.
|
||||||
|
|
||||||
|
This can return any python object that implements the buffer protocol and
|
||||||
|
supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
|
||||||
|
|
||||||
- `queue_new_entry` (optional):
|
- `queue_new_entry` (optional):
|
||||||
|
|
||||||
This methods is called after adding a new test case to the queue.
|
This methods is called after adding a new test case to the queue.
|
||||||
@ -168,7 +182,7 @@ trimmed input. Here's a quick API description:
|
|||||||
on this input (e.g. if your input has n elements and you want to remove them
|
on this input (e.g. if your input has n elements and you want to remove them
|
||||||
one by one, return n, if you do a binary search, return log(n), and so on).
|
one by one, return n, if you do a binary search, return log(n), and so on).
|
||||||
|
|
||||||
If your trimming algorithm doesn't allow you to determine the amount of
|
If your trimming algorithm doesn't allow to determine the amount of
|
||||||
(remaining) steps easily (esp. while running), then you can alternatively
|
(remaining) steps easily (esp. while running), then you can alternatively
|
||||||
return 1 here and always return 0 in `post_trim` until you are finished and
|
return 1 here and always return 0 in `post_trim` until you are finished and
|
||||||
no steps remain. In that case, returning 1 in `post_trim` will end the
|
no steps remain. In that case, returning 1 in `post_trim` will end the
|
||||||
@ -210,19 +224,20 @@ Optionally, the following environment variables are supported:
|
|||||||
|
|
||||||
- `AFL_PYTHON_ONLY`
|
- `AFL_PYTHON_ONLY`
|
||||||
|
|
||||||
Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead
|
Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead.
|
||||||
trimming can cause the same test breakage like havoc and splice.
|
|
||||||
|
|
||||||
- `AFL_DEBUG`
|
- `AFL_DEBUG`
|
||||||
|
|
||||||
When combined with `AFL_NO_UI`, this causes the C trimming code to emit additional messages about the performance and actions of your custom trimmer. Use this to see if it works :)
|
When combined with `AFL_NO_UI`, this causes the C trimming code to emit
|
||||||
|
additional messages about the performance and actions of your custom
|
||||||
|
trimmer. Use this to see if it works :)
|
||||||
|
|
||||||
## 3) Usage
|
## 3) Usage
|
||||||
|
|
||||||
### Prerequisite
|
### Prerequisite
|
||||||
|
|
||||||
For Python mutator, the python 3 or 2 development package is required. On
|
For Python mutators, the python 3 or 2 development package is required. On
|
||||||
Debian/Ubuntu/Kali this can be done:
|
Debian/Ubuntu/Kali it can be installed like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install python3-dev
|
sudo apt install python3-dev
|
||||||
@ -240,13 +255,13 @@ In case your setup is different, set the necessary variables like this:
|
|||||||
|
|
||||||
### Custom Mutator Preparation
|
### Custom Mutator Preparation
|
||||||
|
|
||||||
For C/C++ mutator, the source code must be compiled as a shared object:
|
For C/C++ mutators, the source code must be compiled as a shared object:
|
||||||
```bash
|
```bash
|
||||||
gcc -shared -Wall -O3 example.c -o example.so
|
gcc -shared -Wall -O3 example.c -o example.so
|
||||||
```
|
```
|
||||||
Note that if you specify multiple custom mutators, the corresponding functions will
|
Note that if you specify multiple custom mutators, the corresponding functions will
|
||||||
be called in the order in which they are specified. e.g first `post_process` function of
|
be called in the order in which they are specified. e.g first `post_process` function of
|
||||||
`example_first.so` will be called and then that of `example_second.so`
|
`example_first.so` will be called and then that of `example_second.so`.
|
||||||
|
|
||||||
### Run
|
### Run
|
||||||
|
|
||||||
@ -265,8 +280,8 @@ afl-fuzz /path/to/program
|
|||||||
|
|
||||||
## 4) Example
|
## 4) Example
|
||||||
|
|
||||||
Please see [example.c](../examples/custom_mutators/example.c) and
|
Please see [example.c](../utils/custom_mutators/example.c) and
|
||||||
[example.py](../examples/custom_mutators/example.py)
|
[example.py](../utils/custom_mutators/example.py)
|
||||||
|
|
||||||
## 5) Other Resources
|
## 5) Other Resources
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ make fairly broad use of environmental variables instead:
|
|||||||
in your `$PATH`.
|
in your `$PATH`.
|
||||||
|
|
||||||
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
|
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
|
||||||
One possible use of this is examples/clang_asm_normalize/, which lets
|
One possible use of this is utils/clang_asm_normalize/, which lets
|
||||||
you instrument hand-written assembly when compiling clang code by plugging
|
you instrument hand-written assembly when compiling clang code by plugging
|
||||||
a normalizer into the chain. (There is no equivalent feature for GCC.)
|
a normalizer into the chain. (There is no equivalent feature for GCC.)
|
||||||
|
|
||||||
@ -294,6 +294,9 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
on Linux systems. This slows things down, but lets you run more instances
|
on Linux systems. This slows things down, but lets you run more instances
|
||||||
of afl-fuzz than would be prudent (if you really want to).
|
of afl-fuzz than would be prudent (if you really want to).
|
||||||
|
|
||||||
|
- Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary
|
||||||
|
that is compiled into the target.
|
||||||
|
|
||||||
- `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input
|
- `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input
|
||||||
queue. This can help with rare situations where a program crashes only
|
queue. This can help with rare situations where a program crashes only
|
||||||
intermittently, but it's not really recommended under normal operating
|
intermittently, but it's not really recommended under normal operating
|
||||||
@ -306,6 +309,14 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
don't want AFL++ to spend too much time classifying that stuff and just
|
don't want AFL++ to spend too much time classifying that stuff and just
|
||||||
rapidly put all timeouts in that bin.
|
rapidly put all timeouts in that bin.
|
||||||
|
|
||||||
|
- Setting `AFL_FORKSRV_INIT_TMOUT` allows you to specify a different timeout
|
||||||
|
to wait for the forkserver to spin up. The default is the `-t` value times
|
||||||
|
`FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the
|
||||||
|
default would wait for `1000` milliseconds. Setting a different time here is useful
|
||||||
|
if the target has a very slow startup time, for example when doing
|
||||||
|
full-system fuzzing or emulation, but you don't want the actual runs
|
||||||
|
to wait too long for timeouts.
|
||||||
|
|
||||||
- `AFL_NO_ARITH` causes AFL++ to skip most of the deterministic arithmetics.
|
- `AFL_NO_ARITH` causes AFL++ to skip most of the deterministic arithmetics.
|
||||||
This can be useful to speed up the fuzzing of text-based file formats.
|
This can be useful to speed up the fuzzing of text-based file formats.
|
||||||
|
|
||||||
@ -380,8 +391,12 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to
|
processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to
|
||||||
exit soon after the first crash is found.
|
exit soon after the first crash is found.
|
||||||
|
|
||||||
- Setting `AFL_DEBUG_CHILD_OUTPUT` will not suppress the child output.
|
- Setting `AFL_DEBUG_CHILD` will not suppress the child output.
|
||||||
|
This lets you see all output of the child, making setup issues obvious.
|
||||||
|
For example, in an unicornafl harness, you might see python stacktraces.
|
||||||
|
You may also see other logs that way, indicating why the forkserver won't start.
|
||||||
Not pretty but good for debugging purposes.
|
Not pretty but good for debugging purposes.
|
||||||
|
Note that `AFL_DEBUG_CHILD_OUTPUT` is deprecated.
|
||||||
|
|
||||||
- Setting `AFL_NO_CPU_RED` will not display very high cpu usages in red color.
|
- Setting `AFL_NO_CPU_RED` will not display very high cpu usages in red color.
|
||||||
|
|
||||||
@ -389,6 +404,13 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
for an existing out folder, even if a different `-i` was provided.
|
for an existing out folder, even if a different `-i` was provided.
|
||||||
Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir.
|
Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir.
|
||||||
|
|
||||||
|
- Setting `AFL_MAX_DET_EXRAS` will change the threshold at what number of elements
|
||||||
|
in the `-x` dictionary and LTO autodict (combined) the probabilistic mode will
|
||||||
|
kick off. In probabilistic mode not all dictionary entires will be used all
|
||||||
|
of the times for fuzzing mutations to not slow down fuzzing.
|
||||||
|
The default count is `200` elements. So for the 200 + 1st element, there is a
|
||||||
|
1 in 201 chance, that one of the dictionary entries will not be used directly.
|
||||||
|
|
||||||
- Setting `AFL_NO_FORKSRV` disables the forkserver optimization, reverting to
|
- Setting `AFL_NO_FORKSRV` disables the forkserver optimization, reverting to
|
||||||
fork + execve() call for every tested input. This is useful mostly when
|
fork + execve() call for every tested input. This is useful mostly when
|
||||||
working with unruly libraries that create threads or do other crazy
|
working with unruly libraries that create threads or do other crazy
|
||||||
@ -406,6 +428,13 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
matches your StatsD server.
|
matches your StatsD server.
|
||||||
Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`.
|
Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`.
|
||||||
|
|
||||||
|
- Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash.
|
||||||
|
For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting
|
||||||
|
in an `-1` return code (i.e. `exit(-1)` got called), will be treated
|
||||||
|
as if a crash had ocurred.
|
||||||
|
This may be beneficial if you look for higher-level faulty conditions in which your
|
||||||
|
target still exits gracefully.
|
||||||
|
|
||||||
- Outdated environment variables that are not supported anymore:
|
- Outdated environment variables that are not supported anymore:
|
||||||
`AFL_DEFER_FORKSRV`
|
`AFL_DEFER_FORKSRV`
|
||||||
`AFL_PERSISTENT`
|
`AFL_PERSISTENT`
|
||||||
|
@ -78,10 +78,10 @@ Be sure to check out docs/sister_projects.md before writing your own.
|
|||||||
|
|
||||||
## Need to fuzz the command-line arguments of a particular program?
|
## Need to fuzz the command-line arguments of a particular program?
|
||||||
|
|
||||||
You can find a simple solution in examples/argv_fuzzing.
|
You can find a simple solution in utils/argv_fuzzing.
|
||||||
|
|
||||||
## Attacking a format that uses checksums?
|
## Attacking a format that uses checksums?
|
||||||
|
|
||||||
Remove the checksum-checking code or use a postprocessor!
|
Remove the checksum-checking code or use a postprocessor!
|
||||||
See examples/custom_mutators/ for more.
|
See utils/custom_mutators/ for more.
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Because of this, fuzzing with ASAN is recommended only in four scenarios:
|
|||||||
- Precisely gauge memory needs using http://jwilk.net/software/recidivm .
|
- Precisely gauge memory needs using http://jwilk.net/software/recidivm .
|
||||||
|
|
||||||
- Limit the memory available to process using cgroups on Linux (see
|
- Limit the memory available to process using cgroups on Linux (see
|
||||||
examples/asan_cgroups).
|
utils/asan_cgroups).
|
||||||
|
|
||||||
To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The
|
To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The
|
||||||
afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags.
|
afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags.
|
||||||
@ -74,7 +74,7 @@ There are also cgroups, but they are Linux-specific, not universally available
|
|||||||
even on Linux systems, and they require root permissions to set up; I'm a bit
|
even on Linux systems, and they require root permissions to set up; I'm a bit
|
||||||
hesitant to make afl-fuzz require root permissions just for that. That said,
|
hesitant to make afl-fuzz require root permissions just for that. That said,
|
||||||
if you are on Linux and want to use cgroups, check out the contributed script
|
if you are on Linux and want to use cgroups, check out the contributed script
|
||||||
that ships in examples/asan_cgroups/.
|
that ships in utils/asan_cgroups/.
|
||||||
|
|
||||||
In settings where cgroups aren't available, we have no nice, portable way to
|
In settings where cgroups aren't available, we have no nice, portable way to
|
||||||
avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for
|
avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for
|
||||||
|
@ -152,7 +152,7 @@ write a simple script that performs two actions:
|
|||||||
done
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
There is an example of such a script in examples/distributed_fuzzing/.
|
There is an example of such a script in utils/distributed_fuzzing/.
|
||||||
|
|
||||||
There are other (older) more featured, experimental tools:
|
There are other (older) more featured, experimental tools:
|
||||||
* https://github.com/richo/roving
|
* https://github.com/richo/roving
|
||||||
|
Binary file not shown.
@ -113,6 +113,7 @@
|
|||||||
#include <kstat.h>
|
#include <kstat.h>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <sys/pset.h>
|
#include <sys/pset.h>
|
||||||
|
#include <strings.h>
|
||||||
#endif
|
#endif
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
@ -143,8 +144,8 @@ struct queue_entry {
|
|||||||
u8 *fname; /* File name for the test case */
|
u8 *fname; /* File name for the test case */
|
||||||
u32 len; /* Input length */
|
u32 len; /* Input length */
|
||||||
|
|
||||||
u8 cal_failed, /* Calibration failed? */
|
u8 cal_failed; /* Calibration failed? */
|
||||||
trim_done, /* Trimmed? */
|
bool trim_done, /* Trimmed? */
|
||||||
was_fuzzed, /* historical, but needed for MOpt */
|
was_fuzzed, /* historical, but needed for MOpt */
|
||||||
passed_det, /* Deterministic stages passed? */
|
passed_det, /* Deterministic stages passed? */
|
||||||
has_new_cov, /* Triggers new coverage? */
|
has_new_cov, /* Triggers new coverage? */
|
||||||
@ -167,7 +168,8 @@ struct queue_entry {
|
|||||||
u8 *trace_mini; /* Trace bytes, if kept */
|
u8 *trace_mini; /* Trace bytes, if kept */
|
||||||
u32 tc_ref; /* Trace bytes ref count */
|
u32 tc_ref; /* Trace bytes ref count */
|
||||||
|
|
||||||
double perf_score; /* performance score */
|
double perf_score, /* performance score */
|
||||||
|
weight;
|
||||||
|
|
||||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||||
|
|
||||||
@ -311,6 +313,7 @@ enum {
|
|||||||
/* 10 */ PY_FUNC_QUEUE_GET,
|
/* 10 */ PY_FUNC_QUEUE_GET,
|
||||||
/* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
|
/* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
|
||||||
/* 12 */ PY_FUNC_INTROSPECTION,
|
/* 12 */ PY_FUNC_INTROSPECTION,
|
||||||
|
/* 13 */ PY_FUNC_DESCRIBE,
|
||||||
PY_FUNC_COUNT
|
PY_FUNC_COUNT
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -325,8 +328,7 @@ typedef struct py_mutator {
|
|||||||
u8 * fuzz_buf;
|
u8 * fuzz_buf;
|
||||||
size_t fuzz_size;
|
size_t fuzz_size;
|
||||||
|
|
||||||
u8 * post_process_buf;
|
Py_buffer post_process_buf;
|
||||||
size_t post_process_size;
|
|
||||||
|
|
||||||
u8 * trim_buf;
|
u8 * trim_buf;
|
||||||
size_t trim_size;
|
size_t trim_size;
|
||||||
@ -362,13 +364,14 @@ typedef struct afl_env_vars {
|
|||||||
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
|
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
|
||||||
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
|
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
|
||||||
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
||||||
afl_bench_until_crash, afl_debug_child_output, afl_autoresume,
|
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
|
||||||
afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd;
|
afl_cycle_schedules, afl_expand_havoc, afl_statsd;
|
||||||
|
|
||||||
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
||||||
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
|
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
|
||||||
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
|
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
|
||||||
*afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries;
|
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
|
||||||
|
*afl_testcache_entries;
|
||||||
|
|
||||||
} afl_env_vars_t;
|
} afl_env_vars_t;
|
||||||
|
|
||||||
@ -754,7 +757,7 @@ struct custom_mutator {
|
|||||||
* When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
|
* When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
|
||||||
* also give introspection information back with this function.
|
* also give introspection information back with this function.
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @return pointer to a text string (const char*)
|
* @return pointer to a text string (const char*)
|
||||||
*/
|
*/
|
||||||
const char *(*afl_custom_introspection)(void *data);
|
const char *(*afl_custom_introspection)(void *data);
|
||||||
@ -770,7 +773,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param buf Buffer containing the test case
|
* @param buf Buffer containing the test case
|
||||||
* @param buf_size Size of the test case
|
* @param buf_size Size of the test case
|
||||||
* @return The amount of fuzzes to perform on this queue entry, 0 = skip
|
* @return The amount of fuzzes to perform on this queue entry, 0 = skip
|
||||||
@ -782,7 +785,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional for now. Required in the future)
|
* (Optional for now. Required in the future)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
||||||
* output
|
* output
|
||||||
* @param[in] buf_size Size of the input/output data
|
* @param[in] buf_size Size of the input/output data
|
||||||
@ -797,6 +800,21 @@ struct custom_mutator {
|
|||||||
size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf,
|
size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf,
|
||||||
u8 *add_buf, size_t add_buf_size, size_t max_size);
|
u8 *add_buf, size_t add_buf_size, size_t max_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describe the current testcase, generated by the last mutation.
|
||||||
|
* This will be called, for example, to give the written testcase a name
|
||||||
|
* after a crash ocurred. It can help to reproduce crashing mutations.
|
||||||
|
*
|
||||||
|
* (Optional)
|
||||||
|
*
|
||||||
|
* @param data pointer returned by afl_customm_init for this custom mutator
|
||||||
|
* @paramp[in] max_description_len maximum size avaliable for the description.
|
||||||
|
* A longer return string is legal, but will be truncated.
|
||||||
|
* @return A valid ptr to a 0-terminated string.
|
||||||
|
* An empty or NULL return will result in a default description
|
||||||
|
*/
|
||||||
|
const char *(*afl_custom_describe)(void *data, size_t max_description_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A post-processing function to use right before AFL writes the test case to
|
* A post-processing function to use right before AFL writes the test case to
|
||||||
* disk in order to execute the target.
|
* disk in order to execute the target.
|
||||||
@ -804,7 +822,7 @@ struct custom_mutator {
|
|||||||
* (Optional) If this functionality is not needed, simply don't define this
|
* (Optional) If this functionality is not needed, simply don't define this
|
||||||
* function.
|
* function.
|
||||||
*
|
*
|
||||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
* @param[in] data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param[in] buf Buffer containing the test case to be executed
|
* @param[in] buf Buffer containing the test case to be executed
|
||||||
* @param[in] buf_size Size of the test case
|
* @param[in] buf_size Size of the test case
|
||||||
* @param[out] out_buf Pointer to the buffer storing the test case after
|
* @param[out] out_buf Pointer to the buffer storing the test case after
|
||||||
@ -831,7 +849,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param buf Buffer containing the test case
|
* @param buf Buffer containing the test case
|
||||||
* @param buf_size Size of the test case
|
* @param buf_size Size of the test case
|
||||||
* @return The amount of possible iteration steps to trim the input.
|
* @return The amount of possible iteration steps to trim the input.
|
||||||
@ -850,7 +868,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param[out] out_buf Pointer to the buffer containing the trimmed test case.
|
* @param[out] out_buf Pointer to the buffer containing the trimmed test case.
|
||||||
* The library can reuse a buffer for each call
|
* The library can reuse a buffer for each call
|
||||||
* and will have to free the buf (for example in deinit)
|
* and will have to free the buf (for example in deinit)
|
||||||
@ -865,7 +883,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param success Indicates if the last trim operation was successful.
|
* @param success Indicates if the last trim operation was successful.
|
||||||
* @return The next trim iteration index (from 0 to the maximum amount of
|
* @return The next trim iteration index (from 0 to the maximum amount of
|
||||||
* steps returned in init_trim). Negative on error.
|
* steps returned in init_trim). Negative on error.
|
||||||
@ -878,7 +896,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
* @param[in] data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
||||||
* output
|
* output
|
||||||
* @param[in] buf_size Size of input data
|
* @param[in] buf_size Size of input data
|
||||||
@ -897,7 +915,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @return The probability (0-100).
|
* @return The probability (0-100).
|
||||||
*/
|
*/
|
||||||
u8 (*afl_custom_havoc_mutation_probability)(void *data);
|
u8 (*afl_custom_havoc_mutation_probability)(void *data);
|
||||||
@ -907,7 +925,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param filename File name of the test case in the queue entry
|
* @param filename File name of the test case in the queue entry
|
||||||
* @return Return True(1) if the fuzzer will fuzz the queue entry, and
|
* @return Return True(1) if the fuzzer will fuzz the queue entry, and
|
||||||
* False(0) otherwise.
|
* False(0) otherwise.
|
||||||
@ -920,7 +938,7 @@ struct custom_mutator {
|
|||||||
*
|
*
|
||||||
* (Optional)
|
* (Optional)
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
* @param filename_new_queue File name of the new queue entry
|
* @param filename_new_queue File name of the new queue entry
|
||||||
* @param filename_orig_queue File name of the original queue entry. This
|
* @param filename_orig_queue File name of the original queue entry. This
|
||||||
* argument can be NULL while initializing the fuzzer
|
* argument can be NULL while initializing the fuzzer
|
||||||
@ -930,7 +948,7 @@ struct custom_mutator {
|
|||||||
/**
|
/**
|
||||||
* Deinitialize the custom mutator.
|
* Deinitialize the custom mutator.
|
||||||
*
|
*
|
||||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||||
*/
|
*/
|
||||||
void (*afl_custom_deinit)(void *data);
|
void (*afl_custom_deinit)(void *data);
|
||||||
|
|
||||||
@ -1006,7 +1024,7 @@ void classify_counts(afl_forkserver_t *);
|
|||||||
void init_count_class16(void);
|
void init_count_class16(void);
|
||||||
void minimize_bits(afl_state_t *, u8 *, u8 *);
|
void minimize_bits(afl_state_t *, u8 *, u8 *);
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
u8 *describe_op(afl_state_t *, u8);
|
u8 *describe_op(afl_state_t *, u8, size_t);
|
||||||
#endif
|
#endif
|
||||||
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
||||||
u8 has_new_bits(afl_state_t *, u8 *);
|
u8 has_new_bits(afl_state_t *, u8 *);
|
||||||
|
@ -636,7 +636,7 @@ struct afl_alloc_buf {
|
|||||||
|
|
||||||
#define AFL_ALLOC_SIZE_OFFSET (offsetof(struct afl_alloc_buf, buf))
|
#define AFL_ALLOC_SIZE_OFFSET (offsetof(struct afl_alloc_buf, buf))
|
||||||
|
|
||||||
/* Returs the container element to this ptr */
|
/* Returns the container element to this ptr */
|
||||||
static inline struct afl_alloc_buf *afl_alloc_bufptr(void *buf) {
|
static inline struct afl_alloc_buf *afl_alloc_bufptr(void *buf) {
|
||||||
|
|
||||||
return (struct afl_alloc_buf *)((u8 *)buf - AFL_ALLOC_SIZE_OFFSET);
|
return (struct afl_alloc_buf *)((u8 *)buf - AFL_ALLOC_SIZE_OFFSET);
|
||||||
@ -694,12 +694,18 @@ static inline void *afl_realloc(void **buf, size_t size_needed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* alloc */
|
/* alloc */
|
||||||
new_buf = (struct afl_alloc_buf *)realloc(new_buf, next_size);
|
struct afl_alloc_buf *newer_buf =
|
||||||
if (unlikely(!new_buf)) {
|
(struct afl_alloc_buf *)realloc(new_buf, next_size);
|
||||||
|
if (unlikely(!newer_buf)) {
|
||||||
|
|
||||||
|
free(new_buf); // avoid a leak
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
new_buf = newer_buf;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_buf->complete_size = next_size;
|
new_buf->complete_size = next_size;
|
||||||
@ -730,12 +736,18 @@ static inline void *afl_realloc_exact(void **buf, size_t size_needed) {
|
|||||||
if (unlikely(current_size == size_needed)) { return *buf; }
|
if (unlikely(current_size == size_needed)) { return *buf; }
|
||||||
|
|
||||||
/* alloc */
|
/* alloc */
|
||||||
new_buf = (struct afl_alloc_buf *)realloc(new_buf, size_needed);
|
struct afl_alloc_buf *newer_buf =
|
||||||
if (unlikely(!new_buf)) {
|
(struct afl_alloc_buf *)realloc(new_buf, size_needed);
|
||||||
|
if (unlikely(!newer_buf)) {
|
||||||
|
|
||||||
|
free(new_buf); // avoid a leak
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
new_buf = newer_buf;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_buf->complete_size = size_needed;
|
new_buf->complete_size = size_needed;
|
||||||
|
@ -31,14 +31,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "stdbool.h"
|
|
||||||
|
|
||||||
/* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */
|
/* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */
|
||||||
|
|
||||||
#define STRINGIFY_VAL_SIZE_MAX (16)
|
#define STRINGIFY_VAL_SIZE_MAX (16)
|
||||||
|
|
||||||
void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin);
|
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin);
|
||||||
void check_environment_vars(char **env);
|
void check_environment_vars(char **env);
|
||||||
|
|
||||||
char **argv_cpy_dup(int argc, char **argv);
|
char **argv_cpy_dup(int argc, char **argv);
|
||||||
|
@ -270,6 +270,16 @@
|
|||||||
\
|
\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* Show a prefixed debug output. */
|
||||||
|
|
||||||
|
#define DEBUGF(x...) \
|
||||||
|
do { \
|
||||||
|
\
|
||||||
|
SAYF(cMGN "[D] " cBRI "DEBUG: " cRST x); \
|
||||||
|
SAYF(cRST ""); \
|
||||||
|
\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Error-checking versions of read() and write() that call RPFATAL() as
|
/* Error-checking versions of read() and write() that call RPFATAL() as
|
||||||
appropriate. */
|
appropriate. */
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ static char *afl_environment_deprecated[] = {
|
|||||||
|
|
||||||
"AFL_LLVM_WHITELIST",
|
"AFL_LLVM_WHITELIST",
|
||||||
"AFL_GCC_WHITELIST",
|
"AFL_GCC_WHITELIST",
|
||||||
|
"AFL_DEBUG_CHILD_OUTPUT",
|
||||||
"AFL_DEFER_FORKSRV",
|
"AFL_DEFER_FORKSRV",
|
||||||
"AFL_POST_LIBRARY",
|
"AFL_POST_LIBRARY",
|
||||||
"AFL_PERSISTENT",
|
"AFL_PERSISTENT",
|
||||||
@ -31,12 +32,13 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_CODE_START",
|
"AFL_CODE_START",
|
||||||
"AFL_COMPCOV_BINNAME",
|
"AFL_COMPCOV_BINNAME",
|
||||||
"AFL_COMPCOV_LEVEL",
|
"AFL_COMPCOV_LEVEL",
|
||||||
|
"AFL_CRASH_EXITCODE",
|
||||||
"AFL_CUSTOM_MUTATOR_LIBRARY",
|
"AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||||
"AFL_CUSTOM_MUTATOR_ONLY",
|
"AFL_CUSTOM_MUTATOR_ONLY",
|
||||||
"AFL_CXX",
|
"AFL_CXX",
|
||||||
"AFL_CYCLE_SCHEDULES",
|
"AFL_CYCLE_SCHEDULES",
|
||||||
"AFL_DEBUG",
|
"AFL_DEBUG",
|
||||||
"AFL_DEBUG_CHILD_OUTPUT",
|
"AFL_DEBUG_CHILD",
|
||||||
"AFL_DEBUG_GDB",
|
"AFL_DEBUG_GDB",
|
||||||
"AFL_DISABLE_TRIM",
|
"AFL_DISABLE_TRIM",
|
||||||
"AFL_DONT_OPTIMIZE",
|
"AFL_DONT_OPTIMIZE",
|
||||||
@ -99,6 +101,7 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_LLVM_LTO_STARTID",
|
"AFL_LLVM_LTO_STARTID",
|
||||||
"AFL_LLVM_LTO_DONTWRITEID",
|
"AFL_LLVM_LTO_DONTWRITEID",
|
||||||
"AFL_NO_ARITH",
|
"AFL_NO_ARITH",
|
||||||
|
"AFL_NO_AUTODICT",
|
||||||
"AFL_NO_BUILTIN",
|
"AFL_NO_BUILTIN",
|
||||||
"AFL_NO_CPU_RED",
|
"AFL_NO_CPU_RED",
|
||||||
"AFL_NO_FORKSRV",
|
"AFL_NO_FORKSRV",
|
||||||
@ -123,6 +126,7 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_QEMU_PERSISTENT_CNT",
|
"AFL_QEMU_PERSISTENT_CNT",
|
||||||
"AFL_QEMU_PERSISTENT_GPR",
|
"AFL_QEMU_PERSISTENT_GPR",
|
||||||
"AFL_QEMU_PERSISTENT_HOOK",
|
"AFL_QEMU_PERSISTENT_HOOK",
|
||||||
|
"AFL_QEMU_PERSISTENT_MEM",
|
||||||
"AFL_QEMU_PERSISTENT_RET",
|
"AFL_QEMU_PERSISTENT_RET",
|
||||||
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
|
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
|
||||||
"AFL_QEMU_PERSISTENT_EXITS",
|
"AFL_QEMU_PERSISTENT_EXITS",
|
||||||
|
@ -37,9 +37,7 @@ typedef struct afl_forkserver {
|
|||||||
|
|
||||||
/* a program that includes afl-forkserver needs to define these */
|
/* a program that includes afl-forkserver needs to define these */
|
||||||
|
|
||||||
u8 uses_asan; /* Target uses ASAN? */
|
|
||||||
u8 *trace_bits; /* SHM with instrumentation bitmap */
|
u8 *trace_bits; /* SHM with instrumentation bitmap */
|
||||||
u8 use_stdin; /* use stdin for sending data */
|
|
||||||
|
|
||||||
s32 fsrv_pid, /* PID of the fork server */
|
s32 fsrv_pid, /* PID of the fork server */
|
||||||
child_pid, /* PID of the fuzzed program */
|
child_pid, /* PID of the fuzzed program */
|
||||||
@ -53,8 +51,6 @@ typedef struct afl_forkserver {
|
|||||||
fsrv_ctl_fd, /* Fork server control pipe (write) */
|
fsrv_ctl_fd, /* Fork server control pipe (write) */
|
||||||
fsrv_st_fd; /* Fork server status pipe (read) */
|
fsrv_st_fd; /* Fork server status pipe (read) */
|
||||||
|
|
||||||
u8 no_unlink; /* do not unlink cur_input */
|
|
||||||
|
|
||||||
u32 exec_tmout; /* Configurable exec timeout (ms) */
|
u32 exec_tmout; /* Configurable exec timeout (ms) */
|
||||||
u32 init_tmout; /* Configurable init timeout (ms) */
|
u32 init_tmout; /* Configurable init timeout (ms) */
|
||||||
u32 map_size; /* map size used by the target */
|
u32 map_size; /* map size used by the target */
|
||||||
@ -73,13 +69,22 @@ typedef struct afl_forkserver {
|
|||||||
|
|
||||||
u8 last_kill_signal; /* Signal that killed the child */
|
u8 last_kill_signal; /* Signal that killed the child */
|
||||||
|
|
||||||
u8 use_shmem_fuzz; /* use shared mem for test cases */
|
bool use_shmem_fuzz; /* use shared mem for test cases */
|
||||||
|
|
||||||
u8 support_shmem_fuzz; /* set by afl-fuzz */
|
bool support_shmem_fuzz; /* set by afl-fuzz */
|
||||||
|
|
||||||
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
|
bool use_fauxsrv; /* Fauxsrv for non-forking targets? */
|
||||||
|
|
||||||
u8 qemu_mode; /* if running in qemu mode or not */
|
bool qemu_mode; /* if running in qemu mode or not */
|
||||||
|
|
||||||
|
bool use_stdin; /* use stdin for sending data */
|
||||||
|
|
||||||
|
bool no_unlink; /* do not unlink cur_input */
|
||||||
|
|
||||||
|
bool uses_asan; /* Target uses ASAN? */
|
||||||
|
|
||||||
|
bool uses_crash_exitcode; /* Custom crash exitcode specified? */
|
||||||
|
u8 crash_exitcode; /* The crash exitcode specified */
|
||||||
|
|
||||||
u32 *shmem_fuzz_len; /* length of the fuzzing test case */
|
u32 *shmem_fuzz_len; /* length of the fuzzing test case */
|
||||||
|
|
||||||
|
@ -268,8 +268,8 @@ struct InsTrim : public ModulePass {
|
|||||||
|
|
||||||
for (auto &BB : F)
|
for (auto &BB : F)
|
||||||
if (BB.size() > 0) ++bb_cnt;
|
if (BB.size() > 0) ++bb_cnt;
|
||||||
SAYF(cMGN "[D] " cRST "Function %s size %zu %u\n",
|
DEBUGF("Function %s size %zu %u\n", F.getName().str().c_str(), F.size(),
|
||||||
F.getName().str().c_str(), F.size(), bb_cnt);
|
bb_cnt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ The numerical value specified within the loop controls the maximum number
|
|||||||
of iterations before AFL will restart the process from scratch. This minimizes
|
of iterations before AFL will restart the process from scratch. This minimizes
|
||||||
the impact of memory leaks and similar glitches; 1000 is a good starting point.
|
the impact of memory leaks and similar glitches; 1000 is a good starting point.
|
||||||
|
|
||||||
A more detailed template is shown in ../examples/persistent_demo/.
|
A more detailed template is shown in ../utils/persistent_mode/.
|
||||||
Similarly to the previous mode, the feature works only with afl-gcc-fast or
|
Similarly to the previous mode, the feature works only with afl-gcc-fast or
|
||||||
afl-clang-fast; #ifdef guards can be used to suppress it when using other
|
afl-clang-fast; #ifdef guards can be used to suppress it when using other
|
||||||
compilers.
|
compilers.
|
||||||
|
@ -60,7 +60,12 @@ AUTODICTIONARY: 11 strings found
|
|||||||
|
|
||||||
## Getting llvm 11+
|
## Getting llvm 11+
|
||||||
|
|
||||||
### Installing llvm from the llvm repository (version 11)
|
### Installing llvm version 11
|
||||||
|
|
||||||
|
llvm 11 should be available in all current Linux repositories.
|
||||||
|
If you use an outdated Linux distribution read the next section.
|
||||||
|
|
||||||
|
### Installing llvm from the llvm repository (version 12)
|
||||||
|
|
||||||
Installing the llvm snapshot builds is easy and mostly painless:
|
Installing the llvm snapshot builds is easy and mostly painless:
|
||||||
|
|
||||||
@ -73,11 +78,11 @@ then add the pgp key of llvm and install the packages:
|
|||||||
```
|
```
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||||
apt-get update && apt-get upgrade -y
|
apt-get update && apt-get upgrade -y
|
||||||
apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \
|
apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
|
||||||
libc++abi1-11 libc++abi-11-dev libclang1-11 libclang-11-dev \
|
libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
|
||||||
libclang-common-11-dev libclang-cpp11 libclang-cpp11-dev liblld-11 \
|
libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
|
||||||
liblld-11-dev liblldb-11 liblldb-11-dev libllvm11 libomp-11-dev \
|
liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
|
||||||
libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools
|
libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building llvm yourself (version 12)
|
### Building llvm yourself (version 12)
|
||||||
@ -120,16 +125,22 @@ While compiling, a dictionary based on string comparisons is automatically
|
|||||||
generated and put into the target binary. This dictionary is transfered to afl-fuzz
|
generated and put into the target binary. This dictionary is transfered to afl-fuzz
|
||||||
on start. This improves coverage statistically by 5-10% :)
|
on start. This improves coverage statistically by 5-10% :)
|
||||||
|
|
||||||
|
Note that if for any reason you do not want to use the autodictionary feature
|
||||||
|
then just set the environment variable `AFL_NO_AUTODICT` when starting afl-fuzz.
|
||||||
|
|
||||||
## Fixed memory map
|
## Fixed memory map
|
||||||
|
|
||||||
To speed up fuzzing, it is possible to set a fixed shared memory map.
|
To speed up fuzzing a little bit more, it is possible to set a fixed shared
|
||||||
|
memory map.
|
||||||
Recommended is the value 0x10000.
|
Recommended is the value 0x10000.
|
||||||
|
|
||||||
In most cases this will work without any problems. However if a target uses
|
In most cases this will work without any problems. However if a target uses
|
||||||
early constructors, ifuncs or a deferred forkserver this can crash the target.
|
early constructors, ifuncs or a deferred forkserver this can crash the target.
|
||||||
On unusual operating systems/processors/kernels or weird libraries this might
|
|
||||||
fail so to change the fixed address at compile time set
|
Also on unusual operating systems/processors/kernels or weird libraries the
|
||||||
AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address
|
recommended 0x10000 address might not work, so then change the fixed address.
|
||||||
to be dynamic - the original afl way, which is slower).
|
|
||||||
|
To enable this feature set AFL_LLVM_MAP_ADDR with the address.
|
||||||
|
|
||||||
## Document edge IDs
|
## Document edge IDs
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ and that its state can be resetted so that multiple calls can be performed
|
|||||||
without resource leaks and former runs having no impact on following runs
|
without resource leaks and former runs having no impact on following runs
|
||||||
(this can be seen by the `stability` indicator in the `afl-fuzz` UI).
|
(this can be seen by the `stability` indicator in the `afl-fuzz` UI).
|
||||||
|
|
||||||
Examples can be found in [examples/persistent_mode](../examples/persistent_mode).
|
Examples can be found in [utils/persistent_mode](../utils/persistent_mode).
|
||||||
|
|
||||||
## 2) TLDR;
|
## 2) TLDR;
|
||||||
|
|
||||||
@ -23,15 +23,20 @@ __AFL_FUZZ_INIT();
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
||||||
|
// anything else here, eg. command line arguments, initialization, etc.
|
||||||
|
|
||||||
#ifdef __AFL_HAVE_MANUAL_CONTROL
|
#ifdef __AFL_HAVE_MANUAL_CONTROL
|
||||||
__AFL_INIT();
|
__AFL_INIT();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT
|
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT
|
||||||
|
// and before __AFL_LOOP!
|
||||||
|
|
||||||
while (__AFL_LOOP(10000)) {
|
while (__AFL_LOOP(10000)) {
|
||||||
|
|
||||||
int len = __AFL_FUZZ_TESTCASE_LEN;
|
int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a
|
||||||
|
// call!
|
||||||
|
|
||||||
if (len < 8) continue; // check for a required/useful minimum input length
|
if (len < 8) continue; // check for a required/useful minimum input length
|
||||||
|
|
||||||
/* Setup function call, e.g. struct target *tmp = libtarget_init() */
|
/* Setup function call, e.g. struct target *tmp = libtarget_init() */
|
||||||
@ -110,37 +115,13 @@ With the location selected, add this code in the appropriate spot:
|
|||||||
```
|
```
|
||||||
|
|
||||||
You don't need the #ifdef guards, but including them ensures that the program
|
You don't need the #ifdef guards, but including them ensures that the program
|
||||||
will keep working normally when compiled with a tool other than afl-clang-fast.
|
will keep working normally when compiled with a tool other than afl-clang-fast/
|
||||||
|
afl-clang-lto/afl-gcc-fast.
|
||||||
|
|
||||||
Finally, recompile the program with afl-clang-fast/lto (afl-gcc or afl-clang will
|
Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
|
||||||
*not* generate a deferred-initialization binary) - and you should be all set!
|
(afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
|
||||||
|
and you should be all set!
|
||||||
|
|
||||||
*NOTE:* In the code between `main` and `__AFL_INIT()` should not be any code
|
|
||||||
run that is instrumented - otherwise a crash might occure.
|
|
||||||
In case this is useful (e.g. for expensive one time initialization) you can
|
|
||||||
try to do the following:
|
|
||||||
|
|
||||||
Add after the includes:
|
|
||||||
```
|
|
||||||
extern unsigned char *__afl_area_ptr;
|
|
||||||
#define MAX_DUMMY_SIZE 256000
|
|
||||||
|
|
||||||
__attribute__((constructor(1))) void __afl_protect(void) {
|
|
||||||
#ifdef MAP_FIXED_NOREPLACE
|
|
||||||
__afl_area_ptr = (unsigned char*) mmap((void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
||||||
if ((uint64_t)__afl_area_ptr == -1)
|
|
||||||
#endif
|
|
||||||
__afl_area_ptr = (unsigned char*) mmap((void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
||||||
if ((uint64_t)__afl_area_ptr == -1)
|
|
||||||
__afl_area_ptr = (unsigned char*) mmap(NULL, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
and just before `__AFL_INIT()`:
|
|
||||||
```
|
|
||||||
munmap(__afl_area_ptr, MAX_DUMMY_SIZE);
|
|
||||||
__afl_area_ptr = NULL;
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4) Persistent mode
|
## 4) Persistent mode
|
||||||
|
|
||||||
@ -169,7 +150,7 @@ the impact of memory leaks and similar glitches; 1000 is a good starting point,
|
|||||||
and going much higher increases the likelihood of hiccups without giving you
|
and going much higher increases the likelihood of hiccups without giving you
|
||||||
any real performance benefits.
|
any real performance benefits.
|
||||||
|
|
||||||
A more detailed template is shown in ../examples/persistent_demo/.
|
A more detailed template is shown in ../utils/persistent_mode/.
|
||||||
Similarly to the previous mode, the feature works only with afl-clang-fast; #ifdef
|
Similarly to the previous mode, the feature works only with afl-clang-fast; #ifdef
|
||||||
guards can be used to suppress it when using other compilers.
|
guards can be used to suppress it when using other compilers.
|
||||||
|
|
||||||
|
@ -544,7 +544,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
|
|
||||||
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
||||||
// scanForDangerousFunctions(&M);
|
|
||||||
|
initInstrumentList();
|
||||||
|
scanForDangerousFunctions(&M);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|
||||||
@ -819,6 +821,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
|||||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||||
|
|
||||||
if (F.empty()) return;
|
if (F.empty()) return;
|
||||||
|
if (!isInInstrumentList(&F)) return;
|
||||||
|
|
||||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||||
return; // Should not instrument sanitizer init functions.
|
return; // Should not instrument sanitizer init functions.
|
||||||
if (F.getName().startswith("__sanitizer_"))
|
if (F.getName().startswith("__sanitizer_"))
|
||||||
@ -1123,11 +1127,11 @@ void ModuleSanitizerCoverage::InjectTraceForCmp(
|
|||||||
Value * A1 = ICMP->getOperand(1);
|
Value * A1 = ICMP->getOperand(1);
|
||||||
if (!A0->getType()->isIntegerTy()) continue;
|
if (!A0->getType()->isIntegerTy()) continue;
|
||||||
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
|
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
|
||||||
int CallbackIdx =
|
int CallbackIdx = TypeSize == 8 ? 0
|
||||||
TypeSize == 8
|
|
||||||
? 0
|
|
||||||
: TypeSize == 16 ? 1
|
: TypeSize == 16 ? 1
|
||||||
: TypeSize == 32 ? 2 : TypeSize == 64 ? 3 : -1;
|
: TypeSize == 32 ? 2
|
||||||
|
: TypeSize == 64 ? 3
|
||||||
|
: -1;
|
||||||
if (CallbackIdx < 0) continue;
|
if (CallbackIdx < 0) continue;
|
||||||
// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
|
// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
|
||||||
auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
|
auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
|
||||||
@ -1315,6 +1319,7 @@ std::string ModuleSanitizerCoverage::getSectionEnd(
|
|||||||
}
|
}
|
||||||
|
|
||||||
char ModuleSanitizerCoverageLegacyPass::ID = 0;
|
char ModuleSanitizerCoverageLegacyPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
|
INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
|
||||||
"Pass for instrumenting coverage on functions", false,
|
"Pass for instrumenting coverage on functions", false,
|
||||||
false)
|
false)
|
||||||
@ -1323,6 +1328,7 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
|
|||||||
INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
|
INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
|
||||||
"Pass for instrumenting coverage on functions", false,
|
"Pass for instrumenting coverage on functions", false,
|
||||||
false)
|
false)
|
||||||
|
|
||||||
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
|
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
|
||||||
const SanitizerCoverageOptions &Options,
|
const SanitizerCoverageOptions &Options,
|
||||||
const std::vector<std::string> &AllowlistFiles,
|
const std::vector<std::string> &AllowlistFiles,
|
||||||
|
@ -101,6 +101,11 @@ int __afl_sharedmem_fuzzing __attribute__((weak));
|
|||||||
|
|
||||||
struct cmp_map *__afl_cmp_map;
|
struct cmp_map *__afl_cmp_map;
|
||||||
|
|
||||||
|
/* Child pid? */
|
||||||
|
|
||||||
|
static s32 child_pid;
|
||||||
|
static void (*old_sigterm_handler)(int) = 0;
|
||||||
|
|
||||||
/* Running in persistent mode? */
|
/* Running in persistent mode? */
|
||||||
|
|
||||||
static u8 is_persistent;
|
static u8 is_persistent;
|
||||||
@ -109,6 +114,14 @@ static u8 is_persistent;
|
|||||||
|
|
||||||
static u8 _is_sancov;
|
static u8 _is_sancov;
|
||||||
|
|
||||||
|
/* ensure we kill the child on termination */
|
||||||
|
|
||||||
|
void at_exit(int signal) {
|
||||||
|
|
||||||
|
if (child_pid > 0) { kill(child_pid, SIGKILL); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Uninspired gcc plugin instrumentation */
|
/* Uninspired gcc plugin instrumentation */
|
||||||
|
|
||||||
void __afl_trace(const u32 x) {
|
void __afl_trace(const u32 x) {
|
||||||
@ -150,6 +163,12 @@ static void __afl_map_shm_fuzz() {
|
|||||||
|
|
||||||
char *id_str = getenv(SHM_FUZZ_ENV_VAR);
|
char *id_str = getenv(SHM_FUZZ_ENV_VAR);
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
|
fprintf(stderr, "DEBUG: fuzzcase shmem %s\n", id_str ? id_str : "none");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (id_str) {
|
if (id_str) {
|
||||||
|
|
||||||
u8 *map = NULL;
|
u8 *map = NULL;
|
||||||
@ -182,7 +201,8 @@ static void __afl_map_shm_fuzz() {
|
|||||||
|
|
||||||
if (!map || map == (void *)-1) {
|
if (!map || map == (void *)-1) {
|
||||||
|
|
||||||
perror("Could not access fuzzign shared memory");
|
perror("Could not access fuzzing shared memory");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -199,6 +219,7 @@ static void __afl_map_shm_fuzz() {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n");
|
fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -322,6 +343,8 @@ static void __afl_map_shm(void) {
|
|||||||
send_forkserver_error(FS_ERROR_MAP_ADDR);
|
send_forkserver_error(FS_ERROR_MAP_ADDR);
|
||||||
else
|
else
|
||||||
send_forkserver_error(FS_ERROR_MMAP);
|
send_forkserver_error(FS_ERROR_MMAP);
|
||||||
|
perror("mmap for map");
|
||||||
|
|
||||||
exit(2);
|
exit(2);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -332,20 +355,22 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
__afl_area_ptr = shmat(shm_id, (void *)__afl_map_addr, 0);
|
__afl_area_ptr = shmat(shm_id, (void *)__afl_map_addr, 0);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Whooooops. */
|
/* Whooooops. */
|
||||||
|
|
||||||
if (__afl_area_ptr == (void *)-1) {
|
if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) {
|
||||||
|
|
||||||
if (__afl_map_addr)
|
if (__afl_map_addr)
|
||||||
send_forkserver_error(FS_ERROR_MAP_ADDR);
|
send_forkserver_error(FS_ERROR_MAP_ADDR);
|
||||||
else
|
else
|
||||||
send_forkserver_error(FS_ERROR_SHMAT);
|
send_forkserver_error(FS_ERROR_SHMAT);
|
||||||
|
|
||||||
|
perror("shmat for map");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Write something into the bitmap so that even with low AFL_INST_RATIO,
|
/* Write something into the bitmap so that even with low AFL_INST_RATIO,
|
||||||
our parent doesn't give up on us. */
|
our parent doesn't give up on us. */
|
||||||
|
|
||||||
@ -363,6 +388,7 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
fprintf(stderr, "can not acquire mmap for address %p\n",
|
fprintf(stderr, "can not acquire mmap for address %p\n",
|
||||||
(void *)__afl_map_addr);
|
(void *)__afl_map_addr);
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -397,7 +423,8 @@ static void __afl_map_shm(void) {
|
|||||||
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
|
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
|
||||||
if (shm_fd == -1) {
|
if (shm_fd == -1) {
|
||||||
|
|
||||||
fprintf(stderr, "shm_open() failed\n");
|
perror("shm_open() failed\n");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -411,6 +438,7 @@ static void __afl_map_shm(void) {
|
|||||||
shm_fd = -1;
|
shm_fd = -1;
|
||||||
|
|
||||||
fprintf(stderr, "mmap() failed\n");
|
fprintf(stderr, "mmap() failed\n");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -422,7 +450,13 @@ static void __afl_map_shm(void) {
|
|||||||
__afl_cmp_map = shmat(shm_id, NULL, 0);
|
__afl_cmp_map = shmat(shm_id, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (__afl_cmp_map == (void *)-1) _exit(1);
|
if (!__afl_cmp_map || __afl_cmp_map == (void *)-1) {
|
||||||
|
|
||||||
|
perror("shmat for cmplog");
|
||||||
|
send_forkserver_error(FS_ERROR_SHM_OPEN);
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +466,6 @@ static void __afl_map_shm(void) {
|
|||||||
static void __afl_start_snapshots(void) {
|
static void __afl_start_snapshots(void) {
|
||||||
|
|
||||||
static u8 tmp[4] = {0, 0, 0, 0};
|
static u8 tmp[4] = {0, 0, 0, 0};
|
||||||
s32 child_pid;
|
|
||||||
u32 status = 0;
|
u32 status = 0;
|
||||||
u32 already_read_first = 0;
|
u32 already_read_first = 0;
|
||||||
u32 was_killed;
|
u32 was_killed;
|
||||||
@ -579,6 +612,7 @@ static void __afl_start_snapshots(void) {
|
|||||||
//(void)nice(-20); // does not seem to improve
|
//(void)nice(-20); // does not seem to improve
|
||||||
|
|
||||||
signal(SIGCHLD, old_sigchld_handler);
|
signal(SIGCHLD, old_sigchld_handler);
|
||||||
|
signal(SIGTERM, old_sigterm_handler);
|
||||||
|
|
||||||
close(FORKSRV_FD);
|
close(FORKSRV_FD);
|
||||||
close(FORKSRV_FD + 1);
|
close(FORKSRV_FD + 1);
|
||||||
@ -633,6 +667,11 @@ static void __afl_start_snapshots(void) {
|
|||||||
|
|
||||||
static void __afl_start_forkserver(void) {
|
static void __afl_start_forkserver(void) {
|
||||||
|
|
||||||
|
struct sigaction orig_action;
|
||||||
|
sigaction(SIGTERM, NULL, &orig_action);
|
||||||
|
old_sigterm_handler = orig_action.sa_handler;
|
||||||
|
signal(SIGTERM, at_exit);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
|
if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
|
||||||
afl_snapshot_init() >= 0) {
|
afl_snapshot_init() >= 0) {
|
||||||
@ -645,7 +684,6 @@ static void __afl_start_forkserver(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
u8 tmp[4] = {0, 0, 0, 0};
|
u8 tmp[4] = {0, 0, 0, 0};
|
||||||
s32 child_pid;
|
|
||||||
u32 status = 0;
|
u32 status = 0;
|
||||||
u32 already_read_first = 0;
|
u32 already_read_first = 0;
|
||||||
u32 was_killed;
|
u32 was_killed;
|
||||||
@ -793,6 +831,7 @@ static void __afl_start_forkserver(void) {
|
|||||||
//(void)nice(-20);
|
//(void)nice(-20);
|
||||||
|
|
||||||
signal(SIGCHLD, old_sigchld_handler);
|
signal(SIGCHLD, old_sigchld_handler);
|
||||||
|
signal(SIGTERM, old_sigterm_handler);
|
||||||
|
|
||||||
close(FORKSRV_FD);
|
close(FORKSRV_FD);
|
||||||
close(FORKSRV_FD + 1);
|
close(FORKSRV_FD + 1);
|
||||||
@ -992,7 +1031,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
|
|||||||
// For stability analysis, if you want to know to which function unstable
|
// For stability analysis, if you want to know to which function unstable
|
||||||
// edge IDs belong - uncomment, recompile+install llvm_mode, recompile
|
// edge IDs belong - uncomment, recompile+install llvm_mode, recompile
|
||||||
// the target. libunwind and libbacktrace are better solutions.
|
// the target. libunwind and libbacktrace are better solutions.
|
||||||
// Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
|
// Set AFL_DEBUG_CHILD=1 and run afl-fuzz with 2>file to capture
|
||||||
// the backtrace output
|
// the backtrace output
|
||||||
/*
|
/*
|
||||||
uint32_t unstable[] = { ... unstable edge IDs };
|
uint32_t unstable[] = { ... unstable edge IDs };
|
||||||
|
@ -627,8 +627,7 @@ struct afl_pass : gimple_opt_pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF("loaded allowlist with %zu file and %zu function entries\n",
|
||||||
"loaded allowlist with %zu file and %zu function entries\n",
|
|
||||||
allowListFiles.size(), allowListFunctions.size());
|
allowListFiles.size(), allowListFunctions.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -702,8 +701,7 @@ struct afl_pass : gimple_opt_pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF("loaded denylist with %zu file and %zu function entries\n",
|
||||||
"loaded denylist with %zu file and %zu function entries\n",
|
|
||||||
denyListFiles.size(), denyListFunctions.size());
|
denyListFiles.size(), denyListFunctions.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -745,9 +743,9 @@ struct afl_pass : gimple_opt_pass {
|
|||||||
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the deny function list, "
|
"Function %s is in the deny function list, not "
|
||||||
"not instrumenting ... \n",
|
"instrumenting ... \n",
|
||||||
instFunction.c_str());
|
instFunction.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -825,9 +823,9 @@ struct afl_pass : gimple_opt_pass {
|
|||||||
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the allow function list, "
|
"Function %s is in the allow function list, instrumenting "
|
||||||
"instrumenting ... \n",
|
"... \n",
|
||||||
instFunction.c_str());
|
instFunction.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -859,9 +857,9 @@ struct afl_pass : gimple_opt_pass {
|
|||||||
if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the allowlist (%s), "
|
"Function %s is in the allowlist (%s), instrumenting ... "
|
||||||
"instrumenting ... \n",
|
"\n",
|
||||||
IDENTIFIER_POINTER(DECL_NAME(F->decl)),
|
IDENTIFIER_POINTER(DECL_NAME(F->decl)),
|
||||||
source_file.c_str());
|
source_file.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
@ -173,8 +173,7 @@ void initInstrumentList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF("loaded allowlist with %zu file and %zu function entries\n",
|
||||||
"loaded allowlist with %zu file and %zu function entries\n",
|
|
||||||
allowListFiles.size(), allowListFunctions.size());
|
allowListFiles.size(), allowListFunctions.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -248,8 +247,7 @@ void initInstrumentList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF("loaded denylist with %zu file and %zu function entries\n",
|
||||||
"loaded denylist with %zu file and %zu function entries\n",
|
|
||||||
denyListFiles.size(), denyListFunctions.size());
|
denyListFiles.size(), denyListFunctions.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -409,9 +407,9 @@ bool isInInstrumentList(llvm::Function *F) {
|
|||||||
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the deny function list, "
|
"Function %s is in the deny function list, not instrumenting "
|
||||||
"not instrumenting ... \n",
|
"... \n",
|
||||||
instFunction.c_str());
|
instFunction.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -489,9 +487,9 @@ bool isInInstrumentList(llvm::Function *F) {
|
|||||||
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the allow function list, "
|
"Function %s is in the allow function list, instrumenting "
|
||||||
"instrumenting ... \n",
|
"... \n",
|
||||||
instFunction.c_str());
|
instFunction.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -523,9 +521,9 @@ bool isInInstrumentList(llvm::Function *F) {
|
|||||||
if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
|
if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"Function %s is in the allowlist (%s), "
|
"Function %s is in the allowlist (%s), instrumenting ... "
|
||||||
"instrumenting ... \n",
|
"\n",
|
||||||
F->getName().str().c_str(), source_file.c_str());
|
F->getName().str().c_str(), source_file.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -105,14 +105,13 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
|
|||||||
if (isInInstrumentList(&F)) {
|
if (isInInstrumentList(&F)) {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST "function %s is in the instrument file list\n",
|
DEBUGF("function %s is in the instrument file list\n",
|
||||||
F.getName().str().c_str());
|
F.getName().str().c_str());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF("function %s is NOT in the instrument file list\n",
|
||||||
"function %s is NOT in the instrument file list\n",
|
|
||||||
F.getName().str().c_str());
|
F.getName().str().c_str());
|
||||||
|
|
||||||
auto & Ctx = F.getContext();
|
auto & Ctx = F.getContext();
|
||||||
|
@ -601,11 +601,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
|||||||
if (op_size != op1->getType()->getPrimitiveSizeInBits()) { continue; }
|
if (op_size != op1->getType()->getPrimitiveSizeInBits()) { continue; }
|
||||||
|
|
||||||
const unsigned int sizeInBits = op0->getType()->getPrimitiveSizeInBits();
|
const unsigned int sizeInBits = op0->getType()->getPrimitiveSizeInBits();
|
||||||
const unsigned int precision =
|
const unsigned int precision = sizeInBits == 32 ? 24
|
||||||
sizeInBits == 32
|
: sizeInBits == 64 ? 53
|
||||||
? 24
|
|
||||||
: sizeInBits == 64
|
|
||||||
? 53
|
|
||||||
: sizeInBits == 128 ? 113
|
: sizeInBits == 128 ? 113
|
||||||
: sizeInBits == 16 ? 11
|
: sizeInBits == 16 ? 11
|
||||||
/* sizeInBits == 80 */
|
/* sizeInBits == 80 */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# libdislocator, an abusive allocator
|
# libdislocator, an abusive allocator
|
||||||
|
|
||||||
(See ../docs/README.md for the general instruction manual.)
|
(See ../README.md for the general instruction manual.)
|
||||||
|
|
||||||
This is a companion library that can be used as a drop-in replacement for the
|
This is a companion library that can be used as a drop-in replacement for the
|
||||||
libc allocator in the fuzzed binaries. It improves the odds of bumping into
|
libc allocator in the fuzzed binaries. It improves the odds of bumping into
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# strcmp() / memcmp() token capture library
|
# strcmp() / memcmp() token capture library
|
||||||
|
|
||||||
(See ../docs/README.md for the general instruction manual.)
|
(See ../README.md for the general instruction manual.)
|
||||||
|
|
||||||
This companion library allows you to instrument `strcmp()`, `memcmp()`,
|
This companion library allows you to instrument `strcmp()`, `memcmp()`,
|
||||||
and related functions to automatically extract syntax tokens passed to any of
|
and related functions to automatically extract syntax tokens passed to any of
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# High-performance binary-only instrumentation for afl-fuzz
|
# High-performance binary-only instrumentation for afl-fuzz
|
||||||
|
|
||||||
(See ../docs/README.md for the general instruction manual.)
|
(See ../README.md for the general instruction manual.)
|
||||||
|
|
||||||
## 1) Introduction
|
## 1) Introduction
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ match.
|
|||||||
## 12) Gotchas, feedback, bugs
|
## 12) Gotchas, feedback, bugs
|
||||||
|
|
||||||
If you need to fix up checksums or do other cleanup on mutated test cases, see
|
If you need to fix up checksums or do other cleanup on mutated test cases, see
|
||||||
examples/custom_mutators/ for a viable solution.
|
utils/custom_mutators/ for a viable solution.
|
||||||
|
|
||||||
Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate
|
Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate
|
||||||
the "shadow VM" trick employed by the sanitizers and will probably just
|
the "shadow VM" trick employed by the sanitizers and will probably just
|
||||||
|
@ -172,4 +172,4 @@ and so the input_buf variables of the hook becomes meaningful. Otherwise,
|
|||||||
you have to read the input from a file like stdin.
|
you have to read the input from a file like stdin.
|
||||||
|
|
||||||
An example that you can use with little modification for your target can
|
An example that you can use with little modification for your target can
|
||||||
be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook)
|
be found here: [utils/qemu_persistent_hook](../utils/qemu_persistent_hook)
|
||||||
|
@ -114,7 +114,7 @@ git status 1>/dev/null 2>/dev/null
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "[*] initializing qemuafl submodule"
|
echo "[*] initializing qemuafl submodule"
|
||||||
git submodule init || exit 1
|
git submodule init || exit 1
|
||||||
git submodule update 2>/dev/null # ignore errors
|
git submodule update ./qemuafl 2>/dev/null # ignore errors
|
||||||
else
|
else
|
||||||
echo "[*] cloning qemuafl"
|
echo "[*] cloning qemuafl"
|
||||||
test -d qemuafl || {
|
test -d qemuafl || {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit d66c9e2654efa8939f0fe6995d11a72b98a4da3e
|
Subproject commit 21ff34383764a8c6f66509b3b8d5282468c721e1
|
@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
|||||||
|
|
||||||
static s32 dev_null_fd = -1; /* FD to /dev/null */
|
static s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||||
|
|
||||||
static u8 edges_only, /* Ignore hit counts? */
|
static bool edges_only, /* Ignore hit counts? */
|
||||||
use_hex_offsets, /* Show hex offsets? */
|
use_hex_offsets, /* Show hex offsets? */
|
||||||
use_stdin = 1; /* Use stdin for program input? */
|
use_stdin = true; /* Use stdin for program input? */
|
||||||
|
|
||||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||||
child_timed_out; /* Child timed out? */
|
child_timed_out; /* Child timed out? */
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
utility has right now is to be able to skip them gracefully and allow the
|
utility has right now is to be able to skip them gracefully and allow the
|
||||||
compilation process to continue.
|
compilation process to continue.
|
||||||
|
|
||||||
That said, see examples/clang_asm_normalize/ for a solution that may
|
That said, see utils/clang_asm_normalize/ for a solution that may
|
||||||
allow clang users to make things work even with hand-crafted assembly. Just
|
allow clang users to make things work even with hand-crafted assembly. Just
|
||||||
note that there is no equivalent for GCC.
|
note that there is no equivalent for GCC.
|
||||||
|
|
||||||
|
381
src/afl-cc.c
381
src/afl-cc.c
@ -48,10 +48,11 @@
|
|||||||
static u8 * obj_path; /* Path to runtime libraries */
|
static u8 * obj_path; /* Path to runtime libraries */
|
||||||
static u8 **cc_params; /* Parameters passed to the real CC */
|
static u8 **cc_params; /* Parameters passed to the real CC */
|
||||||
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
|
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
|
||||||
|
static u8 clang_mode; /* Invoked as afl-clang*? */
|
||||||
static u8 llvm_fullpath[PATH_MAX];
|
static u8 llvm_fullpath[PATH_MAX];
|
||||||
static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode,
|
static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
|
||||||
compiler_mode, plusplus_mode;
|
static u8 compiler_mode, plusplus_mode, have_instr_env = 0;
|
||||||
static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto;
|
static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
|
||||||
static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
|
static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
|
||||||
static u8 debug;
|
static u8 debug;
|
||||||
static u8 cwd[4096];
|
static u8 cwd[4096];
|
||||||
@ -105,20 +106,43 @@ u8 *getthecwd() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to find the runtime libraries. If that fails, abort. */
|
/* Try to find a specific runtime we need, returns NULL on fail. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
in find_object() we look here:
|
||||||
|
|
||||||
|
1. if obj_path is already set we look there first
|
||||||
|
2. then we check the $AFL_PATH environment variable location if set
|
||||||
|
3. next we check argv[0] if it has path information and use it
|
||||||
|
a) we also check ../lib/afl
|
||||||
|
4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
|
||||||
|
FreeBSD with procfs)
|
||||||
|
a) and check here in ../lib/afl too
|
||||||
|
5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
|
||||||
|
6. we finally try the current directory
|
||||||
|
|
||||||
|
if all these attempts fail - we return NULL and the caller has to decide
|
||||||
|
what to do.
|
||||||
|
*/
|
||||||
|
|
||||||
static u8 *find_object(u8 *obj, u8 *argv0) {
|
static u8 *find_object(u8 *obj, u8 *argv0) {
|
||||||
|
|
||||||
u8 *afl_path = getenv("AFL_PATH");
|
u8 *afl_path = getenv("AFL_PATH");
|
||||||
u8 *slash = NULL, *tmp;
|
u8 *slash = NULL, *tmp;
|
||||||
|
|
||||||
|
if (obj_path) {
|
||||||
|
|
||||||
|
tmp = alloc_printf("%s/%s", obj_path, obj);
|
||||||
|
|
||||||
|
if (!access(tmp, R_OK)) { return tmp; }
|
||||||
|
|
||||||
|
ck_free(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl_path) {
|
if (afl_path) {
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
tmp = alloc_printf("%s/%s", afl_path, obj);
|
tmp = alloc_printf("%s/%s", afl_path, obj);
|
||||||
#else
|
|
||||||
tmp = alloc_printf("%s/%s", afl_path, obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
@ -131,101 +155,35 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv0) slash = strrchr(argv0, '/');
|
if (argv0) {
|
||||||
|
|
||||||
if (slash) {
|
|
||||||
|
|
||||||
u8 *dir;
|
|
||||||
|
|
||||||
*slash = 0;
|
|
||||||
dir = ck_strdup(argv0);
|
|
||||||
*slash = '/';
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
tmp = alloc_printf("%s/%s", dir, obj);
|
|
||||||
#else
|
|
||||||
tmp = alloc_printf("%s/%s", dir, obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
obj_path = dir;
|
|
||||||
return tmp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
ck_free(dir);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = alloc_printf("%s/%s", AFL_PATH, obj);
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
#else
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
obj_path = AFL_PATH;
|
|
||||||
return tmp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to find the runtime libraries. If that fails, abort. */
|
|
||||||
|
|
||||||
static void find_obj(u8 *argv0) {
|
|
||||||
|
|
||||||
u8 *afl_path = getenv("AFL_PATH");
|
|
||||||
u8 *slash, *tmp;
|
|
||||||
|
|
||||||
if (afl_path) {
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
tmp = alloc_printf("%s/afl-compiler-rt.so", afl_path);
|
|
||||||
#else
|
|
||||||
tmp = alloc_printf("%s/afl-compiler-rt.o", afl_path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
|
||||||
|
|
||||||
obj_path = afl_path;
|
|
||||||
ck_free(tmp);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ck_free(tmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
slash = strrchr(argv0, '/');
|
slash = strrchr(argv0, '/');
|
||||||
|
|
||||||
if (slash) {
|
if (slash) {
|
||||||
|
|
||||||
u8 *dir;
|
u8 *dir = ck_strdup(argv0);
|
||||||
|
|
||||||
|
slash = strrchr(dir, '/');
|
||||||
*slash = 0;
|
*slash = 0;
|
||||||
dir = ck_strdup(argv0);
|
|
||||||
*slash = '/';
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
tmp = alloc_printf("%s/%s", dir, obj);
|
||||||
tmp = alloc_printf("%s/afl-compiler-rt.so", dir);
|
|
||||||
#else
|
|
||||||
tmp = alloc_printf("%s/afl-compiler-rt.o", dir);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) {
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
obj_path = dir;
|
obj_path = dir;
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ck_free(tmp);
|
ck_free(tmp);
|
||||||
return;
|
tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
|
||||||
|
|
||||||
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
|
u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
|
||||||
|
obj_path = dir2;
|
||||||
|
ck_free(dir);
|
||||||
|
return tmp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,22 +192,90 @@ static void find_obj(u8 *argv0) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
|
||||||
if (!access(AFL_PATH "/afl-compiler-rt.so", R_OK)) {
|
defined(__ANDROID__) || defined(__NetBSD__)
|
||||||
|
#define HAS_PROC_FS 1
|
||||||
#else
|
|
||||||
if (!access(AFL_PATH "/afl-compiler-rt.o", R_OK)) {
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_PROC_FS
|
||||||
|
else {
|
||||||
|
|
||||||
obj_path = AFL_PATH;
|
char *procname = NULL;
|
||||||
return;
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
procname = "/proc/curproc/file";
|
||||||
|
#elif defined(__linux__) || defined(__ANDROID__)
|
||||||
|
procname = "/proc/self/exe";
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
procname = "/proc/curproc/exe";
|
||||||
|
#endif
|
||||||
|
if (procname) {
|
||||||
|
|
||||||
|
char exepath[PATH_MAX];
|
||||||
|
ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
|
||||||
|
if (exepath_len > 0 && exepath_len < PATH_MAX) {
|
||||||
|
|
||||||
|
exepath[exepath_len] = 0;
|
||||||
|
slash = strrchr(exepath, '/');
|
||||||
|
|
||||||
|
if (slash) {
|
||||||
|
|
||||||
|
*slash = 0;
|
||||||
|
tmp = alloc_printf("%s/%s", exepath, obj);
|
||||||
|
|
||||||
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
|
u8 *dir = alloc_printf("%s", exepath);
|
||||||
|
obj_path = dir;
|
||||||
|
return tmp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FATAL(
|
ck_free(tmp);
|
||||||
"Unable to find 'afl-compiler-rt.o' or 'afl-llvm-pass.so'. Please set "
|
tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
|
||||||
"AFL_PATH");
|
|
||||||
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
|
u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
|
||||||
|
obj_path = dir;
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#undef HAS_PROC_FS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = alloc_printf("%s/%s", AFL_PATH, obj);
|
||||||
|
|
||||||
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
|
obj_path = AFL_PATH;
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_free(tmp);
|
||||||
|
|
||||||
|
tmp = alloc_printf("./%s", obj);
|
||||||
|
|
||||||
|
if (!access(tmp, R_OK)) {
|
||||||
|
|
||||||
|
obj_path = ".";
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_free(tmp);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,8 +314,16 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
if (compiler_mode >= GCC_PLUGIN) {
|
if (compiler_mode >= GCC_PLUGIN) {
|
||||||
|
|
||||||
|
if (compiler_mode == GCC) {
|
||||||
|
|
||||||
|
alt_cxx = clang_mode ? "clang++" : "g++";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
alt_cxx = "g++";
|
alt_cxx = "g++";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (USE_BINDIR)
|
if (USE_BINDIR)
|
||||||
@ -313,8 +347,16 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
if (compiler_mode >= GCC_PLUGIN) {
|
if (compiler_mode >= GCC_PLUGIN) {
|
||||||
|
|
||||||
|
if (compiler_mode == GCC) {
|
||||||
|
|
||||||
|
alt_cc = clang_mode ? "clang" : "gcc";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
alt_cc = "gcc";
|
alt_cc = "gcc";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (USE_BINDIR)
|
if (USE_BINDIR)
|
||||||
@ -337,12 +379,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
cc_params[cc_par_cnt++] = "-B";
|
cc_params[cc_par_cnt++] = "-B";
|
||||||
cc_params[cc_par_cnt++] = obj_path;
|
cc_params[cc_par_cnt++] = obj_path;
|
||||||
|
|
||||||
|
if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compiler_mode == GCC_PLUGIN) {
|
if (compiler_mode == GCC_PLUGIN) {
|
||||||
|
|
||||||
char *fplugin_arg =
|
char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
|
||||||
alloc_printf("-fplugin=%s", find_object("afl-gcc-pass.so", argvnull));
|
|
||||||
cc_params[cc_par_cnt++] = fplugin_arg;
|
cc_params[cc_par_cnt++] = fplugin_arg;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -354,11 +397,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
if (lto_mode && plusplus_mode)
|
if (lto_mode && plusplus_mode)
|
||||||
cc_params[cc_par_cnt++] = "-lc++"; // needed by fuzzbench, early
|
cc_params[cc_par_cnt++] = "-lc++"; // needed by fuzzbench, early
|
||||||
|
|
||||||
if (lto_mode) {
|
if (lto_mode && have_instr_env) {
|
||||||
|
|
||||||
if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
|
|
||||||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
|
|
||||||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
|
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = "-Xclang";
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
cc_params[cc_par_cnt++] = "-load";
|
||||||
@ -368,8 +407,6 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("AFL_LLVM_DICT2FILE")) {
|
if (getenv("AFL_LLVM_DICT2FILE")) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = "-Xclang";
|
||||||
@ -508,11 +545,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
if (instrument_mode == INSTRUMENT_PCGUARD) {
|
if (instrument_mode == INSTRUMENT_PCGUARD) {
|
||||||
|
|
||||||
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
|
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
|
||||||
|
if (have_instr_list) {
|
||||||
|
|
||||||
|
if (!be_quiet)
|
||||||
|
SAYF(
|
||||||
|
"Using unoptimized trace-pc-guard, due usage of "
|
||||||
|
"-fsanitize-coverage-allow/denylist, you can use "
|
||||||
|
"AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
|
||||||
|
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = "-Xclang";
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
cc_params[cc_par_cnt++] = "-load";
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = "-Xclang";
|
||||||
cc_params[cc_par_cnt++] =
|
cc_params[cc_par_cnt++] =
|
||||||
alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
|
alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#if LLVM_MAJOR >= 4
|
#if LLVM_MAJOR >= 4
|
||||||
if (!be_quiet)
|
if (!be_quiet)
|
||||||
@ -590,6 +641,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
|
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
|
||||||
if (!strcmp(cur, "-m64")) bit_mode = 64;
|
if (!strcmp(cur, "-m64")) bit_mode = 64;
|
||||||
|
|
||||||
|
if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
|
||||||
|
have_instr_list = 1;
|
||||||
|
|
||||||
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
|
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
|
||||||
asan_set = 1;
|
asan_set = 1;
|
||||||
|
|
||||||
@ -675,7 +729,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
|
if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
|
||||||
getenv("LAF_TRANSFORM_COMPARES") || lto_mode) {
|
getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
|
||||||
|
lto_mode) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
|
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
|
||||||
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
|
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
|
||||||
@ -826,7 +881,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#if !defined(__APPLE__) && !defined(__sun)
|
||||||
if (!shared_linking)
|
if (!shared_linking)
|
||||||
cc_params[cc_par_cnt++] =
|
cc_params[cc_par_cnt++] =
|
||||||
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
|
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
|
||||||
@ -856,6 +911,14 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
|
|
||||||
|
if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
|
||||||
|
getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
|
||||||
|
getenv("AFL_LLVM_BLOCKLIST")) {
|
||||||
|
|
||||||
|
have_instr_env = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
|
if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
|
||||||
argvnull = (u8 *)argv[0];
|
argvnull = (u8 *)argv[0];
|
||||||
check_environment_vars(envp);
|
check_environment_vars(envp);
|
||||||
@ -915,7 +978,9 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
} else if (strncmp(callname, "afl-gcc", 7) == 0 ||
|
} else if (strncmp(callname, "afl-gcc", 7) == 0 ||
|
||||||
|
|
||||||
strncmp(callname, "afl-g++", 7) == 0) {
|
strncmp(callname, "afl-g++", 7) == 0 ||
|
||||||
|
|
||||||
|
strncmp(callname, "afl-clang", 9) == 0) {
|
||||||
|
|
||||||
compiler_mode = GCC;
|
compiler_mode = GCC;
|
||||||
|
|
||||||
@ -959,6 +1024,14 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strncmp(callname, "afl-clang", 9) == 0) {
|
||||||
|
|
||||||
|
clang_mode = 1;
|
||||||
|
|
||||||
|
if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
||||||
if (strncmp(argv[i], "--afl", 5) == 0) {
|
if (strncmp(argv[i], "--afl", 5) == 0) {
|
||||||
@ -1015,22 +1088,21 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
|
if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) {
|
||||||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
|
|
||||||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
|
|
||||||
getenv("AFL_DONT_OPTIMIZE"))
|
|
||||||
WARNF(
|
WARNF(
|
||||||
"AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
|
"AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
|
||||||
"for file matching, only function matching!");
|
"for file matching, only function matching!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
|
if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
|
||||||
getenv("INSTRIM_LIB")) {
|
getenv("INSTRIM_LIB")) {
|
||||||
|
|
||||||
if (instrument_mode == 0)
|
if (instrument_mode == 0)
|
||||||
instrument_mode = INSTRUMENT_CFG;
|
instrument_mode = INSTRUMENT_CFG;
|
||||||
else if (instrument_mode != INSTRUMENT_CFG)
|
else if (instrument_mode != INSTRUMENT_CFG)
|
||||||
FATAL(
|
FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
|
||||||
"you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1307,15 +1379,20 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
|
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
|
||||||
"filename\n");
|
"filename\n");
|
||||||
|
|
||||||
|
#if LLVM_MAJOR < 9
|
||||||
|
#define COUNTER_BEHAVIOUR \
|
||||||
|
" AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
|
||||||
|
#else
|
||||||
|
#define COUNTER_BEHAVIOUR \
|
||||||
|
" AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
|
||||||
|
#endif
|
||||||
if (have_llvm)
|
if (have_llvm)
|
||||||
SAYF(
|
SAYF(
|
||||||
"\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
|
"\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
|
||||||
"variables:\n"
|
"variables:\n"
|
||||||
#if LLVM_MAJOR < 9
|
|
||||||
" AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
|
COUNTER_BEHAVIOUR
|
||||||
#else
|
|
||||||
" AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
|
|
||||||
#endif
|
|
||||||
" AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
|
" AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
|
||||||
"comparisons\n"
|
"comparisons\n"
|
||||||
" AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
|
" AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
|
||||||
@ -1426,22 +1503,20 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
#if LLVM_MAJOR <= 6
|
#if LLVM_MAJOR <= 6
|
||||||
instrument_mode = INSTRUMENT_AFL;
|
instrument_mode = INSTRUMENT_AFL;
|
||||||
#else
|
#else
|
||||||
if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
|
#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
|
||||||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
|
if (have_instr_env) {
|
||||||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
|
|
||||||
|
|
||||||
instrument_mode = INSTRUMENT_AFL;
|
instrument_mode = INSTRUMENT_AFL;
|
||||||
|
if (!be_quiet)
|
||||||
WARNF(
|
WARNF(
|
||||||
"switching to classic instrumentation because "
|
"Switching to classic instrumentation because "
|
||||||
"AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
|
"AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
|
||||||
"-fsanitize-coverage-allowlist=allowlist.txt or "
|
|
||||||
"-fsanitize-coverage-blocklist=denylist.txt if you want to use "
|
|
||||||
"PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
|
|
||||||
"SanitizerCoverage.html#partially-disabling-instrumentation");
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
|
||||||
|
#endif
|
||||||
instrument_mode = INSTRUMENT_PCGUARD;
|
instrument_mode = INSTRUMENT_PCGUARD;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1487,18 +1562,16 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
"AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
|
"AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
|
||||||
"together");
|
"together");
|
||||||
|
|
||||||
if (instrument_mode == INSTRUMENT_PCGUARD &&
|
#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
|
||||||
(getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
|
if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
|
||||||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
|
|
||||||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
|
|
||||||
FATAL(
|
FATAL(
|
||||||
"Instrumentation type PCGUARD does not support "
|
"Instrumentation type PCGUARD does not support "
|
||||||
"AFL_LLVM_ALLOWLIST/DENYLIST! Use "
|
"AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
|
||||||
"-fsanitize-coverage-allowlist=allowlist.txt or "
|
|
||||||
"-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
|
}
|
||||||
"12+), see "
|
|
||||||
"https://clang.llvm.org/docs/"
|
#endif
|
||||||
"SanitizerCoverage.html#partially-disabling-instrumentation");
|
|
||||||
|
|
||||||
u8 *ptr2;
|
u8 *ptr2;
|
||||||
|
|
||||||
@ -1525,7 +1598,7 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|
||||||
SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
|
DEBUGF("cd '%s';", getthecwd());
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
SAYF(" '%s'", argv[i]);
|
SAYF(" '%s'", argv[i]);
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
@ -1545,15 +1618,29 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
if (!be_quiet && cmplog_mode)
|
if (!be_quiet && cmplog_mode)
|
||||||
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
|
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
find_obj(argv[0]);
|
ptr = find_object("afl-compiler-rt.so", argv[0]);
|
||||||
|
#else
|
||||||
|
ptr = find_object("afl-compiler-rt.o", argv[0]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!ptr) {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
|
||||||
|
"environment variable.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
|
||||||
|
|
||||||
|
ck_free(ptr);
|
||||||
|
|
||||||
edit_params(argc, argv, envp);
|
edit_params(argc, argv, envp);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|
||||||
SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
|
DEBUGF("cd '%s';", getthecwd());
|
||||||
for (i = 0; i < (s32)cc_par_cnt; i++)
|
for (i = 0; i < (s32)cc_par_cnt; i++)
|
||||||
SAYF(" '%s'", cc_params[i]);
|
SAYF(" '%s'", cc_params[i]);
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
|
@ -46,7 +46,7 @@ u8 be_quiet = 0;
|
|||||||
u8 *doc_path = "";
|
u8 *doc_path = "";
|
||||||
u8 last_intr = 0;
|
u8 last_intr = 0;
|
||||||
|
|
||||||
void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
|
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
|
||||||
|
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
u8 cwd[PATH_MAX];
|
u8 cwd[PATH_MAX];
|
||||||
@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
|
|||||||
|
|
||||||
if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
|
if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
|
||||||
|
|
||||||
*use_stdin = 0;
|
*use_stdin = false;
|
||||||
|
|
||||||
if (prog_in[0] != 0) { // not afl-showmap special case
|
if (prog_in[0] != 0) { // not afl-showmap special case
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
|
|
||||||
execv(fsrv->target_path, argv);
|
execv(fsrv->target_path, argv);
|
||||||
|
|
||||||
|
WARNF("Execv failed in forkserver.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initializes the struct */
|
/* Initializes the struct */
|
||||||
@ -76,8 +77,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
|||||||
fsrv->dev_urandom_fd = -1;
|
fsrv->dev_urandom_fd = -1;
|
||||||
|
|
||||||
/* Settings */
|
/* Settings */
|
||||||
fsrv->use_stdin = 1;
|
fsrv->use_stdin = true;
|
||||||
fsrv->no_unlink = 0;
|
fsrv->no_unlink = false;
|
||||||
fsrv->exec_tmout = EXEC_TIMEOUT;
|
fsrv->exec_tmout = EXEC_TIMEOUT;
|
||||||
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
|
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
|
||||||
fsrv->mem_limit = MEM_LIMIT;
|
fsrv->mem_limit = MEM_LIMIT;
|
||||||
@ -86,8 +87,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
|||||||
/* exec related stuff */
|
/* exec related stuff */
|
||||||
fsrv->child_pid = -1;
|
fsrv->child_pid = -1;
|
||||||
fsrv->map_size = get_map_size();
|
fsrv->map_size = get_map_size();
|
||||||
fsrv->use_fauxsrv = 0;
|
fsrv->use_fauxsrv = false;
|
||||||
fsrv->last_run_timed_out = 0;
|
fsrv->last_run_timed_out = false;
|
||||||
|
|
||||||
|
fsrv->uses_crash_exitcode = false;
|
||||||
|
fsrv->uses_asan = false;
|
||||||
|
|
||||||
fsrv->init_child_func = fsrv_exec_child;
|
fsrv->init_child_func = fsrv_exec_child;
|
||||||
|
|
||||||
@ -109,6 +113,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
|
|||||||
fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
|
fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
|
||||||
fsrv_to->out_fd = from->out_fd; // not sure this is a good idea
|
fsrv_to->out_fd = from->out_fd; // not sure this is a good idea
|
||||||
fsrv_to->no_unlink = from->no_unlink;
|
fsrv_to->no_unlink = from->no_unlink;
|
||||||
|
fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
|
||||||
|
fsrv_to->crash_exitcode = from->crash_exitcode;
|
||||||
|
|
||||||
// These are forkserver specific.
|
// These are forkserver specific.
|
||||||
fsrv_to->out_dir_fd = -1;
|
fsrv_to->out_dir_fd = -1;
|
||||||
@ -116,7 +122,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
|
|||||||
fsrv_to->use_fauxsrv = 0;
|
fsrv_to->use_fauxsrv = 0;
|
||||||
fsrv_to->last_run_timed_out = 0;
|
fsrv_to->last_run_timed_out = 0;
|
||||||
|
|
||||||
fsrv_to->init_child_func = fsrv_exec_child;
|
fsrv_to->init_child_func = from->init_child_func;
|
||||||
// Note: do not copy ->add_extra_func
|
// Note: do not copy ->add_extra_func
|
||||||
|
|
||||||
list_append(&fsrv_list, fsrv_to);
|
list_append(&fsrv_list, fsrv_to);
|
||||||
@ -272,7 +278,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
|
|
||||||
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
|
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
|
||||||
|
|
||||||
PFATAL("Execv failed in fauxserver.");
|
WARNF("Execv failed in fauxserver.");
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +293,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
if (waitpid(child_pid, &status, 0) < 0) {
|
if (waitpid(child_pid, &status, 0) < 0) {
|
||||||
|
|
||||||
// Zombie Child could not be collected. Scary!
|
// Zombie Child could not be collected. Scary!
|
||||||
PFATAL("Fauxserver could not determin child's exit code. ");
|
WARNF("Fauxserver could not determine child's exit code. ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Relay wait status to AFL pipe, then loop back. */
|
/* Relay wait status to AFL pipe, then loop back. */
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
|
if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(1); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +337,7 @@ static void report_error_and_exit(int error) {
|
|||||||
"memory failed.");
|
"memory failed.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FATAL("unknown error code %u from fuzzing target!", error);
|
FATAL("unknown error code %d from fuzzing target!", error);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,12 +357,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
int st_pipe[2], ctl_pipe[2];
|
int st_pipe[2], ctl_pipe[2];
|
||||||
s32 status;
|
s32 status;
|
||||||
s32 rlen;
|
s32 rlen;
|
||||||
|
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
|
||||||
|
|
||||||
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
|
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
|
||||||
|
|
||||||
if (fsrv->use_fauxsrv) {
|
if (fsrv->use_fauxsrv) {
|
||||||
|
|
||||||
/* TODO: Come up with sone nice way to initialize this all */
|
/* TODO: Come up with some nice way to initialize this all */
|
||||||
|
|
||||||
if (fsrv->init_child_func != fsrv_exec_child) {
|
if (fsrv->init_child_func != fsrv_exec_child) {
|
||||||
|
|
||||||
@ -519,8 +527,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
falling through. */
|
falling through. */
|
||||||
|
|
||||||
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
|
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
|
||||||
fprintf(stderr, "Error: execv to target failed\n");
|
FATAL("Error: execv to target failed\n");
|
||||||
exit(0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +613,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
fsrv->use_shmem_fuzz = 1;
|
fsrv->use_shmem_fuzz = 1;
|
||||||
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == 0) {
|
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
|
||||||
|
|
||||||
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
||||||
@ -659,6 +666,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
||||||
|
|
||||||
|
if (ignore_autodict) {
|
||||||
|
|
||||||
|
if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
||||||
|
|
||||||
// this is not afl-fuzz - or it is cmplog - we deny and return
|
// this is not afl-fuzz - or it is cmplog - we deny and return
|
||||||
@ -758,6 +771,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -901,7 +916,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
" estimate the required amount of virtual memory for the "
|
" estimate the required amount of virtual memory for the "
|
||||||
"binary.\n\n"
|
"binary.\n\n"
|
||||||
|
|
||||||
" - the target was compiled with afl-clang-lto and a constructor "
|
" - The target was compiled with afl-clang-lto and a constructor "
|
||||||
"was\n"
|
"was\n"
|
||||||
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
|
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
|
||||||
"your \n"
|
"your \n"
|
||||||
@ -1054,6 +1069,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
if (fsrv->child_pid <= 0) {
|
if (fsrv->child_pid <= 0) {
|
||||||
|
|
||||||
if (*stop_soon_p) { return 0; }
|
if (*stop_soon_p) { return 0; }
|
||||||
|
|
||||||
|
if ((fsrv->child_pid & FS_OPT_ERROR) &&
|
||||||
|
FS_OPT_GET_ERROR(fsrv->child_pid) == FS_ERROR_SHM_OPEN)
|
||||||
|
FATAL(
|
||||||
|
"Target reported shared memory access failed (perhaps increase "
|
||||||
|
"shared memory available).");
|
||||||
|
|
||||||
FATAL("Fork server is misbehaving (OOM?)");
|
FATAL("Fork server is misbehaving (OOM?)");
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1126,10 +1148,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
|
/* MSAN in uses_asan mode uses a special exit code as it doesn't support
|
||||||
must use a special exit code. */
|
abort_on_error.
|
||||||
|
On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */
|
||||||
|
|
||||||
if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) {
|
if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
|
||||||
|
(fsrv->uses_crash_exitcode &&
|
||||||
|
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) {
|
||||||
|
|
||||||
fsrv->last_kill_signal = 0;
|
fsrv->last_kill_signal = 0;
|
||||||
return FSRV_RUN_CRASH;
|
return FSRV_RUN_CRASH;
|
||||||
@ -1137,7 +1162,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fauxserver should handle this now.
|
// Fauxserver should handle this now.
|
||||||
// if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
|
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
|
||||||
|
|
||||||
return FSRV_RUN_OK;
|
return FSRV_RUN_OK;
|
||||||
|
|
||||||
|
@ -425,8 +425,10 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
|
|||||||
/* Construct a file name for a new test case, capturing the operation
|
/* Construct a file name for a new test case, capturing the operation
|
||||||
that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
|
that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
|
||||||
|
|
||||||
u8 *describe_op(afl_state_t *afl, u8 hnb) {
|
u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
|
||||||
|
|
||||||
|
size_t real_max_len =
|
||||||
|
MIN(max_description_len, sizeof(afl->describe_op_buf_256));
|
||||||
u8 *ret = afl->describe_op_buf_256;
|
u8 *ret = afl->describe_op_buf_256;
|
||||||
|
|
||||||
if (unlikely(afl->syncing_party)) {
|
if (unlikely(afl->syncing_party)) {
|
||||||
@ -445,6 +447,38 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
|
|||||||
|
|
||||||
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
|
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
|
||||||
|
|
||||||
|
if (afl->current_custom_fuzz &&
|
||||||
|
afl->current_custom_fuzz->afl_custom_describe) {
|
||||||
|
|
||||||
|
/* We are currently in a custom mutator that supports afl_custom_describe,
|
||||||
|
* use it! */
|
||||||
|
|
||||||
|
size_t len_current = strlen(ret);
|
||||||
|
ret[len_current++] = ',';
|
||||||
|
ret[len_current] = '\0';
|
||||||
|
|
||||||
|
ssize_t size_left = real_max_len - len_current - strlen(",+cov") - 2;
|
||||||
|
if (unlikely(size_left <= 0)) FATAL("filename got too long");
|
||||||
|
|
||||||
|
const char *custom_description =
|
||||||
|
afl->current_custom_fuzz->afl_custom_describe(
|
||||||
|
afl->current_custom_fuzz->data, size_left);
|
||||||
|
if (!custom_description || !custom_description[0]) {
|
||||||
|
|
||||||
|
DEBUGF("Error getting a description from afl_custom_describe");
|
||||||
|
/* Take the stage name as description fallback */
|
||||||
|
sprintf(ret + len_current, "op:%s", afl->stage_short);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* We got a proper custom description, use it */
|
||||||
|
strncat(ret + len_current, custom_description, size_left);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Normal testcase descriptions start here */
|
||||||
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
|
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
|
||||||
|
|
||||||
if (afl->stage_cur_byte >= 0) {
|
if (afl->stage_cur_byte >= 0) {
|
||||||
@ -467,7 +501,12 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hnb == 2) { strcat(ret, ",+cov"); }
|
}
|
||||||
|
|
||||||
|
if (new_bits == 2) { strcat(ret, ",+cov"); }
|
||||||
|
|
||||||
|
if (unlikely(strlen(ret) >= max_description_len))
|
||||||
|
FATAL("describe string is too long");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -540,7 +579,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
if (unlikely(len == 0)) { return 0; }
|
if (unlikely(len == 0)) { return 0; }
|
||||||
|
|
||||||
u8 *queue_fn = "";
|
u8 *queue_fn = "";
|
||||||
u8 hnb = '\0';
|
u8 new_bits = '\0';
|
||||||
s32 fd;
|
s32 fd;
|
||||||
u8 keeping = 0, res;
|
u8 keeping = 0, res;
|
||||||
u64 cksum = 0;
|
u64 cksum = 0;
|
||||||
@ -566,7 +605,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
/* Keep only if there are new bits in the map, add to queue for
|
/* Keep only if there are new bits in the map, add to queue for
|
||||||
future fuzzing, etc. */
|
future fuzzing, etc. */
|
||||||
|
|
||||||
if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
|
if (!(new_bits = has_new_bits(afl, afl->virgin_bits))) {
|
||||||
|
|
||||||
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
|
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
|
||||||
return 0;
|
return 0;
|
||||||
@ -575,8 +614,9 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
|
queue_fn = alloc_printf(
|
||||||
afl->queued_paths, describe_op(afl, hnb));
|
"%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
|
||||||
|
describe_op(afl, new_bits, NAME_MAX - strlen("id:000000,")));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -584,7 +624,10 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
|
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
|
||||||
|
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
|
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||||
|
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
|
||||||
|
ck_write(fd, mem, len, queue_fn);
|
||||||
|
close(fd);
|
||||||
add_to_queue(afl, queue_fn, len, 0);
|
add_to_queue(afl, queue_fn, len, 0);
|
||||||
|
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
@ -616,7 +659,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hnb == 2) {
|
if (new_bits == 2) {
|
||||||
|
|
||||||
afl->queue_top->has_new_cov = 1;
|
afl->queue_top->has_new_cov = 1;
|
||||||
++afl->queued_with_cov;
|
++afl->queued_with_cov;
|
||||||
@ -647,11 +690,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
||||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
|
|
||||||
ck_write(fd, mem, len, queue_fn);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (likely(afl->q_testcase_max_cache_size)) {
|
if (likely(afl->q_testcase_max_cache_size)) {
|
||||||
|
|
||||||
queue_testcase_store_mem(afl, afl->queue_top, mem);
|
queue_testcase_store_mem(afl, afl->queue_top, mem);
|
||||||
@ -744,7 +782,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
|
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
|
||||||
afl->unique_hangs, describe_op(afl, 0));
|
afl->unique_hangs,
|
||||||
|
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -789,7 +828,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
||||||
afl->unique_crashes, afl->fsrv.last_kill_signal,
|
afl->unique_crashes, afl->fsrv.last_kill_signal,
|
||||||
describe_op(afl, 0));
|
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
|
if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
|
||||||
|
|
||||||
for (i = 0; i < ncpus; i++) {
|
for (i = 0; i < (s32)ncpus; i++) {
|
||||||
|
|
||||||
k = kstat_lookup(m, "cpu_stat", i, NULL);
|
k = kstat_lookup(m, "cpu_stat", i, NULL);
|
||||||
if (kstat_read(m, k, &cs)) {
|
if (kstat_read(m, k, &cs)) {
|
||||||
@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (skip_crashes) {
|
if (skip_crashes) {
|
||||||
|
|
||||||
|
if (afl->fsrv.uses_crash_exitcode) {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"Test case results in a crash or AFL_CRASH_EXITCODE %d "
|
||||||
|
"(skipping)",
|
||||||
|
(int)(s8)afl->fsrv.crash_exitcode);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
WARNF("Test case results in a crash (skipping)");
|
WARNF("Test case results in a crash (skipping)");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
q->cal_failed = CAL_CHANCES;
|
q->cal_failed = CAL_CHANCES;
|
||||||
++cal_failures;
|
++cal_failures;
|
||||||
break;
|
break;
|
||||||
@ -954,8 +966,19 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
#undef MSG_ULIMIT_USAGE
|
#undef MSG_ULIMIT_USAGE
|
||||||
#undef MSG_FORK_ON_APPLE
|
#undef MSG_FORK_ON_APPLE
|
||||||
|
|
||||||
|
if (afl->fsrv.uses_crash_exitcode) {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
|
||||||
|
"skipping",
|
||||||
|
fn, (int)(s8)afl->fsrv.crash_exitcode);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
WARNF("Test case '%s' results in a crash, skipping", fn);
|
WARNF("Test case '%s' results in a crash, skipping", fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove from fuzzing queue but keep for splicing */
|
/* Remove from fuzzing queue but keep for splicing */
|
||||||
|
|
||||||
struct queue_entry *p = afl->queue;
|
struct queue_entry *p = afl->queue;
|
||||||
@ -2300,12 +2323,6 @@ void fix_up_sync(afl_state_t *afl) {
|
|||||||
|
|
||||||
u8 *x = afl->sync_id;
|
u8 *x = afl->sync_id;
|
||||||
|
|
||||||
if (afl->non_instrumented_mode) {
|
|
||||||
|
|
||||||
FATAL("-S / -M and -n are mutually exclusive");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*x) {
|
while (*x) {
|
||||||
|
|
||||||
if (!isalnum(*x) && *x != '_' && *x != '-') {
|
if (!isalnum(*x) && *x != '_' && *x != '-') {
|
||||||
@ -2503,7 +2520,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode) {
|
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
|
||||||
|
afl->non_instrumented_mode) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -151,7 +151,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
|
|||||||
/* Mutator */
|
/* Mutator */
|
||||||
/* "afl_custom_init", optional for backward compatibility */
|
/* "afl_custom_init", optional for backward compatibility */
|
||||||
mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
|
mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
|
||||||
if (!mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
|
if (!mutator->afl_custom_init) {
|
||||||
|
|
||||||
|
FATAL("Symbol 'afl_custom_init' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
|
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
|
||||||
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
|
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
|
||||||
@ -161,49 +165,74 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
|
|||||||
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
|
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
|
||||||
|
|
||||||
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
|
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
|
||||||
if (!mutator->afl_custom_fuzz)
|
if (!mutator->afl_custom_fuzz) {
|
||||||
|
|
||||||
WARNF("Symbol 'afl_custom_mutator' not found.");
|
WARNF("Symbol 'afl_custom_mutator' not found.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_introspection", optional */
|
/* "afl_custom_introspection", optional */
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
|
mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
|
||||||
if (!mutator->afl_custom_introspection)
|
if (!mutator->afl_custom_introspection) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_introspection' not found.");
|
ACTF("optional symbol 'afl_custom_introspection' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* "afl_custom_fuzz_count", optional */
|
/* "afl_custom_fuzz_count", optional */
|
||||||
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
|
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
|
||||||
if (!mutator->afl_custom_fuzz_count)
|
if (!mutator->afl_custom_fuzz_count) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
|
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_deinit", optional for backward compatibility */
|
/* "afl_custom_deinit", optional for backward compatibility */
|
||||||
mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
|
mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
|
||||||
if (!mutator->afl_custom_deinit)
|
if (!mutator->afl_custom_deinit) {
|
||||||
|
|
||||||
FATAL("Symbol 'afl_custom_deinit' not found.");
|
FATAL("Symbol 'afl_custom_deinit' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_post_process", optional */
|
/* "afl_custom_post_process", optional */
|
||||||
mutator->afl_custom_post_process = dlsym(dh, "afl_custom_post_process");
|
mutator->afl_custom_post_process = dlsym(dh, "afl_custom_post_process");
|
||||||
if (!mutator->afl_custom_post_process)
|
if (!mutator->afl_custom_post_process) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_post_process' not found.");
|
ACTF("optional symbol 'afl_custom_post_process' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
u8 notrim = 0;
|
u8 notrim = 0;
|
||||||
/* "afl_custom_init_trim", optional */
|
/* "afl_custom_init_trim", optional */
|
||||||
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
||||||
if (!mutator->afl_custom_init_trim)
|
if (!mutator->afl_custom_init_trim) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_init_trim' not found.");
|
ACTF("optional symbol 'afl_custom_init_trim' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_trim", optional */
|
/* "afl_custom_trim", optional */
|
||||||
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
|
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
|
||||||
if (!mutator->afl_custom_trim)
|
if (!mutator->afl_custom_trim) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_trim' not found.");
|
ACTF("optional symbol 'afl_custom_trim' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_post_trim", optional */
|
/* "afl_custom_post_trim", optional */
|
||||||
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
|
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
|
||||||
if (!mutator->afl_custom_post_trim)
|
if (!mutator->afl_custom_post_trim) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_post_trim' not found.");
|
ACTF("optional symbol 'afl_custom_post_trim' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (notrim) {
|
if (notrim) {
|
||||||
|
|
||||||
mutator->afl_custom_init_trim = NULL;
|
mutator->afl_custom_init_trim = NULL;
|
||||||
@ -217,31 +246,54 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
|
|||||||
|
|
||||||
/* "afl_custom_havoc_mutation", optional */
|
/* "afl_custom_havoc_mutation", optional */
|
||||||
mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
|
mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
|
||||||
if (!mutator->afl_custom_havoc_mutation)
|
if (!mutator->afl_custom_havoc_mutation) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
|
ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_havoc_mutation", optional */
|
/* "afl_custom_havoc_mutation", optional */
|
||||||
mutator->afl_custom_havoc_mutation_probability =
|
mutator->afl_custom_havoc_mutation_probability =
|
||||||
dlsym(dh, "afl_custom_havoc_mutation_probability");
|
dlsym(dh, "afl_custom_havoc_mutation_probability");
|
||||||
if (!mutator->afl_custom_havoc_mutation_probability)
|
if (!mutator->afl_custom_havoc_mutation_probability) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
|
ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_queue_get", optional */
|
/* "afl_custom_queue_get", optional */
|
||||||
mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
|
mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
|
||||||
if (!mutator->afl_custom_queue_get)
|
if (!mutator->afl_custom_queue_get) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_queue_get' not found.");
|
ACTF("optional symbol 'afl_custom_queue_get' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* "afl_custom_queue_new_entry", optional */
|
/* "afl_custom_queue_new_entry", optional */
|
||||||
mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
|
mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
|
||||||
if (!mutator->afl_custom_queue_new_entry)
|
if (!mutator->afl_custom_queue_new_entry) {
|
||||||
|
|
||||||
ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
|
ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "afl_custom_describe", optional */
|
||||||
|
mutator->afl_custom_describe = dlsym(dh, "afl_custom_describe");
|
||||||
|
if (!mutator->afl_custom_describe) {
|
||||||
|
|
||||||
|
ACTF("Symbol 'afl_custom_describe' not found.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
OKF("Custom mutator '%s' installed successfully.", fn);
|
OKF("Custom mutator '%s' installed successfully.", fn);
|
||||||
|
|
||||||
/* Initialize the custom mutator */
|
/* Initialize the custom mutator */
|
||||||
if (mutator->afl_custom_init)
|
if (mutator->afl_custom_init) {
|
||||||
|
|
||||||
mutator->data = mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
|
mutator->data = mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
|
mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
|
||||||
mutator->stacked_custom_prob =
|
mutator->stacked_custom_prob =
|
||||||
6; // like one of the default mutations in havoc
|
6; // like one of the default mutations in havoc
|
||||||
|
@ -445,8 +445,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (unlikely(afl->not_on_tty)) {
|
if (unlikely(afl->not_on_tty)) {
|
||||||
|
|
||||||
ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
|
ACTF(
|
||||||
afl->current_entry, afl->queued_paths, afl->unique_crashes);
|
"Fuzzing test case #%u (%u total, %llu uniq crashes found, "
|
||||||
|
"perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
|
||||||
|
afl->current_entry, afl->queued_paths, afl->unique_crashes,
|
||||||
|
afl->queue_cur->perf_score, afl->queue_cur->exec_us,
|
||||||
|
likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
|
||||||
|
afl->queue_cur->bitmap_size);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1790,11 +1795,16 @@ custom_mutator_stage:
|
|||||||
|
|
||||||
afl->current_custom_fuzz = el;
|
afl->current_custom_fuzz = el;
|
||||||
|
|
||||||
if (el->afl_custom_fuzz_count)
|
if (el->afl_custom_fuzz_count) {
|
||||||
|
|
||||||
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
|
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
|
||||||
else
|
|
||||||
|
} else {
|
||||||
|
|
||||||
afl->stage_max = saved_max;
|
afl->stage_max = saved_max;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
has_custom_fuzz = true;
|
has_custom_fuzz = true;
|
||||||
|
|
||||||
afl->stage_short = el->name_short;
|
afl->stage_short = el->name_short;
|
||||||
|
@ -96,7 +96,7 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
|
|||||||
mutated_size = PyByteArray_Size(py_value);
|
mutated_size = PyByteArray_Size(py_value);
|
||||||
|
|
||||||
*out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
|
*out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
|
||||||
if (unlikely(!out_buf)) { PFATAL("alloc"); }
|
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
|
||||||
|
|
||||||
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
|
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
|
||||||
Py_DECREF(py_value);
|
Py_DECREF(py_value);
|
||||||
@ -111,6 +111,37 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *custom_describe_py(void * py_mutator,
|
||||||
|
size_t max_description_len) {
|
||||||
|
|
||||||
|
PyObject *py_args, *py_value;
|
||||||
|
|
||||||
|
py_args = PyTuple_New(1);
|
||||||
|
|
||||||
|
PyLong_FromSize_t(max_description_len);
|
||||||
|
|
||||||
|
/* add_buf */
|
||||||
|
py_value = PyLong_FromSize_t(max_description_len);
|
||||||
|
if (!py_value) {
|
||||||
|
|
||||||
|
Py_DECREF(py_args);
|
||||||
|
FATAL("Failed to convert arguments");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTuple_SetItem(py_args, 0, py_value);
|
||||||
|
|
||||||
|
py_value = PyObject_CallObject(
|
||||||
|
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
|
||||||
|
|
||||||
|
Py_DECREF(py_args);
|
||||||
|
|
||||||
|
if (py_value != NULL) { return PyBytes_AsString(py_value); }
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||||
|
|
||||||
(void)afl;
|
(void)afl;
|
||||||
@ -134,6 +165,18 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
|||||||
PyObject * py_module = py->py_module;
|
PyObject * py_module = py->py_module;
|
||||||
PyObject **py_functions = py->py_functions;
|
PyObject **py_functions = py->py_functions;
|
||||||
|
|
||||||
|
// initialize the post process buffer; ensures it's always valid
|
||||||
|
PyObject *unused_bytes = PyByteArray_FromStringAndSize("OHAI", 4);
|
||||||
|
if (!unused_bytes) { FATAL("allocation failed!"); }
|
||||||
|
if (PyObject_GetBuffer(unused_bytes, &py->post_process_buf, PyBUF_SIMPLE) ==
|
||||||
|
-1) {
|
||||||
|
|
||||||
|
FATAL("buffer initialization failed");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_DECREF(unused_bytes);
|
||||||
|
|
||||||
if (py_module != NULL) {
|
if (py_module != NULL) {
|
||||||
|
|
||||||
u8 py_notrim = 0, py_idx;
|
u8 py_notrim = 0, py_idx;
|
||||||
@ -144,6 +187,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
|||||||
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
||||||
if (!py_functions[PY_FUNC_FUZZ])
|
if (!py_functions[PY_FUNC_FUZZ])
|
||||||
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
|
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
|
||||||
|
py_functions[PY_FUNC_DESCRIBE] =
|
||||||
|
PyObject_GetAttrString(py_module, "describe");
|
||||||
py_functions[PY_FUNC_FUZZ_COUNT] =
|
py_functions[PY_FUNC_FUZZ_COUNT] =
|
||||||
PyObject_GetAttrString(py_module, "fuzz_count");
|
PyObject_GetAttrString(py_module, "fuzz_count");
|
||||||
if (!py_functions[PY_FUNC_FUZZ])
|
if (!py_functions[PY_FUNC_FUZZ])
|
||||||
@ -313,7 +358,6 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
|
|||||||
struct custom_mutator *mutator;
|
struct custom_mutator *mutator;
|
||||||
|
|
||||||
mutator = ck_alloc(sizeof(struct custom_mutator));
|
mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||||
mutator->post_process_buf = NULL;
|
|
||||||
|
|
||||||
mutator->name = module_name;
|
mutator->name = module_name;
|
||||||
ACTF("Loading Python mutator library from '%s'...", module_name);
|
ACTF("Loading Python mutator library from '%s'...", module_name);
|
||||||
@ -329,9 +373,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
|
|||||||
|
|
||||||
if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
|
if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
|
||||||
|
|
||||||
/* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
|
if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
|
||||||
is quite different from the custom mutator. */
|
|
||||||
mutator->afl_custom_fuzz = fuzz_py;
|
if (py_functions[PY_FUNC_DESCRIBE]) {
|
||||||
|
|
||||||
|
mutator->afl_custom_describe = custom_describe_py;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (py_functions[PY_FUNC_POST_PROCESS]) {
|
if (py_functions[PY_FUNC_POST_PROCESS]) {
|
||||||
|
|
||||||
@ -405,10 +453,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
|
|||||||
size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
|
size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
|
||||||
u8 **out_buf) {
|
u8 **out_buf) {
|
||||||
|
|
||||||
size_t py_out_buf_size;
|
|
||||||
PyObject * py_args, *py_value;
|
PyObject * py_args, *py_value;
|
||||||
py_mutator_t *py = (py_mutator_t *)py_mutator;
|
py_mutator_t *py = (py_mutator_t *)py_mutator;
|
||||||
|
|
||||||
|
// buffer returned previously must be released; initialized during init
|
||||||
|
// so we don't need to do comparisons
|
||||||
|
PyBuffer_Release(&py->post_process_buf);
|
||||||
|
|
||||||
py_args = PyTuple_New(1);
|
py_args = PyTuple_New(1);
|
||||||
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
||||||
if (!py_value) {
|
if (!py_value) {
|
||||||
@ -428,20 +479,20 @@ size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
|
|||||||
|
|
||||||
if (py_value != NULL) {
|
if (py_value != NULL) {
|
||||||
|
|
||||||
py_out_buf_size = PyByteArray_Size(py_value);
|
if (PyObject_GetBuffer(py_value, &py->post_process_buf, PyBUF_SIMPLE) ==
|
||||||
|
-1) {
|
||||||
|
|
||||||
if (unlikely(!afl_realloc(BUF_PARAMS(post_process), py_out_buf_size))) {
|
PyErr_Print();
|
||||||
|
FATAL(
|
||||||
PFATAL("alloc");
|
"Python custom mutator: post_process call return value not a "
|
||||||
|
"bytes-like object");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(py->post_process_buf, PyByteArray_AsString(py_value),
|
|
||||||
py_out_buf_size);
|
|
||||||
Py_DECREF(py_value);
|
Py_DECREF(py_value);
|
||||||
|
|
||||||
*out_buf = py->post_process_buf;
|
*out_buf = (u8 *)py->post_process_buf.buf;
|
||||||
return py_out_buf_size;
|
return py->post_process_buf.len;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -581,7 +632,7 @@ size_t trim_py(void *py_mutator, u8 **out_buf) {
|
|||||||
|
|
||||||
ret = PyByteArray_Size(py_value);
|
ret = PyByteArray_Size(py_value);
|
||||||
*out_buf = afl_realloc(BUF_PARAMS(trim), ret);
|
*out_buf = afl_realloc(BUF_PARAMS(trim), ret);
|
||||||
if (unlikely(!out_buf)) { PFATAL("alloc"); }
|
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
|
||||||
memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
|
memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
|
||||||
Py_DECREF(py_value);
|
Py_DECREF(py_value);
|
||||||
|
|
||||||
@ -647,7 +698,7 @@ size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
|
|||||||
|
|
||||||
/* A new buf is needed... */
|
/* A new buf is needed... */
|
||||||
*out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
|
*out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
|
||||||
if (unlikely(!out_buf)) { PFATAL("alloc"); }
|
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,11 +42,29 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double compute_weight(afl_state_t *afl, struct queue_entry *q,
|
||||||
|
double avg_exec_us, double avg_bitmap_size) {
|
||||||
|
|
||||||
|
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
|
||||||
|
if (hits == 0) hits = 1;
|
||||||
|
|
||||||
|
double weight = 1.0;
|
||||||
|
weight *= avg_exec_us / q->exec_us;
|
||||||
|
weight *= log(q->bitmap_size) / avg_bitmap_size;
|
||||||
|
weight /= log10(hits) + 1;
|
||||||
|
|
||||||
|
if (q->favored) weight *= 5;
|
||||||
|
|
||||||
|
return weight;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* create the alias table that allows weighted random selection - expensive */
|
/* create the alias table that allows weighted random selection - expensive */
|
||||||
|
|
||||||
void create_alias_table(afl_state_t *afl) {
|
void create_alias_table(afl_state_t *afl) {
|
||||||
|
|
||||||
u32 n = afl->queued_paths, i = 0, a, g;
|
u32 n = afl->queued_paths, i = 0, a, g;
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
afl->alias_table =
|
afl->alias_table =
|
||||||
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
|
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
|
||||||
@ -56,11 +74,52 @@ void create_alias_table(afl_state_t *afl) {
|
|||||||
int * S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
|
int * S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
|
||||||
int * L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
|
int * L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
|
||||||
|
|
||||||
if (!P || !S || !L) { FATAL("could not aquire memory for alias table"); }
|
if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
|
||||||
|
|
||||||
|
FATAL("could not acquire memory for alias table");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
memset((void *)afl->alias_table, 0, n * sizeof(u32));
|
memset((void *)afl->alias_table, 0, n * sizeof(u32));
|
||||||
memset((void *)afl->alias_probability, 0, n * sizeof(double));
|
memset((void *)afl->alias_probability, 0, n * sizeof(double));
|
||||||
|
|
||||||
double sum = 0;
|
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||||
|
|
||||||
|
double avg_exec_us = 0.0;
|
||||||
|
double avg_bitmap_size = 0.0;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
|
||||||
|
struct queue_entry *q = afl->queue_buf[i];
|
||||||
|
avg_exec_us += q->exec_us;
|
||||||
|
avg_bitmap_size += log(q->bitmap_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
avg_exec_us /= afl->queued_paths;
|
||||||
|
avg_bitmap_size /= afl->queued_paths;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
|
||||||
|
struct queue_entry *q = afl->queue_buf[i];
|
||||||
|
|
||||||
|
if (!q->disabled) {
|
||||||
|
|
||||||
|
q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size);
|
||||||
|
q->perf_score = calculate_score(afl, q);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sum += q->weight;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
|
||||||
|
P[i] = (afl->queue_buf[i]->weight * n) / sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
|
||||||
@ -79,6 +138,8 @@ void create_alias_table(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int nS = 0, nL = 0, s;
|
int nS = 0, nL = 0, s;
|
||||||
for (s = (s32)n - 1; s >= 0; --s) {
|
for (s = (s32)n - 1; s >= 0; --s) {
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
|
|||||||
s32 doc_fd;
|
s32 doc_fd;
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
|
snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
|
||||||
afl->document_counter++, describe_op(afl, 0));
|
afl->document_counter++,
|
||||||
|
describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
|
||||||
|
|
||||||
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
|
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
|
||||||
|
|
||||||
@ -332,7 +333,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
|
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
|
||||||
afl->afl_env.afl_debug_child_output);
|
afl->afl_env.afl_debug_child);
|
||||||
|
|
||||||
if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
|
if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
|
||||||
|
|
||||||
@ -484,7 +485,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
DIR * sd;
|
DIR * sd;
|
||||||
struct dirent *sd_ent;
|
struct dirent *sd_ent;
|
||||||
u32 sync_cnt = 0, synced = 0, entries = 0;
|
u32 sync_cnt = 0, synced = 0, entries = 0;
|
||||||
u8 path[PATH_MAX + 256];
|
u8 path[PATH_MAX + 1 + NAME_MAX];
|
||||||
|
|
||||||
sd = opendir(afl->sync_dir);
|
sd = opendir(afl->sync_dir);
|
||||||
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
|
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
|
||||||
@ -590,7 +591,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
|
|
||||||
while (m < n) {
|
while (m < n) {
|
||||||
|
|
||||||
if (strcmp(namelist[m]->d_name, entry)) {
|
if (strncmp(namelist[m]->d_name, entry, 9)) {
|
||||||
|
|
||||||
m++;
|
m++;
|
||||||
|
|
||||||
|
@ -268,11 +268,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
|||||||
afl->afl_env.afl_bench_until_crash =
|
afl->afl_env.afl_bench_until_crash =
|
||||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||||
|
|
||||||
} else if (!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
|
} else if (!strncmp(env, "AFL_DEBUG_CHILD",
|
||||||
|
|
||||||
|
afl_environment_variable_len) ||
|
||||||
|
!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
|
||||||
afl_environment_variable_len)) {
|
afl_environment_variable_len)) {
|
||||||
|
|
||||||
afl->afl_env.afl_debug_child_output =
|
afl->afl_env.afl_debug_child =
|
||||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||||
|
|
||||||
} else if (!strncmp(env, "AFL_AUTORESUME",
|
} else if (!strncmp(env, "AFL_AUTORESUME",
|
||||||
@ -392,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
|||||||
afl->afl_env.afl_statsd_tags_flavor =
|
afl->afl_env.afl_statsd_tags_flavor =
|
||||||
(u8 *)get_afl_env(afl_environment_variables[i]);
|
(u8 *)get_afl_env(afl_environment_variables[i]);
|
||||||
|
|
||||||
|
} else if (!strncmp(env, "AFL_CRASH_EXITCODE",
|
||||||
|
|
||||||
|
afl_environment_variable_len)) {
|
||||||
|
|
||||||
|
afl->afl_env.afl_crash_exitcode =
|
||||||
|
(u8 *)get_afl_env(afl_environment_variables[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "afl-fuzz.h"
|
#include "afl-fuzz.h"
|
||||||
#include "cmplog.h"
|
#include "cmplog.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#ifndef USEMMAP
|
#ifndef USEMMAP
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -40,7 +41,7 @@ extern u64 time_spent_working;
|
|||||||
|
|
||||||
static void at_exit() {
|
static void at_exit() {
|
||||||
|
|
||||||
int i;
|
s32 i, pid1 = 0, pid2 = 0;
|
||||||
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
|
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
@ -48,10 +49,10 @@ static void at_exit() {
|
|||||||
if (ptr && *ptr) unlink(ptr);
|
if (ptr && *ptr) unlink(ptr);
|
||||||
|
|
||||||
ptr = getenv("__AFL_TARGET_PID1");
|
ptr = getenv("__AFL_TARGET_PID1");
|
||||||
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
|
if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) kill(pid1, SIGTERM);
|
||||||
|
|
||||||
ptr = getenv("__AFL_TARGET_PID2");
|
ptr = getenv("__AFL_TARGET_PID2");
|
||||||
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
|
if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) kill(pid2, SIGTERM);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (list[i] != NULL) {
|
while (list[i] != NULL) {
|
||||||
@ -75,6 +76,9 @@ static void at_exit() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pid1 > 0) { kill(pid1, SIGKILL); }
|
||||||
|
if (pid2 > 0) { kill(pid2, SIGKILL); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display usage hints. */
|
/* Display usage hints. */
|
||||||
@ -162,11 +166,12 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
|
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
|
||||||
"AFL_BENCH_JUST_ONE: run the target just once\n"
|
"AFL_BENCH_JUST_ONE: run the target just once\n"
|
||||||
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
|
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
|
||||||
|
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
|
||||||
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
|
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
|
||||||
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
|
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
|
||||||
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
|
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
|
||||||
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
|
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
|
||||||
"AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
|
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
|
||||||
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
|
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
|
||||||
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
|
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
|
||||||
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
|
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
|
||||||
@ -184,6 +189,7 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
" used. Defaults to 200.\n"
|
" used. Defaults to 200.\n"
|
||||||
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
|
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
|
||||||
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
|
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
|
||||||
|
"AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
|
||||||
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
|
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
|
||||||
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
|
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
|
||||||
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
|
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
|
||||||
@ -350,6 +356,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
case 's': {
|
case 's': {
|
||||||
|
|
||||||
|
if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
|
||||||
rand_set_seed(afl, strtoul(optarg, 0L, 10));
|
rand_set_seed(afl, strtoul(optarg, 0L, 10));
|
||||||
afl->fixed_seed = 1;
|
afl->fixed_seed = 1;
|
||||||
break;
|
break;
|
||||||
@ -419,6 +426,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
case 'i': /* input dir */
|
case 'i': /* input dir */
|
||||||
|
|
||||||
if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
|
if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
|
||||||
|
if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
|
||||||
afl->in_dir = optarg;
|
afl->in_dir = optarg;
|
||||||
|
|
||||||
if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
|
if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
|
||||||
@ -435,9 +443,26 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
u8 *c;
|
u8 *c;
|
||||||
|
|
||||||
|
if (afl->non_instrumented_mode) {
|
||||||
|
|
||||||
|
FATAL("-M is not supported in non-instrumented mode");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
|
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
|
||||||
|
|
||||||
|
/* sanity check for argument: should not begin with '-' (possible
|
||||||
|
* option) */
|
||||||
|
if (optarg && *optarg == '-') {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"argument for -M started with a dash '-', which is used for "
|
||||||
|
"options");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
afl->sync_id = ck_strdup(optarg);
|
afl->sync_id = ck_strdup(optarg);
|
||||||
afl->skip_deterministic = 0; // force determinsitic fuzzing
|
afl->skip_deterministic = 0; // force deterministic fuzzing
|
||||||
afl->old_seed_selection = 1; // force old queue walking seed selection
|
afl->old_seed_selection = 1; // force old queue walking seed selection
|
||||||
|
|
||||||
if ((c = strchr(afl->sync_id, ':'))) {
|
if ((c = strchr(afl->sync_id, ':'))) {
|
||||||
@ -464,7 +489,24 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
case 'S': /* secondary sync id */
|
case 'S': /* secondary sync id */
|
||||||
|
|
||||||
|
if (afl->non_instrumented_mode) {
|
||||||
|
|
||||||
|
FATAL("-S is not supported in non-instrumented mode");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
|
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
|
||||||
|
|
||||||
|
/* sanity check for argument: should not begin with '-' (possible
|
||||||
|
* option) */
|
||||||
|
if (optarg && *optarg == '-') {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"argument for -M started with a dash '-', which is used for "
|
||||||
|
"options");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
afl->sync_id = ck_strdup(optarg);
|
afl->sync_id = ck_strdup(optarg);
|
||||||
afl->is_secondary_node = 1;
|
afl->is_secondary_node = 1;
|
||||||
break;
|
break;
|
||||||
@ -620,6 +662,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
case 'n': /* dumb mode */
|
case 'n': /* dumb mode */
|
||||||
|
|
||||||
|
if (afl->is_main_node || afl->is_secondary_node) {
|
||||||
|
|
||||||
|
FATAL("Non instrumented mode is not supported with -M / -S");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl->non_instrumented_mode) {
|
if (afl->non_instrumented_mode) {
|
||||||
|
|
||||||
FATAL("Multiple -n options not supported");
|
FATAL("Multiple -n options not supported");
|
||||||
@ -656,7 +704,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
case 'N': /* Unicorn mode */
|
case 'N': /* Unicorn mode */
|
||||||
|
|
||||||
if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
|
if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
|
||||||
afl->fsrv.no_unlink = afl->no_unlink = 1;
|
afl->fsrv.no_unlink = (afl->no_unlink = true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -906,7 +954,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
afl->power_name = power_names[afl->schedule];
|
afl->power_name = power_names[afl->schedule];
|
||||||
|
|
||||||
if (!afl->sync_id) {
|
if (!afl->non_instrumented_mode && !afl->sync_id) {
|
||||||
|
|
||||||
auto_sync = 1;
|
auto_sync = 1;
|
||||||
afl->sync_id = ck_strdup("default");
|
afl->sync_id = ck_strdup("default");
|
||||||
@ -1089,6 +1137,23 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (afl->afl_env.afl_crash_exitcode) {
|
||||||
|
|
||||||
|
long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
|
||||||
|
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
|
||||||
|
exitcode < -127 || exitcode > 128) {
|
||||||
|
|
||||||
|
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
|
||||||
|
afl->afl_env.afl_crash_exitcode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
afl->fsrv.uses_crash_exitcode = true;
|
||||||
|
// WEXITSTATUS is 8 bit unsigned
|
||||||
|
afl->fsrv.crash_exitcode = (u8)exitcode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
|
if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
|
||||||
|
|
||||||
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
|
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
|
||||||
@ -1338,7 +1403,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
|
if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
|
||||||
|
|
||||||
|
check_binary(afl, afl->cmplog_binary);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,7 +1449,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
|
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
|
||||||
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
|
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
|
||||||
afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
|
afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
|
||||||
afl->afl_env.afl_debug_child_output);
|
afl->afl_env.afl_debug_child);
|
||||||
OKF("Cmplog forkserver successfully started");
|
OKF("Cmplog forkserver successfully started");
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1436,9 +1505,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
cull_queue(afl);
|
cull_queue(afl);
|
||||||
|
|
||||||
if (!afl->pending_not_fuzzed)
|
if (!afl->pending_not_fuzzed) {
|
||||||
|
|
||||||
FATAL("We need at least on valid input seed that does not crash!");
|
FATAL("We need at least on valid input seed that does not crash!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
show_init_stats(afl);
|
show_init_stats(afl);
|
||||||
|
|
||||||
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
|
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
|
||||||
|
@ -182,7 +182,7 @@ static void edit_params(int argc, char **argv) {
|
|||||||
instrim = 1;
|
instrim = 1;
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
SAYF(cMGN "[D] " cRST
|
DEBUGF(
|
||||||
"passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
|
"passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
|
||||||
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
|
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
|
||||||
passthrough ? "true" : "false", instrim, gold_pos,
|
passthrough ? "true" : "false", instrim, gold_pos,
|
||||||
@ -280,7 +280,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
|
if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
|
||||||
|
|
||||||
SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
|
DEBUGF("cd \"%s\";", thecwd);
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
SAYF(" \"%s\"", argv[i]);
|
SAYF(" \"%s\"", argv[i]);
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
@ -315,7 +315,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|
||||||
SAYF(cMGN "[D]" cRST " cd \"%s\";", thecwd);
|
DEBUGF("cd \"%s\";", thecwd);
|
||||||
for (i = 0; i < ld_param_cnt; i++)
|
for (i = 0; i < ld_param_cnt; i++)
|
||||||
SAYF(" \"%s\"", ld_params[i]);
|
SAYF(" \"%s\"", ld_params[i]);
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
@ -333,7 +333,7 @@ int main(int argc, char **argv) {
|
|||||||
if (pid < 0) PFATAL("fork() failed");
|
if (pid < 0) PFATAL("fork() failed");
|
||||||
|
|
||||||
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
|
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
|
||||||
if (debug) SAYF(cMGN "[D] " cRST "linker result: %d\n", status);
|
if (debug) DEBUGF("linker result: %d\n", status);
|
||||||
|
|
||||||
if (!just_version) {
|
if (!just_version) {
|
||||||
|
|
||||||
|
@ -667,6 +667,8 @@ static void usage(u8 *argv0) {
|
|||||||
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
|
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
|
||||||
"inputs\n"
|
"inputs\n"
|
||||||
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
|
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
|
||||||
|
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
|
||||||
|
"crash\n"
|
||||||
"AFL_DEBUG: enable extra developer output\n"
|
"AFL_DEBUG: enable extra developer output\n"
|
||||||
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
|
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
|
||||||
"size\n"
|
"size\n"
|
||||||
@ -904,7 +906,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (getenv("AFL_DEBUG")) {
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
SAYF(cMGN "[D]" cRST);
|
DEBUGF("");
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
SAYF(" %s", argv[i]);
|
SAYF(" %s", argv[i]);
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
@ -1066,7 +1068,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (get_afl_env("AFL_DEBUG")) {
|
if (get_afl_env("AFL_DEBUG")) {
|
||||||
|
|
||||||
int i = optind;
|
int i = optind;
|
||||||
SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
|
DEBUGF("%s:", fsrv->target_path);
|
||||||
while (argv[i] != NULL) {
|
while (argv[i] != NULL) {
|
||||||
|
|
||||||
SAYF(" \"%s\"", argv[i++]);
|
SAYF(" \"%s\"", argv[i++]);
|
||||||
@ -1090,8 +1092,29 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_CRASH_EXITCODE")) {
|
||||||
|
|
||||||
|
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
|
||||||
|
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
|
||||||
|
exitcode < -127 || exitcode > 128) {
|
||||||
|
|
||||||
|
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
|
||||||
|
getenv("AFL_CRASH_EXITCODE"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fsrv->uses_crash_exitcode = true;
|
||||||
|
// WEXITSTATUS is 8 bit unsigned
|
||||||
|
fsrv->crash_exitcode = (u8)exitcode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
||||||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
|
(get_afl_env("AFL_DEBUG_CHILD") ||
|
||||||
|
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
|
||||||
map_size = fsrv->map_size;
|
map_size = fsrv->map_size;
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@ -841,17 +842,17 @@ static void usage(u8 *argv0) {
|
|||||||
"For additional tips, please consult %s/README.md.\n\n"
|
"For additional tips, please consult %s/README.md.\n\n"
|
||||||
|
|
||||||
"Environment variables used:\n"
|
"Environment variables used:\n"
|
||||||
"TMPDIR: directory to use for temporary input files\n"
|
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
|
||||||
"ASAN_OPTIONS: custom settings for ASAN\n"
|
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
|
||||||
" (must contain abort_on_error=1 and symbolize=0)\n"
|
|
||||||
"MSAN_OPTIONS: custom settings for MSAN\n"
|
|
||||||
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
|
|
||||||
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
|
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
|
||||||
" the target was compiled for\n"
|
" the target was compiled for\n"
|
||||||
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
|
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
|
||||||
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
|
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
|
||||||
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
|
"ASAN_OPTIONS: custom settings for ASAN\n"
|
||||||
|
" (must contain abort_on_error=1 and symbolize=0)\n"
|
||||||
|
"MSAN_OPTIONS: custom settings for MSAN\n"
|
||||||
|
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
|
||||||
|
"TMPDIR: directory to use for temporary input files\n"
|
||||||
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
|
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_CRASH_EXITCODE")) {
|
||||||
|
|
||||||
|
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
|
||||||
|
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
|
||||||
|
exitcode < -127 || exitcode > 128) {
|
||||||
|
|
||||||
|
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
|
||||||
|
getenv("AFL_CRASH_EXITCODE"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fsrv->uses_crash_exitcode = true;
|
||||||
|
// WEXITSTATUS is 8 bit unsigned
|
||||||
|
fsrv->crash_exitcode = (u8)exitcode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
|
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
|
||||||
|
|
||||||
/* initialize cmplog_mode */
|
/* initialize cmplog_mode */
|
||||||
@ -1141,8 +1159,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
read_initial_file();
|
read_initial_file();
|
||||||
|
|
||||||
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
afl_fsrv_start(
|
||||||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
|
fsrv, use_argv, &stop_soon,
|
||||||
|
(get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
||||||
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
$ECHO "$BLUE[*] Testing: custom mutator"
|
$ECHO "$BLUE[*] Testing: custom mutator"
|
||||||
test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
|
test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
|
||||||
# normalize path
|
# normalize path
|
||||||
CUSTOM_MUTATOR_PATH=$(cd $(pwd)/../examples/custom_mutators;pwd)
|
CUSTOM_MUTATOR_PATH=$(cd $(pwd)/../utils/custom_mutators;pwd)
|
||||||
test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
|
test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
|
||||||
unset AFL_CC
|
unset AFL_CC
|
||||||
# Compile the vulnerable program for single mutator
|
# Compile the vulnerable program for single mutator
|
||||||
@ -29,8 +29,8 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
# Compile the custom mutator
|
# Compile the custom mutator
|
||||||
cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
|
cc -D_FIXED_CHAR=0x41 -g -fPIC -shared -I../include ../utils/custom_mutators/simple_example.c -o libexamplemutator.so > /dev/null 2>&1
|
||||||
cc -D_FIXED_CHAR=0x42 -g -fPIC -shared -I../include ../examples/custom_mutators/simple_example.c -o libexamplemutator2.so > /dev/null 2>&1
|
cc -D_FIXED_CHAR=0x42 -g -fPIC -shared -I../include ../utils/custom_mutators/simple_example.c -o libexamplemutator2.so > /dev/null 2>&1
|
||||||
test -e test-custom-mutator -a -e ./libexamplemutator.so && {
|
test -e test-custom-mutator -a -e ./libexamplemutator.so && {
|
||||||
# Create input directory
|
# Create input directory
|
||||||
mkdir -p in
|
mkdir -p in
|
||||||
@ -109,7 +109,7 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
|
|||||||
|
|
||||||
#test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
|
#test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
|
||||||
|
|
||||||
make -C ../examples/custom_mutators clean > /dev/null 2>&1
|
make -C ../utils/custom_mutators clean > /dev/null 2>&1
|
||||||
rm -f test-custom-mutator
|
rm -f test-custom-mutator
|
||||||
rm -f test-custom-mutators
|
rm -f test-custom-mutators
|
||||||
} || {
|
} || {
|
||||||
|
@ -94,7 +94,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
|
|||||||
CODE=1
|
CODE=1
|
||||||
}
|
}
|
||||||
rm -f test-compcov test.out instrumentlist.txt
|
rm -f test-compcov test.out instrumentlist.txt
|
||||||
../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
|
../afl-gcc-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
|
||||||
test -e test-persistent && {
|
test -e test-persistent && {
|
||||||
echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
||||||
$ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
|
$ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
|
||||||
|
@ -57,7 +57,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
|
|||||||
CODE=1
|
CODE=1
|
||||||
}
|
}
|
||||||
rm -f test-compcov test.out instrumentlist.txt
|
rm -f test-compcov test.out instrumentlist.txt
|
||||||
../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
|
../afl-clang-lto -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
|
||||||
test -e test-persistent && {
|
test -e test-persistent && {
|
||||||
echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && {
|
echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && {
|
||||||
$ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly"
|
$ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly"
|
||||||
|
@ -209,7 +209,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
INCOMPLETE=1
|
INCOMPLETE=1
|
||||||
}
|
}
|
||||||
rm -rf errors test-cmplog in core.*
|
rm -rf errors test-cmplog in core.*
|
||||||
../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
|
../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
|
||||||
test -e test-persistent && {
|
test -e test-persistent && {
|
||||||
echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
||||||
$ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"
|
$ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"
|
||||||
|
@ -7,7 +7,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
|
|||||||
test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
|
test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
|
||||||
{
|
{
|
||||||
# We want to see python errors etc. in logs, in case something doesn't work
|
# We want to see python errors etc. in logs, in case something doesn't work
|
||||||
export AFL_DEBUG_CHILD_OUTPUT=1
|
export AFL_DEBUG_CHILD=1
|
||||||
|
|
||||||
# some python version should be available now
|
# some python version should be available now
|
||||||
PYTHONS="`command -v python3` `command -v python` `command -v python2`"
|
PYTHONS="`command -v python3` `command -v python` `command -v python2`"
|
||||||
@ -34,7 +34,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
|
|||||||
cd ../unicorn_mode/samples/persistent
|
cd ../unicorn_mode/samples/persistent
|
||||||
make >>errors 2>&1
|
make >>errors 2>&1
|
||||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds"
|
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds"
|
||||||
AFL_DEBUG_CHILD_OUTPUT=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
|
AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
|
||||||
test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
|
test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
|
||||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
|
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
|
||||||
} || {
|
} || {
|
||||||
@ -96,7 +96,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
|
|||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unset AFL_DEBUG_CHILD_OUTPUT
|
unset AFL_DEBUG_CHILD
|
||||||
|
|
||||||
}
|
}
|
||||||
} || {
|
} || {
|
||||||
|
@ -1 +1 @@
|
|||||||
f44ec48f
|
8cca4801
|
||||||
|
@ -149,7 +149,7 @@ git status 1>/dev/null 2>/dev/null
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "[*] initializing unicornafl submodule"
|
echo "[*] initializing unicornafl submodule"
|
||||||
git submodule init || exit 1
|
git submodule init || exit 1
|
||||||
git submodule update 2>/dev/null # ignore errors
|
git submodule update ./unicornafl 2>/dev/null # ignore errors
|
||||||
else
|
else
|
||||||
echo "[*] cloning unicornafl"
|
echo "[*] cloning unicornafl"
|
||||||
test -d unicornafl || {
|
test -d unicornafl || {
|
||||||
|
@ -44,6 +44,7 @@ MAX_SEG_SIZE = 128 * 1024 * 1024
|
|||||||
# Name of the index file
|
# Name of the index file
|
||||||
INDEX_FILE_NAME = "_index.json"
|
INDEX_FILE_NAME = "_index.json"
|
||||||
|
|
||||||
|
|
||||||
#----------------------
|
#----------------------
|
||||||
#---- Helper Functions
|
#---- Helper Functions
|
||||||
|
|
||||||
@ -59,14 +60,14 @@ def map_arch():
|
|||||||
return "arm64be"
|
return "arm64be"
|
||||||
elif 'armeb' in arch:
|
elif 'armeb' in arch:
|
||||||
# check for THUMB mode
|
# check for THUMB mode
|
||||||
cpsr = get_register('cpsr')
|
cpsr = get_register('$cpsr')
|
||||||
if (cpsr & (1 << 5)):
|
if (cpsr & (1 << 5)):
|
||||||
return "armbethumb"
|
return "armbethumb"
|
||||||
else:
|
else:
|
||||||
return "armbe"
|
return "armbe"
|
||||||
elif 'arm' in arch:
|
elif 'arm' in arch:
|
||||||
# check for THUMB mode
|
# check for THUMB mode
|
||||||
cpsr = get_register('cpsr')
|
cpsr = get_register('$cpsr')
|
||||||
if (cpsr & (1 << 5)):
|
if (cpsr & (1 << 5)):
|
||||||
return "armlethumb"
|
return "armlethumb"
|
||||||
else:
|
else:
|
||||||
@ -88,12 +89,8 @@ def dump_regs():
|
|||||||
reg_state = {}
|
reg_state = {}
|
||||||
for reg in current_arch.all_registers:
|
for reg in current_arch.all_registers:
|
||||||
reg_val = get_register(reg)
|
reg_val = get_register(reg)
|
||||||
# current dumper script looks for register values to be hex strings
|
|
||||||
# reg_str = "0x{:08x}".format(reg_val)
|
|
||||||
# if "64" in get_arch():
|
|
||||||
# reg_str = "0x{:016x}".format(reg_val)
|
|
||||||
# reg_state[reg.strip().strip('$')] = reg_str
|
|
||||||
reg_state[reg.strip().strip('$')] = reg_val
|
reg_state[reg.strip().strip('$')] = reg_val
|
||||||
|
|
||||||
return reg_state
|
return reg_state
|
||||||
|
|
||||||
|
|
||||||
@ -146,6 +143,21 @@ def dump_process_memory(output_dir):
|
|||||||
|
|
||||||
return final_segment_list
|
return final_segment_list
|
||||||
|
|
||||||
|
#---------------------------------------------
|
||||||
|
#---- ARM Extention (dump floating point regs)
|
||||||
|
|
||||||
|
def dump_float(rge=32):
|
||||||
|
reg_convert = ""
|
||||||
|
if map_arch() == "armbe" or map_arch() == "armle" or map_arch() == "armbethumb" or map_arch() == "armbethumb":
|
||||||
|
reg_state = {}
|
||||||
|
for reg_num in range(32):
|
||||||
|
value = gdb.selected_frame().read_register("d" + str(reg_num))
|
||||||
|
reg_state["d" + str(reg_num)] = int(str(value["u64"]), 16)
|
||||||
|
value = gdb.selected_frame().read_register("fpscr")
|
||||||
|
reg_state["fpscr"] = int(str(value), 16)
|
||||||
|
|
||||||
|
return reg_state
|
||||||
|
|
||||||
#----------
|
#----------
|
||||||
#---- Main
|
#---- Main
|
||||||
|
|
||||||
@ -173,6 +185,7 @@ def main():
|
|||||||
context = {
|
context = {
|
||||||
"arch": dump_arch_info(),
|
"arch": dump_arch_info(),
|
||||||
"regs": dump_regs(),
|
"regs": dump_regs(),
|
||||||
|
"regs_extended": dump_float(),
|
||||||
"segments": dump_process_memory(output_path),
|
"segments": dump_process_memory(output_path),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,4 +200,3 @@ def main():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -26,6 +26,13 @@ from unicorn.arm64_const import *
|
|||||||
from unicorn.x86_const import *
|
from unicorn.x86_const import *
|
||||||
from unicorn.mips_const import *
|
from unicorn.mips_const import *
|
||||||
|
|
||||||
|
# If Capstone libraries are availible (only check once)
|
||||||
|
try:
|
||||||
|
from capstone import *
|
||||||
|
CAPSTONE_EXISTS = 1
|
||||||
|
except:
|
||||||
|
CAPSTONE_EXISTS = 0
|
||||||
|
|
||||||
# Name of the index file
|
# Name of the index file
|
||||||
INDEX_FILE_NAME = "_index.json"
|
INDEX_FILE_NAME = "_index.json"
|
||||||
|
|
||||||
@ -86,7 +93,7 @@ class UnicornSimpleHeap(object):
|
|||||||
total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
|
total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
|
||||||
# Gross but efficient way to find space for the chunk:
|
# Gross but efficient way to find space for the chunk:
|
||||||
chunk = None
|
chunk = None
|
||||||
for addr in xrange(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
|
for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
|
||||||
try:
|
try:
|
||||||
self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
|
self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
|
||||||
chunk = self.HeapChunk(addr, total_chunk_size, size)
|
chunk = self.HeapChunk(addr, total_chunk_size, size)
|
||||||
@ -184,29 +191,17 @@ class AflUnicornEngine(Uc):
|
|||||||
# Load the registers
|
# Load the registers
|
||||||
regs = context['regs']
|
regs = context['regs']
|
||||||
reg_map = self.__get_register_map(self._arch_str)
|
reg_map = self.__get_register_map(self._arch_str)
|
||||||
for register, value in regs.iteritems():
|
self.__load_registers(regs, reg_map, debug_print)
|
||||||
if debug_print:
|
# If we have extra FLOATING POINT regs, load them in!
|
||||||
print("Reg {0} = {1}".format(register, value))
|
if 'regs_extended' in context:
|
||||||
if not reg_map.has_key(register.lower()):
|
if context['regs_extended']:
|
||||||
if debug_print:
|
regs_extended = context['regs_extended']
|
||||||
print("Skipping Reg: {}".format(register))
|
reg_map = self.__get_registers_extended(self._arch_str)
|
||||||
else:
|
self.__load_registers(regs_extended, reg_map, debug_print)
|
||||||
reg_write_retry = True
|
|
||||||
try:
|
|
||||||
self.reg_write(reg_map[register.lower()], value)
|
|
||||||
reg_write_retry = False
|
|
||||||
except Exception as e:
|
|
||||||
if debug_print:
|
|
||||||
print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e)))
|
|
||||||
|
|
||||||
if reg_write_retry:
|
# For ARM, sometimes the stack pointer is erased ??? (I think I fixed this (issue with ordering of dumper.py, I'll keep the write anyways)
|
||||||
if debug_print:
|
if self.__get_arch_and_mode(self.get_arch_str())[0] == UC_ARCH_ARM:
|
||||||
print("Trying to parse value ({}) as hex string".format(value))
|
self.reg_write(UC_ARM_REG_SP, regs['sp'])
|
||||||
try:
|
|
||||||
self.reg_write(reg_map[register.lower()], int(value, 16))
|
|
||||||
except Exception as e:
|
|
||||||
if debug_print:
|
|
||||||
print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e)))
|
|
||||||
|
|
||||||
# Setup the memory map and load memory content
|
# Setup the memory map and load memory content
|
||||||
self.__map_segments(context['segments'], context_directory, debug_print)
|
self.__map_segments(context['segments'], context_directory, debug_print)
|
||||||
@ -253,9 +248,39 @@ class AflUnicornEngine(Uc):
|
|||||||
for reg in sorted(self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]):
|
for reg in sorted(self.__get_register_map(self._arch_str).items(), key=lambda reg: reg[0]):
|
||||||
print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
|
print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
|
||||||
|
|
||||||
|
def dump_regs_extended(self):
|
||||||
|
""" Dumps the contents of all the registers to STDOUT """
|
||||||
|
try:
|
||||||
|
for reg in sorted(self.__get_registers_extended(self._arch_str).items(), key=lambda reg: reg[0]):
|
||||||
|
print(">>> {0:>4}: 0x{1:016x}".format(reg[0], self.reg_read(reg[1])))
|
||||||
|
except Exception as e:
|
||||||
|
print("ERROR: Are extended registers loaded?")
|
||||||
|
|
||||||
# TODO: Make this dynamically get the stack pointer register and pointer width for the current architecture
|
# TODO: Make this dynamically get the stack pointer register and pointer width for the current architecture
|
||||||
"""
|
"""
|
||||||
def dump_stack(self, window=10):
|
def dump_stack(self, window=10):
|
||||||
|
arch = self.get_arch()
|
||||||
|
mode = self.get_mode()
|
||||||
|
# Get stack pointers and bit sizes for given architecture
|
||||||
|
if arch == UC_ARCH_X86 and mode == UC_MODE_64:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_X86_REG_RSP)
|
||||||
|
bit_size = 8
|
||||||
|
elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_X86_REG_ESP)
|
||||||
|
bit_size = 4
|
||||||
|
elif arch == UC_ARCH_ARM64:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_ARM64_REG_SP)
|
||||||
|
bit_size = 8
|
||||||
|
elif arch == UC_ARCH_ARM:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_ARM_REG_SP)
|
||||||
|
bit_size = 4
|
||||||
|
elif arch == UC_ARCH_ARM and mode == UC_MODE_THUMB:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_ARM_REG_SP)
|
||||||
|
bit_size = 4
|
||||||
|
elif arch == UC_ARCH_MIPS:
|
||||||
|
stack_ptr_addr = self.reg_read(UC_MIPS_REG_SP)
|
||||||
|
bit_size = 4
|
||||||
|
print("")
|
||||||
print(">>> Stack:")
|
print(">>> Stack:")
|
||||||
stack_ptr_addr = self.reg_read(UC_X86_REG_RSP)
|
stack_ptr_addr = self.reg_read(UC_X86_REG_RSP)
|
||||||
for i in xrange(-window, window + 1):
|
for i in xrange(-window, window + 1):
|
||||||
@ -268,6 +293,31 @@ class AflUnicornEngine(Uc):
|
|||||||
#-----------------------------
|
#-----------------------------
|
||||||
#---- Loader Helper Functions
|
#---- Loader Helper Functions
|
||||||
|
|
||||||
|
def __load_registers(self, regs, reg_map, debug_print):
|
||||||
|
for register, value in regs.items():
|
||||||
|
if debug_print:
|
||||||
|
print("Reg {0} = {1}".format(register, value))
|
||||||
|
if register.lower() not in reg_map:
|
||||||
|
if debug_print:
|
||||||
|
print("Skipping Reg: {}".format(register))
|
||||||
|
else:
|
||||||
|
reg_write_retry = True
|
||||||
|
try:
|
||||||
|
self.reg_write(reg_map[register.lower()], value)
|
||||||
|
reg_write_retry = False
|
||||||
|
except Exception as e:
|
||||||
|
if debug_print:
|
||||||
|
print("ERROR writing register: {}, value: {} -- {}".format(register, value, repr(e)))
|
||||||
|
|
||||||
|
if reg_write_retry:
|
||||||
|
if debug_print:
|
||||||
|
print("Trying to parse value ({}) as hex string".format(value))
|
||||||
|
try:
|
||||||
|
self.reg_write(reg_map[register.lower()], int(value, 16))
|
||||||
|
except Exception as e:
|
||||||
|
if debug_print:
|
||||||
|
print("ERROR writing hex string register: {}, value: {} -- {}".format(register, value, repr(e)))
|
||||||
|
|
||||||
def __map_segment(self, name, address, size, perms, debug_print=False):
|
def __map_segment(self, name, address, size, perms, debug_print=False):
|
||||||
# - size is unsigned and must be != 0
|
# - size is unsigned and must be != 0
|
||||||
# - starting address must be aligned to 4KB
|
# - starting address must be aligned to 4KB
|
||||||
@ -354,7 +404,7 @@ class AflUnicornEngine(Uc):
|
|||||||
else:
|
else:
|
||||||
if debug_print:
|
if debug_print:
|
||||||
print("No content found for segment {0} @ {1:016x}".format(name, seg_start))
|
print("No content found for segment {0} @ {1:016x}".format(name, seg_start))
|
||||||
self.mem_write(seg_start, '\x00' * (seg_end - seg_start))
|
self.mem_write(seg_start, b'\x00' * (seg_end - seg_start))
|
||||||
|
|
||||||
def __get_arch_and_mode(self, arch_str):
|
def __get_arch_and_mode(self, arch_str):
|
||||||
arch_map = {
|
arch_map = {
|
||||||
@ -398,7 +448,6 @@ class AflUnicornEngine(Uc):
|
|||||||
"r14": UC_X86_REG_R14,
|
"r14": UC_X86_REG_R14,
|
||||||
"r15": UC_X86_REG_R15,
|
"r15": UC_X86_REG_R15,
|
||||||
"rip": UC_X86_REG_RIP,
|
"rip": UC_X86_REG_RIP,
|
||||||
"rsp": UC_X86_REG_RSP,
|
|
||||||
"efl": UC_X86_REG_EFLAGS,
|
"efl": UC_X86_REG_EFLAGS,
|
||||||
"cs": UC_X86_REG_CS,
|
"cs": UC_X86_REG_CS,
|
||||||
"ds": UC_X86_REG_DS,
|
"ds": UC_X86_REG_DS,
|
||||||
@ -415,7 +464,6 @@ class AflUnicornEngine(Uc):
|
|||||||
"esi": UC_X86_REG_ESI,
|
"esi": UC_X86_REG_ESI,
|
||||||
"edi": UC_X86_REG_EDI,
|
"edi": UC_X86_REG_EDI,
|
||||||
"ebp": UC_X86_REG_EBP,
|
"ebp": UC_X86_REG_EBP,
|
||||||
"esp": UC_X86_REG_ESP,
|
|
||||||
"eip": UC_X86_REG_EIP,
|
"eip": UC_X86_REG_EIP,
|
||||||
"esp": UC_X86_REG_ESP,
|
"esp": UC_X86_REG_ESP,
|
||||||
"efl": UC_X86_REG_EFLAGS,
|
"efl": UC_X86_REG_EFLAGS,
|
||||||
@ -519,28 +567,96 @@ class AflUnicornEngine(Uc):
|
|||||||
}
|
}
|
||||||
return registers[arch]
|
return registers[arch]
|
||||||
|
|
||||||
|
def __get_registers_extended(self, arch):
|
||||||
|
# Similar to __get_register_map, but for ARM floating point registers
|
||||||
|
if arch == "arm64le" or arch == "arm64be":
|
||||||
|
arch = "arm64"
|
||||||
|
elif arch == "armle" or arch == "armbe" or "thumb" in arch:
|
||||||
|
arch = "arm"
|
||||||
|
elif arch == "mipsel":
|
||||||
|
arch = "mips"
|
||||||
|
|
||||||
|
registers = {
|
||||||
|
"arm": {
|
||||||
|
"d0": UC_ARM_REG_D0,
|
||||||
|
"d1": UC_ARM_REG_D1,
|
||||||
|
"d2": UC_ARM_REG_D2,
|
||||||
|
"d3": UC_ARM_REG_D3,
|
||||||
|
"d4": UC_ARM_REG_D4,
|
||||||
|
"d5": UC_ARM_REG_D5,
|
||||||
|
"d6": UC_ARM_REG_D6,
|
||||||
|
"d7": UC_ARM_REG_D7,
|
||||||
|
"d8": UC_ARM_REG_D8,
|
||||||
|
"d9": UC_ARM_REG_D9,
|
||||||
|
"d10": UC_ARM_REG_D10,
|
||||||
|
"d11": UC_ARM_REG_D11,
|
||||||
|
"d12": UC_ARM_REG_D12,
|
||||||
|
"d13": UC_ARM_REG_D13,
|
||||||
|
"d14": UC_ARM_REG_D14,
|
||||||
|
"d15": UC_ARM_REG_D15,
|
||||||
|
"d16": UC_ARM_REG_D16,
|
||||||
|
"d17": UC_ARM_REG_D17,
|
||||||
|
"d18": UC_ARM_REG_D18,
|
||||||
|
"d19": UC_ARM_REG_D19,
|
||||||
|
"d20": UC_ARM_REG_D20,
|
||||||
|
"d21": UC_ARM_REG_D21,
|
||||||
|
"d22": UC_ARM_REG_D22,
|
||||||
|
"d23": UC_ARM_REG_D23,
|
||||||
|
"d24": UC_ARM_REG_D24,
|
||||||
|
"d25": UC_ARM_REG_D25,
|
||||||
|
"d26": UC_ARM_REG_D26,
|
||||||
|
"d27": UC_ARM_REG_D27,
|
||||||
|
"d28": UC_ARM_REG_D28,
|
||||||
|
"d29": UC_ARM_REG_D29,
|
||||||
|
"d30": UC_ARM_REG_D30,
|
||||||
|
"d31": UC_ARM_REG_D31,
|
||||||
|
"fpscr": UC_ARM_REG_FPSCR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return registers[arch];
|
||||||
#---------------------------
|
#---------------------------
|
||||||
# Callbacks for tracing
|
# Callbacks for tracing
|
||||||
|
|
||||||
# TODO: Make integer-printing fixed widths dependent on bitness of architecture
|
|
||||||
# (i.e. only show 4 bytes for 32-bit, 8 bytes for 64-bit)
|
|
||||||
|
|
||||||
# TODO: Figure out how best to determine the capstone mode and architecture here
|
# TODO: Extra mode for Capstone (i.e. Cs(cs_arch, cs_mode + cs_extra) not implemented
|
||||||
"""
|
|
||||||
try:
|
|
||||||
|
def __trace_instruction(self, uc, address, size, user_data):
|
||||||
|
if CAPSTONE_EXISTS == 1:
|
||||||
# If Capstone is installed then we'll dump disassembly, otherwise just dump the binary.
|
# If Capstone is installed then we'll dump disassembly, otherwise just dump the binary.
|
||||||
from capstone import *
|
arch = self.get_arch()
|
||||||
cs = Cs(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN)
|
mode = self.get_mode()
|
||||||
def __trace_instruction(self, uc, address, size, user_data):
|
bit_size = self.bit_size_arch()
|
||||||
mem = uc.mem_read(address, size)
|
# Map current arch to capstone labeling
|
||||||
for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
|
if arch == UC_ARCH_X86 and mode == UC_MODE_64:
|
||||||
print(" Instr: {:#016x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
|
cs_arch = CS_ARCH_X86
|
||||||
except ImportError:
|
cs_mode = CS_MODE_64
|
||||||
def __trace_instruction(self, uc, address, size, user_data):
|
elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
|
||||||
print(" Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
|
cs_arch = CS_ARCH_X86
|
||||||
"""
|
cs_mode = CS_MODE_32
|
||||||
|
elif arch == UC_ARCH_ARM64:
|
||||||
|
cs_arch = CS_ARCH_ARM64
|
||||||
|
cs_mode = CS_MODE_ARM
|
||||||
|
elif arch == UC_ARCH_ARM and mode == UC_MODE_THUMB:
|
||||||
|
cs_arch = CS_ARCH_ARM
|
||||||
|
cs_mode = CS_MODE_THUMB
|
||||||
|
elif arch == UC_ARCH_ARM:
|
||||||
|
cs_arch = CS_ARCH_ARM
|
||||||
|
cs_mode = CS_MODE_ARM
|
||||||
|
elif arch == UC_ARCH_MIPS:
|
||||||
|
cs_arch = CS_ARCH_MIPS
|
||||||
|
cs_mode = CS_MODE_MIPS32 # No other MIPS supported in program
|
||||||
|
|
||||||
def __trace_instruction(self, uc, address, size, user_data):
|
cs = Cs(cs_arch, cs_mode)
|
||||||
|
mem = uc.mem_read(address, size)
|
||||||
|
if bit_size == 4:
|
||||||
|
for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
|
||||||
|
print(" Instr: {:#08x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
|
||||||
|
else:
|
||||||
|
for (cs_address, cs_size, cs_mnemonic, cs_opstr) in cs.disasm_lite(bytes(mem), size):
|
||||||
|
print(" Instr: {:#16x}:\t{}\t{}".format(address, cs_mnemonic, cs_opstr))
|
||||||
|
else:
|
||||||
print(" Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
|
print(" Instr: addr=0x{0:016x}, size=0x{1:016x}".format(address, size))
|
||||||
|
|
||||||
def __trace_block(self, uc, address, size, user_data):
|
def __trace_block(self, uc, address, size, user_data):
|
||||||
@ -558,3 +674,18 @@ class AflUnicornEngine(Uc):
|
|||||||
else:
|
else:
|
||||||
print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
|
print(" >>> INVALID Read: addr=0x{0:016x} size={1}".format(address, size))
|
||||||
|
|
||||||
|
def bit_size_arch(self):
|
||||||
|
arch = self.get_arch()
|
||||||
|
mode = self.get_mode()
|
||||||
|
# Get bit sizes for given architecture
|
||||||
|
if arch == UC_ARCH_X86 and mode == UC_MODE_64:
|
||||||
|
bit_size = 8
|
||||||
|
elif arch == UC_ARCH_X86 and mode == UC_MODE_32:
|
||||||
|
bit_size = 4
|
||||||
|
elif arch == UC_ARCH_ARM64:
|
||||||
|
bit_size = 8
|
||||||
|
elif arch == UC_ARCH_ARM:
|
||||||
|
bit_size = 4
|
||||||
|
elif arch == UC_ARCH_MIPS:
|
||||||
|
bit_size = 4
|
||||||
|
return bit_size
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c6d6647161a32bae88785a618fcd828d1711d9e6
|
Subproject commit 8cca4801adb767dce7cf72202d7d25bdb420cf7d
|
@ -39,13 +39,13 @@ Here's a quick overview of the stuff you can find in this directory:
|
|||||||
|
|
||||||
- libpng_no_checksum - a sample patch for removing CRC checks in libpng.
|
- libpng_no_checksum - a sample patch for removing CRC checks in libpng.
|
||||||
|
|
||||||
- persistent_demo - an example of how to use the LLVM persistent process
|
- persistent_mode - an example of how to use the LLVM persistent process
|
||||||
mode to speed up certain fuzzing jobs.
|
mode to speed up certain fuzzing jobs.
|
||||||
|
|
||||||
- socket_fuzzing - a LD_PRELOAD library 'redirects' a socket to stdin
|
- socket_fuzzing - a LD_PRELOAD library 'redirects' a socket to stdin
|
||||||
for fuzzing access with afl++
|
for fuzzing access with afl++
|
||||||
|
|
||||||
Note that the minimize_corpus.sh tool has graduated from the examples/
|
Note that the minimize_corpus.sh tool has graduated from the utils/
|
||||||
directory and is now available as ../afl-cmin. The LLVM mode has likewise
|
directory and is now available as ../afl-cmin. The LLVM mode has likewise
|
||||||
graduated to ../instrumentation/*.
|
graduated to ../instrumentation/*.
|
||||||
|
|
@ -358,8 +358,8 @@ int recv_testcase(int s, void **buf) {
|
|||||||
|
|
||||||
if ((size & 0xff000000) != 0xff000000) {
|
if ((size & 0xff000000) != 0xff000000) {
|
||||||
|
|
||||||
*buf = afl_realloc((void **)&buf, size);
|
*buf = afl_realloc(buf, size);
|
||||||
if (unlikely(!buf)) { PFATAL("Alloc"); }
|
if (unlikely(!*buf)) { PFATAL("Alloc"); }
|
||||||
received = 0;
|
received = 0;
|
||||||
// fprintf(stderr, "unCOMPRESS (%u)\n", size);
|
// fprintf(stderr, "unCOMPRESS (%u)\n", size);
|
||||||
while (received < size &&
|
while (received < size &&
|
||||||
@ -371,8 +371,8 @@ int recv_testcase(int s, void **buf) {
|
|||||||
#ifdef USE_DEFLATE
|
#ifdef USE_DEFLATE
|
||||||
u32 clen;
|
u32 clen;
|
||||||
size -= 0xff000000;
|
size -= 0xff000000;
|
||||||
*buf = afl_realloc((void **)&buf, size);
|
*buf = afl_realloc(buf, size);
|
||||||
if (unlikely(!buf)) { PFATAL("Alloc"); }
|
if (unlikely(!*buf)) { PFATAL("Alloc"); }
|
||||||
received = 0;
|
received = 0;
|
||||||
while (received < 4 &&
|
while (received < 4 &&
|
||||||
(ret = recv(s, &clen + received, 4 - received, 0)) > 0)
|
(ret = recv(s, &clen + received, 4 - received, 0)) > 0)
|
||||||
@ -636,8 +636,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (listen(sock, 1) < 0) { PFATAL("listen() failed"); }
|
if (listen(sock, 1) < 0) { PFATAL("listen() failed"); }
|
||||||
|
|
||||||
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
afl_fsrv_start(
|
||||||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
|
fsrv, use_argv, &stop_soon,
|
||||||
|
(get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
|
||||||
#ifdef USE_DEFLATE
|
#ifdef USE_DEFLATE
|
||||||
compressor = libdeflate_alloc_compressor(1);
|
compressor = libdeflate_alloc_compressor(1);
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
// Find patch points for untracer tools (e.g. afl++ examples/afl_untracer)
|
// Find patch points for untracer tools (e.g. afl++ utils/afl_untracer)
|
||||||
//
|
//
|
||||||
// Copy to ..../Ghidra/Features/Search/ghidra_scripts/
|
// Copy to ..../Ghidra/Features/Search/ghidra_scripts/
|
||||||
// Writes the results to ~/Desktop/patches.txt
|
// Writes the results to ~/Desktop/patches.txt
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user