mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
423 Commits
Author | SHA1 | Date | |
---|---|---|---|
e8caa32b0e | |||
be276eb425 | |||
f9a8b60b3b | |||
4a1cf0b9af | |||
d6a2edb42a | |||
5e8e233755 | |||
31ed850c4b | |||
994ac55878 | |||
cb5a61d8a1 | |||
146e535f7b | |||
b88f132975 | |||
12271064f8 | |||
55b67f1372 | |||
595cc3aadd | |||
d21fb1a558 | |||
2e6c74f9b9 | |||
2a4281ce8d | |||
9cd702e75d | |||
8b35dd49be | |||
703fd0b610 | |||
db172473b5 | |||
1f335b0d82 | |||
60620d4c81 | |||
0ee028cfae | |||
1d09b242a9 | |||
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 | |||
1d17210d9f | |||
1582aa9da2 | |||
e01307a993 | |||
beb9f95359 | |||
c49a4c7027 | |||
b08df87f5c | |||
72226d6f89 | |||
40adc34413 | |||
eeae114b76 | |||
48a862c503 | |||
29544e4d2b | |||
420a90ff75 | |||
45603367bf | |||
f7ea0f569f | |||
2bf92848ff | |||
ad65cfb400 | |||
5ffc8c7076 | |||
8943ba0249 | |||
b02adf6b3f | |||
6ef5d7c135 | |||
9ece2e3f2c | |||
4b2cdaf47c | |||
9b5b71b61b | |||
59465bd249 | |||
ed50f37c79 | |||
a96bda82f9 | |||
1860f6e594 | |||
c9ad3acc9b | |||
93c7a42453 | |||
ee07fc9f6d | |||
443edcd771 | |||
6650ef4274 | |||
b85174fc8d | |||
08f6d59f50 | |||
2ed2ac80bc | |||
2300088446 | |||
306a917956 | |||
0ea53ea5b5 | |||
092260e9f9 | |||
52e19d35fa | |||
bf17953353 | |||
e46fac6063 | |||
6062668679 | |||
acc178e5dd | |||
31adb57fd7 | |||
7652406c12 | |||
a607adb7a3 | |||
036a79268b | |||
335b2d4542 | |||
603136efa0 | |||
1e01ccc8fd | |||
9f6d27ddce | |||
8fcd404352 | |||
b2b887d04d | |||
849994dedd | |||
1286d1906f | |||
fae760fc9e | |||
01f442d810 | |||
eaedf2e62f | |||
07e0b39126 | |||
98238ed763 | |||
340d6aa97c | |||
5ae4a7ae02 | |||
80158de3e8 | |||
730713193a | |||
fea76dff23 | |||
808022d3e0 | |||
eee78077e2 | |||
ca91d3fbc0 | |||
ad4a776fc6 | |||
ebdb71aeb0 | |||
6dc58750cf | |||
1b84448be3 | |||
61ceef64b1 | |||
5404eef7be | |||
6fed799957 | |||
dd88069711 | |||
07bc202e0a | |||
f2b7357ff3 | |||
3cbaefd247 | |||
037a14f621 | |||
88e41f01c8 | |||
369fce9c85 | |||
eaf4a29930 | |||
48070e0148 | |||
c23bbddde9 | |||
038fef962c | |||
42c663e7c7 | |||
956fa95d77 | |||
ea0ea88ed3 | |||
e0e8645d6c | |||
a2100f32e0 | |||
25a6c2c006 | |||
7f8347b12e | |||
8e4bd0314e | |||
a7fd84e186 | |||
e405e721fa | |||
49d4fa4346 | |||
375aca2997 | |||
9f8eea5467 | |||
58aa181d01 | |||
f49e391022 | |||
698f1e272b | |||
023fc19ce0 | |||
40df85d1e6 | |||
47e7d243f7 | |||
6d209ce045 | |||
34a3060b0f | |||
c77709cdd9 | |||
27338fcef1 | |||
9fab7e892d | |||
dc151caa18 | |||
e1d7f4af35 | |||
d85722a4f6 | |||
ba3a039e45 | |||
bd13d32437 | |||
79080355ac | |||
e6eee685ce | |||
ceb7e44e6f | |||
d668010bed | |||
44a7696169 | |||
b0a912a838 | |||
4d493452a4 | |||
8fedf49984 | |||
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", "")
|
||||
|
||||
|
||||
|
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@ -34,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
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
*.pyc
|
||||
*.so
|
||||
*.swp
|
||||
.DS_Store
|
||||
.sync_tmp
|
||||
.test
|
||||
.test2
|
||||
@ -99,10 +100,17 @@ unicorn_mode/samples/*/\.test-*
|
||||
utils/afl_network_proxy/afl-network-client
|
||||
utils/afl_network_proxy/afl-network-server
|
||||
utils/afl_proxy/afl-proxy
|
||||
utils/bench/hash
|
||||
utils/optimin/build
|
||||
utils/optimin/optimin
|
||||
utils/persistent_mode/persistent_demo
|
||||
utils/persistent_mode/persistent_demo_new
|
||||
utils/persistent_mode/persistent_demo_new_compat
|
||||
utils/persistent_mode/test-instr
|
||||
utils/replay_record/persistent_demo_replay
|
||||
utils/replay_record/persistent_demo_replay_compat
|
||||
utils/replay_record/persistent_demo_replay_argparse
|
||||
utils/plot_ui/afl-plot-ui
|
||||
vuln_prog
|
||||
argv_fuzz_demo
|
||||
argv_fuzz_persistent_demo
|
@ -27,5 +27,5 @@ keywords:
|
||||
- qemu
|
||||
- llvm
|
||||
- unicorn-emulator
|
||||
- securiy
|
||||
- security
|
||||
license: AGPL-3.0-or-later
|
||||
|
@ -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.
|
||||
|
83
GNUmakefile
83
GNUmakefile
@ -52,7 +52,7 @@ endif
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
override CFLAGS += $(ASAN_CFLAGS)
|
||||
LDFLAGS += $(ASAN_LDFLAGS)
|
||||
override LDFLAGS += $(ASAN_LDFLAGS)
|
||||
endif
|
||||
ifdef UBSAN_BUILD
|
||||
$(info Compiling UBSAN version of binaries)
|
||||
@ -84,38 +84,44 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
|
||||
#endif
|
||||
|
||||
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
# ifndef SOURCE_DATE_EPOCH
|
||||
# HAVE_MARCHNATIVE = 1
|
||||
# CFLAGS_OPT += -march=native
|
||||
# endif
|
||||
#endif
|
||||
ifdef PERFORMANCE
|
||||
SPECIAL_PERFORMANCE := -D_AFL_SPECIAL_PERFORMANCE
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifeq "$(shell grep avx2 /proc/cpuinfo)" ""
|
||||
else
|
||||
SPECIAL_PERFORMANCE += -mavx2 -D_HAVE_AVX2
|
||||
endif
|
||||
endif
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
HAVE_MARCHNATIVE = 1
|
||||
SPECIAL_PERFORMANCE += -march=native
|
||||
endif
|
||||
$(info SPECIAL_PERFORMANCE=$(SPECIAL_PERFORMANCE))
|
||||
else
|
||||
SPECIAL_PERFORMANCE :=
|
||||
endif
|
||||
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
# CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
#endif
|
||||
else
|
||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||
LDFLAGS += $(SDK_LD)
|
||||
override LDFLAGS += $(SDK_LD)
|
||||
endif
|
||||
|
||||
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
||||
ifneq "$(COMPILER_TYPE)" ""
|
||||
#$(info gcc is being used)
|
||||
CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "SunOS"
|
||||
LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
||||
override LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
@ -125,8 +131,8 @@ ifdef STATIC
|
||||
PYFLAGS=
|
||||
PYTHON_INCLUDE = /
|
||||
|
||||
CFLAGS_OPT += -static
|
||||
LDFLAGS += -lm -lpthread -lz -lutil
|
||||
override CFLAGS_OPT += -static
|
||||
override LDFLAGS += -lm -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
ifdef PROFILING
|
||||
@ -389,6 +395,7 @@ help:
|
||||
@echo
|
||||
@echo Known build environment options:
|
||||
@echo "=========================================="
|
||||
@echo "PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended!"
|
||||
@echo STATIC - compile AFL++ static
|
||||
@echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
|
||||
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
||||
@ -434,6 +441,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:
|
||||
@ -453,31 +468,31 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
|
||||
@ln -sf afl-as as
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
|
||||
|
||||
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||
|
||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(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) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
|
||||
.PHONY: document
|
||||
document: afl-fuzz-document
|
||||
@ -494,17 +509,17 @@ unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
|
||||
./test/unittests/unit_maybe_alloc
|
||||
|
||||
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
|
||||
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_hash
|
||||
|
||||
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
|
||||
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_rand
|
||||
|
||||
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
||||
@ -752,7 +767,7 @@ endif
|
||||
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifndef NO_NYX
|
||||
|
@ -32,6 +32,9 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
|
||||
override LLVM_TOO_NEW_DEFAULT := 18
|
||||
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/ .*//' )
|
||||
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-8]\.' && echo 1 || echo 0)
|
||||
# Uncomment to see the values assigned above
|
||||
# $(foreach var,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"
|
||||
@ -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_CONFIG) --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"
|
||||
|
@ -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.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.10c
|
||||
GitHub version: 4.22a
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
7
TODO.md
7
TODO.md
@ -2,22 +2,23 @@
|
||||
|
||||
## Must
|
||||
|
||||
- UI revamp
|
||||
- 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 len, cmplog max items envs?
|
||||
- cmplog max items env?
|
||||
- adapt MOpt to new mutation engine
|
||||
- Update afl->pending_not_fuzzed for MOpt
|
||||
- cmplog rtn sanity check on fixed length? currently we ignore the length
|
||||
- afl-showmap -f support
|
||||
- afl-fuzz multicore wrapper script
|
||||
- when trimming then perform crash detection
|
||||
- problem: either -L0 and/or -p mmopt results in zero new coverage
|
||||
|
||||
|
||||
## 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
|
||||
|
8
afl-cmin
8
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)
|
||||
@ -108,7 +108,7 @@ function usage() {
|
||||
"\n" \
|
||||
"Execution control settings:\n" \
|
||||
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
|
||||
" -f file - location read by the fuzzed program (stdin)\n" \
|
||||
" -f file - location read by the fuzzed program (default: stdin)\n" \
|
||||
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
||||
" -t msec - run time limit for child process (default: 5000)\n" \
|
||||
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
||||
@ -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
|
||||
|
@ -124,17 +124,26 @@ kernel.sched_latency_ns=250000000
|
||||
EOF
|
||||
}
|
||||
|
||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
|
||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
|
||||
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
|
||||
grub_try_disable_mitigation () {
|
||||
KEY="$1"
|
||||
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
|
||||
echo "Configuring performance boot options"
|
||||
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
|
||||
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
|
||||
}
|
||||
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
|
||||
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if grep -E -q '^GRUB_CMDLINE_LINUX=' /etc/default/grub || grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub; then
|
||||
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX_DEFAULT"
|
||||
# We also overwrite GRUB_CMDLINE_LINUX because some distributions already overwrite GRUB_CMDLINE_LINUX_DEFAULT
|
||||
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX"
|
||||
else
|
||||
echo "Error: /etc/default/grub with GRUB_CMDLINE_LINUX is not present, cannot set boot options"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Reboot and enjoy your fuzzing"
|
||||
exit 0
|
||||
|
50
afl-whatsup
50
afl-whatsup
@ -111,9 +111,16 @@ 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
|
||||
|
||||
ALIVE_CNT=0
|
||||
DEAD_CNT=0
|
||||
@ -122,6 +129,7 @@ START_CNT=0
|
||||
TOTAL_TIME=0
|
||||
TOTAL_EXECS=0
|
||||
TOTAL_EPS=0
|
||||
TOTAL_EPLM=0
|
||||
TOTAL_CRASHES=0
|
||||
TOTAL_HANGS=0
|
||||
TOTAL_PFAV=0
|
||||
@ -181,6 +189,8 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
|
||||
if [ -f "$i" ]; then
|
||||
|
||||
IS_STARTING=
|
||||
IS_DEAD=
|
||||
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
|
||||
. "$TMP"
|
||||
DIRECTORY=$DIR
|
||||
@ -211,9 +221,6 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
|
||||
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
|
||||
|
||||
IS_STARTING=
|
||||
IS_DEAD=
|
||||
|
||||
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
|
||||
|
||||
if [ "$i" -ot "$j" ]; then
|
||||
@ -272,11 +279,15 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
ALIVE_CNT=$((ALIVE_CNT + 1))
|
||||
|
||||
EXEC_SEC=0
|
||||
EXEC_MIN=0
|
||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||
|
||||
test "$IS_DEAD" = 1 || EXEC_MIN=$(echo $execs_ps_last_min|sed 's/\..*//')
|
||||
|
||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||
TOTAL_EPLM=$((TOTAL_EPLM + EXEC_MIN))
|
||||
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
||||
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
||||
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
|
||||
@ -398,41 +409,44 @@ if [ -z "$SUMMARY_ONLY" -o -z "$MINIMAL_ONLY" ]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
echo " Fuzzers alive : $ALIVE_CNT"
|
||||
echo " Fuzzers alive : $ALIVE_CNT"
|
||||
|
||||
if [ ! "$START_CNT" = "0" ]; then
|
||||
echo " Starting up : $START_CNT ($TXT)"
|
||||
echo " Starting up : $START_CNT ($TXT)"
|
||||
fi
|
||||
|
||||
if [ ! "$DEAD_CNT" = "0" ]; then
|
||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||
fi
|
||||
|
||||
echo " Total run time : $FMT_TIME"
|
||||
echo " Total run time : $FMT_TIME"
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Total execs : $FMT_EXECS"
|
||||
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
echo " Total execs : $FMT_EXECS"
|
||||
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Total average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
fi
|
||||
fi
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
echo "Current average speed : $TOTAL_EPLM execs/sec"
|
||||
fi
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
fi
|
||||
|
||||
if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Hangs saved : $TOTAL_HANGS"
|
||||
echo "Cycles without finds : $TOTAL_WCOP"
|
||||
echo " Hangs saved : $TOTAL_HANGS"
|
||||
echo " Cycles without finds : $TOTAL_WCOP"
|
||||
fi
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
@ -1,9 +1,14 @@
|
||||
CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
||||
====================================================|=======|=========|============|===========|==============|
|
||||
Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
||||
AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
||||
AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
||||
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
||||
12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
||||
AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
||||
Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
||||
|CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
||||
|----------------------------------------------------|-------|---------|------------|-----------|--------------|
|
||||
|Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
||||
|AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
||||
|AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
||||
|Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
||||
|12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
||||
|AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
||||
|Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
||||
|AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|
||||
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|
||||
|Ampere Altra Q80-30 | 0 | 80 | 54477 | 1604482 | system |
|
||||
|
@ -418,3 +418,7 @@
|
||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.08a", "comment": "", "compiler": "Ubuntu clang version 14.0.0-1ubuntu1.1", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 3700.0, "cpu_model": "AMD Ryzen 5 PRO 4650G with Radeon Graphics", "cpu_threads": 12}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 704840.16, "execs_total": 21163992, "fuzzers_used": 12}, "singlecore": {"execs_per_sec": 95356.14, "execs_total": 2862114, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.09a", "comment": "", "compiler": "Debian clang version 14.0.6", "target_arch": "aarch64-unknown-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 2400.0, "cpu_model": "Raspberry Pi 5", "cpu_threads": 4}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 101114.23, "execs_total": 3036637, "fuzzers_used": 4}, "singlecore": {"execs_per_sec": 25786.11, "execs_total": 774460, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.07a", "comment": "", "compiler": "Debian clang version 17.0.0 (++20230417071830+ae77aceba5ad-1~exp1~20230417071935.630)", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4792.073, "cpu_model": "AMD Ryzen 9 5950X 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2339762.91, "execs_total": 70253164, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161690.07, "execs_total": 4851838, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4675.949, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 614403.91, "execs_total": 18435083, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 62859.9, "execs_total": 1886111, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4744.522, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 991132.96, "execs_total": 29737588, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 135501.07, "execs_total": 4066116, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "Ubuntu clang version 14.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5399.822, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 1566279.42, "execs_total": 46994452, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 71565.56, "execs_total": 2147396, "fuzzers_used": 1}}}}
|
||||
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5478.258, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2173959.15, "execs_total": 65229513, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161960.29, "execs_total": 4859457, "fuzzers_used": 1}}}}
|
||||
|
@ -205,7 +205,7 @@ async def save_benchmark_results() -> None:
|
||||
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
|
||||
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
|
||||
cores = str(args.fuzzers).ljust(7)
|
||||
comparisonfile.write(f"{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
||||
comparisonfile.write(f"|{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
||||
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
|
||||
with open("COMPARISON.md", "r") as comparisonfile:
|
||||
print(comparisonfile.read())
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
typedef struct my_mutator {
|
||||
@ -47,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,8 +1,11 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int max_havoc = 16, verbose;
|
||||
static unsigned char *dict;
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
@ -24,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;
|
||||
|
||||
}
|
||||
|
||||
@ -39,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;
|
||||
|
||||
}
|
||||
@ -56,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;
|
||||
|
||||
@ -69,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;
|
||||
@ -87,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: %zu\n", outlen);
|
||||
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 \
|
||||
|
@ -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]);
|
||||
|
||||
}
|
||||
|
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,122 @@
|
||||
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.22a (dev)
|
||||
- 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
|
||||
- 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!)
|
||||
- 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
|
||||
- code formatting updated to llvm 18
|
||||
- improved custom_mutators/aflpp/standalone/aflpp-standalone
|
||||
- added custom_mutators/autotokens/standalone/autotokens-standalone
|
||||
|
||||
|
||||
### 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
|
||||
for CMPLOG/Redqueen, but new compiled targets will not work with
|
||||
old afl-fuzz versions!
|
||||
! Recompile all targets that are instrumented for CMPLOG/Redqueen!
|
||||
- AFL++ now supports up to 4 billion coverage edges, up from 6 million.
|
||||
- New compile option: `make PERFORMANCE=1` - this will enable special
|
||||
CPU dependent optimizations that make everything more performant - but
|
||||
the binaries will likely won't work on different platforms. Also
|
||||
enables a faster hasher if the CPU requirements are met.
|
||||
- The persistent record feature (see config.h) was expanded to also
|
||||
support replay, thanks to @quarta-qti !
|
||||
- afl-fuzz:
|
||||
- the new deterministic fuzzing feature is now activated by default,
|
||||
deactivate with -z. Parameters -d and -D are ignored.
|
||||
- small improvements to CMPLOG/redqueen
|
||||
- workround for a bug with MOpt -L when used with -M - in the future
|
||||
we will either remove or rewrite MOpt.
|
||||
- fix for `-t xxx+` feature
|
||||
- -e extension option now saves the queue items, crashes, etc. with the
|
||||
extension too
|
||||
- fixes for trimmming, correct -V time and reading stats on resume by eqv
|
||||
thanks a lot!
|
||||
- afl-cc:
|
||||
- added collision free caller instrumentation to LTO mode. activate with
|
||||
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
|
||||
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
|
||||
- fixes for COMPCOV/LAF and most other modules
|
||||
- fix for GCC_PLUGIN cmplog that broke on std::strings
|
||||
- afl-whatsup:
|
||||
- now also displays current average speed
|
||||
- small bugfixes
|
||||
- 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
|
||||
|
129
docs/INSTALL.md
129
docs/INSTALL.md
@ -21,7 +21,7 @@ If you want to build AFL++ yourself, you have many options. The easiest choice
|
||||
is to build and install everything:
|
||||
|
||||
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
|
||||
whatever llvm version is available. We recommend llvm 13, 14, 15 or 16.
|
||||
whatever llvm version is available. We recommend llvm 13 or newer.
|
||||
|
||||
```shell
|
||||
sudo apt-get update
|
||||
@ -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
|
||||
@ -67,19 +70,20 @@ These build targets exist:
|
||||
* unit: perform unit tests (based on cmocka)
|
||||
* help: shows these build options
|
||||
|
||||
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
||||
[Unless you are on macOS](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
||||
you can also build statically linked versions of the AFL++ binaries by passing
|
||||
the `STATIC=1` argument to make:
|
||||
the `PERFORMANCE=1` argument to make:
|
||||
|
||||
```shell
|
||||
make STATIC=1
|
||||
make PERFORMANCE=1
|
||||
```
|
||||
|
||||
These build options exist:
|
||||
|
||||
* STATIC - compile AFL++ static
|
||||
* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
|
||||
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
||||
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended (except on macOS)!
|
||||
* STATIC - compile AFL++ static (does not work on macOS)
|
||||
* CODE_COVERAGE - compile the target for code coverage (see [README.llvm.md](../instrumentation/README.llvm.md))
|
||||
* ASAN_BUILD - compiles AFL++ with address sanitizer for debug purposes
|
||||
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
|
||||
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||
* LLVM_DEBUG - shows llvm deprecation warnings
|
||||
@ -91,101 +95,78 @@ These build options exist:
|
||||
* NO_NYX - disable building nyx mode dependencies
|
||||
* NO_CORESIGHT - disable building coresight (arm64 only)
|
||||
* NO_UNICORN_ARM64 - disable building unicorn on arm64
|
||||
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||
* AFL_NO_X86 - if compiling on non-Intel/AMD platforms
|
||||
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
|
||||
|
||||
e.g.: `make LLVM_CONFIG=llvm-config-14`
|
||||
|
||||
## MacOS X on x86 and arm64 (M1)
|
||||
## macOS on x86_64 and arm64
|
||||
|
||||
MacOS has some gotchas due to the idiosyncrasies of the platform.
|
||||
macOS has some gotchas due to the idiosyncrasies of the platform.
|
||||
|
||||
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
||||
instructions for Linux. If possible, avoid Xcode at all cost.
|
||||
macOS supports SYSV shared memory used by AFL++'s instrumentation, but the
|
||||
default settings aren't sufficient. Before even building, increase
|
||||
them by running the provided script:
|
||||
|
||||
```shell
|
||||
sudo afl-system-config
|
||||
```
|
||||
|
||||
See
|
||||
[https://www.spy-hill.com/help/apple/SharedMemory.html](https://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||
for documentation for the shared memory settings and how to make them permanent.
|
||||
|
||||
Next, to build AFL++, install the following packages from brew:
|
||||
|
||||
```shell
|
||||
brew install wget git make cmake llvm gdb coreutils
|
||||
```
|
||||
|
||||
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
||||
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
|
||||
Depending on your macOS system + brew version, brew may be installed in different places.
|
||||
You can check with `brew info llvm` to know where, then create a variable for it:
|
||||
|
||||
```shell
|
||||
# Depending on your MacOS system + brew version it is either
|
||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||
# or
|
||||
export PATH="/usr/local/opt/llvm/bin:/usr/local/opt/coreutils/libexec/gnubin:$PATH"
|
||||
# you can check with "brew info llvm"
|
||||
export HOMEBREW_BASE="/opt/homebrew/opt"
|
||||
```
|
||||
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
or
|
||||
|
||||
```shell
|
||||
export HOMEBREW_BASE="/usr/local/opt"
|
||||
```
|
||||
|
||||
Set `PATH` to point to the brew clang, clang++, llvm-config, gmake and coreutils.
|
||||
Also use the brew clang compiler; the Xcode clang compiler must not be used.
|
||||
|
||||
```shell
|
||||
export PATH="$HOMEBREW_BASE/coreutils/libexec/gnubin:/usr/local/bin:$HOMEBREW_BASE/llvm/bin:$PATH"
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
gmake
|
||||
cd frida_mode
|
||||
gmake
|
||||
cd ..
|
||||
sudo gmake install
|
||||
```
|
||||
|
||||
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
||||
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
|
||||
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
|
||||
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
||||
Then build following the general Linux instructions.
|
||||
|
||||
The crash reporting daemon that comes by default with MacOS X will cause
|
||||
problems with fuzzing. You need to turn it off:
|
||||
If everything worked, you should then have `afl-clang-fast` installed, which you can check with:
|
||||
|
||||
```
|
||||
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
|
||||
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
|
||||
```shell
|
||||
which afl-clang-fast
|
||||
```
|
||||
|
||||
The `fork()` semantics on OS X are a bit unusual compared to other unix systems
|
||||
Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
|
||||
|
||||
The crash reporting daemon that comes by default with macOS will cause
|
||||
problems with fuzzing. You need to turn it off, which you can do with `afl-system-config`.
|
||||
|
||||
The `fork()` semantics on macOS are a bit unusual compared to other unix systems
|
||||
and definitely don't look POSIX-compliant. This means two things:
|
||||
|
||||
- Fuzzing will be probably slower than on Linux. In fact, some folks report
|
||||
considerable performance gains by running the jobs inside a Linux VM on
|
||||
MacOS X.
|
||||
macOS.
|
||||
- Some non-portable, platform-specific code may be incompatible with the AFL++
|
||||
forkserver. If you run into any problems, set `AFL_NO_FORKSRV=1` in the
|
||||
environment before starting afl-fuzz.
|
||||
|
||||
User emulation mode of QEMU does not appear to be supported on MacOS X, so
|
||||
User emulation mode of QEMU does not appear to be supported on macOS, so
|
||||
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
|
||||
works on both x86 and arm64 MacOS boxes.
|
||||
|
||||
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
|
||||
default settings aren't usable with AFL++. The default settings on 10.14 seem to
|
||||
be:
|
||||
|
||||
```bash
|
||||
$ ipcs -M
|
||||
IPC status from <running system> as of XXX
|
||||
shminfo:
|
||||
shmmax: 4194304 (max shared memory segment size)
|
||||
shmmin: 1 (min shared memory segment size)
|
||||
shmmni: 32 (max number of shared memory identifiers)
|
||||
shmseg: 8 (max shared memory segments per process)
|
||||
shmall: 1024 (max amount of shared memory in pages)
|
||||
```
|
||||
|
||||
To temporarily change your settings to something minimally usable with AFL++,
|
||||
run these commands as root:
|
||||
|
||||
```bash
|
||||
sysctl kern.sysv.shmmax=8388608
|
||||
sysctl kern.sysv.shmall=4096
|
||||
```
|
||||
|
||||
If you're running more than one instance of AFL, you likely want to make
|
||||
`shmall` bigger and increase `shmseg` as well:
|
||||
|
||||
```bash
|
||||
sysctl kern.sysv.shmmax=8388608
|
||||
sysctl kern.sysv.shmseg=48
|
||||
sysctl kern.sysv.shmall=98304
|
||||
```
|
||||
|
||||
See
|
||||
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||
for documentation for these settings and how to make them permanent.
|
||||
works on both x86 and arm64 macOS boxes.
|
||||
|
@ -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:
|
||||
|
@ -248,6 +248,9 @@ use (which only ever the author of this LTO implementation will use). These are
|
||||
used if several separated instrumentations are performed which are then later
|
||||
combined.
|
||||
|
||||
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
|
||||
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
|
||||
to dig deeper into a real function. Default 0.
|
||||
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
||||
to which function. This helps to identify functions with variable bytes or
|
||||
which functions were touched by an input.
|
||||
@ -328,7 +331,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:
|
||||
@ -365,6 +387,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.
|
||||
|
||||
@ -378,6 +404,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
|
||||
|
||||
@ -508,6 +537,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.
|
||||
@ -544,6 +575,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.
|
||||
@ -576,9 +610,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
|
||||
@ -624,7 +661,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:
|
||||
|
||||
@ -696,7 +733,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
|
||||
@ -786,7 +823,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:
|
||||
|
||||
@ -804,7 +841,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
|
||||
@ -815,12 +852,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:
|
||||
|
||||
@ -842,12 +879,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:
|
||||
|
@ -632,7 +632,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`.
|
||||
@ -958,7 +958,7 @@ too long for your overall available fuzz run time.
|
||||
campaign but not good for short CI runs.
|
||||
|
||||
How this can look like can, e.g., be seen at AFL++'s setup in Google's
|
||||
[oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
|
||||
[previous oss-fuzz version](https://github.com/google/oss-fuzz/blob/3e2c5312417d1a6f9564472f3df1fd27759b289d/infra/base-images/base-builder/compile_afl)
|
||||
and
|
||||
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).
|
||||
|
||||
|
@ -5,6 +5,10 @@
|
||||
* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST
|
||||
* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM
|
||||
|
||||
## Starting multiple AFL++ instances in parallel with recommended settings:
|
||||
* [https://github.com/0xricksanchez/AFL_Runner](https://github.com/0xricksanchez/AFL_Runner)
|
||||
* [https://github.com/MegaManSec/AFLplusplus-Parallel-Gen](https://github.com/MegaManSec/AFLplusplus-Parallel-Gen)
|
||||
|
||||
## Speeding up fuzzing
|
||||
|
||||
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the
|
||||
|
@ -21,6 +21,9 @@ training, then we can highly recommend the following:
|
||||
|
||||
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
|
||||
|
||||
A good workflow overview (like our [fuzzing_in_depth.md](fuzzing_in_depth.md)):
|
||||
* [https://appsec.guide/docs/fuzzing/c-cpp/aflpp/](https://appsec.guide/docs/fuzzing/c-cpp/aflpp/)
|
||||
|
||||
Here is a good workflow description (and tutorial) for qemu_mode:
|
||||
|
||||
* [https://airbus-seclab.github.io/AFLplusplus-blogpost/](https://airbus-seclab.github.io/AFLplusplus-blogpost/)
|
||||
|
@ -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]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
|
||||
|
||||
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
|
||||
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep -E 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
|
||||
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep 'Frida\ [0-9.]*'|head -n 1|sed 's/.*Frida\ //'| sed 's/<\/h2>//')
|
||||
|
||||
echo Current set version: $OLD
|
||||
echo Newest available version: $NEW
|
||||
|
@ -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,9 +5,9 @@
|
||||
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>
|
||||
Dominik Maier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
@ -42,6 +42,7 @@
|
||||
#include "debug.h"
|
||||
#include "alloc-inl.h"
|
||||
#include "hash.h"
|
||||
#include "valueprofile.h"
|
||||
#include "sharedmem.h"
|
||||
#include "forkserver.h"
|
||||
#include "common.h"
|
||||
@ -116,6 +117,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
|
||||
@ -124,6 +129,10 @@
|
||||
#define CASE_PREFIX "id_"
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
#define RECORD_PREFIX "RECORD:"
|
||||
#endif
|
||||
|
||||
#define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */
|
||||
|
||||
// Little helper to access the ptr to afl->##name_buf - for use in afl_realloc.
|
||||
@ -135,6 +144,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
|
||||
@ -198,7 +211,8 @@ struct queue_entry {
|
||||
u32 id; /* entry number in queue_buf */
|
||||
|
||||
u8 colorized, /* Do not run redqueen stage again */
|
||||
cal_failed; /* Calibration failed? */
|
||||
cal_failed, /* Calibration failed? */
|
||||
really_interesting; /* really has coverage (VP) */
|
||||
|
||||
bool trim_done, /* Trimmed? */
|
||||
was_fuzzed, /* historical, but needed for MOpt */
|
||||
@ -228,7 +242,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
|
||||
@ -238,13 +251,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;
|
||||
|
||||
};
|
||||
@ -440,15 +451,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,
|
||||
@ -644,7 +657,11 @@ typedef struct afl_state {
|
||||
longest_find_time, /* Longest time taken for a find */
|
||||
exit_on_time, /* Delay to exit if no new paths */
|
||||
sync_time, /* Sync time (ms) */
|
||||
switch_fuzz_mode; /* auto or fixed fuzz mode */
|
||||
switch_fuzz_mode, /* auto or fixed fuzz mode */
|
||||
calibration_time_us, /* Time spend on calibration */
|
||||
sync_time_us, /* Time spend on sync */
|
||||
cmplog_time_us, /* Time spend on cmplog */
|
||||
trim_time_us; /* Time spend on trimming */
|
||||
|
||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
subseq_tmouts; /* Number of timeouts in a row */
|
||||
@ -840,6 +857,8 @@ typedef struct afl_state {
|
||||
u32 bitsmap_size;
|
||||
#endif
|
||||
|
||||
u32 vp_ptr[VP_MAP_SIZE];
|
||||
|
||||
} afl_state_t;
|
||||
|
||||
struct custom_mutator {
|
||||
@ -1178,7 +1197,7 @@ void discover_word(u8 *ret, u32 *current, u32 *virgin);
|
||||
void init_count_class16(void);
|
||||
void minimize_bits(afl_state_t *, u8 *, u8 *);
|
||||
#ifndef SIMPLE_FILES
|
||||
u8 *describe_op(afl_state_t *, u8, size_t);
|
||||
u8 *describe_op(afl_state_t *, u8, size_t, u8);
|
||||
#endif
|
||||
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
||||
u8 has_new_bits(afl_state_t *, u8 *);
|
||||
@ -1211,6 +1230,11 @@ void show_stats_normal(afl_state_t *);
|
||||
void show_stats_pizza(afl_state_t *);
|
||||
void show_init_stats(afl_state_t *);
|
||||
|
||||
void update_calibration_time(afl_state_t *afl, u64 *time);
|
||||
void update_trim_time(afl_state_t *afl, u64 *time);
|
||||
void update_sync_time(afl_state_t *afl, u64 *time);
|
||||
void update_cmplog_time(afl_state_t *afl, u64 *time);
|
||||
|
||||
/* StatsD */
|
||||
|
||||
void statsd_setup_format(afl_state_t *afl);
|
||||
@ -1260,6 +1284,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);
|
||||
@ -1393,6 +1418,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
|
||||
|
@ -30,10 +30,17 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
#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};
|
||||
|
||||
enum {
|
||||
|
||||
/* 00 */ MUT_FLIPBIT,
|
||||
|
131
include/afl-persistent-replay.h
Normal file
131
include/afl-persistent-replay.h
Normal file
@ -0,0 +1,131 @@
|
||||
#ifndef _HAVE_PERSISTENT_REPLAY_H
|
||||
#define _HAVE_PERSISTENT_REPLAY_H
|
||||
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
static unsigned short int is_replay_record;
|
||||
static unsigned int replay_record;
|
||||
static unsigned int replay_record_cnt;
|
||||
static char replay_record_path[PATH_MAX];
|
||||
static char *replay_record_dir;
|
||||
static struct dirent **record_list;
|
||||
|
||||
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
static char **record_arg = NULL;
|
||||
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
|
||||
static int select_files(const struct dirent *dirbuf) {
|
||||
|
||||
char fn[PATH_MAX];
|
||||
|
||||
if (dirbuf->d_name[0] == '.') {
|
||||
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record);
|
||||
return !!strstr(dirbuf->d_name, fn);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int compare_files(const struct dirent **da, const struct dirent **db) {
|
||||
|
||||
unsigned int c1 = 0, c2 = 0;
|
||||
|
||||
sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1);
|
||||
sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2);
|
||||
|
||||
return c1 - c2;
|
||||
|
||||
}
|
||||
|
||||
__attribute__((destructor)) static void __afl_record_replay_destroy(void) {
|
||||
|
||||
for (int i = 0; i < replay_record_cnt; i++) {
|
||||
|
||||
free(record_list[i]);
|
||||
|
||||
}
|
||||
|
||||
free(record_list);
|
||||
|
||||
}
|
||||
|
||||
__attribute__((constructor)) static void __afl_record_replay_init(
|
||||
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
int argc, char **argv
|
||||
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
) {
|
||||
|
||||
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
char **argp;
|
||||
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
|
||||
struct stat sb;
|
||||
|
||||
/* caveat: if harness uses @@ and we don't pass it, it will regardless loop
|
||||
* the number of iterations defined for AFL_LOOP (on the same file)*/
|
||||
if (!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))) {
|
||||
|
||||
// printf("[warning] AFL_PERSISTENT_REPLAY not set.\n");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY"));
|
||||
replay_record_dir = getenv("AFL_PERSISTENT_DIR");
|
||||
|
||||
if (!(stat(replay_record_dir, &sb) == 0 && S_ISDIR(sb.st_mode))) {
|
||||
|
||||
fprintf(stderr, "[error] Can't find the requested record directory!\n");
|
||||
is_replay_record = 0;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./",
|
||||
&record_list, select_files, compare_files);
|
||||
|
||||
if (!replay_record_cnt) {
|
||||
|
||||
fprintf(stderr, "[error] Can't find the requested record!\n");
|
||||
is_replay_record = 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
argp = argv;
|
||||
while (*argp) {
|
||||
|
||||
if (!strcmp(*argp, "@@")) {
|
||||
|
||||
record_arg = argp;
|
||||
*record_arg = replay_record_path;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
++argp;
|
||||
|
||||
}
|
||||
|
||||
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
|
||||
}
|
||||
|
||||
#endif // _HAVE_PERSISTENT_REPLAY_H
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>
|
||||
|
||||
|
67
include/afl-record-compat.h
Normal file
67
include/afl-record-compat.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef _HAVE_AFL_COMPAT_H
|
||||
#define _HAVE_AFL_COMPAT_H
|
||||
|
||||
#include <afl-persistent-replay.h>
|
||||
|
||||
#define FUZZ_BUF_SIZE 1024000
|
||||
|
||||
// extern ssize_t read(int fildes, void *buf, size_t nbyte);
|
||||
|
||||
// extern int __afl_persistent_loop(unsigned int max_cnt);
|
||||
// extern unsigned char fuzz_buf[];
|
||||
|
||||
#ifndef __AFL_HAVE_MANUAL_CONTROL
|
||||
#define __AFL_HAVE_MANUAL_CONTROL
|
||||
#endif
|
||||
|
||||
#define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE))
|
||||
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
|
||||
#define __AFL_FUZZ_INIT() void sync(void);
|
||||
#define __AFL_INIT() sync()
|
||||
#define __AFL_LOOP(x) __afl_persistent_loop(x)
|
||||
|
||||
unsigned char fuzz_buf[FUZZ_BUF_SIZE];
|
||||
|
||||
int __afl_persistent_loop(unsigned int max_cnt) {
|
||||
|
||||
static unsigned int cycle_cnt = 1;
|
||||
static unsigned short int inited = 0;
|
||||
char tcase[PATH_MAX];
|
||||
|
||||
if (is_replay_record && cycle_cnt) {
|
||||
|
||||
if (!inited) {
|
||||
|
||||
cycle_cnt = replay_record_cnt;
|
||||
inited = 1;
|
||||
|
||||
}
|
||||
|
||||
snprintf(tcase, PATH_MAX, "%s/%s",
|
||||
replay_record_dir ? replay_record_dir : "./",
|
||||
record_list[replay_record_cnt - cycle_cnt]->d_name);
|
||||
|
||||
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
if (record_arg) {
|
||||
|
||||
*record_arg = tcase;
|
||||
|
||||
} else
|
||||
|
||||
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
{
|
||||
|
||||
int fd = open(tcase, O_RDONLY);
|
||||
dup2(fd, 0);
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cycle_cnt--;
|
||||
|
||||
}
|
||||
|
||||
#endif // _HAVE_AFL_COMPAT_H
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
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>
|
||||
|
||||
@ -38,36 +38,39 @@
|
||||
|
||||
#define SHAPE_BYTES(x) (x + 1)
|
||||
|
||||
#define CMP_TYPE_INS 1
|
||||
#define CMP_TYPE_RTN 2
|
||||
#define CMP_TYPE_INS 0
|
||||
#define CMP_TYPE_RTN 1
|
||||
|
||||
struct cmp_header {
|
||||
struct cmp_header { // 16 bit = 2 bytes
|
||||
|
||||
unsigned hits : 24;
|
||||
unsigned id : 24;
|
||||
unsigned shape : 5;
|
||||
unsigned type : 2;
|
||||
unsigned attribute : 4;
|
||||
unsigned overflow : 1;
|
||||
unsigned reserved : 4;
|
||||
unsigned hits : 6; // up to 63 entries, we have CMP_MAP_H = 32
|
||||
unsigned shape : 5; // 31+1 bytes max
|
||||
unsigned type : 1; // 2: cmp, rtn
|
||||
unsigned attribute : 4; // 16 for arithmetic comparison types
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
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 v1_256_0;
|
||||
u64 v1_256_1;
|
||||
u8 unused[8];
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cmpfn_operands {
|
||||
|
||||
u8 v0[31];
|
||||
u8 v0[32];
|
||||
u8 v1[32];
|
||||
u8 v0_len;
|
||||
u8 v1[31];
|
||||
u8 v1_len;
|
||||
u8 unused[6];
|
||||
|
||||
} __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.10c"
|
||||
#define VERSION "++4.22a"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -97,6 +97,11 @@
|
||||
|
||||
// #define AFL_PERSISTENT_RECORD
|
||||
|
||||
/* Adds support in compiler-rt to replay persistent records in @@-style
|
||||
* harnesses */
|
||||
|
||||
// #define AFL_PERSISTENT_REPLAY_ARGPARSE
|
||||
|
||||
/* console output colors: There are three ways to configure its behavior
|
||||
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
|
||||
* ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect
|
||||
@ -319,9 +324,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): */
|
||||
|
||||
@ -459,7 +464,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)); \
|
||||
|
@ -21,13 +21,15 @@ static char *afl_environment_variables[] = {
|
||||
"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_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
||||
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
||||
"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_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_TRIM",
|
||||
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
||||
"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",
|
||||
@ -38,8 +40,7 @@ static char *afl_environment_variables[] = {
|
||||
"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,7 +49,7 @@ 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_FUZZER_ARGS", // oss-fuzz
|
||||
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
|
||||
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
|
||||
@ -63,7 +64,10 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", "AFL_LD_PASSTHROUGH",
|
||||
"AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_ALLOWLIST",
|
||||
"AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG",
|
||||
"AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||
"AFL_LLVM_VALUEPROFILE", "AFL_LLVM_VALUE_PROFILE", "AFL_GCC_CMPLOG",
|
||||
"AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||
"AFL_LLVM_LTO_CALLER", "AFL_LLVM_LTO_CTX", "AFL_LLVM_LTO_CALLER_DEPTH",
|
||||
"AFL_LLVM_LTO_CTX_DEPTH", "AFL_LLVM_CALLER_DEPTH", "AFL_LLVM_CTX_DEPTH",
|
||||
"AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN",
|
||||
"AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT",
|
||||
"AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
|
||||
@ -78,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",
|
||||
@ -93,27 +96,28 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_MAX_DET_EXTRAS",
|
||||
"AFL_NO_X86", // not really an env but we dont want to warn on it
|
||||
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
|
||||
"AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH",
|
||||
"AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD",
|
||||
"AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV",
|
||||
"AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV",
|
||||
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
|
||||
"AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR",
|
||||
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR",
|
||||
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM",
|
||||
"AFL_QEMU_PERSISTENT_RET", "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_NYX_HANDLE_INVALID_WRITE", "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT",
|
||||
"AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE",
|
||||
"AFL_PERSISTENT_RECORD", "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD",
|
||||
"AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN",
|
||||
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS",
|
||||
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL",
|
||||
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
|
||||
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
|
||||
"AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET",
|
||||
"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_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_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",
|
||||
"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>>
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "valueprofile.h"
|
||||
|
||||
#ifdef __linux__
|
||||
/**
|
||||
@ -89,11 +90,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 {
|
||||
@ -179,7 +183,8 @@ typedef struct afl_forkserver {
|
||||
/* Function to kick off the forkserver child */
|
||||
void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
|
||||
|
||||
u8 *afl_ptr; /* for autodictionary: afl ptr */
|
||||
u8 *afl_ptr; /* for autodictionary: afl ptr */
|
||||
u32 *vp_map_control;
|
||||
|
||||
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
|
||||
|
||||
@ -188,6 +193,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 +209,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 +247,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>
|
||||
|
||||
@ -52,7 +52,9 @@ typedef struct sharedmem {
|
||||
|
||||
int cmplog_mode;
|
||||
int shmemfuzz_mode;
|
||||
int vp_mode;
|
||||
struct cmp_map *cmp_map;
|
||||
struct vp_map *vp_map;
|
||||
|
||||
} sharedmem_t;
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
738
include/t1ha.h
Normal file
738
include/t1ha.h
Normal file
@ -0,0 +1,738 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
|
||||
* Fast Positive Hash.
|
||||
*
|
||||
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
|
||||
* The 1Hippeus project (t1h).
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgement in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
|
||||
* by [Positive Technologies](https://www.ptsecurity.ru)
|
||||
*
|
||||
* Briefly, it is a 64-bit Hash Function:
|
||||
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
|
||||
* but portable and without penalties it can run on any 64-bit CPU.
|
||||
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
|
||||
* and all others portable hash-functions (which do not use specific
|
||||
* hardware tricks).
|
||||
* 3. Not suitable for cryptography.
|
||||
*
|
||||
* The Future will (be) Positive. Всё будет хорошо.
|
||||
*
|
||||
* ACKNOWLEDGEMENT:
|
||||
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
|
||||
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* PLEASE PAY ATTENTION TO THE FOLLOWING NOTES
|
||||
* about macros definitions which controls t1ha behaviour and/or performance.
|
||||
*
|
||||
*
|
||||
* 1) T1HA_SYS_UNALIGNED_ACCESS = Defines the system/platform/CPU/architecture
|
||||
* abilities for unaligned data access.
|
||||
*
|
||||
* By default, when the T1HA_SYS_UNALIGNED_ACCESS not defined,
|
||||
* it will defined on the basis hardcoded knowledge about of capabilities
|
||||
* of most common CPU architectures. But you could override this
|
||||
* default behavior when build t1ha library itself:
|
||||
*
|
||||
* // To disable unaligned access at all.
|
||||
* #define T1HA_SYS_UNALIGNED_ACCESS 0
|
||||
*
|
||||
* // To enable unaligned access, but indicate that it significantly slow.
|
||||
* #define T1HA_SYS_UNALIGNED_ACCESS 1
|
||||
*
|
||||
* // To enable unaligned access, and indicate that it effecient.
|
||||
* #define T1HA_SYS_UNALIGNED_ACCESS 2
|
||||
*
|
||||
*
|
||||
* 2) T1HA_USE_FAST_ONESHOT_READ = Controls the data reads at the end of buffer.
|
||||
*
|
||||
* When defined to non-zero, t1ha will use 'one shot' method for reading
|
||||
* up to 8 bytes at the end of data. In this case just the one 64-bit read
|
||||
* will be performed even when the available less than 8 bytes.
|
||||
*
|
||||
* This is little bit faster that switching by length of data tail.
|
||||
* Unfortunately this will triggering a false-positive alarms from Valgrind,
|
||||
* AddressSanitizer and other similar tool.
|
||||
*
|
||||
* By default, t1ha defines it to 1, but you could override this
|
||||
* default behavior when build t1ha library itself:
|
||||
*
|
||||
* // For little bit faster and small code.
|
||||
* #define T1HA_USE_FAST_ONESHOT_READ 1
|
||||
*
|
||||
* // For calmness if doubt.
|
||||
* #define T1HA_USE_FAST_ONESHOT_READ 0
|
||||
*
|
||||
*
|
||||
* 3) T1HA0_RUNTIME_SELECT = Controls choice fastest function in runtime.
|
||||
*
|
||||
* t1ha library offers the t1ha0() function as the fastest for current CPU.
|
||||
* But actual CPU's features/capabilities and may be significantly different,
|
||||
* especially on x86 platform. Therefore, internally, t1ha0() may require
|
||||
* dynamic dispatching for choice best implementation.
|
||||
*
|
||||
* By default, t1ha enables such runtime choice and (may be) corresponding
|
||||
* indirect calls if it reasonable, but you could override this default
|
||||
* behavior when build t1ha library itself:
|
||||
*
|
||||
* // To enable runtime choice of fastest implementation.
|
||||
* #define T1HA0_RUNTIME_SELECT 1
|
||||
*
|
||||
* // To disable runtime choice of fastest implementation.
|
||||
* #define T1HA0_RUNTIME_SELECT 0
|
||||
*
|
||||
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
|
||||
* be used to get actual t1ha0() implementation address at runtime. This is
|
||||
* useful for two cases:
|
||||
* - calling by local pointer-to-function usually is little
|
||||
* bit faster (less overhead) than via a PLT thru the DSO boundary.
|
||||
* - GNU Indirect functions (see below) don't supported by environment
|
||||
* and calling by t1ha0_funcptr is not available and/or expensive.
|
||||
*
|
||||
* 4) T1HA_USE_INDIRECT_FUNCTIONS = Controls usage of GNU Indirect functions.
|
||||
*
|
||||
* In continue of T1HA0_RUNTIME_SELECT the T1HA_USE_INDIRECT_FUNCTIONS
|
||||
* controls usage of ELF indirect functions feature. In general, when
|
||||
* available, this reduces overhead of indirect function's calls though
|
||||
* a DSO-bundary (https://sourceware.org/glibc/wiki/GNU_IFUNC).
|
||||
*
|
||||
* By default, t1ha engage GNU Indirect functions when it available
|
||||
* and useful, but you could override this default behavior when build
|
||||
* t1ha library itself:
|
||||
*
|
||||
* // To enable use of GNU ELF Indirect functions.
|
||||
* #define T1HA_USE_INDIRECT_FUNCTIONS 1
|
||||
*
|
||||
* // To disable use of GNU ELF Indirect functions. This may be useful
|
||||
* // if the actual toolchain or the system's loader don't support ones.
|
||||
* #define T1HA_USE_INDIRECT_FUNCTIONS 0
|
||||
*
|
||||
* 5) T1HA0_AESNI_AVAILABLE = Controls AES-NI detection and dispatching on x86.
|
||||
*
|
||||
* In continue of T1HA0_RUNTIME_SELECT the T1HA0_AESNI_AVAILABLE controls
|
||||
* detection and usage of AES-NI CPU's feature. On the other hand, this
|
||||
* requires compiling parts of t1ha library with certain properly options,
|
||||
* and could be difficult or inconvenient in some cases.
|
||||
*
|
||||
* By default, t1ha engade AES-NI for t1ha0() on the x86 platform, but
|
||||
* you could override this default behavior when build t1ha library itself:
|
||||
*
|
||||
* // To disable detection and usage of AES-NI instructions for t1ha0().
|
||||
* // This may be useful when you unable to build t1ha library properly
|
||||
* // or known that AES-NI will be unavailable at the deploy.
|
||||
* #define T1HA0_AESNI_AVAILABLE 0
|
||||
*
|
||||
* // To force detection and usage of AES-NI instructions for t1ha0(),
|
||||
* // but I don't known reasons to anybody would need this.
|
||||
* #define T1HA0_AESNI_AVAILABLE 1
|
||||
*
|
||||
* 6) T1HA0_DISABLED, T1HA1_DISABLED, T1HA2_DISABLED = Controls availability of
|
||||
* t1ha functions.
|
||||
*
|
||||
* In some cases could be useful to import/use only few of t1ha functions
|
||||
* or just the one. So, this definitions allows disable corresponding parts
|
||||
* of t1ha library.
|
||||
*
|
||||
* // To disable t1ha0(), t1ha0_32le(), t1ha0_32be() and all AES-NI.
|
||||
* #define T1HA0_DISABLED
|
||||
*
|
||||
* // To disable t1ha1_le() and t1ha1_be().
|
||||
* #define T1HA1_DISABLED
|
||||
*
|
||||
* // To disable t1ha2_atonce(), t1ha2_atonce128() and so on.
|
||||
* #define T1HA2_DISABLED
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define T1HA_VERSION_MAJOR 2
|
||||
#define T1HA_VERSION_MINOR 1
|
||||
#define T1HA_VERSION_RELEASE 1
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) (0)
|
||||
#endif
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(x) (0)
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC_PREREQ
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
#define __GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
#define __GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
#endif /* __GNUC_PREREQ */
|
||||
|
||||
#ifndef __CLANG_PREREQ
|
||||
#ifdef __clang__
|
||||
#define __CLANG_PREREQ(maj, min) \
|
||||
((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
#define __CLANG_PREREQ(maj, min) (0)
|
||||
#endif
|
||||
#endif /* __CLANG_PREREQ */
|
||||
|
||||
#ifndef __LCC_PREREQ
|
||||
#ifdef __LCC__
|
||||
#define __LCC_PREREQ(maj, min) \
|
||||
((__LCC__ << 16) + __LCC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
#define __LCC_PREREQ(maj, min) (0)
|
||||
#endif
|
||||
#endif /* __LCC_PREREQ */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Avoid '16' bytes padding added after data member 't1ha_context::total'
|
||||
* and other warnings from std-headers if warning-level > 3. */
|
||||
#pragma warning(push, 3)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \
|
||||
defined(i486) || defined(__i486) || defined(__i486__) || \
|
||||
defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \
|
||||
defined(__i686) || defined(__i686__) || defined(_M_IX86) || \
|
||||
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
|
||||
defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \
|
||||
defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__)
|
||||
#ifndef __ia32__
|
||||
/* LY: define neutral __ia32__ for x86 and x86-64 archs */
|
||||
#define __ia32__ 1
|
||||
#endif /* __ia32__ */
|
||||
#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(__amd64) || defined(_M_X64))
|
||||
/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */
|
||||
#define __amd64__ 1
|
||||
#endif /* __amd64__ */
|
||||
#endif /* all x86 */
|
||||
|
||||
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
|
||||
!defined(__ORDER_BIG_ENDIAN__)
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
/* clang-format off */
|
||||
|
||||
#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \
|
||||
defined(HAVE_ENDIAN_H) || __has_include(<endian.h>)
|
||||
#include <endian.h>
|
||||
#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \
|
||||
defined(HAVE_MACHINE_ENDIAN_H) || __has_include(<machine/endian.h>)
|
||||
#include <machine/endian.h>
|
||||
#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include(<sys/isa_defs.h>)
|
||||
#include <sys/isa_defs.h>
|
||||
#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \
|
||||
(__has_include(<sys/types.h>) && __has_include(<sys/endian.h>))
|
||||
#include <sys/endian.h>
|
||||
#include <sys/types.h>
|
||||
#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
|
||||
defined(__NETBSD__) || defined(__NetBSD__) || \
|
||||
defined(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>)
|
||||
#include <sys/param.h>
|
||||
#endif /* OS */
|
||||
|
||||
/* *INDENT-ON* */
|
||||
/* clang-format on */
|
||||
|
||||
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
|
||||
#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
|
||||
#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
|
||||
#define __BYTE_ORDER__ __BYTE_ORDER
|
||||
#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
|
||||
#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN
|
||||
#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN
|
||||
#define __BYTE_ORDER__ _BYTE_ORDER
|
||||
#else
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__) || \
|
||||
(defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
|
||||
defined(__ARMEL__) || defined(__THUMBEL__) || \
|
||||
defined(__AARCH64EL__) || defined(__MIPSEL__) || defined(_MIPSEL) || \
|
||||
defined(__MIPSEL) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__e2k__) || defined(__elbrus_4c__) || \
|
||||
defined(__elbrus_8c__) || defined(__bfin__) || defined(__BFIN__) || \
|
||||
defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \
|
||||
defined(__ia64) || defined(_M_IA64) || defined(__itanium__) || \
|
||||
defined(__ia32__) || defined(__CYGWIN__) || defined(_WIN64) || \
|
||||
defined(_WIN32) || defined(__TOS_WIN__) || defined(__WINDOWS__)
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
|
||||
#elif defined(__BIG_ENDIAN__) || \
|
||||
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
|
||||
defined(__ARMEB__) || defined(__THUMBEB__) || \
|
||||
defined(__AARCH64EB__) || defined(__MIPSEB__) || defined(_MIPSEB) || \
|
||||
defined(__MIPSEB) || defined(__m68k__) || defined(M68000) || \
|
||||
defined(__hppa__) || defined(__hppa) || defined(__HPPA__) || \
|
||||
defined(__sparc__) || defined(__sparc) || defined(__370__) || \
|
||||
defined(__THW_370__) || defined(__s390__) || defined(__s390x__) || \
|
||||
defined(__SYSC_ZARCH__)
|
||||
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
|
||||
|
||||
#else
|
||||
#error __BYTE_ORDER__ should be defined.
|
||||
#endif /* Arch */
|
||||
|
||||
#endif
|
||||
#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dll_export
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
||||
#if defined(__GNUC__) || __has_attribute(dllexport)
|
||||
#define __dll_export __attribute__((dllexport))
|
||||
#else
|
||||
#define __dll_export __declspec(dllexport)
|
||||
#endif
|
||||
#elif defined(__GNUC__) || __has_attribute(__visibility__)
|
||||
#define __dll_export __attribute__((__visibility__("default")))
|
||||
#else
|
||||
#define __dll_export
|
||||
#endif
|
||||
#endif /* __dll_export */
|
||||
|
||||
#ifndef __dll_import
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
||||
#if defined(__GNUC__) || __has_attribute(dllimport)
|
||||
#define __dll_import __attribute__((dllimport))
|
||||
#else
|
||||
#define __dll_import __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__GNUC__) || __has_attribute(__visibility__)
|
||||
#define __dll_import __attribute__((__visibility__("default")))
|
||||
#else
|
||||
#define __dll_import
|
||||
#endif
|
||||
#endif /* __dll_import */
|
||||
|
||||
#ifndef __force_inline
|
||||
#ifdef _MSC_VER
|
||||
#define __force_inline __forceinline
|
||||
#elif __GNUC_PREREQ(3, 2) || __has_attribute(__always_inline__)
|
||||
#define __force_inline __inline __attribute__((__always_inline__))
|
||||
#else
|
||||
#define __force_inline __inline
|
||||
#endif
|
||||
#endif /* __force_inline */
|
||||
|
||||
#ifndef T1HA_API
|
||||
#if defined(t1ha_EXPORTS)
|
||||
#define T1HA_API __dll_export
|
||||
#elif defined(t1ha_IMPORTS)
|
||||
#define T1HA_API __dll_import
|
||||
#else
|
||||
#define T1HA_API
|
||||
#endif
|
||||
#endif /* T1HA_API */
|
||||
|
||||
#if defined(_MSC_VER) && defined(__ia32__)
|
||||
#define T1HA_ALIGN_PREFIX __declspec(align(32)) /* required only for SIMD */
|
||||
#else
|
||||
#define T1HA_ALIGN_PREFIX
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#if defined(__GNUC__) && defined(__ia32__)
|
||||
#define T1HA_ALIGN_SUFFIX \
|
||||
__attribute__((__aligned__(32))) /* required only for SIMD */
|
||||
#else
|
||||
#define T1HA_ALIGN_SUFFIX
|
||||
#endif /* GCC x86 */
|
||||
|
||||
#ifndef T1HA_USE_INDIRECT_FUNCTIONS
|
||||
/* GNU ELF indirect functions usage control. For more info please see
|
||||
* https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
* and https://sourceware.org/glibc/wiki/GNU_IFUNC */
|
||||
#if defined(__ELF__) && defined(__amd64__) && \
|
||||
(__has_attribute(__ifunc__) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && \
|
||||
!defined(__SANITIZE_ADDRESS__) && !defined(__SSP_ALL__)))
|
||||
/* Enable gnu_indirect_function by default if :
|
||||
* - ELF AND x86_64
|
||||
* - attribute(__ifunc__) is available OR
|
||||
* GCC >= 4 WITHOUT -fsanitize=address NOR -fstack-protector-all */
|
||||
#define T1HA_USE_INDIRECT_FUNCTIONS 1
|
||||
#else
|
||||
#define T1HA_USE_INDIRECT_FUNCTIONS 0
|
||||
#endif
|
||||
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
|
||||
|
||||
#if __GNUC_PREREQ(4, 0)
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif /* __GNUC_PREREQ(4,0) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
typedef union T1HA_ALIGN_PREFIX t1ha_state256 {
|
||||
|
||||
uint8_t bytes[32];
|
||||
uint32_t u32[8];
|
||||
uint64_t u64[4];
|
||||
struct {
|
||||
|
||||
uint64_t a, b, c, d;
|
||||
|
||||
} n;
|
||||
|
||||
} t1ha_state256_t T1HA_ALIGN_SUFFIX;
|
||||
|
||||
typedef struct t1ha_context {
|
||||
|
||||
t1ha_state256_t state;
|
||||
t1ha_state256_t buffer;
|
||||
size_t partial;
|
||||
uint64_t total;
|
||||
|
||||
} t1ha_context_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Self-testing API.
|
||||
*
|
||||
* Unfortunately, some compilers (exactly only Microsoft Visual C/C++) has
|
||||
* a bugs which leads t1ha-functions to produce wrong results. This API allows
|
||||
* check the correctness of the actual code in runtime.
|
||||
*
|
||||
* All check-functions returns 0 on success, or -1 in case the corresponding
|
||||
* hash-function failed verification. PLEASE, always perform such checking at
|
||||
* initialization of your code, if you using MSVC or other troubleful compilers.
|
||||
*/
|
||||
|
||||
T1HA_API int t1ha_selfcheck__all_enabled(void);
|
||||
|
||||
#ifndef T1HA2_DISABLED
|
||||
T1HA_API int t1ha_selfcheck__t1ha2_atonce(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha2_atonce128(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha2_stream(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha2(void);
|
||||
#endif /* T1HA2_DISABLED */
|
||||
|
||||
#ifndef T1HA1_DISABLED
|
||||
T1HA_API int t1ha_selfcheck__t1ha1_le(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha1_be(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha1(void);
|
||||
#endif /* T1HA1_DISABLED */
|
||||
|
||||
#ifndef T1HA0_DISABLED
|
||||
T1HA_API int t1ha_selfcheck__t1ha0_32le(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha0_32be(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha0(void);
|
||||
|
||||
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
|
||||
#ifndef T1HA0_AESNI_AVAILABLE
|
||||
#if defined(__e2k__) || \
|
||||
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
|
||||
#define T1HA0_AESNI_AVAILABLE 1
|
||||
#else
|
||||
#define T1HA0_AESNI_AVAILABLE 0
|
||||
#endif
|
||||
#endif /* ifndef T1HA0_AESNI_AVAILABLE */
|
||||
|
||||
#if T1HA0_AESNI_AVAILABLE
|
||||
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_noavx(void);
|
||||
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx(void);
|
||||
#ifndef __e2k__
|
||||
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx2(void);
|
||||
#endif
|
||||
#endif /* if T1HA0_AESNI_AVAILABLE */
|
||||
#endif /* T1HA0_DISABLED */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* t1ha2 = 64 and 128-bit, SLIGHTLY MORE ATTENTION FOR QUALITY AND STRENGTH.
|
||||
*
|
||||
* - The recommended version of "Fast Positive Hash" with good quality
|
||||
* for checksum, hash tables and fingerprinting.
|
||||
* - Portable and extremely efficiency on modern 64-bit CPUs.
|
||||
* Designed for 64-bit little-endian platforms,
|
||||
* in other cases will runs slowly.
|
||||
* - Great quality of hashing and still faster than other non-t1ha hashes.
|
||||
* Provides streaming mode and 128-bit result.
|
||||
*
|
||||
* Note: Due performance reason 64- and 128-bit results are completely
|
||||
* different each other, i.e. 64-bit result is NOT any part of 128-bit.
|
||||
*/
|
||||
#ifndef T1HA2_DISABLED
|
||||
|
||||
/* The at-once variant with 64-bit result */
|
||||
T1HA_API uint64_t t1ha2_atonce(const void *data, size_t length, uint64_t seed);
|
||||
|
||||
/* The at-once variant with 128-bit result.
|
||||
* Argument `extra_result` is NOT optional and MUST be valid.
|
||||
* The high 64-bit part of 128-bit hash will be always unconditionally
|
||||
* stored to the address given by `extra_result` argument. */
|
||||
T1HA_API uint64_t t1ha2_atonce128(uint64_t *__restrict extra_result,
|
||||
const void *__restrict data, size_t length,
|
||||
uint64_t seed);
|
||||
|
||||
/* The init/update/final trinity for streaming.
|
||||
* Return 64 or 128-bit result depentently from `extra_result` argument. */
|
||||
T1HA_API void t1ha2_init(t1ha_context_t *ctx, uint64_t seed_x, uint64_t seed_y);
|
||||
T1HA_API void t1ha2_update(t1ha_context_t *__restrict ctx,
|
||||
const void *__restrict data, size_t length);
|
||||
|
||||
/* Argument `extra_result` is optional and MAY be NULL.
|
||||
* - If `extra_result` is NOT NULL then the 128-bit hash will be calculated,
|
||||
* and high 64-bit part of it will be stored to the address given
|
||||
* by `extra_result` argument.
|
||||
* - Otherwise the 64-bit hash will be calculated
|
||||
* and returned from function directly.
|
||||
*
|
||||
* Note: Due performance reason 64- and 128-bit results are completely
|
||||
* different each other, i.e. 64-bit result is NOT any part of 128-bit. */
|
||||
T1HA_API uint64_t t1ha2_final(t1ha_context_t *__restrict ctx,
|
||||
uint64_t *__restrict extra_result /* optional */);
|
||||
|
||||
#endif /* T1HA2_DISABLED */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* t1ha1 = 64-bit, BASELINE FAST PORTABLE HASH:
|
||||
*
|
||||
* - Runs faster on 64-bit platforms in other cases may runs slowly.
|
||||
* - Portable and stable, returns same 64-bit result
|
||||
* on all architectures and CPUs.
|
||||
* - Unfortunately it fails the "strict avalanche criteria",
|
||||
* see test results at https://github.com/demerphq/smhasher.
|
||||
*
|
||||
* This flaw is insignificant for the t1ha1() purposes and imperceptible
|
||||
* from a practical point of view.
|
||||
* However, nowadays this issue has resolved in the next t1ha2(),
|
||||
* that was initially planned to providing a bit more quality.
|
||||
*/
|
||||
#ifndef T1HA1_DISABLED
|
||||
|
||||
/* The little-endian variant. */
|
||||
T1HA_API uint64_t t1ha1_le(const void *data, size_t length, uint64_t seed);
|
||||
|
||||
/* The big-endian variant. */
|
||||
T1HA_API uint64_t t1ha1_be(const void *data, size_t length, uint64_t seed);
|
||||
|
||||
#endif /* T1HA1_DISABLED */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* t1ha0 = 64-bit, JUST ONLY FASTER:
|
||||
*
|
||||
* - Provides fast-as-possible hashing for current CPU, including
|
||||
* 32-bit systems and engaging the available hardware acceleration.
|
||||
* - It is a facade that selects most quick-and-dirty hash
|
||||
* for the current processor. For instance, on IA32 (x86) actual function
|
||||
* will be selected in runtime, depending on current CPU capabilities
|
||||
*
|
||||
* BE CAREFUL!!! THIS IS MEANS:
|
||||
*
|
||||
* 1. The quality of hash is a subject for tradeoffs with performance.
|
||||
* So, the quality and strength of t1ha0() may be lower than t1ha1(),
|
||||
* especially on 32-bit targets, but then much faster.
|
||||
* However, guaranteed that it passes all SMHasher tests.
|
||||
*
|
||||
* 2. No warranty that the hash result will be same for particular
|
||||
* key on another machine or another version of libt1ha.
|
||||
*
|
||||
* Briefly, such hash-results and their derivatives, should be
|
||||
* used only in runtime, but should not be persist or transferred
|
||||
* over a network.
|
||||
*
|
||||
*
|
||||
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
|
||||
* be used to get actual t1ha0() implementation address at runtime. This is
|
||||
* useful for two cases:
|
||||
* - calling by local pointer-to-function usually is little
|
||||
* bit faster (less overhead) than via a PLT thru the DSO boundary.
|
||||
* - GNU Indirect functions (see below) don't supported by environment
|
||||
* and calling by t1ha0_funcptr is not available and/or expensive.
|
||||
*/
|
||||
|
||||
#ifndef T1HA0_DISABLED
|
||||
|
||||
/* The little-endian variant for 32-bit CPU. */
|
||||
uint64_t t1ha0_32le(const void *data, size_t length, uint64_t seed);
|
||||
/* The big-endian variant for 32-bit CPU. */
|
||||
uint64_t t1ha0_32be(const void *data, size_t length, uint64_t seed);
|
||||
|
||||
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
|
||||
#ifndef T1HA0_AESNI_AVAILABLE
|
||||
#if defined(__e2k__) || \
|
||||
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
|
||||
#define T1HA0_AESNI_AVAILABLE 1
|
||||
#else
|
||||
#define T1HA0_AESNI_AVAILABLE 0
|
||||
#endif
|
||||
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||
|
||||
/* Define T1HA0_RUNTIME_SELECT to 0 for disable dispatching t1ha0 at runtime.
|
||||
*/
|
||||
#ifndef T1HA0_RUNTIME_SELECT
|
||||
#if T1HA0_AESNI_AVAILABLE && !defined(__e2k__)
|
||||
#define T1HA0_RUNTIME_SELECT 1
|
||||
#else
|
||||
#define T1HA0_RUNTIME_SELECT 0
|
||||
#endif
|
||||
#endif /* T1HA0_RUNTIME_SELECT */
|
||||
|
||||
#if !T1HA0_RUNTIME_SELECT && !defined(T1HA0_USE_DEFINE)
|
||||
#if defined(__LCC__)
|
||||
#define T1HA0_USE_DEFINE 1
|
||||
#else
|
||||
#define T1HA0_USE_DEFINE 0
|
||||
#endif
|
||||
#endif /* T1HA0_USE_DEFINE */
|
||||
|
||||
#if T1HA0_AESNI_AVAILABLE
|
||||
uint64_t t1ha0_ia32aes_noavx(const void *data, size_t length, uint64_t seed);
|
||||
uint64_t t1ha0_ia32aes_avx(const void *data, size_t length, uint64_t seed);
|
||||
#ifndef __e2k__
|
||||
uint64_t t1ha0_ia32aes_avx2(const void *data, size_t length, uint64_t seed);
|
||||
#endif
|
||||
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||
|
||||
#if T1HA0_RUNTIME_SELECT
|
||||
typedef uint64_t (*t1ha0_function_t)(const void *, size_t, uint64_t);
|
||||
T1HA_API t1ha0_function_t t1ha0_resolve(void);
|
||||
#if T1HA_USE_INDIRECT_FUNCTIONS
|
||||
T1HA_API uint64_t t1ha0(const void *data, size_t length, uint64_t seed);
|
||||
#else
|
||||
/* Otherwise function pointer will be used.
|
||||
* Unfortunately this may cause some overhead calling. */
|
||||
T1HA_API extern uint64_t (*t1ha0_funcptr)(const void *data, size_t length,
|
||||
uint64_t seed);
|
||||
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||
uint64_t seed) {
|
||||
|
||||
return t1ha0_funcptr(data, length, seed);
|
||||
|
||||
}
|
||||
|
||||
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
|
||||
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
|
||||
#if T1HA0_USE_DEFINE
|
||||
|
||||
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||
#if defined(T1HA1_DISABLED)
|
||||
#define t1ha0 t1ha2_atonce
|
||||
#else
|
||||
#define t1ha0 t1ha1_be
|
||||
#endif /* T1HA1_DISABLED */
|
||||
#else /* 32/64 */
|
||||
#define t1ha0 t1ha0_32be
|
||||
#endif /* 32/64 */
|
||||
|
||||
#else /* T1HA0_USE_DEFINE */
|
||||
|
||||
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||
uint64_t seed) {
|
||||
|
||||
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||
#if defined(T1HA1_DISABLED)
|
||||
return t1ha2_atonce(data, length, seed);
|
||||
#else
|
||||
return t1ha1_be(data, length, seed);
|
||||
#endif /* T1HA1_DISABLED */
|
||||
#else /* 32/64 */
|
||||
return t1ha0_32be(data, length, seed);
|
||||
#endif /* 32/64 */
|
||||
|
||||
}
|
||||
|
||||
#endif /* !T1HA0_USE_DEFINE */
|
||||
|
||||
#else /* !T1HA0_RUNTIME_SELECT && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
|
||||
|
||||
#if T1HA0_USE_DEFINE
|
||||
|
||||
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||
#if defined(T1HA1_DISABLED)
|
||||
#define t1ha0 t1ha2_atonce
|
||||
#else
|
||||
#define t1ha0 t1ha1_le
|
||||
#endif /* T1HA1_DISABLED */
|
||||
#else /* 32/64 */
|
||||
#define t1ha0 t1ha0_32le
|
||||
#endif /* 32/64 */
|
||||
|
||||
#else
|
||||
|
||||
static __force_inline uint64_t t1ha0(const void *data, size_t length,
|
||||
uint64_t seed) {
|
||||
|
||||
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
|
||||
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
|
||||
#if defined(T1HA1_DISABLED)
|
||||
return t1ha2_atonce(data, length, seed);
|
||||
#else
|
||||
return t1ha1_le(data, length, seed);
|
||||
#endif /* T1HA1_DISABLED */
|
||||
#else /* 32/64 */
|
||||
return t1ha0_32le(data, length, seed);
|
||||
#endif /* 32/64 */
|
||||
|
||||
}
|
||||
|
||||
#endif /* !T1HA0_USE_DEFINE */
|
||||
|
||||
#endif /* !T1HA0_RUNTIME_SELECT */
|
||||
|
||||
#endif /* T1HA0_DISABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __GNUC_PREREQ(4, 0)
|
||||
#pragma GCC visibility pop
|
||||
#endif /* __GNUC_PREREQ(4,0) */
|
||||
|
183
include/t1ha0_ia32aes_b.h
Normal file
183
include/t1ha0_ia32aes_b.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
|
||||
* Fast Positive Hash.
|
||||
*
|
||||
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
|
||||
* The 1Hippeus project (t1h).
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgement in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
|
||||
* by [Positive Technologies](https://www.ptsecurity.ru)
|
||||
*
|
||||
* Briefly, it is a 64-bit Hash Function:
|
||||
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
|
||||
* but portable and without penalties it can run on any 64-bit CPU.
|
||||
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
|
||||
* and all others portable hash-functions (which do not use specific
|
||||
* hardware tricks).
|
||||
* 3. Not suitable for cryptography.
|
||||
*
|
||||
* The Future will (be) Positive. Всё будет хорошо.
|
||||
*
|
||||
* ACKNOWLEDGEMENT:
|
||||
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
|
||||
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
|
||||
*/
|
||||
|
||||
#include "t1ha_bits.h"
|
||||
#include "t1ha_selfcheck.h"
|
||||
|
||||
#if T1HA0_AESNI_AVAILABLE
|
||||
|
||||
uint64_t T1HA_IA32AES_NAME(const void *data, uint32_t len) {
|
||||
|
||||
uint64_t a = 0;
|
||||
uint64_t b = len;
|
||||
|
||||
if (likely(len > 32)) {
|
||||
|
||||
__m128i x = _mm_set_epi64x(a, b);
|
||||
__m128i y = _mm_aesenc_si128(x, _mm_set_epi64x(prime_0, prime_1));
|
||||
|
||||
const __m128i *v = (const __m128i *)data;
|
||||
const __m128i *const detent =
|
||||
(const __m128i *)((const uint8_t *)data + (len & ~15ul));
|
||||
data = detent;
|
||||
|
||||
if (len & 16) {
|
||||
|
||||
x = _mm_add_epi64(x, _mm_loadu_si128(v++));
|
||||
y = _mm_aesenc_si128(x, y);
|
||||
|
||||
}
|
||||
|
||||
len &= 15;
|
||||
|
||||
if (v + 7 < detent) {
|
||||
|
||||
__m128i salt = y;
|
||||
do {
|
||||
|
||||
__m128i t = _mm_aesenc_si128(_mm_loadu_si128(v++), salt);
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
|
||||
|
||||
salt = _mm_add_epi64(salt, _mm_set_epi64x(prime_5, prime_6));
|
||||
t = _mm_aesenc_si128(x, t);
|
||||
x = _mm_add_epi64(y, x);
|
||||
y = t;
|
||||
|
||||
} while (v + 7 < detent);
|
||||
|
||||
}
|
||||
|
||||
while (v < detent) {
|
||||
|
||||
__m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++));
|
||||
__m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++));
|
||||
x = _mm_aesdec_si128(x, v0y);
|
||||
y = _mm_aesdec_si128(y, v1x);
|
||||
|
||||
}
|
||||
|
||||
x = _mm_add_epi64(_mm_aesdec_si128(x, _mm_aesenc_si128(y, x)), y);
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#if defined(__SSE4_1__) || defined(__AVX__)
|
||||
a = _mm_extract_epi64(x, 0);
|
||||
b = _mm_extract_epi64(x, 1);
|
||||
#else
|
||||
a = _mm_cvtsi128_si64(x);
|
||||
b = _mm_cvtsi128_si64(_mm_unpackhi_epi64(x, x));
|
||||
#endif
|
||||
#else
|
||||
#if defined(__SSE4_1__) || defined(__AVX__)
|
||||
a = (uint32_t)_mm_extract_epi32(x, 0) | (uint64_t)_mm_extract_epi32(x, 1)
|
||||
<< 32;
|
||||
b = (uint32_t)_mm_extract_epi32(x, 2) | (uint64_t)_mm_extract_epi32(x, 3)
|
||||
<< 32;
|
||||
#else
|
||||
a = (uint32_t)_mm_cvtsi128_si32(x);
|
||||
a |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
|
||||
x = _mm_unpackhi_epi64(x, x);
|
||||
b = (uint32_t)_mm_cvtsi128_si32(x);
|
||||
b |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __AVX__
|
||||
_mm256_zeroupper();
|
||||
#elif !(defined(_X86_64_) || defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(__e2k__))
|
||||
_mm_empty();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
const uint64_t *v = (const uint64_t *)data;
|
||||
switch (len) {
|
||||
|
||||
default:
|
||||
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_4);
|
||||
/* fall through */
|
||||
case 24:
|
||||
case 23:
|
||||
case 22:
|
||||
case 21:
|
||||
case 20:
|
||||
case 19:
|
||||
case 18:
|
||||
case 17:
|
||||
mixup64(&b, &a, fetch64_le_unaligned(v++), prime_3);
|
||||
/* fall through */
|
||||
case 16:
|
||||
case 15:
|
||||
case 14:
|
||||
case 13:
|
||||
case 12:
|
||||
case 11:
|
||||
case 10:
|
||||
case 9:
|
||||
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_2);
|
||||
/* fall through */
|
||||
case 8:
|
||||
case 7:
|
||||
case 6:
|
||||
case 5:
|
||||
case 4:
|
||||
case 3:
|
||||
case 2:
|
||||
case 1:
|
||||
mixup64(&b, &a, tail64_le_unaligned(v, len), prime_1);
|
||||
/* fall through */
|
||||
case 0:
|
||||
return final64(a, b);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* T1HA0_AESNI_AVAILABLE */
|
||||
#undef T1HA_IA32AES_NAME
|
||||
|
1428
include/t1ha_bits.h
Normal file
1428
include/t1ha_bits.h
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user