mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 06:42:42 +00:00
Compare commits
395 Commits
Author | SHA1 | Date | |
---|---|---|---|
33f3c4c7da | |||
7ad694716b | |||
e93ab23823 | |||
79a24685b2 | |||
cad7536036 | |||
1ddfb1fec2 | |||
ae8df744ee | |||
aaaa96af6d | |||
2e2a3a2718 | |||
eee4be90c1 | |||
5fe21c3797 | |||
4eaacfb095 | |||
82b0cf0540 | |||
5a352adb19 | |||
9afba51ec1 | |||
99402aa31c | |||
af11b80fda | |||
10db3a35cf | |||
af44b07b31 | |||
9b433e2d8c | |||
85e14cf8d1 | |||
f2f417325f | |||
3e18b1a10c | |||
1d3e885441 | |||
0c69d0a0d8 | |||
bbffece7d7 | |||
2956b9cc4c | |||
9160805f4a | |||
50e2f9d46c | |||
223b14134c | |||
f5a672f9d8 | |||
9ce45665d7 | |||
10883b1392 | |||
d206d5fc46 | |||
4f53803dfe | |||
ed06b3bc9f | |||
3081f589cc | |||
5d08f33a5f | |||
46cbe22feb | |||
6cba007c76 | |||
1461f3a0ee | |||
03d306a97f | |||
0278eb5351 | |||
8e88ef02ad | |||
ad2eaf54ad | |||
a287076ac0 | |||
c352943aa5 | |||
bd3900c084 | |||
48002fe146 | |||
31c8a052a6 | |||
46b87a6d62 | |||
b4208dde94 | |||
4a492d5d8e | |||
945309c316 | |||
41de569353 | |||
7aecf14c07 | |||
7b24f4a329 | |||
ebb919f771 | |||
b43f37456f | |||
701e89bbcd | |||
e3fae3e9b0 | |||
464ec516d5 | |||
3af042d5bf | |||
c1e4b8f7f6 | |||
79deeb46dd | |||
9cf260ca1f | |||
82752fe38d | |||
d11ade56e2 | |||
665d32a0dc | |||
e1bd9fc6ac | |||
2c6f2c970d | |||
0e3157375b | |||
f39cf57eac | |||
e62999c95f | |||
0b22665391 | |||
5777ceaf23 | |||
21916a7f60 | |||
6c83a9ccc1 | |||
bc9fda61a3 | |||
4e0b8beba8 | |||
1448eab8ec | |||
55aec64038 | |||
42fc9acf5b | |||
cdbd86a112 | |||
1aa58a1972 | |||
d0587a3ac4 | |||
d1fd072b79 | |||
c282156451 | |||
a9bda37d18 | |||
577b286508 | |||
009f663e2c | |||
1efb7c8a8b | |||
7f614be3a5 | |||
04d2476b32 | |||
c1d9a4fab9 | |||
8a060a4b68 | |||
a11488b9dc | |||
4cc9232485 | |||
20c46c0ed6 | |||
b3d16f7b8c | |||
c0837409bd | |||
78b7e14c73 | |||
f9a8b60b3b | |||
4a1cf0b9af | |||
c1e40c5fb7 | |||
d6a2edb42a | |||
5e8e233755 | |||
31ed850c4b | |||
994ac55878 | |||
cb5a61d8a1 | |||
146e535f7b | |||
b88f132975 | |||
12271064f8 | |||
55b67f1372 | |||
d21fb1a558 | |||
2e6c74f9b9 | |||
2a4281ce8d | |||
9cd702e75d | |||
8b35dd49be | |||
703fd0b610 | |||
db172473b5 | |||
5b44067e9c | |||
8531928fa4 | |||
804c98a1e8 | |||
1792ce2825 | |||
1d6cd5dd19 | |||
7e9abf1bba | |||
6a28502191 | |||
fc7c95e9f4 | |||
4086b93ad7 | |||
837a9693ab | |||
60d3ecab63 | |||
d0f39849c2 | |||
8820bf4758 | |||
75d8c47a6b | |||
3ec794c806 | |||
bf46ff8823 | |||
6f61fca15a | |||
b8cb35fa8c | |||
dfc9b3dba0 | |||
ab5f95e17a | |||
fe66a95d96 | |||
72a24e6439 | |||
088dd6476c | |||
30df52cd8c | |||
74d262c7b5 | |||
d7c99007ff | |||
bdb5622bd4 | |||
cf2ddf437b | |||
2b7aae66b6 | |||
598a3c6b5e | |||
0978283915 | |||
f27cbdb793 | |||
1689a8e053 | |||
6edc3b51ba | |||
93fb1d1a24 | |||
bf7a6d69cf | |||
6ddd5ecf4a | |||
e2099114aa | |||
db84f75a81 | |||
9111035495 | |||
d78a8698e4 | |||
7b2f983bf3 | |||
1910b0ad42 | |||
9a04df5d97 | |||
4f03f380ea | |||
e3b08d430c | |||
4f35c30371 | |||
9df9064549 | |||
256bc6ab42 | |||
614c5127ca | |||
5bb894f1ee | |||
8d72f41e20 | |||
b928303dd0 | |||
76b26ac2c6 | |||
dd16be405a | |||
2e57d86576 | |||
4369d6209f | |||
26ae4124f3 | |||
25945d51a4 | |||
db23931e7c | |||
6e37f9b237 | |||
2f2ddbbd79 | |||
ba7c012427 | |||
5bfe0c1a15 | |||
bb72cc752a | |||
8c4ecd90a8 | |||
c0d53a1aa7 | |||
31a1fbae33 | |||
09f1854cd1 | |||
4a6b751b93 | |||
bbcb3dd53e | |||
eac53afe7b | |||
19ca7b3761 | |||
55a2362348 | |||
8afb60d2f9 | |||
69a596c089 | |||
ccb952dde8 | |||
7c380a6612 | |||
88e2affe73 | |||
3f26818d97 | |||
bd83eb0f42 | |||
c5acf3f137 | |||
ea42feb06a | |||
a09720665d | |||
6f394842be | |||
02f4f75526 | |||
43f462c91b | |||
77bad3ad23 | |||
835a4b6497 | |||
d1a7b6988c | |||
365129d811 | |||
b840ac91dc | |||
dcd2f9ac77 | |||
37d9afc5cc | |||
62b3a1e800 | |||
9c54be6cf1 | |||
53409530b3 | |||
43014cd465 | |||
e27e3622d4 | |||
b169629dbd | |||
8fbeeb1439 | |||
2a489f844b | |||
a161aac7c1 | |||
a7f928ac31 | |||
50ae95cee4 | |||
f6bfa96a96 | |||
e86dcc9f18 | |||
9d33580aac | |||
77cfd504cf | |||
f7bbd467b5 | |||
8993ba4305 | |||
ba7313b521 | |||
e2d30641be | |||
2248773566 | |||
5f43d0ad42 | |||
af47531745 | |||
e80bd2d30c | |||
ac5815d994 | |||
540d741df0 | |||
ecb5854be0 | |||
25b650f59d | |||
ed6f19d3d8 | |||
aecd157244 | |||
43a98b0ec2 | |||
3b00cee858 | |||
2fbc0aefb1 | |||
2276a2f5c3 | |||
8fcca6fb41 | |||
b8568034f0 | |||
3ebf41ba34 | |||
304e84502d | |||
a6e42d98d9 | |||
de176a10bc | |||
e3183f7cda | |||
b5e0fff6b9 | |||
36db3428ab | |||
e7da8b9d6b | |||
c134df30db | |||
b5e6c2d6e2 | |||
b6f8509234 | |||
d45cd63583 | |||
0c9b460cc4 | |||
dd762726dc | |||
e68d57feec | |||
0c9d8e5929 | |||
75c3fa91dc | |||
a37c7e1246 | |||
392dcd57c6 | |||
1369cf7176 | |||
eccd0985a0 | |||
0617b8898a | |||
fbcdeb8439 | |||
6ed0a2b4aa | |||
8e50c0c103 | |||
f2cd5e1d8e | |||
9f6b012fbf | |||
ec0b83f127 | |||
0c81982e67 | |||
5014b86c3c | |||
44b5e1f488 | |||
31652eeb2a | |||
4bb4d4ad00 | |||
5331eca5d9 | |||
74e264a20a | |||
f0937f96d4 | |||
92cbdb9f45 | |||
fe36ceaa55 | |||
0618bfd4ae | |||
bdfd38771a | |||
477063e9ee | |||
e46c106b89 | |||
69630338ff | |||
112759cd39 | |||
f8767c397b | |||
e8d098335b | |||
12a87cfacb | |||
2806d6be2f | |||
2d9b793dbb | |||
7f02f0da61 | |||
bc2ccf464f | |||
b8536ced09 | |||
1db82f3303 | |||
fd713413e8 | |||
2d4a4ba73f | |||
348f980f21 | |||
ca55858aa7 | |||
e639521b01 | |||
894339c5d7 | |||
e13dc9b7e6 | |||
5fb657f569 | |||
d2700c7525 | |||
4cf358b589 | |||
5e708b23c6 | |||
9419e39fdf | |||
c202d80dea | |||
eecbdd99e1 | |||
64293cdc82 | |||
f8a5f1cd9e | |||
a3125c38f4 | |||
224add0222 | |||
19636f748c | |||
7aa5e1c443 | |||
93279db71b | |||
5bf760510e | |||
03dc80afc4 | |||
fda3106fd9 | |||
9721a77204 | |||
92a8c2804f | |||
e1521fa8eb | |||
4e3cd8ac3f | |||
31a8beb449 | |||
e7d871c8bf | |||
56d5aa3101 | |||
c6a2a4046e | |||
6dd5e931fc | |||
635140ba43 | |||
497f341eac | |||
068aa13c6b | |||
ba7ae6c59d | |||
6ae95271be | |||
a2e0163cc1 | |||
1db3b81d2e | |||
0a16ea7487 | |||
a26bb0b0f2 | |||
7d3530a22e | |||
a87ea96913 | |||
81609a0f42 | |||
938edab25f | |||
29c9870658 | |||
b6c4f3775a | |||
5ee5564ae2 | |||
ab36756061 | |||
831b8f35d5 | |||
0cf78b7748 | |||
0892a2245e | |||
622474e9e4 | |||
0cabc12f91 | |||
b282ce999d | |||
24b9d74e70 | |||
c03f2897d0 | |||
90fbf59bf1 | |||
93c7cbd496 | |||
db60555c1b | |||
45117a3384 | |||
4d4880b428 | |||
ac6ccd53df | |||
4ec376bd6a | |||
3c0448305b | |||
a6029a10cc | |||
26eaf53a83 | |||
5d623a27ed | |||
69e554b941 | |||
7340374a7c | |||
67d356b73f | |||
da18f1f722 | |||
58abcceff5 | |||
ad0d0c77fb | |||
2c3f761ede | |||
70c60cfba7 | |||
f3b6d64ad3 | |||
43e9a13921 | |||
526dbe8f16 | |||
951a0e5225 | |||
458b939bc4 | |||
476aca5b67 | |||
96bf0f8323 | |||
58206a3180 | |||
f138ab8ac6 | |||
50839cf6e9 | |||
626a4434ed | |||
d84cc73d13 | |||
6b049536f1 | |||
629edb1e78 | |||
8012b555a8 |
@ -24,7 +24,7 @@ import importlib.metadata
|
||||
|
||||
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
|
||||
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 17)
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
|
||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
|
||||
|
||||
|
||||
|
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
@ -5,7 +5,6 @@ on:
|
||||
branches:
|
||||
- stable
|
||||
- dev
|
||||
- 420
|
||||
pull_request:
|
||||
branches:
|
||||
- dev # No need for stable-pull-request, as that equals dev-push
|
||||
@ -35,23 +34,25 @@ jobs:
|
||||
run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 distrib
|
||||
- name: run tests
|
||||
run: sudo -E ./afl-system-config; make tests
|
||||
# macos:
|
||||
# runs-on: macOS-latest
|
||||
# env:
|
||||
# AFL_MAP_SIZE: 65536
|
||||
# AFL_SKIP_CPUFREQ: 1
|
||||
# AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - name: install
|
||||
# run: brew install make gcc llvm
|
||||
# - name: fix install
|
||||
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
|
||||
# - name: build
|
||||
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
|
||||
# - name: frida
|
||||
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||
# - name: run tests
|
||||
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||
# - name: force frida test for MacOS
|
||||
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||
macos:
|
||||
runs-on: macOS-latest
|
||||
env:
|
||||
AFL_MAP_SIZE: 65536
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: install
|
||||
run: brew install make gcc llvm
|
||||
# - name: fix install
|
||||
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
|
||||
# - name: build
|
||||
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
|
||||
- name: build
|
||||
run: sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
|
||||
# - name: frida
|
||||
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||
# - name: run tests
|
||||
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||
# - name: force frida test for MacOS
|
||||
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
*.pyc
|
||||
*.so
|
||||
*.swp
|
||||
.DS_Store
|
||||
.sync_tmp
|
||||
.test
|
||||
.test2
|
||||
@ -111,3 +112,5 @@ utils/replay_record/persistent_demo_replay_compat
|
||||
utils/replay_record/persistent_demo_replay_argparse
|
||||
utils/plot_ui/afl-plot-ui
|
||||
vuln_prog
|
||||
argv_fuzz_demo
|
||||
argv_fuzz_persistent_demo
|
@ -34,6 +34,7 @@ file in one the following folders:
|
||||
* [docs/](docs/) (this is where you can find most of our docs content)
|
||||
* [frida_mode/](frida_mode/)
|
||||
* [instrumentation/](instrumentation/)
|
||||
* [nyx_mode/](nyx_mode/)
|
||||
* [qemu_mode/](qemu_mode/)
|
||||
* [unicorn_mode/](unicorn_mode/)
|
||||
|
||||
@ -47,7 +48,7 @@ When working on the docs, please keep the following guidelines in mind:
|
||||
* Don't: fuzzing-network-service.md
|
||||
* Use a maximum of 80 characters per line to make reading in a console easier.
|
||||
* Make all pull requests against `dev`, see
|
||||
[#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl).
|
||||
[#how-to-submit-a-pull-request](#how-to-submit-a-pull-request).
|
||||
|
||||
And finally, here are some best practices for writing docs content:
|
||||
|
||||
@ -56,4 +57,4 @@ And finally, here are some best practices for writing docs content:
|
||||
* Use bulleted lists to present similar content in a way that makes it easy to
|
||||
scan.
|
||||
* Use numbered lists for procedures or prioritizing.
|
||||
* Link to related content, for example, prerequisites or in-depth discussions.
|
||||
* Link to related content, for example, prerequisites or in-depth discussions.
|
||||
|
77
GNUmakefile
77
GNUmakefile
@ -19,21 +19,21 @@
|
||||
# so use a variable for '#'
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH = $(PREFIX)/share/doc/afl
|
||||
MISC_PATH = $(PREFIX)/share/afl
|
||||
MAN_PATH = $(PREFIX)/share/man/man8
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH = $(PREFIX)/share/doc/afl
|
||||
MISC_PATH = $(PREFIX)/share/afl
|
||||
MAN_PATH = $(PREFIX)/share/man/man8
|
||||
INCLUDE_PATH = $(PREFIX)/include/afl
|
||||
|
||||
PROGNAME = afl
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
# PROGS intentionally omit afl-as, which gets installed elsewhere.
|
||||
|
||||
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
|
||||
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-addseeds afl-system-config afl-persistent-config afl-cc
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
|
||||
HEADERS = include/afl-fuzz.h include/afl-mutations.h include/afl-persistent-replay.h include/afl-prealloc.h include/afl-record-compat.h include/alloc-inl.h include/android-ashmem.h include/cmplog.h include/common.h include/config.h include/coverage-32.h include/coverage-64.h include/debug.h include/envs.h include/forkserver.h include/hash.h include/list.h include/sharedmem.h include/snapshot-inl.h include/t1ha.h include/t1ha0_ia32aes_b.h include/t1ha_bits.h include/t1ha_selfcheck.h include/types.h include/xxhash.h
|
||||
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8)
|
||||
ASAN_OPTIONS=detect_leaks=0
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
@ -41,10 +41,6 @@ ARCH = $(shell uname -m)
|
||||
|
||||
$(info [*] Compiling AFL++ for OS $(SYS) on ARCH $(ARCH))
|
||||
|
||||
ifdef NO_SPLICING
|
||||
override CFLAGS_OPT += -DNO_SPLICING
|
||||
endif
|
||||
|
||||
ifdef NO_UTF
|
||||
override CFLAGS_OPT += -DFANCY_BOXES_NO_UTF
|
||||
endif
|
||||
@ -65,6 +61,10 @@ ifdef MSAN_BUILD
|
||||
override CFLAGS += -fsanitize=memory -fno-omit-frame-pointer
|
||||
override LDFLAGS += -fsanitize=memory
|
||||
endif
|
||||
ifdef NO_SPLICING
|
||||
$(info The NO_SPLICING parameter is deprecated)
|
||||
endif
|
||||
|
||||
|
||||
ifdef CODE_COVERAGE
|
||||
override CFLAGS += -D__AFL_CODE_COVERAGE=1
|
||||
@ -117,7 +117,7 @@ endif
|
||||
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
||||
ifneq "$(COMPILER_TYPE)" ""
|
||||
#$(info gcc is being used)
|
||||
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||
override CFLAGS_OPT += -Wno-format-truncation
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "SunOS"
|
||||
@ -325,10 +325,12 @@ ifdef TEST_MMAP
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
|
||||
all: test_x86 test_shm test_python ready $(PROGS) llvm gcc_plugin test_build all_done
|
||||
-$(MAKE) -C utils/aflpp_driver
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
@echo Build Summary:
|
||||
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
|
||||
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
|
||||
@ -337,6 +339,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
|
||||
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"
|
||||
endif
|
||||
@test -e afl-cc || echo "[-] AFL++ instrumentation compilers could not be built! Install llvm-VERSION-dev or gcc-VERSION-plugin-dev, see docs/INSTALL.md!"
|
||||
@echo
|
||||
|
||||
.PHONY: llvm
|
||||
@ -405,7 +408,6 @@ help:
|
||||
@echo PROFILING - compile afl-fuzz with profiling information
|
||||
@echo INTROSPECTION - compile afl-fuzz with mutation introspection
|
||||
@echo NO_PYTHON - disable python support
|
||||
@echo NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
|
||||
@echo "NO_UTF - do not use UTF-8 for line rendering in status screen (fallback to G1 box drawing, of vanilla AFL)"
|
||||
@echo NO_NYX - disable building nyx mode dependencies
|
||||
@echo "NO_CORESIGHT - disable building coresight (arm64 only)"
|
||||
@ -441,6 +443,14 @@ test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <zlib.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
override SPECIAL_PERFORMANCE += -DHAVE_ZLIB
|
||||
override LDFLAGS += -lz
|
||||
$(info [+] ZLIB detected)
|
||||
else
|
||||
$(info [!] Warning: no ZLIB detected)
|
||||
endif
|
||||
|
||||
.PHONY: test_python
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
test_python:
|
||||
@ -455,10 +465,6 @@ endif
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
|
||||
|
||||
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
|
||||
@ln -sf afl-as as
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
@ -471,8 +477,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
$(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 src/hashmap.c | test_x86
|
||||
$(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-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(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)
|
||||
@ -566,27 +572,27 @@ code-format:
|
||||
|
||||
.PHONY: test_build
|
||||
ifndef AFL_NO_X86
|
||||
test_build: afl-cc afl-gcc afl-as afl-showmap
|
||||
test_build: afl-cc afl-showmap
|
||||
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
|
||||
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
||||
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
|
||||
-ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
|
||||
-echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo
|
||||
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
|
||||
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
|
||||
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
|
||||
# @echo "[*] Testing the CC wrapper and its instrumentation output..."
|
||||
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-clang-fast test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-clang-fast failed"; exit 1 )
|
||||
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
# @rm -f test-instr
|
||||
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
|
||||
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-clang-fast does not seem to be behaving correctly!"; \
|
||||
# gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option." ) || \
|
||||
# ( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
|
||||
# @echo
|
||||
# @echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
|
||||
# @echo "[+] All right, the instrumentation of afl-clang-fast seems to be working!"
|
||||
else
|
||||
test_build: afl-cc afl-as afl-showmap
|
||||
test_build: afl-cc afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
endif
|
||||
|
||||
@ -596,7 +602,8 @@ all_done: test_build
|
||||
@test -e cmplog-instructions-pass.so && echo "[+] LLVM mode for 'afl-cc' successfully built!" || echo "[-] LLVM mode for 'afl-cc' failed to build, likely you either don't have llvm installed, or you need to set LLVM_CONFIG, to point to e.g. llvm-config-11. See instrumentation/README.llvm.md how to do this. Highly recommended!"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@test -e afl-cc && echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@test -e afl-cc || echo "[-] ERROR - neither afl-clang-fast or afl-gcc-fast could be compiled - YOU ARE MISSING PACKAGES! Read docs/INSTALL.md!"
|
||||
@if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
@ -604,7 +611,7 @@ all_done: test_build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
|
||||
rm -rf $(PROGS) afl-fuzz-document as afl-as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
|
||||
-$(MAKE) -f GNUmakefile.llvm clean
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||
-$(MAKE) -C utils/libdislocator clean
|
||||
@ -817,10 +824,10 @@ endif
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
|
||||
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang++
|
||||
@mkdir -m 755 -p $${DESTDIR}$(INCLUDE_PATH)
|
||||
install -m 644 $(HEADERS) $${DESTDIR}$(INCLUDE_PATH)
|
||||
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
|
||||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
|
||||
@ -828,12 +835,14 @@ endif
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
|
||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-ld-lto afl-c* afl-lto*
|
||||
-cd $${DESTDIR}$(INCLUDE_PATH) && rm -f $(HEADERS:include/%=%)
|
||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt injections.dic
|
||||
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
|
||||
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
||||
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
||||
-rmdir $${DESTDIR}$(BIN_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(INCLUDE_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(HELPER_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(MISC_PATH) 2>/dev/null
|
||||
-rmdir $${DESTDIR}$(DOC_PATH) 2>/dev/null
|
||||
|
@ -163,7 +163,7 @@ $(PASSES): instrumentation/afl-gcc-common.h
|
||||
.PHONY: test_build
|
||||
test_build: $(PROGS)
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
|
@ -28,10 +28,13 @@ MAN_PATH ?= $(PREFIX)/share/man/man8
|
||||
|
||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||
VERSION = $(shell grep '^ *$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
|
||||
override LLVM_TOO_NEW_DEFAULT := 19
|
||||
override LLVM_TOO_OLD_DEFAULT := 13
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
@ -39,24 +42,36 @@ ifeq "$(SYS)" "OpenBSD"
|
||||
$(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
# Small function to use Bash to detect the latest available clang and clang++ binaries, if using them by that name fails
|
||||
override _CLANG_VERSIONS_TO_TEST := $(patsubst %,-%,$(shell seq $(LLVM_TOO_NEW_DEFAULT) -1 $(LLVM_TOO_OLD_DEFAULT)))
|
||||
detect_newest=$(shell for v in "" $(_CLANG_VERSIONS_TO_TEST); do test -n "$$(command -v -- $1$$v)" && { echo "$1$$v"; break; }; done)
|
||||
LLVM_CONFIG ?= $(call detect_newest,llvm-config)
|
||||
endif
|
||||
|
||||
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_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_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^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_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_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 )
|
||||
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 )
|
||||
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
|
||||
LLVM_LTO = 0
|
||||
ifneq "$(LLVM_CONFIG)" ""
|
||||
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
|
||||
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
|
||||
|
||||
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
|
||||
endif
|
||||
|
||||
ifneq "$(LLVMVER)" ""
|
||||
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
|
||||
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
|
||||
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
|
||||
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
|
||||
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
|
||||
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
|
||||
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
|
||||
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
|
||||
endif
|
||||
|
||||
LLVM_STDCXX := gnu++11
|
||||
LLVM_LTO := 0
|
||||
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.|^2[0-9]\.' && echo 1 || echo 0)
|
||||
# Uncomment to see the values assigned above
|
||||
# $(foreach var,_CLANG_VERSIONS_TO_TEST LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
|
||||
@ -103,10 +118,6 @@ ifeq "$(LLVM_LTO)" "0"
|
||||
$(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# We were using llvm-config --bindir to get the location of clang, but
|
||||
# this seems to be busted on some distros, so using the one in $PATH is
|
||||
# probably better.
|
||||
@ -114,6 +125,11 @@ endif
|
||||
CC = $(LLVM_BINDIR)/clang
|
||||
CXX = $(LLVM_BINDIR)/clang++
|
||||
|
||||
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
|
||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
# however we must ensure that this is not a "CC=gcc make"
|
||||
@ -147,7 +163,7 @@ endif
|
||||
|
||||
# sanity check.
|
||||
# Are versions of clang --version and llvm-config --version equal?
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
# I disable this because it does not make sense with what we did before (marc)
|
||||
# We did exactly set these 26 lines above with these values, and it would break
|
||||
@ -245,7 +261,7 @@ endif
|
||||
|
||||
AFL_CLANG_FUSELD=
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=$$(command -v ld) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FUSELD=1
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_LDPATH=1
|
||||
@ -300,8 +316,8 @@ endif
|
||||
ifneq "$(LLVM_CONFIG)" ""
|
||||
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
|
||||
endif
|
||||
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
|
||||
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
|
||||
CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
|
||||
CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS)
|
||||
|
||||
# wasm fuzzing: disable thread-local storage and unset LLVM debug flag
|
||||
ifdef WAFL_MODE
|
||||
@ -311,7 +327,7 @@ endif
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(SYS)" "Darwin"
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
CLANG_LFL += -Wl,-undefined,dynamic_lookup
|
||||
override LLVM_HAVE_LTO := 0
|
||||
override LLVM_LTO := 0
|
||||
else
|
||||
@ -319,7 +335,7 @@ else
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
|
||||
CLANG_LFL += $(LLVM_LIBDIR)/libLLVM.so
|
||||
CLANG_CPPFL += -mno-retpoline
|
||||
CFLAGS += -mno-retpoline
|
||||
# Needed for unwind symbols
|
||||
@ -417,7 +433,7 @@ endif
|
||||
endif
|
||||
|
||||
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
|
||||
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||
|
||||
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
||||
@ -492,7 +508,7 @@ document:
|
||||
.PHONY: test_build
|
||||
test_build: $(PROGS)
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
|
@ -1,10 +1,10 @@
|
||||
# American Fuzzy Lop plus plus (AFL++)
|
||||
|
||||
<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" height="250">
|
||||
|
||||
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.30c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.20c
|
||||
GitHub version: 4.31a
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
3
TODO.md
3
TODO.md
@ -2,6 +2,8 @@
|
||||
|
||||
## Must
|
||||
|
||||
- ijon support?
|
||||
- check for null ptr for xml/curl/g_ string transform functions
|
||||
- hardened_usercopy=0 page_alloc.shuffle=0
|
||||
- add value_profile but only enable after 15 minutes without finds
|
||||
- cmplog max items env?
|
||||
@ -16,6 +18,7 @@
|
||||
## Should
|
||||
|
||||
- afl-crash-analysis
|
||||
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
|
||||
- support persistent and deferred fork server in afl-showmap?
|
||||
- better autodetection of shifting runtime timeout values
|
||||
- afl-plot to support multiple plot_data
|
||||
|
6
afl-cmin
6
afl-cmin
@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
|
||||
# awk script to minimize a test corpus of input files
|
||||
#
|
||||
# based on afl-cmin bash script written by Michal Zalewski
|
||||
# rewritten by Heiko Eißfeldt (hexcoder-)
|
||||
# rewritten by Heiko Eissfeldt (hexcoder-)
|
||||
# tested with:
|
||||
# gnu awk (x86 Linux)
|
||||
# bsd awk (x86 *BSD)
|
||||
@ -603,8 +603,8 @@ BEGIN {
|
||||
# create path for the trace file from afl-showmap
|
||||
tracefile_path = trace_dir"/"fn
|
||||
# ensure the file size is not zero
|
||||
cmd = "du -b "tracefile_path
|
||||
"ls -l "tracefile_path
|
||||
cmd = "du -b \""tracefile_path"\""
|
||||
# "ls -l \""tracefile_path"\""
|
||||
cmd | getline output
|
||||
close(cmd)
|
||||
split(output, result, "\t")
|
||||
|
@ -152,6 +152,7 @@ Minimization settings:
|
||||
-e - solve for edge coverage only, ignore hit counts
|
||||
|
||||
For additional tips, please consult README.md.
|
||||
This script cannot read filenames that end with a space ' '.
|
||||
|
||||
Environment variables used:
|
||||
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
|
||||
|
@ -111,7 +111,13 @@ if [ -z "$NO_COLOR" ]; then
|
||||
RESET="$NC"
|
||||
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
|
||||
trap "rm -f $TMP" 1 2 3 13 15
|
||||
|
@ -11,3 +11,4 @@
|
||||
|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 |
|
||||
|Ampere Altra Q80-30 | 0 | 80 | 54477 | 1604482 | system |
|
||||
|
@ -48,7 +48,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
u8 *ptr = realloc(data->buf, max_size);
|
||||
|
||||
if (ptr) {
|
||||
if (!ptr) {
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC
|
||||
all: aflpp-standalone
|
||||
|
||||
aflpp-standalone: aflpp-standalone.c
|
||||
$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c ../../../src/afl-fuzz-extras.c ../../../src/afl-common.c
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ aflpp-standalone core
|
||||
|
@ -5,6 +5,6 @@ this is the AFL++ havoc mutator as a standalone mutator
|
||||
just type `make` to build.
|
||||
|
||||
```
|
||||
aflpp-standalone inputfile outputfile [splicefile]
|
||||
aflpp-standalone -h # to see all parameteres
|
||||
cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int max_havoc = 16, verbose;
|
||||
static unsigned char *dict;
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
@ -21,14 +27,14 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
}
|
||||
|
||||
if ((data->buf = malloc(1024*1024)) == NULL) {
|
||||
if ((data->buf = malloc(1024 * 1024)) == NULL) {
|
||||
|
||||
perror("afl_custom_init alloc");
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
|
||||
data->buf_size = 1024*1024;
|
||||
data->buf_size = 1024 * 1024;
|
||||
|
||||
}
|
||||
|
||||
@ -36,9 +42,23 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
data->afl = calloc(1, sizeof(afl_state_t));
|
||||
data->afl->queue_cycle = 1;
|
||||
data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
|
||||
if (data->afl->fsrv.dev_urandom_fd < 0) {
|
||||
|
||||
PFATAL("Unable to open /dev/urandom");
|
||||
|
||||
}
|
||||
|
||||
rand_set_seed(data->afl, getpid());
|
||||
|
||||
if (dict) {
|
||||
|
||||
load_extras(data->afl, dict);
|
||||
if (verbose)
|
||||
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
|
||||
data->afl->extras_cnt);
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
@ -53,7 +73,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
u8 *ptr = realloc(data->buf, max_size);
|
||||
|
||||
if (ptr) {
|
||||
if (!ptr) {
|
||||
|
||||
return 0;
|
||||
|
||||
@ -66,14 +86,20 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
}
|
||||
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, 16);
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, max_havoc);
|
||||
if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps);
|
||||
|
||||
/* set everything up, costly ... :( */
|
||||
memcpy(data->buf, buf, buf_size);
|
||||
|
||||
/* the mutation */
|
||||
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
|
||||
false, true, add_buf, add_buf_size, max_size);
|
||||
u32 out_buf_len;
|
||||
do {
|
||||
|
||||
out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, false,
|
||||
true, add_buf, add_buf_size, max_size);
|
||||
|
||||
} while (out_buf_len == buf_size && memcmp(buf, data->buf, buf_size) == 0);
|
||||
|
||||
/* return size of mutated data */
|
||||
*out_buf = data->buf;
|
||||
@ -84,80 +110,143 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
|
||||
printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]);
|
||||
printf("Reads a testcase from stdin when no input file (or '-') is specified,\n");
|
||||
printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n");
|
||||
printf("no output filename is given. As an optional third parameter you can give a file\n");
|
||||
|
||||
printf(
|
||||
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
|
||||
"[splicefile]]]\n\n",
|
||||
argv[0]);
|
||||
printf(
|
||||
"Reads a testcase from stdin when no input file (or '-') is "
|
||||
"specified,\n");
|
||||
printf(
|
||||
"mutates according to AFL++'s mutation engine, and write to stdout "
|
||||
"when '-' or\n");
|
||||
printf(
|
||||
"no output filename is given. As an optional third parameter you can "
|
||||
"give a file\n");
|
||||
printf("for splicing. Maximum input and output length is 1MB.\n");
|
||||
printf("The -v verbose option prints debug output to stderr.\n");
|
||||
printf("Options:\n");
|
||||
printf(" -v verbose debug output to stderr.\n");
|
||||
printf(" -m val max mutations (1-val, val default is 16)\n");
|
||||
printf(" -x file dictionary file (AFL++ format)\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL;
|
||||
int verbose = 0, splicelen = 0;
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
|
||||
int splicelen = 0, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'm':
|
||||
max_havoc = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'x':
|
||||
dict = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (max_havoc < 1) {
|
||||
|
||||
fprintf(stderr, "Error: illegal -m value\n");
|
||||
exit(-1);
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-v") == 0) {
|
||||
verbose = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
fprintf(stderr, "Verbose active\n");
|
||||
}
|
||||
|
||||
my_mutator_t *data = afl_custom_init(NULL, 0);
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-") != 0) {
|
||||
if ((in = fopen(argv[1], "r")) == NULL) {
|
||||
if (argc > optind && strcmp(argv[optind], "-") != 0) {
|
||||
|
||||
if ((in = fopen(argv[optind], "r")) == NULL) {
|
||||
|
||||
perror(argv[1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
|
||||
|
||||
}
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024*1024, in);
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
|
||||
|
||||
if (!inlen) {
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n",
|
||||
argv[optind] ? argv[optind] : "stdin");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (argc > 2 && strcmp(argv[2], "-") != 0) {
|
||||
if ((out = fopen(argv[2], "w")) == NULL) {
|
||||
perror(argv[2]);
|
||||
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
|
||||
|
||||
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
|
||||
|
||||
perror(argv[optind + 1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
|
||||
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
if ((splice = fopen(argv[3], "r")) == NULL) {
|
||||
perror(argv[3]);
|
||||
if (argc > optind + 2) {
|
||||
|
||||
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
|
||||
|
||||
perror(argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
|
||||
splicebuf = malloc(1024*1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024*1024, splice);
|
||||
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
|
||||
splicebuf = malloc(1024 * 1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
|
||||
if (!splicelen) {
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[3]);
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
|
||||
splicelen, 1024 * 1024);
|
||||
|
||||
if (outlen == 0 || !outbuf) {
|
||||
|
||||
fprintf(stderr, "Error: no mutation data returned.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||
|
||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||
|
||||
fprintf(stderr, "Warning: incomplete write.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`.
|
||||
**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
|
||||
|
||||
```bash
|
||||
# create the required a random seed first
|
||||
# create the required random seed first
|
||||
mkdir -p ~/campaign/example/seeds
|
||||
cd ~/campaign/example/seeds
|
||||
head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded
|
||||
|
@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
|
||||
|
||||
if (fd_socket != -1) { close(fd_socket); }
|
||||
*out_buf = NULL;
|
||||
return 0;
|
||||
fprintf(stderr, "atnwalk.socket not found in current directory!\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ extern "C" {
|
||||
#ifndef AFL_TXT_MAX_LEN
|
||||
#define AFL_TXT_MAX_LEN 65535
|
||||
#endif
|
||||
#define AUTOTOKENS_TXT_MIN_LEN 1
|
||||
|
||||
#if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN
|
||||
#error SPLICE_MIN must be lower than SIZE_MIN
|
||||
@ -57,8 +58,9 @@ typedef struct my_mutator {
|
||||
if (unlikely(debug)) fprintf
|
||||
#define IFDEBUG if (unlikely(debug))
|
||||
|
||||
int module_disabled = 0;
|
||||
|
||||
static afl_state *afl_ptr;
|
||||
static int module_disabled = 0;
|
||||
static int auto_disable = AUTOTOKENS_AUTO_DISABLE;
|
||||
static int debug = AUTOTOKENS_DEBUG;
|
||||
static int only_fav = AUTOTOKENS_ONLY_FAV;
|
||||
@ -104,9 +106,9 @@ static void first_run(void *data) {
|
||||
if (afl_ptr->custom_only || !auto_disable) { return; }
|
||||
|
||||
if (unlikely(afl_ptr->active_items == 1 &&
|
||||
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) {
|
||||
afl_ptr->queue_cur->len < AUTOTOKENS_TXT_MIN_LEN)) {
|
||||
|
||||
if (afl_ptr->extras_cnt > 8) {
|
||||
if (afl_ptr->extras_cnt) {
|
||||
|
||||
u32 valid = 0;
|
||||
|
||||
@ -237,7 +239,7 @@ extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf,
|
||||
|
||||
}
|
||||
|
||||
extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
|
||||
extern "C" size_t afl_custom_fuzz(void *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, u8 *add_buf,
|
||||
size_t add_buf_size, size_t max_size) {
|
||||
|
||||
@ -655,6 +657,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 &&
|
||||
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) {
|
||||
|
||||
retry_thin_air:
|
||||
DEBUGF(stderr, "Creating an entry from thin air...\n");
|
||||
structure = new vector<u32>();
|
||||
u32 item, prev, cnt = current_id >> 1;
|
||||
@ -684,8 +687,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
create_from_thin_air = 0;
|
||||
|
||||
}
|
||||
|
||||
if (entry == file_mapping.end()) {
|
||||
@ -693,7 +694,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
// this input file was not analyzed for tokens yet, so let's do it!
|
||||
size_t len = afl_ptr->queue_cur->len;
|
||||
|
||||
if (len < AFL_TXT_MIN_LEN) {
|
||||
if (len < AUTOTOKENS_TXT_MIN_LEN) {
|
||||
|
||||
file_mapping[fn] = structure; // NULL ptr so we don't read the file again
|
||||
s = NULL;
|
||||
@ -895,6 +896,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
if (tokens.size() < AUTOTOKENS_SIZE_MIN) {
|
||||
|
||||
if (create_from_thin_air) { goto retry_thin_air; }
|
||||
file_mapping[fn] = NULL;
|
||||
s = NULL;
|
||||
DEBUGF(stderr, "too few tokens\n");
|
||||
@ -955,7 +957,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
|
||||
extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
(void)(seed);
|
||||
my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t));
|
||||
@ -1070,7 +1072,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
|
||||
id_to_token[current_id] = "'";
|
||||
++current_id;
|
||||
|
||||
return data;
|
||||
return (void *)data;
|
||||
|
||||
}
|
||||
|
||||
|
19
custom_mutators/autotokens/standalone/Makefile
Normal file
19
custom_mutators/autotokens/standalone/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
CFLAGS = -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1 -Wno-implicit-function-declaration
|
||||
CXXFLAGS= -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1
|
||||
|
||||
all: autotokens-standalone
|
||||
|
||||
autotokens.o: ../autotokens.cpp
|
||||
$(CXX) $(CXXFLAGS) -I../../../include -I. -I../.. -c ../autotokens.cpp
|
||||
|
||||
autotokens-standalone: autotokens-standalone.c autotokens.o
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c autotokens-standalone.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-performance.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-extras.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-queue.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-common.c
|
||||
$(CXX) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o autotokens-standalone *.o
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ autotokens-standalone core
|
12
custom_mutators/autotokens/standalone/README.md
Normal file
12
custom_mutators/autotokens/standalone/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Autotokens standalone mutator
|
||||
|
||||
this is a standalone version of the AFL++ autotokens custom mutator.
|
||||
|
||||
just type `make` to build.
|
||||
|
||||
You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer!
|
||||
|
||||
```
|
||||
autotokens-standalone -h # to see all parameteres
|
||||
autotokens-standalone -x foo.dict inputfile outputfile # example
|
||||
```
|
192
custom_mutators/autotokens/standalone/autotokens-standalone.c
Normal file
192
custom_mutators/autotokens/standalone/autotokens-standalone.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int max_havoc = 16, verbose;
|
||||
static unsigned char *dict, *mh = "16";
|
||||
|
||||
extern int module_disabled;
|
||||
|
||||
void *afl_custom_init(afl_state_t *, unsigned int);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
|
||||
|
||||
printf(
|
||||
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
|
||||
"[splicefile]]]\n\n",
|
||||
argv[0]);
|
||||
printf("Reads a testcase from a file (not stdin!),\n");
|
||||
printf("writes to stdout when '-' or\n");
|
||||
printf(
|
||||
"no output filename is given. As an optional third parameter you can "
|
||||
"give a file\n");
|
||||
printf("for splicing. Maximum input and output length is 1MB.\n");
|
||||
printf("Options:\n");
|
||||
printf(" -v verbose debug output to stderr.\n");
|
||||
printf(" -m val max mutations (1-val, val default is 16)\n");
|
||||
printf(" -x file dictionary file (AFL++ format)\n");
|
||||
printf("You can set the following environment variable parameters:\n");
|
||||
printf("AUTOTOKENS_COMMENT` - what character or string starts a comment which will be\n");
|
||||
printf(" removed. Default: \"/* ... */\"\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
|
||||
int splicelen = 0, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'm':
|
||||
max_havoc = atoi(optarg);
|
||||
mh = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'x':
|
||||
dict = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (max_havoc < 1) {
|
||||
|
||||
fprintf(stderr, "Error: illegal -m value\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind && strcmp(argv[optind], "-") != 0) {
|
||||
|
||||
if ((in = fopen(argv[optind], "r")) == NULL) {
|
||||
|
||||
perror(argv[1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
|
||||
|
||||
}
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
|
||||
|
||||
if (!inlen) {
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n",
|
||||
argv[optind] ? argv[optind] : "stdin");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
|
||||
|
||||
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
|
||||
|
||||
perror(argv[optind + 1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind + 2) {
|
||||
|
||||
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
|
||||
|
||||
perror(argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
|
||||
splicebuf = malloc(1024 * 1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
|
||||
if (!splicelen) {
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
|
||||
|
||||
}
|
||||
|
||||
/* configure autotokens */
|
||||
setenv("AUTOTOKENS_LEARN_DICT", "1", 0);
|
||||
setenv("AUTOTOKENS_CREATE_FROM_THIN_AIR", "1", 0);
|
||||
setenv("AUTOTOKENS_CHANGE_MAX", mh, 0);
|
||||
|
||||
/* fake AFL++ state */
|
||||
afl_state_t *afl = (afl_state_t *)calloc(1, sizeof(afl_state_t));
|
||||
afl->queue_cycle = afl->havoc_div = afl->active_items = afl->queued_items = 1;
|
||||
afl->shm.cmplog_mode = 0;
|
||||
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
|
||||
|
||||
rand_set_seed(afl, getpid());
|
||||
|
||||
if (dict) {
|
||||
|
||||
load_extras(afl, dict);
|
||||
if (verbose)
|
||||
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
|
||||
afl->extras_cnt);
|
||||
|
||||
}
|
||||
|
||||
// setup a fake queue entry
|
||||
afl->queue_buf = malloc(64);
|
||||
afl->queue_buf[0] = afl->queue_cur =
|
||||
(struct queue_entry *)malloc(sizeof(struct queue_entry));
|
||||
afl->queue_cur->testcase_buf = inbuf;
|
||||
afl->queue_cur->fname = (u8 *)argv[optind];
|
||||
afl->queue_cur->len = inlen;
|
||||
afl->queue_cur->perf_score = 100;
|
||||
afl->queue_cur->favored = afl->queue_cur->is_ascii = 1;
|
||||
// afl->custom_only = 1;
|
||||
|
||||
void *data = (void *)afl_custom_init(afl, (u32)0);
|
||||
|
||||
u8 res = afl_custom_queue_get(inbuf, (u8 *)argv[optind]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
|
||||
splicelen, 1024 * 1024);
|
||||
|
||||
if (outlen == 0 || !outbuf) {
|
||||
|
||||
fprintf(stderr, "Error: no mutation data returned.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||
|
||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||
|
||||
fprintf(stderr, "Warning: incomplete write.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
7
custom_mutators/custom_send_tcp/Makefile
Normal file
7
custom_mutators/custom_send_tcp/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
all: custom_send_tcp.so
|
||||
|
||||
custom_send_tcp.so:
|
||||
$(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c
|
||||
|
||||
clean:
|
||||
rm -f custom_send_tcp.so *.o *~ core
|
13
custom_mutators/custom_send_tcp/README.md
Normal file
13
custom_mutators/custom_send_tcp/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Send testcases via TCP custom mutator
|
||||
|
||||
This custom mutator sends the fuzzing testcases via TCP.
|
||||
|
||||
`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set!
|
||||
`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense)
|
||||
`CUSTOM_SEND_PORT` - the TCP port to send to
|
||||
`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target
|
||||
|
||||
Example:
|
||||
```
|
||||
CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ...
|
||||
```
|
113
custom_mutators/custom_send_tcp/custom_send_tcp.c
Normal file
113
custom_mutators/custom_send_tcp/custom_send_tcp.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
static int my_debug = 0;
|
||||
static int my_read = 0;
|
||||
|
||||
#define DEBUG(...) if (my_debug) printf(__VA_ARGS__)
|
||||
|
||||
typedef struct tcp_send_mutator {
|
||||
afl_state_t* afl;
|
||||
struct sockaddr_in server_addr;
|
||||
} tcp_send_mutator_t;
|
||||
|
||||
void *afl_custom_init(afl_state_t* afl, uint32_t seed) {
|
||||
const char* ip = getenv("CUSTOM_SEND_IP");
|
||||
const char* port = getenv("CUSTOM_SEND_PORT");
|
||||
|
||||
if (getenv("AFL_DEBUG")) my_debug = 1;
|
||||
if (getenv("CUSTOM_SEND_READ")) my_read = 1;
|
||||
|
||||
if (!ip || !port) {
|
||||
fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t));
|
||||
if (!mutator) {
|
||||
fprintf(stderr, "Failed to allocate mutator struct\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mutator->afl = afl;
|
||||
|
||||
bzero(&mutator->server_addr, sizeof(mutator->server_addr));
|
||||
mutator->server_addr.sin_family = AF_INET;
|
||||
if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) {
|
||||
fprintf(stderr, "Could not convert target ip address!\n");
|
||||
exit(1);
|
||||
}
|
||||
mutator->server_addr.sin_port = htons(atoi(port));
|
||||
|
||||
printf("[+] Custom tcp send mutator setup ready to go!\n");
|
||||
|
||||
return mutator;
|
||||
}
|
||||
|
||||
int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) {
|
||||
while (max_attempts > 0) {
|
||||
if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the
|
||||
// application under test having started to listen for connections and
|
||||
// afl_custom_fuzz_send being called. To address this race, we attempt
|
||||
// to connect N times and sleep a short period of time in between
|
||||
// connection attempts.
|
||||
struct timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 100;
|
||||
nanosleep(&t, NULL);
|
||||
--max_attempts;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) {
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
int written = 0;
|
||||
if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) {
|
||||
DEBUG("connected, write()\n");
|
||||
written = write(sock, buf, buf_size);
|
||||
} else {
|
||||
DEBUG("socket() or connect() error: %d\n", errno);
|
||||
}
|
||||
|
||||
if (written < 0) {
|
||||
DEBUG("write() error: %d\n", errno);
|
||||
} else if (my_read) {
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int select_res = select(sock + 1, &set, NULL, NULL, &timeout);
|
||||
if (select_res == -1) {
|
||||
DEBUG("select() error: %d\n", errno);
|
||||
} else if (select_res == 0) {
|
||||
DEBUG("read() timeout!\n");
|
||||
} else {
|
||||
uint8_t buf[64];
|
||||
(void)read(sock, buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void afl_custom_deinit(tcp_send_mutator_t* mutator) {
|
||||
free(mutator);
|
||||
}
|
Submodule custom_mutators/gramatron/json-c updated: 11546bfd07...af8dd4a307
@ -1 +1 @@
|
||||
5ed4f8d
|
||||
05d8f53
|
||||
|
Submodule custom_mutators/grammar_mutator/grammar_mutator updated: 5ed4f8d6e6...05d8f537f8
@ -3707,7 +3707,7 @@ typedef intptr_t wdiff;
|
||||
1024 * 1024 * 8 /* static malloc'd heap size if used as a library */
|
||||
#define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */
|
||||
#define FMAX \
|
||||
((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
*/
|
||||
#define MAXOBJ 0xffff /* max words in tuple including header */
|
||||
#define MAXPAYL \
|
||||
|
@ -5,4 +5,5 @@ members = [
|
||||
"example",
|
||||
# Lain needs a nightly toolchain
|
||||
# "example_lain",
|
||||
]
|
||||
# "example_lain_post_process",
|
||||
]
|
||||
|
@ -5,7 +5,15 @@ Bindings to create custom mutators in Rust.
|
||||
These bindings are documented with rustdoc. To view the documentation run
|
||||
```cargo doc -p custom_mutator --open```.
|
||||
|
||||
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
|
||||
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
|
||||
|
||||
An example using [lain](https://github.com/microsoft/lain) for structured fuzzing can be found in `example_lain`.
|
||||
Since lain requires a nightly rust toolchain, you need to set one up before you can play with it.
|
||||
|
||||
An example for the use of the post_process function, using [lain](https://github.com/microsoft/lain) with [serde](https://github.com/serde-rs/serde) and [bincode](https://github.com/bincode-org/bincode) can be found in `example_lain_post_process`.
|
||||
In order for it to work you need to:
|
||||
|
||||
- disable input trimming with `AFL_DISABLE_TRIM=1`
|
||||
- provide an initial instance serialized with `bincode` or use the `AFL_NO_STARTUP_CALIBRATION=1` environment variable.
|
||||
|
||||
Note that `bincode` can also be used to serialize/deserialize the lain-generated structure and mutate it rather than generating a new one at each iteration, but it requires some structure serialized with `bincode` as input seed.
|
||||
|
@ -73,6 +73,8 @@ pub trait RawCustomMutator {
|
||||
None
|
||||
}
|
||||
|
||||
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]>;
|
||||
|
||||
/*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
|
||||
int afl_custom_init_trim(&self, buffer: &[u8]);
|
||||
size_t afl_custom_trim(&self, unsigned char **out_buf);
|
||||
@ -353,6 +355,33 @@ pub mod wrappers {
|
||||
Err(err) => panic_handler("afl_custom_queue_get", &err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal function used in the macro
|
||||
pub unsafe fn afl_custom_post_process<M: RawCustomMutator>(
|
||||
data: *mut c_void,
|
||||
buf: *mut u8,
|
||||
buf_size: usize,
|
||||
out_buf: *mut *const u8,
|
||||
) -> usize {
|
||||
match catch_unwind(|| {
|
||||
let mut context = FFIContext::<M>::from(data);
|
||||
|
||||
assert!(!buf.is_null(), "null buf passed to afl_custom_post_process");
|
||||
assert!(
|
||||
!out_buf.is_null(),
|
||||
"null out_buf passed to afl_custom_post_process"
|
||||
);
|
||||
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
|
||||
if let Some(buffer) = context.mutator.post_process(buff_slice) {
|
||||
*out_buf = buffer.as_ptr();
|
||||
return buffer.len();
|
||||
}
|
||||
0
|
||||
}) {
|
||||
Ok(ret) => ret,
|
||||
Err(err) => panic_handler("afl_custom_post_process", &err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An exported macro to defined afl_custom_init meant for insternal usage
|
||||
@ -480,6 +509,16 @@ macro_rules! export_mutator {
|
||||
pub unsafe extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) {
|
||||
$crate::wrappers::afl_custom_deinit_::<$mutator_type>(data)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn afl_custom_post_process(
|
||||
data: *mut ::std::os::raw::c_void,
|
||||
buf: *mut u8,
|
||||
buf_size: usize,
|
||||
out_buf: *mut *const u8,
|
||||
) -> usize {
|
||||
$crate::wrappers::afl_custom_post_process::<$mutator_type>(data, buf, buf_size, out_buf)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -512,6 +551,10 @@ mod sanity_test {
|
||||
) -> Option<&'b [u8]> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
export_mutator!(ExampleMutator);
|
||||
@ -579,6 +622,13 @@ pub trait CustomMutator {
|
||||
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn post_process<'b, 's: 'b>(
|
||||
&'s mut self,
|
||||
buffer: &'b mut [u8],
|
||||
) -> Result<Option<&'b [u8]>, Self::Error> {
|
||||
Ok(Some(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> RawCustomMutator for M
|
||||
@ -682,6 +732,16 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
|
||||
match self.post_process(buffer) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
Self::handle_error(e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// the default value to return from [`CustomMutator::describe`].
|
||||
|
@ -8,9 +8,9 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
custom_mutator = { path = "../custom_mutator" }
|
||||
lain="0.5"
|
||||
lain = { git = "https://github.com/AFLplusplus/lain.git" }
|
||||
|
||||
[[example]]
|
||||
name = "example_lain"
|
||||
path = "./src/lain_mutator.rs"
|
||||
crate-type = ["cdylib"]
|
||||
crate-type = ["cdylib"]
|
||||
|
21
custom_mutators/rust/example_lain_post_process/Cargo.toml
Normal file
21
custom_mutators/rust/example_lain_post_process/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "example_lain_post_process"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Julius Hohnerlein <julihoh@users.noreply.github.com>",
|
||||
"jma <94166787+jma-qb@users.noreply.github.com>",
|
||||
]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
custom_mutator = { path = "../custom_mutator" }
|
||||
lain = { git = "https://github.com/AFLplusplus/lain.git" }
|
||||
bincode = "1.3.3"
|
||||
serde = { version = "1.0.214", features = ["derive"] }
|
||||
|
||||
[[example]]
|
||||
name = "example_lain_post_process"
|
||||
path = "./src/lain_mutator.rs"
|
||||
crate-type = ["cdylib"]
|
@ -0,0 +1 @@
|
||||
nightly
|
@ -0,0 +1,70 @@
|
||||
#![cfg(unix)]
|
||||
|
||||
use custom_mutator::{export_mutator, CustomMutator};
|
||||
use lain::{
|
||||
mutator::Mutator,
|
||||
prelude::*,
|
||||
rand::{rngs::StdRng, SeedableRng},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Mutatable, NewFuzzed, BinarySerialize)]
|
||||
struct MyStruct {
|
||||
tag: u8,
|
||||
#[lain(ignore)]
|
||||
length: u32,
|
||||
#[lain(min = 0, max = 10)]
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
struct LainMutator {
|
||||
mutator: Mutator<StdRng>,
|
||||
buffer: Vec<u8>,
|
||||
post_buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl CustomMutator for LainMutator {
|
||||
type Error = ();
|
||||
|
||||
fn init(seed: u32) -> Result<Self, ()> {
|
||||
Ok(Self {
|
||||
mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)),
|
||||
buffer: Vec::new(),
|
||||
post_buffer: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
fn fuzz<'b, 's: 'b>(
|
||||
&'s mut self,
|
||||
_buffer: &'b mut [u8],
|
||||
_add_buff: Option<&[u8]>,
|
||||
max_size: usize,
|
||||
) -> Result<Option<&'b [u8]>, ()> {
|
||||
// we just sample an instance of MyStruct, ignoring the current input
|
||||
let instance = MyStruct::new_fuzzed(&mut self.mutator, None);
|
||||
let serialized = bincode::serialize(&instance).unwrap();
|
||||
let size = serialized.len();
|
||||
if size > max_size {
|
||||
return Err(());
|
||||
}
|
||||
self.buffer.clear();
|
||||
self.buffer.reserve(size);
|
||||
self.buffer.extend_from_slice(&serialized);
|
||||
Ok(Some(self.buffer.as_slice()))
|
||||
}
|
||||
|
||||
fn post_process<'b, 's: 'b>(
|
||||
&'s mut self,
|
||||
buffer: &'b mut [u8],
|
||||
) -> Result<Option<&'b [u8]>, Self::Error> {
|
||||
let mut instance = bincode::deserialize::<MyStruct>(&buffer).unwrap();
|
||||
instance.length = instance.data.len() as u32;
|
||||
let size = instance.serialized_size();
|
||||
self.post_buffer.clear();
|
||||
self.post_buffer.reserve(size);
|
||||
instance.binary_serialize::<_, BigEndian>(&mut self.post_buffer);
|
||||
Ok(Some(&self.post_buffer))
|
||||
}
|
||||
}
|
||||
|
||||
export_mutator!(LainMutator);
|
@ -22,10 +22,10 @@ afl_state_t *afl_struct;
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
u8 * mutator_buf;
|
||||
u8 * out_dir;
|
||||
u8 * tmp_dir;
|
||||
u8 * target;
|
||||
u8 *mutator_buf;
|
||||
u8 *out_dir;
|
||||
u8 *tmp_dir;
|
||||
u8 *target;
|
||||
uint32_t seed;
|
||||
|
||||
} my_mutator_t;
|
||||
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
/* When a new queue entry is added we run this input with the symcc
|
||||
instrumented binary */
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
|
||||
struct dirent **nl;
|
||||
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
|
||||
u8 * origin_name = basename(filename_new_queue);
|
||||
u8 *origin_name = basename(filename_new_queue);
|
||||
int32_t i;
|
||||
if (items > 0) {
|
||||
|
||||
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
u8 *destination_name =
|
||||
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
|
||||
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
|
||||
origin_name, nl[i]->d_name);
|
||||
rename(source_name, destination_name);
|
||||
ck_free(destination_name);
|
||||
DBG("found=%s\n", source_name);
|
||||
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
|
||||
struct stat st;
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
if (items <= 0) return 0;
|
||||
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
for (i = 0; i < (s32)items; ++i) {
|
||||
|
||||
struct stat st;
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
if (!done) {
|
||||
|
||||
if (done == 0) {
|
||||
struct stat st;
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
}
|
||||
|
||||
unlink(fn);
|
||||
ck_free(fn);
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
free(nl[i]);
|
||||
|
||||
}
|
||||
|
120
dictionaries/jsonschema.dict
Normal file
120
dictionaries/jsonschema.dict
Normal file
@ -0,0 +1,120 @@
|
||||
#
|
||||
# AFL dictionary for JSON Schema
|
||||
# https://json-schema.org/
|
||||
# -----------------------
|
||||
#
|
||||
|
||||
"\"$schema\""
|
||||
"\"$id\""
|
||||
"\"$ref\""
|
||||
"\"$defs\""
|
||||
"\"definitions\""
|
||||
"\"enum\""
|
||||
"\"const\""
|
||||
"\"type\""
|
||||
|
||||
# Annotations
|
||||
|
||||
"\"title\""
|
||||
"\"description\""
|
||||
"\"default\""
|
||||
"\"examples\""
|
||||
"\"$comment\""
|
||||
"\"readOnly\""
|
||||
"\"writeOnly\""
|
||||
"\"deprecated\""
|
||||
|
||||
# Types
|
||||
|
||||
"\"string\""
|
||||
"\"integer\""
|
||||
"\"number\""
|
||||
"\"object\""
|
||||
"\"array\""
|
||||
"\"null\""
|
||||
"\"boolean\""
|
||||
|
||||
# String
|
||||
|
||||
"\"minLength\""
|
||||
"\"maxLength\""
|
||||
"\"pattern\""
|
||||
"\"format\""
|
||||
"\"contentMediaType\""
|
||||
"\"contentEncoding\""
|
||||
"\"contentSchema\""
|
||||
|
||||
# Formats
|
||||
|
||||
"\"date-time\""
|
||||
"\"time\""
|
||||
"\"date\""
|
||||
"\"duration\""
|
||||
"\"email\""
|
||||
"\"idn-email\""
|
||||
"\"hostname\""
|
||||
"\"idn-hostname\""
|
||||
"\"ipv4\""
|
||||
"\"ipv6\""
|
||||
"\"uuid\""
|
||||
"\"uri\""
|
||||
"\"uri-reference\""
|
||||
"\"iri\""
|
||||
"\"iri-reference\""
|
||||
"\"uri-template\""
|
||||
"\"json-pointer\""
|
||||
"\"relative-json-pointer\""
|
||||
"\"regex\""
|
||||
|
||||
# Numeric
|
||||
|
||||
"\"multipleOf\""
|
||||
"\"minimum\""
|
||||
"\"exclusiveMinimum\""
|
||||
"\"maximum\""
|
||||
"\"exclusiveMaximum\""
|
||||
|
||||
# Object
|
||||
|
||||
"\"properties\""
|
||||
"\"patternProperties\""
|
||||
"\"additionalProperties\""
|
||||
"\"unevaluatedProperties\""
|
||||
"\"required\""
|
||||
"\"propertyNames\""
|
||||
"\"minProperties\""
|
||||
"\"maxProperties\""
|
||||
"\"dependencies\""
|
||||
|
||||
# Array
|
||||
|
||||
"\"items\""
|
||||
"\"prefixItems\""
|
||||
"\"additionalItems\""
|
||||
"\"unevaluatedItems\""
|
||||
"\"contains\""
|
||||
"\"minContains\""
|
||||
"\"maxContains\""
|
||||
"\"minItems\""
|
||||
"\"maxItems\""
|
||||
"\"uniqueItems\""
|
||||
|
||||
# Booleans
|
||||
|
||||
"true"
|
||||
"false"
|
||||
|
||||
# Composition
|
||||
|
||||
"\"allOf\""
|
||||
"\"anyOf\""
|
||||
"\"oneOf\""
|
||||
"\"not\""
|
||||
|
||||
# Conditions
|
||||
|
||||
"\"dependentRequired\""
|
||||
"\"dependentSchemas\""
|
||||
"\"if\""
|
||||
"\"then\""
|
||||
"\"else\""
|
5713
dictionaries/ruby.dict
Normal file
5713
dictionaries/ruby.dict
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,107 @@
|
||||
This is the list of all noteworthy changes made in every public
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
|
||||
### Version ++4.31a (dev)
|
||||
- afl-fuzz:
|
||||
- Python 3.13+ support
|
||||
- loose file and shared memory permissions on Android and iPhone
|
||||
- splicing is now DISABLED by default because research showed
|
||||
it is counterproductive. New command line parameter `-u` to enable
|
||||
it. Splicing is auto-enabled if two cycles without finds happen.
|
||||
- afl-cc:
|
||||
- -fsanitize=fuzzer now inserts libAFLDriver.a addtionally early to help
|
||||
compiling if LLVMFuzzerTestOneOnput is in an .a archive
|
||||
- added __sanitizer_weak_hook_* functions (in case that is helpful in
|
||||
weird setups)
|
||||
- fix bug with large map sizes when multiple libraries are loaded after
|
||||
the shared memory was obtained.
|
||||
|
||||
|
||||
### Version ++4.30c (release)
|
||||
! afl-gcc and afl-clang funcionality is now removed !
|
||||
- afl-fuzz:
|
||||
- fastresume feature added. if you abort fuzzing and resume fuzzing
|
||||
with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed
|
||||
then a dump will be loaded and the calibration phase skipped.
|
||||
to disable this feature set `AFL_NO_FASTRESUME=1`
|
||||
zlib compression is used if zlib is found at compile time
|
||||
- improved seed selection algorithm
|
||||
- added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send()
|
||||
function after the target has been restarted.
|
||||
- because of bad math and undefined behaviour fixes we have to change
|
||||
the CMPLOG map. **YOU NEED TO RECOMPILE CMPLOG TARGETS**
|
||||
- fixed custom_post_process for calibration
|
||||
- fixes for AFL_EXIT_ON_TIME and AFL_EXIT_WHEN_DONE, changed behaviour of
|
||||
AFL_EXIT_WHEN_DONE to finish when really done :-)
|
||||
- frida_mode:
|
||||
- AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just
|
||||
a function entry
|
||||
- AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE
|
||||
- AFL_FRIDA_DEBUG_MAPS now works as expected
|
||||
- qemu_mode:
|
||||
- new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to
|
||||
@CowBoy4mH3LL
|
||||
- unicorn_mode:
|
||||
- fix install and forkserver (thanks aarnav!)
|
||||
- pin unicorn version
|
||||
- nyx_mode:
|
||||
- bugfixes
|
||||
- custom mutators:
|
||||
- custom_send_tcp custom mutator added, thanks to @dergoegge
|
||||
- afl-cc
|
||||
- fix to support pointless changes in LLVM 20
|
||||
- new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla
|
||||
AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with
|
||||
AFL_LLVM_INSTRUMENT=CLASSIC
|
||||
- new compile time variable: `AFL_OPT_LEVEL` to set a specific optimization
|
||||
level, default is `3`
|
||||
- correctly explain how to get the correct map size for large targets
|
||||
- small fix for weird LLVM defines in redhat
|
||||
- code formatting updated to llvm 18
|
||||
- improved custom_mutators/aflpp/standalone/aflpp-standalone
|
||||
- added custom_mutators/autotokens/standalone/autotokens-standalone
|
||||
- AFL++ headers are now installed to $PREFIX/include/afl
|
||||
|
||||
### Version ++4.21c (release)
|
||||
* afl-fuzz
|
||||
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
|
||||
do a switch from gettimeofday() to clock_gettime() which should be rather
|
||||
three times faster. The reason for this is unknown.
|
||||
- new queue selection algorithm based on 2 core years of queue data
|
||||
analysis. gives a noticable improvement on coverage although the results
|
||||
seem counterintuitive :-)
|
||||
- added AFL_DISABLE_REDUNDANT for huge queues
|
||||
- added `AFL_NO_SYNC` environment variable that does what you think it does
|
||||
- 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)
|
||||
- now timing of calibration, trimming and syncing is measured seperately,
|
||||
thanks to @eqv!
|
||||
- -V timing is now accurately the fuzz time (without syncing), before
|
||||
long calibration times and syncing could result in now fuzzing being
|
||||
made when the time was already run out until then, thanks to @eqv!
|
||||
- fix -n uninstrumented mode when ending fuzzing
|
||||
- enhanced the ASAN configuration
|
||||
- make afl-fuzz use less memory with cmplog and fix a memleak
|
||||
* afl-cc:
|
||||
- re-enable i386 support that was accidently disabled
|
||||
- fixes for LTO and outdated afl-gcc mode for i386
|
||||
- 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
|
||||
- compatability to new LLVM 19 changes
|
||||
* afl-cmin
|
||||
- work with input files that have a space
|
||||
* afl-showmap
|
||||
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
|
||||
- minor fix to collect coverage -C (thanks to @bet4it)
|
||||
* Fixed a shmem mmap bug (that rarely came up on MacOS)
|
||||
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
|
||||
|
||||
### 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
|
||||
@ -36,12 +137,13 @@
|
||||
- afl-whatsup:
|
||||
- now also displays current average speed
|
||||
- small bugfixes
|
||||
- Fixes for aflpp custom mutator and standalone tool
|
||||
- custom mutators:
|
||||
- fixes for aflpp custom mutator and standalone tool
|
||||
- important fix to the symcc custom mutator
|
||||
- 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)
|
||||
- afl-fuzz:
|
||||
- default power schedule is now EXPLORE, due a fix in fast schedules
|
||||
|
@ -30,6 +30,9 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso
|
||||
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang
|
||||
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
|
||||
sudo apt-get install -y ninja-build # for QEMU mode
|
||||
sudo apt-get install -y cpio libcapstone-dev # for Nyx mode
|
||||
sudo apt-get install -y wget curl # for Frida mode
|
||||
sudo apt-get install -y python3-pip # for Unicorn mode
|
||||
git clone https://github.com/AFLplusplus/AFLplusplus
|
||||
cd AFLplusplus
|
||||
make distrib
|
||||
@ -87,7 +90,6 @@ These build options exist:
|
||||
* PROFILING - compile afl-fuzz with profiling information
|
||||
* INTROSPECTION - compile afl-fuzz with mutation introspection
|
||||
* NO_PYTHON - disable python support
|
||||
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
|
||||
* NO_UTF - do not use UTF-8 for line rendering in status screen (fallback to G1 box drawing, of vanilla AFL)
|
||||
* NO_NYX - disable building nyx mode dependencies
|
||||
* NO_CORESIGHT - disable building coresight (arm64 only)
|
||||
|
@ -38,9 +38,8 @@ For PCGUARD instrumentation `abort()` is called if this is detected, for LTO
|
||||
there will either be no coverage for the instrumented dlopen()'ed libraries or
|
||||
you will see lots of crashes in the UI.
|
||||
|
||||
Note that this is not an issue if you use the inferiour `afl-gcc-fast`,
|
||||
`afl-gcc` or`AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast`
|
||||
instrumentation.
|
||||
Note that this is not an issue if you use the inferiour `afl-gcc-fast`, or
|
||||
`AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast` instrumentation.
|
||||
|
||||
### Fuzzing a binary-only target
|
||||
|
||||
|
@ -198,6 +198,11 @@ def deinit(): # optional for Python
|
||||
This method can be used if you want to send data to the target yourself,
|
||||
e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
|
||||
that you start the target with afl-fuzz.
|
||||
|
||||
Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
|
||||
function after the target has been restarted. (This is needed for e.g. TCP
|
||||
services.)
|
||||
|
||||
Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
|
||||
|
||||
- `queue_new_entry` (optional):
|
||||
@ -266,6 +271,11 @@ trimmed input. Here's a quick API description:
|
||||
Omitting any of three trimming methods will cause the trimming to be disabled
|
||||
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
|
||||
|
||||
Optionally, the following environment variables are supported:
|
||||
|
@ -24,7 +24,6 @@ To select the different instrumentation modes, use one of the following options:
|
||||
- Use the `AFL_CC_COMPILER` environment variable with `MODE`. To select
|
||||
`MODE`, use one of the following values:
|
||||
|
||||
- `GCC` (afl-gcc/afl-g++)
|
||||
- `GCC_PLUGIN` (afl-g*-fast)
|
||||
- `LLVM` (afl-clang-fast*)
|
||||
- `LTO` (afl-clang-lto*).
|
||||
@ -45,14 +44,10 @@ fairly broad use of environment variables instead:
|
||||
make
|
||||
```
|
||||
|
||||
- Setting `AFL_AS`, `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
|
||||
compilation tools, rather than the default 'as', 'clang', or 'gcc' binaries
|
||||
- Setting `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
|
||||
compilation tools, rather than the default 'clang', or 'gcc' binaries
|
||||
in your `$PATH`.
|
||||
|
||||
- If you are a weird person that wants to compile and instrument asm text
|
||||
files, then use the `AFL_AS_FORCE_INSTRUMENT` variable:
|
||||
`AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo`
|
||||
|
||||
- Most AFL tools do not print any output if stdout/stderr are redirected. If
|
||||
you want to get the output into a file, then set the `AFL_DEBUG` environment
|
||||
variable. This is sadly necessary for various build processes which fail
|
||||
@ -64,6 +59,9 @@ fairly broad use of environment variables instead:
|
||||
optimizations, set `AFL_DONT_OPTIMIZE`. However, if `-O...` and/or
|
||||
`-fno-unroll-loops` are set, these are not overridden.
|
||||
|
||||
- The optimization level can also be set with `AFL_OPT_LEVEL`, e.g.
|
||||
`AFL_OPT_LEVEL=z` for `-Oz`, default is `3`
|
||||
|
||||
- Setting `AFL_HARDEN` automatically adds code hardening options when invoking
|
||||
the downstream compiler. This currently includes `-D_FORTIFY_SOURCE=2` and
|
||||
`-fstack-protector-all`. The setting is useful for catching non-crashing
|
||||
@ -80,17 +78,13 @@ fairly broad use of environment variables instead:
|
||||
Setting `AFL_INST_RATIO` to 0 is a valid choice. This will instrument only
|
||||
the transitions between function entry points, but not individual branches.
|
||||
|
||||
Note that this is an outdated variable. A few instances (e.g., afl-gcc)
|
||||
still support these, but state-of-the-art (e.g., LLVM LTO and LLVM PCGUARD)
|
||||
do not need this.
|
||||
Note that this is an outdated variable. Only LLVM CLASSIC pass can use this.
|
||||
|
||||
- `AFL_NO_BUILTIN` causes the compiler to generate code suitable for use with
|
||||
libtokencap.so (but perhaps running a bit slower than without the flag).
|
||||
|
||||
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
|
||||
One possible use of this is utils/clang_asm_normalize/, which lets you
|
||||
instrument hand-written assembly when compiling clang code by plugging a
|
||||
normalizer into the chain. (There is no equivalent feature for GCC.)
|
||||
- `AFL_PATH` can be used to point a directory that contains LLVM/GCC plugins
|
||||
for AFL++, AFL++'s runtime objects and QEMU/Frida support files.
|
||||
|
||||
- Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being
|
||||
displayed during compilation, in case you find them distracting.
|
||||
@ -101,6 +95,7 @@ fairly broad use of environment variables instead:
|
||||
detection)
|
||||
- `AFL_USE_CFISAN=1` - activates the Control Flow Integrity sanitizer (e.g.
|
||||
type confusion vulnerabilities)
|
||||
- `AFL_CFISAN_VERBOSE=1` - outputs detailed information when control flow integrity violations occur, instead of simply terminating with "Illegal Instruction"
|
||||
- `AFL_USE_LSAN` - activates the leak sanitizer. To perform a leak check
|
||||
within your program at a certain point (such as at the end of an
|
||||
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
|
||||
@ -111,6 +106,9 @@ fairly broad use of environment variables instead:
|
||||
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
|
||||
conditions
|
||||
- `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer
|
||||
- `AFL_UBSAN_VERBOSE=1` - outputs detailed diagnostic information when undefined behavior is detected, instead of simply terminating with "Illegal Instruction"
|
||||
|
||||
- Note: both `AFL_CFISAN_VERBOSE=1` and `AFL_UBSAN_VERBOSE=1` are disabled by default as verbose output can significantly slow down fuzzing performance. Use these options only during debugging or when additional crash diagnostics are required
|
||||
|
||||
- `TMPDIR` is used by afl-as for temporary files; if this variable is not set,
|
||||
the tool defaults to /tmp.
|
||||
@ -323,6 +321,11 @@ mode.
|
||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||
for more information.
|
||||
|
||||
Setting `AFL_GCC_DISABLE_VERSION_CHECK=1` will disable the GCC plugin
|
||||
version check if the target GCC plugin differs from the system-installed
|
||||
version, resolving issues caused by version mismatches between GCC and
|
||||
the plugin.
|
||||
|
||||
Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the
|
||||
code with calls to an injected subroutine instead of the much more efficient
|
||||
inline instrumentation.
|
||||
@ -331,7 +334,26 @@ mode.
|
||||
the target performs only a few loops, then this will give a small
|
||||
performance boost.
|
||||
|
||||
## 4) Settings for afl-fuzz
|
||||
## 4) Runtime settings
|
||||
|
||||
The following environment variables are for a compiled AFL++ target.
|
||||
|
||||
- Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will
|
||||
dump the map size of the target and exit.
|
||||
|
||||
- Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver.
|
||||
This makes only sense when you
|
||||
a) compile in a classic colliding coverage mode (e.g.
|
||||
AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is
|
||||
below MAP_SIZE (65536 by default), AND
|
||||
b) you want to use this compiled AFL++ target with a different tool
|
||||
that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc.
|
||||
You would use this option together with the target fuzzing application.
|
||||
|
||||
- Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting
|
||||
instrumentation. (More of an internal option.)
|
||||
|
||||
## 5) Settings for afl-fuzz
|
||||
|
||||
The main fuzzer binary accepts several options that disable a couple of sanity
|
||||
checks or alter some of the more exotic semantics of the tool:
|
||||
@ -368,6 +390,10 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
XML or other highly flexible structured input. For details, see
|
||||
[custom_mutators.md](custom_mutators.md).
|
||||
|
||||
- Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
|
||||
function after the target has been restarted. (This is needed for e.g. TCP
|
||||
services.)
|
||||
|
||||
- Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time
|
||||
a cycle is finished.
|
||||
|
||||
@ -381,6 +407,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
|
||||
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
|
||||
new coverage
|
||||
|
||||
@ -398,9 +427,8 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
types of automated jobs.
|
||||
|
||||
- `AFL_EXIT_WHEN_DONE` causes afl-fuzz to terminate when all existing paths
|
||||
have been fuzzed and there were no new finds for a while. This would be
|
||||
normally indicated by the cycle counter in the UI turning green. May be
|
||||
convenient for some types of automated jobs.
|
||||
have been fuzzed and there were no new finds for a while. This is basically
|
||||
when the fuzzing state says `state: finished`
|
||||
|
||||
- Setting `AFL_EXPAND_HAVOC_NOW` will start in the extended havoc mode that
|
||||
includes costly mutations. afl-fuzz automatically enables this mode when
|
||||
@ -511,6 +539,8 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
|
||||
the snapshot lkm is loaded.
|
||||
|
||||
- `AFL_NO_FASTRESUME` will not try to read or write a fast resume file.
|
||||
|
||||
- Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints
|
||||
some basic stats. This behavior is also automatically triggered when the
|
||||
output from afl-fuzz is redirected to a file or to a pipe.
|
||||
@ -547,6 +577,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
|
||||
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
|
||||
by some users for unorthodox parallelized fuzzing setups, but not advisable
|
||||
otherwise.
|
||||
@ -579,9 +612,12 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
see [rpc_statsd.md](rpc_statsd.md).
|
||||
|
||||
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes)
|
||||
between fuzzing instances synchronization. Default sync time is 30 minutes,
|
||||
between fuzzing instances synchronization. Default sync time is 20 minutes,
|
||||
note that time is halved for -M main nodes.
|
||||
|
||||
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
|
||||
other syncing parameters.
|
||||
|
||||
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
|
||||
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
|
||||
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
|
||||
@ -627,7 +663,7 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
Note that will not be exact and with slow targets it can take seconds
|
||||
until there is a slice for the time test.
|
||||
|
||||
## 5) Settings for afl-qemu-trace
|
||||
## 6) Settings for afl-qemu-trace
|
||||
|
||||
The QEMU wrapper used to instrument binary-only code supports several settings:
|
||||
|
||||
@ -699,7 +735,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
|
||||
crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when
|
||||
counting crashes based on a file count in that directory.
|
||||
|
||||
## 7) Settings for afl-frida-trace
|
||||
## 8) Settings for afl-frida-trace
|
||||
|
||||
The FRIDA wrapper used to instrument binary-only code supports many of the same
|
||||
options as `afl-qemu-trace`, but also has a number of additional advanced
|
||||
@ -789,7 +825,7 @@ support.
|
||||
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
||||
killing the process whilst it is being dumped.
|
||||
|
||||
## 8) Settings for afl-cmin
|
||||
## 9) Settings for afl-cmin
|
||||
|
||||
The corpus minimization script offers very little customization:
|
||||
|
||||
@ -807,7 +843,7 @@ The corpus minimization script offers very little customization:
|
||||
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed.
|
||||
This can help when embedding `afl-cmin` or `afl-showmap` in other scripts.
|
||||
|
||||
## 9) Settings for afl-tmin
|
||||
## 10) Settings for afl-tmin
|
||||
|
||||
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be
|
||||
searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a
|
||||
@ -818,12 +854,12 @@ to match when minimizing crashes. This will make minimization less useful, but
|
||||
may prevent the tool from "jumping" from one crashing condition to another in
|
||||
very buggy software. You probably want to combine it with the `-e` flag.
|
||||
|
||||
## 10) Settings for afl-analyze
|
||||
## 11) Settings for afl-analyze
|
||||
|
||||
You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
|
||||
of decimal.
|
||||
|
||||
## 11) Settings for libdislocator
|
||||
## 12) Settings for libdislocator
|
||||
|
||||
The library honors these environment variables:
|
||||
|
||||
@ -845,12 +881,12 @@ The library honors these environment variables:
|
||||
- `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that
|
||||
may be useful for pinpointing the cause of any observed issues.
|
||||
|
||||
## 11) Settings for libtokencap
|
||||
## 13) Settings for libtokencap
|
||||
|
||||
This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
|
||||
discovered tokens should be written.
|
||||
|
||||
## 12) Third-party variables set by afl-fuzz & other tools
|
||||
## 14) Third-party variables set by afl-fuzz & other tools
|
||||
|
||||
Several variables are not directly interpreted by afl-fuzz, but are set to
|
||||
optimal values if not already present in the environment:
|
||||
|
@ -6,20 +6,22 @@ QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
||||
|
||||
## Features and instrumentation
|
||||
|
||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||
| Threadsafe counters [A] | | x(3) | | | | | x | |
|
||||
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | |
|
||||
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
|
||||
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
|
||||
| CmpLog [E] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
|
||||
| Selective Instrumentation [F] | | x | x | x | x | | | |
|
||||
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | |
|
||||
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | |
|
||||
| Context Coverage [I] | | x(6) | | | | | | |
|
||||
| Auto Dictionary [J] | | x(7) | | | | | | |
|
||||
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | |
|
||||
Note that afl-gcc and afl-clang have been removed because their instrumentation is absolutely outdated.
|
||||
|
||||
| Feature/Instrumentation | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||
| ------------------------------|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||
| Threadsafe counters [A] | x(3) | | | | | x | |
|
||||
| NeverZero [B] | x(1) | x | x | x | x | | |
|
||||
| Persistent Mode [C] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
|
||||
| LAF-Intel / CompCov [D] | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
|
||||
| CmpLog [E] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
|
||||
| Selective Instrumentation [F] | x | x | x | x | | | |
|
||||
| Non-Colliding Coverage [G] | x(4) | | | (x)(5) | | | |
|
||||
| Ngram prev_loc Coverage [H] | x(6) | | | | | | |
|
||||
| Context Coverage [I] | x(6) | | | | | | |
|
||||
| Auto Dictionary [J] | x(7) | | | | | | |
|
||||
| Snapshot Support [K] | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||
| Shared Memory Test cases [L] | x | x | x86[_64]/arm64 | x | x | x | |
|
||||
|
||||
## More information about features
|
||||
|
||||
@ -94,7 +96,7 @@ L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase
|
||||
|
||||
Among others, the following features and patches have been integrated:
|
||||
|
||||
* NeverZero patch for afl-gcc, instrumentation, QEMU mode and unicorn_mode which
|
||||
* NeverZero for llvm/gcc instrumentation, QEMU mode and unicorn_mode which
|
||||
prevents a wrapping map value to zero, increases coverage
|
||||
* Persistent mode, deferred forkserver and in-memory fuzzing for QEMU mode
|
||||
* Unicorn mode which allows fuzzing of binaries from completely different
|
||||
|
@ -46,10 +46,9 @@ The following setup to use QEMU mode is recommended:
|
||||
`AFL_COMPCOV_LEVEL=2`), alternatively you can use FRIDA mode, just switch `-Q`
|
||||
with `-O` and remove the LAF instance
|
||||
|
||||
Then run as many instances as you have cores left with either -Q mode or - even
|
||||
better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
|
||||
The binary rewriters all have their own advantages and caveats.
|
||||
ZAFL is the best but cannot be used in a business/commercial context.
|
||||
Then run as many instances as you have cores left with either `-Q` mode or use
|
||||
a static binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
|
||||
The binary rewriters all have their own advantages and caveats, but ZAFL is a good choice.
|
||||
|
||||
If a binary rewriter works for your target then you can use afl-fuzz normally
|
||||
and it will have twice the speed compared to QEMU mode (but slower than QEMU
|
||||
@ -200,6 +199,7 @@ have an x86_64 or arm64 binary that does not contain C++ exceptions and - if
|
||||
x86_64 - still has it's symbols and compiled with position independent code
|
||||
(PIC/PIE), then the RetroWrite solution might be for you.
|
||||
It decompiles to ASM files which can then be instrumented with afl-gcc.
|
||||
Note that afl-gcc is only present until AFL++ v4.21c and was subsequently removed as it is obsolete.
|
||||
|
||||
Binaries that are statically instrumented for fuzzing using RetroWrite are close
|
||||
in performance to compiler-instrumented binaries and outperform the QEMU-based
|
||||
|
@ -61,6 +61,8 @@ evaluation flow will help you to select the best possible.
|
||||
It is highly recommended to have the newest llvm version possible installed,
|
||||
anything below 9 is not recommended.
|
||||
|
||||
IMPORTANT NOTICE: afl-gcc/afl-clang have been removed from AFL++ as they are obsolete.
|
||||
|
||||
```
|
||||
+--------------------------------+
|
||||
| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
|
||||
@ -84,7 +86,7 @@ anything below 9 is not recommended.
|
||||
| if not, or if you do not have a gcc with plugin support
|
||||
|
|
||||
v
|
||||
use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)
|
||||
GAME OVER! Install gcc-VERSION-plugin-dev or llvm-VERSION-dev
|
||||
```
|
||||
|
||||
Clickable README links for the chosen compiler:
|
||||
@ -92,14 +94,12 @@ Clickable README links for the chosen compiler:
|
||||
* [LTO mode - afl-clang-lto](../instrumentation/README.lto.md)
|
||||
* [LLVM mode - afl-clang-fast](../instrumentation/README.llvm.md)
|
||||
* [GCC_PLUGIN mode - afl-gcc-fast](../instrumentation/README.gcc_plugin.md)
|
||||
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
|
||||
features
|
||||
|
||||
You can select the mode for the afl-cc compiler by one of the following methods:
|
||||
|
||||
* Using a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||
* Using a symlink to afl-cc:
|
||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||
afl-gcc-fast, afl-g++-fast (recommended!).
|
||||
afl-gcc-fast, afl-g++-fast.
|
||||
* Using the environment variable `AFL_CC_COMPILER` with `MODE`.
|
||||
* Passing --afl-`MODE` command line options to the compiler via
|
||||
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`.
|
||||
@ -108,8 +108,7 @@ You can select the mode for the afl-cc compiler by one of the following methods:
|
||||
|
||||
* LTO (afl-clang-lto*)
|
||||
* LLVM (afl-clang-fast*)
|
||||
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++)
|
||||
* CLANG(afl-clang/afl-clang++)
|
||||
* GCC_PLUGIN (afl-g*-fast)
|
||||
|
||||
Because no AFL++ specific command-line options are accepted (beside the
|
||||
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
||||
@ -201,6 +200,9 @@ type. This is enough because e.g. a use-after-free bug will be picked up by ASAN
|
||||
(address sanitizer) anyway after syncing test cases from other fuzzing
|
||||
instances, so running more than one address sanitized target would be a waste.
|
||||
|
||||
*IF* you are running a saturated corpus, then you can run up to half of the
|
||||
instances with sanitizers.
|
||||
|
||||
The following sanitizers have built-in support in AFL++:
|
||||
|
||||
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
|
||||
@ -632,7 +634,7 @@ crash or timeout during startup.
|
||||
|
||||
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
|
||||
from other fuzzers in the campaign first. But note that can slow down the start
|
||||
of the first fuzz by quite a lot of you have many fuzzers and/or many seeds.
|
||||
of the first fuzz by quite a lot if you have many fuzzers and/or many seeds.
|
||||
|
||||
If you have a large corpus, a corpus from a previous run or are fuzzing in a CI,
|
||||
then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.
|
||||
|
@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE
|
||||
arm:
|
||||
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all
|
||||
|
||||
arm64:
|
||||
ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
|
@ -6,34 +6,39 @@
|
||||
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
UNUSED_PARAMETER (size);
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
|
||||
ElfW(Addr) * base = data;
|
||||
UNUSED_PARAMETER(size);
|
||||
|
||||
ElfW(Addr) *base = data;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv, char** envp) {
|
||||
UNUSED_PARAMETER (argc);
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
|
||||
ElfW(Addr) base = 0;
|
||||
UNUSED_PARAMETER(argc);
|
||||
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
ElfW(Addr) base = 0;
|
||||
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
}
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
}
|
||||
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
js_api_set_stdout;
|
||||
js_api_set_traceable;
|
||||
js_api_set_verbose;
|
||||
js_api_ijon_set;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
|
||||
// do a length check matching the target!
|
||||
|
||||
void **esp = (void **)regs->esp;
|
||||
void *arg1 = esp[0];
|
||||
void **arg2 = &esp[1];
|
||||
void *arg1 = esp[1];
|
||||
void **arg2 = &esp[2];
|
||||
memcpy(arg1, input_buf, input_buf_len);
|
||||
*arg2 = (void *)input_buf_len;
|
||||
|
||||
|
@ -36,7 +36,7 @@ struct x86_64_regs {
|
||||
void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
memcpy((void *)regs->rdi, input_buf, input_buf_len);
|
||||
regs->rsi = input_buf_len;
|
||||
|
||||
@ -76,14 +76,15 @@ struct x86_regs {
|
||||
void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
void **esp = (void **)regs->esp;
|
||||
void * arg1 = esp[1];
|
||||
void *arg1 = esp[1];
|
||||
void **arg2 = &esp[2];
|
||||
memcpy(arg1, input_buf, input_buf_len);
|
||||
*arg2 = (void *)input_buf_len;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
struct arm64_regs {
|
||||
@ -177,9 +178,10 @@ struct arm64_regs {
|
||||
void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
memcpy((void *)regs->x0, input_buf, input_buf_len);
|
||||
regs->x1 = input_buf_len;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) {
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed;
|
||||
|
||||
extern uint8_t *__afl_area_ptr;
|
||||
extern uint32_t __afl_map_size;
|
||||
extern void __afl_coverage_interesting(uint8_t, uint32_t);
|
||||
|
||||
extern __thread guint64 *instrument_previous_pc_addr;
|
||||
|
||||
@ -72,5 +73,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
|
||||
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data);
|
||||
void instrument_regs_format(int fd, char *format, ...);
|
||||
|
||||
void ijon_set(uint32_t edge);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -39,18 +39,18 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
||||
|
||||
address = base + index + mem->disp;
|
||||
|
||||
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
|
||||
|
||||
asan_loadN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) {
|
||||
|
||||
asan_storeN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
|
||||
|
||||
asan_loadN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
|
||||
|
@ -449,3 +449,9 @@ void instrument_regs_format(int fd, char *format, ...) {
|
||||
|
||||
}
|
||||
|
||||
void ijon_set(uint32_t edge) {
|
||||
|
||||
__afl_coverage_interesting(1, edge);
|
||||
|
||||
}
|
||||
|
||||
|
@ -818,6 +818,9 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
|
||||
GDir *dir = g_dir_open(fds_name, 0, NULL);
|
||||
|
||||
gchar *path_tmp = getenv("AFL_CUSTOM_INFO_OUT");
|
||||
gchar *instance_name = g_path_get_basename(path_tmp);
|
||||
|
||||
FVERBOSE("Coverage Unstable - fds: %s", fds_name);
|
||||
|
||||
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
|
||||
@ -829,7 +832,7 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
if (link == NULL) { FFATAL("Failed to read link: %s", fullname); }
|
||||
|
||||
gchar *basename = g_path_get_basename(link);
|
||||
if (g_strcmp0(basename, "default") != 0) {
|
||||
if (g_strcmp0(basename, instance_name) != 0) {
|
||||
|
||||
g_free(basename);
|
||||
g_free(link);
|
||||
@ -874,6 +877,7 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
g_free(instance_name);
|
||||
g_free(fds_name);
|
||||
|
||||
if (unstable_coverage_fuzzer_stats == NULL) {
|
||||
|
@ -49,14 +49,23 @@ void instrument_cache_init(void) {
|
||||
|
||||
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
|
||||
|
||||
FFATAL("Failed to setrlimit: %d", errno);
|
||||
FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
|
||||
errno);
|
||||
|
||||
}
|
||||
|
||||
map_base =
|
||||
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
|
||||
GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
|
||||
if (map_base == MAP_FAILED) {
|
||||
|
||||
FFATAL(
|
||||
"Failed to map segment: %d. This can be caused by failure to setrlimit."
|
||||
"Disabling or reducing the size of the allocation using "
|
||||
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
|
||||
errno);
|
||||
|
||||
}
|
||||
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
|
||||
GUM_ADDRESS(map_base));
|
||||
|
@ -326,6 +326,12 @@ class Afl {
|
||||
static jsApiGetSymbol(name) {
|
||||
return Afl.module.getExportByName(name);
|
||||
}
|
||||
|
||||
static IJON = class {
|
||||
static set(addr, val) {
|
||||
Afl.jsApiIjonSet((addr ^ val) & 0xffffffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode
|
||||
@ -377,3 +383,4 @@ Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
|
||||
Afl.jsApiWrite = new NativeFunction(
|
||||
/* tslint:disable-next-line:no-null-keyword */
|
||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||
Afl.jsApiIjonSet = Afl.jsApiGetFunction("js_api_ijon_set", "void", ["uint32"]);
|
||||
|
@ -316,3 +316,9 @@ __attribute__((visibility("default"))) void js_api_set_verbose(void) {
|
||||
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void js_api_ijon_set(uint32_t edge) {
|
||||
|
||||
ijon_set(edge);
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
// r15 - pc
|
||||
|
||||
static GumCpuContext saved_regs = {0};
|
||||
static gpointer saved_lr = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumArmWriter *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0);
|
||||
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
|
||||
GUM_ARG_REGISTER, ARM_REG_R0);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
|
||||
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
|
||||
GUM_RED_ZONE_SIZE);
|
||||
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0);
|
||||
|
||||
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
|
||||
@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumArmWriter *cw = output->writer.arm;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_arm_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0);
|
||||
gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_arm_writer_put_bl_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_arm_writer_put_b_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_arm_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_arm_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_lr(cw);
|
||||
|
||||
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
|
||||
|
||||
@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
|
||||
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
|
||||
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
|
||||
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);
|
||||
|
||||
|
@ -16,7 +16,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
static gpointer saved_lr = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumArm64Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
|
||||
gum_arm64_writer_put_call_address_with_arguments(
|
||||
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
|
||||
GUM_INDEX_PRE_ADJUST);
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
|
||||
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
|
||||
|
||||
@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumArm64Writer *cw = output->writer.arm64;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_arm64_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm64_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
|
||||
gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_arm64_writer_put_bl_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_arm64_writer_put_b_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_arm64_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_arm64_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_lr(cw);
|
||||
|
||||
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
|
||||
|
||||
@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0);
|
||||
|
||||
|
@ -17,7 +17,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
static gpointer saved_ret = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit));
|
||||
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
|
||||
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
|
||||
-(GUM_RED_ZONE_SIZE));
|
||||
gum_x86_writer_put_call_address_with_arguments(
|
||||
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
|
||||
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
|
||||
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
|
||||
(GUM_RED_ZONE_SIZE));
|
||||
@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
|
||||
offset);
|
||||
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
|
||||
@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumX86Writer *cw = output->writer.x86;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
|
||||
/*
|
||||
* If we haven't set persistent_ret, then assume that we are dealing with a
|
||||
* function and we should loop when that function returns.
|
||||
*/
|
||||
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_x86_writer_put_call_near_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_x86_writer_put_jmp_near_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_x86_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_x86_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_ret(cw);
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
/* The original instrumented code is emitted here. */
|
||||
|
||||
}
|
||||
|
||||
void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
|
||||
gum_x86_writer_put_label(cw, zero);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
|
||||
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
|
||||
static gpointer saved_ret = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit));
|
||||
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EDI);
|
||||
gum_x86_writer_put_call_reg(cw, GUM_X86_EAX);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
|
||||
|
||||
gum_x86_writer_put_call_address_with_arguments(
|
||||
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
|
||||
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
|
||||
|
||||
}
|
||||
|
||||
@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
|
||||
offset);
|
||||
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
|
||||
@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumX86Writer *cw = output->writer.x86;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
|
||||
/*
|
||||
* If we haven't set persistent_ret, then assume that we are dealing with a
|
||||
* function and we should loop when that function returns.
|
||||
*/
|
||||
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
gum_x86_writer_put_call_near_label(cw, original);
|
||||
/* jmp loop */
|
||||
gum_x86_writer_put_jmp_near_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_x86_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_x86_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_ret(cw);
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
/* The original instrumented code is emitted here. */
|
||||
|
||||
}
|
||||
|
||||
void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
|
||||
/* The stack should be aligned when we re-enter our loop */
|
||||
gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0);
|
||||
gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
|
||||
|
||||
}
|
||||
|
@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
|
||||
|
||||
if (details->file == NULL) {
|
||||
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
|
||||
} else {
|
||||
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
|
||||
details->file->path, details->file->offset);
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
|
||||
details->file->offset);
|
||||
|
||||
}
|
||||
|
||||
@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) {
|
||||
|
||||
void ranges_print_debug_maps(void) {
|
||||
|
||||
FVERBOSE("Maps");
|
||||
OKF("Maps");
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
|
||||
|
||||
}
|
||||
|
@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) {
|
||||
if (!initialized) {
|
||||
|
||||
initialized = TRUE;
|
||||
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
|
||||
if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) {
|
||||
|
||||
util_verbose = TRUE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
69
frida_mode/test/cache/cache.c
vendored
69
frida_mode/test/cache/cache.c
vendored
@ -6,46 +6,45 @@
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len);
|
||||
|
||||
__asm__ (
|
||||
"LLVMFuzzerTestOneInput:\n"
|
||||
".func LLVMFuzzerTestOneInput\n"
|
||||
".global LLVMFuzzerTestOneInput\n"
|
||||
" jmpq *jmp_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"call_target:\n"
|
||||
" ret\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"jmp_target:\n"
|
||||
" callq *call_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" leaq rax_offset(%rip), %rax\n"
|
||||
" jmp (%rax)\n"
|
||||
" nop\n"
|
||||
" ud2\n"
|
||||
" nop\n"
|
||||
"rax_target:\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
"\n"
|
||||
".global jmp_offset\n"
|
||||
".p2align 3\n"
|
||||
"jmp_offset:\n"
|
||||
" .quad jmp_target\n"
|
||||
"call_offset:\n"
|
||||
" .quad call_target\n"
|
||||
"rax_offset:\n"
|
||||
" .quad rax_target\n"
|
||||
);
|
||||
__asm__(
|
||||
"LLVMFuzzerTestOneInput:\n"
|
||||
".func LLVMFuzzerTestOneInput\n"
|
||||
".global LLVMFuzzerTestOneInput\n"
|
||||
" jmpq *jmp_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"call_target:\n"
|
||||
" ret\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"jmp_target:\n"
|
||||
" callq *call_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" leaq rax_offset(%rip), %rax\n"
|
||||
" jmp (%rax)\n"
|
||||
" nop\n"
|
||||
" ud2\n"
|
||||
" nop\n"
|
||||
"rax_target:\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
"\n"
|
||||
".global jmp_offset\n"
|
||||
".p2align 3\n"
|
||||
"jmp_offset:\n"
|
||||
" .quad jmp_target\n"
|
||||
"call_offset:\n"
|
||||
" .quad call_target\n"
|
||||
"rax_offset:\n"
|
||||
" .quad rax_target\n");
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
static bool cmov_test(char *x, char *y, size_t len) {
|
||||
|
||||
register char * __rdi __asm__("rdi") = x;
|
||||
register char * __rsi __asm__("rsi") = y;
|
||||
register char *__rdi __asm__("rdi") = x;
|
||||
register char *__rsi __asm__("rsi") = y;
|
||||
register size_t __rcx __asm__("rcx") = len;
|
||||
|
||||
register long __rax __asm__("rax");
|
||||
@ -49,10 +49,10 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -41,7 +41,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
@ -51,6 +51,7 @@ int run(char *file) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
||||
perror("open");
|
||||
break;
|
||||
|
||||
@ -110,8 +111,10 @@ void slow() {
|
||||
|
||||
}
|
||||
|
||||
TESTINSTR_SECTION int do_run(char * file) {
|
||||
TESTINSTR_SECTION int do_run(char *file) {
|
||||
|
||||
return run(file);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -19,32 +19,40 @@
|
||||
typedef void (*fntestinstrlib)(char *buf, int len);
|
||||
|
||||
void testinstr(char *buf, int len) {
|
||||
|
||||
void *lib = dlopen("testinstrlib.so", RTLD_NOW);
|
||||
if (lib == NULL) {
|
||||
|
||||
puts("Library not found");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
fntestinstrlib fn = (fntestinstrlib)(dlsym(lib, "testinstrlib"));
|
||||
if (fn == NULL) {
|
||||
|
||||
puts("Function not found");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
fn(buf, len);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char * file;
|
||||
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
if (argc != 2) { return 1; }
|
||||
|
||||
do {
|
||||
|
||||
file = argv[1];
|
||||
printf("file: %s\n", file);
|
||||
|
||||
@ -52,33 +60,43 @@ int main(int argc, char **argv) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
||||
perror("open");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
len = lseek(fd, 0, SEEK_END);
|
||||
if (len < 0) {
|
||||
|
||||
perror("lseek (SEEK_END)");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) != 0) {
|
||||
|
||||
perror("lseek (SEEK_SET)");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
printf("len: %ld\n", len);
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
|
||||
perror("malloc");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
n_read = read(fd, buf, len);
|
||||
if (n_read != len) {
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read);
|
||||
@ -95,4 +113,6 @@ int main(int argc, char **argv) {
|
||||
if (fd != -1) { close(fd); }
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void testinstrlib(char *buf, int len) {
|
||||
|
||||
if (len < 1) return;
|
||||
buf[len] = 0;
|
||||
|
||||
@ -11,4 +12,6 @@ void testinstrlib(char *buf, int len) {
|
||||
printf("Pretty sure that is a one!\n");
|
||||
else
|
||||
printf("Neither one or zero? How quaint!\n");
|
||||
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -35,7 +35,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -22,60 +22,60 @@
|
||||
#define IGNORED_RETURN(x) (void)!(x)
|
||||
|
||||
const uint32_t crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t
|
||||
crc32(const void *buf, size_t size)
|
||||
{
|
||||
const uint8_t *p = buf;
|
||||
uint32_t crc;
|
||||
crc = ~0U;
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
return crc ^ ~0U;
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
|
||||
uint32_t crc32(const void *buf, size_t size) {
|
||||
|
||||
const uint8_t *p = buf;
|
||||
uint32_t crc;
|
||||
crc = ~0U;
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
return crc ^ ~0U;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -83,11 +83,13 @@ crc32(const void *buf, size_t size)
|
||||
* FRIDA to patch this function out and always return success. Otherwise, we
|
||||
* could change it to actually correct the checksum.
|
||||
*/
|
||||
int crc32_check (char * buf, int len) {
|
||||
int crc32_check(char *buf, int len) {
|
||||
|
||||
if (len < sizeof(uint32_t)) { return 0; }
|
||||
uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)];
|
||||
uint32_t calculated = crc32(buf, len - sizeof(uint32_t));
|
||||
return expected == calculated;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -97,27 +99,31 @@ int crc32_check (char * buf, int len) {
|
||||
* cloud your output unnecessarily. Again, we can use FRIDA to patch it out.
|
||||
*/
|
||||
void some_boring_bug(char c) {
|
||||
|
||||
switch (c) {
|
||||
case 'A'...'Z':
|
||||
case 'a'...'z':
|
||||
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z':
|
||||
__builtin_trap();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern void some_boring_bug2(char c);
|
||||
|
||||
__asm__ (
|
||||
".text \n"
|
||||
"some_boring_bug2: \n"
|
||||
".global some_boring_bug2 \n"
|
||||
".type some_boring_bug2, @function \n"
|
||||
"mov %edi, %eax \n"
|
||||
"cmp $0xb4, %al \n"
|
||||
"jne ok \n"
|
||||
"ud2 \n"
|
||||
"ok: \n"
|
||||
"ret \n");
|
||||
__asm__(
|
||||
".text \n"
|
||||
"some_boring_bug2: \n"
|
||||
".global some_boring_bug2 \n"
|
||||
".type some_boring_bug2, @function \n"
|
||||
"mov %edi, %eax \n"
|
||||
"cmp $0xb4, %al \n"
|
||||
"jne ok \n"
|
||||
"ud2 \n"
|
||||
"ok: \n"
|
||||
"ret \n");
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
some_boring_bug2(buf[0]);
|
||||
|
||||
if (buf[0] == '0') {
|
||||
|
||||
printf("Looks like a zero to me!\n");
|
||||
}
|
||||
else if (buf[0] == '1') {
|
||||
|
||||
} else if (buf[0] == '1') {
|
||||
|
||||
printf("Pretty sure that is a one!\n");
|
||||
}
|
||||
else if (buf[0] == '2') {
|
||||
|
||||
} else if (buf[0] == '2') {
|
||||
|
||||
printf("Oh we, weren't expecting that!");
|
||||
__builtin_trap();
|
||||
}
|
||||
else
|
||||
|
||||
} else
|
||||
|
||||
printf("Neither one or zero? How quaint!\n");
|
||||
|
||||
}
|
||||
@ -145,7 +155,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
@ -173,5 +183,6 @@ int main(int argc, char **argv) {
|
||||
printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,66 +4,68 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
//typedef for our exported target function.
|
||||
// typedef for our exported target function.
|
||||
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
|
||||
|
||||
//globals
|
||||
// globals
|
||||
CRASHME fpn_crashme = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
}
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,66 +4,68 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
//typedef for our exported target function.
|
||||
// typedef for our exported target function.
|
||||
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
|
||||
|
||||
//globals
|
||||
// globals
|
||||
CRASHME fpn_crashme = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
}
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,37 +4,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
extern void crashme(const uint8_t *Data, size_t Size);
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
crashme(data, size);
|
||||
return 0;
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
crashme(data, size);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void run (int argc, const char * argv[])
|
||||
{
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
void run(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
run(argc, argv);
|
||||
run(argc, argv);
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 5) return;
|
||||
@ -13,5 +12,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
if (Data[3] == '$')
|
||||
if (Data[4] == '$') abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 1) return;
|
||||
@ -56,6 +55,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -20,22 +20,32 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
int ret = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
switch(buf[i]) {
|
||||
case 'A': ret += 2; break;
|
||||
case '1': ret += 3; break;
|
||||
default: ret++;
|
||||
|
||||
switch (buf[i]) {
|
||||
|
||||
case 'A':
|
||||
ret += 2;
|
||||
break;
|
||||
case '1':
|
||||
ret += 3;
|
||||
break;
|
||||
default:
|
||||
ret++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("ret: %d\n", ret);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
printf (">>> LLVMFuzzerTestOneInput >>>\n");
|
||||
printf(">>> LLVMFuzzerTestOneInput >>>\n");
|
||||
if (len < 1) return;
|
||||
buf[len] = 0;
|
||||
|
||||
@ -40,10 +40,10 @@ void slow() {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -48,7 +48,7 @@ all: $(TEST_BIN)
|
||||
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
|
||||
|
||||
arm:
|
||||
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN)
|
||||
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
|
||||
cd $(LIBZ_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
./configure \
|
||||
--static \
|
||||
--archs="$(ARCH)"
|
||||
--static
|
||||
|
||||
$(LIBZ_LIB): | $(LIBZ_PC)
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
|
||||
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
|
||||
LDFLAGS="-L$(LIBZ_DIR)" \
|
||||
./configure \
|
||||
--host="$(ARCH)"
|
||||
--host="$(PNG_ARCH)"
|
||||
|
||||
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
|
||||
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define TESTINSTR_SECTION __attribute__((section(".testinstr")))
|
||||
#endif
|
||||
|
||||
void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
void LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
if (size < 1) return;
|
||||
|
||||
@ -30,9 +30,13 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (gettimeofday(&tv, NULL) < 0) return;
|
||||
|
||||
if ((tv.tv_usec % 2) == 0) {
|
||||
printf ("Hooray all even\n");
|
||||
|
||||
printf("Hooray all even\n");
|
||||
|
||||
} else {
|
||||
printf ("Hmm that's odd\n");
|
||||
|
||||
printf("Hmm that's odd\n");
|
||||
|
||||
}
|
||||
|
||||
// we support three input cases
|
||||
@ -45,26 +49,33 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
}
|
||||
|
||||
void run_test(char * file) {
|
||||
void run_test(char *file) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", file);
|
||||
FILE *f = fopen(file, "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", file, n_read);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
srand(1);
|
||||
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
run_test(argv[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,5 +9,11 @@ echo Newest available version: $NEW
|
||||
|
||||
test -z "$OLD" -o -z "$NEW" -o "$OLD" = "$NEW" && { echo Nothing to be done. ; exit 0 ; }
|
||||
|
||||
sed -i "s/=$OLD/=$NEW/" GNUmakefile || exit 1
|
||||
# Determine the correct sed command
|
||||
case $(sed --help 2>&1) in
|
||||
*GNU*) set sed -i;;
|
||||
*) set sed -i '';;
|
||||
esac
|
||||
|
||||
"$@" "s/=$OLD/=$NEW/" GNUmakefile || exit 1
|
||||
echo Successfully updated GNUmakefile
|
||||
|
775
include/afl-as.h
775
include/afl-as.h
@ -1,775 +0,0 @@
|
||||
/*
|
||||
american fuzzy lop++ - injectable parts
|
||||
---------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This file houses the assembly-level instrumentation injected into fuzzed
|
||||
programs. The instrumentation stores XORed pairs of data: identifiers of the
|
||||
currently executing branch and the one that executed immediately before.
|
||||
|
||||
TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++
|
||||
|
||||
The code is designed for 32-bit and 64-bit x86 systems. Both modes should
|
||||
work everywhere except for Apple systems. Apple does relocations differently
|
||||
from everybody else, so since their OSes have been 64-bit for a longer while,
|
||||
I didn't go through the mental effort of porting the 32-bit code.
|
||||
|
||||
In principle, similar code should be easy to inject into any well-behaved
|
||||
binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural
|
||||
targets for instrumentation, and should offer comparable probe density.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _HAVE_AFL_AS_H
|
||||
#define _HAVE_AFL_AS_H
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
|
||||
/*
|
||||
------------------
|
||||
Performances notes
|
||||
------------------
|
||||
|
||||
Contributions to make this code faster are appreciated! Here are some
|
||||
rough notes that may help with the task:
|
||||
|
||||
- Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are
|
||||
really worth optimizing; the setup / fork server stuff matters a lot less
|
||||
and should be mostly just kept readable.
|
||||
|
||||
- We're aiming for modern CPUs with out-of-order execution and large
|
||||
pipelines; the code is mostly follows intuitive, human-readable
|
||||
instruction ordering, because "textbook" manual reorderings make no
|
||||
substantial difference.
|
||||
|
||||
- Interestingly, instrumented execution isn't a lot faster if we store a
|
||||
variable pointer to the setup, log, or return routine and then do a reg
|
||||
call from within trampoline_fmt. It does speed up non-instrumented
|
||||
execution quite a bit, though, since that path just becomes
|
||||
push-call-ret-pop.
|
||||
|
||||
- There is also not a whole lot to be gained by doing SHM attach at a
|
||||
fixed address instead of retrieving __afl_area_ptr. Although it allows us
|
||||
to have a shorter log routine inserted for conditional jumps and jump
|
||||
labels (for a ~10% perf gain), there is a risk of bumping into other
|
||||
allocations created by the program or by tools such as ASAN.
|
||||
|
||||
- popf is *awfully* slow, which is why we're doing the lahf / sahf +
|
||||
overflow test trick. Unfortunately, this forces us to taint eax / rax, but
|
||||
this dependency on a commonly-used register still beats the alternative of
|
||||
using pushf / popf.
|
||||
|
||||
One possible optimization is to avoid touching flags by using a circular
|
||||
buffer that stores just a sequence of current locations, with the XOR stuff
|
||||
happening offline. Alas, this doesn't seem to have a huge impact:
|
||||
|
||||
https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ
|
||||
|
||||
- Preforking one child a bit sooner, and then waiting for the "go" command
|
||||
from within the child, doesn't offer major performance gains; fork() seems
|
||||
to be relatively inexpensive these days. Preforking multiple children does
|
||||
help, but badly breaks the "~1 core per fuzzer" design, making it harder to
|
||||
scale up. Maybe there is some middle ground.
|
||||
|
||||
Perhaps of note: in the 64-bit version for all platforms except for Apple,
|
||||
the instrumentation is done slightly differently than on 32-bit, with
|
||||
__afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm),
|
||||
rather than global (.comm). This is to avoid GOTRELPC lookups in the critical
|
||||
code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to
|
||||
work; simple relocations between .bss and .text won't work on most 64-bit
|
||||
platforms in such a case.
|
||||
|
||||
(Fun fact: on Apple systems, .lcomm can segfault the linker.)
|
||||
|
||||
The side effect is that state transitions are measured in a somewhat
|
||||
different way, with previous tuple being recorded separately within the scope
|
||||
of every .c file. This should have no impact in any practical sense.
|
||||
|
||||
Another side effect of this design is that getenv() will be called once per
|
||||
every .o file when running in non-instrumented mode; and since getenv() tends
|
||||
to be optimized in funny ways, we need to be very careful to save every
|
||||
oddball register it may touch.
|
||||
|
||||
*/
|
||||
|
||||
static const u8 *trampoline_fmt_32 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL TRAMPOLINE (32-BIT) --- */\n"
|
||||
"\n"
|
||||
".align 4\n"
|
||||
"\n"
|
||||
"leal -16(%%esp), %%esp\n"
|
||||
"movl %%edi, 0(%%esp)\n"
|
||||
"movl %%edx, 4(%%esp)\n"
|
||||
"movl %%ecx, 8(%%esp)\n"
|
||||
"movl %%eax, 12(%%esp)\n"
|
||||
"movl $0x%08x, %%ecx\n"
|
||||
"call __afl_maybe_log\n"
|
||||
"movl 12(%%esp), %%eax\n"
|
||||
"movl 8(%%esp), %%ecx\n"
|
||||
"movl 4(%%esp), %%edx\n"
|
||||
"movl 0(%%esp), %%edi\n"
|
||||
"leal 16(%%esp), %%esp\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
static const u8 *trampoline_fmt_64 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL TRAMPOLINE (64-BIT) --- */\n"
|
||||
"\n"
|
||||
".align 4\n"
|
||||
"\n"
|
||||
"leaq -(128+24)(%%rsp), %%rsp\n"
|
||||
"movq %%rdx, 0(%%rsp)\n"
|
||||
"movq %%rcx, 8(%%rsp)\n"
|
||||
"movq %%rax, 16(%%rsp)\n"
|
||||
"movq $0x%08x, %%rcx\n"
|
||||
"call __afl_maybe_log\n"
|
||||
"movq 16(%%rsp), %%rax\n"
|
||||
"movq 8(%%rsp), %%rcx\n"
|
||||
"movq 0(%%rsp), %%rdx\n"
|
||||
"leaq (128+24)(%%rsp), %%rsp\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
static const u8 *main_payload_32 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n"
|
||||
"\n"
|
||||
".text\n"
|
||||
".att_syntax\n"
|
||||
".code32\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
|
||||
"__afl_maybe_log:\n"
|
||||
"\n"
|
||||
" lahf\n"
|
||||
" seto %al\n"
|
||||
"\n"
|
||||
" /* Check if SHM region is already mapped. */\n"
|
||||
"\n"
|
||||
" movl __afl_area_ptr, %edx\n"
|
||||
" testl %edx, %edx\n"
|
||||
" je __afl_setup\n"
|
||||
"\n"
|
||||
"__afl_store:\n"
|
||||
"\n"
|
||||
" /* Calculate and store hit for the code location specified in ecx. There\n"
|
||||
" is a double-XOR way of doing this without tainting another register,\n"
|
||||
" and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n"
|
||||
"\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" movl __afl_prev_loc, %edi\n"
|
||||
" xorl %ecx, %edi\n"
|
||||
" shrl $1, %ecx\n"
|
||||
" movl %ecx, __afl_prev_loc\n"
|
||||
#else
|
||||
" movl %ecx, %edi\n"
|
||||
#endif /* ^!COVERAGE_ONLY */
|
||||
"\n"
|
||||
#ifdef SKIP_COUNTS
|
||||
" orb $1, (%edx, %edi, 1)\n"
|
||||
#else
|
||||
" addb $1, (%edx, %edi, 1)\n"
|
||||
" adcb $0, (%edx, %edi, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
|
||||
#endif /* ^SKIP_COUNTS */
|
||||
"\n"
|
||||
"__afl_return:\n"
|
||||
"\n"
|
||||
" addb $127, %al\n"
|
||||
" sahf\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_setup:\n"
|
||||
"\n"
|
||||
" /* Do not retry setup if we had previous failures. */\n"
|
||||
"\n"
|
||||
" cmpb $0, __afl_setup_failure\n"
|
||||
" jne __afl_return\n"
|
||||
"\n"
|
||||
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n"
|
||||
" We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n"
|
||||
" will notice this early in the game. */\n"
|
||||
"\n"
|
||||
" pushl %eax\n"
|
||||
" pushl %ecx\n"
|
||||
"\n"
|
||||
" pushl $.AFL_SHM_ENV\n"
|
||||
" call getenv\n"
|
||||
" addl $4, %esp\n"
|
||||
"\n"
|
||||
" testl %eax, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#ifdef USEMMAP
|
||||
" pushl $384 /* shm_open mode 0600 */\n"
|
||||
" pushl $2 /* flags O_RDWR */\n"
|
||||
" pushl %eax /* SHM file path */\n"
|
||||
" call shm_open\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
" pushl $0 /* mmap off */\n"
|
||||
" pushl %eax /* shm fd */\n"
|
||||
" pushl $1 /* mmap flags */\n"
|
||||
" pushl $3 /* mmap prot */\n"
|
||||
" pushl $"STRINGIFY(MAP_SIZE)" /* mmap len */\n"
|
||||
" pushl $0 /* mmap addr */\n"
|
||||
" call mmap\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#else
|
||||
" pushl %eax\n"
|
||||
" call atoi\n"
|
||||
" addl $4, %esp\n"
|
||||
"\n"
|
||||
" pushl $0 /* shmat flags */\n"
|
||||
" pushl $0 /* requested addr */\n"
|
||||
" pushl %eax /* SHM ID */\n"
|
||||
" call shmat\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $-1, %eax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#endif
|
||||
" movb $1, (%eax)\n"
|
||||
" /* Store the address of the SHM region. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_area_ptr\n"
|
||||
" movl %eax, %edx\n"
|
||||
"\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
"\n"
|
||||
"__afl_forkserver:\n"
|
||||
"\n"
|
||||
" /* Enter the fork server mode to avoid the overhead of execve() calls. */\n"
|
||||
"\n"
|
||||
" pushl %eax\n"
|
||||
" pushl %ecx\n"
|
||||
" pushl %edx\n"
|
||||
"\n"
|
||||
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
|
||||
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
|
||||
" closed because we were execve()d from an instrumented binary, or because\n"
|
||||
" the parent doesn't want to use the fork server. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $4, %eax\n"
|
||||
" jne __afl_fork_resume\n"
|
||||
"\n"
|
||||
"__afl_fork_wait_loop:\n"
|
||||
"\n"
|
||||
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n"
|
||||
" call read\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $4, %eax\n"
|
||||
" jne __afl_die\n"
|
||||
"\n"
|
||||
" /* Once woken up, create a clone of our process. This is an excellent use\n"
|
||||
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
|
||||
" caches getpid() results and offers no way to update the value, breaking\n"
|
||||
" abort(), raise(), and a bunch of other things :-( */\n"
|
||||
"\n"
|
||||
" call fork\n"
|
||||
"\n"
|
||||
" cmpl $0, %eax\n"
|
||||
" jl __afl_die\n"
|
||||
" je __afl_fork_resume\n"
|
||||
"\n"
|
||||
" /* In parent process: write PID to pipe, then wait for child. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_fork_pid\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_fork_pid /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" pushl $0 /* no flags */\n"
|
||||
" pushl $__afl_temp /* status */\n"
|
||||
" pushl __afl_fork_pid /* PID */\n"
|
||||
" call waitpid\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" cmpl $0, %eax\n"
|
||||
" jle __afl_die\n"
|
||||
"\n"
|
||||
" /* Relay wait status to pipe, then loop back. */\n"
|
||||
"\n"
|
||||
" pushl $4 /* length */\n"
|
||||
" pushl $__afl_temp /* data */\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
|
||||
" call write\n"
|
||||
" addl $12, %esp\n"
|
||||
"\n"
|
||||
" jmp __afl_fork_wait_loop\n"
|
||||
"\n"
|
||||
"__afl_fork_resume:\n"
|
||||
"\n"
|
||||
" /* In child process: close fds, resume execution. */\n"
|
||||
"\n"
|
||||
" pushl $" STRINGIFY(FORKSRV_FD) "\n"
|
||||
" call close\n"
|
||||
"\n"
|
||||
" pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n"
|
||||
" call close\n"
|
||||
"\n"
|
||||
" addl $8, %esp\n"
|
||||
"\n"
|
||||
" popl %edx\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_die:\n"
|
||||
"\n"
|
||||
" xorl %eax, %eax\n"
|
||||
" call _exit\n"
|
||||
"\n"
|
||||
"__afl_setup_abort:\n"
|
||||
"\n"
|
||||
" /* Record setup failure so that we don't keep calling\n"
|
||||
" shmget() / shmat() over and over again. */\n"
|
||||
"\n"
|
||||
" incb __afl_setup_failure\n"
|
||||
" popl %ecx\n"
|
||||
" popl %eax\n"
|
||||
" jmp __afl_return\n"
|
||||
"\n"
|
||||
".AFL_VARS:\n"
|
||||
"\n"
|
||||
" .comm __afl_area_ptr, 4, 32\n"
|
||||
" .comm __afl_setup_failure, 1, 32\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .comm __afl_prev_loc, 4, 32\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .comm __afl_final_loc, 4, 32\n"
|
||||
" .comm __afl_fork_pid, 4, 32\n"
|
||||
" .comm __afl_temp, 4, 32\n"
|
||||
"\n"
|
||||
".AFL_SHM_ENV:\n"
|
||||
" .asciz \"" SHM_ENV_VAR "\"\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
/* The OpenBSD hack is due to lahf and sahf not being recognized by some
|
||||
versions of binutils: https://marc.info/?l=openbsd-cvs&m=141636589924400
|
||||
|
||||
The Apple code is a bit different when calling libc functions because
|
||||
they are doing relocations differently from everybody else. We also need
|
||||
to work around the crash issue with .lcomm and the fact that they don't
|
||||
recognize .string. */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define CALL_L64(str) "call _" str "\n"
|
||||
#else
|
||||
#define CALL_L64(str) "call " str "@PLT\n"
|
||||
#endif /* ^__APPLE__ */
|
||||
|
||||
static const u8 *main_payload_64 =
|
||||
|
||||
"\n"
|
||||
"/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n"
|
||||
"\n"
|
||||
".text\n"
|
||||
".att_syntax\n"
|
||||
".code64\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_maybe_log:\n"
|
||||
"\n"
|
||||
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
|
||||
" .byte 0x9f /* lahf */\n"
|
||||
#else
|
||||
" lahf\n"
|
||||
#endif /* ^__OpenBSD__, etc */
|
||||
" seto %al\n"
|
||||
"\n"
|
||||
" /* Check if SHM region is already mapped. */\n"
|
||||
"\n"
|
||||
" movq __afl_area_ptr(%rip), %rdx\n"
|
||||
" testq %rdx, %rdx\n"
|
||||
" je __afl_setup\n"
|
||||
"\n"
|
||||
"__afl_store:\n"
|
||||
"\n"
|
||||
" /* Calculate and store hit for the code location specified in rcx. */\n"
|
||||
"\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" xorq __afl_prev_loc(%rip), %rcx\n"
|
||||
" xorq %rcx, __afl_prev_loc(%rip)\n"
|
||||
" shrq $1, __afl_prev_loc(%rip)\n"
|
||||
#endif /* ^!COVERAGE_ONLY */
|
||||
"\n"
|
||||
#ifdef SKIP_COUNTS
|
||||
" orb $1, (%rdx, %rcx, 1)\n"
|
||||
#else
|
||||
" addb $1, (%rdx, %rcx, 1)\n"
|
||||
" adcb $0, (%rdx, %rcx, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
|
||||
#endif /* ^SKIP_COUNTS */
|
||||
"\n"
|
||||
"__afl_return:\n"
|
||||
"\n"
|
||||
" addb $127, %al\n"
|
||||
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
|
||||
" .byte 0x9e /* sahf */\n"
|
||||
#else
|
||||
" sahf\n"
|
||||
#endif /* ^__OpenBSD__, etc */
|
||||
" ret\n"
|
||||
"\n"
|
||||
".align 8\n"
|
||||
"\n"
|
||||
"__afl_setup:\n"
|
||||
"\n"
|
||||
" /* Do not retry setup if we had previous failures. */\n"
|
||||
"\n"
|
||||
" cmpb $0, __afl_setup_failure(%rip)\n"
|
||||
" jne __afl_return\n"
|
||||
"\n"
|
||||
" /* Check out if we have a global pointer on file. */\n"
|
||||
"\n"
|
||||
#ifndef __APPLE__
|
||||
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
|
||||
" movq (%rdx), %rdx\n"
|
||||
#else
|
||||
" movq __afl_global_area_ptr(%rip), %rdx\n"
|
||||
#endif /* !^__APPLE__ */
|
||||
" testq %rdx, %rdx\n"
|
||||
" je __afl_setup_first\n"
|
||||
"\n"
|
||||
" movq %rdx, __afl_area_ptr(%rip)\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_setup_first:\n"
|
||||
"\n"
|
||||
" /* Save everything that is not yet saved and that may be touched by\n"
|
||||
" getenv() and several other libcalls we'll be relying on. */\n"
|
||||
"\n"
|
||||
" leaq -352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" movq %rax, 0(%rsp)\n"
|
||||
" movq %rcx, 8(%rsp)\n"
|
||||
" movq %rdi, 16(%rsp)\n"
|
||||
" movq %rsi, 32(%rsp)\n"
|
||||
" movq %r8, 40(%rsp)\n"
|
||||
" movq %r9, 48(%rsp)\n"
|
||||
" movq %r10, 56(%rsp)\n"
|
||||
" movq %r11, 64(%rsp)\n"
|
||||
"\n"
|
||||
" movq %xmm0, 96(%rsp)\n"
|
||||
" movq %xmm1, 112(%rsp)\n"
|
||||
" movq %xmm2, 128(%rsp)\n"
|
||||
" movq %xmm3, 144(%rsp)\n"
|
||||
" movq %xmm4, 160(%rsp)\n"
|
||||
" movq %xmm5, 176(%rsp)\n"
|
||||
" movq %xmm6, 192(%rsp)\n"
|
||||
" movq %xmm7, 208(%rsp)\n"
|
||||
" movq %xmm8, 224(%rsp)\n"
|
||||
" movq %xmm9, 240(%rsp)\n"
|
||||
" movq %xmm10, 256(%rsp)\n"
|
||||
" movq %xmm11, 272(%rsp)\n"
|
||||
" movq %xmm12, 288(%rsp)\n"
|
||||
" movq %xmm13, 304(%rsp)\n"
|
||||
" movq %xmm14, 320(%rsp)\n"
|
||||
" movq %xmm15, 336(%rsp)\n"
|
||||
"\n"
|
||||
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n"
|
||||
"\n"
|
||||
" /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n"
|
||||
" original stack ptr in the callee-saved r12. */\n"
|
||||
"\n"
|
||||
" pushq %r12\n"
|
||||
" movq %rsp, %r12\n"
|
||||
" subq $16, %rsp\n"
|
||||
" andq $0xfffffffffffffff0, %rsp\n"
|
||||
"\n"
|
||||
" leaq .AFL_SHM_ENV(%rip), %rdi\n"
|
||||
CALL_L64("getenv")
|
||||
"\n"
|
||||
" testq %rax, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#ifdef USEMMAP
|
||||
" movl $384, %edx /* shm_open mode 0600 */\n"
|
||||
" movl $2, %esi /* flags O_RDWR */\n"
|
||||
" movq %rax, %rdi /* SHM file path */\n"
|
||||
CALL_L64("shm_open")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
" movl $0, %r9d\n"
|
||||
" movl %eax, %r8d\n"
|
||||
" movl $1, %ecx\n"
|
||||
" movl $3, %edx\n"
|
||||
" movl $"STRINGIFY(MAP_SIZE)", %esi\n"
|
||||
" movl $0, %edi\n"
|
||||
CALL_L64("mmap")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#else
|
||||
" movq %rax, %rdi\n"
|
||||
CALL_L64("atoi")
|
||||
"\n"
|
||||
" xorq %rdx, %rdx /* shmat flags */\n"
|
||||
" xorq %rsi, %rsi /* requested addr */\n"
|
||||
" movq %rax, %rdi /* SHM ID */\n"
|
||||
CALL_L64("shmat")
|
||||
"\n"
|
||||
" cmpq $-1, %rax\n"
|
||||
" je __afl_setup_abort\n"
|
||||
"\n"
|
||||
#endif
|
||||
" movb $1, (%rax)\n"
|
||||
" /* Store the address of the SHM region. */\n"
|
||||
"\n"
|
||||
" movq %rax, %rdx\n"
|
||||
" movq %rax, __afl_area_ptr(%rip)\n"
|
||||
"\n"
|
||||
#ifdef __APPLE__
|
||||
" movq %rax, __afl_global_area_ptr(%rip)\n"
|
||||
#else
|
||||
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
|
||||
" movq %rax, (%rdx)\n"
|
||||
#endif /* ^__APPLE__ */
|
||||
" movq %rax, %rdx\n"
|
||||
"\n"
|
||||
"__afl_forkserver:\n"
|
||||
"\n"
|
||||
" /* Enter the fork server mode to avoid the overhead of execve() calls. We\n"
|
||||
" push rdx (area ptr) twice to keep stack alignment neat. */\n"
|
||||
"\n"
|
||||
" pushq %rdx\n"
|
||||
" pushq %rdx\n"
|
||||
"\n"
|
||||
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
|
||||
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
|
||||
" closed because we were execve()d from an instrumented binary, or because\n"
|
||||
" the parent doesn't want to use the fork server. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" cmpq $4, %rax\n"
|
||||
" jne __afl_fork_resume\n"
|
||||
"\n"
|
||||
"__afl_fork_wait_loop:\n"
|
||||
"\n"
|
||||
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n"
|
||||
CALL_L64("read")
|
||||
" cmpq $4, %rax\n"
|
||||
" jne __afl_die\n"
|
||||
"\n"
|
||||
" /* Once woken up, create a clone of our process. This is an excellent use\n"
|
||||
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
|
||||
" caches getpid() results and offers no way to update the value, breaking\n"
|
||||
" abort(), raise(), and a bunch of other things :-( */\n"
|
||||
"\n"
|
||||
CALL_L64("fork")
|
||||
" cmpq $0, %rax\n"
|
||||
" jl __afl_die\n"
|
||||
" je __afl_fork_resume\n"
|
||||
"\n"
|
||||
" /* In parent process: write PID to pipe, then wait for child. */\n"
|
||||
"\n"
|
||||
" movl %eax, __afl_fork_pid(%rip)\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_fork_pid(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" movq $0, %rdx /* no flags */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* status */\n"
|
||||
" movq __afl_fork_pid(%rip), %rdi /* PID */\n"
|
||||
CALL_L64("waitpid")
|
||||
" cmpq $0, %rax\n"
|
||||
" jle __afl_die\n"
|
||||
"\n"
|
||||
" /* Relay wait status to pipe, then loop back. */\n"
|
||||
"\n"
|
||||
" movq $4, %rdx /* length */\n"
|
||||
" leaq __afl_temp(%rip), %rsi /* data */\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
|
||||
CALL_L64("write")
|
||||
"\n"
|
||||
" jmp __afl_fork_wait_loop\n"
|
||||
"\n"
|
||||
"__afl_fork_resume:\n"
|
||||
"\n"
|
||||
" /* In child process: close fds, resume execution. */\n"
|
||||
"\n"
|
||||
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n"
|
||||
CALL_L64("close")
|
||||
"\n"
|
||||
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n"
|
||||
CALL_L64("close")
|
||||
"\n"
|
||||
" popq %rdx\n"
|
||||
" popq %rdx\n"
|
||||
"\n"
|
||||
" movq %r12, %rsp\n"
|
||||
" popq %r12\n"
|
||||
"\n"
|
||||
" movq 0(%rsp), %rax\n"
|
||||
" movq 8(%rsp), %rcx\n"
|
||||
" movq 16(%rsp), %rdi\n"
|
||||
" movq 32(%rsp), %rsi\n"
|
||||
" movq 40(%rsp), %r8\n"
|
||||
" movq 48(%rsp), %r9\n"
|
||||
" movq 56(%rsp), %r10\n"
|
||||
" movq 64(%rsp), %r11\n"
|
||||
"\n"
|
||||
" movq 96(%rsp), %xmm0\n"
|
||||
" movq 112(%rsp), %xmm1\n"
|
||||
" movq 128(%rsp), %xmm2\n"
|
||||
" movq 144(%rsp), %xmm3\n"
|
||||
" movq 160(%rsp), %xmm4\n"
|
||||
" movq 176(%rsp), %xmm5\n"
|
||||
" movq 192(%rsp), %xmm6\n"
|
||||
" movq 208(%rsp), %xmm7\n"
|
||||
" movq 224(%rsp), %xmm8\n"
|
||||
" movq 240(%rsp), %xmm9\n"
|
||||
" movq 256(%rsp), %xmm10\n"
|
||||
" movq 272(%rsp), %xmm11\n"
|
||||
" movq 288(%rsp), %xmm12\n"
|
||||
" movq 304(%rsp), %xmm13\n"
|
||||
" movq 320(%rsp), %xmm14\n"
|
||||
" movq 336(%rsp), %xmm15\n"
|
||||
"\n"
|
||||
" leaq 352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" jmp __afl_store\n"
|
||||
"\n"
|
||||
"__afl_die:\n"
|
||||
"\n"
|
||||
" xorq %rax, %rax\n"
|
||||
CALL_L64("_exit")
|
||||
"\n"
|
||||
"__afl_setup_abort:\n"
|
||||
"\n"
|
||||
" /* Record setup failure so that we don't keep calling\n"
|
||||
" shmget() / shmat() over and over again. */\n"
|
||||
"\n"
|
||||
" incb __afl_setup_failure(%rip)\n"
|
||||
"\n"
|
||||
" movq %r12, %rsp\n"
|
||||
" popq %r12\n"
|
||||
"\n"
|
||||
" movq 0(%rsp), %rax\n"
|
||||
" movq 8(%rsp), %rcx\n"
|
||||
" movq 16(%rsp), %rdi\n"
|
||||
" movq 32(%rsp), %rsi\n"
|
||||
" movq 40(%rsp), %r8\n"
|
||||
" movq 48(%rsp), %r9\n"
|
||||
" movq 56(%rsp), %r10\n"
|
||||
" movq 64(%rsp), %r11\n"
|
||||
"\n"
|
||||
" movq 96(%rsp), %xmm0\n"
|
||||
" movq 112(%rsp), %xmm1\n"
|
||||
" movq 128(%rsp), %xmm2\n"
|
||||
" movq 144(%rsp), %xmm3\n"
|
||||
" movq 160(%rsp), %xmm4\n"
|
||||
" movq 176(%rsp), %xmm5\n"
|
||||
" movq 192(%rsp), %xmm6\n"
|
||||
" movq 208(%rsp), %xmm7\n"
|
||||
" movq 224(%rsp), %xmm8\n"
|
||||
" movq 240(%rsp), %xmm9\n"
|
||||
" movq 256(%rsp), %xmm10\n"
|
||||
" movq 272(%rsp), %xmm11\n"
|
||||
" movq 288(%rsp), %xmm12\n"
|
||||
" movq 304(%rsp), %xmm13\n"
|
||||
" movq 320(%rsp), %xmm14\n"
|
||||
" movq 336(%rsp), %xmm15\n"
|
||||
"\n"
|
||||
" leaq 352(%rsp), %rsp\n"
|
||||
"\n"
|
||||
" jmp __afl_return\n"
|
||||
"\n"
|
||||
".AFL_VARS:\n"
|
||||
"\n"
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
" .comm __afl_area_ptr, 8\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .comm __afl_prev_loc, 8\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .comm __afl_fork_pid, 4\n"
|
||||
" .comm __afl_temp, 4\n"
|
||||
" .comm __afl_setup_failure, 1\n"
|
||||
|
||||
#else
|
||||
|
||||
" .lcomm __afl_area_ptr, 8\n"
|
||||
#ifndef COVERAGE_ONLY
|
||||
" .lcomm __afl_prev_loc, 8\n"
|
||||
#endif /* !COVERAGE_ONLY */
|
||||
" .lcomm __afl_fork_pid, 4\n"
|
||||
" .lcomm __afl_temp, 4\n"
|
||||
" .lcomm __afl_setup_failure, 1\n"
|
||||
|
||||
#endif /* ^__APPLE__ */
|
||||
|
||||
" .comm __afl_global_area_ptr, 8, 8\n"
|
||||
"\n"
|
||||
".AFL_SHM_ENV:\n"
|
||||
" .asciz \"" SHM_ENV_VAR "\"\n"
|
||||
"\n"
|
||||
"/* --- END --- */\n"
|
||||
"\n";
|
||||
|
||||
#endif /* !_HAVE_AFL_AS_H */
|
||||
|
@ -116,6 +116,10 @@
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#undef LIST_FOREACH /* clashes with FreeBSD */
|
||||
#include "list.h"
|
||||
#ifndef SIMPLE_FILES
|
||||
@ -139,6 +143,10 @@
|
||||
#define AFL_RAND_RETURN u32
|
||||
#endif
|
||||
|
||||
#ifndef INTERESTING_32_LEN
|
||||
#error INTERESTING_32_LEN not defined - BUG!
|
||||
#endif
|
||||
|
||||
extern s8 interesting_8[INTERESTING_8_LEN];
|
||||
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
|
||||
extern s32
|
||||
@ -232,7 +240,6 @@ struct queue_entry {
|
||||
custom, /* Marker for custom mutators */
|
||||
stats_mutated; /* stats: # of mutations performed */
|
||||
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u32 tc_ref; /* Trace bytes ref count */
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
@ -242,13 +249,11 @@ struct queue_entry {
|
||||
double perf_score, /* performance score */
|
||||
weight;
|
||||
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
struct skipdet_entry *skipdet_e;
|
||||
|
||||
};
|
||||
@ -444,15 +449,17 @@ extern char *power_names[POWER_SCHEDULES_NUM];
|
||||
typedef struct afl_env_vars {
|
||||
|
||||
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
|
||||
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
|
||||
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
||||
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only,
|
||||
afl_custom_mutator_late_send, afl_no_ui, afl_force_ui,
|
||||
afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
||||
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
|
||||
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
|
||||
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
|
||||
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
|
||||
afl_no_startup_calibration, afl_no_warn_instability,
|
||||
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, afl_no_sync, afl_no_fastresume;
|
||||
|
||||
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
||||
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
|
||||
@ -651,6 +658,7 @@ typedef struct afl_state {
|
||||
switch_fuzz_mode, /* auto or fixed fuzz mode */
|
||||
calibration_time_us, /* Time spend on calibration */
|
||||
sync_time_us, /* Time spend on sync */
|
||||
cmplog_time_us, /* Time spend on cmplog */
|
||||
trim_time_us; /* Time spend on trimming */
|
||||
|
||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
@ -739,7 +747,7 @@ typedef struct afl_state {
|
||||
up to 256 */
|
||||
|
||||
unsigned long long int last_avg_exec_update;
|
||||
u32 last_avg_execs;
|
||||
u64 last_avg_total_execs;
|
||||
double last_avg_execs_saved;
|
||||
|
||||
/* foreign sync */
|
||||
@ -1221,6 +1229,7 @@ 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);
|
||||
void update_cmplog_time(afl_state_t *afl, u64 *time);
|
||||
|
||||
/* StatsD */
|
||||
|
||||
@ -1271,6 +1280,7 @@ void get_core_count(afl_state_t *);
|
||||
void fix_up_sync(afl_state_t *);
|
||||
void check_asan_opts(afl_state_t *);
|
||||
void check_binary(afl_state_t *, u8 *);
|
||||
u64 get_binary_hash(u8 *fn);
|
||||
void check_if_tty(afl_state_t *);
|
||||
void save_cmdline(afl_state_t *, u32, char **);
|
||||
void read_foreign_testcases(afl_state_t *, int);
|
||||
@ -1404,6 +1414,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);
|
||||
|
||||
/* 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
|
||||
#error define of TESTCASE_CACHE must be zero or larger than 1
|
||||
#endif
|
||||
|
@ -33,6 +33,10 @@
|
||||
|
||||
#define MUT_STRATEGY_ARRAY_SIZE 256
|
||||
|
||||
#ifndef INTERESTING_32
|
||||
#error INTERESTING_32 is not defined - BUG!
|
||||
#endif
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -53,21 +53,24 @@ struct cmp_header { // 16 bit = 2 bytes
|
||||
struct cmp_operands {
|
||||
|
||||
u64 v0;
|
||||
u64 v1;
|
||||
u64 v0_128;
|
||||
u64 v0_256_0; // u256 is unsupported by any compiler for now, so future use
|
||||
u64 v0_256_1;
|
||||
u64 v1;
|
||||
u64 v1_128;
|
||||
u64 unused;
|
||||
u8 unused1;
|
||||
u8 unused2;
|
||||
u64 v1_256_0;
|
||||
u64 v1_256_1;
|
||||
u8 unused[8]; // 2 bits could be used for "is constant operand"
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cmpfn_operands {
|
||||
|
||||
u8 v0[32];
|
||||
u8 v0_len;
|
||||
u8 v1[32];
|
||||
u8 v0_len;
|
||||
u8 v1_len;
|
||||
u8 unused[6]; // 2 bits could be used for "is constant operand"
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.20c"
|
||||
#define VERSION "++4.31a"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -52,6 +52,18 @@
|
||||
/* Default file permission umode when creating files (default: 0600) */
|
||||
#define DEFAULT_PERMISSION 0600
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
#undef DEFAULT_PERMISSION
|
||||
#define DEFAULT_PERMISSION 0666
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#undef DEFAULT_PERMISSION
|
||||
#define DEFAULT_PERMISSION 0666
|
||||
#endif
|
||||
|
||||
/* SkipDet's global configuration */
|
||||
|
||||
#define MINIMAL_BLOCK_SIZE 64
|
||||
@ -324,9 +336,9 @@
|
||||
#define SYNC_INTERVAL 8
|
||||
|
||||
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
|
||||
nodes) - default is 30 minutes: */
|
||||
nodes) - default is 20 minutes: */
|
||||
|
||||
#define SYNC_TIME (30 * 60 * 1000)
|
||||
#define SYNC_TIME (20 * 60 * 1000)
|
||||
|
||||
/* Output directory reuse grace period (minutes): */
|
||||
|
||||
@ -464,7 +476,7 @@
|
||||
/* Do not change this unless you really know what you are doing. */
|
||||
|
||||
#define MAP_SIZE (1U << MAP_SIZE_POW2)
|
||||
#if MAP_SIZE <= 65536
|
||||
#if MAP_SIZE <= 2097152
|
||||
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
|
||||
#else
|
||||
#define MAP_INITIAL_SIZE MAP_SIZE
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -314,8 +314,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
#define FATAL(x...) \
|
||||
do { \
|
||||
\
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
exit(1); \
|
||||
@ -327,8 +327,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
#define ABORT(x...) \
|
||||
do { \
|
||||
\
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
abort(); \
|
||||
@ -341,8 +341,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
do { \
|
||||
\
|
||||
fflush(stdout); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] SYSTEM ERROR : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] SYSTEM ERROR : " cRST x); \
|
||||
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
|
||||
|
@ -20,26 +20,28 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
|
||||
"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_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
||||
"AFL_CMPLOG_DEBUG", "AFL_CTX_K", "AFL_LLVM_DONTWRITEID", "AFL_PC_FILTER",
|
||||
"AFL_PC_FILTER_FILE", "AFL_CODE_END", "AFL_CODE_START",
|
||||
"AFL_COMPCOV_BINNAME", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
|
||||
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
||||
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
||||
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
|
||||
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
|
||||
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
||||
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
|
||||
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
|
||||
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
|
||||
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_MUTATOR_LATE_SEND",
|
||||
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
|
||||
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
|
||||
"AFL_DEBUG_UNICORN", "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_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
|
||||
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
|
||||
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
|
||||
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
|
||||
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
|
||||
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE",
|
||||
"AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE",
|
||||
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
|
||||
"AFL_FRIDA_INST_NO_SUPPRESS"
|
||||
"AFL_FRIDA_INST_RANGES",
|
||||
"AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES",
|
||||
"AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE",
|
||||
"AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE",
|
||||
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR",
|
||||
@ -48,12 +50,12 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
|
||||
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
|
||||
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE",
|
||||
"AFL_FRIDA_VERBOSE",
|
||||
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER", "AFL_OPT_LEVEL",
|
||||
"AFL_FUZZER_ARGS", // oss-fuzz
|
||||
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
|
||||
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
|
||||
"AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO", "AFL_GCJ",
|
||||
"AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
|
||||
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_DISABLE_VERSION_CHECK",
|
||||
"AFL_GCC_INSTRUMENT_FILE", "AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO",
|
||||
"AFL_GCJ", "AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
|
||||
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS",
|
||||
"AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS",
|
||||
"AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST",
|
||||
@ -80,14 +82,13 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
|
||||
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
|
||||
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
|
||||
"AFL_LLVM_LTO_SKIPINIT"
|
||||
"AFL_LLVM_LTO_STARTID",
|
||||
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
|
||||
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
|
||||
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
#if defined USE_COLOR && !defined ALWAYS_COLORED
|
||||
"AFL_NO_COLOR", "AFL_NO_COLOUR",
|
||||
#endif
|
||||
"AFL_NO_CPU_RED",
|
||||
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
|
||||
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
|
||||
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
|
||||
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
|
||||
@ -107,15 +108,16 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
|
||||
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
|
||||
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
|
||||
"AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK",
|
||||
"AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD",
|
||||
"AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR",
|
||||
"AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES",
|
||||
"AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC",
|
||||
"AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN",
|
||||
"AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH",
|
||||
"AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
|
||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
|
||||
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
|
||||
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
|
||||
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
|
||||
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
|
||||
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
|
||||
"AFL_USE_UBSAN", "AFL_UBSAN_VERBOSE", "AFL_USE_TSAN", "AFL_USE_CFISAN",
|
||||
"AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
|
||||
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
|
||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL
|
||||
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>>
|
||||
|
||||
@ -89,11 +89,14 @@ typedef struct {
|
||||
bool (*nyx_config_set_aux_buffer_size)(void *config,
|
||||
uint32_t aux_buffer_size);
|
||||
|
||||
uint64_t (*nyx_get_target_hash64)(void *config);
|
||||
|
||||
void (*nyx_config_free)(void *config);
|
||||
|
||||
} nyx_plugin_handler_t;
|
||||
|
||||
/* Imports helper functions to enable Nyx mode (Linux only )*/
|
||||
nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct afl_forkserver {
|
||||
@ -188,6 +191,8 @@ typedef struct afl_forkserver {
|
||||
|
||||
u8 persistent_mode;
|
||||
|
||||
u32 max_length;
|
||||
|
||||
#ifdef __linux__
|
||||
nyx_plugin_handler_t *nyx_handlers;
|
||||
char *out_dir_path; /* path to the output directory */
|
||||
@ -202,8 +207,18 @@ typedef struct afl_forkserver {
|
||||
bool nyx_use_tmp_workdir;
|
||||
char *nyx_tmp_workdir_path;
|
||||
s32 nyx_log_fd;
|
||||
u64 nyx_target_hash64;
|
||||
#endif
|
||||
|
||||
#ifdef __AFL_CODE_COVERAGE
|
||||
u8 *persistent_trace_bits; /* Persistent copy of bitmap */
|
||||
#endif
|
||||
|
||||
void *custom_data_ptr;
|
||||
u8 *custom_input;
|
||||
u32 custom_input_len;
|
||||
void (*late_send)(void *, const u8 *, size_t);
|
||||
|
||||
} afl_forkserver_t;
|
||||
|
||||
typedef enum fsrv_run_result {
|
||||
@ -230,6 +245,10 @@ void afl_fsrv_killall(void);
|
||||
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
|
||||
void afl_fsrv_kill(afl_forkserver_t *fsrv);
|
||||
|
||||
#ifdef __linux__
|
||||
void nyx_load_target_hash(afl_forkserver_t *fsrv);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define MSG_FORK_ON_APPLE \
|
||||
" - On MacOS X, the semantics of fork() syscalls are non-standard and " \
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
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>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user