mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 14:43:22 +00:00
Compare commits
186 Commits
Author | SHA1 | Date | |
---|---|---|---|
9fd950b0c0 | |||
b0839ffcaf | |||
3f065ea70a | |||
d869913efa | |||
6a246516df | |||
daab85f3f1 | |||
97ed8c2877 | |||
dca144fbff | |||
ab9bd37b86 | |||
d4071b0fe4 | |||
5a0a33e52a | |||
c510ba6863 | |||
bd4c9a5eab | |||
f9e85817ad | |||
8758be3630 | |||
31a7ff2ba2 | |||
1db3b81d2e | |||
0a16ea7487 | |||
7d3530a22e | |||
a87ea96913 | |||
81609a0f42 | |||
938edab25f | |||
29c9870658 | |||
b6c4f3775a | |||
5ee5564ae2 | |||
ab36756061 | |||
831b8f35d5 | |||
0892a2245e | |||
622474e9e4 | |||
0cabc12f91 | |||
b282ce999d | |||
24b9d74e70 | |||
c03f2897d0 | |||
93c7cbd496 | |||
db60555c1b | |||
45117a3384 | |||
4d4880b428 | |||
ac6ccd53df | |||
4ec376bd6a | |||
3c0448305b | |||
a6029a10cc | |||
26eaf53a83 | |||
5d623a27ed | |||
69e554b941 | |||
7340374a7c | |||
67d356b73f | |||
da18f1f722 | |||
58abcceff5 | |||
2c3f761ede | |||
70c60cfba7 | |||
f3b6d64ad3 | |||
43e9a13921 | |||
526dbe8f16 | |||
951a0e5225 | |||
458b939bc4 | |||
476aca5b67 | |||
96bf0f8323 | |||
58206a3180 | |||
f138ab8ac6 | |||
50839cf6e9 | |||
626a4434ed | |||
d84cc73d13 | |||
6b049536f1 | |||
1582aa9da2 | |||
e01307a993 | |||
beb9f95359 | |||
c49a4c7027 | |||
b08df87f5c | |||
72226d6f89 | |||
40adc34413 | |||
eeae114b76 | |||
48a862c503 | |||
29544e4d2b | |||
420a90ff75 | |||
45603367bf | |||
f7ea0f569f | |||
2bf92848ff | |||
ad65cfb400 | |||
5ffc8c7076 | |||
8943ba0249 | |||
b02adf6b3f | |||
6ef5d7c135 | |||
9ece2e3f2c | |||
4b2cdaf47c | |||
9b5b71b61b | |||
59465bd249 | |||
ed50f37c79 | |||
a96bda82f9 | |||
1860f6e594 | |||
c9ad3acc9b | |||
93c7a42453 | |||
ee07fc9f6d | |||
443edcd771 | |||
6650ef4274 | |||
b85174fc8d | |||
08f6d59f50 | |||
2ed2ac80bc | |||
2300088446 | |||
306a917956 | |||
0ea53ea5b5 | |||
092260e9f9 | |||
52e19d35fa | |||
bf17953353 | |||
e46fac6063 | |||
6062668679 | |||
acc178e5dd | |||
31adb57fd7 | |||
7652406c12 | |||
a607adb7a3 | |||
036a79268b | |||
335b2d4542 | |||
603136efa0 | |||
1e01ccc8fd | |||
9f6d27ddce | |||
8fcd404352 | |||
b2b887d04d | |||
849994dedd | |||
1286d1906f | |||
fae760fc9e | |||
01f442d810 | |||
eaedf2e62f | |||
07e0b39126 | |||
98238ed763 | |||
340d6aa97c | |||
5ae4a7ae02 | |||
80158de3e8 | |||
730713193a | |||
fea76dff23 | |||
808022d3e0 | |||
eee78077e2 | |||
ca91d3fbc0 | |||
ad4a776fc6 | |||
ebdb71aeb0 | |||
6dc58750cf | |||
1b84448be3 | |||
61ceef64b1 | |||
5404eef7be | |||
6fed799957 | |||
dd88069711 | |||
07bc202e0a | |||
f2b7357ff3 | |||
3cbaefd247 | |||
037a14f621 | |||
88e41f01c8 | |||
369fce9c85 | |||
eaf4a29930 | |||
48070e0148 | |||
c23bbddde9 | |||
038fef962c | |||
42c663e7c7 | |||
956fa95d77 | |||
ea0ea88ed3 | |||
e0e8645d6c | |||
a2100f32e0 | |||
25a6c2c006 | |||
7f8347b12e | |||
8e4bd0314e | |||
a7fd84e186 | |||
e405e721fa | |||
49d4fa4346 | |||
375aca2997 | |||
9f8eea5467 | |||
58aa181d01 | |||
f49e391022 | |||
698f1e272b | |||
023fc19ce0 | |||
40df85d1e6 | |||
47e7d243f7 | |||
6d209ce045 | |||
34a3060b0f | |||
c77709cdd9 | |||
27338fcef1 | |||
9fab7e892d | |||
dc151caa18 | |||
e1d7f4af35 | |||
d85722a4f6 | |||
ba3a039e45 | |||
bd13d32437 | |||
79080355ac | |||
e6eee685ce | |||
ceb7e44e6f | |||
d668010bed | |||
44a7696169 | |||
b0a912a838 | |||
4d493452a4 | |||
8fedf49984 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -99,10 +99,15 @@ unicorn_mode/samples/*/\.test-*
|
|||||||
utils/afl_network_proxy/afl-network-client
|
utils/afl_network_proxy/afl-network-client
|
||||||
utils/afl_network_proxy/afl-network-server
|
utils/afl_network_proxy/afl-network-server
|
||||||
utils/afl_proxy/afl-proxy
|
utils/afl_proxy/afl-proxy
|
||||||
|
utils/bench/hash
|
||||||
utils/optimin/build
|
utils/optimin/build
|
||||||
utils/optimin/optimin
|
utils/optimin/optimin
|
||||||
utils/persistent_mode/persistent_demo
|
utils/persistent_mode/persistent_demo
|
||||||
utils/persistent_mode/persistent_demo_new
|
utils/persistent_mode/persistent_demo_new
|
||||||
|
utils/persistent_mode/persistent_demo_new_compat
|
||||||
utils/persistent_mode/test-instr
|
utils/persistent_mode/test-instr
|
||||||
|
utils/replay_record/persistent_demo_replay
|
||||||
|
utils/replay_record/persistent_demo_replay_compat
|
||||||
|
utils/replay_record/persistent_demo_replay_argparse
|
||||||
utils/plot_ui/afl-plot-ui
|
utils/plot_ui/afl-plot-ui
|
||||||
vuln_prog
|
vuln_prog
|
||||||
|
@ -27,5 +27,5 @@ keywords:
|
|||||||
- qemu
|
- qemu
|
||||||
- llvm
|
- llvm
|
||||||
- unicorn-emulator
|
- unicorn-emulator
|
||||||
- securiy
|
- security
|
||||||
license: AGPL-3.0-or-later
|
license: AGPL-3.0-or-later
|
||||||
|
77
GNUmakefile
77
GNUmakefile
@ -52,7 +52,7 @@ endif
|
|||||||
ifdef ASAN_BUILD
|
ifdef ASAN_BUILD
|
||||||
$(info Compiling ASAN version of binaries)
|
$(info Compiling ASAN version of binaries)
|
||||||
override CFLAGS += $(ASAN_CFLAGS)
|
override CFLAGS += $(ASAN_CFLAGS)
|
||||||
LDFLAGS += $(ASAN_LDFLAGS)
|
override LDFLAGS += $(ASAN_LDFLAGS)
|
||||||
endif
|
endif
|
||||||
ifdef UBSAN_BUILD
|
ifdef UBSAN_BUILD
|
||||||
$(info Compiling UBSAN version of binaries)
|
$(info Compiling UBSAN version of binaries)
|
||||||
@ -84,38 +84,44 @@ else
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
ifdef PERFORMANCE
|
||||||
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
|
SPECIAL_PERFORMANCE := -D_AFL_SPECIAL_PERFORMANCE
|
||||||
#endif
|
ifeq "$(SYS)" "Linux"
|
||||||
|
ifeq "$(shell grep avx2 /proc/cpuinfo)" ""
|
||||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
else
|
||||||
# ifndef SOURCE_DATE_EPOCH
|
SPECIAL_PERFORMANCE += -mavx2 -D_HAVE_AVX2
|
||||||
# HAVE_MARCHNATIVE = 1
|
endif
|
||||||
# CFLAGS_OPT += -march=native
|
endif
|
||||||
# endif
|
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||||
#endif
|
HAVE_MARCHNATIVE = 1
|
||||||
|
SPECIAL_PERFORMANCE += -march=native
|
||||||
|
endif
|
||||||
|
$(info SPECIAL_PERFORMANCE=$(SPECIAL_PERFORMANCE))
|
||||||
|
else
|
||||||
|
SPECIAL_PERFORMANCE :=
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||||
# SPECIAL_PERFORMANCE += -march=native
|
# SPECIAL_PERFORMANCE += -march=native
|
||||||
#endif
|
#endif
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
# CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||||
LDFLAGS += $(SDK_LD)
|
override LDFLAGS += $(SDK_LD)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
||||||
ifneq "$(COMPILER_TYPE)" ""
|
ifneq "$(COMPILER_TYPE)" ""
|
||||||
#$(info gcc is being used)
|
#$(info gcc is being used)
|
||||||
CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(SYS)" "SunOS"
|
ifeq "$(SYS)" "SunOS"
|
||||||
LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
override LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef STATIC
|
ifdef STATIC
|
||||||
@ -125,8 +131,8 @@ ifdef STATIC
|
|||||||
PYFLAGS=
|
PYFLAGS=
|
||||||
PYTHON_INCLUDE = /
|
PYTHON_INCLUDE = /
|
||||||
|
|
||||||
CFLAGS_OPT += -static
|
override CFLAGS_OPT += -static
|
||||||
LDFLAGS += -lm -lpthread -lz -lutil
|
override LDFLAGS += -lm -lpthread -lz -lutil
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef PROFILING
|
ifdef PROFILING
|
||||||
@ -389,6 +395,7 @@ help:
|
|||||||
@echo
|
@echo
|
||||||
@echo Known build environment options:
|
@echo Known build environment options:
|
||||||
@echo "=========================================="
|
@echo "=========================================="
|
||||||
|
@echo "PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended!"
|
||||||
@echo STATIC - compile AFL++ static
|
@echo STATIC - compile AFL++ static
|
||||||
@echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
|
@echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
|
||||||
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
||||||
@ -453,31 +460,31 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
|||||||
@ln -sf afl-as as
|
@ln -sf afl-as as
|
||||||
|
|
||||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||||
|
|
||||||
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
|
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
|
||||||
|
|
||||||
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||||
|
|
||||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
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) $(SPECIAL_PERFORMANCE) -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 src/hashmap.c | 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) -lm
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||||
|
|
||||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c 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) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.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 src/afl-performance.o -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.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-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
.PHONY: document
|
.PHONY: document
|
||||||
document: afl-fuzz-document
|
document: afl-fuzz-document
|
||||||
@ -494,17 +501,17 @@ unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
|
|||||||
./test/unittests/unit_maybe_alloc
|
./test/unittests/unit_maybe_alloc
|
||||||
|
|
||||||
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||||
|
|
||||||
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
|
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
|
||||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
@$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||||
./test/unittests/unit_hash
|
./test/unittests/unit_hash
|
||||||
|
|
||||||
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||||
|
|
||||||
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
|
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
|
||||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||||
./test/unittests/unit_rand
|
./test/unittests/unit_rand
|
||||||
|
|
||||||
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
||||||
@ -752,7 +759,7 @@ endif
|
|||||||
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
|
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
|
||||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
|
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
|
||||||
ifneq "$(SYS)" "Darwin"
|
ifneq "$(SYS)" "Darwin"
|
||||||
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||||
endif
|
endif
|
||||||
ifeq "$(SYS)" "Linux"
|
ifeq "$(SYS)" "Linux"
|
||||||
ifndef NO_NYX
|
ifndef NO_NYX
|
||||||
|
@ -44,9 +44,9 @@ endif
|
|||||||
|
|
||||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
|
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
|
||||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
||||||
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
|
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
|
||||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
|
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
|
||||||
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 )
|
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
|
||||||
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
|
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
|
||||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
|
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
|
||||||
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
|
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||||
|
|
||||||
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||||
|
|
||||||
GitHub version: 4.10c
|
GitHub version: 4.21a
|
||||||
|
|
||||||
Repository:
|
Repository:
|
||||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||||
|
5
TODO.md
5
TODO.md
@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
## Must
|
## Must
|
||||||
|
|
||||||
- UI revamp
|
|
||||||
- hardened_usercopy=0 page_alloc.shuffle=0
|
- hardened_usercopy=0 page_alloc.shuffle=0
|
||||||
- add value_profile but only enable after 15 minutes without finds
|
- add value_profile but only enable after 15 minutes without finds
|
||||||
- cmplog max len, cmplog max items envs?
|
- cmplog max items env?
|
||||||
- adapt MOpt to new mutation engine
|
- adapt MOpt to new mutation engine
|
||||||
- Update afl->pending_not_fuzzed for MOpt
|
- Update afl->pending_not_fuzzed for MOpt
|
||||||
- cmplog rtn sanity check on fixed length? currently we ignore the length
|
- cmplog rtn sanity check on fixed length? currently we ignore the length
|
||||||
- afl-showmap -f support
|
- afl-showmap -f support
|
||||||
- afl-fuzz multicore wrapper script
|
- afl-fuzz multicore wrapper script
|
||||||
- when trimming then perform crash detection
|
- when trimming then perform crash detection
|
||||||
- problem: either -L0 and/or -p mmopt results in zero new coverage
|
- cyclomatic complexity: 2 + calls + edges - blocks
|
||||||
|
|
||||||
|
|
||||||
## Should
|
## Should
|
||||||
|
8
afl-cmin
8
afl-cmin
@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
|
|||||||
# awk script to minimize a test corpus of input files
|
# awk script to minimize a test corpus of input files
|
||||||
#
|
#
|
||||||
# based on afl-cmin bash script written by Michal Zalewski
|
# based on afl-cmin bash script written by Michal Zalewski
|
||||||
# rewritten by Heiko Eißfeldt (hexcoder-)
|
# rewritten by Heiko Eissfeldt (hexcoder-)
|
||||||
# tested with:
|
# tested with:
|
||||||
# gnu awk (x86 Linux)
|
# gnu awk (x86 Linux)
|
||||||
# bsd awk (x86 *BSD)
|
# bsd awk (x86 *BSD)
|
||||||
@ -108,7 +108,7 @@ function usage() {
|
|||||||
"\n" \
|
"\n" \
|
||||||
"Execution control settings:\n" \
|
"Execution control settings:\n" \
|
||||||
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
|
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
|
||||||
" -f file - location read by the fuzzed program (stdin)\n" \
|
" -f file - location read by the fuzzed program (default: stdin)\n" \
|
||||||
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
||||||
" -t msec - run time limit for child process (default: 5000)\n" \
|
" -t msec - run time limit for child process (default: 5000)\n" \
|
||||||
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
||||||
@ -603,8 +603,8 @@ BEGIN {
|
|||||||
# create path for the trace file from afl-showmap
|
# create path for the trace file from afl-showmap
|
||||||
tracefile_path = trace_dir"/"fn
|
tracefile_path = trace_dir"/"fn
|
||||||
# ensure the file size is not zero
|
# ensure the file size is not zero
|
||||||
cmd = "du -b "tracefile_path
|
cmd = "du -b \""tracefile_path"\""
|
||||||
"ls -l "tracefile_path
|
# "ls -l \""tracefile_path"\""
|
||||||
cmd | getline output
|
cmd | getline output
|
||||||
close(cmd)
|
close(cmd)
|
||||||
split(output, result, "\t")
|
split(output, result, "\t")
|
||||||
|
@ -152,6 +152,7 @@ Minimization settings:
|
|||||||
-e - solve for edge coverage only, ignore hit counts
|
-e - solve for edge coverage only, ignore hit counts
|
||||||
|
|
||||||
For additional tips, please consult README.md.
|
For additional tips, please consult README.md.
|
||||||
|
This script cannot read filenames that end with a space ' '.
|
||||||
|
|
||||||
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
|
||||||
|
@ -124,17 +124,26 @@ kernel.sched_latency_ns=250000000
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
|
grub_try_disable_mitigation () {
|
||||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
|
KEY="$1"
|
||||||
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
|
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
|
||||||
echo "Configuring performance boot options"
|
echo "Configuring performance boot options"
|
||||||
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
|
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
|
||||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||||
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
|
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
|
||||||
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
|
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
|
||||||
}
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if grep -E -q '^GRUB_CMDLINE_LINUX=' /etc/default/grub || grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub; then
|
||||||
|
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX_DEFAULT"
|
||||||
|
# We also overwrite GRUB_CMDLINE_LINUX because some distributions already overwrite GRUB_CMDLINE_LINUX_DEFAULT
|
||||||
|
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX"
|
||||||
|
else
|
||||||
|
echo "Error: /etc/default/grub with GRUB_CMDLINE_LINUX is not present, cannot set boot options"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Reboot and enjoy your fuzzing"
|
echo "Reboot and enjoy your fuzzing"
|
||||||
exit 0
|
exit 0
|
||||||
|
50
afl-whatsup
50
afl-whatsup
@ -111,9 +111,16 @@ if [ -z "$NO_COLOR" ]; then
|
|||||||
RESET="$NC"
|
RESET="$NC"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CUR_TIME=`date +%s`
|
PLATFORM=`uname -s`
|
||||||
|
if [ "$PLATFORM" = "Linux" ] ; then
|
||||||
|
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
|
||||||
|
else
|
||||||
|
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
|
||||||
|
CUR_TIME=`date +%s`
|
||||||
|
fi
|
||||||
|
|
||||||
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
||||||
|
trap "rm -f $TMP" 1 2 3 13 15
|
||||||
|
|
||||||
ALIVE_CNT=0
|
ALIVE_CNT=0
|
||||||
DEAD_CNT=0
|
DEAD_CNT=0
|
||||||
@ -122,6 +129,7 @@ START_CNT=0
|
|||||||
TOTAL_TIME=0
|
TOTAL_TIME=0
|
||||||
TOTAL_EXECS=0
|
TOTAL_EXECS=0
|
||||||
TOTAL_EPS=0
|
TOTAL_EPS=0
|
||||||
|
TOTAL_EPLM=0
|
||||||
TOTAL_CRASHES=0
|
TOTAL_CRASHES=0
|
||||||
TOTAL_HANGS=0
|
TOTAL_HANGS=0
|
||||||
TOTAL_PFAV=0
|
TOTAL_PFAV=0
|
||||||
@ -181,6 +189,8 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
|||||||
|
|
||||||
if [ -f "$i" ]; then
|
if [ -f "$i" ]; then
|
||||||
|
|
||||||
|
IS_STARTING=
|
||||||
|
IS_DEAD=
|
||||||
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
|
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
|
||||||
. "$TMP"
|
. "$TMP"
|
||||||
DIRECTORY=$DIR
|
DIRECTORY=$DIR
|
||||||
@ -211,9 +221,6 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
|||||||
|
|
||||||
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
|
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
|
||||||
|
|
||||||
IS_STARTING=
|
|
||||||
IS_DEAD=
|
|
||||||
|
|
||||||
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
|
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
|
||||||
|
|
||||||
if [ "$i" -ot "$j" ]; then
|
if [ "$i" -ot "$j" ]; then
|
||||||
@ -272,11 +279,15 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
|||||||
ALIVE_CNT=$((ALIVE_CNT + 1))
|
ALIVE_CNT=$((ALIVE_CNT + 1))
|
||||||
|
|
||||||
EXEC_SEC=0
|
EXEC_SEC=0
|
||||||
|
EXEC_MIN=0
|
||||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||||
PATH_PERC=$((cur_item * 100 / corpus_count))
|
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||||
|
|
||||||
|
test "$IS_DEAD" = 1 || EXEC_MIN=$(echo $execs_ps_last_min|sed 's/\..*//')
|
||||||
|
|
||||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||||
|
TOTAL_EPLM=$((TOTAL_EPLM + EXEC_MIN))
|
||||||
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
||||||
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
||||||
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
|
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
|
||||||
@ -398,41 +409,44 @@ if [ -z "$SUMMARY_ONLY" -o -z "$MINIMAL_ONLY" ]; then
|
|||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Fuzzers alive : $ALIVE_CNT"
|
echo " Fuzzers alive : $ALIVE_CNT"
|
||||||
|
|
||||||
if [ ! "$START_CNT" = "0" ]; then
|
if [ ! "$START_CNT" = "0" ]; then
|
||||||
echo " Starting up : $START_CNT ($TXT)"
|
echo " Starting up : $START_CNT ($TXT)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! "$DEAD_CNT" = "0" ]; then
|
if [ ! "$DEAD_CNT" = "0" ]; then
|
||||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Total run time : $FMT_TIME"
|
echo " Total run time : $FMT_TIME"
|
||||||
if [ -z "$MINIMAL_ONLY" ]; then
|
if [ -z "$MINIMAL_ONLY" ]; then
|
||||||
echo " Total execs : $FMT_EXECS"
|
echo " Total execs : $FMT_EXECS"
|
||||||
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||||
|
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||||
|
echo " Total average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
echo "Current average speed : $TOTAL_EPLM execs/sec"
|
||||||
fi
|
fi
|
||||||
if [ -z "$MINIMAL_ONLY" ]; then
|
if [ -z "$MINIMAL_ONLY" ]; then
|
||||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then
|
if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then
|
||||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
||||||
echo " Crashes saved : $TOTAL_CRASHES"
|
echo " Crashes saved : $TOTAL_CRASHES"
|
||||||
if [ -z "$MINIMAL_ONLY" ]; then
|
if [ -z "$MINIMAL_ONLY" ]; then
|
||||||
echo " Hangs saved : $TOTAL_HANGS"
|
echo " Hangs saved : $TOTAL_HANGS"
|
||||||
echo "Cycles without finds : $TOTAL_WCOP"
|
echo " Cycles without finds : $TOTAL_WCOP"
|
||||||
fi
|
fi
|
||||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
|CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
||||||
====================================================|=======|=========|============|===========|==============|
|
|----------------------------------------------------|-------|---------|------------|-----------|--------------|
|
||||||
Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
|Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
||||||
AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
|AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
||||||
AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
|AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
||||||
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
|Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
||||||
12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
|12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
||||||
AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
|AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
||||||
Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
|Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
||||||
|
|AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|
||||||
|
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|
||||||
|
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|
||||||
|
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|
||||||
|
@ -418,3 +418,7 @@
|
|||||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.08a", "comment": "", "compiler": "Ubuntu clang version 14.0.0-1ubuntu1.1", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 3700.0, "cpu_model": "AMD Ryzen 5 PRO 4650G with Radeon Graphics", "cpu_threads": 12}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 704840.16, "execs_total": 21163992, "fuzzers_used": 12}, "singlecore": {"execs_per_sec": 95356.14, "execs_total": 2862114, "fuzzers_used": 1}}}}
|
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.08a", "comment": "", "compiler": "Ubuntu clang version 14.0.0-1ubuntu1.1", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 3700.0, "cpu_model": "AMD Ryzen 5 PRO 4650G with Radeon Graphics", "cpu_threads": 12}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 704840.16, "execs_total": 21163992, "fuzzers_used": 12}, "singlecore": {"execs_per_sec": 95356.14, "execs_total": 2862114, "fuzzers_used": 1}}}}
|
||||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.09a", "comment": "", "compiler": "Debian clang version 14.0.6", "target_arch": "aarch64-unknown-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 2400.0, "cpu_model": "Raspberry Pi 5", "cpu_threads": 4}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 101114.23, "execs_total": 3036637, "fuzzers_used": 4}, "singlecore": {"execs_per_sec": 25786.11, "execs_total": 774460, "fuzzers_used": 1}}}}
|
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.09a", "comment": "", "compiler": "Debian clang version 14.0.6", "target_arch": "aarch64-unknown-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 2400.0, "cpu_model": "Raspberry Pi 5", "cpu_threads": 4}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 101114.23, "execs_total": 3036637, "fuzzers_used": 4}, "singlecore": {"execs_per_sec": 25786.11, "execs_total": 774460, "fuzzers_used": 1}}}}
|
||||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.07a", "comment": "", "compiler": "Debian clang version 17.0.0 (++20230417071830+ae77aceba5ad-1~exp1~20230417071935.630)", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4792.073, "cpu_model": "AMD Ryzen 9 5950X 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2339762.91, "execs_total": 70253164, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161690.07, "execs_total": 4851838, "fuzzers_used": 1}}}}
|
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.07a", "comment": "", "compiler": "Debian clang version 17.0.0 (++20230417071830+ae77aceba5ad-1~exp1~20230417071935.630)", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4792.073, "cpu_model": "AMD Ryzen 9 5950X 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2339762.91, "execs_total": 70253164, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161690.07, "execs_total": 4851838, "fuzzers_used": 1}}}}
|
||||||
|
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4675.949, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 614403.91, "execs_total": 18435083, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 62859.9, "execs_total": 1886111, "fuzzers_used": 1}}}}
|
||||||
|
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4744.522, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 991132.96, "execs_total": 29737588, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 135501.07, "execs_total": 4066116, "fuzzers_used": 1}}}}
|
||||||
|
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "Ubuntu clang version 14.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5399.822, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 1566279.42, "execs_total": 46994452, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 71565.56, "execs_total": 2147396, "fuzzers_used": 1}}}}
|
||||||
|
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5478.258, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2173959.15, "execs_total": 65229513, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161960.29, "execs_total": 4859457, "fuzzers_used": 1}}}}
|
||||||
|
@ -205,7 +205,7 @@ async def save_benchmark_results() -> None:
|
|||||||
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
|
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
|
||||||
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
|
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
|
||||||
cores = str(args.fuzzers).ljust(7)
|
cores = str(args.fuzzers).ljust(7)
|
||||||
comparisonfile.write(f"{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
comparisonfile.write(f"|{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
||||||
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
|
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
|
||||||
with open("COMPARISON.md", "r") as comparisonfile:
|
with open("COMPARISON.md", "r") as comparisonfile:
|
||||||
print(comparisonfile.read())
|
print(comparisonfile.read())
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "afl-fuzz.h"
|
||||||
#include "afl-mutations.h"
|
#include "afl-mutations.h"
|
||||||
|
|
||||||
typedef struct my_mutator {
|
typedef struct my_mutator {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
#include "afl-fuzz.h"
|
||||||
#include "afl-mutations.h"
|
#include "afl-mutations.h"
|
||||||
|
|
||||||
s8 interesting_8[] = {INTERESTING_8};
|
|
||||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
|
||||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
|
||||||
|
|
||||||
typedef struct my_mutator {
|
typedef struct my_mutator {
|
||||||
|
|
||||||
afl_state_t *afl;
|
afl_state_t *afl;
|
||||||
@ -155,7 +152,7 @@ int main(int argc, char *argv[]) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) fprintf(stderr, "Mutation output length: %zu\n", outlen);
|
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||||
|
|
||||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||||
fprintf(stderr, "Warning: incomplete write.\n");
|
fprintf(stderr, "Warning: incomplete write.\n");
|
||||||
|
@ -3,6 +3,65 @@
|
|||||||
This is the list of all noteworthy changes made in every public
|
This is the list of all noteworthy changes made in every public
|
||||||
release of the tool. See README.md for the general instruction manual.
|
release of the tool. See README.md for the general instruction manual.
|
||||||
|
|
||||||
|
### Version ++4.21a (dev)
|
||||||
|
* afl-fuzz
|
||||||
|
- added AFL_DISABLE_REDUNDANT for huge queues
|
||||||
|
- fix AFL_PERSISTENT_RECORD
|
||||||
|
- run custom_post_process after standard trimming
|
||||||
|
- prevent filenames in the queue that have spaces
|
||||||
|
- minor fix for FAST schedules
|
||||||
|
- more frequent stats update when syncing (todo: check performance impact)
|
||||||
|
* afl-cc:
|
||||||
|
- re-enable i386 support that was accidently disabled
|
||||||
|
- fixes for LTO and outdated afl-gcc mode
|
||||||
|
- fix COMPCOV split compare for old LLVMs
|
||||||
|
- disable xml/curl/g_ string transform functions because we do not check
|
||||||
|
for null pointers ... TODO
|
||||||
|
- ensure shared memory variables are visible in weird build setups
|
||||||
|
* afl-cmin
|
||||||
|
- work with input files that have a space
|
||||||
|
* enhanced the ASAN configuration
|
||||||
|
|
||||||
|
|
||||||
|
### Version ++4.20c (release)
|
||||||
|
! A new forkserver communication model is now introduced. afl-fuzz is
|
||||||
|
backward compatible to old compiled targets if they are not built
|
||||||
|
for CMPLOG/Redqueen, but new compiled targets will not work with
|
||||||
|
old afl-fuzz versions!
|
||||||
|
! Recompile all targets that are instrumented for CMPLOG/Redqueen!
|
||||||
|
- AFL++ now supports up to 4 billion coverage edges, up from 6 million.
|
||||||
|
- New compile option: `make PERFORMANCE=1` - this will enable special
|
||||||
|
CPU dependent optimizations that make everything more performant - but
|
||||||
|
the binaries will likely won't work on different platforms. Also
|
||||||
|
enables a faster hasher if the CPU requirements are met.
|
||||||
|
- The persistent record feature (see config.h) was expanded to also
|
||||||
|
support replay, thanks to @quarta-qti !
|
||||||
|
- afl-fuzz:
|
||||||
|
- the new deterministic fuzzing feature is now activated by default,
|
||||||
|
deactivate with -z. Parameters -d and -D are ignored.
|
||||||
|
- small improvements to CMPLOG/redqueen
|
||||||
|
- workround for a bug with MOpt -L when used with -M - in the future
|
||||||
|
we will either remove or rewrite MOpt.
|
||||||
|
- fix for `-t xxx+` feature
|
||||||
|
- -e extension option now saves the queue items, crashes, etc. with the
|
||||||
|
extension too
|
||||||
|
- fixes for trimmming, correct -V time and reading stats on resume by eqv
|
||||||
|
thanks a lot!
|
||||||
|
- afl-cc:
|
||||||
|
- added collision free caller instrumentation to LTO mode. activate with
|
||||||
|
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
|
||||||
|
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
|
||||||
|
- fixes for COMPCOV/LAF and most other modules
|
||||||
|
- fix for GCC_PLUGIN cmplog that broke on std::strings
|
||||||
|
- afl-whatsup:
|
||||||
|
- now also displays current average speed
|
||||||
|
- small bugfixes
|
||||||
|
- Fixes for aflpp custom mutator and standalone tool
|
||||||
|
- Minor edits to afl-persistent-config
|
||||||
|
- Prevent temporary files being left behind on aborted afl-whatsup
|
||||||
|
- More CPU benchmarks added to benchmark/
|
||||||
|
|
||||||
|
|
||||||
### Version ++4.10c (release)
|
### Version ++4.10c (release)
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
- default power schedule is now EXPLORE, due a fix in fast schedules
|
- default power schedule is now EXPLORE, due a fix in fast schedules
|
||||||
|
126
docs/INSTALL.md
126
docs/INSTALL.md
@ -21,7 +21,7 @@ If you want to build AFL++ yourself, you have many options. The easiest choice
|
|||||||
is to build and install everything:
|
is to build and install everything:
|
||||||
|
|
||||||
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
|
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
|
||||||
whatever llvm version is available. We recommend llvm 13, 14, 15 or 16.
|
whatever llvm version is available. We recommend llvm 13 or newer.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
@ -67,19 +67,20 @@ These build targets exist:
|
|||||||
* unit: perform unit tests (based on cmocka)
|
* unit: perform unit tests (based on cmocka)
|
||||||
* help: shows these build options
|
* help: shows these build options
|
||||||
|
|
||||||
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
[Unless you are on macOS](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
||||||
you can also build statically linked versions of the AFL++ binaries by passing
|
you can also build statically linked versions of the AFL++ binaries by passing
|
||||||
the `STATIC=1` argument to make:
|
the `PERFORMANCE=1` argument to make:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
make STATIC=1
|
make PERFORMANCE=1
|
||||||
```
|
```
|
||||||
|
|
||||||
These build options exist:
|
These build options exist:
|
||||||
|
|
||||||
* STATIC - compile AFL++ static
|
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended (except on macOS)!
|
||||||
* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
|
* STATIC - compile AFL++ static (does not work on macOS)
|
||||||
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
* CODE_COVERAGE - compile the target for code coverage (see [README.llvm.md](../instrumentation/README.llvm.md))
|
||||||
|
* ASAN_BUILD - compiles AFL++ with address sanitizer for debug purposes
|
||||||
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
|
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
|
||||||
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||||
* LLVM_DEBUG - shows llvm deprecation warnings
|
* LLVM_DEBUG - shows llvm deprecation warnings
|
||||||
@ -91,101 +92,78 @@ These build options exist:
|
|||||||
* NO_NYX - disable building nyx mode dependencies
|
* NO_NYX - disable building nyx mode dependencies
|
||||||
* NO_CORESIGHT - disable building coresight (arm64 only)
|
* NO_CORESIGHT - disable building coresight (arm64 only)
|
||||||
* NO_UNICORN_ARM64 - disable building unicorn on arm64
|
* NO_UNICORN_ARM64 - disable building unicorn on arm64
|
||||||
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
* AFL_NO_X86 - if compiling on non-Intel/AMD platforms
|
||||||
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
|
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
|
||||||
|
|
||||||
e.g.: `make LLVM_CONFIG=llvm-config-14`
|
e.g.: `make LLVM_CONFIG=llvm-config-14`
|
||||||
|
|
||||||
## MacOS X on x86 and arm64 (M1)
|
## macOS on x86_64 and arm64
|
||||||
|
|
||||||
MacOS has some gotchas due to the idiosyncrasies of the platform.
|
macOS has some gotchas due to the idiosyncrasies of the platform.
|
||||||
|
|
||||||
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
macOS supports SYSV shared memory used by AFL++'s instrumentation, but the
|
||||||
instructions for Linux. If possible, avoid Xcode at all cost.
|
default settings aren't sufficient. Before even building, increase
|
||||||
|
them by running the provided script:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo afl-system-config
|
||||||
|
```
|
||||||
|
|
||||||
|
See
|
||||||
|
[https://www.spy-hill.com/help/apple/SharedMemory.html](https://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||||
|
for documentation for the shared memory settings and how to make them permanent.
|
||||||
|
|
||||||
|
Next, to build AFL++, install the following packages from brew:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
brew install wget git make cmake llvm gdb coreutils
|
brew install wget git make cmake llvm gdb coreutils
|
||||||
```
|
```
|
||||||
|
|
||||||
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
Depending on your macOS system + brew version, brew may be installed in different places.
|
||||||
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
|
You can check with `brew info llvm` to know where, then create a variable for it:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Depending on your MacOS system + brew version it is either
|
export HOMEBREW_BASE="/opt/homebrew/opt"
|
||||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
```
|
||||||
# or
|
|
||||||
export PATH="/usr/local/opt/llvm/bin:/usr/local/opt/coreutils/libexec/gnubin:$PATH"
|
|
||||||
# you can check with "brew info llvm"
|
|
||||||
|
|
||||||
export PATH="/usr/local/bin:$PATH"
|
or
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export HOMEBREW_BASE="/usr/local/opt"
|
||||||
|
```
|
||||||
|
|
||||||
|
Set `PATH` to point to the brew clang, clang++, llvm-config, gmake and coreutils.
|
||||||
|
Also use the brew clang compiler; the Xcode clang compiler must not be used.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export PATH="$HOMEBREW_BASE/coreutils/libexec/gnubin:/usr/local/bin:$HOMEBREW_BASE/llvm/bin:$PATH"
|
||||||
export CC=clang
|
export CC=clang
|
||||||
export CXX=clang++
|
export CXX=clang++
|
||||||
gmake
|
|
||||||
cd frida_mode
|
|
||||||
gmake
|
|
||||||
cd ..
|
|
||||||
sudo gmake install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
Then build following the general Linux instructions.
|
||||||
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
|
|
||||||
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
|
|
||||||
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
|
||||||
|
|
||||||
The crash reporting daemon that comes by default with MacOS X will cause
|
If everything worked, you should then have `afl-clang-fast` installed, which you can check with:
|
||||||
problems with fuzzing. You need to turn it off:
|
|
||||||
|
|
||||||
```
|
```shell
|
||||||
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
|
which afl-clang-fast
|
||||||
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `fork()` semantics on OS X are a bit unusual compared to other unix systems
|
Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
|
||||||
|
|
||||||
|
The crash reporting daemon that comes by default with macOS will cause
|
||||||
|
problems with fuzzing. You need to turn it off, which you can do with `afl-system-config`.
|
||||||
|
|
||||||
|
The `fork()` semantics on macOS are a bit unusual compared to other unix systems
|
||||||
and definitely don't look POSIX-compliant. This means two things:
|
and definitely don't look POSIX-compliant. This means two things:
|
||||||
|
|
||||||
- Fuzzing will be probably slower than on Linux. In fact, some folks report
|
- Fuzzing will be probably slower than on Linux. In fact, some folks report
|
||||||
considerable performance gains by running the jobs inside a Linux VM on
|
considerable performance gains by running the jobs inside a Linux VM on
|
||||||
MacOS X.
|
macOS.
|
||||||
- Some non-portable, platform-specific code may be incompatible with the AFL++
|
- Some non-portable, platform-specific code may be incompatible with the AFL++
|
||||||
forkserver. If you run into any problems, set `AFL_NO_FORKSRV=1` in the
|
forkserver. If you run into any problems, set `AFL_NO_FORKSRV=1` in the
|
||||||
environment before starting afl-fuzz.
|
environment before starting afl-fuzz.
|
||||||
|
|
||||||
User emulation mode of QEMU does not appear to be supported on MacOS X, so
|
User emulation mode of QEMU does not appear to be supported on macOS, so
|
||||||
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
|
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
|
||||||
works on both x86 and arm64 MacOS boxes.
|
works on both x86 and arm64 macOS boxes.
|
||||||
|
|
||||||
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
|
|
||||||
default settings aren't usable with AFL++. The default settings on 10.14 seem to
|
|
||||||
be:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ ipcs -M
|
|
||||||
IPC status from <running system> as of XXX
|
|
||||||
shminfo:
|
|
||||||
shmmax: 4194304 (max shared memory segment size)
|
|
||||||
shmmin: 1 (min shared memory segment size)
|
|
||||||
shmmni: 32 (max number of shared memory identifiers)
|
|
||||||
shmseg: 8 (max shared memory segments per process)
|
|
||||||
shmall: 1024 (max amount of shared memory in pages)
|
|
||||||
```
|
|
||||||
|
|
||||||
To temporarily change your settings to something minimally usable with AFL++,
|
|
||||||
run these commands as root:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sysctl kern.sysv.shmmax=8388608
|
|
||||||
sysctl kern.sysv.shmall=4096
|
|
||||||
```
|
|
||||||
|
|
||||||
If you're running more than one instance of AFL, you likely want to make
|
|
||||||
`shmall` bigger and increase `shmseg` as well:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sysctl kern.sysv.shmmax=8388608
|
|
||||||
sysctl kern.sysv.shmseg=48
|
|
||||||
sysctl kern.sysv.shmall=98304
|
|
||||||
```
|
|
||||||
|
|
||||||
See
|
|
||||||
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
|
||||||
for documentation for these settings and how to make them permanent.
|
|
||||||
|
@ -266,6 +266,11 @@ trimmed input. Here's a quick API description:
|
|||||||
Omitting any of three trimming methods will cause the trimming to be disabled
|
Omitting any of three trimming methods will cause the trimming to be disabled
|
||||||
and trigger a fallback to the built-in default trimming routine.
|
and trigger a fallback to the built-in default trimming routine.
|
||||||
|
|
||||||
|
**IMPORTANT** If you have a custom post process mutator that needs to be run
|
||||||
|
after trimming, you must call it yourself at the end of your successful
|
||||||
|
trimming!
|
||||||
|
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
Optionally, the following environment variables are supported:
|
Optionally, the following environment variables are supported:
|
||||||
|
@ -248,6 +248,9 @@ use (which only ever the author of this LTO implementation will use). These are
|
|||||||
used if several separated instrumentations are performed which are then later
|
used if several separated instrumentations are performed which are then later
|
||||||
combined.
|
combined.
|
||||||
|
|
||||||
|
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
|
||||||
|
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
|
||||||
|
to dig deeper into a real function. Default 0.
|
||||||
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
||||||
to which function. This helps to identify functions with variable bytes or
|
to which function. This helps to identify functions with variable bytes or
|
||||||
which functions were touched by an input.
|
which functions were touched by an input.
|
||||||
@ -378,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
|
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
|
||||||
usually a bad idea!
|
usually a bad idea!
|
||||||
|
|
||||||
|
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
|
||||||
|
This can be useful with huge queues.
|
||||||
|
|
||||||
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
|
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
|
||||||
new coverage
|
new coverage
|
||||||
|
|
||||||
@ -544,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
|
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
|
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
|
||||||
|
of their contents, rather than use the standard `id:000000,...` names.
|
||||||
|
|
||||||
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
|
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
|
||||||
by some users for unorthodox parallelized fuzzing setups, but not advisable
|
by some users for unorthodox parallelized fuzzing setups, but not advisable
|
||||||
otherwise.
|
otherwise.
|
||||||
|
@ -958,7 +958,7 @@ too long for your overall available fuzz run time.
|
|||||||
campaign but not good for short CI runs.
|
campaign but not good for short CI runs.
|
||||||
|
|
||||||
How this can look like can, e.g., be seen at AFL++'s setup in Google's
|
How this can look like can, e.g., be seen at AFL++'s setup in Google's
|
||||||
[oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
|
[previous oss-fuzz version](https://github.com/google/oss-fuzz/blob/3e2c5312417d1a6f9564472f3df1fd27759b289d/infra/base-images/base-builder/compile_afl)
|
||||||
and
|
and
|
||||||
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).
|
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).
|
||||||
|
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST
|
* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST
|
||||||
* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM
|
* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM
|
||||||
|
|
||||||
|
## Starting multiple AFL++ instances in parallel with recommended settings:
|
||||||
|
* [https://github.com/0xricksanchez/AFL_Runner](https://github.com/0xricksanchez/AFL_Runner)
|
||||||
|
* [https://github.com/MegaManSec/AFLplusplus-Parallel-Gen](https://github.com/MegaManSec/AFLplusplus-Parallel-Gen)
|
||||||
|
|
||||||
## Speeding up fuzzing
|
## Speeding up fuzzing
|
||||||
|
|
||||||
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
|
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
|
||||||
|
@ -21,6 +21,9 @@ training, then we can highly recommend the following:
|
|||||||
|
|
||||||
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
|
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
|
||||||
|
|
||||||
|
A good workflow overview (like our [fuzzing_in_depth.md](fuzzing_in_depth.md)):
|
||||||
|
* [https://appsec.guide/docs/fuzzing/c-cpp/aflpp/](https://appsec.guide/docs/fuzzing/c-cpp/aflpp/)
|
||||||
|
|
||||||
Here is a good workflow description (and tutorial) for qemu_mode:
|
Here is a good workflow description (and tutorial) for qemu_mode:
|
||||||
|
|
||||||
* [https://airbus-seclab.github.io/AFLplusplus-blogpost/](https://airbus-seclab.github.io/AFLplusplus-blogpost/)
|
* [https://airbus-seclab.github.io/AFLplusplus-blogpost/](https://airbus-seclab.github.io/AFLplusplus-blogpost/)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
|
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
|
||||||
|
|
||||||
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
|
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
|
||||||
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep -E 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
|
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep 'Frida\ [0-9.]*'|head -n 1|sed 's/.*Frida\ //'| sed 's/<\/h2>//')
|
||||||
|
|
||||||
echo Current set version: $OLD
|
echo Current set version: $OLD
|
||||||
echo Newest available version: $NEW
|
echo Newest available version: $NEW
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Dominik Maier <mail@dmnk.co>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||||
Dominik Maier <mail@dmnk.co>
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||||
@ -124,6 +124,10 @@
|
|||||||
#define CASE_PREFIX "id_"
|
#define CASE_PREFIX "id_"
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
#define RECORD_PREFIX "RECORD:"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */
|
#define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */
|
||||||
|
|
||||||
// Little helper to access the ptr to afl->##name_buf - for use in afl_realloc.
|
// Little helper to access the ptr to afl->##name_buf - for use in afl_realloc.
|
||||||
@ -196,6 +200,7 @@ 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 */
|
||||||
u32 id; /* entry number in queue_buf */
|
u32 id; /* entry number in queue_buf */
|
||||||
|
u32 found;
|
||||||
|
|
||||||
u8 colorized, /* Do not run redqueen stage again */
|
u8 colorized, /* Do not run redqueen stage again */
|
||||||
cal_failed; /* Calibration failed? */
|
cal_failed; /* Calibration failed? */
|
||||||
@ -247,6 +252,9 @@ struct queue_entry {
|
|||||||
|
|
||||||
struct skipdet_entry *skipdet_e;
|
struct skipdet_entry *skipdet_e;
|
||||||
|
|
||||||
|
u32 score; /* complexity/vulnerability score */
|
||||||
|
u64 total_execs; /* total executes of this item */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct extra_data {
|
struct extra_data {
|
||||||
@ -448,7 +456,8 @@ typedef struct afl_env_vars {
|
|||||||
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
|
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
|
||||||
afl_no_startup_calibration, afl_no_warn_instability,
|
afl_no_startup_calibration, afl_no_warn_instability,
|
||||||
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
|
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
|
||||||
afl_final_sync, afl_ignore_seed_problems;
|
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
|
||||||
|
afl_sha1_filenames;
|
||||||
|
|
||||||
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_preload,
|
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
|
||||||
@ -644,7 +653,10 @@ typedef struct afl_state {
|
|||||||
longest_find_time, /* Longest time taken for a find */
|
longest_find_time, /* Longest time taken for a find */
|
||||||
exit_on_time, /* Delay to exit if no new paths */
|
exit_on_time, /* Delay to exit if no new paths */
|
||||||
sync_time, /* Sync time (ms) */
|
sync_time, /* Sync time (ms) */
|
||||||
switch_fuzz_mode; /* auto or fixed fuzz mode */
|
switch_fuzz_mode, /* auto or fixed fuzz mode */
|
||||||
|
calibration_time_us, /* Time spend on calibration */
|
||||||
|
sync_time_us, /* Time spend on sync */
|
||||||
|
trim_time_us; /* Time spend on trimming */
|
||||||
|
|
||||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||||
subseq_tmouts; /* Number of timeouts in a row */
|
subseq_tmouts; /* Number of timeouts in a row */
|
||||||
@ -824,6 +836,9 @@ typedef struct afl_state {
|
|||||||
/* How often did we evict from the cache (for statistics only) */
|
/* How often did we evict from the cache (for statistics only) */
|
||||||
u32 q_testcase_evictions;
|
u32 q_testcase_evictions;
|
||||||
|
|
||||||
|
/* current complexity/vulnerability score received */
|
||||||
|
u32 current_score;
|
||||||
|
|
||||||
/* Refs to each queue entry with cached testcase (for eviction, if cache_count
|
/* Refs to each queue entry with cached testcase (for eviction, if cache_count
|
||||||
* is too large) */
|
* is too large) */
|
||||||
struct queue_entry **q_testcase_cache;
|
struct queue_entry **q_testcase_cache;
|
||||||
@ -1211,6 +1226,10 @@ void show_stats_normal(afl_state_t *);
|
|||||||
void show_stats_pizza(afl_state_t *);
|
void show_stats_pizza(afl_state_t *);
|
||||||
void show_init_stats(afl_state_t *);
|
void show_init_stats(afl_state_t *);
|
||||||
|
|
||||||
|
void update_calibration_time(afl_state_t *afl, u64 *time);
|
||||||
|
void update_trim_time(afl_state_t *afl, u64 *time);
|
||||||
|
void update_sync_time(afl_state_t *afl, u64 *time);
|
||||||
|
|
||||||
/* StatsD */
|
/* StatsD */
|
||||||
|
|
||||||
void statsd_setup_format(afl_state_t *afl);
|
void statsd_setup_format(afl_state_t *afl);
|
||||||
@ -1393,6 +1412,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
|
|||||||
|
|
||||||
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
|
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
|
||||||
|
|
||||||
|
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
|
||||||
|
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
|
||||||
|
char *sha1_hex(const u8 *data, size_t len);
|
||||||
|
|
||||||
|
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
|
||||||
|
char *sha1_hex_for_file(const char *fname, u32 len);
|
||||||
|
|
||||||
|
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
|
||||||
|
* enabled. */
|
||||||
|
static inline int permissive_create(afl_state_t *afl, const char *fn) {
|
||||||
|
|
||||||
|
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||||
|
if (unlikely(fd < 0)) {
|
||||||
|
|
||||||
|
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
|
||||||
|
|
||||||
|
PFATAL("Unable to create '%s'", fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#if TESTCASE_CACHE == 1
|
#if TESTCASE_CACHE == 1
|
||||||
#error define of TESTCASE_CACHE must be zero or larger than 1
|
#error define of TESTCASE_CACHE must be zero or larger than 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,10 +30,13 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "afl-fuzz.h"
|
|
||||||
|
|
||||||
#define MUT_STRATEGY_ARRAY_SIZE 256
|
#define MUT_STRATEGY_ARRAY_SIZE 256
|
||||||
|
|
||||||
|
s8 interesting_8[] = {INTERESTING_8};
|
||||||
|
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||||
|
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
||||||
/* 00 */ MUT_FLIPBIT,
|
/* 00 */ MUT_FLIPBIT,
|
||||||
|
131
include/afl-persistent-replay.h
Normal file
131
include/afl-persistent-replay.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#ifndef _HAVE_PERSISTENT_REPLAY_H
|
||||||
|
#define _HAVE_PERSISTENT_REPLAY_H
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static unsigned short int is_replay_record;
|
||||||
|
static unsigned int replay_record;
|
||||||
|
static unsigned int replay_record_cnt;
|
||||||
|
static char replay_record_path[PATH_MAX];
|
||||||
|
static char *replay_record_dir;
|
||||||
|
static struct dirent **record_list;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
static char **record_arg = NULL;
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
|
||||||
|
static int select_files(const struct dirent *dirbuf) {
|
||||||
|
|
||||||
|
char fn[PATH_MAX];
|
||||||
|
|
||||||
|
if (dirbuf->d_name[0] == '.') {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record);
|
||||||
|
return !!strstr(dirbuf->d_name, fn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_files(const struct dirent **da, const struct dirent **db) {
|
||||||
|
|
||||||
|
unsigned int c1 = 0, c2 = 0;
|
||||||
|
|
||||||
|
sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1);
|
||||||
|
sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2);
|
||||||
|
|
||||||
|
return c1 - c2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor)) static void __afl_record_replay_destroy(void) {
|
||||||
|
|
||||||
|
for (int i = 0; i < replay_record_cnt; i++) {
|
||||||
|
|
||||||
|
free(record_list[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(record_list);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor)) static void __afl_record_replay_init(
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
int argc, char **argv
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
) {
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
char **argp;
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
/* caveat: if harness uses @@ and we don't pass it, it will regardless loop
|
||||||
|
* the number of iterations defined for AFL_LOOP (on the same file)*/
|
||||||
|
if (!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))) {
|
||||||
|
|
||||||
|
// printf("[warning] AFL_PERSISTENT_REPLAY not set.\n");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY"));
|
||||||
|
replay_record_dir = getenv("AFL_PERSISTENT_DIR");
|
||||||
|
|
||||||
|
if (!(stat(replay_record_dir, &sb) == 0 && S_ISDIR(sb.st_mode))) {
|
||||||
|
|
||||||
|
fprintf(stderr, "[error] Can't find the requested record directory!\n");
|
||||||
|
is_replay_record = 0;
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./",
|
||||||
|
&record_list, select_files, compare_files);
|
||||||
|
|
||||||
|
if (!replay_record_cnt) {
|
||||||
|
|
||||||
|
fprintf(stderr, "[error] Can't find the requested record!\n");
|
||||||
|
is_replay_record = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
argp = argv;
|
||||||
|
while (*argp) {
|
||||||
|
|
||||||
|
if (!strcmp(*argp, "@@")) {
|
||||||
|
|
||||||
|
record_arg = argp;
|
||||||
|
*record_arg = replay_record_path;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
++argp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _HAVE_PERSISTENT_REPLAY_H
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
67
include/afl-record-compat.h
Normal file
67
include/afl-record-compat.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef _HAVE_AFL_COMPAT_H
|
||||||
|
#define _HAVE_AFL_COMPAT_H
|
||||||
|
|
||||||
|
#include <afl-persistent-replay.h>
|
||||||
|
|
||||||
|
#define FUZZ_BUF_SIZE 1024000
|
||||||
|
|
||||||
|
// extern ssize_t read(int fildes, void *buf, size_t nbyte);
|
||||||
|
|
||||||
|
// extern int __afl_persistent_loop(unsigned int max_cnt);
|
||||||
|
// extern unsigned char fuzz_buf[];
|
||||||
|
|
||||||
|
#ifndef __AFL_HAVE_MANUAL_CONTROL
|
||||||
|
#define __AFL_HAVE_MANUAL_CONTROL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE))
|
||||||
|
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
|
||||||
|
#define __AFL_FUZZ_INIT() void sync(void);
|
||||||
|
#define __AFL_INIT() sync()
|
||||||
|
#define __AFL_LOOP(x) __afl_persistent_loop(x)
|
||||||
|
|
||||||
|
unsigned char fuzz_buf[FUZZ_BUF_SIZE];
|
||||||
|
|
||||||
|
int __afl_persistent_loop(unsigned int max_cnt) {
|
||||||
|
|
||||||
|
static unsigned int cycle_cnt = 1;
|
||||||
|
static unsigned short int inited = 0;
|
||||||
|
char tcase[PATH_MAX];
|
||||||
|
|
||||||
|
if (is_replay_record && cycle_cnt) {
|
||||||
|
|
||||||
|
if (!inited) {
|
||||||
|
|
||||||
|
cycle_cnt = replay_record_cnt;
|
||||||
|
inited = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tcase, PATH_MAX, "%s/%s",
|
||||||
|
replay_record_dir ? replay_record_dir : "./",
|
||||||
|
record_list[replay_record_cnt - cycle_cnt]->d_name);
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
if (record_arg) {
|
||||||
|
|
||||||
|
*record_arg = tcase;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
{
|
||||||
|
|
||||||
|
int fd = open(tcase, O_RDONLY);
|
||||||
|
dup2(fd, 0);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return cycle_cnt--;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _HAVE_AFL_COMPAT_H
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -38,18 +38,15 @@
|
|||||||
|
|
||||||
#define SHAPE_BYTES(x) (x + 1)
|
#define SHAPE_BYTES(x) (x + 1)
|
||||||
|
|
||||||
#define CMP_TYPE_INS 1
|
#define CMP_TYPE_INS 0
|
||||||
#define CMP_TYPE_RTN 2
|
#define CMP_TYPE_RTN 1
|
||||||
|
|
||||||
struct cmp_header {
|
struct cmp_header { // 16 bit = 2 bytes
|
||||||
|
|
||||||
unsigned hits : 24;
|
unsigned hits : 6; // up to 63 entries, we have CMP_MAP_H = 32
|
||||||
unsigned id : 24;
|
unsigned shape : 5; // 31+1 bytes max
|
||||||
unsigned shape : 5;
|
unsigned type : 1; // 2: cmp, rtn
|
||||||
unsigned type : 2;
|
unsigned attribute : 4; // 16 for arithmetic comparison types
|
||||||
unsigned attribute : 4;
|
|
||||||
unsigned overflow : 1;
|
|
||||||
unsigned reserved : 4;
|
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
@ -59,14 +56,17 @@ struct cmp_operands {
|
|||||||
u64 v1;
|
u64 v1;
|
||||||
u64 v0_128;
|
u64 v0_128;
|
||||||
u64 v1_128;
|
u64 v1_128;
|
||||||
|
u64 unused;
|
||||||
|
u8 unused1;
|
||||||
|
u8 unused2;
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct cmpfn_operands {
|
struct cmpfn_operands {
|
||||||
|
|
||||||
u8 v0[31];
|
u8 v0[32];
|
||||||
u8 v0_len;
|
u8 v0_len;
|
||||||
u8 v1[31];
|
u8 v1[32];
|
||||||
u8 v1_len;
|
u8 v1_len;
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
/* Version string: */
|
/* Version string: */
|
||||||
|
|
||||||
// c = release, a = volatile github dev, e = experimental branch
|
// c = release, a = volatile github dev, e = experimental branch
|
||||||
#define VERSION "++4.10c"
|
#define VERSION "++4.21a"
|
||||||
|
|
||||||
/******************************************************
|
/******************************************************
|
||||||
* *
|
* *
|
||||||
@ -97,6 +97,11 @@
|
|||||||
|
|
||||||
// #define AFL_PERSISTENT_RECORD
|
// #define AFL_PERSISTENT_RECORD
|
||||||
|
|
||||||
|
/* Adds support in compiler-rt to replay persistent records in @@-style
|
||||||
|
* harnesses */
|
||||||
|
|
||||||
|
// #define AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
|
||||||
/* console output colors: There are three ways to configure its behavior
|
/* console output colors: There are three ways to configure its behavior
|
||||||
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
|
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
|
||||||
* ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect
|
* ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect
|
||||||
@ -459,7 +464,7 @@
|
|||||||
/* Do not change this unless you really know what you are doing. */
|
/* Do not change this unless you really know what you are doing. */
|
||||||
|
|
||||||
#define MAP_SIZE (1U << MAP_SIZE_POW2)
|
#define MAP_SIZE (1U << MAP_SIZE_POW2)
|
||||||
#if MAP_SIZE <= 65536
|
#if MAP_SIZE <= 2097152
|
||||||
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
|
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
|
||||||
#else
|
#else
|
||||||
#define MAP_INITIAL_SIZE MAP_SIZE
|
#define MAP_INITIAL_SIZE MAP_SIZE
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -21,13 +21,16 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
||||||
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
||||||
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
||||||
|
"AFL_DUMP_QUEUE_ON_EXIT", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
|
||||||
|
"AFL_DUMP_VULNERABILITY_COMPLEXITY", "AFL_CMPLOG_MAX_LEN",
|
||||||
"AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
"AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
||||||
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
||||||
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
||||||
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
|
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
|
||||||
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
|
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN",
|
||||||
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
"AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM",
|
||||||
|
"AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
||||||
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
|
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
|
||||||
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
|
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
|
||||||
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
|
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
|
||||||
@ -64,6 +67,8 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_ALLOWLIST",
|
"AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_ALLOWLIST",
|
||||||
"AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG",
|
"AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG",
|
||||||
"AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
"AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||||
|
"AFL_LLVM_LTO_CALLER", "AFL_LLVM_LTO_CTX", "AFL_LLVM_LTO_CALLER_DEPTH",
|
||||||
|
"AFL_LLVM_LTO_CTX_DEPTH", "AFL_LLVM_CALLER_DEPTH", "AFL_LLVM_CTX_DEPTH",
|
||||||
"AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN",
|
"AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN",
|
||||||
"AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT",
|
"AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT",
|
||||||
"AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
|
"AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
|
||||||
@ -93,27 +98,27 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_MAX_DET_EXTRAS",
|
"AFL_MAX_DET_EXTRAS",
|
||||||
"AFL_NO_X86", // not really an env but we dont want to warn on it
|
"AFL_NO_X86", // not really an env but we dont want to warn on it
|
||||||
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
|
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
|
||||||
"AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH",
|
"AFL_NYX_HANDLE_INVALID_WRITE", "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT",
|
||||||
"AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD",
|
"AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE",
|
||||||
"AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV",
|
"AFL_PERSISTENT_RECORD", "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD",
|
||||||
"AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV",
|
"AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN",
|
||||||
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
|
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS",
|
||||||
"AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR",
|
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL",
|
||||||
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR",
|
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
|
||||||
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM",
|
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
|
||||||
"AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
|
"AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET",
|
||||||
"AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES",
|
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
|
||||||
"AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE",
|
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
|
||||||
"AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH",
|
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
|
||||||
"AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
|
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
|
||||||
"AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST",
|
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
|
||||||
"AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME",
|
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
|
||||||
"AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT",
|
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
|
||||||
"AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_USE_ASAN",
|
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
|
||||||
"AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN",
|
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
|
||||||
"AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
|
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
|
||||||
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
|
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
|
||||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>>
|
Dominik Maier <mail@dmnk.co>>
|
||||||
|
|
||||||
@ -188,6 +188,8 @@ typedef struct afl_forkserver {
|
|||||||
|
|
||||||
u8 persistent_mode;
|
u8 persistent_mode;
|
||||||
|
|
||||||
|
u32 max_length;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
nyx_plugin_handler_t *nyx_handlers;
|
nyx_plugin_handler_t *nyx_handlers;
|
||||||
char *out_dir_path; /* path to the output directory */
|
char *out_dir_path; /* path to the output directory */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
738
include/t1ha.h
Normal file
738
include/t1ha.h
Normal file
@ -0,0 +1,738 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
|
||||||
|
* Fast Positive Hash.
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
|
||||||
|
* The 1Hippeus project (t1h).
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgement in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
|
||||||
|
* by [Positive Technologies](https://www.ptsecurity.ru)
|
||||||
|
*
|
||||||
|
* Briefly, it is a 64-bit Hash Function:
|
||||||
|
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
|
||||||
|
* but portable and without penalties it can run on any 64-bit CPU.
|
||||||
|
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
|
||||||
|
* and all others portable hash-functions (which do not use specific
|
||||||
|
* hardware tricks).
|
||||||
|
* 3. Not suitable for cryptography.
|
||||||
|
*
|
||||||
|
* The Future will (be) Positive. Всё будет хорошо.
|
||||||
|
*
|
||||||
|
* ACKNOWLEDGEMENT:
|
||||||
|
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
|
||||||
|
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* PLEASE PAY ATTENTION TO THE FOLLOWING NOTES
|
||||||
|
* about macros definitions which controls t1ha behaviour and/or performance.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 1) T1HA_SYS_UNALIGNED_ACCESS = Defines the system/platform/CPU/architecture
|
||||||
|
* abilities for unaligned data access.
|
||||||
|
*
|
||||||
|
* By default, when the T1HA_SYS_UNALIGNED_ACCESS not defined,
|
||||||
|
* it will defined on the basis hardcoded knowledge about of capabilities
|
||||||
|
* of most common CPU architectures. But you could override this
|
||||||
|
* default behavior when build t1ha library itself:
|
||||||
|
*
|
||||||
|
* // To disable unaligned access at all.
|
||||||
|
* #define T1HA_SYS_UNALIGNED_ACCESS 0
|
||||||
|
*
|
||||||
|
* // To enable unaligned access, but indicate that it significantly slow.
|
||||||
|
* #define T1HA_SYS_UNALIGNED_ACCESS 1
|
||||||
|
*
|
||||||
|
* // To enable unaligned access, and indicate that it effecient.
|
||||||
|
* #define T1HA_SYS_UNALIGNED_ACCESS 2
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 2) T1HA_USE_FAST_ONESHOT_READ = Controls the data reads at the end of buffer.
|
||||||
|
*
|
||||||
|
* When defined to non-zero, t1ha will use 'one shot' method for reading
|
||||||
|
* up to 8 bytes at the end of data. In this case just the one 64-bit read
|
||||||
|
* will be performed even when the available less than 8 bytes.
|
||||||
|
*
|
||||||
|
* This is little bit faster that switching by length of data tail.
|
||||||
|
* Unfortunately this will triggering a false-positive alarms from Valgrind,
|
||||||
|
* AddressSanitizer and other similar tool.
|
||||||
|
*
|
||||||
|
* By default, t1ha defines it to 1, but you could override this
|
||||||
|
* default behavior when build t1ha library itself:
|
||||||
|
*
|
||||||
|
* // For little bit faster and small code.
|
||||||
|
* #define T1HA_USE_FAST_ONESHOT_READ 1
|
||||||
|
*
|
||||||
|
* // For calmness if doubt.
|
||||||
|
* #define T1HA_USE_FAST_ONESHOT_READ 0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 3) T1HA0_RUNTIME_SELECT = Controls choice fastest function in runtime.
|
||||||
|
*
|
||||||
|
* t1ha library offers the t1ha0() function as the fastest for current CPU.
|
||||||
|
* But actual CPU's features/capabilities and may be significantly different,
|
||||||
|
* especially on x86 platform. Therefore, internally, t1ha0() may require
|
||||||
|
* dynamic dispatching for choice best implementation.
|
||||||
|
*
|
||||||
|
* By default, t1ha enables such runtime choice and (may be) corresponding
|
||||||
|
* indirect calls if it reasonable, but you could override this default
|
||||||
|
* behavior when build t1ha library itself:
|
||||||
|
*
|
||||||
|
* // To enable runtime choice of fastest implementation.
|
||||||
|
* #define T1HA0_RUNTIME_SELECT 1
|
||||||
|
*
|
||||||
|
* // To disable runtime choice of fastest implementation.
|
||||||
|
* #define T1HA0_RUNTIME_SELECT 0
|
||||||
|
*
|
||||||
|
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
|
||||||
|
* be used to get actual t1ha0() implementation address at runtime. This is
|
||||||
|
* useful for two cases:
|
||||||
|
* - calling by local pointer-to-function usually is little
|
||||||
|
* bit faster (less overhead) than via a PLT thru the DSO boundary.
|
||||||
|
* - GNU Indirect functions (see below) don't supported by environment
|
||||||
|
* and calling by t1ha0_funcptr is not available and/or expensive.
|
||||||
|
*
|
||||||
|
* 4) T1HA_USE_INDIRECT_FUNCTIONS = Controls usage of GNU Indirect functions.
|
||||||
|
*
|
||||||
|
* In continue of T1HA0_RUNTIME_SELECT the T1HA_USE_INDIRECT_FUNCTIONS
|
||||||
|
* controls usage of ELF indirect functions feature. In general, when
|
||||||
|
* available, this reduces overhead of indirect function's calls though
|
||||||
|
* a DSO-bundary (https://sourceware.org/glibc/wiki/GNU_IFUNC).
|
||||||
|
*
|
||||||
|
* By default, t1ha engage GNU Indirect functions when it available
|
||||||
|
* and useful, but you could override this default behavior when build
|
||||||
|
* t1ha library itself:
|
||||||
|
*
|
||||||
|
* // To enable use of GNU ELF Indirect functions.
|
||||||
|
* #define T1HA_USE_INDIRECT_FUNCTIONS 1
|
||||||
|
*
|
||||||
|
* // To disable use of GNU ELF Indirect functions. This may be useful
|
||||||
|
* // if the actual toolchain or the system's loader don't support ones.
|
||||||
|
* #define T1HA_USE_INDIRECT_FUNCTIONS 0
|
||||||
|
*
|
||||||
|
* 5) T1HA0_AESNI_AVAILABLE = Controls AES-NI detection and dispatching on x86.
|
||||||
|
*
|
||||||
|
* In continue of T1HA0_RUNTIME_SELECT the T1HA0_AESNI_AVAILABLE controls
|
||||||
|
* detection and usage of AES-NI CPU's feature. On the other hand, this
|
||||||
|
* requires compiling parts of t1ha library with certain properly options,
|
||||||
|
* and could be difficult or inconvenient in some cases.
|
||||||
|
*
|
||||||
|
* By default, t1ha engade AES-NI for t1ha0() on the x86 platform, but
|
||||||
|
* you could override this default behavior when build t1ha library itself:
|
||||||
|
*
|
||||||
|
* // To disable detection and usage of AES-NI instructions for t1ha0().
|
||||||
|
* // This may be useful when you unable to build t1ha library properly
|
||||||
|
* // or known that AES-NI will be unavailable at the deploy.
|
||||||
|
* #define T1HA0_AESNI_AVAILABLE 0
|
||||||
|
*
|
||||||
|
* // To force detection and usage of AES-NI instructions for t1ha0(),
|
||||||
|
* // but I don't known reasons to anybody would need this.
|
||||||
|
* #define T1HA0_AESNI_AVAILABLE 1
|
||||||
|
*
|
||||||
|
* 6) T1HA0_DISABLED, T1HA1_DISABLED, T1HA2_DISABLED = Controls availability of
|
||||||
|
* t1ha functions.
|
||||||
|
*
|
||||||
|
* In some cases could be useful to import/use only few of t1ha functions
|
||||||
|
* or just the one. So, this definitions allows disable corresponding parts
|
||||||
|
* of t1ha library.
|
||||||
|
*
|
||||||
|
* // To disable t1ha0(), t1ha0_32le(), t1ha0_32be() and all AES-NI.
|
||||||
|
* #define T1HA0_DISABLED
|
||||||
|
*
|
||||||
|
* // To disable t1ha1_le() and t1ha1_be().
|
||||||
|
* #define T1HA1_DISABLED
|
||||||
|
*
|
||||||
|
* // To disable t1ha2_atonce(), t1ha2_atonce128() and so on.
|
||||||
|
* #define T1HA2_DISABLED
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#define T1HA_VERSION_MAJOR 2
|
||||||
|
#define T1HA_VERSION_MINOR 1
|
||||||
|
#define T1HA_VERSION_RELEASE 1
|
||||||
|
|
||||||
|
#ifndef __has_attribute
|
||||||
|
#define __has_attribute(x) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __has_include
|
||||||
|
#define __has_include(x) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __GNUC_PREREQ
|
||||||
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||||
|
#define __GNUC_PREREQ(maj, min) \
|
||||||
|
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||||
|
#else
|
||||||
|
#define __GNUC_PREREQ(maj, min) 0
|
||||||
|
#endif
|
||||||
|
#endif /* __GNUC_PREREQ */
|
||||||
|
|
||||||
|
#ifndef __CLANG_PREREQ
|
||||||
|
#ifdef __clang__
|
||||||
|
#define __CLANG_PREREQ(maj, min) \
|
||||||
|
((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
|
||||||
|
#else
|
||||||
|
#define __CLANG_PREREQ(maj, min) (0)
|
||||||
|
#endif
|
||||||
|
#endif /* __CLANG_PREREQ */
|
||||||
|
|
||||||
|
#ifndef __LCC_PREREQ
|
||||||
|
#ifdef __LCC__
|
||||||
|
#define __LCC_PREREQ(maj, min) \
|
||||||
|
((__LCC__ << 16) + __LCC_MINOR__ >= ((maj) << 16) + (min))
|
||||||
|
#else
|
||||||
|
#define __LCC_PREREQ(maj, min) (0)
|
||||||
|
#endif
|
||||||
|
#endif /* __LCC_PREREQ */
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* Avoid '16' bytes padding added after data member 't1ha_context::total'
|
||||||
|
* and other warnings from std-headers if warning-level > 3. */
|
||||||
|
#pragma warning(push, 3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||||
|
#include <climits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#else
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \
|
||||||
|
defined(i486) || defined(__i486) || defined(__i486__) || \
|
||||||
|
defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \
|
||||||
|
defined(__i686) || defined(__i686__) || defined(_M_IX86) || \
|
||||||
|
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
|
||||||
|
defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \
|
||||||
|
defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \
|
||||||
|
defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__)
|
||||||
|
#ifndef __ia32__
|
||||||
|
/* LY: define neutral __ia32__ for x86 and x86-64 archs */
|
||||||
|
#define __ia32__ 1
|
||||||
|
#endif /* __ia32__ */
|
||||||
|
#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \
|
||||||
|
defined(__amd64) || defined(_M_X64))
|
||||||
|
/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */
|
||||||
|
#define __amd64__ 1
|
||||||
|
#endif /* __amd64__ */
|
||||||
|
#endif /* all x86 */
|
||||||
|
|
||||||
|
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
|
||||||
|
!defined(__ORDER_BIG_ENDIAN__)
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \
|
||||||
|
defined(HAVE_ENDIAN_H) || __has_include(<endian.h>)
|
||||||
|
#include <endian.h>
|
||||||
|
#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \
|
||||||
|
defined(HAVE_MACHINE_ENDIAN_H) || __has_include(<machine/endian.h>)
|
||||||
|
#include <machine/endian.h>
|
||||||
|
#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include(<sys/isa_defs.h>)
|
||||||
|
#include <sys/isa_defs.h>
|
||||||
|
#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \
|
||||||
|
(__has_include(<sys/types.h>) && __has_include(<sys/endian.h>))
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
|
||||||
|
defined(__NETBSD__) || defined(__NetBSD__) || \
|
||||||
|
defined(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif /* OS */
|
||||||
|
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
|
||||||
|
#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
|
||||||
|
#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
|
||||||
|
#define __BYTE_ORDER__ __BYTE_ORDER
|
||||||
|
#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
|
||||||
|
#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN
|
||||||
|
#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN
|
||||||
|
#define __BYTE_ORDER__ _BYTE_ORDER
|
||||||
|
#else
|
||||||
|
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||||
|
#define __ORDER_BIG_ENDIAN__ 4321
|
||||||
|
|
||||||
|
#if defined(__LITTLE_ENDIAN__) || \
|
||||||
|
(defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
|
||||||
|
defined(__ARMEL__) || defined(__THUMBEL__) || \
|
||||||
|
defined(__AARCH64EL__) || defined(__MIPSEL__) || defined(_MIPSEL) || \
|
||||||
|
defined(__MIPSEL) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||||
|
defined(__e2k__) || defined(__elbrus_4c__) || \
|
||||||
|
defined(__elbrus_8c__) || defined(__bfin__) || defined(__BFIN__) || \
|
||||||
|
defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \
|
||||||
|
defined(__ia64) || defined(_M_IA64) || defined(__itanium__) || \
|
||||||
|
defined(__ia32__) || defined(__CYGWIN__) || defined(_WIN64) || \
|
||||||
|
defined(_WIN32) || defined(__TOS_WIN__) || defined(__WINDOWS__)
|
||||||
|
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||||
|
|
||||||
|
#elif defined(__BIG_ENDIAN__) || \
|
||||||
|
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
|
||||||
|
defined(__ARMEB__) || defined(__THUMBEB__) || \
|
||||||
|
defined(__AARCH64EB__) || defined(__MIPSEB__) || defined(_MIPSEB) || \
|
||||||
|
defined(__MIPSEB) || defined(__m68k__) || defined(M68000) || \
|
||||||
|
defined(__hppa__) || defined(__hppa) || defined(__HPPA__) || \
|
||||||
|
defined(__sparc__) || defined(__sparc) || defined(__370__) || \
|
||||||
|
defined(__THW_370__) || defined(__s390__) || defined(__s390x__) || \
|
||||||
|
defined(__SYSC_ZARCH__)
|
||||||
|
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error __BYTE_ORDER__ should be defined.
|
||||||
|
#endif /* Arch */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __dll_export
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
||||||
|
#if defined(__GNUC__) || __has_attribute(dllexport)
|
||||||
|
#define __dll_export __attribute__((dllexport))
|
||||||
|
#else
|
||||||
|
#define __dll_export __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__) || __has_attribute(__visibility__)
|
||||||
|
#define __dll_export __attribute__((__visibility__("default")))
|
||||||
|
#else
|
||||||
|
#define __dll_export
|
||||||
|
#endif
|
||||||
|
#endif /* __dll_export */
|
||||||
|
|
||||||
|
#ifndef __dll_import
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
||||||
|
#if defined(__GNUC__) || __has_attribute(dllimport)
|
||||||
|
#define __dll_import __attribute__((dllimport))
|
||||||
|
#else
|
||||||
|
#define __dll_import __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__) || __has_attribute(__visibility__)
|
||||||
|
#define __dll_import __attribute__((__visibility__("default")))
|
||||||
|
#else
|
||||||
|
#define __dll_import
|
||||||
|
#endif
|
||||||
|
#endif /* __dll_import */
|
||||||
|
|
||||||
|
#ifndef __force_inline
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define __force_inline __forceinline
|
||||||
|
#elif __GNUC_PREREQ(3, 2) || __has_attribute(__always_inline__)
|
||||||
|
#define __force_inline __inline __attribute__((__always_inline__))
|
||||||
|
#else
|
||||||
|
#define __force_inline __inline
|
||||||
|
#endif
|
||||||
|
#endif /* __force_inline */
|
||||||
|
|
||||||
|
#ifndef T1HA_API
|
||||||
|
#if defined(t1ha_EXPORTS)
|
||||||
|
#define T1HA_API __dll_export
|
||||||
|
#elif defined(t1ha_IMPORTS)
|
||||||
|
#define T1HA_API __dll_import
|
||||||
|
#else
|
||||||
|
#define T1HA_API
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA_API */
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(__ia32__)
|
||||||
|
#define T1HA_ALIGN_PREFIX __declspec(align(32)) /* required only for SIMD */
|
||||||
|
#else
|
||||||
|
#define T1HA_ALIGN_PREFIX
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined(__ia32__)
|
||||||
|
#define T1HA_ALIGN_SUFFIX \
|
||||||
|
__attribute__((__aligned__(32))) /* required only for SIMD */
|
||||||
|
#else
|
||||||
|
#define T1HA_ALIGN_SUFFIX
|
||||||
|
#endif /* GCC x86 */
|
||||||
|
|
||||||
|
#ifndef T1HA_USE_INDIRECT_FUNCTIONS
|
||||||
|
/* GNU ELF indirect functions usage control. For more info please see
|
||||||
|
* https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
* and https://sourceware.org/glibc/wiki/GNU_IFUNC */
|
||||||
|
#if defined(__ELF__) && defined(__amd64__) && \
|
||||||
|
(__has_attribute(__ifunc__) || \
|
||||||
|
(!defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && \
|
||||||
|
!defined(__SANITIZE_ADDRESS__) && !defined(__SSP_ALL__)))
|
||||||
|
/* Enable gnu_indirect_function by default if :
|
||||||
|
* - ELF AND x86_64
|
||||||
|
* - attribute(__ifunc__) is available OR
|
||||||
|
* GCC >= 4 WITHOUT -fsanitize=address NOR -fstack-protector-all */
|
||||||
|
#define T1HA_USE_INDIRECT_FUNCTIONS 1
|
||||||
|
#else
|
||||||
|
#define T1HA_USE_INDIRECT_FUNCTIONS 0
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ(4, 0)
|
||||||
|
#pragma GCC visibility push(hidden)
|
||||||
|
#endif /* __GNUC_PREREQ(4,0) */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef union T1HA_ALIGN_PREFIX t1ha_state256 {
|
||||||
|
|
||||||
|
uint8_t bytes[32];
|
||||||
|
uint32_t u32[8];
|
||||||
|
uint64_t u64[4];
|
||||||
|
struct {
|
||||||
|
|
||||||
|
uint64_t a, b, c, d;
|
||||||
|
|
||||||
|
} n;
|
||||||
|
|
||||||
|
} t1ha_state256_t T1HA_ALIGN_SUFFIX;
|
||||||
|
|
||||||
|
typedef struct t1ha_context {
|
||||||
|
|
||||||
|
t1ha_state256_t state;
|
||||||
|
t1ha_state256_t buffer;
|
||||||
|
size_t partial;
|
||||||
|
uint64_t total;
|
||||||
|
|
||||||
|
} t1ha_context_t;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Self-testing API.
|
||||||
|
*
|
||||||
|
* Unfortunately, some compilers (exactly only Microsoft Visual C/C++) has
|
||||||
|
* a bugs which leads t1ha-functions to produce wrong results. This API allows
|
||||||
|
* check the correctness of the actual code in runtime.
|
||||||
|
*
|
||||||
|
* All check-functions returns 0 on success, or -1 in case the corresponding
|
||||||
|
* hash-function failed verification. PLEASE, always perform such checking at
|
||||||
|
* initialization of your code, if you using MSVC or other troubleful compilers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
T1HA_API int t1ha_selfcheck__all_enabled(void);
|
||||||
|
|
||||||
|
#ifndef T1HA2_DISABLED
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha2_atonce(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha2_atonce128(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha2_stream(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha2(void);
|
||||||
|
#endif /* T1HA2_DISABLED */
|
||||||
|
|
||||||
|
#ifndef T1HA1_DISABLED
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha1_le(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha1_be(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha1(void);
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
|
||||||
|
#ifndef T1HA0_DISABLED
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0_32le(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0_32be(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0(void);
|
||||||
|
|
||||||
|
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
|
||||||
|
#ifndef T1HA0_AESNI_AVAILABLE
|
||||||
|
#if defined(__e2k__) || \
|
||||||
|
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
|
||||||
|
#define T1HA0_AESNI_AVAILABLE 1
|
||||||
|
#else
|
||||||
|
#define T1HA0_AESNI_AVAILABLE 0
|
||||||
|
#endif
|
||||||
|
#endif /* ifndef T1HA0_AESNI_AVAILABLE */
|
||||||
|
|
||||||
|
#if T1HA0_AESNI_AVAILABLE
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_noavx(void);
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx(void);
|
||||||
|
#ifndef __e2k__
|
||||||
|
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx2(void);
|
||||||
|
#endif
|
||||||
|
#endif /* if T1HA0_AESNI_AVAILABLE */
|
||||||
|
#endif /* T1HA0_DISABLED */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* t1ha2 = 64 and 128-bit, SLIGHTLY MORE ATTENTION FOR QUALITY AND STRENGTH.
|
||||||
|
*
|
||||||
|
* - The recommended version of "Fast Positive Hash" with good quality
|
||||||
|
* for checksum, hash tables and fingerprinting.
|
||||||
|
* - Portable and extremely efficiency on modern 64-bit CPUs.
|
||||||
|
* Designed for 64-bit little-endian platforms,
|
||||||
|
* in other cases will runs slowly.
|
||||||
|
* - Great quality of hashing and still faster than other non-t1ha hashes.
|
||||||
|
* Provides streaming mode and 128-bit result.
|
||||||
|
*
|
||||||
|
* Note: Due performance reason 64- and 128-bit results are completely
|
||||||
|
* different each other, i.e. 64-bit result is NOT any part of 128-bit.
|
||||||
|
*/
|
||||||
|
#ifndef T1HA2_DISABLED
|
||||||
|
|
||||||
|
/* The at-once variant with 64-bit result */
|
||||||
|
T1HA_API uint64_t t1ha2_atonce(const void *data, size_t length, uint64_t seed);
|
||||||
|
|
||||||
|
/* The at-once variant with 128-bit result.
|
||||||
|
* Argument `extra_result` is NOT optional and MUST be valid.
|
||||||
|
* The high 64-bit part of 128-bit hash will be always unconditionally
|
||||||
|
* stored to the address given by `extra_result` argument. */
|
||||||
|
T1HA_API uint64_t t1ha2_atonce128(uint64_t *__restrict extra_result,
|
||||||
|
const void *__restrict data, size_t length,
|
||||||
|
uint64_t seed);
|
||||||
|
|
||||||
|
/* The init/update/final trinity for streaming.
|
||||||
|
* Return 64 or 128-bit result depentently from `extra_result` argument. */
|
||||||
|
T1HA_API void t1ha2_init(t1ha_context_t *ctx, uint64_t seed_x, uint64_t seed_y);
|
||||||
|
T1HA_API void t1ha2_update(t1ha_context_t *__restrict ctx,
|
||||||
|
const void *__restrict data, size_t length);
|
||||||
|
|
||||||
|
/* Argument `extra_result` is optional and MAY be NULL.
|
||||||
|
* - If `extra_result` is NOT NULL then the 128-bit hash will be calculated,
|
||||||
|
* and high 64-bit part of it will be stored to the address given
|
||||||
|
* by `extra_result` argument.
|
||||||
|
* - Otherwise the 64-bit hash will be calculated
|
||||||
|
* and returned from function directly.
|
||||||
|
*
|
||||||
|
* Note: Due performance reason 64- and 128-bit results are completely
|
||||||
|
* different each other, i.e. 64-bit result is NOT any part of 128-bit. */
|
||||||
|
T1HA_API uint64_t t1ha2_final(t1ha_context_t *__restrict ctx,
|
||||||
|
uint64_t *__restrict extra_result /* optional */);
|
||||||
|
|
||||||
|
#endif /* T1HA2_DISABLED */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* t1ha1 = 64-bit, BASELINE FAST PORTABLE HASH:
|
||||||
|
*
|
||||||
|
* - Runs faster on 64-bit platforms in other cases may runs slowly.
|
||||||
|
* - Portable and stable, returns same 64-bit result
|
||||||
|
* on all architectures and CPUs.
|
||||||
|
* - Unfortunately it fails the "strict avalanche criteria",
|
||||||
|
* see test results at https://github.com/demerphq/smhasher.
|
||||||
|
*
|
||||||
|
* This flaw is insignificant for the t1ha1() purposes and imperceptible
|
||||||
|
* from a practical point of view.
|
||||||
|
* However, nowadays this issue has resolved in the next t1ha2(),
|
||||||
|
* that was initially planned to providing a bit more quality.
|
||||||
|
*/
|
||||||
|
#ifndef T1HA1_DISABLED
|
||||||
|
|
||||||
|
/* The little-endian variant. */
|
||||||
|
T1HA_API uint64_t t1ha1_le(const void *data, size_t length, uint64_t seed);
|
||||||
|
|
||||||
|
/* The big-endian variant. */
|
||||||
|
T1HA_API uint64_t t1ha1_be(const void *data, size_t length, uint64_t seed);
|
||||||
|
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* t1ha0 = 64-bit, JUST ONLY FASTER:
|
||||||
|
*
|
||||||
|
* - Provides fast-as-possible hashing for current CPU, including
|
||||||
|
* 32-bit systems and engaging the available hardware acceleration.
|
||||||
|
* - It is a facade that selects most quick-and-dirty hash
|
||||||
|
* for the current processor. For instance, on IA32 (x86) actual function
|
||||||
|
* will be selected in runtime, depending on current CPU capabilities
|
||||||
|
*
|
||||||
|
* BE CAREFUL!!! THIS IS MEANS:
|
||||||
|
*
|
||||||
|
* 1. The quality of hash is a subject for tradeoffs with performance.
|
||||||
|
* So, the quality and strength of t1ha0() may be lower than t1ha1(),
|
||||||
|
* especially on 32-bit targets, but then much faster.
|
||||||
|
* However, guaranteed that it passes all SMHasher tests.
|
||||||
|
*
|
||||||
|
* 2. No warranty that the hash result will be same for particular
|
||||||
|
* key on another machine or another version of libt1ha.
|
||||||
|
*
|
||||||
|
* Briefly, such hash-results and their derivatives, should be
|
||||||
|
* used only in runtime, but should not be persist or transferred
|
||||||
|
* over a network.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
|
||||||
|
* be used to get actual t1ha0() implementation address at runtime. This is
|
||||||
|
* useful for two cases:
|
||||||
|
* - calling by local pointer-to-function usually is little
|
||||||
|
* bit faster (less overhead) than via a PLT thru the DSO boundary.
|
||||||
|
* - GNU Indirect functions (see below) don't supported by environment
|
||||||
|
* and calling by t1ha0_funcptr is not available and/or expensive.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef T1HA0_DISABLED
|
||||||
|
|
||||||
|
/* The little-endian variant for 32-bit CPU. */
|
||||||
|
uint64_t t1ha0_32le(const void *data, size_t length, uint64_t seed);
|
||||||
|
/* The big-endian variant for 32-bit CPU. */
|
||||||
|
uint64_t t1ha0_32be(const void *data, size_t length, uint64_t seed);
|
||||||
|
|
||||||
|
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
|
||||||
|
#ifndef T1HA0_AESNI_AVAILABLE
|
||||||
|
#if defined(__e2k__) || \
|
||||||
|
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
|
||||||
|
#define T1HA0_AESNI_AVAILABLE 1
|
||||||
|
#else
|
||||||
|
#define T1HA0_AESNI_AVAILABLE 0
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||||
|
|
||||||
|
/* Define T1HA0_RUNTIME_SELECT to 0 for disable dispatching t1ha0 at runtime.
|
||||||
|
*/
|
||||||
|
#ifndef T1HA0_RUNTIME_SELECT
|
||||||
|
#if T1HA0_AESNI_AVAILABLE && !defined(__e2k__)
|
||||||
|
#define T1HA0_RUNTIME_SELECT 1
|
||||||
|
#else
|
||||||
|
#define T1HA0_RUNTIME_SELECT 0
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA0_RUNTIME_SELECT */
|
||||||
|
|
||||||
|
#if !T1HA0_RUNTIME_SELECT && !defined(T1HA0_USE_DEFINE)
|
||||||
|
#if defined(__LCC__)
|
||||||
|
#define T1HA0_USE_DEFINE 1
|
||||||
|
#else
|
||||||
|
#define T1HA0_USE_DEFINE 0
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA0_USE_DEFINE */
|
||||||
|
|
||||||
|
#if T1HA0_AESNI_AVAILABLE
|
||||||
|
uint64_t t1ha0_ia32aes_noavx(const void *data, size_t length, uint64_t seed);
|
||||||
|
uint64_t t1ha0_ia32aes_avx(const void *data, size_t length, uint64_t seed);
|
||||||
|
#ifndef __e2k__
|
||||||
|
uint64_t t1ha0_ia32aes_avx2(const void *data, size_t length, uint64_t seed);
|
||||||
|
#endif
|
||||||
|
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||||
|
|
||||||
|
#if T1HA0_RUNTIME_SELECT
|
||||||
|
typedef uint64_t (*t1ha0_function_t)(const void *, size_t, uint64_t);
|
||||||
|
T1HA_API t1ha0_function_t t1ha0_resolve(void);
|
||||||
|
#if T1HA_USE_INDIRECT_FUNCTIONS
|
||||||
|
T1HA_API uint64_t t1ha0(const void *data, size_t length, uint64_t seed);
|
||||||
|
#else
|
||||||
|
/* Otherwise function pointer will be used.
|
||||||
|
* Unfortunately this may cause some overhead calling. */
|
||||||
|
T1HA_API extern uint64_t (*t1ha0_funcptr)(const void *data, size_t length,
|
||||||
|
uint64_t seed);
|
||||||
|
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||||
|
uint64_t seed) {
|
||||||
|
|
||||||
|
return t1ha0_funcptr(data, length, seed);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
|
||||||
|
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
|
||||||
|
#if T1HA0_USE_DEFINE
|
||||||
|
|
||||||
|
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||||
|
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||||
|
#if defined(T1HA1_DISABLED)
|
||||||
|
#define t1ha0 t1ha2_atonce
|
||||||
|
#else
|
||||||
|
#define t1ha0 t1ha1_be
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
#else /* 32/64 */
|
||||||
|
#define t1ha0 t1ha0_32be
|
||||||
|
#endif /* 32/64 */
|
||||||
|
|
||||||
|
#else /* T1HA0_USE_DEFINE */
|
||||||
|
|
||||||
|
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||||
|
uint64_t seed) {
|
||||||
|
|
||||||
|
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||||
|
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||||
|
#if defined(T1HA1_DISABLED)
|
||||||
|
return t1ha2_atonce(data, length, seed);
|
||||||
|
#else
|
||||||
|
return t1ha1_be(data, length, seed);
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
#else /* 32/64 */
|
||||||
|
return t1ha0_32be(data, length, seed);
|
||||||
|
#endif /* 32/64 */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !T1HA0_USE_DEFINE */
|
||||||
|
|
||||||
|
#else /* !T1HA0_RUNTIME_SELECT && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
|
||||||
|
|
||||||
|
#if T1HA0_USE_DEFINE
|
||||||
|
|
||||||
|
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||||
|
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||||
|
#if defined(T1HA1_DISABLED)
|
||||||
|
#define t1ha0 t1ha2_atonce
|
||||||
|
#else
|
||||||
|
#define t1ha0 t1ha1_le
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
#else /* 32/64 */
|
||||||
|
#define t1ha0 t1ha0_32le
|
||||||
|
#endif /* 32/64 */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||||
|
uint64_t seed) {
|
||||||
|
|
||||||
|
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||||
|
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||||
|
#if defined(T1HA1_DISABLED)
|
||||||
|
return t1ha2_atonce(data, length, seed);
|
||||||
|
#else
|
||||||
|
return t1ha1_le(data, length, seed);
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
#else /* 32/64 */
|
||||||
|
return t1ha0_32le(data, length, seed);
|
||||||
|
#endif /* 32/64 */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !T1HA0_USE_DEFINE */
|
||||||
|
|
||||||
|
#endif /* !T1HA0_RUNTIME_SELECT */
|
||||||
|
|
||||||
|
#endif /* T1HA0_DISABLED */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC_PREREQ(4, 0)
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
#endif /* __GNUC_PREREQ(4,0) */
|
||||||
|
|
183
include/t1ha0_ia32aes_b.h
Normal file
183
include/t1ha0_ia32aes_b.h
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
|
||||||
|
* Fast Positive Hash.
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
|
||||||
|
* The 1Hippeus project (t1h).
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgement in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
|
||||||
|
* by [Positive Technologies](https://www.ptsecurity.ru)
|
||||||
|
*
|
||||||
|
* Briefly, it is a 64-bit Hash Function:
|
||||||
|
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
|
||||||
|
* but portable and without penalties it can run on any 64-bit CPU.
|
||||||
|
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
|
||||||
|
* and all others portable hash-functions (which do not use specific
|
||||||
|
* hardware tricks).
|
||||||
|
* 3. Not suitable for cryptography.
|
||||||
|
*
|
||||||
|
* The Future will (be) Positive. Всё будет хорошо.
|
||||||
|
*
|
||||||
|
* ACKNOWLEDGEMENT:
|
||||||
|
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
|
||||||
|
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "t1ha_bits.h"
|
||||||
|
#include "t1ha_selfcheck.h"
|
||||||
|
|
||||||
|
#if T1HA0_AESNI_AVAILABLE
|
||||||
|
|
||||||
|
uint64_t T1HA_IA32AES_NAME(const void *data, uint32_t len) {
|
||||||
|
|
||||||
|
uint64_t a = 0;
|
||||||
|
uint64_t b = len;
|
||||||
|
|
||||||
|
if (likely(len > 32)) {
|
||||||
|
|
||||||
|
__m128i x = _mm_set_epi64x(a, b);
|
||||||
|
__m128i y = _mm_aesenc_si128(x, _mm_set_epi64x(prime_0, prime_1));
|
||||||
|
|
||||||
|
const __m128i *v = (const __m128i *)data;
|
||||||
|
const __m128i *const detent =
|
||||||
|
(const __m128i *)((const uint8_t *)data + (len & ~15ul));
|
||||||
|
data = detent;
|
||||||
|
|
||||||
|
if (len & 16) {
|
||||||
|
|
||||||
|
x = _mm_add_epi64(x, _mm_loadu_si128(v++));
|
||||||
|
y = _mm_aesenc_si128(x, y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
len &= 15;
|
||||||
|
|
||||||
|
if (v + 7 < detent) {
|
||||||
|
|
||||||
|
__m128i salt = y;
|
||||||
|
do {
|
||||||
|
|
||||||
|
__m128i t = _mm_aesenc_si128(_mm_loadu_si128(v++), salt);
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||||
|
|
||||||
|
salt = _mm_add_epi64(salt, _mm_set_epi64x(prime_5, prime_6));
|
||||||
|
t = _mm_aesenc_si128(x, t);
|
||||||
|
x = _mm_add_epi64(y, x);
|
||||||
|
y = t;
|
||||||
|
|
||||||
|
} while (v + 7 < detent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (v < detent) {
|
||||||
|
|
||||||
|
__m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++));
|
||||||
|
__m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++));
|
||||||
|
x = _mm_aesdec_si128(x, v0y);
|
||||||
|
y = _mm_aesdec_si128(y, v1x);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
x = _mm_add_epi64(_mm_aesdec_si128(x, _mm_aesenc_si128(y, x)), y);
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64)
|
||||||
|
#if defined(__SSE4_1__) || defined(__AVX__)
|
||||||
|
a = _mm_extract_epi64(x, 0);
|
||||||
|
b = _mm_extract_epi64(x, 1);
|
||||||
|
#else
|
||||||
|
a = _mm_cvtsi128_si64(x);
|
||||||
|
b = _mm_cvtsi128_si64(_mm_unpackhi_epi64(x, x));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(__SSE4_1__) || defined(__AVX__)
|
||||||
|
a = (uint32_t)_mm_extract_epi32(x, 0) | (uint64_t)_mm_extract_epi32(x, 1)
|
||||||
|
<< 32;
|
||||||
|
b = (uint32_t)_mm_extract_epi32(x, 2) | (uint64_t)_mm_extract_epi32(x, 3)
|
||||||
|
<< 32;
|
||||||
|
#else
|
||||||
|
a = (uint32_t)_mm_cvtsi128_si32(x);
|
||||||
|
a |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
|
||||||
|
x = _mm_unpackhi_epi64(x, x);
|
||||||
|
b = (uint32_t)_mm_cvtsi128_si32(x);
|
||||||
|
b |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef __AVX__
|
||||||
|
_mm256_zeroupper();
|
||||||
|
#elif !(defined(_X86_64_) || defined(__x86_64__) || defined(_M_X64) || \
|
||||||
|
defined(__e2k__))
|
||||||
|
_mm_empty();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t *v = (const uint64_t *)data;
|
||||||
|
switch (len) {
|
||||||
|
|
||||||
|
default:
|
||||||
|
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_4);
|
||||||
|
/* fall through */
|
||||||
|
case 24:
|
||||||
|
case 23:
|
||||||
|
case 22:
|
||||||
|
case 21:
|
||||||
|
case 20:
|
||||||
|
case 19:
|
||||||
|
case 18:
|
||||||
|
case 17:
|
||||||
|
mixup64(&b, &a, fetch64_le_unaligned(v++), prime_3);
|
||||||
|
/* fall through */
|
||||||
|
case 16:
|
||||||
|
case 15:
|
||||||
|
case 14:
|
||||||
|
case 13:
|
||||||
|
case 12:
|
||||||
|
case 11:
|
||||||
|
case 10:
|
||||||
|
case 9:
|
||||||
|
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_2);
|
||||||
|
/* fall through */
|
||||||
|
case 8:
|
||||||
|
case 7:
|
||||||
|
case 6:
|
||||||
|
case 5:
|
||||||
|
case 4:
|
||||||
|
case 3:
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
mixup64(&b, &a, tail64_le_unaligned(v, len), prime_1);
|
||||||
|
/* fall through */
|
||||||
|
case 0:
|
||||||
|
return final64(a, b);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||||
|
#undef T1HA_IA32AES_NAME
|
||||||
|
|
1423
include/t1ha_bits.h
Normal file
1423
include/t1ha_bits.h
Normal file
File diff suppressed because it is too large
Load Diff
77
include/t1ha_selfcheck.h
Normal file
77
include/t1ha_selfcheck.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
|
||||||
|
* Fast Positive Hash.
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
|
||||||
|
* The 1Hippeus project (t1h).
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgement in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
|
||||||
|
* by [Positive Technologies](https://www.ptsecurity.ru)
|
||||||
|
*
|
||||||
|
* Briefly, it is a 64-bit Hash Function:
|
||||||
|
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
|
||||||
|
* but portable and without penalties it can run on any 64-bit CPU.
|
||||||
|
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
|
||||||
|
* and all others portable hash-functions (which do not use specific
|
||||||
|
* hardware tricks).
|
||||||
|
* 3. Not suitable for cryptography.
|
||||||
|
*
|
||||||
|
* The Future will (be) Positive. Всё будет хорошо.
|
||||||
|
*
|
||||||
|
* ACKNOWLEDGEMENT:
|
||||||
|
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
|
||||||
|
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER > 1800
|
||||||
|
#pragma warning(disable : 4464) /* relative include path contains '..' */
|
||||||
|
#endif /* MSVC */
|
||||||
|
#include "t1ha.h"
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* Self-checking */
|
||||||
|
|
||||||
|
extern const uint8_t t1ha_test_pattern[64];
|
||||||
|
int t1ha_selfcheck(uint64_t (*hash)(const void *, size_t, uint64_t),
|
||||||
|
const uint64_t *reference_values);
|
||||||
|
|
||||||
|
#ifndef T1HA2_DISABLED
|
||||||
|
extern const uint64_t t1ha_refval_2atonce[81];
|
||||||
|
extern const uint64_t t1ha_refval_2atonce128[81];
|
||||||
|
extern const uint64_t t1ha_refval_2stream[81];
|
||||||
|
extern const uint64_t t1ha_refval_2stream128[81];
|
||||||
|
#endif /* T1HA2_DISABLED */
|
||||||
|
|
||||||
|
#ifndef T1HA1_DISABLED
|
||||||
|
extern const uint64_t t1ha_refval_64le[81];
|
||||||
|
extern const uint64_t t1ha_refval_64be[81];
|
||||||
|
#endif /* T1HA1_DISABLED */
|
||||||
|
|
||||||
|
#ifndef T1HA0_DISABLED
|
||||||
|
extern const uint64_t t1ha_refval_32le[81];
|
||||||
|
extern const uint64_t t1ha_refval_32be[81];
|
||||||
|
#if T1HA0_AESNI_AVAILABLE
|
||||||
|
extern const uint64_t t1ha_refval_ia32aes_a[81];
|
||||||
|
extern const uint64_t t1ha_refval_ia32aes_b[81];
|
||||||
|
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||||
|
#endif /* T1HA0_DISABLED */
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -49,6 +49,14 @@ typedef uint128_t u128;
|
|||||||
#define FS_ERROR_OLD_CMPLOG 32
|
#define FS_ERROR_OLD_CMPLOG 32
|
||||||
#define FS_ERROR_OLD_CMPLOG_QEMU 64
|
#define FS_ERROR_OLD_CMPLOG_QEMU 64
|
||||||
|
|
||||||
|
/* New Forkserver */
|
||||||
|
#define FS_NEW_VERSION_MIN 1
|
||||||
|
#define FS_NEW_VERSION_MAX 1
|
||||||
|
#define FS_NEW_ERROR 0xeffe0000
|
||||||
|
#define FS_NEW_OPT_MAPSIZE 0x00000001 // parameter: 32 bit value
|
||||||
|
#define FS_NEW_OPT_SHDMEM_FUZZ 0x00000002 // parameter: none
|
||||||
|
#define FS_NEW_OPT_AUTODICT 0x00000800 // autodictionary data
|
||||||
|
|
||||||
/* Reporting options */
|
/* Reporting options */
|
||||||
#define FS_OPT_ENABLED 0x80000001
|
#define FS_OPT_ENABLED 0x80000001
|
||||||
#define FS_OPT_MAPSIZE 0x40000000
|
#define FS_OPT_MAPSIZE 0x40000000
|
||||||
|
4692
include/xxhash.h
4692
include/xxhash.h
File diff suppressed because it is too large
Load Diff
@ -195,4 +195,34 @@ Then as first line after the `__AFL_LOOP` while loop:
|
|||||||
int len = __AFL_FUZZ_TESTCASE_LEN;
|
int len = __AFL_FUZZ_TESTCASE_LEN;
|
||||||
```
|
```
|
||||||
|
|
||||||
And that is all!
|
And that is all!
|
||||||
|
|
||||||
|
## 6) Persistent record, and replay
|
||||||
|
|
||||||
|
If your software under test requires keeping a state between persistent loop iterations (i.e., a stateful network stack), you can use the `AFL_PERSISTENT_RECORD` variable as described in the [environment variables documentation](../docs/env_variables.md).
|
||||||
|
|
||||||
|
When `AFL_PERSISTENT_RECORD` is enabled, replay functionality is also included in the compiler-rt library. To replay a specific record, assign the record number to the AFL_PERSISTENT_REPLAY environment variable (i.e., `RECORD:XXXXX`` -> `AFL_PERSISTENT_REPLAY=XXXXX`), and run the test binary as you would normally do.
|
||||||
|
The directory where the record files live can be specified via the `AFL_PERSISTENT_DIR` environment varilable, otherwise by default it will be considered the current directory (`./`).
|
||||||
|
|
||||||
|
If your harness reads the input files from arguments using the special `@@` argument you will need to include support by enabling `AFL_PERSISTENT_ARGPARSE` in `config.h`.
|
||||||
|
|
||||||
|
In order to offer transparent support to harnesses using the `@@` command line argument, arguments are parsed by the `__afl_record_replay_init` init function. Since not all systems support passing arguments to initializers, this functionality is disabled by default, it's recommendable to use the `__AFL_FUZZ_TESTCASE_BUF/__AFL_FUZZ_TESTCASE_LEN` shared memory mechanism instead.
|
||||||
|
|
||||||
|
## 7) Drop-in persistent loop replay replacement
|
||||||
|
|
||||||
|
To use the replay functionality without having to use `afl-cc`, include the [include/record_compat.h](../include/afl-record_compat.h) header file. Together with the [include/afl-persistent-replay.h](../include/afl-persistent-replay.h) header included in it, `afl-record-compat.h` provides a drop-in replacement for the persistent loop mechanism.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#ifndef __AFL_FUZZ_TESTCASE_LEN
|
||||||
|
// #define AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
#include "afl-record-compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__AFL_FUZZ_INIT();
|
||||||
|
```
|
||||||
|
|
||||||
|
A simple example is provided in [persistent_demo_replay.c](../utils/replay_record/persistent_demo_replay.c).
|
||||||
|
|
||||||
|
Be aware that the [afl-record-compat.h](../include/afl-record-compat.h) header should only be included in a single compilation unit, or you will end up with clobbered functions and variables.
|
||||||
|
|
||||||
|
If you need a cleaner solution, you'll have to move the functions and variables defined in [include/record_compat.h](../include/afl-record-compat.h) and [include/afl-persistent-replay.h](../include/afl-persistent-replay.h) in a C file, and add the relevant declarations to a header file. After including the new header file, the compilation unit resulting from compiling the C file can then be linked with your program.
|
File diff suppressed because it is too large
Load Diff
@ -70,6 +70,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||||
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -119,6 +121,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
|
||||||
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
|
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
|
||||||
using PostDomTreeCallback =
|
using PostDomTreeCallback =
|
||||||
function_ref<const PostDominatorTree *(Function &F)>;
|
function_ref<const PostDominatorTree *(Function &F)>;
|
||||||
@ -135,11 +138,13 @@ class ModuleSanitizerCoverageAFL
|
|||||||
|
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
|
||||||
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
|
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
|
||||||
PostDomTreeCallback PDTCallback);
|
PostDomTreeCallback PDTCallback,
|
||||||
|
LoopInfoCallback LCallback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
|
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
|
||||||
PostDomTreeCallback PDTCallback);
|
PostDomTreeCallback PDTCallback,
|
||||||
|
LoopInfoCallback LCallback);
|
||||||
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
|
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
|
||||||
void InjectTraceForSwitch(Function &F,
|
void InjectTraceForSwitch(Function &F,
|
||||||
ArrayRef<Instruction *> SwitchTraceTargets);
|
ArrayRef<Instruction *> SwitchTraceTargets);
|
||||||
@ -195,7 +200,7 @@ class ModuleSanitizerCoverageAFL
|
|||||||
|
|
||||||
SanitizerCoverageOptions Options;
|
SanitizerCoverageOptions Options;
|
||||||
|
|
||||||
uint32_t instr = 0, selects = 0, unhandled = 0;
|
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0, dump_vc = 0;
|
||||||
GlobalVariable *AFLMapPtr = NULL;
|
GlobalVariable *AFLMapPtr = NULL;
|
||||||
ConstantInt *One = NULL;
|
ConstantInt *One = NULL;
|
||||||
ConstantInt *Zero = NULL;
|
ConstantInt *Zero = NULL;
|
||||||
@ -233,8 +238,10 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
|||||||
ModuleAnalysisManager &MAM) {
|
ModuleAnalysisManager &MAM) {
|
||||||
|
|
||||||
ModuleSanitizerCoverageAFL ModuleSancov(Options);
|
ModuleSanitizerCoverageAFL ModuleSancov(Options);
|
||||||
|
|
||||||
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||||
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
|
|
||||||
|
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
|
||||||
|
|
||||||
return &FAM.getResult<DominatorTreeAnalysis>(F);
|
return &FAM.getResult<DominatorTreeAnalysis>(F);
|
||||||
|
|
||||||
@ -246,9 +253,21 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
|
||||||
|
|
||||||
|
return &FAM.getResult<LoopAnalysis>(F);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback)) {
|
||||||
|
|
||||||
return PreservedAnalyses::none();
|
return PreservedAnalyses::none();
|
||||||
return PreservedAnalyses::all();
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,12 +343,17 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleSanitizerCoverageAFL::instrumentModule(
|
bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||||
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||||
|
LoopInfoCallback LCallback) {
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG")) { debug = 1; }
|
if (getenv("AFL_DEBUG")) { debug = 1; }
|
||||||
|
|
||||||
|
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
|
||||||
|
|
||||||
|
if (getenv("AFL_DUMP_VULNERABILITY_COMPLEXITY")) { dump_vc = 1; }
|
||||||
|
|
||||||
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
|
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
|
||||||
|
|
||||||
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
|
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
|
||||||
@ -427,7 +451,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
|||||||
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
|
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
|
||||||
|
|
||||||
for (auto &F : M)
|
for (auto &F : M)
|
||||||
instrumentFunction(F, DTCallback, PDTCallback);
|
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
|
||||||
|
|
||||||
Function *Ctor = nullptr;
|
Function *Ctor = nullptr;
|
||||||
|
|
||||||
@ -566,7 +590,8 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ModuleSanitizerCoverageAFL::instrumentFunction(
|
void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||||
|
LoopInfoCallback LCallback) {
|
||||||
|
|
||||||
if (F.empty()) return;
|
if (F.empty()) return;
|
||||||
if (!isInInstrumentList(&F, FMNAME)) return;
|
if (!isInInstrumentList(&F, FMNAME)) return;
|
||||||
@ -602,6 +627,7 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
|||||||
|
|
||||||
const DominatorTree *DT = DTCallback(F);
|
const DominatorTree *DT = DTCallback(F);
|
||||||
const PostDominatorTree *PDT = PDTCallback(F);
|
const PostDominatorTree *PDT = PDTCallback(F);
|
||||||
|
const LoopInfo *LI = LCallback(F);
|
||||||
bool IsLeafFunc = true;
|
bool IsLeafFunc = true;
|
||||||
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
@ -634,6 +660,51 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int score = 0;
|
||||||
|
|
||||||
|
if (dump_cc) { score += calcCyclomaticComplexity(&F, LI); }
|
||||||
|
if (dump_vc) { score += calcVulnerabilityScore(&F, LI, DT, PDT); }
|
||||||
|
|
||||||
|
if (score) {
|
||||||
|
|
||||||
|
BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
|
||||||
|
IRBuilder<> builder(&*IP);
|
||||||
|
|
||||||
|
// Access the int32 value at u8 offset 1 (unaligned access)
|
||||||
|
LoadInst *MapPtr =
|
||||||
|
builder.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
|
||||||
|
llvm::Value *CastToInt8Ptr =
|
||||||
|
builder.CreateBitCast(MapPtr, llvm::PointerType::get(Int8Ty, 0));
|
||||||
|
llvm::Value *Int32Ptr = builder.CreateGEP(
|
||||||
|
Int8Ty, CastToInt8Ptr, llvm::ConstantInt::get(Int32Ty, 1));
|
||||||
|
llvm::Value *CastToInt32Ptr =
|
||||||
|
builder.CreateBitCast(Int32Ptr, llvm::PointerType::get(Int32Ty, 0));
|
||||||
|
|
||||||
|
// Load the unaligned int32 value
|
||||||
|
llvm::LoadInst *Load = builder.CreateLoad(Int32Ty, CastToInt32Ptr);
|
||||||
|
Load->setAlignment(llvm::Align(1));
|
||||||
|
|
||||||
|
// Value to add
|
||||||
|
llvm::Value *ValueToAdd = llvm::ConstantInt::get(Int32Ty, score);
|
||||||
|
|
||||||
|
// Perform addition and check for wrap around
|
||||||
|
llvm::Value *Add =
|
||||||
|
builder.CreateAdd(Load, ValueToAdd, "addValue", true, true);
|
||||||
|
|
||||||
|
// Check if addition wrapped (unsigned)
|
||||||
|
llvm::Value *DidWrap = builder.CreateICmpULT(Add, Load, "didWrap");
|
||||||
|
|
||||||
|
// Select the maximum value if there was a wrap, otherwise use the result
|
||||||
|
llvm::Value *MaxInt32 = llvm::ConstantInt::get(Int32Ty, UINT32_MAX);
|
||||||
|
llvm::Value *Result =
|
||||||
|
builder.CreateSelect(DidWrap, MaxInt32, Add, "selectMaxOrResult");
|
||||||
|
|
||||||
|
// Store the result back at the same unaligned offset
|
||||||
|
llvm::StoreInst *Store = builder.CreateStore(Result, CastToInt32Ptr);
|
||||||
|
Store->setAlignment(llvm::Align(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
|
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
|
||||||
// InjectTraceForCmp(F, CmpTraceTargets);
|
// InjectTraceForCmp(F, CmpTraceTargets);
|
||||||
// InjectTraceForSwitch(F, SwitchTraceTargets);
|
// InjectTraceForSwitch(F, SwitchTraceTargets);
|
||||||
|
@ -87,6 +87,10 @@ __attribute__((weak)) void __sanitizer_symbolize_pc(void *, const char *fmt,
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
#include "afl-persistent-replay.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Globals needed by the injected instrumentation. The __afl_area_initial region
|
/* Globals needed by the injected instrumentation. The __afl_area_initial region
|
||||||
is used for instrumentation output before __afl_map_shm() has a chance to
|
is used for instrumentation output before __afl_map_shm() has a chance to
|
||||||
run. It will end up as .comm, so it shouldn't be too wasteful. */
|
run. It will end up as .comm, so it shouldn't be too wasteful. */
|
||||||
@ -186,6 +190,8 @@ __thread u32 __afl_prev_ctx;
|
|||||||
struct cmp_map *__afl_cmp_map;
|
struct cmp_map *__afl_cmp_map;
|
||||||
struct cmp_map *__afl_cmp_map_backup;
|
struct cmp_map *__afl_cmp_map_backup;
|
||||||
|
|
||||||
|
static u8 __afl_cmplog_max_len = 32; // 16-32
|
||||||
|
|
||||||
/* Child pid? */
|
/* Child pid? */
|
||||||
|
|
||||||
static s32 child_pid;
|
static s32 child_pid;
|
||||||
@ -264,7 +270,7 @@ static void send_forkserver_error(int error) {
|
|||||||
|
|
||||||
u32 status;
|
u32 status;
|
||||||
if (!error || error > 0xffff) return;
|
if (!error || error > 0xffff) return;
|
||||||
status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
|
status = (FS_NEW_ERROR | error);
|
||||||
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
|
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -367,32 +373,13 @@ static void __afl_map_shm(void) {
|
|||||||
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
|
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
|
||||||
if (val < __afl_final_loc) {
|
if (val < __afl_final_loc) {
|
||||||
|
|
||||||
if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
|
if (__afl_final_loc > MAP_INITIAL_SIZE && !getenv("AFL_QUIET")) {
|
||||||
|
|
||||||
if (!getenv("AFL_QUIET"))
|
fprintf(stderr,
|
||||||
fprintf(stderr,
|
"Warning: AFL++ tools might need to set AFL_MAP_SIZE to %u "
|
||||||
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
|
"to be able to run this instrumented program if this "
|
||||||
"to be able to run this instrumented program!\n",
|
"crashes!\n",
|
||||||
__afl_final_loc);
|
__afl_final_loc);
|
||||||
|
|
||||||
if (id_str) {
|
|
||||||
|
|
||||||
send_forkserver_error(FS_ERROR_MAP_SIZE);
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (__afl_final_loc > MAP_INITIAL_SIZE && !getenv("AFL_QUIET")) {
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"Warning: AFL++ tools might need to set AFL_MAP_SIZE to %u "
|
|
||||||
"to be able to run this instrumented program if this "
|
|
||||||
"crashes!\n",
|
|
||||||
__afl_final_loc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,15 +387,6 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (getenv("AFL_DUMP_MAP_SIZE")) {
|
|
||||||
|
|
||||||
printf("%u\n", MAP_SIZE);
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing && (!id_str || !getenv(SHM_FUZZ_ENV_VAR) ||
|
if (__afl_sharedmem_fuzzing && (!id_str || !getenv(SHM_FUZZ_ENV_VAR) ||
|
||||||
@ -474,14 +452,13 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
if (__afl_debug) {
|
if (__afl_debug) {
|
||||||
|
|
||||||
fprintf(
|
fprintf(stderr,
|
||||||
stderr,
|
"DEBUG: (1) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
||||||
"DEBUG: (1) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE %u, "
|
||||||
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE %u, "
|
"__afl_final_loc %u, __afl_map_size %u\n",
|
||||||
"__afl_final_loc %u, __afl_map_size %u, max_size_forkserver %u/0x%x\n",
|
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
||||||
id_str == NULL ? "<null>" : id_str, __afl_area_ptr, __afl_area_initial,
|
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
||||||
__afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc,
|
__afl_final_loc, __afl_map_size);
|
||||||
__afl_map_size, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,12 +616,10 @@ static void __afl_map_shm(void) {
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
||||||
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
|
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
|
||||||
"%u, __afl_final_loc %u, __afl_map_size %u, "
|
"%u, __afl_final_loc %u, __afl_map_size %u",
|
||||||
"max_size_forkserver %u/0x%x\n",
|
|
||||||
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
||||||
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
||||||
__afl_final_loc, __afl_map_size, FS_OPT_MAX_MAPSIZE,
|
__afl_final_loc, __afl_map_size);
|
||||||
FS_OPT_MAX_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,6 +736,19 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
#endif // __AFL_CODE_COVERAGE
|
#endif // __AFL_CODE_COVERAGE
|
||||||
|
|
||||||
|
if (!__afl_cmp_map && getenv("AFL_CMPLOG_DEBUG")) {
|
||||||
|
|
||||||
|
__afl_cmp_map_backup = __afl_cmp_map = malloc(sizeof(struct cmp_map));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_CMPLOG_MAX_LEN")) {
|
||||||
|
|
||||||
|
int tmp = atoi(getenv("AFL_CMPLOG_MAX_LEN"));
|
||||||
|
if (tmp >= 16 && tmp <= 32) { __afl_cmplog_max_len = tmp; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unmap SHM. */
|
/* unmap SHM. */
|
||||||
@ -855,242 +843,6 @@ void write_error_with_location(char *text, char *filename, int linenumber) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
static void __afl_start_snapshots(void) {
|
|
||||||
|
|
||||||
static u8 tmp[4] = {0, 0, 0, 0};
|
|
||||||
u32 status = 0;
|
|
||||||
u32 already_read_first = 0;
|
|
||||||
u32 was_killed;
|
|
||||||
|
|
||||||
u8 child_stopped = 0;
|
|
||||||
|
|
||||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
|
||||||
|
|
||||||
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
|
||||||
assume we're not running in forkserver mode and just execute program. */
|
|
||||||
|
|
||||||
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT | FS_OPT_NEWCMPLOG);
|
|
||||||
if (__afl_sharedmem_fuzzing) { status |= FS_OPT_SHDMEM_FUZZ; }
|
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
|
||||||
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
|
||||||
if (__afl_dictionary_len && __afl_dictionary) { status |= FS_OPT_AUTODICT; }
|
|
||||||
memcpy(tmp, &status, 4);
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
|
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("read to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_debug) {
|
|
||||||
|
|
||||||
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
|
|
||||||
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
|
||||||
|
|
||||||
__afl_map_shm_fuzz();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
|
|
||||||
__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
// great lets pass the dictionary through the forkserver FD
|
|
||||||
u32 len = __afl_dictionary_len, offset = 0;
|
|
||||||
s32 ret;
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary len\n",
|
|
||||||
strlen("Error: could not send dictionary len\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len != 0) {
|
|
||||||
|
|
||||||
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
|
||||||
|
|
||||||
if (ret < 1) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary\n",
|
|
||||||
strlen("Error: could not send dictionary\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= ret;
|
|
||||||
offset += ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// uh this forkserver does not understand extended option passing
|
|
||||||
// or does not want the dictionary
|
|
||||||
if (!__afl_fuzz_ptr) already_read_first = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (already_read_first) {
|
|
||||||
|
|
||||||
already_read_first = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Wait for parent by reading from the pipe. Abort if read fails. */
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("reading from afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _AFL_DOCUMENT_MUTATIONS
|
|
||||||
if (__afl_fuzz_ptr) {
|
|
||||||
|
|
||||||
static uint32_t counter = 0;
|
|
||||||
char fn[32];
|
|
||||||
sprintf(fn, "%09u:forkserver", counter);
|
|
||||||
s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
|
|
||||||
if (fd_doc >= 0) {
|
|
||||||
|
|
||||||
if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) {
|
|
||||||
|
|
||||||
fprintf(stderr, "write of mutation file failed: %s\n", fn);
|
|
||||||
unlink(fn);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd_doc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
|
||||||
process. */
|
|
||||||
|
|
||||||
if (child_stopped && was_killed) {
|
|
||||||
|
|
||||||
child_stopped = 0;
|
|
||||||
if (waitpid(child_pid, &status, 0) < 0) {
|
|
||||||
|
|
||||||
write_error("child_stopped && was_killed");
|
|
||||||
_exit(1); // TODO why exit?
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!child_stopped) {
|
|
||||||
|
|
||||||
/* Once woken up, create a clone of our process. */
|
|
||||||
|
|
||||||
child_pid = fork();
|
|
||||||
if (child_pid < 0) {
|
|
||||||
|
|
||||||
write_error("fork");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In child process: close fds, resume execution. */
|
|
||||||
|
|
||||||
if (!child_pid) {
|
|
||||||
|
|
||||||
//(void)nice(-20); // does not seem to improve
|
|
||||||
|
|
||||||
signal(SIGCHLD, old_sigchld_handler);
|
|
||||||
signal(SIGTERM, old_sigterm_handler);
|
|
||||||
|
|
||||||
close(FORKSRV_FD);
|
|
||||||
close(FORKSRV_FD + 1);
|
|
||||||
|
|
||||||
if (!afl_snapshot_take(AFL_SNAPSHOT_MMAP | AFL_SNAPSHOT_FDS |
|
|
||||||
AFL_SNAPSHOT_REGS | AFL_SNAPSHOT_EXIT)) {
|
|
||||||
|
|
||||||
raise(SIGSTOP);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__afl_area_ptr[0] = 1;
|
|
||||||
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Special handling for persistent mode: if the child is alive but
|
|
||||||
currently stopped, simply restart it with SIGCONT. */
|
|
||||||
|
|
||||||
kill(child_pid, SIGCONT);
|
|
||||||
child_stopped = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In parent process: write PID to pipe, then wait for child. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("write to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitpid(child_pid, &status, WUNTRACED) < 0) {
|
|
||||||
|
|
||||||
write_error("waitpid");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In persistent mode, the child stops itself with SIGSTOP to indicate
|
|
||||||
a successful run. In this case, we want to wake it up without forking
|
|
||||||
again. */
|
|
||||||
|
|
||||||
if (WIFSTOPPED(status)) child_stopped = 1;
|
|
||||||
|
|
||||||
/* Relay wait status to pipe, then loop back. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("writing to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fork server logic. */
|
/* Fork server logic. */
|
||||||
|
|
||||||
static void __afl_start_forkserver(void) {
|
static void __afl_start_forkserver(void) {
|
||||||
@ -1103,114 +855,93 @@ static void __afl_start_forkserver(void) {
|
|||||||
old_sigterm_handler = orig_action.sa_handler;
|
old_sigterm_handler = orig_action.sa_handler;
|
||||||
signal(SIGTERM, at_exit);
|
signal(SIGTERM, at_exit);
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
|
|
||||||
afl_snapshot_init() >= 0) {
|
|
||||||
|
|
||||||
__afl_start_snapshots();
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u8 tmp[4] = {0, 0, 0, 0};
|
|
||||||
u32 status_for_fsrv = 0;
|
|
||||||
u32 already_read_first = 0;
|
u32 already_read_first = 0;
|
||||||
u32 was_killed;
|
u32 was_killed;
|
||||||
|
u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
|
||||||
|
u32 tmp = version ^ 0xffffffff, status2, status = version;
|
||||||
|
u8 *msg = (u8 *)&status;
|
||||||
|
u8 *reply = (u8 *)&status2;
|
||||||
|
|
||||||
u8 child_stopped = 0;
|
u8 child_stopped = 0;
|
||||||
|
|
||||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) {
|
|
||||||
|
|
||||||
status_for_fsrv |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
status_for_fsrv |= FS_OPT_AUTODICT;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
|
|
||||||
if (status_for_fsrv) {
|
|
||||||
|
|
||||||
status_for_fsrv |= (FS_OPT_ENABLED | FS_OPT_NEWCMPLOG);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tmp, &status_for_fsrv, 4);
|
|
||||||
|
|
||||||
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
||||||
assume we're not running in forkserver mode and just execute program. */
|
assume we're not running in forkserver mode and just execute program. */
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
|
// return because possible non-forkserver usage
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
|
||||||
|
|
||||||
__afl_connected = 1;
|
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
|
||||||
|
if (tmp != status2) {
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
write_error("wrong forkserver message from AFL++ tool");
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
}
|
||||||
|
|
||||||
if (__afl_debug) {
|
// send the set/requested options to forkserver
|
||||||
|
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
|
||||||
|
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
|
||||||
|
if (__afl_dictionary_len && __afl_dictionary) {
|
||||||
|
|
||||||
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
|
status |= FS_NEW_OPT_AUTODICT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// Now send the parameters for the set options, increasing by option number
|
||||||
|
|
||||||
|
// FS_NEW_OPT_MAPSIZE - we always send the map size
|
||||||
|
status = __afl_map_size;
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// FS_NEW_OPT_SHDMEM_FUZZ - no data
|
||||||
|
|
||||||
|
// FS_NEW_OPT_AUTODICT - send autodictionary
|
||||||
|
if (__afl_dictionary_len && __afl_dictionary) {
|
||||||
|
|
||||||
|
// pass the dictionary through the forkserver FD
|
||||||
|
u32 len = __afl_dictionary_len, offset = 0;
|
||||||
|
|
||||||
|
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
||||||
|
|
||||||
|
write(2, "Error: could not send dictionary len\n",
|
||||||
|
strlen("Error: could not send dictionary len\n"));
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
|
while (len != 0) {
|
||||||
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
|
||||||
|
|
||||||
__afl_map_shm_fuzz();
|
s32 ret;
|
||||||
|
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
||||||
|
|
||||||
}
|
if (ret < 1) {
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
write_error("could not send dictionary");
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
|
|
||||||
__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
// great lets pass the dictionary through the forkserver FD
|
|
||||||
u32 len = __afl_dictionary_len, offset = 0;
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary len\n",
|
|
||||||
strlen("Error: could not send dictionary len\n"));
|
|
||||||
_exit(1);
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len != 0) {
|
len -= ret;
|
||||||
|
offset += ret;
|
||||||
s32 ret;
|
|
||||||
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
|
||||||
|
|
||||||
if (ret < 1) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary\n",
|
|
||||||
strlen("Error: could not send dictionary\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= ret;
|
|
||||||
offset += ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// uh this forkserver does not understand extended option passing
|
|
||||||
// or does not want the dictionary
|
|
||||||
if (!__afl_fuzz_ptr) already_read_first = 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send welcome message as final message
|
||||||
|
status = version;
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// END forkserver handshake
|
||||||
|
|
||||||
|
__afl_connected = 1;
|
||||||
|
|
||||||
|
if (__afl_sharedmem_fuzzing) { __afl_map_shm_fuzz(); }
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
@ -1225,7 +956,7 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
||||||
|
|
||||||
// write_error("read from afl-fuzz");
|
write_error("read from AFL++ tool");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1354,6 +1085,10 @@ int __afl_persistent_loop(unsigned int max_cnt) {
|
|||||||
static u8 first_pass = 1;
|
static u8 first_pass = 1;
|
||||||
static u32 cycle_cnt;
|
static u32 cycle_cnt;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
char tcase[PATH_MAX];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (first_pass) {
|
if (first_pass) {
|
||||||
|
|
||||||
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
|
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
|
||||||
@ -1365,14 +1100,59 @@ int __afl_persistent_loop(unsigned int max_cnt) {
|
|||||||
__afl_area_ptr[0] = 1;
|
__afl_area_ptr[0] = 1;
|
||||||
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
|
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
|
||||||
|
|
||||||
cycle_cnt = max_cnt;
|
|
||||||
first_pass = 0;
|
first_pass = 0;
|
||||||
__afl_selective_coverage_temp = 1;
|
__afl_selective_coverage_temp = 1;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
if (unlikely(is_replay_record)) {
|
||||||
|
|
||||||
|
cycle_cnt = replay_record_cnt;
|
||||||
|
goto persistent_record;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
cycle_cnt = max_cnt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else if (--cycle_cnt) {
|
} else if (--cycle_cnt) {
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
if (unlikely(is_replay_record)) {
|
||||||
|
|
||||||
|
persistent_record:
|
||||||
|
|
||||||
|
snprintf(tcase, PATH_MAX, "%s/%s",
|
||||||
|
replay_record_dir ? replay_record_dir : "./",
|
||||||
|
record_list[replay_record_cnt - cycle_cnt]->d_name);
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
if (unlikely(record_arg)) {
|
||||||
|
|
||||||
|
*record_arg = tcase;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||||
|
{
|
||||||
|
|
||||||
|
int fd = open(tcase, O_RDONLY);
|
||||||
|
dup2(fd, 0);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
raise(SIGSTOP);
|
raise(SIGSTOP);
|
||||||
|
|
||||||
__afl_area_ptr[0] = 1;
|
__afl_area_ptr[0] = 1;
|
||||||
@ -1837,7 +1617,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pc_filter) {
|
if (pc_filter && !mod_info->next) {
|
||||||
|
|
||||||
char PcDescr[1024];
|
char PcDescr[1024];
|
||||||
// This function is a part of the sanitizer run-time.
|
// This function is a part of the sanitizer run-time.
|
||||||
@ -1864,7 +1644,8 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__afl_filter_pcs && strstr(mod_info->name, __afl_filter_pcs_module)) {
|
if (__afl_filter_pcs && !mod_info->next &&
|
||||||
|
strstr(mod_info->name, __afl_filter_pcs_module)) {
|
||||||
|
|
||||||
u32 result_index;
|
u32 result_index;
|
||||||
if (locate_in_pcs(PC, &result_index)) {
|
if (locate_in_pcs(PC, &result_index)) {
|
||||||
@ -1889,7 +1670,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_info->mapped = 1;
|
if (__afl_pcmap_ptr) { mod_info->mapped = 1; }
|
||||||
|
|
||||||
if (__afl_debug) {
|
if (__afl_debug) {
|
||||||
|
|
||||||
@ -2068,7 +1849,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
|
|||||||
to avoid duplicate calls (which can happen as an artifact of the underlying
|
to avoid duplicate calls (which can happen as an artifact of the underlying
|
||||||
implementation in LLVM). */
|
implementation in LLVM). */
|
||||||
|
|
||||||
if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries
|
if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries
|
||||||
|
|
||||||
*(start++) = ++__afl_final_loc;
|
*(start++) = ++__afl_final_loc;
|
||||||
|
|
||||||
@ -2181,7 +1962,8 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
|
void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2219,7 +2001,8 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
// fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
|
// fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2257,7 +2040,8 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
// fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
|
// fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2300,7 +2084,8 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
|
|||||||
// (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
|
// (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
|
||||||
// attr);
|
// attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2 || size > __afl_cmplog_max_len)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2344,6 +2129,7 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
|
|||||||
void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
|
void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
|
||||||
|
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (16 > __afl_cmplog_max_len) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2537,13 +2323,25 @@ void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
|
|
||||||
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!len)) return;
|
if (unlikely(!len || len > __afl_cmplog_max_len)) return;
|
||||||
int len0 = MIN(len, 31);
|
|
||||||
|
int len0 = MIN(len, 32);
|
||||||
|
|
||||||
int len1 = strnlen(ptr1, len0);
|
int len1 = strnlen(ptr1, len0);
|
||||||
if (len1 < 31) len1 = area_is_valid(ptr1, len1 + 1);
|
if (len1 <= 32) len1 = area_is_valid(ptr1, len1 + 1);
|
||||||
|
if (len1 > __afl_cmplog_max_len) len1 = 0;
|
||||||
|
|
||||||
int len2 = strnlen(ptr2, len0);
|
int len2 = strnlen(ptr2, len0);
|
||||||
if (len2 < 31) len2 = area_is_valid(ptr2, len2 + 1);
|
if (len2 <= 32) len2 = area_is_valid(ptr2, len2 + 1);
|
||||||
int l = MAX(len1, len2);
|
if (len2 > __afl_cmplog_max_len) len2 = 0;
|
||||||
|
|
||||||
|
int l;
|
||||||
|
if (!len1)
|
||||||
|
l = len2;
|
||||||
|
else if (!len2)
|
||||||
|
l = len1;
|
||||||
|
else
|
||||||
|
l = MAX(len1, len2);
|
||||||
if (l < 2) return;
|
if (l < 2) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
@ -2587,10 +2385,18 @@ void __cmplog_rtn_hook_str(u8 *ptr1, u8 *ptr2) {
|
|||||||
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!ptr1 || !ptr2)) return;
|
if (unlikely(!ptr1 || !ptr2)) return;
|
||||||
int len1 = strnlen(ptr1, 30) + 1;
|
int len1 = strnlen(ptr1, 31) + 1;
|
||||||
int len2 = strnlen(ptr2, 30) + 1;
|
int len2 = strnlen(ptr2, 31) + 1;
|
||||||
int l = MAX(len1, len2);
|
if (len1 > __afl_cmplog_max_len) len1 = 0;
|
||||||
if (l < 3) return;
|
if (len2 > __afl_cmplog_max_len) len2 = 0;
|
||||||
|
int l;
|
||||||
|
if (!len1)
|
||||||
|
l = len2;
|
||||||
|
else if (!len2)
|
||||||
|
l = len1;
|
||||||
|
else
|
||||||
|
l = MAX(len1, len2);
|
||||||
|
if (l < 2) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2632,7 +2438,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
u32 i;
|
u32 i;
|
||||||
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
|
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
|
||||||
fprintf(stderr, "rtn arg0=");
|
fprintf(stderr, "rtn arg0=");
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
fprintf(stderr, "%02x", ptr1[i]);
|
fprintf(stderr, "%02x", ptr1[i]);
|
||||||
@ -2645,10 +2451,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
|
|||||||
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
int l1, l2;
|
int l1, l2;
|
||||||
if ((l1 = area_is_valid(ptr1, 31)) <= 0 ||
|
if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
|
||||||
(l2 = area_is_valid(ptr2, 31)) <= 0)
|
(l2 = area_is_valid(ptr2, 32)) <= 0)
|
||||||
return;
|
return;
|
||||||
int len = MIN(31, MIN(l1, l2));
|
int len = MIN(__afl_cmplog_max_len, MIN(l1, l2));
|
||||||
|
|
||||||
// fprintf(stderr, "RTN2 %u\n", len);
|
// fprintf(stderr, "RTN2 %u\n", len);
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
@ -2697,7 +2503,7 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
u32 i;
|
u32 i;
|
||||||
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
|
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
|
||||||
fprintf(stderr, "rtn_n len=%u arg0=", len);
|
fprintf(stderr, "rtn_n len=%u arg0=", len);
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
fprintf(stderr, "%02x", ptr1[i]);
|
fprintf(stderr, "%02x", ptr1[i]);
|
||||||
@ -2709,12 +2515,15 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
|
|
||||||
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!len)) return;
|
if (!len) return;
|
||||||
int l = MIN(31, len);
|
int l = MIN(32, len), l1, l2;
|
||||||
|
|
||||||
if ((l = area_is_valid(ptr1, l)) <= 0 || (l = area_is_valid(ptr2, l)) <= 0)
|
if ((l1 = area_is_valid(ptr1, l)) <= 0 || (l2 = area_is_valid(ptr2, l)) <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
len = MIN(l1, l2);
|
||||||
|
if (len > __afl_cmplog_max_len) return;
|
||||||
|
|
||||||
// fprintf(stderr, "RTN2 %u\n", l);
|
// fprintf(stderr, "RTN2 %u\n", l);
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
|
@ -180,19 +180,19 @@ struct afl_cmptrs_pass : afl_base_pass {
|
|||||||
c = DECL_CONTEXT(c);
|
c = DECL_CONTEXT(c);
|
||||||
if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
|
if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
|
||||||
|
|
||||||
/* Check that the first nonstatic data member of the record type
|
/* Check that the first nonstatic named data member of the record type
|
||||||
is named _M_dataplus. */
|
is named _M_dataplus. */
|
||||||
for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
|
for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
|
||||||
if (TREE_CODE(c) == FIELD_DECL) break;
|
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
|
||||||
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
||||||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
|
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Check that the second nonstatic data member of the record type
|
/* Check that the second nonstatic named data member of the record type
|
||||||
is named _M_string_length. */
|
is named _M_string_length. */
|
||||||
tree f2;
|
tree f2;
|
||||||
for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
|
for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
|
||||||
if (TREE_CODE(f2) == FIELD_DECL) break;
|
if (TREE_CODE(f2) == FIELD_DECL && DECL_NAME(f2)) break;
|
||||||
if (!f2 /* No need to check this field's offset. */
|
if (!f2 /* No need to check this field's offset. */
|
||||||
|| strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
|
|| strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
|
||||||
return false;
|
return false;
|
||||||
@ -208,9 +208,12 @@ struct afl_cmptrs_pass : afl_base_pass {
|
|||||||
strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
|
strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* And its first data member is named _M_p. */
|
/* And its first nonstatic named data member should be named _M_p.
|
||||||
|
There may be (unnamed) subobjects from empty base classes. We
|
||||||
|
skip the subobjects, then check the offset of the first data
|
||||||
|
member. */
|
||||||
for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
|
for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
|
||||||
if (TREE_CODE(c) == FIELD_DECL) break;
|
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
|
||||||
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
||||||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
|
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -14,7 +14,21 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <llvm/Support/raw_ostream.h>
|
#if LLVM_VERSION_MAJOR >= 13
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/IR/InstIterator.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
|
#include "llvm/IR/Operator.h"
|
||||||
|
#include "llvm/IR/Dominators.h"
|
||||||
|
#include "llvm/Analysis/PostDominators.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #define LEOPARD_USE_WEIGHTS 1
|
||||||
|
|
||||||
#define IS_EXTERN extern
|
#define IS_EXTERN extern
|
||||||
#include "afl-llvm-common.h"
|
#include "afl-llvm-common.h"
|
||||||
@ -26,6 +40,294 @@ static std::list<std::string> allowListFunctions;
|
|||||||
static std::list<std::string> denyListFiles;
|
static std::list<std::string> denyListFiles;
|
||||||
static std::list<std::string> denyListFunctions;
|
static std::list<std::string> denyListFunctions;
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 13
|
||||||
|
// Leopard complexity calculations
|
||||||
|
|
||||||
|
#ifndef LEOPARD_USE_WEIGHTS
|
||||||
|
#define C1_WEIGHT 1.0
|
||||||
|
#define C2_WEIGHT 1.0
|
||||||
|
#define C3_WEIGHT 1.0
|
||||||
|
#define C4_WEIGHT 1.0
|
||||||
|
#define V1_WEIGHT 1.0
|
||||||
|
#define V2_WEIGHT 1.0
|
||||||
|
#define V3_WEIGHT 1.0
|
||||||
|
#define V4_WEIGHT 1.0
|
||||||
|
#define V5_WEIGHT 1.0
|
||||||
|
#define V6_WEIGHT 1.0
|
||||||
|
#define V7_WEIGHT 1.0
|
||||||
|
#define V8_WEIGHT 1.0
|
||||||
|
#define V9_WEIGHT 1.0
|
||||||
|
#define V10_WEIGHT 1.0
|
||||||
|
#define V11_WEIGHT 1.0
|
||||||
|
#else
|
||||||
|
// Cyclomatic weights
|
||||||
|
#define C1_WEIGHT 1.0
|
||||||
|
#define C2_WEIGHT 1.0
|
||||||
|
#define C3_WEIGHT 1.0
|
||||||
|
#define C4_WEIGHT 1.0
|
||||||
|
|
||||||
|
// Vulnerability weights
|
||||||
|
#define V1_WEIGHT 1.5
|
||||||
|
#define V2_WEIGHT 3.25
|
||||||
|
#define V3_WEIGHT 4.25
|
||||||
|
#define V4_WEIGHT 3.0
|
||||||
|
#define V5_WEIGHT 4.25
|
||||||
|
#define V6_WEIGHT 7.75
|
||||||
|
#define V7_WEIGHT 2.5
|
||||||
|
#define V8_WEIGHT 2.5
|
||||||
|
#define V9_WEIGHT 4.0
|
||||||
|
#define V10_WEIGHT 5.25
|
||||||
|
#define V11_WEIGHT 3.5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void countNestedLoops(Loop *L, int depth, unsigned int &loopCount,
|
||||||
|
unsigned int &nestedLoopCount,
|
||||||
|
unsigned int &maxNestingLevel) {
|
||||||
|
|
||||||
|
loopCount++;
|
||||||
|
if (!L->getSubLoops().empty()) {
|
||||||
|
|
||||||
|
// Increment nested loop count by the number of sub-loops
|
||||||
|
nestedLoopCount += L->getSubLoops().size();
|
||||||
|
// Update maximum nesting level
|
||||||
|
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
|
||||||
|
|
||||||
|
// Recursively count sub-loops
|
||||||
|
for (Loop *SubLoop : L->getSubLoops()) {
|
||||||
|
|
||||||
|
countNestedLoops(SubLoop, depth + 1, loopCount, nestedLoopCount,
|
||||||
|
maxNestingLevel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int calcCyclomaticComplexity(llvm::Function *F,
|
||||||
|
const llvm::LoopInfo *LI) {
|
||||||
|
|
||||||
|
unsigned int numBlocks = 0;
|
||||||
|
unsigned int numEdges = 0;
|
||||||
|
unsigned int numCalls = 0;
|
||||||
|
unsigned int numLoops = 0;
|
||||||
|
unsigned int numNestedLoops = 0;
|
||||||
|
unsigned int maxLoopNesting = 0;
|
||||||
|
|
||||||
|
// Iterate through each basic block in the function
|
||||||
|
for (BasicBlock &BB : *F) {
|
||||||
|
|
||||||
|
// count all nodes == basic blocks
|
||||||
|
numBlocks++;
|
||||||
|
// Count the number of successors (outgoing edges)
|
||||||
|
for (BasicBlock *Succ : successors(&BB)) {
|
||||||
|
|
||||||
|
// count edges for CC
|
||||||
|
numEdges++;
|
||||||
|
(void)(Succ);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Instruction &I : BB) {
|
||||||
|
|
||||||
|
// every call is also an edge, so we need to count the calls too
|
||||||
|
if (isa<CallInst>(&I) || isa<InvokeInst>(&I)) { numCalls++; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Loop *L : *LI) {
|
||||||
|
|
||||||
|
countNestedLoops(L, 1, numLoops, numNestedLoops, maxLoopNesting);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cyclomatic Complexity V(G) = E - N + 2P
|
||||||
|
// For a single function, P (number of connected components) is 1
|
||||||
|
// Calls are considered to be an edge
|
||||||
|
unsigned int cc =
|
||||||
|
(unsigned int)(C1_WEIGHT * (double)(2 + numCalls + numEdges - numBlocks) +
|
||||||
|
C2_WEIGHT * (double)numLoops +
|
||||||
|
C3_WEIGHT * (double)numNestedLoops +
|
||||||
|
C4_WEIGHT * (double)maxLoopNesting);
|
||||||
|
|
||||||
|
// if (debug) {
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"CyclomaticComplexity for %s: %u (calls=%u edges=%u blocks=%u "
|
||||||
|
"loops=%u nested_loops=%u max_loop_nesting_level=%u)\n",
|
||||||
|
F->getName().str().c_str(), cc, numCalls, numEdges, numBlocks,
|
||||||
|
numLoops, numNestedLoops, maxLoopNesting);
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
|
||||||
|
const llvm::DominatorTree *DT,
|
||||||
|
const llvm::PostDominatorTree *PDT) {
|
||||||
|
|
||||||
|
unsigned int score = 0;
|
||||||
|
// V1 and V2
|
||||||
|
unsigned paramCount = F->arg_size();
|
||||||
|
unsigned calledParamCount = 0;
|
||||||
|
// V3, V4 and V5
|
||||||
|
unsigned pointerArithCount = 0;
|
||||||
|
unsigned totalPointerArithParams = 0;
|
||||||
|
unsigned maxPointerArithVars = 0;
|
||||||
|
// V6 to V11
|
||||||
|
unsigned nestedControlStructCount = 0;
|
||||||
|
unsigned maxNestingLevel = 0;
|
||||||
|
unsigned maxControlDependentControls = 0;
|
||||||
|
unsigned maxDataDependentControls = 0;
|
||||||
|
unsigned ifWithoutElseCount = 0;
|
||||||
|
unsigned controlPredicateVarCount = 0;
|
||||||
|
|
||||||
|
std::function<void(Loop *, unsigned)> countNestedLoops = [&](Loop *L,
|
||||||
|
unsigned depth) {
|
||||||
|
|
||||||
|
nestedControlStructCount++;
|
||||||
|
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
|
||||||
|
for (Loop *SubLoop : L->getSubLoops()) {
|
||||||
|
|
||||||
|
countNestedLoops(SubLoop, depth + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
for (Loop *TopLoop : *LI) {
|
||||||
|
|
||||||
|
countNestedLoops(TopLoop, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inst_iterator I = inst_begin(*F), E = inst_end(*F); I != E; ++I) {
|
||||||
|
|
||||||
|
if (CallInst *CI = dyn_cast<CallInst>(&*I)) {
|
||||||
|
|
||||||
|
if (Function *CalledF = CI->getCalledFunction()) {
|
||||||
|
|
||||||
|
calledParamCount += CalledF->arg_size();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(&*I)) {
|
||||||
|
|
||||||
|
pointerArithCount++;
|
||||||
|
unsigned numPointerArithVars = GEP->getNumOperands();
|
||||||
|
totalPointerArithParams += numPointerArithVars;
|
||||||
|
if (numPointerArithVars > maxPointerArithVars) {
|
||||||
|
|
||||||
|
maxPointerArithVars = numPointerArithVars;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BranchInst *BI = dyn_cast<BranchInst>(&*I)) {
|
||||||
|
|
||||||
|
if (BI->isConditional()) {
|
||||||
|
|
||||||
|
unsigned controlDependentCount = 0;
|
||||||
|
unsigned dataDependentCount = 0;
|
||||||
|
for (Use &U : BI->operands()) {
|
||||||
|
|
||||||
|
if (Instruction *Op = dyn_cast<Instruction>(U.get())) {
|
||||||
|
|
||||||
|
if (DT->dominates(Op, &*I)) { controlDependentCount++; }
|
||||||
|
if (PDT->dominates(Op, &*I)) { dataDependentCount++; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controlDependentCount > maxControlDependentControls) {
|
||||||
|
|
||||||
|
maxControlDependentControls = controlDependentCount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataDependentCount > maxDataDependentControls) {
|
||||||
|
|
||||||
|
maxDataDependentControls = dataDependentCount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for if() without else
|
||||||
|
BasicBlock *TrueBB = BI->getSuccessor(0);
|
||||||
|
BasicBlock *FalseBB = BI->getSuccessor(1);
|
||||||
|
if (TrueBB && FalseBB) {
|
||||||
|
|
||||||
|
if (TrueBB->getSinglePredecessor() == &*I->getParent() &&
|
||||||
|
FalseBB->empty()) {
|
||||||
|
|
||||||
|
ifWithoutElseCount++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count variables involved in control predicates
|
||||||
|
if (ICmpInst *ICmp = dyn_cast<ICmpInst>(BI->getCondition())) {
|
||||||
|
|
||||||
|
controlPredicateVarCount += ICmp->getNumOperands();
|
||||||
|
|
||||||
|
} else if (BinaryOperator *BinOp =
|
||||||
|
|
||||||
|
dyn_cast<BinaryOperator>(BI->getCondition())) {
|
||||||
|
|
||||||
|
controlPredicateVarCount += BinOp->getNumOperands();
|
||||||
|
|
||||||
|
} else if (SelectInst *Select =
|
||||||
|
|
||||||
|
dyn_cast<SelectInst>(BI->getCondition())) {
|
||||||
|
|
||||||
|
controlPredicateVarCount += Select->getNumOperands();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
score = (unsigned int)(V1_WEIGHT * (double)paramCount +
|
||||||
|
V2_WEIGHT * (double)calledParamCount +
|
||||||
|
V3_WEIGHT * (double)pointerArithCount +
|
||||||
|
V4_WEIGHT * (double)totalPointerArithParams +
|
||||||
|
V5_WEIGHT * (double)maxPointerArithVars +
|
||||||
|
V6_WEIGHT * (double)nestedControlStructCount +
|
||||||
|
V7_WEIGHT * (double)maxNestingLevel +
|
||||||
|
V8_WEIGHT * (double)maxControlDependentControls +
|
||||||
|
V9_WEIGHT * (double)maxDataDependentControls +
|
||||||
|
V10_WEIGHT * (double)ifWithoutElseCount +
|
||||||
|
V11_WEIGHT * (double)controlPredicateVarCount);
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"VulnerabilityScore for %s: %u (paramCount=%u "
|
||||||
|
"calledParamCount=%u|pointerArithCount=%u totalPointerArithParams=%u "
|
||||||
|
"maxPointerArithVars=%u|maxNestingLevel=%u "
|
||||||
|
"maxControlDependentControls=%u maxDataDependentControls=%u "
|
||||||
|
"ifWithoutElseCount=%u controlPredicateVarCount=%u)\n",
|
||||||
|
F->getName().str().c_str(), score, paramCount, calledParamCount,
|
||||||
|
pointerArithCount, totalPointerArithParams, maxPointerArithVars,
|
||||||
|
maxNestingLevel, maxControlDependentControls,
|
||||||
|
maxDataDependentControls, ifWithoutElseCount,
|
||||||
|
controlPredicateVarCount);
|
||||||
|
|
||||||
|
return score;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
char *getBBName(const llvm::BasicBlock *BB) {
|
char *getBBName(const llvm::BasicBlock *BB) {
|
||||||
|
|
||||||
static char *name;
|
static char *name;
|
||||||
@ -91,7 +393,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
|||||||
|
|
||||||
for (auto const &ignoreListFunc : ignoreList) {
|
for (auto const &ignoreListFunc : ignoreList) {
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 19
|
||||||
|
if (F->getName().starts_with(ignoreListFunc)) { return true; }
|
||||||
|
#else
|
||||||
if (F->getName().startswith(ignoreListFunc)) { return true; }
|
if (F->getName().startswith(ignoreListFunc)) { return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "llvm/Config/llvm-config.h"
|
#include "llvm/Config/llvm-config.h"
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
|
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
|
||||||
typedef long double max_align_t;
|
typedef long double max_align_t;
|
||||||
#endif
|
#endif
|
||||||
@ -26,6 +27,19 @@ typedef long double max_align_t;
|
|||||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR > 12
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
|
#include "llvm/Analysis/LoopPass.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/IR/InstIterator.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
|
#include "llvm/IR/Operator.h"
|
||||||
|
#include "llvm/IR/Dominators.h"
|
||||||
|
#include "llvm/Analysis/PostDominators.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR > 3 || \
|
#if LLVM_VERSION_MAJOR > 3 || \
|
||||||
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
|
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
|
||||||
#include "llvm/IR/DebugInfo.h"
|
#include "llvm/IR/DebugInfo.h"
|
||||||
@ -55,6 +69,11 @@ void initInstrumentList();
|
|||||||
bool isInInstrumentList(llvm::Function *F, std::string Filename);
|
bool isInInstrumentList(llvm::Function *F, std::string Filename);
|
||||||
unsigned long long int calculateCollisions(uint32_t edges);
|
unsigned long long int calculateCollisions(uint32_t edges);
|
||||||
void scanForDangerousFunctions(llvm::Module *M);
|
void scanForDangerousFunctions(llvm::Module *M);
|
||||||
|
unsigned int calcCyclomaticComplexity(llvm::Function *F,
|
||||||
|
const llvm::LoopInfo *LI);
|
||||||
|
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
|
||||||
|
const llvm::DominatorTree *DT,
|
||||||
|
const llvm::PostDominatorTree *PDT);
|
||||||
|
|
||||||
#ifndef IS_EXTERN
|
#ifndef IS_EXTERN
|
||||||
#define IS_EXTERN
|
#define IS_EXTERN
|
||||||
|
@ -746,7 +746,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
|
|||||||
auto PA = PreservedAnalyses::all();
|
auto PA = PreservedAnalyses::all();
|
||||||
return PA;
|
return PA;
|
||||||
#else
|
#else
|
||||||
return true;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,11 @@ llvmGetPassPluginInfo() {
|
|||||||
#if LLVM_VERSION_MAJOR <= 13
|
#if LLVM_VERSION_MAJOR <= 13
|
||||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||||
#endif
|
#endif
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
PB.registerOptimizerEarlyEPCallback(
|
||||||
|
#else
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
#endif
|
||||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||||
|
|
||||||
MPM.addPass(AFLCoverage());
|
MPM.addPass(AFLCoverage());
|
||||||
@ -212,10 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
|||||||
u32 rand_seed;
|
u32 rand_seed;
|
||||||
unsigned int cur_loc = 0;
|
unsigned int cur_loc = 0;
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
|
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
|
||||||
gettimeofday(&tv, &tz);
|
gettimeofday(&tv, &tz);
|
||||||
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
||||||
@ -1081,7 +1081,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
return PA;
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -680,13 +680,16 @@ bool CmpLogInstructions::runOnModule(Module &M) {
|
|||||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
hookInstrs(M);
|
bool ret = hookInstrs(M);
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||||
return PreservedAnalyses::all();
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -758,16 +758,16 @@ bool CmpLogRoutines::runOnModule(Module &M) {
|
|||||||
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
hookRtns(M);
|
bool ret = hookRtns(M);
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
return PA;
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -442,16 +442,16 @@ bool CmplogSwitches::runOnModule(Module &M) {
|
|||||||
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
hookInstrs(M);
|
bool ret = hookInstrs(M);
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
return PA;
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,12 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include "afl-llvm-common.h"
|
#include "afl-llvm-common.h"
|
||||||
|
|
||||||
|
#if LLVM_MAJOR >= 19
|
||||||
|
#define STARTSWITH starts_with
|
||||||
|
#else
|
||||||
|
#define STARTSWITH startswith
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -89,7 +95,7 @@ class CompareTransform : public ModulePass {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return "cmplog transform";
|
return "compcov transform";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +129,11 @@ llvmGetPassPluginInfo() {
|
|||||||
#if LLVM_VERSION_MAJOR <= 13
|
#if LLVM_VERSION_MAJOR <= 13
|
||||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||||
#endif
|
#endif
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
PB.registerOptimizerEarlyEPCallback(
|
||||||
|
#else
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
#endif
|
||||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||||
|
|
||||||
MPM.addPass(CompareTransform());
|
MPM.addPass(CompareTransform());
|
||||||
@ -226,38 +236,38 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
|||||||
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
||||||
StringRef FuncName = Callee->getName();
|
StringRef FuncName = Callee->getName();
|
||||||
isStrcmp &=
|
isStrcmp &=
|
||||||
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
|
(!FuncName.compare("strcmp") /*|| !FuncName.compare("xmlStrcmp") ||
|
||||||
!FuncName.compare("xmlStrEqual") ||
|
!FuncName.compare("xmlStrEqual") ||
|
||||||
!FuncName.compare("curl_strequal") ||
|
!FuncName.compare("curl_strequal") ||
|
||||||
!FuncName.compare("strcsequal") ||
|
!FuncName.compare("strcsequal") ||
|
||||||
!FuncName.compare("g_strcmp0"));
|
!FuncName.compare("g_strcmp0")*/);
|
||||||
isMemcmp &=
|
isMemcmp &=
|
||||||
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
|
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
|
||||||
!FuncName.compare("CRYPTO_memcmp") ||
|
!FuncName.compare("CRYPTO_memcmp") ||
|
||||||
!FuncName.compare("OPENSSL_memcmp") ||
|
!FuncName.compare("OPENSSL_memcmp") ||
|
||||||
!FuncName.compare("memcmp_const_time") ||
|
!FuncName.compare("memcmp_const_time") ||
|
||||||
!FuncName.compare("memcmpct"));
|
!FuncName.compare("memcmpct"));
|
||||||
isStrncmp &= (!FuncName.compare("strncmp") ||
|
isStrncmp &= (!FuncName.compare("strncmp")/* ||
|
||||||
!FuncName.compare("curl_strnequal") ||
|
!FuncName.compare("curl_strnequal") ||
|
||||||
!FuncName.compare("xmlStrncmp"));
|
!FuncName.compare("xmlStrncmp")*/);
|
||||||
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
|
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
|
||||||
!FuncName.compare("stricmp") ||
|
!FuncName.compare("stricmp") ||
|
||||||
!FuncName.compare("ap_cstr_casecmp") ||
|
!FuncName.compare("ap_cstr_casecmp") ||
|
||||||
!FuncName.compare("OPENSSL_strcasecmp") ||
|
!FuncName.compare("OPENSSL_strcasecmp") ||
|
||||||
!FuncName.compare("xmlStrcasecmp") ||
|
/*!FuncName.compare("xmlStrcasecmp") ||
|
||||||
!FuncName.compare("g_strcasecmp") ||
|
!FuncName.compare("g_strcasecmp") ||
|
||||||
!FuncName.compare("g_ascii_strcasecmp") ||
|
!FuncName.compare("g_ascii_strcasecmp") ||
|
||||||
!FuncName.compare("Curl_strcasecompare") ||
|
!FuncName.compare("Curl_strcasecompare") ||
|
||||||
!FuncName.compare("Curl_safe_strcasecompare") ||
|
!FuncName.compare("Curl_safe_strcasecompare") ||*/
|
||||||
!FuncName.compare("cmsstrcasecmp"));
|
!FuncName.compare("cmsstrcasecmp"));
|
||||||
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
|
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
|
||||||
!FuncName.compare("strnicmp") ||
|
!FuncName.compare("strnicmp") ||
|
||||||
!FuncName.compare("ap_cstr_casecmpn") ||
|
!FuncName.compare("ap_cstr_casecmpn") ||
|
||||||
!FuncName.compare("OPENSSL_strncasecmp") ||
|
!FuncName.compare("OPENSSL_strncasecmp") /*||
|
||||||
!FuncName.compare("xmlStrncasecmp") ||
|
!FuncName.compare("xmlStrncasecmp") ||
|
||||||
!FuncName.compare("g_ascii_strncasecmp") ||
|
!FuncName.compare("g_ascii_strncasecmp") ||
|
||||||
!FuncName.compare("Curl_strncasecompare") ||
|
!FuncName.compare("Curl_strncasecompare") ||
|
||||||
!FuncName.compare("g_strncasecmp"));
|
!FuncName.compare("g_strncasecmp")*/);
|
||||||
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
|
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
|
||||||
|
|
||||||
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
|
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
|
||||||
@ -461,8 +471,20 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
|||||||
bool isCaseInsensitive = false;
|
bool isCaseInsensitive = false;
|
||||||
bool needs_null = false;
|
bool needs_null = false;
|
||||||
bool success_is_one = false;
|
bool success_is_one = false;
|
||||||
|
bool nullCheck = false;
|
||||||
Function *Callee = callInst->getCalledFunction();
|
Function *Callee = callInst->getCalledFunction();
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "%s - %s - %s\n",
|
||||||
|
callInst->getParent()
|
||||||
|
->getParent()
|
||||||
|
->getParent()
|
||||||
|
->getName()
|
||||||
|
.str()
|
||||||
|
.c_str(),
|
||||||
|
callInst->getParent()->getParent()->getName().str().c_str(),
|
||||||
|
Callee ? Callee->getName().str().c_str() : "NULL");*/
|
||||||
|
|
||||||
if (Callee) {
|
if (Callee) {
|
||||||
|
|
||||||
if (!Callee->getName().compare("memcmp") ||
|
if (!Callee->getName().compare("memcmp") ||
|
||||||
@ -516,6 +538,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isSizedcmp) needs_null = true;
|
if (!isSizedcmp) needs_null = true;
|
||||||
|
if (Callee->getName().STARTSWITH("g_") ||
|
||||||
|
Callee->getName().STARTSWITH("curl_") ||
|
||||||
|
Callee->getName().STARTSWITH("Curl_") ||
|
||||||
|
Callee->getName().STARTSWITH("xml"))
|
||||||
|
nullCheck = true;
|
||||||
|
|
||||||
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
|
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
|
||||||
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
|
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
|
||||||
@ -600,8 +627,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
|||||||
/* split before the call instruction */
|
/* split before the call instruction */
|
||||||
BasicBlock *bb = callInst->getParent();
|
BasicBlock *bb = callInst->getParent();
|
||||||
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
|
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
|
||||||
|
|
||||||
BasicBlock *next_lenchk_bb = NULL;
|
BasicBlock *next_lenchk_bb = NULL;
|
||||||
|
|
||||||
|
if (nullCheck) { fprintf(stderr, "TODO: null check\n"); }
|
||||||
|
|
||||||
if (isSizedcmp && !isConstSized) {
|
if (isSizedcmp && !isConstSized) {
|
||||||
|
|
||||||
next_lenchk_bb =
|
next_lenchk_bb =
|
||||||
@ -746,6 +775,8 @@ bool CompareTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
|
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
|
||||||
printf(
|
printf(
|
||||||
"Running compare-transform-pass by laf.intel@gmail.com, extended by "
|
"Running compare-transform-pass by laf.intel@gmail.com, extended by "
|
||||||
@ -753,11 +784,7 @@ bool CompareTransform::runOnModule(Module &M) {
|
|||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
if (transformCmps(M, true, true, true, true, true) == true) ret = true;
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
transformCmps(M, true, true, true, true, true);
|
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||||
@ -767,9 +794,18 @@ bool CompareTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
return PA;
|
if (ret == true) {
|
||||||
|
|
||||||
|
return PreservedAnalyses();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,8 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
|||||||
Function *FuncPtr;
|
Function *FuncPtr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
/* iterate over all functions, bbs and instruction and add suitable calls */
|
/* iterate over all functions, bbs and instruction and add suitable calls */
|
||||||
for (auto &F : M) {
|
for (auto &F : M) {
|
||||||
|
|
||||||
@ -281,6 +283,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
|||||||
|
|
||||||
IRBuilder<> IRB(callInst->getParent());
|
IRBuilder<> IRB(callInst->getParent());
|
||||||
IRB.SetInsertPoint(callInst);
|
IRB.SetInsertPoint(callInst);
|
||||||
|
ret = true;
|
||||||
|
|
||||||
Value *parameter = callInst->getArgOperand(param);
|
Value *parameter = callInst->getArgOperand(param);
|
||||||
|
|
||||||
@ -299,7 +302,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,16 +331,16 @@ bool InjectionRoutines::runOnModule(Module &M) {
|
|||||||
if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; }
|
if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; }
|
||||||
if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; }
|
if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; }
|
||||||
|
|
||||||
hookRtns(M);
|
bool ret = hookRtns(M);
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
return PA;
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 laf-intel
|
* Copyright 2016 laf-intel
|
||||||
* extended for floating point by Heiko Eißfeldt
|
* extended for floating point by Heiko Eissfeldt
|
||||||
* adapted to new pass manager by Heiko Eißfeldt
|
* adapted to new pass manager by Heiko Eissfeldt
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -189,7 +189,11 @@ llvmGetPassPluginInfo() {
|
|||||||
#if LLVM_VERSION_MAJOR <= 13
|
#if LLVM_VERSION_MAJOR <= 13
|
||||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||||
#endif
|
#endif
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
PB.registerOptimizerEarlyEPCallback(
|
||||||
|
#else
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
#endif
|
||||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||||
|
|
||||||
MPM.addPass(SplitComparesTransform());
|
MPM.addPass(SplitComparesTransform());
|
||||||
@ -262,8 +266,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
|
|||||||
|
|
||||||
/* this is probably not needed but we do it anyway */
|
/* this is probably not needed but we do it anyway */
|
||||||
if (TyOp0 != TyOp1) { continue; }
|
if (TyOp0 != TyOp1) { continue; }
|
||||||
|
|
||||||
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
|
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
|
||||||
|
int constants = 0;
|
||||||
|
if (llvm::isa<llvm::Constant>(op0)) { ++constants; }
|
||||||
|
if (llvm::isa<llvm::Constant>(op1)) { ++constants; }
|
||||||
|
if (constants != 1) { continue; }
|
||||||
|
|
||||||
fcomps.push_back(selectcmpInst);
|
fcomps.push_back(selectcmpInst);
|
||||||
|
|
||||||
@ -935,7 +942,7 @@ size_t SplitComparesTransform::nextPowerOfTwo(size_t in) {
|
|||||||
/* splits fcmps into two nested fcmps with sign compare and the rest */
|
/* splits fcmps into two nested fcmps with sign compare and the rest */
|
||||||
size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||||
|
|
||||||
size_t count = 0;
|
size_t counts = 0;
|
||||||
|
|
||||||
LLVMContext &C = M.getContext();
|
LLVMContext &C = M.getContext();
|
||||||
|
|
||||||
@ -951,7 +958,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return count;
|
return counts;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,7 +1011,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fcomps.size()) { return count; }
|
if (!fcomps.size()) { return counts; }
|
||||||
|
|
||||||
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
|
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
|
||||||
|
|
||||||
@ -1690,11 +1697,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
|||||||
#else
|
#else
|
||||||
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
|
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
|
||||||
#endif
|
#endif
|
||||||
++count;
|
++counts;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return counts;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1743,10 +1750,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_MAJOR >= 11
|
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (enableFPSplit) {
|
if (enableFPSplit) {
|
||||||
|
|
||||||
simplifyFPCompares(M);
|
simplifyFPCompares(M);
|
||||||
@ -1778,15 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
auto op0 = CI->getOperand(0);
|
auto op0 = CI->getOperand(0);
|
||||||
auto op1 = CI->getOperand(1);
|
auto op1 = CI->getOperand(1);
|
||||||
if (!op0 || !op1) {
|
// has to valid operands
|
||||||
|
if (!op0 || !op1) { continue; }
|
||||||
#if LLVM_MAJOR >= 11
|
// has exactly one constant and one variable
|
||||||
return PA;
|
int constants = 0;
|
||||||
#else
|
if (dyn_cast<ConstantInt>(op0)) { ++constants; }
|
||||||
return false;
|
if (dyn_cast<ConstantInt>(op1)) { ++constants; }
|
||||||
#endif
|
if (constants != 1) { continue; }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
|
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
|
||||||
if (iTy1 && isa<IntegerType>(op1->getType())) {
|
if (iTy1 && isa<IntegerType>(op1->getType())) {
|
||||||
@ -1814,6 +1815,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ret = count == 0 ? false : true;
|
||||||
|
|
||||||
bool brokenDebug = false;
|
bool brokenDebug = false;
|
||||||
if (verifyModule(M, &errs()
|
if (verifyModule(M, &errs()
|
||||||
#if LLVM_VERSION_MAJOR >= 4 || \
|
#if LLVM_VERSION_MAJOR >= 4 || \
|
||||||
@ -1852,9 +1855,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
return PA;
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,11 @@ llvmGetPassPluginInfo() {
|
|||||||
#if LLVM_VERSION_MAJOR <= 13
|
#if LLVM_VERSION_MAJOR <= 13
|
||||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||||
#endif
|
#endif
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
PB.registerOptimizerEarlyEPCallback(
|
||||||
|
#else
|
||||||
PB.registerOptimizerLastEPCallback(
|
PB.registerOptimizerLastEPCallback(
|
||||||
|
#endif
|
||||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||||
|
|
||||||
MPM.addPass(SplitSwitchesTransform());
|
MPM.addPass(SplitSwitchesTransform());
|
||||||
@ -516,11 +520,7 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
|
|||||||
else
|
else
|
||||||
be_quiet = 1;
|
be_quiet = 1;
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
bool ret = splitSwitches(M);
|
||||||
auto PA = PreservedAnalyses::all();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
splitSwitches(M);
|
|
||||||
verifyModule(M);
|
verifyModule(M);
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||||
@ -530,9 +530,12 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
|
|||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
return PA;
|
if (ret == false)
|
||||||
|
return PreservedAnalyses::all();
|
||||||
|
else
|
||||||
|
return PreservedAnalyses();
|
||||||
#else
|
#else
|
||||||
return true;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
e63c9af193
|
a6f0632a65
|
||||||
|
@ -215,8 +215,10 @@ if [ "$STATIC" = "1" ]; then
|
|||||||
echo Building STATIC binary
|
echo Building STATIC binary
|
||||||
|
|
||||||
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
|
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
|
||||||
|
# plugin support requires dynamic linking
|
||||||
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
||||||
--static --disable-pie \
|
--static --disable-pie \
|
||||||
|
--disable-plugins \
|
||||||
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
|
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
|
||||||
"
|
"
|
||||||
|
|
||||||
|
Submodule qemu_mode/qemuafl updated: e63c9af193...a6f0632a65
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
109
src/afl-cc.c
109
src/afl-cc.c
@ -17,6 +17,10 @@
|
|||||||
|
|
||||||
#define AFL_MAIN
|
#define AFL_MAIN
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -32,7 +36,9 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#if (LLVM_MAJOR - 0 == 0)
|
#if (LLVM_MAJOR - 0 == 0)
|
||||||
#undef LLVM_MAJOR
|
#undef LLVM_MAJOR
|
||||||
@ -464,6 +470,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) {
|
|||||||
*slash = 0;
|
*slash = 0;
|
||||||
tmp = alloc_printf("%s/%s", exepath, obj);
|
tmp = alloc_printf("%s/%s", exepath, obj);
|
||||||
|
|
||||||
|
if (aflcc->debug) DEBUGF("Trying %s\n", tmp);
|
||||||
|
|
||||||
if (!access(tmp, R_OK)) { return tmp; }
|
if (!access(tmp, R_OK)) { return tmp; }
|
||||||
|
|
||||||
ck_free(tmp);
|
ck_free(tmp);
|
||||||
@ -517,8 +525,8 @@ void find_built_deps(aflcc_state_t *aflcc) {
|
|||||||
|
|
||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
if ((ptr = find_object(aflcc, "as")) != NULL) {
|
if ((ptr = find_object(aflcc, "afl-as")) != NULL) {
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
// on OSX clang masquerades as GCC
|
// on OSX clang masquerades as GCC
|
||||||
@ -828,7 +836,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX;
|
if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX;
|
||||||
if (getenv("AFL_LLVM_CALLER"))
|
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") ||
|
||||||
|
getenv("AFL_LLVM_LTO_CTX"))
|
||||||
aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
|
aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
|
||||||
|
|
||||||
if (getenv("AFL_LLVM_NGRAM_SIZE")) {
|
if (getenv("AFL_LLVM_NGRAM_SIZE")) {
|
||||||
@ -1148,12 +1157,16 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM)
|
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM &&
|
||||||
|
!((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
|
||||||
|
aflcc->compiler_mode == LTO))
|
||||||
FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
|
FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
|
||||||
|
|
||||||
if (aflcc->instrument_opt_mode &&
|
if (aflcc->instrument_opt_mode &&
|
||||||
aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
|
aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
|
||||||
aflcc->instrument_mode != INSTRUMENT_CLASSIC)
|
aflcc->instrument_mode != INSTRUMENT_CLASSIC &&
|
||||||
|
!(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER &&
|
||||||
|
aflcc->compiler_mode == LTO))
|
||||||
FATAL(
|
FATAL(
|
||||||
"CALLER, CTX and NGRAM instrumentation options can only be used with "
|
"CALLER, CTX and NGRAM instrumentation options can only be used with "
|
||||||
"the LLVM CLASSIC instrumentation mode.");
|
"the LLVM CLASSIC instrumentation mode.");
|
||||||
@ -1256,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
|
|||||||
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
|
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
|
||||||
|
|
||||||
aflcc->lto_mode = 1;
|
aflcc->lto_mode = 1;
|
||||||
// force CFG
|
|
||||||
// if (!aflcc->instrument_mode) {
|
|
||||||
|
|
||||||
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
|
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
|
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
|
||||||
|
|
||||||
aflcc->lto_mode = 1;
|
aflcc->lto_mode = 1;
|
||||||
@ -1364,6 +1372,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_LLVM_DICT2FILE") &&
|
||||||
|
(getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
|
||||||
|
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
|
||||||
|
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
|
||||||
|
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")))
|
||||||
|
FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*");
|
||||||
|
|
||||||
aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") ||
|
aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") ||
|
||||||
getenv("AFL_GCC_CMPLOG");
|
getenv("AFL_GCC_CMPLOG");
|
||||||
|
|
||||||
@ -1571,8 +1586,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) {
|
|||||||
insert_param(aflcc,
|
insert_param(aflcc,
|
||||||
"-D__AFL_FUZZ_INIT()="
|
"-D__AFL_FUZZ_INIT()="
|
||||||
"int __afl_sharedmem_fuzzing = 1;"
|
"int __afl_sharedmem_fuzzing = 1;"
|
||||||
"extern unsigned int *__afl_fuzz_len;"
|
"extern __attribute__((visibility(\"default\"))) "
|
||||||
"extern unsigned char *__afl_fuzz_ptr;"
|
"unsigned int *__afl_fuzz_len;"
|
||||||
|
"extern __attribute__((visibility(\"default\"))) "
|
||||||
|
"unsigned char *__afl_fuzz_ptr;"
|
||||||
"unsigned char __afl_fuzz_alt[1048576];"
|
"unsigned char __afl_fuzz_alt[1048576];"
|
||||||
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
|
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
|
||||||
|
|
||||||
@ -1894,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_defs_fortify(aflcc, 0);
|
add_defs_fortify(aflcc, 0);
|
||||||
if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); }
|
if (!aflcc->have_asan) {
|
||||||
|
|
||||||
|
insert_param(aflcc, "-fsanitize=address");
|
||||||
|
insert_param(aflcc, "-fno-common");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
aflcc->have_asan = 1;
|
aflcc->have_asan = 1;
|
||||||
|
|
||||||
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
|
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
|
||||||
@ -2375,7 +2398,11 @@ void add_runtime(aflcc_state_t *aflcc) {
|
|||||||
if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
|
if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
|
||||||
strncmp(libdir, "/lib", 4)) {
|
strncmp(libdir, "/lib", 4)) {
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR);
|
||||||
|
#else
|
||||||
u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR);
|
u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR);
|
||||||
|
#endif
|
||||||
insert_param(aflcc, libdir_opt);
|
insert_param(aflcc, libdir_opt);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2457,13 +2484,60 @@ void add_runtime(aflcc_state_t *aflcc) {
|
|||||||
*/
|
*/
|
||||||
void add_assembler(aflcc_state_t *aflcc) {
|
void add_assembler(aflcc_state_t *aflcc) {
|
||||||
|
|
||||||
u8 *afl_as = find_object(aflcc, "as");
|
u8 *afl_as = find_object(aflcc, "afl-as");
|
||||||
|
|
||||||
if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as').");
|
if (!afl_as) FATAL("Cannot find 'afl-as'.");
|
||||||
|
|
||||||
u8 *slash = strrchr(afl_as, '/');
|
u8 *slash = strrchr(afl_as, '/');
|
||||||
if (slash) *slash = 0;
|
if (slash) *slash = 0;
|
||||||
|
|
||||||
|
// Search for 'as' may be unreliable in some cases (see #2058)
|
||||||
|
// so use 'afl-as' instead, because 'as' is usually a symbolic link,
|
||||||
|
// or can be a renamed copy of 'afl-as' created in the same dir.
|
||||||
|
// Now we should verify if the compiler can find the 'as' we need.
|
||||||
|
|
||||||
|
#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')"
|
||||||
|
|
||||||
|
u8 *afl_as_dup = alloc_printf("%s/as", afl_as);
|
||||||
|
|
||||||
|
int fd = open(afl_as_dup, O_RDONLY);
|
||||||
|
if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); }
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(fd, &st) < 0) {
|
||||||
|
|
||||||
|
PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 f_len = st.st_size;
|
||||||
|
|
||||||
|
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (f_data == MAP_FAILED) {
|
||||||
|
|
||||||
|
PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// "AFL_AS" is a const str passed to getenv in afl-as.c
|
||||||
|
if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. "
|
||||||
|
"It is a prerequisite to override system-wide 'as' for "
|
||||||
|
"instrumentation.",
|
||||||
|
afl_as_dup, afl_as);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
|
||||||
|
|
||||||
|
ck_free(afl_as_dup);
|
||||||
|
|
||||||
|
#undef AFL_AS_ERR
|
||||||
|
|
||||||
insert_param(aflcc, "-B");
|
insert_param(aflcc, "-B");
|
||||||
insert_param(aflcc, afl_as);
|
insert_param(aflcc, afl_as);
|
||||||
|
|
||||||
@ -2917,11 +2991,12 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
|||||||
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
|
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
|
||||||
"functions\n"
|
"functions\n"
|
||||||
" into this file (LTO mode)\n"
|
" into this file (LTO mode)\n"
|
||||||
|
" AFL_LLVM_LTO_CALLER: activate CALLER/CTX instrumentation\n"
|
||||||
|
" AFL_LLVM_LTO_CALLER_DEPTH: skip how many empty functions\n"
|
||||||
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
|
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
|
||||||
"global var\n"
|
"global var\n"
|
||||||
" AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
|
" AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
|
||||||
"a "
|
"a bb\n"
|
||||||
"bb\n"
|
|
||||||
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
||||||
"path\n"
|
"path\n"
|
||||||
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
|
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
@ -58,6 +59,27 @@ u8 last_intr = 0;
|
|||||||
#define AFL_PATH "/usr/local/lib/afl/"
|
#define AFL_PATH "/usr/local/lib/afl/"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* - Some BSD (i.e.: FreeBSD) offer the FAST clock source as
|
||||||
|
* equivalent to Linux COARSE clock source. Aliasing COARSE to
|
||||||
|
* FAST on such systems when COARSE is not already defined.
|
||||||
|
* - macOS has no support of CLOCK_MONOTONIC_COARSE clock type.
|
||||||
|
*/
|
||||||
|
#if defined(OS_DARWIN) || defined(OS_SUNOS) || defined(__APPLE__) || \
|
||||||
|
defined(__sun) || defined(__NetBSD__)
|
||||||
|
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
|
||||||
|
#elif defined(OS_FREEBSD)
|
||||||
|
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convert seconds to milliseconds. */
|
||||||
|
#define SEC_TO_MS(sec) ((sec) * 1000)
|
||||||
|
/* Convert seconds to microseconds. */
|
||||||
|
#define SEC_TO_US(sec) ((sec) * 1000000)
|
||||||
|
/* Convert nanoseconds to milliseconds. */
|
||||||
|
#define NS_TO_MS(ns) ((ns) / 1000000)
|
||||||
|
/* Convert nanoseconds to microseconds. */
|
||||||
|
#define NS_TO_US(ns) ((ns) / 1000)
|
||||||
|
|
||||||
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
|
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
|
||||||
size_t needlelen) {
|
size_t needlelen) {
|
||||||
|
|
||||||
@ -86,9 +108,10 @@ void set_sanitizer_defaults() {
|
|||||||
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
|
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
|
||||||
u8 have_san_options = 0;
|
u8 have_san_options = 0;
|
||||||
u8 default_options[1024] =
|
u8 default_options[1024] =
|
||||||
"detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
|
"detect_odr_violation=0:abort_on_error=1:symbolize=0:"
|
||||||
"return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
|
"allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
|
||||||
"sigfpe=0:handle_sigill=0:";
|
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:"
|
||||||
|
"detect_stack_use_after_return=0:check_initialization_order=0:";
|
||||||
|
|
||||||
if (have_asan_options || have_ubsan_options || have_msan_options ||
|
if (have_asan_options || have_ubsan_options || have_msan_options ||
|
||||||
have_lsan_options) {
|
have_lsan_options) {
|
||||||
@ -974,12 +997,16 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
|
|||||||
|
|
||||||
inline u64 get_cur_time(void) {
|
inline u64 get_cur_time(void) {
|
||||||
|
|
||||||
struct timeval tv;
|
struct timespec ts;
|
||||||
struct timezone tz;
|
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||||
|
if (rc == -1) {
|
||||||
|
|
||||||
gettimeofday(&tv, &tz);
|
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
|
}
|
||||||
|
|
||||||
|
return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,12 +1014,16 @@ inline u64 get_cur_time(void) {
|
|||||||
|
|
||||||
u64 get_cur_time_us(void) {
|
u64 get_cur_time_us(void) {
|
||||||
|
|
||||||
struct timeval tv;
|
struct timespec ts;
|
||||||
struct timezone tz;
|
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||||
|
if (rc == -1) {
|
||||||
|
|
||||||
gettimeofday(&tv, &tz);
|
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
}
|
||||||
|
|
||||||
|
return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -27,6 +27,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
#include "afl-fuzz.h"
|
||||||
|
#endif
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -389,7 +392,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
uint32_t was_killed;
|
uint32_t was_killed;
|
||||||
int status;
|
u32 status;
|
||||||
|
|
||||||
/* Wait for parent by reading from the pipe. Exit if read fails. */
|
/* Wait for parent by reading from the pipe. Exit if read fails. */
|
||||||
|
|
||||||
@ -524,7 +527,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
volatile u8 *stop_soon_p, u8 debug_child_output) {
|
volatile u8 *stop_soon_p, u8 debug_child_output) {
|
||||||
|
|
||||||
int st_pipe[2], ctl_pipe[2];
|
int st_pipe[2], ctl_pipe[2];
|
||||||
s32 status;
|
u32 status;
|
||||||
s32 rlen;
|
s32 rlen;
|
||||||
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
|
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
|
||||||
|
|
||||||
@ -575,7 +578,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
|
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
|
||||||
|
|
||||||
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
|
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
|
||||||
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
|
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
|
||||||
|
fsrv->max_length);
|
||||||
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
|
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
@ -724,7 +728,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* autodict in Nyx mode */
|
/* autodict in Nyx mode */
|
||||||
if (!ignore_autodict) {
|
if (!ignore_autodict && fsrv->add_extra_func) {
|
||||||
|
|
||||||
char *x =
|
char *x =
|
||||||
alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
|
alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
|
||||||
@ -1017,83 +1021,68 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
if (rlen == 4) {
|
if (rlen == 4) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The new fork server model works like this:
|
||||||
|
* Client: sends "AFLx" in little endian, with x being the forkserver
|
||||||
|
* protocol version.
|
||||||
|
* Server: replies with XOR of the message or exits with an error if it
|
||||||
|
* is not a supported version.
|
||||||
|
* Client: sends 32 bit of options and then sends all parameters of
|
||||||
|
* the options, one after another, increasing by option number.
|
||||||
|
* Ends with "AFLx".
|
||||||
|
* After the initial protocol version confirmation the server does not
|
||||||
|
* send any data anymore - except a future option requires this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((status & FS_NEW_ERROR) == FS_NEW_ERROR) {
|
||||||
|
|
||||||
|
report_error_and_exit(status & 0x0000ffff);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (status >= 0x41464c00 && status <= 0x41464cff) {
|
if (status >= 0x41464c00 && status <= 0x41464cff) {
|
||||||
|
|
||||||
FATAL(
|
u32 version = status - 0x41464c00;
|
||||||
"Target uses the new forkserver model, you need to switch to a newer "
|
|
||||||
"afl-fuzz too!");
|
|
||||||
|
|
||||||
}
|
if (!version) {
|
||||||
|
|
||||||
if (!be_quiet) { OKF("All right - fork server is up."); }
|
FATAL(
|
||||||
|
"Fork server version is not assigned, this should not happen. "
|
||||||
|
"Recompile target.");
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG")) {
|
} else if (version < FS_NEW_VERSION_MIN || version > FS_NEW_VERSION_MAX) {
|
||||||
|
|
||||||
ACTF("Extended forkserver functions received (%08x).", status);
|
FATAL(
|
||||||
|
"Fork server version is not not supported. Recompile the target.");
|
||||||
}
|
|
||||||
|
|
||||||
if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
|
|
||||||
report_error_and_exit(FS_OPT_GET_ERROR(status));
|
|
||||||
|
|
||||||
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
|
||||||
|
|
||||||
// workaround for recent AFL++ versions
|
|
||||||
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
|
|
||||||
status = (status & 0xf0ffffff);
|
|
||||||
|
|
||||||
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
|
|
||||||
|
|
||||||
if (fsrv->qemu_mode || fsrv->frida_mode) {
|
|
||||||
|
|
||||||
report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
report_error_and_exit(FS_ERROR_OLD_CMPLOG);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
|
u32 keep = status;
|
||||||
|
status ^= 0xffffffff;
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
fsrv->snapshot = 1;
|
FATAL("Writing to forkserver failed.");
|
||||||
if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
|
if (!be_quiet) {
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz) {
|
OKF("All right - new fork server model v%u is up.", version);
|
||||||
|
|
||||||
fsrv->use_shmem_fuzz = 1;
|
|
||||||
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
|
||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
|
|
||||||
|
|
||||||
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
|
||||||
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Writing to forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
FATAL(
|
|
||||||
"Target requested sharedmem fuzzing, but we failed to enable "
|
|
||||||
"it.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
rlen = read(fsrv->fsrv_st_fd, &status, 4);
|
||||||
|
|
||||||
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
|
ACTF("Forkserver options received: (0x%08x)", status);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_NEW_OPT_MAPSIZE)) {
|
||||||
|
|
||||||
|
u32 tmp_map_size;
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, &tmp_map_size, 4);
|
||||||
|
|
||||||
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
||||||
|
|
||||||
@ -1110,7 +1099,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
FATAL(
|
FATAL(
|
||||||
"Target's coverage map size of %u is larger than the one this "
|
"Target's coverage map size of %u is larger than the one this "
|
||||||
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
|
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
|
||||||
|
"restart "
|
||||||
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
||||||
"afl-fuzz",
|
"afl-fuzz",
|
||||||
tmp_map_size, fsrv->map_size, tmp_map_size);
|
tmp_map_size, fsrv->map_size, tmp_map_size);
|
||||||
@ -1119,22 +1109,261 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
fsrv->map_size = tmp_map_size;
|
fsrv->map_size = tmp_map_size;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fsrv->real_map_size = fsrv->map_size = MAP_SIZE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
if (status & FS_NEW_OPT_SHDMEM_FUZZ) {
|
||||||
|
|
||||||
if (!ignore_autodict) {
|
if (fsrv->support_shmem_fuzz) {
|
||||||
|
|
||||||
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
fsrv->use_shmem_fuzz = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Target requested sharedmem fuzzing, but we failed to enable "
|
||||||
|
"it.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & FS_NEW_OPT_AUTODICT) {
|
||||||
|
|
||||||
|
// even if we do not need the dictionary we have to read it
|
||||||
|
|
||||||
|
u32 dict_size;
|
||||||
|
if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Reading from forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict_size < 2 || dict_size > 0xffffff) {
|
||||||
|
|
||||||
|
FATAL("Dictionary has an illegal size: %d", dict_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 offset = 0, count = 0;
|
||||||
|
u8 *dict = ck_alloc(dict_size);
|
||||||
|
if (dict == NULL) {
|
||||||
|
|
||||||
|
FATAL("Could not allocate %u bytes of autodictionary memory",
|
||||||
|
dict_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset < dict_size) {
|
||||||
|
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size - offset);
|
||||||
|
if (rlen > 0) {
|
||||||
|
|
||||||
|
offset += rlen;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Reading autodictionary fail at position %u with %u bytes "
|
||||||
|
"left.",
|
||||||
|
offset, dict_size - offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
|
||||||
|
|
||||||
|
if (!ignore_autodict && fsrv->add_extra_func) {
|
||||||
|
|
||||||
|
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||||
|
(u8)dict[offset]);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += (1 + dict[offset]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet && count) {
|
||||||
|
|
||||||
|
ACTF("Loaded %u autodictionary entries", count);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_free(dict);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 status2;
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, &status2, 4);
|
||||||
|
|
||||||
|
if (status2 != keep) {
|
||||||
|
|
||||||
|
FATAL("Error in forkserver communication (%08x=>%08x)", keep, status2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!fsrv->qemu_mode && !fsrv->cs_mode
|
||||||
|
#ifdef __linux__
|
||||||
|
&& !fsrv->nyx_mode
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"Old fork server model is used by the target, this still works "
|
||||||
|
"though.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { OKF("All right - old fork server is up."); }
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
|
ACTF("Extended forkserver functions received (%08x).", status);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
|
||||||
|
report_error_and_exit(FS_OPT_GET_ERROR(status));
|
||||||
|
|
||||||
|
if (fsrv->cmplog_binary && !fsrv->qemu_mode) {
|
||||||
|
|
||||||
|
FATAL("Target was compiled with outdated CMPLOG, recompile it!\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
||||||
|
|
||||||
|
// workaround for recent AFL++ versions
|
||||||
|
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) ==
|
||||||
|
FS_OPT_OLD_AFLPP_WORKAROUND)
|
||||||
|
status = (status & 0xf0ffffff);
|
||||||
|
|
||||||
|
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
|
||||||
|
|
||||||
|
if (fsrv->qemu_mode || fsrv->frida_mode) {
|
||||||
|
|
||||||
|
report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
report_error_and_exit(FS_ERROR_OLD_CMPLOG);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
|
||||||
|
|
||||||
|
fsrv->snapshot = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
|
||||||
|
|
||||||
|
if (fsrv->support_shmem_fuzz) {
|
||||||
|
|
||||||
|
fsrv->use_shmem_fuzz = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
|
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
|
||||||
|
|
||||||
|
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Writing to forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Target requested sharedmem fuzzing, but we failed to enable "
|
||||||
|
"it.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
||||||
|
|
||||||
|
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
||||||
|
|
||||||
|
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
||||||
|
|
||||||
|
fsrv->real_map_size = tmp_map_size;
|
||||||
|
|
||||||
|
if (tmp_map_size % 64) {
|
||||||
|
|
||||||
|
tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
|
||||||
|
if (tmp_map_size > fsrv->map_size) {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Target's coverage map size of %u is larger than the one this "
|
||||||
|
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
|
||||||
|
"restart "
|
||||||
|
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
||||||
|
"afl-fuzz",
|
||||||
|
tmp_map_size, fsrv->map_size, tmp_map_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fsrv->map_size = tmp_map_size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
||||||
|
|
||||||
|
if (!ignore_autodict) {
|
||||||
|
|
||||||
|
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
||||||
|
|
||||||
|
// this is not afl-fuzz - or it is cmplog - we deny and return
|
||||||
|
if (fsrv->use_shmem_fuzz) {
|
||||||
|
|
||||||
|
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
status = (FS_OPT_ENABLED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Writing to forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
|
||||||
|
|
||||||
// this is not afl-fuzz - or it is cmplog - we deny and return
|
|
||||||
if (fsrv->use_shmem_fuzz) {
|
if (fsrv->use_shmem_fuzz) {
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED);
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,82 +1373,63 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
}
|
FATAL("Reading from forkserver failed.");
|
||||||
|
|
||||||
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
|
|
||||||
|
|
||||||
if (fsrv->use_shmem_fuzz) {
|
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Writing to forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Reading from forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status < 2 || (u32)status > 0xffffff) {
|
|
||||||
|
|
||||||
FATAL("Dictionary has an illegal size: %d", status);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = 0, count = 0;
|
|
||||||
u32 len = status;
|
|
||||||
u8 *dict = ck_alloc(len);
|
|
||||||
if (dict == NULL) {
|
|
||||||
|
|
||||||
FATAL("Could not allocate %u bytes of autodictionary memory", len);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len != 0) {
|
|
||||||
|
|
||||||
rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
|
|
||||||
if (rlen > 0) {
|
|
||||||
|
|
||||||
len -= rlen;
|
|
||||||
offset += rlen;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
FATAL(
|
|
||||||
"Reading autodictionary fail at position %u with %u bytes "
|
|
||||||
"left.",
|
|
||||||
offset, len);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (status < 2 || (u32)status > 0xffffff) {
|
||||||
|
|
||||||
offset = 0;
|
FATAL("Dictionary has an illegal size: %d", status);
|
||||||
while (offset < (u32)status &&
|
|
||||||
(u8)dict[offset] + offset < (u32)status) {
|
|
||||||
|
|
||||||
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
}
|
||||||
(u8)dict[offset]);
|
|
||||||
offset += (1 + dict[offset]);
|
u32 offset = 0, count = 0;
|
||||||
count++;
|
u32 len = status;
|
||||||
|
u8 *dict = ck_alloc(len);
|
||||||
|
if (dict == NULL) {
|
||||||
|
|
||||||
|
FATAL("Could not allocate %u bytes of autodictionary memory",
|
||||||
|
len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len != 0) {
|
||||||
|
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
|
||||||
|
if (rlen > 0) {
|
||||||
|
|
||||||
|
len -= rlen;
|
||||||
|
offset += rlen;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Reading autodictionary fail at position %u with %u bytes "
|
||||||
|
"left.",
|
||||||
|
offset, len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
while (offset < (u32)status &&
|
||||||
|
(u8)dict[offset] + offset < (u32)status) {
|
||||||
|
|
||||||
|
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||||
|
(u8)dict[offset]);
|
||||||
|
offset += (1 + dict[offset]);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
||||||
|
ck_free(dict);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
|
||||||
ck_free(dict);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1599,6 +1809,11 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
u32 exec_ms;
|
u32 exec_ms;
|
||||||
u32 write_value = fsrv->last_run_timed_out;
|
u32 write_value = fsrv->last_run_timed_out;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
fsrv_run_result_t retval = FSRV_RUN_OK;
|
||||||
|
char *persistent_out_fmt;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (fsrv->nyx_mode) {
|
if (fsrv->nyx_mode) {
|
||||||
|
|
||||||
@ -1628,6 +1843,8 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
case Timeout:
|
case Timeout:
|
||||||
return FSRV_RUN_TMOUT;
|
return FSRV_RUN_TMOUT;
|
||||||
case InvalidWriteToPayload:
|
case InvalidWriteToPayload:
|
||||||
|
if (!!getenv("AFL_NYX_HANDLE_INVALID_WRITE")) { return FSRV_RUN_CRASH; }
|
||||||
|
|
||||||
/* ??? */
|
/* ??? */
|
||||||
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
|
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
|
||||||
break;
|
break;
|
||||||
@ -1661,7 +1878,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
territory. */
|
territory. */
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (!fsrv->nyx_mode) {
|
if (likely(!fsrv->nyx_mode)) {
|
||||||
|
|
||||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||||
MEM_BARRIER();
|
MEM_BARRIER();
|
||||||
@ -1731,7 +1948,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
|
|
||||||
if (exec_ms > timeout) {
|
if (exec_ms > timeout) {
|
||||||
|
|
||||||
/* If there was no response from forkserver after timeout seconds,
|
/* If there was no response from forkserver after timeout milliseconds,
|
||||||
we kill the child. The forkserver should inform us afterwards */
|
we kill the child. The forkserver should inform us afterwards */
|
||||||
|
|
||||||
s32 tmp_pid = fsrv->child_pid;
|
s32 tmp_pid = fsrv->child_pid;
|
||||||
@ -1798,6 +2015,18 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
if (unlikely(fsrv->last_run_timed_out)) {
|
if (unlikely(fsrv->last_run_timed_out)) {
|
||||||
|
|
||||||
fsrv->last_kill_signal = fsrv->child_kill_signal;
|
fsrv->last_kill_signal = fsrv->child_kill_signal;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
if (unlikely(fsrv->persistent_record)) {
|
||||||
|
|
||||||
|
retval = FSRV_RUN_TMOUT;
|
||||||
|
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u%s%s";
|
||||||
|
goto store_persistent_record;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
return FSRV_RUN_TMOUT;
|
return FSRV_RUN_TMOUT;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1819,42 +2048,21 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
(fsrv->uses_crash_exitcode &&
|
(fsrv->uses_crash_exitcode &&
|
||||||
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
|
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
|
||||||
|
|
||||||
|
/* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
|
||||||
|
fsrv->last_kill_signal =
|
||||||
|
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
|
||||||
|
|
||||||
#ifdef AFL_PERSISTENT_RECORD
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
if (unlikely(fsrv->persistent_record)) {
|
if (unlikely(fsrv->persistent_record)) {
|
||||||
|
|
||||||
char fn[PATH_MAX];
|
retval = FSRV_RUN_CRASH;
|
||||||
u32 i, writecnt = 0;
|
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u%s%s";
|
||||||
for (i = 0; i < fsrv->persistent_record; ++i) {
|
goto store_persistent_record;
|
||||||
|
|
||||||
u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record;
|
|
||||||
u8 *data = fsrv->persistent_record_data[entry];
|
|
||||||
u32 len = fsrv->persistent_record_len[entry];
|
|
||||||
if (likely(len && data)) {
|
|
||||||
|
|
||||||
snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u",
|
|
||||||
fsrv->persistent_record_dir, fsrv->persistent_record_cnt,
|
|
||||||
writecnt++);
|
|
||||||
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
|
||||||
if (fd >= 0) {
|
|
||||||
|
|
||||||
ck_write(fd, data, len, fn);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
++fsrv->persistent_record_cnt;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
|
|
||||||
fsrv->last_kill_signal =
|
|
||||||
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
|
|
||||||
return FSRV_RUN_CRASH;
|
return FSRV_RUN_CRASH;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1862,6 +2070,45 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
|||||||
/* success :) */
|
/* success :) */
|
||||||
return FSRV_RUN_OK;
|
return FSRV_RUN_OK;
|
||||||
|
|
||||||
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
store_persistent_record: {
|
||||||
|
|
||||||
|
char fn[PATH_MAX];
|
||||||
|
u32 i, writecnt = 0;
|
||||||
|
for (i = 0; i < fsrv->persistent_record; ++i) {
|
||||||
|
|
||||||
|
u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record;
|
||||||
|
u8 *data = fsrv->persistent_record_data[entry];
|
||||||
|
u32 len = fsrv->persistent_record_len[entry];
|
||||||
|
if (likely(len && data)) {
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
|
||||||
|
fsrv->persistent_record_cnt, writecnt++,
|
||||||
|
((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "",
|
||||||
|
((afl_state_t *)(fsrv->afl_ptr))->file_extension
|
||||||
|
? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension
|
||||||
|
: "");
|
||||||
|
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||||
|
if (fd >= 0) {
|
||||||
|
|
||||||
|
ck_write(fd, data, len, fn);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
++fsrv->persistent_record_cnt;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void afl_fsrv_killall() {
|
void afl_fsrv_killall() {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -481,6 +481,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
s32 fd;
|
s32 fd;
|
||||||
u64 cksum = 0;
|
u64 cksum = 0;
|
||||||
|
|
||||||
|
// will be classified away otherwise
|
||||||
|
if (unlikely((afl->current_score = *(u32 *)((u8 *)afl->fsrv.trace_bits + 1)) >
|
||||||
|
0)) {
|
||||||
|
|
||||||
|
memset(afl->fsrv.trace_bits + 1, 0, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Update path frequency. */
|
/* Update path frequency. */
|
||||||
|
|
||||||
/* Generating a hash on every input is super expensive. Bad idea and should
|
/* Generating a hash on every input is super expensive. Bad idea and should
|
||||||
@ -527,21 +535,41 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
queue_fn =
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_items,
|
|
||||||
describe_op(afl, new_bits + is_timeout,
|
queue_fn = alloc_printf(
|
||||||
NAME_MAX - strlen("id:000000,")));
|
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
|
||||||
|
describe_op(afl, new_bits + is_timeout,
|
||||||
|
NAME_MAX - strlen("id:000000,")),
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const char *hex = sha1_hex(mem, len);
|
||||||
|
queue_fn = alloc_printf(
|
||||||
|
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
ck_free((char *)hex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
queue_fn =
|
queue_fn = alloc_printf(
|
||||||
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items);
|
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
fd = permissive_create(afl, queue_fn);
|
||||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
|
if (likely(fd >= 0)) {
|
||||||
ck_write(fd, mem, len, queue_fn);
|
|
||||||
close(fd);
|
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);
|
||||||
|
|
||||||
if (unlikely(afl->fuzz_mode) &&
|
if (unlikely(afl->fuzz_mode) &&
|
||||||
@ -739,14 +767,29 @@ 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,
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
afl->saved_hangs,
|
|
||||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
|
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
|
||||||
|
afl->saved_hangs,
|
||||||
|
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const char *hex = sha1_hex(mem, len);
|
||||||
|
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
ck_free((char *)hex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
|
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir,
|
||||||
afl->saved_hangs);
|
afl->saved_hangs, afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
|
|
||||||
@ -792,14 +835,30 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
|
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
|
||||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
|
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
|
||||||
|
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||||
|
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const char *hex = sha1_hex(mem, len);
|
||||||
|
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
ck_free((char *)hex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
|
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
|
||||||
afl->saved_crashes, afl->fsrv.last_kill_signal);
|
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
|
|
||||||
@ -862,10 +921,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
|||||||
/* If we're here, we apparently want to save the crash or hang
|
/* If we're here, we apparently want to save the crash or hang
|
||||||
test case, too. */
|
test case, too. */
|
||||||
|
|
||||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
fd = permissive_create(afl, fn);
|
||||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
|
if (fd >= 0) {
|
||||||
ck_write(fd, mem, len, fn);
|
|
||||||
close(fd);
|
ck_write(fd, mem, len, fn);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {
|
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -742,8 +742,11 @@ void save_auto(afl_state_t *afl) {
|
|||||||
|
|
||||||
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
|
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
|
||||||
|
|
||||||
u8 *fn =
|
u8 *fn = alloc_printf(
|
||||||
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
|
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
s32 fd;
|
s32 fd;
|
||||||
|
|
||||||
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
|
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -459,6 +459,24 @@ void bind_to_free_cpu(afl_state_t *afl) {
|
|||||||
|
|
||||||
#endif /* HAVE_AFFINITY */
|
#endif /* HAVE_AFFINITY */
|
||||||
|
|
||||||
|
/* transforms spaces in a string to underscores (inplace) */
|
||||||
|
|
||||||
|
static void no_spaces(u8 *string) {
|
||||||
|
|
||||||
|
if (string) {
|
||||||
|
|
||||||
|
u8 *ptr = string;
|
||||||
|
while (*ptr != 0) {
|
||||||
|
|
||||||
|
if (*ptr == ' ') { *ptr = '_'; }
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Shuffle an array of pointers. Might be slightly biased. */
|
/* Shuffle an array of pointers. Might be slightly biased. */
|
||||||
|
|
||||||
static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
|
static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
|
||||||
@ -559,6 +577,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
|||||||
afl->stage_cur = 0;
|
afl->stage_cur = 0;
|
||||||
afl->stage_max = 0;
|
afl->stage_max = 0;
|
||||||
|
|
||||||
|
show_stats(afl);
|
||||||
|
|
||||||
for (i = 0; i < (u32)nl_cnt; ++i) {
|
for (i = 0; i < (u32)nl_cnt; ++i) {
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -637,7 +657,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
|||||||
munmap(mem, st.st_size);
|
munmap(mem, st.st_size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
|
if (st.st_mtime > mtime_max) {
|
||||||
|
|
||||||
|
mtime_max = st.st_mtime;
|
||||||
|
show_stats(afl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,6 +939,14 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
|
|
||||||
res = calibrate_case(afl, q, use_mem, 0, 1);
|
res = calibrate_case(afl, q, use_mem, 0, 1);
|
||||||
|
|
||||||
|
/* For AFLFast schedules we update the queue entry */
|
||||||
|
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) &&
|
||||||
|
likely(q->exec_cksum)) {
|
||||||
|
|
||||||
|
q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (afl->stop_soon) { return; }
|
if (afl->stop_soon) { return; }
|
||||||
|
|
||||||
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
|
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
|
||||||
@ -1157,18 +1190,35 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
|
|
||||||
#ifndef SIMPLE_FILES
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
|
||||||
describe_op(afl, 0,
|
snprintf(
|
||||||
NAME_MAX - strlen("id:000000,sig:00,") -
|
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
|
||||||
strlen(use_name)),
|
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||||
use_name);
|
describe_op(
|
||||||
|
afl, 0,
|
||||||
|
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
|
||||||
|
use_name, afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const char *hex = sha1_hex(use_mem, read_len);
|
||||||
|
snprintf(
|
||||||
|
crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
ck_free((char *)hex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
|
snprintf(
|
||||||
afl->out_dir, afl->saved_crashes,
|
crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
|
||||||
afl->fsrv.last_kill_signal);
|
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1372,11 +1422,11 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
static void link_or_copy(u8 *old_path, u8 *new_path) {
|
static void link_or_copy(u8 *old_path, u8 *new_path) {
|
||||||
|
|
||||||
s32 i = link(old_path, new_path);
|
s32 i = link(old_path, new_path);
|
||||||
|
if (!i) { return; }
|
||||||
|
|
||||||
s32 sfd, dfd;
|
s32 sfd, dfd;
|
||||||
u8 *tmp;
|
u8 *tmp;
|
||||||
|
|
||||||
if (!i) { return; }
|
|
||||||
|
|
||||||
sfd = open(old_path, O_RDONLY);
|
sfd = open(old_path, O_RDONLY);
|
||||||
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
|
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
|
||||||
|
|
||||||
@ -1439,7 +1489,9 @@ void pivot_inputs(afl_state_t *afl) {
|
|||||||
u32 src_id;
|
u32 src_id;
|
||||||
|
|
||||||
afl->resuming_fuzz = 1;
|
afl->resuming_fuzz = 1;
|
||||||
nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
|
nfn = alloc_printf(
|
||||||
|
"%s/queue/%s%s%s", afl->out_dir, rsl, afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
/* Since we're at it, let's also get the parent and figure out the
|
/* Since we're at it, let's also get the parent and figure out the
|
||||||
appropriate depth for this entry. */
|
appropriate depth for this entry. */
|
||||||
@ -1479,12 +1531,33 @@ void pivot_inputs(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
|
if (!afl->afl_env.afl_sha1_filenames) {
|
||||||
afl->out_dir, id, afl->fsrv.total_execs, use_name);
|
|
||||||
|
nfn = alloc_printf(
|
||||||
|
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
|
||||||
|
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const char *hex = sha1_hex_for_file(q->fname, q->len);
|
||||||
|
nfn = alloc_printf(
|
||||||
|
"%s/queue/%s%s%s", afl->out_dir, hex,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
ck_free((char *)hex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *pos = strrchr(nfn, '/');
|
||||||
|
no_spaces(pos + 30);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
|
nfn = alloc_printf(
|
||||||
|
"%s/queue/id_%06u%s%s", afl->out_dir, id,
|
||||||
|
afl->file_extension ? "." : "",
|
||||||
|
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||||
|
|
||||||
#endif /* ^!SIMPLE_FILES */
|
#endif /* ^!SIMPLE_FILES */
|
||||||
|
|
||||||
@ -1691,10 +1764,11 @@ double get_runnable_processes(void) {
|
|||||||
|
|
||||||
void nuke_resume_dir(afl_state_t *afl) {
|
void nuke_resume_dir(afl_state_t *afl) {
|
||||||
|
|
||||||
u8 *fn;
|
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
|
||||||
|
u8 *fn;
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
|
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
|
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
|
||||||
@ -1702,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) {
|
|||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
|
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
|
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
|
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
|
||||||
@ -1714,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) {
|
|||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/_resume", afl->out_dir);
|
fn = alloc_printf("%s/_resume", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1731,8 +1805,9 @@ dir_cleanup_failed:
|
|||||||
|
|
||||||
static void handle_existing_out_dir(afl_state_t *afl) {
|
static void handle_existing_out_dir(afl_state_t *afl) {
|
||||||
|
|
||||||
FILE *f;
|
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
|
||||||
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
|
FILE *f;
|
||||||
|
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
|
||||||
|
|
||||||
/* See if the output directory is locked. If yes, bail out. If not,
|
/* See if the output directory is locked. If yes, bail out. If not,
|
||||||
create a lock that will persist for the lifetime of the process
|
create a lock that will persist for the lifetime of the process
|
||||||
@ -1854,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
|||||||
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
|
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
|
||||||
|
|
||||||
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
|
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
|
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
|
||||||
@ -1862,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
|||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
|
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
|
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
/* Then, get rid of the .state subdirectory itself (should be empty by now)
|
/* Then, get rid of the .state subdirectory itself (should be empty by now)
|
||||||
@ -1877,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
|||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/queue", afl->out_dir);
|
fn = alloc_printf("%s/queue", afl->out_dir);
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
/* All right, let's do <afl->out_dir>/crashes/id:* and
|
/* All right, let's do <afl->out_dir>/crashes/id:* and
|
||||||
@ -1921,7 +1996,10 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
delete_files(fn, RECORD_PREFIX);
|
||||||
|
#endif
|
||||||
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
fn = alloc_printf("%s/hangs", afl->out_dir);
|
fn = alloc_printf("%s/hangs", afl->out_dir);
|
||||||
@ -1953,7 +2031,10 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
#ifdef AFL_PERSISTENT_RECORD
|
||||||
|
delete_files(fn, RECORD_PREFIX);
|
||||||
|
#endif
|
||||||
|
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||||
ck_free(fn);
|
ck_free(fn);
|
||||||
|
|
||||||
/* And now, for some finishing touches. */
|
/* And now, for some finishing touches. */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Shengtuo Hu
|
Originally written by Shengtuo Hu
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -60,37 +60,80 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define DEBUG_QUEUE 1
|
||||||
double compute_weight(afl_state_t *afl, struct queue_entry *q,
|
double compute_weight(afl_state_t *afl, struct queue_entry *q,
|
||||||
double avg_exec_us, double avg_bitmap_size,
|
double avg_exec_us, double avg_bitmap_size,
|
||||||
double avg_top_size) {
|
double avg_top_size, double avg_score) {
|
||||||
|
|
||||||
double weight = 1.0;
|
if (likely(avg_score > 0)) {
|
||||||
|
|
||||||
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
return q->score / avg_score;
|
||||||
|
|
||||||
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
|
} else {
|
||||||
if (likely(hits)) { weight /= (log10(hits) + 1); }
|
|
||||||
|
double weight = 1.0;
|
||||||
|
|
||||||
|
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||||
|
|
||||||
|
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
|
||||||
|
if (likely(hits)) { weight /= (log10(hits) + 1); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, "WEIGHT id=%u fname=%s start_weight=1.0\n", q->id,
|
||||||
|
q->fname);
|
||||||
|
fprintf(stderr, " after step 1: %.2f (log10(hits))\n", weight);
|
||||||
|
#endif
|
||||||
|
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 2: %.2f (exec_us)\n", weight);
|
||||||
|
#endif
|
||||||
|
weight *= (log(q->bitmap_size) / avg_bitmap_size);
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 3: %.2f (log(bitmap_size))\n", weight);
|
||||||
|
#endif
|
||||||
|
weight *= (1 + (q->tc_ref / avg_top_size));
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 4: %.2f (top_size)\n", weight);
|
||||||
|
#endif
|
||||||
|
if (unlikely(avg_score != 0.0)) { weight *= (q->score / avg_score); }
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 5: %.2f (score)\n", weight);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (unlikely(weight < 0.1)) { weight = 0.1; }
|
||||||
|
if (unlikely(q->favored)) {
|
||||||
|
|
||||||
|
weight += 1;
|
||||||
|
weight *= 5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 6: %.2f (favored)\n", weight);
|
||||||
|
#endif
|
||||||
|
if (unlikely(!q->was_fuzzed)) { weight *= 2.5; }
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after step 7: %.2f (was_fuzzed)\n", weight);
|
||||||
|
#endif
|
||||||
|
if (unlikely(q->fs_redundant)) { weight *= 0.75; }
|
||||||
|
#ifdef DEBUG_QUEUE
|
||||||
|
fprintf(stderr, " after final step: %.2f (fs_redundant)\n", weight);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return weight;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
|
|
||||||
weight *= (log(q->bitmap_size) / avg_bitmap_size);
|
|
||||||
weight *= (1 + (q->tc_ref / avg_top_size));
|
|
||||||
|
|
||||||
if (unlikely(weight < 0.1)) { weight = 0.1; }
|
|
||||||
if (unlikely(q->favored)) { weight *= 5; }
|
|
||||||
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
|
|
||||||
if (unlikely(q->fs_redundant)) { weight *= 0.8; }
|
|
||||||
|
|
||||||
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_items, i = 0, nSmall = 0, nLarge = n - 1;
|
u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1,
|
||||||
|
exploit = afl->fuzz_mode;
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
|
|
||||||
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
|
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
|
||||||
@ -118,6 +161,7 @@ void create_alias_table(afl_state_t *afl) {
|
|||||||
double avg_exec_us = 0.0;
|
double avg_exec_us = 0.0;
|
||||||
double avg_bitmap_size = 0.0;
|
double avg_bitmap_size = 0.0;
|
||||||
double avg_top_size = 0.0;
|
double avg_top_size = 0.0;
|
||||||
|
double avg_score = 0.0;
|
||||||
u32 active = 0;
|
u32 active = 0;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@ -130,6 +174,7 @@ void create_alias_table(afl_state_t *afl) {
|
|||||||
avg_exec_us += q->exec_us;
|
avg_exec_us += q->exec_us;
|
||||||
avg_bitmap_size += log(q->bitmap_size);
|
avg_bitmap_size += log(q->bitmap_size);
|
||||||
avg_top_size += q->tc_ref;
|
avg_top_size += q->tc_ref;
|
||||||
|
if (exploit) { avg_score += /*log(*/ q->score /*)*/; }
|
||||||
++active;
|
++active;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -140,14 +185,16 @@ void create_alias_table(afl_state_t *afl) {
|
|||||||
avg_bitmap_size /= active;
|
avg_bitmap_size /= active;
|
||||||
avg_top_size /= active;
|
avg_top_size /= active;
|
||||||
|
|
||||||
|
if (exploit) { avg_score /= active; }
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
|
||||||
struct queue_entry *q = afl->queue_buf[i];
|
struct queue_entry *q = afl->queue_buf[i];
|
||||||
|
|
||||||
if (likely(!q->disabled)) {
|
if (likely(!q->disabled)) {
|
||||||
|
|
||||||
q->weight =
|
q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size,
|
||||||
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
|
avg_top_size, avg_score);
|
||||||
q->perf_score = calculate_score(afl, q);
|
q->perf_score = calculate_score(afl, q);
|
||||||
sum += q->weight;
|
sum += q->weight;
|
||||||
|
|
||||||
@ -370,9 +417,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
|||||||
|
|
||||||
s32 fd;
|
s32 fd;
|
||||||
|
|
||||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
|
||||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
fd = permissive_create(afl, fn);
|
||||||
close(fd);
|
if (fd >= 0) { close(fd); }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -596,6 +643,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
|||||||
q->trace_mini = NULL;
|
q->trace_mini = NULL;
|
||||||
q->testcase_buf = NULL;
|
q->testcase_buf = NULL;
|
||||||
q->mother = afl->queue_cur;
|
q->mother = afl->queue_cur;
|
||||||
|
q->score = afl->current_score;
|
||||||
|
if (unlikely(!q->score)) { q->score = 1; }
|
||||||
|
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
q->bitsmap_size = afl->bitsmap_size;
|
q->bitsmap_size = afl->bitsmap_size;
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2023 AFLplusplus Project. All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -29,6 +29,7 @@
|
|||||||
#include "cmplog.h"
|
#include "cmplog.h"
|
||||||
|
|
||||||
// #define _DEBUG
|
// #define _DEBUG
|
||||||
|
// #define USE_HASHMAP
|
||||||
// #define CMPLOG_INTROSPECTION
|
// #define CMPLOG_INTROSPECTION
|
||||||
|
|
||||||
// CMP attribute enum
|
// CMP attribute enum
|
||||||
@ -87,6 +88,13 @@ static u32 hshape;
|
|||||||
static u64 screen_update;
|
static u64 screen_update;
|
||||||
static u64 last_update;
|
static u64 last_update;
|
||||||
|
|
||||||
|
#ifdef USE_HASHMAP
|
||||||
|
// hashmap functions
|
||||||
|
void hashmap_reset();
|
||||||
|
bool hashmap_search_and_add(uint8_t type, uint64_t key);
|
||||||
|
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key);
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
|
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
|
||||||
|
|
||||||
struct range *r = ck_alloc_nozero(sizeof(struct range));
|
struct range *r = ck_alloc_nozero(sizeof(struct range));
|
||||||
@ -795,7 +803,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
u64 *o_buf_64 = (u64 *)&orig_buf[idx];
|
u64 *o_buf_64 = (u64 *)&orig_buf[idx];
|
||||||
u32 *o_buf_32 = (u32 *)&orig_buf[idx];
|
u32 *o_buf_32 = (u32 *)&orig_buf[idx];
|
||||||
u16 *o_buf_16 = (u16 *)&orig_buf[idx];
|
u16 *o_buf_16 = (u16 *)&orig_buf[idx];
|
||||||
u8 *o_buf_8 = &orig_buf[idx];
|
// u8 *o_buf_8 = &orig_buf[idx];
|
||||||
|
|
||||||
u32 its_len = MIN(len - idx, taint_len);
|
u32 its_len = MIN(len - idx, taint_len);
|
||||||
|
|
||||||
@ -836,6 +844,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
// necessary for preventing heap access overflow
|
// necessary for preventing heap access overflow
|
||||||
bytes = MIN(bytes, len - idx);
|
bytes = MIN(bytes, len - idx);
|
||||||
|
if (unlikely(bytes <= 1)) { return 0; }
|
||||||
|
|
||||||
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
|
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
|
||||||
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
|
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
|
||||||
@ -1266,6 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (*status != 1) { // u8
|
if (*status != 1) { // u8
|
||||||
|
|
||||||
// if (its_len >= 1)
|
// if (its_len >= 1)
|
||||||
@ -1290,6 +1300,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If 'S' is set for cmplog mode then we try a scale encoding of the value.
|
// If 'S' is set for cmplog mode then we try a scale encoding of the value.
|
||||||
@ -1881,6 +1893,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
hshape = SHAPE_BYTES(h->shape);
|
hshape = SHAPE_BYTES(h->shape);
|
||||||
|
|
||||||
|
if (hshape < 2) { return 0; }
|
||||||
|
|
||||||
if (h->hits > CMP_MAP_H) {
|
if (h->hits > CMP_MAP_H) {
|
||||||
|
|
||||||
loggeds = CMP_MAP_H;
|
loggeds = CMP_MAP_H;
|
||||||
@ -1906,8 +1920,6 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hshape < 2) { return 0; }
|
|
||||||
|
|
||||||
for (i = 0; i < loggeds; ++i) {
|
for (i = 0; i < loggeds; ++i) {
|
||||||
|
|
||||||
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
|
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
|
||||||
@ -1945,6 +1957,19 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_HASHMAP
|
||||||
|
// TODO: add attribute? not sure
|
||||||
|
if (hshape <= 8 && hashmap_search_and_add(hshape - 1, o->v0) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, orig_o->v0) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, o->v1) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, orig_o->v1)) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
|
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
|
||||||
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
|
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
|
||||||
@ -2219,15 +2244,15 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
|
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 32 || l1 > 32 ||
|
||||||
ol0 > 31 || ol1 > 31) {
|
ol0 > 32 || ol1 > 32) {
|
||||||
|
|
||||||
l0 = ol0 = hshape;
|
l0 = ol0 = hshape;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 lmax = MAX(l0, ol0);
|
u8 lmax = MAX(l0, ol0);
|
||||||
u8 save[40];
|
u8 save[80];
|
||||||
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
|
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
|
||||||
u32 its_len = MIN(MIN(lmax, hshape), len - idx);
|
u32 its_len = MIN(MIN(lmax, hshape), len - idx);
|
||||||
its_len = MIN(its_len, taint_len);
|
its_len = MIN(its_len, taint_len);
|
||||||
@ -2330,7 +2355,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
u32 tob64 = 0, fromb64 = 0;
|
u32 tob64 = 0, fromb64 = 0;
|
||||||
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
|
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
|
||||||
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
|
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
|
||||||
u8 xor_val[32], arith_val[32], tmp[48];
|
u8 xor_val[64], arith_val[64], tmp[64];
|
||||||
|
|
||||||
idx = saved_idx;
|
idx = saved_idx;
|
||||||
its_len = saved_its_len;
|
its_len = saved_its_len;
|
||||||
@ -2615,12 +2640,13 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buf + idx, tmp, hlen + 1 + off);
|
u32 tmp_l = hlen + 1 + off;
|
||||||
|
memcpy(buf + idx, tmp, tmp_l);
|
||||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||||
tmp[hlen + 1 + off] = 0;
|
tmp[tmp_l] = 0;
|
||||||
// fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
|
// fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
|
||||||
// %u\n", idx, len, fromhex, tmp, repl, *status);
|
// %u\n", idx, len, fromhex, tmp, repl, *status);
|
||||||
memcpy(buf + idx, save, hlen + 1 + off);
|
memcpy(buf + idx, save, tmp_l);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2738,15 +2764,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
u32 j;
|
u32 j;
|
||||||
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
|
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
|
||||||
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
|
fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape,
|
||||||
hshape, h->attribute);
|
h->attribute);
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
fprintf(stderr, "%02x", o->v0[j]);
|
fprintf(stderr, "%02x", o->v0[j]);
|
||||||
fprintf(stderr, " v1=");
|
fprintf(stderr, " v1=");
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
fprintf(stderr, "%02x", o->v1[j]);
|
fprintf(stderr, "%02x", o->v1[j]);
|
||||||
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
|
fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape,
|
||||||
hh->id, hshape, hh->attribute);
|
hh->attribute);
|
||||||
for (j = 0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
fprintf(stderr, "%02x", orig_o->v0[j]);
|
fprintf(stderr, "%02x", orig_o->v0[j]);
|
||||||
fprintf(stderr, " o1=");
|
fprintf(stderr, " o1=");
|
||||||
@ -2755,6 +2781,18 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_HASHMAP
|
||||||
|
if (hshape <= 8 && hashmap_search_and_add_ptr(hshape - 1, o->v0) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, o->v1) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
t = taint;
|
t = taint;
|
||||||
while (t->next) {
|
while (t->next) {
|
||||||
|
|
||||||
@ -3021,6 +3059,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
|||||||
|
|
||||||
// Start insertion loop
|
// Start insertion loop
|
||||||
|
|
||||||
|
#ifdef USE_HASHMAP
|
||||||
|
hashmap_reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
u64 orig_hit_cnt, new_hit_cnt;
|
u64 orig_hit_cnt, new_hit_cnt;
|
||||||
u64 orig_execs = afl->fsrv.total_execs;
|
u64 orig_execs = afl->fsrv.total_execs;
|
||||||
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
u32 use_tmout = afl->fsrv.exec_tmout;
|
u32 use_tmout = afl->fsrv.exec_tmout;
|
||||||
u8 *old_sn = afl->stage_name;
|
u8 *old_sn = afl->stage_name;
|
||||||
|
|
||||||
|
u64 calibration_start_us = get_cur_time_us();
|
||||||
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
|
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
|
||||||
|
|
||||||
/* Be a bit more generous about timeouts when resuming sessions, or when
|
/* Be a bit more generous about timeouts when resuming sessions, or when
|
||||||
@ -504,6 +505,10 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
|
|
||||||
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
||||||
|
|
||||||
|
// update the time spend in calibration after each execution, as those may
|
||||||
|
// be slow
|
||||||
|
update_calibration_time(afl, &calibration_start_us);
|
||||||
|
|
||||||
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
||||||
we want to bail out quickly. */
|
we want to bail out quickly. */
|
||||||
|
|
||||||
@ -601,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
q->exec_us = diff_us / afl->stage_max;
|
q->exec_us = diff_us / afl->stage_max;
|
||||||
|
if (unlikely(!q->exec_us)) { q->exec_us = 1; }
|
||||||
|
|
||||||
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
|
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
|
||||||
q->handicap = handicap;
|
q->handicap = handicap;
|
||||||
q->cal_failed = 0;
|
q->cal_failed = 0;
|
||||||
@ -650,6 +657,7 @@ abort_calibration:
|
|||||||
|
|
||||||
if (!first_run) { show_stats(afl); }
|
if (!first_run) { show_stats(afl); }
|
||||||
|
|
||||||
|
update_calibration_time(afl, &calibration_start_us);
|
||||||
return fault;
|
return fault;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -669,11 +677,16 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
afl->stage_max = afl->stage_cur = 0;
|
afl->stage_max = afl->stage_cur = 0;
|
||||||
afl->cur_depth = 0;
|
afl->cur_depth = 0;
|
||||||
|
|
||||||
|
u64 sync_start_us = get_cur_time_us();
|
||||||
/* Look at the entries created for every other fuzzer in the sync directory.
|
/* Look at the entries created for every other fuzzer in the sync directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while ((sd_ent = readdir(sd))) {
|
while ((sd_ent = readdir(sd))) {
|
||||||
|
|
||||||
|
// since sync can take substantial amounts of time, update time spend every
|
||||||
|
// iteration
|
||||||
|
update_sync_time(afl, &sync_start_us);
|
||||||
|
|
||||||
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
|
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
|
||||||
u32 min_accept = 0, next_min_accept = 0;
|
u32 min_accept = 0, next_min_accept = 0;
|
||||||
|
|
||||||
@ -760,6 +773,8 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
afl->stage_cur = 0;
|
afl->stage_cur = 0;
|
||||||
afl->stage_max = 0;
|
afl->stage_max = 0;
|
||||||
|
|
||||||
|
show_stats(afl);
|
||||||
|
|
||||||
/* For every file queued by this fuzzer, parse ID and see if we have
|
/* For every file queued by this fuzzer, parse ID and see if we have
|
||||||
looked at it before; exec a test case if not. */
|
looked at it before; exec a test case if not. */
|
||||||
|
|
||||||
@ -811,15 +826,15 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
/* See what happens. We rely on save_if_interesting() to catch major
|
/* See what happens. We rely on save_if_interesting() to catch major
|
||||||
errors and save the test case. */
|
errors and save the test case. */
|
||||||
|
|
||||||
(void)write_to_testcase(afl, (void **)&mem, st.st_size, 1);
|
u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
|
||||||
|
|
||||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||||
|
|
||||||
if (afl->stop_soon) { goto close_sync; }
|
if (afl->stop_soon) { goto close_sync; }
|
||||||
|
|
||||||
afl->syncing_party = sd_ent->d_name;
|
afl->syncing_party = sd_ent->d_name;
|
||||||
afl->queued_imported +=
|
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
|
||||||
save_if_interesting(afl, mem, st.st_size, fault);
|
show_stats(afl);
|
||||||
afl->syncing_party = 0;
|
afl->syncing_party = 0;
|
||||||
|
|
||||||
munmap(mem, st.st_size);
|
munmap(mem, st.st_size);
|
||||||
@ -861,6 +876,9 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
|
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
|
||||||
|
|
||||||
|
// add time in sync one last time
|
||||||
|
update_sync_time(afl, &sync_start_us);
|
||||||
|
|
||||||
afl->last_sync_time = get_cur_time();
|
afl->last_sync_time = get_cur_time();
|
||||||
afl->last_sync_cycle = afl->queue_cycle;
|
afl->last_sync_cycle = afl->queue_cycle;
|
||||||
|
|
||||||
@ -872,8 +890,9 @@ void sync_fuzzers(afl_state_t *afl) {
|
|||||||
|
|
||||||
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||||
|
|
||||||
|
u8 needs_write = 0, fault = 0;
|
||||||
u32 orig_len = q->len;
|
u32 orig_len = q->len;
|
||||||
|
u64 trim_start_us = get_cur_time_us();
|
||||||
/* Custom mutator trimmer */
|
/* Custom mutator trimmer */
|
||||||
if (afl->custom_mutators_count) {
|
if (afl->custom_mutators_count) {
|
||||||
|
|
||||||
@ -897,11 +916,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (custom_trimmed) return trimmed_case;
|
if (custom_trimmed) {
|
||||||
|
|
||||||
|
fault = trimmed_case;
|
||||||
|
goto abort_trimming;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 needs_write = 0, fault = 0;
|
|
||||||
u32 trim_exec = 0;
|
u32 trim_exec = 0;
|
||||||
u32 remove_len;
|
u32 remove_len;
|
||||||
u32 len_p2;
|
u32 len_p2;
|
||||||
@ -912,7 +935,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
detected, it will still work to some extent, so we don't check for
|
detected, it will still work to some extent, so we don't check for
|
||||||
this. */
|
this. */
|
||||||
|
|
||||||
if (unlikely(q->len < 5)) { return 0; }
|
if (unlikely(q->len < 5)) {
|
||||||
|
|
||||||
|
fault = 0;
|
||||||
|
goto abort_trimming;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
afl->stage_name = afl->stage_name_buf;
|
afl->stage_name = afl->stage_name_buf;
|
||||||
afl->bytes_trim_in += q->len;
|
afl->bytes_trim_in += q->len;
|
||||||
@ -946,6 +974,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
|
|
||||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||||
|
|
||||||
|
update_trim_time(afl, &trim_start_us);
|
||||||
|
|
||||||
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
|
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
|
||||||
|
|
||||||
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
|
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
|
||||||
@ -972,7 +1002,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
|
|
||||||
/* Let's save a clean trace, which will be needed by
|
/* Let's save a clean trace, which will be needed by
|
||||||
update_bitmap_score once we're done with the trimming stuff. */
|
update_bitmap_score once we're done with the trimming stuff. */
|
||||||
|
|
||||||
if (!needs_write) {
|
if (!needs_write) {
|
||||||
|
|
||||||
needs_write = 1;
|
needs_write = 1;
|
||||||
@ -987,7 +1016,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Since this can be slow, update the screen every now and then. */
|
/* Since this can be slow, update the screen every now and then. */
|
||||||
|
|
||||||
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
|
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
|
||||||
++afl->stage_cur;
|
++afl->stage_cur;
|
||||||
|
|
||||||
@ -1002,6 +1030,68 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
|
|
||||||
if (needs_write) {
|
if (needs_write) {
|
||||||
|
|
||||||
|
// run afl_custom_post_process
|
||||||
|
|
||||||
|
if (unlikely(afl->custom_mutators_count) &&
|
||||||
|
likely(!afl->afl_env.afl_post_process_keep_original)) {
|
||||||
|
|
||||||
|
ssize_t new_size = q->len;
|
||||||
|
u8 *new_mem = in_buf;
|
||||||
|
u8 *new_buf = NULL;
|
||||||
|
|
||||||
|
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
|
||||||
|
|
||||||
|
if (el->afl_custom_post_process) {
|
||||||
|
|
||||||
|
new_size = el->afl_custom_post_process(el->data, new_mem, new_size,
|
||||||
|
&new_buf);
|
||||||
|
|
||||||
|
if (unlikely(!new_buf || new_size <= 0)) {
|
||||||
|
|
||||||
|
new_size = 0;
|
||||||
|
new_buf = new_mem;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
new_mem = new_buf;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (unlikely(!new_size)) {
|
||||||
|
|
||||||
|
new_size = q->len;
|
||||||
|
new_mem = in_buf;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(new_size < afl->min_length)) {
|
||||||
|
|
||||||
|
new_size = afl->min_length;
|
||||||
|
|
||||||
|
} else if (unlikely(new_size > afl->max_length)) {
|
||||||
|
|
||||||
|
new_size = afl->max_length;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
q->len = new_size;
|
||||||
|
|
||||||
|
if (new_mem != in_buf && new_mem != NULL) {
|
||||||
|
|
||||||
|
new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
|
||||||
|
if (unlikely(!new_buf)) { PFATAL("alloc"); }
|
||||||
|
memcpy(new_buf, new_mem, new_size);
|
||||||
|
|
||||||
|
in_buf = new_buf;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
s32 fd;
|
s32 fd;
|
||||||
|
|
||||||
if (unlikely(afl->no_unlink)) {
|
if (unlikely(afl->no_unlink)) {
|
||||||
@ -1039,8 +1129,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abort_trimming:
|
abort_trimming:
|
||||||
|
|
||||||
afl->bytes_trim_out += q->len;
|
afl->bytes_trim_out += q->len;
|
||||||
|
update_trim_time(afl, &trim_start_us);
|
||||||
|
|
||||||
return fault;
|
return fault;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
@ -28,10 +28,6 @@
|
|||||||
#include "afl-fuzz.h"
|
#include "afl-fuzz.h"
|
||||||
#include "envs.h"
|
#include "envs.h"
|
||||||
|
|
||||||
s8 interesting_8[] = {INTERESTING_8};
|
|
||||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
|
||||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
|
||||||
|
|
||||||
char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit",
|
char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit",
|
||||||
"fast", "coe", "lin",
|
"fast", "coe", "lin",
|
||||||
"quad", "rare", "seek"};
|
"quad", "rare", "seek"};
|
||||||
@ -102,7 +98,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
|
|||||||
afl->stats_update_freq = 1;
|
afl->stats_update_freq = 1;
|
||||||
afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
|
afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
|
||||||
afl->stats_avg_exec = 0;
|
afl->stats_avg_exec = 0;
|
||||||
afl->skip_deterministic = 1;
|
afl->skip_deterministic = 0;
|
||||||
afl->sync_time = SYNC_TIME;
|
afl->sync_time = SYNC_TIME;
|
||||||
afl->cmplog_lvl = 2;
|
afl->cmplog_lvl = 2;
|
||||||
afl->min_length = 1;
|
afl->min_length = 1;
|
||||||
@ -297,6 +293,16 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
|||||||
afl->afl_env.afl_cmplog_only_new =
|
afl->afl_env.afl_cmplog_only_new =
|
||||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||||
|
|
||||||
|
} else if (!strncmp(env, "AFL_DISABLE_REDUNDANT",
|
||||||
|
|
||||||
|
afl_environment_variable_len) ||
|
||||||
|
!strncmp(env, "AFL_NO_REDUNDANT",
|
||||||
|
|
||||||
|
afl_environment_variable_len)) {
|
||||||
|
|
||||||
|
afl->afl_env.afl_disable_redundant =
|
||||||
|
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||||
|
|
||||||
} else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
|
} else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
|
||||||
|
|
||||||
afl_environment_variable_len)) {
|
afl_environment_variable_len)) {
|
||||||
@ -623,6 +629,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (!strncmp(env, "AFL_SHA1_FILENAMES",
|
||||||
|
|
||||||
|
afl_environment_variable_len)) {
|
||||||
|
|
||||||
|
afl->afl_env.afl_sha1_filenames =
|
||||||
|
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Dominik Meier <mail@dmnk.co>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||||
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||||
@ -133,6 +134,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool starts_with(char *key, char *line) {
|
||||||
|
|
||||||
|
return strncmp(key, line, strlen(key)) == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* load some of the existing stats file when resuming.*/
|
/* load some of the existing stats file when resuming.*/
|
||||||
void load_stats_file(afl_state_t *afl) {
|
void load_stats_file(afl_state_t *afl) {
|
||||||
|
|
||||||
@ -175,58 +182,84 @@ void load_stats_file(afl_state_t *afl) {
|
|||||||
strcpy(keystring, lstartptr);
|
strcpy(keystring, lstartptr);
|
||||||
lptr++;
|
lptr++;
|
||||||
char *nptr;
|
char *nptr;
|
||||||
switch (lineno) {
|
if (starts_with("run_time", keystring)) {
|
||||||
|
|
||||||
case 3:
|
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
|
||||||
if (!strcmp(keystring, "run_time "))
|
|
||||||
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
if (!strcmp(keystring, "cycles_done "))
|
|
||||||
afl->queue_cycle =
|
|
||||||
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
if (!strcmp(keystring, "execs_done "))
|
|
||||||
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
if (!strcmp(keystring, "corpus_count ")) {
|
|
||||||
|
|
||||||
u32 corpus_count = strtoul(lptr, &nptr, 10);
|
}
|
||||||
if (corpus_count != afl->queued_items) {
|
|
||||||
|
|
||||||
WARNF(
|
if (starts_with("cycles_done", keystring)) {
|
||||||
"queue/ has been modified -- things might not work, you're "
|
|
||||||
"on your own!");
|
|
||||||
|
|
||||||
}
|
afl->queue_cycle =
|
||||||
|
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
if (starts_with("calibration_time", keystring)) {
|
||||||
case 12:
|
|
||||||
if (!strcmp(keystring, "corpus_found "))
|
afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||||
afl->queued_discovered = strtoul(lptr, &nptr, 10);
|
|
||||||
break;
|
}
|
||||||
case 13:
|
|
||||||
if (!strcmp(keystring, "corpus_imported "))
|
if (starts_with("sync_time", keystring)) {
|
||||||
afl->queued_imported = strtoul(lptr, &nptr, 10);
|
|
||||||
break;
|
afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||||
case 14:
|
|
||||||
if (!strcmp(keystring, "max_depth "))
|
}
|
||||||
afl->max_depth = strtoul(lptr, &nptr, 10);
|
|
||||||
break;
|
if (starts_with("trim_time", keystring)) {
|
||||||
case 21:
|
|
||||||
if (!strcmp(keystring, "saved_crashes "))
|
afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||||
afl->saved_crashes = strtoull(lptr, &nptr, 10);
|
|
||||||
break;
|
}
|
||||||
case 22:
|
|
||||||
if (!strcmp(keystring, "saved_hangs "))
|
if (starts_with("execs_done", keystring)) {
|
||||||
afl->saved_hangs = strtoull(lptr, &nptr, 10);
|
|
||||||
break;
|
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
|
||||||
default:
|
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
if (starts_with("corpus_count", keystring)) {
|
||||||
|
|
||||||
|
u32 corpus_count = strtoul(lptr, &nptr, 10);
|
||||||
|
if (corpus_count != afl->queued_items) {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"queue/ has been modified -- things might not work, you're "
|
||||||
|
"on your own!");
|
||||||
|
sleep(3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with("corpus_found", keystring)) {
|
||||||
|
|
||||||
|
afl->queued_discovered = strtoul(lptr, &nptr, 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with("corpus_imported", keystring)) {
|
||||||
|
|
||||||
|
afl->queued_imported = strtoul(lptr, &nptr, 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with("max_depth", keystring)) {
|
||||||
|
|
||||||
|
afl->max_depth = strtoul(lptr, &nptr, 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with("saved_crashes", keystring)) {
|
||||||
|
|
||||||
|
afl->saved_crashes = strtoull(lptr, &nptr, 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with("saved_hangs", keystring)) {
|
||||||
|
|
||||||
|
afl->saved_hangs = strtoull(lptr, &nptr, 10);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +333,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
|||||||
"cycles_done : %llu\n"
|
"cycles_done : %llu\n"
|
||||||
"cycles_wo_finds : %llu\n"
|
"cycles_wo_finds : %llu\n"
|
||||||
"time_wo_finds : %llu\n"
|
"time_wo_finds : %llu\n"
|
||||||
|
"fuzz_time : %llu\n"
|
||||||
|
"calibration_time : %llu\n"
|
||||||
|
"sync_time : %llu\n"
|
||||||
|
"trim_time : %llu\n"
|
||||||
"execs_done : %llu\n"
|
"execs_done : %llu\n"
|
||||||
"execs_per_sec : %0.02f\n"
|
"execs_per_sec : %0.02f\n"
|
||||||
"execs_ps_last_min : %0.02f\n"
|
"execs_ps_last_min : %0.02f\n"
|
||||||
@ -337,7 +374,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
|||||||
"\n"
|
"\n"
|
||||||
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
|
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
|
||||||
"command_line : %s\n",
|
"command_line : %s\n",
|
||||||
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
|
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
|
||||||
runtime / 1000, (u32)getpid(),
|
runtime / 1000, (u32)getpid(),
|
||||||
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
||||||
afl->longest_find_time > cur_time - afl->last_find_time
|
afl->longest_find_time > cur_time - afl->last_find_time
|
||||||
@ -345,7 +382,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
|||||||
: ((afl->start_time == 0 || afl->last_find_time == 0)
|
: ((afl->start_time == 0 || afl->last_find_time == 0)
|
||||||
? 0
|
? 0
|
||||||
: (cur_time - afl->last_find_time) / 1000),
|
: (cur_time - afl->last_find_time) / 1000),
|
||||||
afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000),
|
(runtime -
|
||||||
|
((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) /
|
||||||
|
1000)) /
|
||||||
|
1000,
|
||||||
|
afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000,
|
||||||
|
afl->trim_time_us / 1000000, afl->fsrv.total_execs,
|
||||||
|
afl->fsrv.total_execs / ((double)(runtime) / 1000),
|
||||||
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
|
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
|
||||||
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
|
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
|
||||||
afl->max_depth, afl->current_entry, afl->pending_favored,
|
afl->max_depth, afl->current_entry, afl->pending_favored,
|
||||||
@ -876,6 +919,10 @@ void show_stats_normal(afl_state_t *afl) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (banner_pad)
|
||||||
|
for (u32 i = 0; i < banner_pad; ++i)
|
||||||
|
strcat(banner, " ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SAYF("\n%s\n", banner);
|
SAYF("\n%s\n", banner);
|
||||||
@ -1112,7 +1159,7 @@ void show_stats_normal(afl_state_t *afl) {
|
|||||||
|
|
||||||
} else if (likely(afl->skip_deterministic)) {
|
} else if (likely(afl->skip_deterministic)) {
|
||||||
|
|
||||||
strcpy(tmp, "disabled (default, enable with -D)");
|
strcpy(tmp, "disabled (-z switch used)");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -2435,3 +2482,27 @@ void show_init_stats(afl_state_t *afl) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_calibration_time(afl_state_t *afl, u64 *time) {
|
||||||
|
|
||||||
|
u64 cur = get_cur_time_us();
|
||||||
|
afl->calibration_time_us += cur - *time;
|
||||||
|
*time = cur;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_trim_time(afl_state_t *afl, u64 *time) {
|
||||||
|
|
||||||
|
u64 cur = get_cur_time_us();
|
||||||
|
afl->trim_time_us += cur - *time;
|
||||||
|
*time = cur;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_sync_time(afl_state_t *afl, u64 *time) {
|
||||||
|
|
||||||
|
u64 cur = get_cur_time_us();
|
||||||
|
afl->sync_time_us += cur - *time;
|
||||||
|
*time = cur;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
124
src/afl-fuzz.c
124
src/afl-fuzz.c
@ -5,8 +5,9 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Dominik Meier <mail@dmnk.co>,
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||||
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||||
@ -170,7 +171,6 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
" -g minlength - set min length of generated fuzz input (default: 1)\n"
|
" -g minlength - set min length of generated fuzz input (default: 1)\n"
|
||||||
" -G maxlength - set max length of generated fuzz input (default: "
|
" -G maxlength - set max length of generated fuzz input (default: "
|
||||||
"%lu)\n"
|
"%lu)\n"
|
||||||
" -D - enable (a new) effective deterministic fuzzing\n"
|
|
||||||
" -L minutes - use MOpt(imize) mode and set the time limit for "
|
" -L minutes - use MOpt(imize) mode and set the time limit for "
|
||||||
"entering the\n"
|
"entering the\n"
|
||||||
" pacemaker mode (minutes of no new finds). 0 = "
|
" pacemaker mode (minutes of no new finds). 0 = "
|
||||||
@ -200,7 +200,8 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
|
|
||||||
"Test settings:\n"
|
"Test settings:\n"
|
||||||
" -s seed - use a fixed seed for the RNG\n"
|
" -s seed - use a fixed seed for the RNG\n"
|
||||||
" -V seconds - fuzz for a specified time then terminate\n"
|
" -V seconds - fuzz for a specified time then terminate (fuzz time "
|
||||||
|
"only!)\n"
|
||||||
" -E execs - fuzz for an approx. no. of total executions then "
|
" -E execs - fuzz for an approx. no. of total executions then "
|
||||||
"terminate\n"
|
"terminate\n"
|
||||||
" Note: not precise and can have several more "
|
" Note: not precise and can have several more "
|
||||||
@ -213,7 +214,8 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
" -F path - sync to a foreign fuzzer queue directory (requires "
|
" -F path - sync to a foreign fuzzer queue directory (requires "
|
||||||
"-M, can\n"
|
"-M, can\n"
|
||||||
" be specified up to %u times)\n"
|
" be specified up to %u times)\n"
|
||||||
// " -d - skip deterministic fuzzing in -M mode\n"
|
" -z - skip the enhanced deterministic fuzzing\n"
|
||||||
|
" (note that the old -d and -D flags are ignored.)\n"
|
||||||
" -T text - text banner to show on the screen\n"
|
" -T text - text banner to show on the screen\n"
|
||||||
" -I command - execute this command/script when a new crash is "
|
" -I command - execute this command/script when a new crash is "
|
||||||
"found\n"
|
"found\n"
|
||||||
@ -262,6 +264,7 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
"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: do not suppress stdout/stderr from target\n"
|
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
|
||||||
|
"AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\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"
|
||||||
@ -401,6 +404,12 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
|
SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _AFL_SPECIAL_PERFORMANCE
|
||||||
|
SAYF(
|
||||||
|
"Compiled with special performance options for this specific system, it "
|
||||||
|
"might not work on other platforms!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
|
SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -539,7 +548,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
// still available: HjJkKqruvwz
|
// still available: HjJkKqruvwz
|
||||||
while ((opt = getopt(argc, argv,
|
while ((opt = getopt(argc, argv,
|
||||||
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
||||||
"T:UV:WXx:YZ")) > 0) {
|
"T:UV:WXx:YzZ")) > 0) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -955,20 +964,17 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D': /* partial deterministic */
|
case 'd':
|
||||||
|
case 'D': /* old deterministic */
|
||||||
|
|
||||||
afl->skip_deterministic = 0;
|
WARNF(
|
||||||
|
"Parameters -d and -D are deprecated, a new enhanced deterministic "
|
||||||
|
"fuzzing is active by default, to disable it use -z");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': /* no deterministic */
|
case 'z': /* no deterministic */
|
||||||
|
|
||||||
// this is the default and currently a lot of infrastructure enforces
|
afl->skip_deterministic = 1;
|
||||||
// it (e.g. clusterfuzz, fuzzbench) based on that this feature
|
|
||||||
// originally was bad performance wise. We now have a better
|
|
||||||
// implementation, hence if it is activated, we do not want to
|
|
||||||
// deactivate it by such setups.
|
|
||||||
|
|
||||||
// afl->skip_deterministic = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B': /* load bitmap */
|
case 'B': /* load bitmap */
|
||||||
@ -1232,6 +1238,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afl->old_seed_selection = 1;
|
||||||
u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
|
u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
|
||||||
|
|
||||||
if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
|
if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
|
||||||
@ -1558,7 +1565,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
setenv("__AFL_OUT_DIR", afl->out_dir, 1);
|
setenv("__AFL_OUT_DIR", afl->out_dir, 1);
|
||||||
|
|
||||||
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
|
if (get_afl_env("AFL_DISABLE_TRIM") || get_afl_env("AFL_NO_TRIM")) {
|
||||||
|
|
||||||
|
afl->disable_trim = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
|
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
|
||||||
|
|
||||||
@ -1794,6 +1805,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
|
afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
|
||||||
|
|
||||||
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
|
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
|
||||||
|
afl->fsrv.max_length = afl->max_length;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (!afl->fsrv.nyx_mode) {
|
if (!afl->fsrv.nyx_mode) {
|
||||||
@ -2069,6 +2081,17 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Simply code if AFL_TMPDIR is used or not */
|
||||||
|
if (!afl->afl_env.afl_tmpdir) {
|
||||||
|
|
||||||
|
afl->tmp_dir = afl->out_dir;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
afl->tmp_dir = afl->afl_env.afl_tmpdir;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
write_setup_file(afl, argc, argv);
|
write_setup_file(afl, argc, argv);
|
||||||
|
|
||||||
setup_cmdline_file(afl, argv + optind);
|
setup_cmdline_file(afl, argv + optind);
|
||||||
@ -2081,8 +2104,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
|
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
|
||||||
|
|
||||||
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
|
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
|
||||||
!afl->in_place_resume) {
|
|
||||||
|
|
||||||
char tmpfile[PATH_MAX];
|
char tmpfile[PATH_MAX];
|
||||||
|
|
||||||
@ -2107,10 +2129,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
afl->tmp_dir = afl->out_dir;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have a file name chosen yet, use a safe default. */
|
/* If we don't have a file name chosen yet, use a safe default. */
|
||||||
@ -2182,7 +2200,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
|
afl->fsrv.persistent_record_dir = alloc_printf("%s", afl->out_dir);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2489,8 +2507,15 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
for (entry = 0; entry < afl->queued_items; ++entry)
|
for (entry = 0; entry < afl->queued_items; ++entry)
|
||||||
if (!afl->queue_buf[entry]->disabled)
|
if (!afl->queue_buf[entry]->disabled)
|
||||||
if (afl->queue_buf[entry]->exec_us > max_ms)
|
if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms)
|
||||||
max_ms = afl->queue_buf[entry]->exec_us;
|
max_ms = afl->queue_buf[entry]->exec_us / 1000;
|
||||||
|
|
||||||
|
// Add 20% as a safety margin, capped to exec_tmout given in -t option
|
||||||
|
max_ms *= 1.2;
|
||||||
|
if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout;
|
||||||
|
|
||||||
|
// Ensure that there is a sensible timeout even for very fast binaries
|
||||||
|
if (max_ms < 5) max_ms = 5;
|
||||||
|
|
||||||
afl->fsrv.exec_tmout = max_ms;
|
afl->fsrv.exec_tmout = max_ms;
|
||||||
afl->timeout_given = 1;
|
afl->timeout_given = 1;
|
||||||
@ -2526,8 +2551,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (void)nice(-20); // does not improve the speed
|
// (void)nice(-20); // does not improve the speed
|
||||||
// real start time, we reset, so this works correctly with -V
|
|
||||||
afl->start_time = get_cur_time();
|
|
||||||
|
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
|
u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
|
||||||
@ -2548,6 +2571,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
OKF("Writing mutation introspection to '%s'", ifn);
|
OKF("Writing mutation introspection to '%s'", ifn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// real start time, we reset, so this works correctly with -V
|
||||||
|
afl->start_time = get_cur_time();
|
||||||
|
|
||||||
while (likely(!afl->stop_soon)) {
|
while (likely(!afl->stop_soon)) {
|
||||||
|
|
||||||
cull_queue(afl);
|
cull_queue(afl);
|
||||||
@ -2568,6 +2594,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
sync_fuzzers(afl);
|
sync_fuzzers(afl);
|
||||||
|
|
||||||
|
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
|
||||||
|
|
||||||
|
// real start time, we reset, so this works correctly with -V
|
||||||
|
afl->start_time = get_cur_time();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++afl->queue_cycle;
|
++afl->queue_cycle;
|
||||||
@ -2835,7 +2868,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 execs_before = afl->fsrv.total_execs;
|
||||||
skipped_fuzz = fuzz_one(afl);
|
skipped_fuzz = fuzz_one(afl);
|
||||||
|
afl->queue_cur->total_execs += afl->fsrv.total_execs - execs_before;
|
||||||
#ifdef INTROSPECTION
|
#ifdef INTROSPECTION
|
||||||
++afl->queue_cur->stats_selected;
|
++afl->queue_cur->stats_selected;
|
||||||
|
|
||||||
@ -3034,6 +3069,37 @@ stop_fuzzing:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_DUMP_QUEUE_ON_EXIT")) {
|
||||||
|
|
||||||
|
for (u32 mode = 0; mode < 2; mode++) { // explore + exploit mode data
|
||||||
|
|
||||||
|
afl->fuzz_mode = mode;
|
||||||
|
create_alias_table(afl);
|
||||||
|
fprintf(stderr, "\nQUEUE DUMP MODE: %u\n", mode);
|
||||||
|
|
||||||
|
for (u32 k = 0; k < afl->queued_items; ++k) {
|
||||||
|
|
||||||
|
struct queue_entry *q = afl->queue_buf[k];
|
||||||
|
fprintf(stderr,
|
||||||
|
"item=%u fname=%s len=%u exec_us=%llu total_execs=%llu "
|
||||||
|
"has_new_cov=%u "
|
||||||
|
"var_behavior=%u favored=%u fs_redundant=%u disabled=%u "
|
||||||
|
"bitmap_size=%u tc_ref=%u fuzz_level=%u was_fuzzed=%u "
|
||||||
|
"mother=%d found=%u perf_score=%.2f weight=%.2f score=%u\n",
|
||||||
|
k, q->fname, q->len, q->exec_us, q->total_execs, q->has_new_cov,
|
||||||
|
q->var_behavior, q->favored, q->fs_redundant, q->disabled,
|
||||||
|
q->bitmap_size, q->tc_ref, q->fuzz_level, q->was_fuzzed,
|
||||||
|
q->mother == NULL ? -1 : (int)q->mother->id, q->found,
|
||||||
|
q->perf_score, q->weight, q->score);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (frida_afl_preload) { ck_free(frida_afl_preload); }
|
if (frida_afl_preload) { ck_free(frida_afl_preload); }
|
||||||
|
|
||||||
fclose(afl->fsrv.plot_file);
|
fclose(afl->fsrv.plot_file);
|
||||||
@ -3057,7 +3123,7 @@ stop_fuzzing:
|
|||||||
afl_fsrv_deinit(&afl->fsrv);
|
afl_fsrv_deinit(&afl->fsrv);
|
||||||
|
|
||||||
/* remove tmpfile */
|
/* remove tmpfile */
|
||||||
if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
|
if (!afl->in_place_resume && afl->fsrv.out_file) {
|
||||||
|
|
||||||
(void)unlink(afl->fsrv.out_file);
|
(void)unlink(afl->fsrv.out_file);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Originally written by Michal Zalewski
|
Originally written by Michal Zalewski
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Written by Marc Heuse <mh@mh-sec.de> for AFL++
|
Written by Marc Heuse <mh@mh-sec.de> for AFL++
|
||||||
|
|
||||||
Maintained by Marc Heuse <mh@mh-sec.de>,
|
Maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
Dominik Maier <domenukk@gmail.com>
|
Dominik Maier <domenukk@gmail.com>
|
||||||
|
|
||||||
|
@ -2,9 +2,17 @@
|
|||||||
#include "afl-fuzz.h"
|
#include "afl-fuzz.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define XXH_INLINE_ALL
|
#ifdef _HAVE_AVX2
|
||||||
#include "xxhash.h"
|
#define T1HA0_AESNI_AVAILABLE 1
|
||||||
#undef XXH_INLINE_ALL
|
#define T1HA_USE_FAST_ONESHOT_READ 1
|
||||||
|
#define T1HA_USE_INDIRECT_FUNCTIONS 1
|
||||||
|
#define T1HA_IA32AES_NAME XXH3_64bits
|
||||||
|
#include "t1ha0_ia32aes_b.h"
|
||||||
|
#else
|
||||||
|
#define XXH_INLINE_ALL
|
||||||
|
#include "xxhash.h"
|
||||||
|
#undef XXH_INLINE_ALL
|
||||||
|
#endif
|
||||||
|
|
||||||
void rand_set_seed(afl_state_t *afl, s64 init_seed) {
|
void rand_set_seed(afl_state_t *afl, s64 init_seed) {
|
||||||
|
|
||||||
@ -87,3 +95,313 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public domain SHA1 implementation copied from:
|
||||||
|
// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c
|
||||||
|
|
||||||
|
/* This code is public-domain - it is based on libcrypt
|
||||||
|
* placed in the public domain by Wei Dai and other contributors.
|
||||||
|
*/
|
||||||
|
// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
#define SHA_BIG_ENDIAN
|
||||||
|
#elif defined __LITTLE_ENDIAN__
|
||||||
|
/* override */
|
||||||
|
#elif defined __BYTE_ORDER
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define SHA_BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
#else // ! defined __LITTLE_ENDIAN__
|
||||||
|
#include <endian.h> // machine/endian.h
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define SHA_BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* header */
|
||||||
|
|
||||||
|
#define HASH_LENGTH 20
|
||||||
|
#define BLOCK_LENGTH 64
|
||||||
|
|
||||||
|
typedef struct sha1nfo {
|
||||||
|
|
||||||
|
uint32_t buffer[BLOCK_LENGTH / 4];
|
||||||
|
uint32_t state[HASH_LENGTH / 4];
|
||||||
|
uint32_t byteCount;
|
||||||
|
uint8_t bufferOffset;
|
||||||
|
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||||
|
uint8_t innerHash[HASH_LENGTH];
|
||||||
|
|
||||||
|
} sha1nfo;
|
||||||
|
|
||||||
|
/* public API - prototypes - TODO: doxygen*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
void sha1_init(sha1nfo *s);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
void sha1_writebyte(sha1nfo *s, uint8_t data);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
void sha1_write(sha1nfo *s, const char *data, size_t len);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
uint8_t *sha1_result(sha1nfo *s);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength);
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
uint8_t *sha1_resultHmac(sha1nfo *s);
|
||||||
|
|
||||||
|
/* code */
|
||||||
|
#define SHA1_K0 0x5a827999
|
||||||
|
#define SHA1_K20 0x6ed9eba1
|
||||||
|
#define SHA1_K40 0x8f1bbcdc
|
||||||
|
#define SHA1_K60 0xca62c1d6
|
||||||
|
|
||||||
|
void sha1_init(sha1nfo *s) {
|
||||||
|
|
||||||
|
s->state[0] = 0x67452301;
|
||||||
|
s->state[1] = 0xefcdab89;
|
||||||
|
s->state[2] = 0x98badcfe;
|
||||||
|
s->state[3] = 0x10325476;
|
||||||
|
s->state[4] = 0xc3d2e1f0;
|
||||||
|
s->byteCount = 0;
|
||||||
|
s->bufferOffset = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
|
||||||
|
|
||||||
|
return ((number << bits) | (number >> (32 - bits)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_hashBlock(sha1nfo *s) {
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t a, b, c, d, e, t;
|
||||||
|
|
||||||
|
a = s->state[0];
|
||||||
|
b = s->state[1];
|
||||||
|
c = s->state[2];
|
||||||
|
d = s->state[3];
|
||||||
|
e = s->state[4];
|
||||||
|
for (i = 0; i < 80; i++) {
|
||||||
|
|
||||||
|
if (i >= 16) {
|
||||||
|
|
||||||
|
t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^
|
||||||
|
s->buffer[(i + 2) & 15] ^ s->buffer[i & 15];
|
||||||
|
s->buffer[i & 15] = sha1_rol32(t, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 20) {
|
||||||
|
|
||||||
|
t = (d ^ (b & (c ^ d))) + SHA1_K0;
|
||||||
|
|
||||||
|
} else if (i < 40) {
|
||||||
|
|
||||||
|
t = (b ^ c ^ d) + SHA1_K20;
|
||||||
|
|
||||||
|
} else if (i < 60) {
|
||||||
|
|
||||||
|
t = ((b & c) | (d & (b | c))) + SHA1_K40;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
t = (b ^ c ^ d) + SHA1_K60;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t += sha1_rol32(a, 5) + e + s->buffer[i & 15];
|
||||||
|
e = d;
|
||||||
|
d = c;
|
||||||
|
c = sha1_rol32(b, 30);
|
||||||
|
b = a;
|
||||||
|
a = t;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s->state[0] += a;
|
||||||
|
s->state[1] += b;
|
||||||
|
s->state[2] += c;
|
||||||
|
s->state[3] += d;
|
||||||
|
s->state[4] += e;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_addUncounted(sha1nfo *s, uint8_t data) {
|
||||||
|
|
||||||
|
uint8_t *const b = (uint8_t *)s->buffer;
|
||||||
|
#ifdef SHA_BIG_ENDIAN
|
||||||
|
b[s->bufferOffset] = data;
|
||||||
|
#else
|
||||||
|
b[s->bufferOffset ^ 3] = data;
|
||||||
|
#endif
|
||||||
|
s->bufferOffset++;
|
||||||
|
if (s->bufferOffset == BLOCK_LENGTH) {
|
||||||
|
|
||||||
|
sha1_hashBlock(s);
|
||||||
|
s->bufferOffset = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_writebyte(sha1nfo *s, uint8_t data) {
|
||||||
|
|
||||||
|
++s->byteCount;
|
||||||
|
sha1_addUncounted(s, data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_write(sha1nfo *s, const char *data, size_t len) {
|
||||||
|
|
||||||
|
for (; len--;)
|
||||||
|
sha1_writebyte(s, (uint8_t)*data++);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_pad(sha1nfo *s) {
|
||||||
|
|
||||||
|
// Implement SHA-1 padding (fips180-2 §5.1.1)
|
||||||
|
|
||||||
|
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||||
|
sha1_addUncounted(s, 0x80);
|
||||||
|
while (s->bufferOffset != 56)
|
||||||
|
sha1_addUncounted(s, 0x00);
|
||||||
|
|
||||||
|
// Append length in the last 8 bytes
|
||||||
|
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
|
||||||
|
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
|
||||||
|
sha1_addUncounted(s, 0); // So zero pad the top bits
|
||||||
|
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
|
||||||
|
sha1_addUncounted(
|
||||||
|
s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||||
|
sha1_addUncounted(s, s->byteCount >> 13); // byte.
|
||||||
|
sha1_addUncounted(s, s->byteCount >> 5);
|
||||||
|
sha1_addUncounted(s, s->byteCount << 3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *sha1_result(sha1nfo *s) {
|
||||||
|
|
||||||
|
// Pad to complete the last block
|
||||||
|
sha1_pad(s);
|
||||||
|
|
||||||
|
#ifndef SHA_BIG_ENDIAN
|
||||||
|
// Swap byte order back
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
|
||||||
|
s->state[i] = (((s->state[i]) << 24) & 0xff000000) |
|
||||||
|
(((s->state[i]) << 8) & 0x00ff0000) |
|
||||||
|
(((s->state[i]) >> 8) & 0x0000ff00) |
|
||||||
|
(((s->state[i]) >> 24) & 0x000000ff);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Return pointer to hash (20 characters)
|
||||||
|
return (uint8_t *)s->state;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HMAC_IPAD 0x36
|
||||||
|
#define HMAC_OPAD 0x5c
|
||||||
|
|
||||||
|
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) {
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
memset(s->keyBuffer, 0, BLOCK_LENGTH);
|
||||||
|
if (keyLength > BLOCK_LENGTH) {
|
||||||
|
|
||||||
|
// Hash long keys
|
||||||
|
sha1_init(s);
|
||||||
|
for (; keyLength--;)
|
||||||
|
sha1_writebyte(s, *key++);
|
||||||
|
memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Block length keys are used as is
|
||||||
|
memcpy(s->keyBuffer, key, keyLength);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start inner hash
|
||||||
|
sha1_init(s);
|
||||||
|
for (i = 0; i < BLOCK_LENGTH; i++) {
|
||||||
|
|
||||||
|
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *sha1_resultHmac(sha1nfo *s) {
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
// Complete inner hash
|
||||||
|
memcpy(s->innerHash, sha1_result(s), HASH_LENGTH);
|
||||||
|
// Calculate outer hash
|
||||||
|
sha1_init(s);
|
||||||
|
for (i = 0; i < BLOCK_LENGTH; i++)
|
||||||
|
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
|
||||||
|
for (i = 0; i < HASH_LENGTH; i++)
|
||||||
|
sha1_writebyte(s, s->innerHash[i]);
|
||||||
|
return sha1_result(s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// End public domain SHA1 implementation
|
||||||
|
|
||||||
|
void sha1(const u8 *data, size_t len, u8 *out) {
|
||||||
|
|
||||||
|
sha1nfo s;
|
||||||
|
sha1_init(&s);
|
||||||
|
sha1_write(&s, (const char *)data, len);
|
||||||
|
memcpy(out, sha1_result(&s), HASH_LENGTH);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sha1_hex(const u8 *data, size_t len) {
|
||||||
|
|
||||||
|
u8 digest[HASH_LENGTH];
|
||||||
|
sha1(data, len, digest);
|
||||||
|
u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1);
|
||||||
|
for (size_t i = 0; i < HASH_LENGTH; ++i) {
|
||||||
|
|
||||||
|
sprintf((char *)(hex + i * 2), "%02x", digest[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sha1_hex_for_file(const char *fname, u32 len) {
|
||||||
|
|
||||||
|
int fd = open(fname, O_RDONLY);
|
||||||
|
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
|
||||||
|
|
||||||
|
u32 read_len = MIN(len, (u32)MAX_FILE);
|
||||||
|
u8 *tmp = ck_alloc(read_len);
|
||||||
|
ck_read(fd, tmp, read_len, fname);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
char *hex = sha1_hex(tmp, read_len);
|
||||||
|
ck_free(tmp);
|
||||||
|
return hex;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -83,6 +83,8 @@ static u32 tcnt, highest; /* tuple content information */
|
|||||||
|
|
||||||
static u32 in_len; /* Input data length */
|
static u32 in_len; /* Input data length */
|
||||||
|
|
||||||
|
static u32 score;
|
||||||
|
|
||||||
static u32 map_size = MAP_SIZE, timed_out = 0;
|
static u32 map_size = MAP_SIZE, timed_out = 0;
|
||||||
|
|
||||||
static bool quiet_mode, /* Hide non-essential messages? */
|
static bool quiet_mode, /* Hide non-essential messages? */
|
||||||
@ -238,6 +240,13 @@ static void at_exit_handler(void) {
|
|||||||
static void analyze_results(afl_forkserver_t *fsrv) {
|
static void analyze_results(afl_forkserver_t *fsrv) {
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
|
if (unlikely((score = *(u32 *)((u8 *)fsrv->trace_bits + 1)) > 0)) {
|
||||||
|
|
||||||
|
memset(fsrv->trace_bits + 1, 0, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < map_size; i++) {
|
for (i = 0; i < map_size; i++) {
|
||||||
|
|
||||||
if (fsrv->trace_bits[i]) {
|
if (fsrv->trace_bits[i]) {
|
||||||
@ -269,6 +278,12 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely((score = *(u32 *)((u8 *)fsrv->trace_bits + 1)) > 0)) {
|
||||||
|
|
||||||
|
memset(fsrv->trace_bits + 1, 0, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (cmin_mode &&
|
if (cmin_mode &&
|
||||||
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
|
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
|
||||||
|
|
||||||
@ -1766,12 +1781,20 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
|
OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
|
||||||
"in '%s'." cRST,
|
"in '%s'." cRST,
|
||||||
tcnt, fsrv->real_map_size, highest, total, out_file);
|
tcnt, fsrv->real_map_size, highest, total, out_file);
|
||||||
if (collect_coverage)
|
if (collect_coverage) {
|
||||||
|
|
||||||
OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
|
OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
|
||||||
"with %llu input files.",
|
"with %llu input files.",
|
||||||
tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
|
tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
|
||||||
fsrv->total_execs);
|
fsrv->total_execs);
|
||||||
|
|
||||||
|
} else if (score > 0) {
|
||||||
|
|
||||||
|
OKF("Path score is %u (cyclomatic and/or vulnerability scoring).\n",
|
||||||
|
score);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdin_file) {
|
if (stdin_file) {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||||
|
|
||||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||||
Dominik Maier <mail@dmnk.co>
|
Dominik Maier <mail@dmnk.co>
|
||||||
|
|
||||||
@ -82,6 +82,8 @@ static u8 crash_mode, /* Crash-centric mode? */
|
|||||||
remove_shm = 1, /* remove shmem on exit? */
|
remove_shm = 1, /* remove shmem on exit? */
|
||||||
debug; /* debug mode */
|
debug; /* debug mode */
|
||||||
|
|
||||||
|
static u32 del_len_limit = 1; /* Minimum block deletion length */
|
||||||
|
|
||||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||||
|
|
||||||
static afl_forkserver_t *fsrv;
|
static afl_forkserver_t *fsrv;
|
||||||
@ -480,7 +482,7 @@ next_del_blksize:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (del_len > 1 && in_len >= 1) {
|
if (del_len > del_len_limit && in_len >= 1) {
|
||||||
|
|
||||||
del_len /= 2;
|
del_len /= 2;
|
||||||
goto next_del_blksize;
|
goto next_del_blksize;
|
||||||
@ -796,8 +798,9 @@ static void usage(u8 *argv0) {
|
|||||||
"Minimization settings:\n"
|
"Minimization settings:\n"
|
||||||
|
|
||||||
" -e - solve for edge coverage only, ignore hit counts\n"
|
" -e - solve for edge coverage only, ignore hit counts\n"
|
||||||
" -x - treat non-zero exit codes as crashes\n\n"
|
" -l bytes - set minimum block deletion length to speed up minimization\n"
|
||||||
" -H - minimize a hang (hang mode)\n"
|
" -x - treat non-zero exit codes as crashes\n"
|
||||||
|
" -H - minimize a hang (hang mode)\n\n"
|
||||||
|
|
||||||
"For additional tips, please consult %s/README.md.\n\n"
|
"For additional tips, please consult %s/README.md.\n\n"
|
||||||
|
|
||||||
@ -829,8 +832,9 @@ static void usage(u8 *argv0) {
|
|||||||
|
|
||||||
int main(int argc, char **argv_orig, char **envp) {
|
int main(int argc, char **argv_orig, char **envp) {
|
||||||
|
|
||||||
s32 opt;
|
s32 opt;
|
||||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
|
||||||
|
del_limit_given = 0;
|
||||||
char **use_argv;
|
char **use_argv;
|
||||||
|
|
||||||
char **argv = argv_cpy_dup(argc, argv_orig);
|
char **argv = argv_cpy_dup(argc, argv_orig);
|
||||||
@ -846,7 +850,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
|
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
|
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -1055,6 +1059,24 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
read_bitmap(optarg, mask_bitmap, map_size);
|
read_bitmap(optarg, mask_bitmap, map_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
if (del_limit_given) { FATAL("Multiple -l options not supported"); }
|
||||||
|
del_limit_given = 1;
|
||||||
|
|
||||||
|
if (!optarg) { FATAL("Wrong usage of -l"); }
|
||||||
|
|
||||||
|
if (optarg[0] == '-') { FATAL("Dangerously low value of -l"); }
|
||||||
|
|
||||||
|
del_len_limit = atoi(optarg);
|
||||||
|
|
||||||
|
if (del_len_limit < 1 || del_len_limit > TMIN_MAX_FILE) {
|
||||||
|
|
||||||
|
FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
|
149
src/hashmap.c
Normal file
149
src/hashmap.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
#define TABLE_SIZE 10007 // Use a prime number for better distribution
|
||||||
|
|
||||||
|
typedef struct HashNode {
|
||||||
|
|
||||||
|
uint64_t key;
|
||||||
|
struct HashNode *next;
|
||||||
|
|
||||||
|
} HashNode;
|
||||||
|
|
||||||
|
typedef struct HashMap {
|
||||||
|
|
||||||
|
HashNode **table;
|
||||||
|
|
||||||
|
} HashMap;
|
||||||
|
|
||||||
|
static HashMap *_hashmap;
|
||||||
|
|
||||||
|
void hashmap_reset() {
|
||||||
|
|
||||||
|
if (unlikely(!_hashmap)) {
|
||||||
|
|
||||||
|
_hashmap = (HashMap *)malloc(sizeof(HashMap));
|
||||||
|
_hashmap->table = (HashNode **)malloc(sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (int i = 0; i < TABLE_SIZE; i++) {
|
||||||
|
|
||||||
|
HashNode *node = _hashmap->table[i];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
HashNode *temp = node;
|
||||||
|
node = node->next;
|
||||||
|
free(temp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int hash(uint64_t key) {
|
||||||
|
|
||||||
|
return key % TABLE_SIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// type must be below 8
|
||||||
|
bool hashmap_search_and_add(uint8_t type, uint64_t key) {
|
||||||
|
|
||||||
|
if (unlikely(type >= 8)) return false;
|
||||||
|
uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56);
|
||||||
|
unsigned int index = hash(val);
|
||||||
|
HashNode *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == val) return true;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found so add it
|
||||||
|
node = (HashNode *)malloc(sizeof(HashNode));
|
||||||
|
node->key = val;
|
||||||
|
node->next = _hashmap->table[index];
|
||||||
|
_hashmap->table[index] = node;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// type must be below 8
|
||||||
|
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key) {
|
||||||
|
|
||||||
|
if (unlikely(type >= 8)) return false;
|
||||||
|
uint64_t key_t = 0;
|
||||||
|
memcpy(((char *)key_t) + (7 - type), key, type + 1);
|
||||||
|
return hashmap_search_and_add(type, key_t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* below is not used */
|
||||||
|
|
||||||
|
void hashmap_insert(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *node = (HashNode *)malloc(sizeof(HashNode));
|
||||||
|
node->key = key;
|
||||||
|
node->next = _hashmap->table[index];
|
||||||
|
_hashmap->table[index] = node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hashmap_search(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == key) return true;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *prev = NULL, *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == key) {
|
||||||
|
|
||||||
|
if (prev)
|
||||||
|
prev->next = node->next;
|
||||||
|
else
|
||||||
|
_hashmap->table[index] = node->next;
|
||||||
|
free(node);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeHashMap(HashMap *map) {
|
||||||
|
|
||||||
|
free(_hashmap->table);
|
||||||
|
free(map);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -10,12 +10,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) {
|
|||||||
|
|
||||||
if (i < 15) return -1;
|
if (i < 15) return -1;
|
||||||
if (buf[0] != 'A') return 0;
|
if (buf[0] != 'A') return 0;
|
||||||
if (buf[1] != 'B') return 0;
|
int *icmp = (int *)(buf + 1);
|
||||||
if (buf[2] != 'C') return 0;
|
|
||||||
if (buf[3] != 'D') return 0;
|
|
||||||
int *icmp = (int *)(buf + 4);
|
|
||||||
if (*icmp != 0x69694141) return 0;
|
if (*icmp != 0x69694141) return 0;
|
||||||
if (memcmp(buf + 8, "1234EF", 6) == 0) abort();
|
if (memcmp(buf + 5, "1234EF", 6) == 0) abort();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
|
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
|
||||||
CODE=1
|
CODE=1
|
||||||
}
|
}
|
||||||
rm -f test-instr.ts.0 test-instr.ts.1
|
rm -f test-instr.ts.0 test-instr.ts.1 test-instr.ts
|
||||||
} || {
|
} || {
|
||||||
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
|
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
|
||||||
CODE=1
|
CODE=1
|
||||||
@ -197,7 +197,8 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
for I in char short int long "long long"; do
|
for I in char short int long "long long"; do
|
||||||
for BITS in 8 16 32 64; do
|
for BITS in 8 16 32 64; do
|
||||||
bin="$testcase-split-$I-$BITS.compcov"
|
bin="$testcase-split-$I-$BITS.compcov"
|
||||||
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
|
#AFL_LLVM_INSTRUMENT=AFL
|
||||||
|
AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
|
||||||
if ! test -e "$bin"; then
|
if ! test -e "$bin"; then
|
||||||
cat test.out
|
cat test.out
|
||||||
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
|
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
|
||||||
@ -263,13 +264,12 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
}
|
}
|
||||||
rm -f test-compcov test.out instrumentlist.txt
|
rm -f test-compcov test.out instrumentlist.txt
|
||||||
AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
|
AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
|
||||||
../afl-clang-fast -O0 -o test-c test-cmplog.c > /dev/null 2>&1
|
|
||||||
test -e test-cmplog && {
|
test -e test-cmplog && {
|
||||||
$ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
|
$ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
|
||||||
{
|
{
|
||||||
mkdir -p in
|
mkdir -p in
|
||||||
echo 00000000000000000000000000000000 > in/in
|
echo 00000000000000000000000000000000 > in/in
|
||||||
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -l 3 -m none -V30 -i in -o out -c ./test-cmplog -- ./test-c >>errors 2>&1
|
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1
|
||||||
} >>errors 2>&1
|
} >>errors 2>&1
|
||||||
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
|
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
|
||||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
|
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
|
||||||
@ -284,7 +284,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
$ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
|
$ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
|
||||||
INCOMPLETE=1
|
INCOMPLETE=1
|
||||||
}
|
}
|
||||||
rm -rf errors test-cmplog test-c in core.*
|
rm -rf errors test-cmplog in core.*
|
||||||
../afl-clang-fast -o test-persistent ../utils/persistent_mode/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_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
||||||
|
@ -63,7 +63,7 @@ test -e ../afl-qemu-trace && {
|
|||||||
{
|
{
|
||||||
export AFL_PRELOAD=../libcompcov.so
|
export AFL_PRELOAD=../libcompcov.so
|
||||||
export AFL_COMPCOV_LEVEL=2
|
export AFL_COMPCOV_LEVEL=2
|
||||||
../afl-fuzz -m ${MEM_LIMIT} -V07 -Q -i in -o out -- ./test-compcov >>errors 2>&1
|
AFL_NO_UI=1 ../afl-fuzz -V07 -Q -i in -o out -- ./test-compcov 2>&1
|
||||||
unset AFL_PRELOAD
|
unset AFL_PRELOAD
|
||||||
unset AFL_COMPCOV_LEVEL
|
unset AFL_COMPCOV_LEVEL
|
||||||
} >>errors 2>&1
|
} >>errors 2>&1
|
||||||
@ -88,7 +88,7 @@ test -e ../afl-qemu-trace && {
|
|||||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
|
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
|
||||||
$ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds"
|
$ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds"
|
||||||
{
|
{
|
||||||
../afl-fuzz -m none -V07 -Q -c 0 -l 3 -i in -o out -- ./test-compcov >>errors 2>&1
|
../afl-fuzz -V07 -Q -c 0 -l 3 -i in -o out -- ./test-compcov >>errors 2>&1
|
||||||
} >>errors 2>&1
|
} >>errors 2>&1
|
||||||
test -n "$( ls out/default/queue/id:000001* 2>/dev/null )" && {
|
test -n "$( ls out/default/queue/id:000001* 2>/dev/null )" && {
|
||||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog"
|
$ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog"
|
||||||
|
@ -1 +1 @@
|
|||||||
63aab0f
|
764b66b2
|
||||||
|
@ -198,10 +198,12 @@ $MAKECMD -j1 || exit 1
|
|||||||
echo "[+] Build process successful!"
|
echo "[+] Build process successful!"
|
||||||
|
|
||||||
echo "[*] Installing Unicorn python bindings..."
|
echo "[*] Installing Unicorn python bindings..."
|
||||||
|
XOPT=
|
||||||
|
$PYTHONBIN -m pip install --help 2>/dev/null | grep -q break-system-packages && XOPT=--break-system-packages
|
||||||
cd unicorn/bindings/python || exit 1
|
cd unicorn/bindings/python || exit 1
|
||||||
if [ -z "$VIRTUAL_ENV" ]; then
|
if [ -z "$VIRTUAL_ENV" ]; then
|
||||||
echo "[*] Info: Installing python unicornafl using --user"
|
echo "[*] Info: Installing python unicornafl using --user"
|
||||||
THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
|
THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
|
||||||
else
|
else
|
||||||
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
|
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
|
||||||
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
|
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
|
||||||
@ -211,7 +213,7 @@ echo "[*] Installing Unicornafl python bindings..."
|
|||||||
cd bindings/python || exit 1
|
cd bindings/python || exit 1
|
||||||
if [ -z "$VIRTUAL_ENV" ]; then
|
if [ -z "$VIRTUAL_ENV" ]; then
|
||||||
echo "[*] Info: Installing python unicornafl using --user"
|
echo "[*] Info: Installing python unicornafl using --user"
|
||||||
THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
|
THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
|
||||||
else
|
else
|
||||||
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
|
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
|
||||||
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
|
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
|
||||||
|
@ -89,8 +89,8 @@ def dump_arch_info():
|
|||||||
|
|
||||||
def dump_regs():
|
def dump_regs():
|
||||||
reg_state = {}
|
reg_state = {}
|
||||||
for reg in current_arch.all_registers:
|
for reg in gef.arch.registers:
|
||||||
reg_val = get_register(reg)
|
reg_val = gef.arch.register(reg)
|
||||||
reg_state[reg.strip().strip("$")] = reg_val
|
reg_state[reg.strip().strip("$")] = reg_val
|
||||||
|
|
||||||
return reg_state
|
return reg_state
|
||||||
@ -101,7 +101,9 @@ def dump_process_memory(output_dir):
|
|||||||
final_segment_list = []
|
final_segment_list = []
|
||||||
|
|
||||||
# GEF:
|
# GEF:
|
||||||
vmmap = get_process_maps()
|
vmmap = gef.memory.maps
|
||||||
|
memory = GefMemoryManager()
|
||||||
|
|
||||||
if not vmmap:
|
if not vmmap:
|
||||||
print("No address mapping information found")
|
print("No address mapping information found")
|
||||||
return final_segment_list
|
return final_segment_list
|
||||||
@ -126,7 +128,7 @@ def dump_process_memory(output_dir):
|
|||||||
if entry.is_readable() and not "(deleted)" in entry.path:
|
if entry.is_readable() and not "(deleted)" in entry.path:
|
||||||
try:
|
try:
|
||||||
# Compress and dump the content to a file
|
# Compress and dump the content to a file
|
||||||
seg_content = read_memory(entry.page_start, entry.size)
|
seg_content = memory.read(entry.page_start, entry.size)
|
||||||
if seg_content == None:
|
if seg_content == None:
|
||||||
print(
|
print(
|
||||||
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(
|
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(
|
||||||
|
@ -111,12 +111,14 @@ def dump_regs():
|
|||||||
reg_state = {}
|
reg_state = {}
|
||||||
for reg in pwndbg.gdblib.regs.all:
|
for reg in pwndbg.gdblib.regs.all:
|
||||||
reg_val = pwndbg.gdblib.regs[reg]
|
reg_val = pwndbg.gdblib.regs[reg]
|
||||||
|
if reg_val is None:
|
||||||
|
continue
|
||||||
# current dumper script looks for register values to be hex strings
|
# current dumper script looks for register values to be hex strings
|
||||||
# reg_str = "0x{:08x}".format(reg_val)
|
# reg_str = "0x{:08x}".format(reg_val)
|
||||||
# if "64" in get_arch():
|
# if "64" in get_arch():
|
||||||
# reg_str = "0x{:016x}".format(reg_val)
|
# reg_str = "0x{:016x}".format(reg_val)
|
||||||
# reg_state[reg.strip().strip('$')] = reg_str
|
# reg_state[reg.strip().strip('$')] = reg_str
|
||||||
reg_state[reg.strip().strip("$")] = reg_val
|
reg_state[reg.strip().strip("$")] = int(reg_val)
|
||||||
return reg_state
|
return reg_state
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ import zlib
|
|||||||
|
|
||||||
# Unicorn imports
|
# Unicorn imports
|
||||||
from unicornafl import *
|
from unicornafl import *
|
||||||
from unicornafl.arm_const import *
|
from unicorn.arm_const import *
|
||||||
from unicornafl.arm64_const import *
|
from unicorn.arm64_const import *
|
||||||
from unicornafl.x86_const import *
|
from unicorn.x86_const import *
|
||||||
from unicornafl.mips_const import *
|
from unicorn.mips_const import *
|
||||||
|
|
||||||
# If Capstone libraries are availible (only check once)
|
# If Capstone libraries are availible (only check once)
|
||||||
try:
|
try:
|
||||||
@ -87,9 +87,10 @@ class UnicornSimpleHeap(object):
|
|||||||
|
|
||||||
_uc = None # Unicorn engine instance to interact with
|
_uc = None # Unicorn engine instance to interact with
|
||||||
_chunks = [] # List of all known chunks
|
_chunks = [] # List of all known chunks
|
||||||
|
_chunks_freed = [] # List of all freed chunks
|
||||||
_debug_print = False # True to print debug information
|
_debug_print = False # True to print debug information
|
||||||
|
|
||||||
def __init__(self, uc, debug_print=False):
|
def __init__(self, uc, debug_print=False, uaf_check=False):
|
||||||
self._uc = uc
|
self._uc = uc
|
||||||
self._debug_print = debug_print
|
self._debug_print = debug_print
|
||||||
|
|
||||||
@ -101,12 +102,23 @@ class UnicornSimpleHeap(object):
|
|||||||
# - Allocate at least 1 4k page of memory to make Unicorn happy
|
# - Allocate at least 1 4k page of memory to make Unicorn happy
|
||||||
# - Add guard pages at the start and end of the region
|
# - Add guard pages at the start and end of the region
|
||||||
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
|
||||||
|
|
||||||
|
if size == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
# 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 range(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)
|
||||||
|
|
||||||
|
if self.uaf_check:
|
||||||
|
for chunk_freed in self._chunks_freed:
|
||||||
|
if chunk_freed.is_buffer_in_chunk(chunk.data_addr, 1):
|
||||||
|
self._chunks_freed.remove(chunk_freed)
|
||||||
|
break
|
||||||
|
|
||||||
if self._debug_print:
|
if self._debug_print:
|
||||||
print(
|
print(
|
||||||
"Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
|
"Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
|
||||||
@ -148,6 +160,9 @@ class UnicornSimpleHeap(object):
|
|||||||
return new_chunk_addr
|
return new_chunk_addr
|
||||||
|
|
||||||
def free(self, addr):
|
def free(self, addr):
|
||||||
|
if addr == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
for chunk in self._chunks:
|
for chunk in self._chunks:
|
||||||
if chunk.is_buffer_in_chunk(addr, 1):
|
if chunk.is_buffer_in_chunk(addr, 1):
|
||||||
if self._debug_print:
|
if self._debug_print:
|
||||||
@ -157,9 +172,14 @@ class UnicornSimpleHeap(object):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
|
self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
|
||||||
|
|
||||||
|
if self.uaf_check:
|
||||||
|
self._chunks_freed.append(chunk)
|
||||||
|
|
||||||
self._chunks.remove(chunk)
|
self._chunks.remove(chunk)
|
||||||
return True
|
return True
|
||||||
return False
|
# Freed an object that doesn't exist. Maybe 'dobule-free' or 'invalid free' vulnerability here.
|
||||||
|
self._uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
|
||||||
|
|
||||||
# Implements basic guard-page functionality
|
# Implements basic guard-page functionality
|
||||||
def __check_mem_access(self, uc, access, address, size, value, user_data):
|
def __check_mem_access(self, uc, access, address, size, value, user_data):
|
||||||
@ -179,6 +199,15 @@ class UnicornSimpleHeap(object):
|
|||||||
# Force a memory-based crash
|
# Force a memory-based crash
|
||||||
uc.force_crash(UcError(UC_ERR_READ_PROT))
|
uc.force_crash(UcError(UC_ERR_READ_PROT))
|
||||||
|
|
||||||
|
if self.uaf_check:
|
||||||
|
for chunk in self._chunks_freed:
|
||||||
|
if address >= chunk.actual_addr and (
|
||||||
|
(address + size) <= (chunk.actual_addr + chunk.total_size)
|
||||||
|
):
|
||||||
|
if chunk.is_buffer_in_chunk(address, size):
|
||||||
|
print("Use-after-free @ 0x{0:016x}".format(address))
|
||||||
|
uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# ---- Loading function
|
# ---- Loading function
|
||||||
|
Submodule unicorn_mode/unicornafl updated: 63aab0f752...764b66b21c
@ -10,6 +10,7 @@ PROGRAMS = afl-network-client afl-network-server
|
|||||||
HASH=\#
|
HASH=\#
|
||||||
|
|
||||||
CFLAGS += -Wno-pointer-sign
|
CFLAGS += -Wno-pointer-sign
|
||||||
|
LDFLAGS += -ldl
|
||||||
|
|
||||||
ifdef STATIC
|
ifdef STATIC
|
||||||
CFLAGS += -static
|
CFLAGS += -static
|
||||||
|
8
utils/bench/Makefile
Normal file
8
utils/bench/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
all: hash
|
||||||
|
|
||||||
|
hash: hash.c
|
||||||
|
gcc -O3 -mavx2 -march=native -I../../include -o hash hash.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f hash
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user