Compare commits

...

581 Commits
3.0c ... 3.11c

Author SHA1 Message Date
23f7bee81c Merge pull request #820 from AFLplusplus/dev
push to stable
2021-03-15 23:14:07 +01:00
ac795ae1e1 v3.11c release 2021-03-15 23:08:28 +01:00
aa6a50c2b4 fix test 2021-03-15 23:01:07 +01:00
61c8304f24 fixes 2021-03-15 20:32:01 +01:00
01ad0f3c6a Merge pull request #813 from MarcoFalke/patch-1
doc: Clarify default value of N iterations in aflpp_driver
2021-03-13 13:08:58 +01:00
db342c9c81 doc: Clarify default value of N iterations in aflpp_driver 2021-03-13 11:03:08 +01:00
f1d8a01047 added ui change to changelog 2021-03-12 03:55:18 +01:00
3753f56c25 make get_offsets executable 2021-03-12 03:47:12 +01:00
d32b1d6b0c unique crashes yellow on resume (#801) 2021-03-12 03:46:50 +01:00
e5bdba4b9f Merge pull request #807 from AFLplusplus/dev
push to stable
2021-03-11 19:13:53 +01:00
c725cb71de more time for fp split 2021-03-11 19:12:21 +01:00
8ff5063545 fix 2021-03-11 18:03:18 +01:00
e549102563 Merge pull request #806 from AFLplusplus/dev
Dev
2021-03-11 09:43:27 +01:00
b7d90a9e31 new auto map 2021-03-11 09:32:22 +01:00
adeb0d18b1 fix the auto map fix 2021-03-11 08:59:34 +01:00
16e3e2a7f7 implemented #801 2021-03-11 01:39:21 +01:00
0484d9b024 more time for float split test 2021-03-11 00:49:23 +01:00
d60bbff0d9 more time for tests 2021-03-11 00:17:52 +01:00
966eba50a6 Revert "PFATAL for libdislocator"
This reverts commit ffd8fae22a.
2021-03-10 22:51:05 +01:00
ffd8fae22a PFATAL for libdislocator 2021-03-10 22:46:38 +01:00
cb0fe044dd Merge pull request #802 from MarcoFalke/patch-1
doc: Clarify memory limits in Readme
2021-03-10 22:39:05 +01:00
4f3b5f8adc doc: Clarify memory limits in Readme 2021-03-10 20:59:30 +01:00
3bb12b456f Merge pull request #800 from AFLplusplus/dev
push to stable
2021-03-10 19:33:50 +01:00
a10a627622 fix auto map discovery 2021-03-10 19:22:57 +01:00
2777784f4f fix man path 2021-03-10 18:43:30 +01:00
4bd0d4cbaf cmplog finetuning 2021-03-10 15:52:27 +01:00
2d92bb483e Merge pull request #786 from AFLplusplus/dev
push to stable
2021-03-10 15:45:14 +01:00
071edb1a2d brackets make dominik happy 2021-03-10 15:44:54 +01:00
7f36290703 Merge pull request #790 from rchildre3/qemu-deps
Remove QEMU dependency checks
2021-03-10 15:42:32 +01:00
6cc59a38be gsoc2021 clarification 2021-03-10 15:37:28 +01:00
87eb44abe4 Remove QEMU dependency checks
Most of these packages (bison, flex, pixman (in non-system mode)) are no
longer dependencies of QEMU and regardless, QEMU's build system is quite
capable of finding dependencies by itself and will error out
accordingly.  This prevents having to further change this code as QEMU's
dependencies inevitably change.
2021-03-10 09:12:41 -05:00
a0c3011673 change map_size tests 2021-03-10 11:08:03 +01:00
69f3095045 correct debug 2021-03-10 10:40:52 +01:00
d678d59372 fix 2021-03-10 10:07:54 +01:00
b2feada293 rt debug 2021-03-10 10:04:45 +01:00
bff02dae0d cmplog rtn rt fix 2021-03-10 09:32:54 +01:00
851231c846 fixed scan-build warnings 2021-03-10 01:15:38 +01:00
f21a5c42c1 tiny typo fixed 2021-03-10 00:55:26 +01:00
d471fc9509 add version dependency 2021-03-10 00:07:33 +01:00
9f22a151f3 mention added support for gcc_plugin mode 2021-03-09 23:55:22 +01:00
0c2478cae6 typos, small additions 2021-03-09 23:27:14 +01:00
b865fc6080 typos, rewording 2021-03-09 23:04:53 +01:00
d44b650cd4 typo 2021-03-09 22:14:34 +01:00
aa12e46013 formatting and RedQueen reference added 2021-03-09 22:09:58 +01:00
2c18fbbb2e Merge pull request #787 from devnexen/mac_m1_thr_priority
setting general schedule priority for performance on Mac.
2021-03-09 22:05:53 +01:00
4131965d48 md formatting 2021-03-09 21:59:31 +01:00
5fab0fa51f setting general schedule priority for performance on Mac. 2021-03-09 20:27:48 +00:00
9c9232b4e8 Merge pull request #789 from wyattearp/dev
documentation correction & formatting
2021-03-09 21:13:41 +01:00
0d6e571237 better CROSS detection 2021-03-09 21:11:44 +01:00
40ba8814b3 better CROSS detection 2021-03-09 21:05:58 +01:00
a0a917ad87 better CROSS detection 2021-03-09 21:03:18 +01:00
8628839c55 relsolving merge 2021-03-09 15:03:05 -05:00
5001779984 documentation correction & formatting
* fixed up manual define for `__AFL_LOOP()`
* added the code language formaters to the various blocks
* fixed a couple of missing backticks
2021-03-09 15:01:52 -05:00
93d91dd7a1 documentation correction & formatting
* fixed up manual define for `__AFL_LOOP()`
* added the code language formaters to the various blocks
* fixed a couple of missing backticks
2021-03-09 14:57:40 -05:00
791c5c171d fix ctx-1 2021-03-09 18:44:42 +01:00
a723156740 Merge pull request #785 from MarcoFalke/patch-1
doc: Add lld to required dependencies
2021-03-09 17:22:13 +01:00
0868ea8348 fix compiler rt on -c 2021-03-09 17:15:19 +01:00
5a6ad71f3f doc: Add lld to required dependencies 2021-03-09 17:08:55 +01:00
47f2650a32 add AFL_NOOPT 2021-03-09 16:53:56 +01:00
74a6044b3f fix sanitizer settings 2021-03-09 14:11:52 +01:00
e82ce95251 remove duplicate 2021-03-08 18:12:18 +01:00
e226d1bbb3 update changelog 2021-03-08 15:16:43 +01:00
54c1087340 more system speed in afl-system-config 2021-03-08 15:12:54 +01:00
eb1e8619eb fix handling of test case file names with spaces 2021-03-08 14:55:48 +01:00
c96fca6833 Merge pull request #779 from AFLplusplus/top-k-ctx
Restore correct CTX behaviour and enable K-CTX coverage for LLVM Classic
2021-03-08 09:50:18 +01:00
976cb3e36c Merge pull request #778 from AFLplusplus/dev
This fixes 3 different crash issues
2021-03-06 18:47:58 +01:00
9b3d8c327d fix for asan compile rt 2021-03-06 10:20:01 +01:00
7b907e45ad we do not support 80 + 128 bit FP in laf 2021-03-05 19:55:29 +01:00
e8d580f54d rust mutator changes added to changelog 2021-03-05 19:45:48 +01:00
2dd5a02061 Ergonomic Improvements for Rust Custom Mutators (#772)
* allow returning of str instead of CStr in rust custom mutator

* use OsStr instead of CStr for file paths

* fix cfg and compiler errors

* custom mutator default descriptions

* fix usage of afl_internal feature flag

* fix example mutator cfg

* fix lain mutator

* Revert "fix lain mutator"

This reverts commit adf7001808.

* actually fix lain mutator

* resolve question around utf-8 null bytes

* change from OsStr to Path to be even more ergonomic

* add rust custom mutator ci

* fix github action

* again

* separate compilation check
2021-03-05 19:40:59 +01:00
9844e1a856 fix 2021-03-05 19:32:27 +01:00
44be521ab8 fix 2021-03-05 19:19:43 +01:00
c9819e3b94 reduce github action minutes 2021-03-05 18:24:41 +01:00
16d6f35aa6 typos 2021-03-05 18:11:05 +01:00
c9854ec8cb typo 2021-03-05 18:07:16 +01:00
c429021de1 fix typos and format 2021-03-05 15:27:10 +01:00
41ad23041b remove warnings 2021-03-05 14:58:37 +01:00
3e5ac0af52 no static for rt initialized markers 2021-03-05 10:21:28 +01:00
f848562732 point explicitly to AFL_MAP_SIZE on problems 2021-03-05 10:15:38 +01:00
3342aa751d fix laf string transform crash 2021-03-05 10:05:43 +01:00
a2f40aa285 disable corpus introspection, potentially creates huge data 2021-03-04 22:10:32 +01:00
f34a860d5f NO_ARCH_OPT was removed due many issues 2021-03-04 20:14:47 +01:00
af9aeb89d4 afl-cc code for k-ctx 2021-03-04 15:26:15 +01:00
be5274d4a9 fix kctx compilation hang 2021-03-04 15:12:08 +01:00
b6dc529bc3 no ASAN odr violations by default 2021-03-04 14:55:57 +01:00
0aa93afeb8 vectorial top-k CTX first implementation 2021-03-04 14:50:26 +01:00
79d75d8e42 even support dlopen instrumented libs after the forkserver 2021-03-04 14:19:00 +01:00
96c526cb78 fix caller/ctx change, support dlopen in afl-compiler-rt 2021-03-04 14:04:40 +01:00
02f3319256 only initialize afl-compiler-rt once 2021-03-04 12:23:27 +01:00
8f538e77ed code format 2021-03-04 11:33:51 +01:00
1e76079e93 llvm mode CALLER mode 2021-03-04 11:32:32 +01:00
0e736276e6 restore correct CTX behaviour in llvm mode 2021-03-04 11:00:54 +01:00
08ef8d6b78 NO_CHECKOUT=1 ./build_qemu_support.sh 2021-03-04 10:57:00 +01:00
3977d50b55 update qemuafl and remove git stas 2021-03-04 10:52:22 +01:00
3bcfbf5038 Merge pull request #776 from realmadsci/afl-exclude-ranges
Add AFL_QEMU_EXCLUDE_RANGES
2021-03-04 10:33:16 +01:00
f0c7967fbf add new tutorial 2021-03-03 08:58:09 +01:00
8bdb40b763 cpu-exec: Add AFL_QEMU_EXCLUDE_RANGES
This environment variable allows rejection of
specific regions from instrumentation.

It takes priority over AFL_INST_LIBS and AFL_QEMU_INST_RANGES,
so it can be used to poke a "hole" in previously included sections.
2021-03-02 12:55:44 -08:00
f0bc2e0e8b docu 2021-03-02 18:45:41 +01:00
108e588e88 add de-unicoded dictionary entries 2021-03-02 17:46:43 +01:00
333509bb0a better unicode support 2021-03-02 16:24:43 +01:00
c269c3977c fix llvm for unicode strings (hopefully) 2021-03-02 11:38:12 +01:00
c3a8052a16 update changelog 2021-03-01 19:30:39 +01:00
d0a61279b8 write to correct pipe end 2021-03-01 19:15:58 +01:00
7259075b71 len for cmplog rtn 2021-03-01 19:13:29 +01:00
14fd477147 better fix for asan? 2021-03-01 19:03:25 +01:00
05e2f577f6 fix area_is_valid with write 2021-03-01 17:21:27 +01:00
a29b360d55 area_is_valid with write 2021-03-01 17:16:34 +01:00
75d6a8b701 fix last commit 2021-03-01 15:33:28 +01:00
ad7a7fcf07 ASan-compatible area_is_mapped() 2021-03-01 15:30:55 +01:00
82c05630ba 3.11a init 2021-03-01 10:12:42 +01:00
bd0a23de73 Merge pull request #767 from AFLplusplus/dev
Final push for release
2021-03-01 10:12:04 +01:00
4619a1395b ensure proper aligning for skim patch 2021-03-01 09:57:57 +01:00
0c38850f95 3.10c release 2021-03-01 09:43:35 +01:00
07884e0054 feodora qemu lib fix 2021-03-01 09:37:07 +01:00
bdadbb7207 Merge pull request #770 from rchildre3/qasan-print-formats
Fix printf specifiers of (s)size_t in QAsan hooks
2021-02-28 22:02:35 +01:00
e389eb9842 Fix printf specifiers of (s)size_t in QAsan hooks
* size_t specifier is %zu or %zx
* ssize_t specifier is %zd

Helpful for cross compiling
2021-02-28 15:08:59 -05:00
5cf0655071 metrics 2021-02-28 10:01:35 +01:00
f81ef4abf4 fix afl-common compile 2021-02-28 00:12:39 +01:00
6036cf8437 BSD: how to avoid core dumps 2021-02-28 00:24:29 +01:00
1cad645400 fix %ld in hooks.c 2021-02-27 18:30:04 +01:00
36846836ed libqasan: read and write hooks 2021-02-27 18:26:57 +01:00
79f1a44a01 fix qasan search path 2021-02-27 18:14:58 +01:00
c2127e3ff7 disable the generation of core files in DragonFly BSD 2021-02-27 17:58:25 +01:00
2ad495ad0a reworked unicornafl documentation 2021-02-27 17:19:00 +01:00
8e051fd075 fixed rust bindings placement 2021-02-27 16:37:00 +01:00
af628b16d1 added rust binding reference 2021-02-27 16:29:29 +01:00
c219502f0f some rust cleanup 2021-02-27 15:52:36 +01:00
a5da9ce42c custom mutator rust support (#752)
* custom mutator rust support

* clarify how to view documentation for rust mutators

* remove `FuzzResult` hack and clarify lifetimes of CustomMutator::fuzz

* rename TErr associated tyep to Error to be more idiomatic

* fix warnings

* add example for fallible custom mutator

* make Fallible Custom Mutator the default and implement it's handle_err method by default

* rename CustomMutator::handle_err to handle_error

* add example mutator using lain
2021-02-27 15:05:13 +01:00
79e02c2a9b remove debug output 2021-02-26 22:54:35 +01:00
3a461944ec fine tune cmplog 2021-02-26 22:36:19 +01:00
78d96c4dc8 Merge pull request #759 from AFLplusplus/dev
push to stable
2021-02-26 09:45:43 +01:00
ee0ca07f3c changing the -t ...+ meaning to "auto-calculate buth this is the max" 2021-02-25 12:19:46 +01:00
7ae7b0f373 docs update 2021-02-25 11:08:37 +01:00
e2b4bc9310 update changelog 2021-02-25 11:02:59 +01:00
6c9777de13 edges in afl-plot 2021-02-25 10:42:39 +01:00
2f7e57f6aa helper_min3 func 2021-02-25 10:04:41 +01:00
5c239451cf cmplog finetuning 2021-02-25 09:15:54 +01:00
35ca51c5a8 Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev 2021-02-24 21:29:09 +01:00
047f3436e9 edges in plot file 2021-02-24 21:29:00 +01:00
5d181950eb fixes 2021-02-24 21:17:58 +01:00
48a1a29baa typos 2021-02-24 20:34:33 +01:00
c05d392cd9 Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev 2021-02-24 18:07:18 +01:00
cc7c651dc9 tidied up env suggestions 2021-02-24 18:07:08 +01:00
e6ef2ee338 typo 2021-02-24 12:14:10 +01:00
a090b2013f docs 2021-02-24 12:02:44 +01:00
564f491566 redqueen settings opt 2021-02-24 09:29:19 +01:00
2daeeab844 encode double quote in dict 2021-02-23 10:06:15 +01:00
4ab90e739f code format 2021-02-22 22:24:59 +01:00
745bc083d1 fix error msg 2021-02-22 18:22:09 +01:00
7674dac1a1 auto mode for CTX + NGRAM 2021-02-22 18:17:35 +01:00
fb2a6b6941 minimum sync time 2021-02-22 16:56:35 +01:00
70fe872940 ensure a valid seed exists 2021-02-22 16:39:38 +01:00
a252943236 another fix for disabled entries 2021-02-22 12:59:01 +01:00
8c133b607c stdstring fix attempt 2021-02-22 12:43:39 +01:00
2785c8b197 crash fix 2021-02-22 12:34:37 +01:00
a81b5aa921 dict2file fix 2021-02-22 11:08:25 +01:00
8ad78f5b65 fix 2021-02-21 23:42:08 +01:00
ac9cfd89da how to compare afl++ 2021-02-21 23:27:07 +01:00
c67c4ce757 doc update 2021-02-21 23:17:40 +01:00
974aab6cf6 cmplog config.h -> -l option 2021-02-21 17:53:09 +01:00
b957218a3a more attuned colorize repace 2021-02-21 11:30:05 +01:00
f629f4e341 Merge pull request #755 from rchildre3/improve-llvm-build-instructions
Improve LLVM build instructions
2021-02-21 09:15:20 +01:00
871c3c91ec Improve LLVM build instructions
* Enable shell highlighting on code block
* Shallow clone of source due to extensive history
* Line break and sort the CMake options for visibility
* Disable most extraneous options (e.g. docs, tests, benchmarks,
  clang-tools-extra, OpenCL interface)
* Only build for the host architecture by default
* Support other sub-make interfaces, like the recommended Ninja Build
  System
* Harden against paths with spaces
* Prefer linking against the newly built LLVM libraries by prepending to
  LD_LIBRARY_PATH
2021-02-20 19:24:28 -05:00
100aac4dd3 -t help 2021-02-20 14:15:38 +01:00
d941da33ae qemuafl 2021-02-19 21:20:33 +01:00
62767a42dc improved env suggestions 2021-02-19 20:40:38 +01:00
89cf94f0e6 suggested env vars for lazy ppl 2021-02-19 20:33:12 +01:00
17211253b2 libhfcommon not anymore a symlink 2021-02-19 18:25:24 +01:00
6998489b26 Revert "Remove self-referential symlink"
This reverts commit aaf5fcd98a.
2021-02-19 18:21:10 +01:00
4290cb5877 fix hongg mutator API change 2021-02-19 16:07:47 +01:00
801f2449ec Merge pull request #753 from frewsxcv/frewsxcv-libhf
Remove self-referential symlink
2021-02-19 16:02:25 +01:00
aaf5fcd98a Remove self-referential symlink 2021-02-19 09:18:59 -05:00
5edfb7ba85 nicer bib 2021-02-19 15:04:53 +01:00
a5cb522f01 Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev 2021-02-19 15:03:22 +01:00
3195119dad pointer to cite in readme 2021-02-19 15:03:10 +01:00
d6fe6b9537 qemuafl 2021-02-19 10:49:36 +01:00
c0f9fba6d6 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-02-18 19:40:22 +01:00
1a713ff420 fix qemu AFL_ENTRYPOINT for arm 32 and 64 bit 2021-02-18 19:39:46 +01:00
89af2ef7a9 update honggfuzz custom mutator 2021-02-18 11:15:59 +01:00
907c5d4276 Merge pull request #751 from AFLplusplus/dev
fix a rare i2s illegal memory access
2021-02-17 19:19:25 +01:00
5dd35f5281 fix a rare i2s illegal memory access 2021-02-17 19:10:05 +01:00
857229654e Merge pull request #750 from AFLplusplus/dev
Push to stable
2021-02-17 17:43:11 +01:00
4c47b242eb fix FPE in colorization 2021-02-17 17:40:01 +01:00
938512a6b9 minor fixes 2021-02-17 09:48:04 +01:00
7444cfa450 Merge pull request #748 from b1gr3db/dev
Regression fix
2021-02-16 17:52:44 +01:00
f091b8d692 Regression fix
Previous fix was undone in a subsequent commit
2021-02-16 11:17:55 -05:00
7d97ffb1e8 check for setuptools instead of easy_install 2021-02-16 16:27:56 +01:00
80bdbf7be0 minor cmplog fix 2021-02-16 09:54:15 +01:00
686719cdca Merge pull request #746 from f0rki/cmplog-intcast-fix
CMPLOG llvm pass: use CreateIntCast to cast to the right integer type
2021-02-16 09:51:31 +01:00
6caec2169c Revert "llvm bug workaround for lto extint"
This reverts commit e3a5c31307.
2021-02-15 19:14:28 +01:00
5212481352 CMPLOG llvm pass: use CreateIntCast to cast to the right integer type 2021-02-15 19:13:50 +01:00
d999725de2 Merge pull request #737 from AFLplusplus/dev
push to stable
2021-02-15 15:20:06 +01:00
145c673a80 finished merge 2021-02-15 15:04:34 +01:00
c5017945f7 merged 2021-02-15 14:07:10 +01:00
5c4c49d9ca black 2021-02-15 14:00:08 +01:00
cebde1f9e6 ran black on python scripts 2021-02-15 13:52:23 +01:00
0298ae82b0 code-format 2021-02-15 13:52:03 +01:00
512f53984c fixed scan-build issues 2021-02-15 13:51:32 +01:00
e3a5c31307 llvm bug workaround for lto extint 2021-02-15 13:25:15 +01:00
dd2fd80274 doc updates 2021-02-15 12:40:10 +01:00
ffc1fc655f qenuafl 2021-02-15 10:27:44 +01:00
fe477e96ae fix configure arguments 2021-02-15 09:24:13 +01:00
98559ea8b0 fix compiler warning 2021-02-15 08:54:53 +01:00
f31d8b8401 redqueen fix compiler warnings for 32 bit 2021-02-15 08:46:19 +01:00
389e348826 fixes 2021-02-14 22:43:52 +01:00
98fd50f78f Merge branch 'stable' into dev 2021-02-14 22:42:13 +01:00
95561ec5a7 dockerfile fix 2021-02-14 21:47:42 +01:00
fe9da70705 disabling march=native due problems on intel platforms 2021-02-14 18:43:43 +01:00
95c77c8486 try qemu build fix 2021-02-14 11:46:23 +01:00
e45333bcf9 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-02-13 23:29:04 +01:00
c906c042be fix compiler warning 2021-02-13 23:28:15 +01:00
9bd1e19d7f added AFL_IGNORE_UNKNOWN_ENVS 2021-02-13 22:43:56 +01:00
6ce9230ed6 afl-cmin/afl-showmap -f 2021-02-13 14:29:22 +01:00
1d60c39191 fix new compiler warning 2021-02-13 13:42:37 +01:00
70651d60bd Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-02-13 13:32:42 +01:00
385312c658 fix issue #732 afl-cmin and afl-showmap should support '-f' 2021-02-13 13:31:17 +01:00
87a607c7d0 update doc 2021-02-13 11:17:53 +01:00
1ba5d1008e fuck you llvm 13 2021-02-13 10:53:40 +01:00
129a5adaf1 fix 2021-02-13 09:29:35 +01:00
d827bc4580 dont break on llvm 13 2021-02-13 09:12:36 +01:00
64e46dcefc remvoe libcompcov 32 bits warnings 2021-02-12 22:07:17 +01:00
c0b3127b9d remove travis badge 2021-02-12 14:54:24 +01:00
7cfa690d1c typo 2021-02-12 11:05:46 +01:00
22a3c7f7d0 fix #736 (ty b1gr3db) 2021-02-12 09:42:22 +01:00
16ffbb37f5 typo 2021-02-11 22:09:19 +01:00
ea05f3f4cd typos 2021-02-11 21:55:14 +01:00
91f2f057e4 fix #723 2021-02-11 21:17:08 +01:00
d44cf1344d typo 2021-02-11 21:08:10 +01:00
756206e4d7 typo 2021-02-11 20:26:02 +01:00
2ff6e5023f typos 2021-02-11 20:14:48 +01:00
223bd70f1f typo 2021-02-11 20:08:28 +01:00
dd3f4bb41c typos & formatting 2021-02-11 20:05:06 +01:00
f3e783d343 typo 2021-02-11 19:55:21 +01:00
f4cac37b04 typos 2021-02-11 10:20:36 +01:00
5b2634f711 update changelog + ideas 2021-02-10 17:56:27 +01:00
267b085f80 dlmalloc only for non glibc qasan and AFL_QEMU_FORCE_DFL 2021-02-10 15:15:16 +01:00
b6643743d6 fix laf for potential crashes 2021-02-10 10:13:08 +01:00
17cbb03ba7 more cmplog options in config.h 2021-02-09 09:18:24 +01:00
2cd4624779 build docker without march=native 2021-02-09 08:38:33 +01:00
e11665564b fix docker build action 2021-02-09 08:30:49 +01:00
93cebd6c7f Merge pull request #734 from Pamplemousse/build_docker_image_in_actions
Use GitHub Actions to build Docker image
2021-02-09 08:28:31 +01:00
a124540e50 Use GitHub Actions to build Docker image
... then deploy to hub.docker.com .

Signed-off-by: Pamplemousse <xav.maso@gmail.com>
2021-02-08 20:36:06 -07:00
c465e48e27 remove AFL_CC from unset list to allow success for unusual environments 2021-02-07 16:19:27 +01:00
c2c65fd9c1 mark llvm 13 as unsupported (yet) 2021-02-07 09:42:28 +01:00
0ad56167c5 fix scan-build issues 2021-02-07 07:51:29 +01:00
aeb7d70483 remove debug output 2021-02-07 06:16:53 +01:00
209c5ba465 larger map, stats reload fix, code format 2021-02-07 05:33:02 +01:00
01327ad301 Merge pull request #728 from vj-27/dev
load existing stats file when in AFL_AUTORESUME or -i - mode.
2021-02-07 05:20:02 +01:00
96cdc97c98 prev_run_time loaded used only for ui and when writing the stats file 2021-02-07 03:33:47 +05:30
a763c61d89 add missing sancov cmp functions 2021-02-06 12:43:22 +01:00
d920104248 remove compiler warnings 2021-02-06 12:26:51 +01:00
08076f0500 fix qemu build script for Arch Linux ($CROSS) 2021-02-06 12:04:29 +01:00
e81f30828f fix test-qemu-mode.sh to run standalone 2021-02-06 11:24:04 +01:00
f54c4dbfdb set prev_run_time inside afl state 2021-02-06 09:41:15 +00:00
bf289ce50e larger dummy map 2021-02-06 09:31:41 +01:00
1a8c242d28 load run time and donot load pending_* or *_favoured 2021-02-05 19:46:24 +00:00
19d8f00963 doc fix 2021-02-05 13:01:42 +01:00
bed789cd5a fix doc 2021-02-05 13:01:13 +01:00
7e625c3687 more doc, so good 2021-02-05 12:30:21 +01:00
f53a2e4b88 nits 2021-02-05 12:11:18 +01:00
d8a18a03e3 update unicorn ref 2021-02-05 11:44:48 +01:00
1677481726 try if this helps on fuzzbench 2021-02-05 10:47:16 +01:00
6f163bb0c5 load existing stats file when in AFL_AUTORESUME or -i - 2021-02-05 00:26:23 +00:00
3533df9453 Merge pull request #730 from AFLplusplus/replay
update readme
2021-02-04 23:10:32 +01:00
faa9daf260 update readme 2021-02-04 23:09:49 +01:00
bf1198c4db dockerfile: fix qemu built, update llvm to 12 2021-02-04 20:47:51 +01:00
ec737f3368 workaroung for llvm LTO bitcast bug 2021-02-04 18:57:27 +01:00
208254f47c Merge pull request #726 from b1gr3db/dev
Fix for off by one in libqasan's memmem
2021-02-04 13:32:54 +01:00
d0ab2ded00 Create string.c
Off by one error resulted in memmem calling memcmp where h + needle_len is one past the end.
2021-02-03 15:32:06 -05:00
58a5372bf0 typo 2021-02-03 14:18:35 +01:00
ea5d9c42b6 Merge pull request #724 from devnexen/afl_untracer
afl-untracer: Mac M1 build update proposal.
2021-02-03 09:21:41 +01:00
8bd70a50b1 afl-untracer: Mac M1 build update proposal. 2021-02-03 07:38:09 +00:00
6be3896bfa linux performance option 2021-02-02 14:41:31 +01:00
1f71b85426 automagically fix sanitize fuzzer+coverage 2021-02-02 10:05:10 +01:00
654f389e73 try to remove warnings during compilation 2021-02-01 23:36:27 +01:00
cd95ee67bc code format qasan 2021-02-01 23:00:45 +01:00
90fdafa1ad fix warnings and an llvm cmplog+lto panic 2021-02-01 22:59:41 +01:00
b9f469e12f make some really weird targets compile 2021-02-01 20:00:29 +01:00
ba7bf99235 Merge pull request #721 from GanbaruTobi/patch-1
Clarify usage of LD_LIBRARY_PATH in afl_frida
2021-02-01 17:53:08 +01:00
e954c891a0 Clarify usage of LD_LIBRARY_PATH in afl_frida
This will help not *accidentally* trying to set the variable to the library's binary.
2021-02-01 17:32:45 +01:00
80fc6166d0 adjust expand havoc 2021-02-01 16:28:52 +01:00
4018e7f8e5 mv cmplog options to config.h 2021-02-01 16:23:40 +01:00
05472a0fc5 move cmplog compile options to config.h 2021-02-01 16:04:34 +01:00
32110a04c0 fixes 2021-02-01 15:51:04 +01:00
812cf4c9e0 reorder 2021-02-01 15:21:39 +01:00
374fa8af47 add case when cmplog map neds to be larger 2021-02-01 14:56:22 +01:00
fc5f865796 reorder check 2021-02-01 14:02:31 +01:00
88155d2c3b make dominik more happy - no auto map size for qemu+unicorn 2021-02-01 13:04:39 +01:00
d808a8401e import cmplog opts 2021-02-01 12:16:55 +01:00
bca4026f62 Merge pull request #718 from AFLplusplus/cmplog_lowfail
cmplog lower fail
2021-02-01 12:07:13 +01:00
965b854803 correct afl-showmap be_quiet state 2021-02-01 12:05:54 +01:00
981ffb27a8 making AFL_MAP_SIZE obsolete 2021-02-01 12:01:23 +01:00
522eacce71 qemuafl 2021-01-31 21:48:30 +01:00
19d02d7bf6 update qemu and main makefile for qasan 2021-01-31 17:45:55 +01:00
cc0210426a code-format 2021-01-31 17:32:24 +01:00
459dd8cb07 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-01-31 17:30:17 +01:00
e5116c6d55 fix -Z, remove q->next 2021-01-31 17:29:37 +01:00
7a861498c2 added support for __afl_coverage_interesting 2021-01-31 15:04:40 +01:00
893cd47d9c disable trimming for -M 2021-01-31 13:03:00 +01:00
9d08f0d098 added AFL_CMPLOG_ONLY_NEW feature 2021-01-30 15:39:47 +01:00
3b3565269d foreign sync from ctime to mtime (libfuzzer) 2021-01-30 14:57:17 +01:00
2f96f1e920 afl-frida faster for x86_x64 2021-01-30 10:28:34 +01:00
1b557d1a70 remove warnings 2021-01-30 09:01:06 +01:00
b06e3d9f2b Merge pull request #715 from AFLplusplus/qasan
Qasan
2021-01-29 18:52:45 +01:00
aaec45b652 changelog 2021-01-29 18:51:44 +01:00
af24d87220 qasan readme 2021-01-29 18:48:46 +01:00
2e3bc3b613 update qemuafl 2021-01-29 18:42:21 +01:00
29c1131fe0 working AFL_USE_QASAN 2021-01-29 18:32:28 +01:00
debd832f36 32bit fix 2021-01-29 18:25:25 +01:00
8a8ecef6f5 cmplog lower fail 2021-01-29 18:13:45 +01:00
66c290f804 fix compile 2021-01-29 17:23:19 +01:00
40f609c735 better cmplog arithmetic 2021-01-29 15:57:47 +01:00
28e1aaa0f1 qasan support in aflpp 2021-01-29 15:47:25 +01:00
6f5746d428 AFL_USE_QASAN 2021-01-29 15:38:49 +01:00
4488e8e10a fix qemu build script 2021-01-29 15:16:35 +01:00
d21ca3e480 libqasan and use target cross compiler to compile target qemu libs 2021-01-29 15:14:20 +01:00
1b1006ddd4 qemuafl 2021-01-29 13:04:03 +01:00
cb428e55bb Merge pull request #714 from AFLplusplus/vanhauser-thc-patch-1
Update issue templates
2021-01-29 10:17:53 +01:00
0c616087e0 Update issue templates 2021-01-29 10:17:32 +01:00
ce673ccab3 remove snapshot reference 2021-01-28 19:19:57 +01:00
d5a170655f update qemuafl 2021-01-28 19:08:36 +01:00
2a9fcd2a87 warn on afl-gcc/afl-clang instrumentation 2021-01-28 18:01:27 +01:00
a61a30dee0 fix another pending_not_fuzzed location 2021-01-28 14:11:33 +01:00
d62c83d58f Merge pull request #712 from zodf0055980/dev
Fix getopt arg string
2021-01-28 10:46:36 +01:00
ad63ba49c1 Fix getopt arg string
There is no '-P' case here.
2021-01-28 17:21:54 +08:00
1dfea4e91a Merge pull request #711 from wideglide/patch-1
enable warnings for LTO mode 's/warn /warning /'
2021-01-28 08:26:30 +01:00
47f62eb0ca Fix dev branch for android (#710)
* android: replace rindex with strrchr

* android: support 64bit only due to 128bit integer not supported by 32bit system

Co-authored-by: joeyjiaojg@qq.com <joeyjiaojg@163.com>
2021-01-28 05:51:45 +01:00
9bc8c7518f enable warnings for LTO mode 's/warn /warning /' 2021-01-27 22:39:33 -05:00
2044c7e2b5 fix include 2021-01-27 08:41:45 +01:00
6b721900d5 Merge pull request #707 from ampanasiuk/bug-703-wrong-src-attribute-in-sync-stage-filenames
Bug 703 wrong src attribute in sync stage filenames
2021-01-27 08:35:21 +01:00
f5127c0e2b Merge pull request #706 from fuzzah/dev
include limits.h to fix build on BSD systems
2021-01-27 08:33:28 +01:00
f571f074a8 update envs 2021-01-27 08:21:22 +01:00
d046b28f2f Fix "src" attribute in sync stage filenames (#703) 2021-01-27 03:04:06 +00:00
a754694ac4 include limits.h to fix build on BSD systems 2021-01-27 05:48:59 +03:00
36b5336152 better foreign sync name 2021-01-26 22:45:59 +01:00
9c393adbb9 real fix plus code format 2021-01-26 17:12:11 +01:00
e0663c91b9 wip fix 2021-01-26 12:15:13 +01:00
7c381a782e enable cmplog combine 2021-01-25 20:18:42 +01:00
cd8668ad3a mopt fix 2021-01-25 13:55:09 +01:00
9a7531942d fix rpc_stats.md 2021-01-25 10:04:21 +01:00
107b624224 Merge branch 'dev' of github.com:aflplusplus/aflplusplus into dev 2021-01-25 04:24:57 +01:00
822aea3cb4 unicorn fix 2021-01-25 04:24:43 +01:00
52af7caf8a Add StatsD readme (#702)
* Adding draft notes for statsd readme

* Add statsd dashboard json template & image.
2021-01-25 02:07:51 +01:00
afc15965c0 updated unicornalf, bindings 2021-01-25 02:01:34 +01:00
e82cd40440 added cargo lock 2021-01-23 19:39:34 +01:00
08c716da9c removed lock' 2021-01-23 19:39:16 +01:00
0a3a708f9b less stack mem req 2021-01-23 10:01:09 +01:00
a22c8ffdf2 Merge branch 'dev' of github.com:aflplusplus/aflplusplus into dev 2021-01-23 06:45:16 +01:00
4179affe2c enabled persistent mode 2021-01-23 06:42:55 +01:00
46cef4bc11 fixed rust example 2021-01-23 06:39:55 +01:00
fea0286989 tried to fix rust example 2021-01-23 06:03:15 +01:00
b0a8bc28d2 changelog 2021-01-23 00:13:32 +01:00
e37e432952 updated uc ref 2021-01-23 00:10:59 +01:00
c4118e869d unicorn speedtest initial commit 2021-01-23 00:02:59 +01:00
258ae1632a stack 2 heap 2021-01-22 21:10:23 +01:00
1c19804834 fix for cmplog stdstring 2021-01-22 16:41:31 +01:00
9ed533a0e3 fix debug output 2021-01-22 16:01:00 +01:00
baf1ac2e69 basic cmplog std::string support 2021-01-22 15:58:12 +01:00
46010a8704 prepare for cmplog rtn std::string support for llvm and g++ 2021-01-22 13:50:16 +01:00
ac21e4dd73 typos 2021-01-22 00:41:23 +01:00
f0be89a5b6 Merge pull request #699 from Edznux/origin/statsd-env-doc
Add more docs for AFL_STATSD_TAGS_FLAVOR
2021-01-22 00:37:35 +01:00
0a12d519f7 Add better doc for AFL_STATSD_TAGS_FLAVOR 2021-01-22 00:18:56 +01:00
2ef8dc4378 afl-cmin -m none 2021-01-21 21:42:15 +01:00
30148bc1a9 fix afl-showmap and gcc plugin test 2021-01-21 19:58:25 +01:00
60764ebdf1 forkserver debug flag support 2021-01-21 18:43:06 +01:00
040bf5a61d fix silly mistake 2021-01-21 18:26:08 +01:00
b850951c72 code format and not setting sanitizers if debug and settings present 2021-01-21 17:15:14 +01:00
43edd969d8 fix qemu x86 cmplog issue 2021-01-21 16:57:19 +01:00
e8c1b43a3d fix docs 2021-01-21 15:24:34 +01:00
3903dac1f5 fix gcc plugin test 2021-01-21 14:17:08 +01:00
1ee0946f69 update changelog 2021-01-21 12:11:12 +01:00
fc3f06caec Merge pull request #689 from AFLplusplus/cmplog_merge
cmplog merge
2021-01-21 12:03:21 +01:00
0d472adef0 temp conflict resolve 2021-01-21 12:02:50 +01:00
ba47bee252 pre merge changes 2021-01-21 11:41:25 +01:00
f7c93d741c base64 solving done 2021-01-21 03:52:46 +01:00
cf5fee7c52 remove debug output 2021-01-20 21:03:55 +01:00
d20a50a413 hex en/decode works now 2021-01-20 20:59:17 +01:00
b39b87b2f7 Merge pull request #693 from vishesh-sharma-123/patch-2
Update README.md
2021-01-20 19:13:02 +01:00
068bef5eab Merge pull request #691 from AFLplusplus/dev
push to stable
2021-01-20 19:12:52 +01:00
5174eb6741 Update README.md
typo and correction in link
2021-01-20 22:31:21 +05:30
b9e855b7b5 Merge pull request #695 from joeyjiaojg/dev
Fix Porting of AFLplusplus for Android
2021-01-20 14:00:26 +01:00
f380487bb4 wip 2021-01-20 13:51:57 +01:00
02079d8ef9 android: Remove frida-gum package 2021-01-20 19:16:57 +08:00
9dff3495d5 better cmp map fsrv fix 2021-01-20 10:01:34 +01:00
2cd3010f82 Merge pull request #694 from rchildre3/wine-preload
LD_PRELOAD in the QEMU environ and enforce arch
2021-01-20 09:55:00 +01:00
bb9d275350 afl_frida: Add AFL_FRIDA_TEST_INPUT env to debug input 2021-01-20 15:48:48 +08:00
f3ef91e8d6 Migrates DebugLoc::get to DILocation::get
- Refer to https://reviews.llvm.org/D93087
2021-01-20 15:48:48 +08:00
ac1117ffae android: Fix runtime for mutator 2021-01-20 15:46:41 +08:00
7ad8f6c717 android: Add libprotobuf aflpp custom_mutator example 2021-01-20 15:46:41 +08:00
9d9e148e5c android: build custom mutators for symcc, radamsa 2021-01-20 15:46:41 +08:00
1e2da1dfb9 android: port libfuzzer-mutator 2021-01-20 15:46:41 +08:00
6dc20fc298 afl_frida: fix target lib 2021-01-20 15:46:41 +08:00
868ef6c10c android: afl_frida: get target lib/function from command line 2021-01-20 15:46:41 +08:00
52f1d535bd android: port afl_frida for arm64 2021-01-20 15:46:41 +08:00
0306261fec Fix build error for Android
- LTO not work yet
2021-01-20 15:46:39 +08:00
17e3e65d96 LD_PRELOAD in the QEMU environ and enforce arch 2021-01-20 01:02:28 -05:00
e3835b4d68 Update README.md
Typo
2021-01-20 09:22:28 +05:30
e7b572af36 bugfix and new transform detection feature 2021-01-20 01:49:32 +01:00
473b3e5fb0 updated unicornafl qemu versions 2021-01-19 19:45:53 +01:00
86c567fa3a update qemuafl + unicorn for include changes 2021-01-19 16:49:00 +01:00
ed9f94c5b9 fix CI 2021-01-19 14:20:43 +01:00
0367f6c723 cleanup and rename _DISCARD->_SKIP 2021-01-19 14:03:10 +01:00
292f91a55f tiny scan-build nags fixed 2021-01-19 13:16:39 +01:00
95ee2cdd57 cleanup 2021-01-19 13:05:42 +01:00
e91f3b0de6 codeql fix 2021-01-19 10:41:42 +01:00
ca1eb32552 fix compiles 2021-01-19 10:16:12 +01:00
a9ebf72a84 cmp map memset fix 2021-01-18 22:19:04 +01:00
e2d9dc16e3 fix compiler warning avoid signess difference in comparisons 2021-01-18 21:36:19 +01:00
0b545aaeb4 use enums, support cmplog map collisions 2021-01-18 20:18:18 +01:00
94a15b8ca7 arithmetic also for <= >= 2021-01-18 13:20:40 +01:00
0c061186cf less logging 2021-01-18 12:13:36 +01:00
bbfaa6092d refactoring 2021-01-18 11:12:20 +01:00
a8b0629163 introspection, favor extint over long double 2021-01-18 09:26:16 +01:00
7b97410060 cmplog introspection 2021-01-17 23:47:04 +01:00
8951f90623 no cmplog when no taint is found 2021-01-17 17:03:08 +01:00
6b375489ed better extint cmplog 2021-01-17 16:50:10 +01:00
c8c0983ab8 make combined test a define option 2021-01-17 15:51:38 +01:00
c71ce79963 fix colorization 2021-01-17 15:18:20 +01:00
d36af0d576 fix msg 2021-01-15 17:32:43 +01:00
a0e884cf8b merge cmplog 2021-01-15 16:56:40 +01:00
fba8790e32 better error reporting 2021-01-15 15:12:27 +01:00
8eb00a5dfa remove warning 2021-01-15 14:55:58 +01:00
d5049da5e4 better error message 2021-01-15 14:50:51 +01:00
9646960f88 update doc 2021-01-14 21:36:52 +01:00
7ba17d182f more sync in deterministic mode 2021-01-14 21:26:46 +01:00
c42875ddea Merge pull request #688 from murx-/dev
Update documentation to reflect new default power schedule
2021-01-14 14:15:01 +01:00
53c7aaa57b Update documentation to reflect new default power schedule 2021-01-14 13:46:03 +01:00
68acd3d101 Merge pull request #686 from AFLplusplus/weight
better seed selection
2021-01-14 00:26:08 +01:00
0ddbffd80e fix 2021-01-12 17:36:10 +01:00
b9ba2805e5 minor changes 2021-01-12 17:31:29 +01:00
efd8042431 fix lto cmplog instability 2021-01-12 13:42:00 +01:00
dc81f681c9 fix weight calc, thanks to Marcel 2021-01-10 13:12:44 +01:00
4581ad3df9 code fmt 2021-01-08 18:19:40 +01:00
3196a5f666 cleaned up and added comments to forkserver exits 2021-01-08 18:17:52 +01:00
20a47cb23e Merge pull request #679 from AFLplusplus/dev
Dev
2021-01-08 15:43:13 +01:00
813627cbd3 better gcc_plugin error msg 2021-01-08 13:01:46 +01:00
1827c65596 better gcc_plugin error msg 2021-01-08 12:55:05 +01:00
3d1a25ce4e added check to silence scan-build 2021-01-08 11:54:35 +01:00
34732e3c5e refactored kill signal env parsing 2021-01-08 11:36:40 +01:00
7b8c8cf12f fix 2021-01-08 00:47:52 +01:00
7eaca9c840 Merge branch 'stable' of github.com:aflplusplus/aflplusplus into dev 2021-01-07 23:37:57 +01:00
a06b25538f cleaned up AFL_KILL_SIGNAL 2021-01-07 23:21:10 +01:00
9cdf5c4150 User defined kill signal value (#678)
* Adding AFL_KILL_SIGNAL environment variable

Controlling the kill signal used to end forked processes.

* Checking validity of AFL_KILL_SIGNAL env variable

This commit also sets a valid value in the environment to avoid
duplicating code in at_exit(). Changing data type of
fsrv->kill_signal to u8 to match last_kill_signal.

* Adding afl_kill_signal to AFL (environment) state

This commit simply introduces a struct member for future use. The
env variable is not used from the afl struct but from fsrv, where
its validity is checked, resulting in a FATAL in case of errors.
2021-01-07 22:35:34 +01:00
52c221fc48 selective coverage fix 2021-01-06 09:35:47 +01:00
4c78bb7080 cpp fix 2021-01-05 22:13:55 +01:00
59b86b0db0 haiku fix 2021-01-05 19:20:10 +01:00
1a85fca49f haiku fix 2021-01-05 19:14:51 +01:00
9d4614ce2f haiku support 2021-01-05 19:06:27 +01:00
faefad564b Haiku afl-system-config disable debugger, afl-cc.c avoid -lrt 2021-01-05 16:49:04 +00:00
6b54310452 selective instrumentation documented 2021-01-05 12:30:26 +01:00
caf1fbd632 selective_coverage implementation in afl-compiler-rt 2021-01-05 11:52:55 +01:00
a561de6e97 forgot struct keyword 2021-01-05 10:40:46 +01:00
7acf410ab6 afl coverage feature example 2021-01-05 10:35:12 +01:00
6c095b3937 code format 2021-01-04 23:13:56 +01:00
d367b033a2 add missing FCMP_UEQ to split-compares-pass.so.cc 2021-01-04 23:08:46 +01:00
7f4b3a460a more code cleanup (instrumentation) 2021-01-04 22:23:04 +01:00
251e72f136 mehr code cleanup 2021-01-04 21:25:53 +01:00
c6e038fe25 code cleanups (shadowed vars, (un)signed type mismatches, format types, etc.) 2021-01-04 20:40:53 +01:00
5c22472616 cmplog fix 2021-01-04 18:20:02 +01:00
b7cd6d4035 code cleanup 2021-01-04 18:11:51 +01:00
1842c8390f fix for llvm < 11 2021-01-04 17:53:47 +01:00
9c15f53a47 fix for changes in llvm 12 2021-01-04 17:45:52 +01:00
b7af98e945 code cleanups (from cppcheck mostly) 2021-01-04 15:32:22 +01:00
5cdbfeef4a Revert "code cleanups (from cppcheck)"
This reverts commit 33a7d6f168.
2021-01-04 15:17:39 +01:00
33a7d6f168 code cleanups (from cppcheck) 2021-01-04 15:14:20 +01:00
c423aebb1a FP support for cmplog 2021-01-04 12:57:29 +01:00
58039d181a stability fix 2021-01-03 12:34:23 +01:00
880513651d cmplog cleanup 2021-01-03 10:13:55 +01:00
1857df8d06 cleanup 2021-01-03 00:37:56 +01:00
3c88de565a afl-cmin tests: allow leading whitespace in wc -l output 2021-01-02 23:17:30 +01:00
8bcb17b11f Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-01-02 23:16:37 +01:00
848db92196 build_unicorn_support.sh: allow DragonFly to build 2021-01-02 23:15:55 +01:00
6ed465bacc afl-system-config: cosmetic support for DragonFly 2021-01-02 23:14:29 +01:00
e83a1bc0d1 test-basic.sh: fix color GRAY to GREY 2021-01-02 20:18:26 +01:00
33abd70647 typo 2021-01-02 20:06:02 +01:00
84d3192f01 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2021-01-02 20:01:19 +01:00
d2a1f05a69 add first support for DragonFly OS 2021-01-02 19:59:06 +01:00
7620f6f396 Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev 2021-01-02 11:36:17 +01:00
214da5c42e fix qemu linking error with mips 2021-01-02 11:36:06 +01:00
697e3e285b add missing git submodule sync 2021-01-02 08:35:27 +01:00
fac373ec9e try new weighting 2021-01-01 13:42:58 +01:00
16d2bd3177 doc update 2021-01-01 13:34:24 +01:00
af10a635f5 Merge pull request #670 from devnexen/libdislocator_build_fix
libdislocator, ptr algo warning fix on clang/Xcode (m1).
2020-12-31 15:56:57 +01:00
935724557f libdislocator, ptr algo warning fix on clang/Xcode (m1). 2020-12-31 11:38:35 +00:00
7e6645d5a2 float2double 2020-12-31 11:51:10 +01:00
271116f870 Merge pull request #666 from AFLplusplus/dev
push to stable
2020-12-30 18:13:55 +01:00
84e72b0a51 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2020-12-30 13:03:13 +01:00
b0d69f1b69 cleanup of hot fix for -s on 32-bit 2020-12-30 13:02:11 +01:00
f38595f6b4 better weighting 2020-12-30 12:32:55 +01:00
5a99e67e02 add less to Dockerfile 2020-12-30 11:02:00 +01:00
0246fe9200 fix 32-bit mode, fix weighting 2020-12-30 10:34:22 +01:00
5d560c1ece tests: let afl-fuzz run with -D, so more test cases are produced 2020-12-29 23:54:10 +01:00
d687fbdfb4 fix CodeQL warning on theoretically possible unsigned overflow 2020-12-29 19:53:56 +01:00
e9a306a50e fix localtime warnings from CodeQL 2020-12-29 10:25:48 +01:00
107c79b84b now fix afl-clang compiles on 32-Bit properly 2020-12-29 18:17:50 +01:00
80767480f0 Revert "fix afl-clang on 32-Bit systems"
This reverts commit 83c1378fc1.
2020-12-29 18:13:36 +01:00
83c1378fc1 fix afl-clang on 32-Bit systems 2020-12-29 14:19:35 +01:00
871d42e389 Merge pull request #665 from mboehme/patch-1
Handle disabled seeds properly in distribution-based schedule
2020-12-29 12:18:02 +01:00
0922763db1 Update afl-fuzz-queue.c 2020-12-29 14:57:05 +11:00
d103e39f58 fix instrumentation type display 2020-12-28 17:06:55 +01:00
3f871d1d8f allow tests when utils/aflpp_driver fails to build (platform support) 2020-12-28 16:29:30 +01:00
688f4ffb89 added corpus introspection 2020-12-28 14:01:48 +01:00
41dad9ab7d Merge pull request #664 from AFLplusplus/dev
fix CFLAGS for extra libs
2020-12-28 13:54:17 +01:00
108e28ff10 fix CFLAGS for extra libs 2020-12-28 13:53:11 +01:00
e22db8d609 Merge pull request #663 from AFLplusplus/dev
Fix Dockerfile
2020-12-28 13:32:51 +01:00
f1b4b38152 fix dockerfile for older CPUs 2020-12-28 13:31:20 +01:00
8e2b59ffca more flexible system support for afl-frida 2020-12-26 23:04:21 +01:00
7375d8fcb7 Merge pull request #661 from Manouchehri/dev
Fix missing Apple headers for afl_frida
2020-12-26 22:09:03 +01:00
2c4b51b437 utils/afl_frida is not 5% faster 2020-12-26 22:01:49 +01:00
fe0dca9d96 fixed a few forgotten old afl-llvm-rt references 2020-12-26 21:33:54 +01:00
159707f74c Include Apple headers. 2020-12-26 15:32:22 -05:00
4af0065f4a Fix missing include for macOS. (#660) 2020-12-26 20:23:59 +01:00
fa933036a7 Merge pull request #658 from AFLplusplus/dev
fix exec/s display
2020-12-26 13:29:07 +01:00
0b9ca807f2 fix exec/s display 2020-12-26 13:15:05 +01:00
450fd17451 Merge pull request #654 from AFLplusplus/dev
fix LTO
2020-12-25 12:25:05 +01:00
a4fd4ea0f4 fix LTO 2020-12-25 12:13:45 +01:00
949f075247 revert condition on llvm-config.h (it did not work) 2020-12-24 12:08:01 +01:00
895d0778b6 fix conditional include 2020-12-24 11:40:02 +01:00
dbdb95bc23 use positive logic to be future safe 2020-12-24 10:46:59 +01:00
92bf656cd3 better wording, typo 2020-12-24 09:57:33 +01:00
849b8cd084 typo 2020-12-23 18:38:12 +01:00
03849d147a warn on _AFL and __AFL env vars 2020-12-23 17:56:39 +01:00
1c79687dfe faster llvm compile, update README 2020-12-23 15:56:25 +01:00
1fe3af0418 update unicorn checkout 2020-12-23 15:55:02 +01:00
7dc433a0c0 Merge pull request #637 from AFLplusplus/dev
minor push to stable
2020-12-23 14:58:52 +01:00
8d10d12ab3 Merge pull request #629 from rchildre3/qemu-flags
Cleanup QEMU configuration options
2020-12-23 12:51:45 +01:00
ceed19f275 Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2020-12-22 20:33:56 +01:00
9a5ea5b5c2 workaround for Solaris: NAME_MAX is not defined 2020-12-22 20:33:06 +01:00
e790667fd2 one more with nonstd array initializers 2020-12-22 20:29:22 +01:00
8241ded12e more portability non std array initializers 2020-12-22 20:19:43 +01:00
f18afa8ccd Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev 2020-12-22 19:42:00 +01:00
2a994e457a portability: avoid void * arithmetic (UB), avoid GNU extension for array initializations 2020-12-22 19:39:49 +01:00
9759320266 afl-clang-fast fix 2020-12-22 12:33:58 +01:00
27b9ba4502 better gcc and clang support for afl-cc 2020-12-22 10:51:40 +01:00
e8374e3deb temporary fix for unusual builds where CC is set 2020-12-21 17:04:58 +01:00
f37cc223d8 Merge branch 'stable' into dev 2020-12-21 14:25:50 +01:00
6f0f167b73 test: skip afl-fuzz test if too few locations were instrumented 2020-12-21 14:05:58 +01:00
a39228def6 make ubuntu 18.04 ci work 2020-12-21 13:36:09 +01:00
f7ceafab1c fix BSD 2020-12-21 13:21:40 +01:00
2a22dc433c ci fix 2020-12-21 13:01:56 +01:00
6e27c66058 ci fix 2020-12-21 12:48:02 +01:00
7172302be8 ci fix 2020-12-21 12:38:12 +01:00
b42f405e60 ci fix 2020-12-21 12:35:09 +01:00
816ba61080 fix ci 2020-12-21 12:27:06 +01:00
7e27448dac another 32 bit fix 2020-12-21 12:19:22 +01:00
2a0d066121 update ci 2020-12-21 12:14:08 +01:00
1078409875 Create ci.yml 2020-12-21 12:06:06 +01:00
45a68760ee fix 32 bit 2020-12-21 12:02:01 +01:00
ed85d5374b switch to github actions 2020-12-21 11:56:01 +01:00
47e04548d4 Merge pull request #649 from AFLplusplus/skim_romu
switch to romu and skim
2020-12-21 11:19:18 +01:00
6d1f17d78d Merge branch 'dev' into skim_romu 2020-12-21 11:02:09 +01:00
c28ecbbb2b update codeql yml 2020-12-21 10:59:29 +01:00
bf3ba489a0 Merge pull request #648 from AFLplusplus/add-codeql
Add codeql
2020-12-21 09:52:38 +01:00
f9d9ff2cd2 Create codeql-analysis.yml 2020-12-21 09:52:20 +01:00
0b4f6adfee Merge pull request #647 from rchildre3/binary-only-make
Remove binary-only target's depend on source tools
2020-12-21 01:57:59 +01:00
81e3e991a7 Test Python and Shared Memory in binary-only mode 2020-12-20 19:54:40 -05:00
eddabf6b05 Remove binary-only target's depend on source tools
The `binary-only` target currently depends on the `all` target which
always build the source tools, such as afl-cc and afl-as.  This is
unnecessary if the user specifically is asking for only binary fuzzing
tools.
2020-12-20 19:39:28 -05:00
2e3cf10070 document AFL_LLVM_INSTRUMENT option NATIVE 2020-12-20 22:53:41 +01:00
59c1c6a431 fix for non-default gcc installations 2020-12-20 14:42:45 +01:00
98ee17bc47 fix endless loop in afl-cc allow/blocklists starting a line with a comment 2020-12-20 14:30:06 +01:00
a6116ed533 Merge pull request #646 from pr0xy-t/dev
fixed typo in include/forkserver.h
2020-12-20 12:15:31 +01:00
bc9f956c84 update changelog 2020-12-20 11:30:11 +01:00
e1a7ed9d6e fixed typo in include/forkserver.h 2020-12-20 18:54:32 +09:00
7374503f14 add tinyinst to binary fuzzing tools 2020-12-19 09:55:51 +01:00
12ebb351dc apply nocolor changes 2020-12-18 21:10:39 +01:00
73dd6d86ab dont fail with ASAN_BUILD 2020-12-18 16:38:24 +01:00
2748d5c962 fix 2020-12-18 16:16:22 +01:00
ea9db86bb8 mem error fix 2020-12-18 10:20:43 +01:00
4ff9eb0e67 fix compile 2020-12-18 10:02:26 +01:00
f0b6576f97 fix 2020-12-18 09:55:47 +01:00
3ee12009c0 Merge pull request #641 from AFLplusplus/dev
Dev
2020-12-18 09:36:22 +01:00
0011f2047b merge romu and skim 2020-12-18 09:33:52 +01:00
79c98731c9 small improvements: dump output on error in test-llvm, fix compiler warnings 2020-12-18 09:22:58 +01:00
b6b907705e afl-cmin: skip instrumentation check if AFL_SKIP_BIN_CHECK is set 2020-12-18 00:18:30 +01:00
fd6bff727a fix crash for very fast targets 2020-12-17 22:57:28 +01:00
3282775a15 Cleanup QEMU configuration options
Take into account `STATIC`, `DEBUG`, and `PROFILING`

Turn off most options

Remove non-exsistant config options (e.g. bluez)
2020-12-17 14:23:16 -05:00
d07b0169cb skim import 2020-12-17 10:55:33 +01:00
14c67f15c9 small fixes 2020-12-16 14:22:09 +01:00
6e0aeb9833 allow instrumenting LLVMFuzzerTestOneInput 2020-12-15 18:17:55 +01:00
db76b06e01 add dummy Makefile to instrumentation/ 2020-12-15 18:07:01 +01:00
1fc0918ac0 v3.01a init 2020-12-15 09:55:33 +01:00
208 changed files with 24381 additions and 4108 deletions

View File

@ -33,13 +33,13 @@ if CLANG_FORMAT_BIN is None:
o, _ = p.communicate()
o = str(o, "utf-8")
o = re.sub(r".*ersion ", "", o)
#o = o[len("clang-format version "):].strip()
o = o[:o.find(".")]
# o = o[len("clang-format version "):].strip()
o = o[: o.find(".")]
o = int(o)
except:
print ("clang-format-11 is needed. Aborted.")
print("clang-format-11 is needed. Aborted.")
exit(1)
#if o < 7:
# if o < 7:
# if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
# CLANG_FORMAT_BIN = 'clang-format-7'
# elif subprocess.call(['which', 'clang-format-8'], stdout=subprocess.PIPE) == 0:
@ -52,8 +52,8 @@ if CLANG_FORMAT_BIN is None:
# print ("clang-format 7 or above is needed. Aborted.")
# exit(1)
else:
CLANG_FORMAT_BIN = 'clang-format-11'
CLANG_FORMAT_BIN = "clang-format-11"
COLUMN_LIMIT = 80
for line in fmt.split("\n"):
line = line.split(":")
@ -69,26 +69,47 @@ def custom_format(filename):
in_define = False
last_line = None
out = ""
for line in src.split("\n"):
if line.lstrip().startswith("#"):
if line[line.find("#")+1:].lstrip().startswith("define"):
if line[line.find("#") + 1 :].lstrip().startswith("define"):
in_define = True
if "/*" in line and not line.strip().startswith("/*") and line.endswith("*/") and len(line) < (COLUMN_LIMIT-2):
if (
"/*" in line
and not line.strip().startswith("/*")
and line.endswith("*/")
and len(line) < (COLUMN_LIMIT - 2)
):
cmt_start = line.rfind("/*")
line = line[:cmt_start] + " " * (COLUMN_LIMIT-2 - len(line)) + line[cmt_start:]
line = (
line[:cmt_start]
+ " " * (COLUMN_LIMIT - 2 - len(line))
+ line[cmt_start:]
)
define_padding = 0
if last_line is not None and in_define and last_line.endswith("\\"):
last_line = last_line[:-1]
define_padding = max(0, len(last_line[last_line.rfind("\n")+1:]))
define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :]))
if last_line is not None and last_line.strip().endswith("{") and line.strip() != "":
if (
last_line is not None
and last_line.strip().endswith("{")
and line.strip() != ""
):
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
elif last_line is not None and last_line.strip().startswith("}") and line.strip() != "":
elif (
last_line is not None
and last_line.strip().startswith("}")
and line.strip() != ""
):
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
elif line.strip().startswith("}") and last_line is not None and last_line.strip() != "":
elif (
line.strip().startswith("}")
and last_line is not None
and last_line.strip() != ""
):
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
if not line.endswith("\\"):
@ -97,14 +118,15 @@ def custom_format(filename):
out += line + "\n"
last_line = line
return (out)
return out
args = sys.argv[1:]
if len(args) == 0:
print ("Usage: ./format.py [-i] <filename>")
print ()
print (" The -i option, if specified, let the script to modify in-place")
print (" the source files. By default the results are written to stdout.")
print("Usage: ./format.py [-i] <filename>")
print()
print(" The -i option, if specified, let the script to modify in-place")
print(" the source files. By default the results are written to stdout.")
print()
exit(1)
@ -120,4 +142,3 @@ for filename in args:
f.write(code)
else:
print(code)

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**IMPORTANT**
1. You have verified that the issue to be present in the current `dev` branch
2. Please supply the command line options and relevant environment variables, e.g. a copy-paste of the contents of `out/default/fuzzer_setup`
Thank you for making afl++ better!
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. ...
2. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screen output/Screenshots**
If applicable, add copy-paste of the screen output or screenshot that shows the issue. Please ensure the output is in **English** and not in Chinese, Russian, German, etc.
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -0,0 +1,27 @@
name: Publish Docker Images
on:
push:
branches: [ stable ]
paths:
- Dockerfile
pull_request:
branches: [ stable ]
paths:
- Dockerfile
jobs:
push_to_registry:
name: Push Docker images to Dockerhub
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Publish aflpp to Registry
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: aflplusplus/aflplusplus:latest

28
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: CI
on:
push:
branches: [ stable, dev ]
# pull_request:
# branches: [ stable, dev ]
jobs:
build:
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
steps:
- uses: actions/checkout@v2
- name: debug
run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format-
- name: install packages
run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools
- name: compiler installed
run: gcc -v ; echo ; clang -v
- name: install gcc plugin
run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev
- name: build afl++
run: make distrib ASAN_BUILD=1
- name: run tests
run: sudo -E ./afl-system-config ; export AFL_SKIP_CPUFREQ=1 ; make tests

32
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: "CodeQL"
on:
push:
branches: [ stable, dev ]
# pull_request:
# branches: [ stable, dev ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -0,0 +1,30 @@
name: Rust Custom Mutators
on:
push:
branches: [ stable, dev ]
pull_request:
branches: [ stable, dev ]
jobs:
test:
name: Test Rust Custom Mutator Support
runs-on: '${{ matrix.os }}'
defaults:
run:
working-directory: custom_mutators/rust
strategy:
matrix:
os: [ubuntu-20.04]
steps:
- uses: actions/checkout@v2
- name: Install Rust Toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Check Code Compiles
run: cargo check
- name: Run General Tests
run: cargo test
- name: Run Tests for afl_internals feature flag
run: cd custom_mutator && cargo test --features=afl_internals

1
.gitignore vendored
View File

@ -82,3 +82,4 @@ examples/aflpp_driver/libAFLQemuDriver.a
libAFLDriver.a
libAFLQemuDriver.a
test/.afl_performance
gmon.out

View File

@ -1,59 +0,0 @@
language: c
sudo: required
branches:
only:
- stable
- dev
matrix:
include:
#- os: linux # again disabled because fetching packages times out very often :(
# dist: focal
# env: NAME="focal-amd64" MODERN="yes" GCC="9"
- os: linux
dist: bionic
env: NAME="bionic-amd64" MODERN="yes" GCC="7"
- os: linux
dist: xenial
env: NAME="xenial-amd64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0"
# - os: linux # disabled: fatal: unable to access 'https://git.qemu.org/git/capstone/': gnutls_handshake() failed: Handshake failed
# dist: trusty
# env: NAME="trusty-amd64" MODERN="no" GCC="4.8"
- os: linux # until travis can fix this!
dist: xenial
arch: arm64
env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64"
# - os: osx
# osx_image: xcode11.2
# env: NAME="osx" HOMEBREW_NO_ANALYTICS="1" LINK="http://releases.llvm.org/9.0.0/" NAME="clang+llvm-9.0.0-x86_64-darwin-apple"
jobs:
allow_failures:
- os: osx
- arch: arm64
env:
- AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_EXIT_WHEN_DONE=1
# TODO: test AFL_BENCH_UNTIL_CRASH once we have a target that crashes
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_BENCH_JUST_ONE=1
before_install:
# export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
- echo Testing on $NAME
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y git libtool libtool-bin automake bison libglib2.0-0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev python3-setuptools ; fi
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y git libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev python3-setuptools ; fi
script:
- gcc -v
- clang -v
- sudo -E ./afl-system-config
- sudo sysctl -w kernel.shmmax=10000000000
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ASAN_BUILD=1 ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ASAN_BUILD=1 ; fi
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then export LLVM_CONFIG=llvm-config-6.0 ; make ASAN_BUILD=1 ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
- make tests
# - travis_terminate 0

View File

@ -1,7 +1,16 @@
cc_defaults {
name: "afl-defaults",
sanitize: {
never: true,
},
local_include_dirs: [
"include",
"instrumentation",
],
cflags: [
"-flto=full",
"-funroll-loops",
"-Wno-pointer-sign",
"-Wno-pointer-arith",
@ -10,24 +19,35 @@ cc_defaults {
"-Wno-unused-function",
"-Wno-format",
"-Wno-user-defined-warnings",
"-DUSE_TRACE_PC=1",
"-DAFL_LLVM_USE_TRACE_PC=1",
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
"-D__USE_GNU",
"-D__aarch64__",
"-DDEBUG_BUILD",
"-U_FORTIFY_SOURCE",
"-ggdb3",
"-g",
"-O0",
"-fno-omit-frame-pointer",
],
}
cc_binary {
name: "afl-fuzz",
static_executable: true,
host_supported: true,
compile_multilib: "64",
defaults: [
"afl-defaults",
],
srcs: [
"afl-fuzz.c",
"src/afl-fuzz*.c",
"src/afl-common.c",
"src/afl-sharedmem.c",
"src/afl-forkserver.c",
"src/afl-performance.c",
],
}
@ -41,7 +61,11 @@ cc_binary {
],
srcs: [
"afl-showmap.c",
"src/afl-showmap.c",
"src/afl-common.c",
"src/afl-sharedmem.c",
"src/afl-forkserver.c",
"src/afl-performance.c",
],
}
@ -55,7 +79,11 @@ cc_binary {
],
srcs: [
"afl-tmin.c",
"src/afl-tmin.c",
"src/afl-common.c",
"src/afl-sharedmem.c",
"src/afl-forkserver.c",
"src/afl-performance.c",
],
}
@ -69,7 +97,10 @@ cc_binary {
],
srcs: [
"afl-analyze.c",
"src/afl-analyze.c",
"src/afl-common.c",
"src/afl-sharedmem.c",
"src/afl-performance.c",
],
}
@ -83,12 +114,13 @@ cc_binary {
],
srcs: [
"afl-gotcpu.c",
"src/afl-gotcpu.c",
"src/afl-common.c",
],
}
cc_binary_host {
name: "afl-clang-fast",
name: "afl-cc",
static_executable: true,
defaults: [
@ -98,44 +130,144 @@ cc_binary_host {
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
"-DAFL_CLANG_FLTO=\"-flto=full\"",
"-DUSE_BINDIR=1",
"-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
"-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
"-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
"-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
"-DLLVM_LTO=1",
"-DLLVM_MAJOR=11",
"-DLLVM_MINOR=2",
],
srcs: [
"src/afl-cc.c",
],
}
cc_binary_host {
name: "afl-clang-fast++",
static_executable: true,
defaults: [
"afl-defaults",
"src/afl-common.c",
],
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
],
srcs: [
"src/afl-cc.c",
symlinks: [
"afl-clang-fast",
"afl-clang-fast++",
],
}
cc_library_static {
name: "afl-llvm-rt",
compile_multilib: "both",
compile_multilib: "64",
vendor_available: true,
host_supported: true,
recovery_available: true,
sdk_version: "9",
apex_available: [
"com.android.adbd",
"com.android.appsearch",
"com.android.art",
"com.android.bluetooth.updatable",
"com.android.cellbroadcast",
"com.android.conscrypt",
"com.android.extservices",
"com.android.cronet",
"com.android.neuralnetworks",
"com.android.media",
"com.android.media.swcodec",
"com.android.mediaprovider",
"com.android.permission",
"com.android.runtime",
"com.android.resolv",
"com.android.tethering",
"com.android.wifi",
"com.android.sdkext",
"com.android.os.statsd",
"//any",
],
defaults: [
"afl-defaults",
],
srcs: [
"instrumentation/afl-llvm-rt.o.c",
"instrumentation/afl-compiler-rt.o.c",
],
}
cc_library_headers {
name: "libafl_headers",
vendor_available: true,
host_supported: true,
export_include_dirs: [
"include",
],
}
cc_prebuilt_library_static {
name: "libfrida-gum",
compile_multilib: "64",
strip: {
none: true,
},
srcs: [
"utils/afl_frida/android/libfrida-gum.a",
],
export_include_dirs: [
"utils/afl_frida/android",
],
}
cc_library_shared {
name: "libtestinstr",
srcs: [
"utils/afl_frida/libtestinstr.c",
],
cflags: [
"-O0",
"-fPIC",
],
}
cc_binary {
name: "afl-frida",
compile_multilib: "64",
defaults: [
"afl-defaults",
],
cflags: [
"-g",
"-O0",
"-Wno-format",
"-Wno-pointer-sign",
"-fpermissive",
"-fPIC",
],
static_libs: [
"afl-llvm-rt",
"libfrida-gum",
],
shared_libs: [
"libdl",
"liblog",
],
srcs: [
"utils/afl_frida/afl-frida.c",
],
local_include_dirs: [
"utils/afl_frida",
"utils/afl_frida/android",
],
}
subdirs = [
"custom_mutators",
]

View File

@ -1 +0,0 @@
Makefile

View File

@ -11,22 +11,25 @@ LABEL "about"="AFLplusplus docker image"
ARG DEBIAN_FRONTEND=noninteractive
env NO_ARCH_OPT 1
RUN apt-get update && \
apt-get -y install --no-install-suggests --no-install-recommends \
automake \
ninja-build \
bison flex \
build-essential \
git \
python3 python3-dev python3-setuptools python-is-python3 \
libtool libtool-bin \
libglib2.0-dev \
wget vim jupp nano bash-completion \
wget vim jupp nano bash-completion less \
apt-utils apt-transport-https ca-certificates gnupg dialog \
libpixman-1-dev \
gnuplot-nox \
&& rm -rf /var/lib/apt/lists/*
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main" >> /etc/apt/sources.list && \
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main" >> /etc/apt/sources.list && \
wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu focal main" >> /etc/apt/sources.list && \
@ -35,27 +38,27 @@ RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu focal main
RUN apt-get update && apt-get full-upgrade -y && \
apt-get -y install --no-install-suggests --no-install-recommends \
gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib gdb lcov \
clang-11 clang-tools-11 libc++1-11 libc++-11-dev \
libc++abi1-11 libc++abi-11-dev libclang1-11 libclang-11-dev \
libclang-common-11-dev libclang-cpp11 libclang-cpp11-dev liblld-11 \
liblld-11-dev liblldb-11 liblldb-11-dev libllvm11 libomp-11-dev \
libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools \
clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools \
&& rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 0
RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
ENV LLVM_CONFIG=llvm-config-11
ENV LLVM_CONFIG=llvm-config-12
ENV AFL_SKIP_CPUFREQ=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN git clone https://github.com/vanhauser-thc/afl-cov /afl-cov
RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov /afl-cov
RUN cd /afl-cov && make install && cd ..
COPY . /AFLplusplus
WORKDIR /AFLplusplus
RUN export REAL_CXX=g++-10 && export CC=gcc-10 && \
export CXX=g++-10 && make clean && \
RUN export CC=gcc-10 && export CXX=g++-10 && make clean && \
make distrib && make install && make clean
RUN echo 'alias joe="jupp --wordwrap"' >> ~/.bashrc

View File

@ -24,7 +24,7 @@ BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/man/man8
MAN_PATH = $(PREFIX)/share/man/man8
PROGNAME = afl
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
@ -42,8 +42,8 @@ endif
ifdef ASAN_BUILD
$(info Compiling ASAN version of binaries)
override CFLAGS+=$(ASAN_CFLAGS)
LDFLAGS+=$(ASAN_LDFLAGS)
override CFLAGS += $(ASAN_CFLAGS)
LDFLAGS += $(ASAN_LDFLAGS)
endif
ifdef UBSAN_BUILD
$(info Compiling UBSAN version of binaries)
@ -57,8 +57,6 @@ ifdef MSAN_BUILD
override LDFLAGS += -fsanitize=memory
endif
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
CFLAGS_FLTO ?= -flto=full
@ -77,30 +75,34 @@ ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -
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
ifneq "$(shell uname)" "Darwin"
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
#CFLAGS_OPT += -march=native
SPECIAL_PERFORMANCE += -march=native
endif
endif
#ifeq "$(HAVE_MARCHNATIVE)" "1"
# SPECIAL_PERFORMANCE += -march=native
#endif
# OS X does not like _FORTIFY_SOURCE=2
ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif
ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif
endif
ifeq "$(shell uname)" "SunOS"
CFLAGS_OPT += -Wno-format-truncation
LDFLAGS=-lkstat -lrt
CFLAGS_OPT += -Wno-format-truncation
LDFLAGS = -lkstat -lrt
endif
ifdef STATIC
$(info Compiling static version of binaries, disabling python though)
# Disable python for static compilation to simplify things
PYTHON_OK=0
PYTHON_OK = 0
PYFLAGS=
PYTHON_INCLUDE=/
PYTHON_INCLUDE = /
CFLAGS_OPT += -static
LDFLAGS += -lm -lpthread -lz -lutil
@ -117,6 +119,7 @@ ifdef INTROSPECTION
CFLAGS_OPT += -DINTROSPECTION=1
endif
ifneq "$(shell uname -m)" "x86_64"
ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386"
ifneq "$(shell uname -m)" "amd64"
@ -131,7 +134,7 @@ ifdef DEBUG
$(info Compiling DEBUG version of binaries)
CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror
else
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
endif
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
@ -302,7 +305,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
.PHONY: llvm
llvm:
-$(MAKE) -f GNUmakefile.llvm
-$(MAKE) -j -f GNUmakefile.llvm
@test -e afl-cc || { echo "[-] Compiling afl-cc failed. You seem not to have a working compiler." ; exit 1; }
.PHONY: gcc_plugin
@ -409,7 +412,7 @@ 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) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
$(CC) $(CFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -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
@ -423,8 +426,8 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
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
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
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-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(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)
@ -504,6 +507,8 @@ code-format:
./.custom-format.py -i qemu_mode/libcompcov/*.c
./.custom-format.py -i qemu_mode/libcompcov/*.cc
./.custom-format.py -i qemu_mode/libcompcov/*.h
./.custom-format.py -i qemu_mode/libqasan/*.c
./.custom-format.py -i qemu_mode/libqasan/*.h
./.custom-format.py -i *.h
./.custom-format.py -i *.c
@ -512,23 +517,23 @@ code-format:
ifndef AFL_NO_X86
test_build: afl-cc afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
@echo
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
@echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option."; echo "See docs/INSTALL.md section 5 how to build a -B enabled gcc." ) || \
( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
@echo
@echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
# @rm -f test-instr
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
# gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option."; echo "See docs/INSTALL.md section 5 how to build a -B enabled gcc." ) || \
# ( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
# @echo
# @echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
else
test_build: afl-cc afl-as afl-showmap
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
@ -558,6 +563,7 @@ clean:
$(MAKE) -C utils/argv_fuzzing clean
$(MAKE) -C qemu_mode/unsigaction clean
$(MAKE) -C qemu_mode/libcompcov clean
$(MAKE) -C qemu_mode/libqasan clean
ifeq "$(IN_REPO)" "1"
test -e qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true
test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
@ -574,11 +580,11 @@ deepclean: clean
.PHONY: distrib
distrib: all
-$(MAKE) -f GNUmakefile.llvm
-$(MAKE) -j -f GNUmakefile.llvm
-$(MAKE) -f GNUmakefile.gcc_plugin
$(MAKE) -C utils/libdislocator
$(MAKE) -C utils/libtokencap
$(MAKE) -C utils/aflpp_driver
-$(MAKE) -C utils/aflpp_driver
$(MAKE) -C utils/afl_network_proxy
$(MAKE) -C utils/socket_fuzzing
$(MAKE) -C utils/argv_fuzzing
@ -586,7 +592,7 @@ distrib: all
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
.PHONY: binary-only
binary-only: all
binary-only: test_shm test_python ready $(PROGS)
$(MAKE) -C utils/libdislocator
$(MAKE) -C utils/libtokencap
$(MAKE) -C utils/afl_network_proxy
@ -597,11 +603,11 @@ binary-only: all
.PHONY: source-only
source-only: all
-$(MAKE) -f GNUmakefile.llvm
-$(MAKE) -j -f GNUmakefile.llvm
-$(MAKE) -f GNUmakefile.gcc_plugin
$(MAKE) -C utils/libdislocator
$(MAKE) -C utils/libtokencap
$(MAKE) -C utils/aflpp_driver
-$(MAKE) -C utils/aflpp_driver
%.8: %
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@ -633,6 +639,7 @@ install: all $(MANPAGES)
@if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f libqasan.so ]; then set -e; install -m 755 libqasan.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi

View File

@ -138,7 +138,7 @@ afl-common.o: ./src/afl-common.c
.PHONY: test_build
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
unset AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr

View File

@ -43,7 +43,8 @@ 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 | egrep -q '^3\.[0-3]|^19' && echo 1 || echo 0 )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^[0-2]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[3-9]' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]' && echo 1 || echo 0 )
@ -58,7 +59,11 @@ ifeq "$(LLVMVER)" ""
endif
ifeq "$(LLVM_UNSUPPORTED)" "1"
$(warning llvm_mode only supports llvm versions 3.4 up to 12)
$(error llvm_mode only supports llvm from version 3.4 onwards)
endif
ifeq "$(LLVM_TOO_NEW)" "1"
$(warning you are using an in-development llvm version - this might break llvm_mode!)
endif
LLVM_TOO_OLD=1
@ -208,12 +213,12 @@ ifeq "$(LLVM_LTO)" "1"
ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" ""
AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld
else
$(warn ld.lld not found, cannot enable LTO mode)
$(warning ld.lld not found, cannot enable LTO mode)
LLVM_LTO = 0
endif
endif
else
$(warn clang option -flto is not working - maybe LLVMgold.so not found - cannot enable LTO mode)
$(warning clang option -flto is not working - maybe LLVMgold.so not found - cannot enable LTO mode)
LLVM_LTO = 0
endif
endif
@ -226,7 +231,7 @@ ifeq "$(LLVM_LTO)" "1"
AFL_CLANG_LDPATH=1
endif
else
$(warn -fuse-ld is not working, cannot enable LTO mode)
$(warning -fuse-ld is not working, cannot enable LTO mode)
LLVM_LTO = 0
endif
endif
@ -357,7 +362,7 @@ instrumentation/afl-common.o: ./src/afl-common.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
./afl-cc: src/afl-cc.c instrumentation/afl-common.o
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< instrumentation/afl-common.o -o $@ -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR) $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< instrumentation/afl-common.o -o $@ -DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR) $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" -lm
@ln -sf afl-cc ./afl-c++
@ln -sf afl-cc ./afl-gcc
@ln -sf afl-cc ./afl-g++
@ -452,7 +457,7 @@ document:
.PHONY: test_build
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr

207
README.md
View File

@ -2,11 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo">
![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=stable)
Release Version: [3.11c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release Version: [3.00c](https://github.com/AFLplusplus/AFLplusplus/releases)
Github Version: 3.00a
Github Version: 3.12a
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -23,26 +21,33 @@
mutations, more and better instrumentation, custom module support, etc.
If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
on the website.
on the website. To cite our work, look at the [Cite](#cite) section.
For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
with `AFL_LLVM_CMPLOG=1`.
## Major changes in afl++ 3.0
## Major changes in afl++ 3.00 + 3.10
With afl++ 3.0 we introduced changes that break some previous afl and afl++
With afl++ 3.10 we introduced the following changes from previous behaviours:
* The '+' feature of the '-t' option now means to auto-calculate the timeout
with the value given being the maximum timeout. The original meaning of
"skipping timeouts instead of abort" is now inherent to the -t option.
With afl++ 3.00 we introduced changes that break some previous afl and afl++
behaviours and defaults:
* There are no llvm_mode and gcc_plugin subdirectories anymore and there is
only one compiler: afl-cc. All previous compilers now symlink to this one
compiler. All instrumentation source code is now in the `instrumentation/`
folder.
only one compiler: afl-cc. All previous compilers now symlink to this one.
All instrumentation source code is now in the `instrumentation/` folder.
* The gcc_plugin was replaced with a new version submitted by AdaCore that
supports more features. thank you!
supports more features. Thank you!
* qemu_mode got upgraded to QEMU 5.1, but to be able to build this a current
ninja build tool version and python3 setuptools are required.
qemu_mode also got new options like snapshotting, instrumenting specific
shared libraries, etc. Additionally QEMU 5.1 supports more CPU targets so
this is really worth it.
* When instrumenting targets, afl-cc will not supersede optimizations. This
allows to fuzz targets as same as they are built for debug or release.
* When instrumenting targets, afl-cc will not supersede optimizations anymore
if any were given. This allows to fuzz targets as same as they are built
for debug or release.
* afl-fuzz:
* if neither -M or -S is specified, `-S default` is assumed, so more
fuzzers can easily be added later
@ -55,6 +60,7 @@ behaviours and defaults:
* a caching of testcases can now be performed and can be modified by
editing config.h for TESTCASE_CACHE or by specifying the env variable
`AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500 (default: 50).
* -M mains do not perform trimming
* examples/ got renamed to utils/
* libtokencap/ libdislocator/ and qdbi_mode/ were moved to utils/
* afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH
@ -67,9 +73,10 @@ behaviours and defaults:
3. [How to fuzz a target](#how-to-fuzz-with-afl)
4. [Fuzzing binary-only targets](#fuzzing-binary-only-targets)
5. [Good examples and writeups of afl++ usages](#good-examples-and-writeups)
6. [Branches](#branches)
7. [Want to help?](#help-wanted)
8. [Detailed help and description of afl++](#challenges-of-guided-fuzzing)
6. [CI Fuzzing](#ci-fuzzing)
7. [Branches](#branches)
8. [Want to help?](#help-wanted)
9. [Detailed help and description of afl++](#challenges-of-guided-fuzzing)
## Important features of afl++
@ -88,7 +95,7 @@ behaviours and defaults:
| Ngram prev_loc Coverage | | x(6) | | | |
| Context Coverage | | x(6) | | | |
| Auto Dictionary | | x(7) | | | |
| Snapshot LKM Support | | x | x | (x)(5) | |
| Snapshot LKM Support | | x(8) | x(8) | (x)(5) | |
1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
@ -97,6 +104,7 @@ behaviours and defaults:
5. upcoming, development in the branch
6. not compatible with LTO instrumentation and needs at least LLVM >= 4.1
7. automatic in LTO mode with LLVM >= 11, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
8. the snapshot LKM is currently unmaintained due to too many kernel changes coming too fast :-(
Among others, the following features and patches have been integrated:
@ -139,9 +147,6 @@ behaviours and defaults:
## Help wanted
We were happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)
and we will try to participate again in 2021!
We have several ideas we would like to see in AFL++ to make it even better.
However, we already work on so many things that we do not have the time for
all the big ideas.
@ -170,7 +175,7 @@ If you want to build afl++ yourself you have many options.
The easiest choice is to build and install everything:
```shell
sudo apt install build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools clang llvm llvm-dev libstdc++-dev
sudo apt install build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev python3-setuptools clang lld llvm llvm-dev libstdc++-dev
make distrib
sudo make install
```
@ -206,7 +211,7 @@ These build targets exist:
afl++ binaries by passing the STATIC=1 argument to make:
```shell
make all STATIC=1
make STATIC=1
```
These build options exist:
@ -221,7 +226,7 @@ These build options exist:
* 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 ASAN_BUILD=1
e.g.: `make ASAN_BUILD=1`
## Good examples and writeups
@ -233,6 +238,7 @@ Here are some good writeups to show how to effectively use AFL++:
* [https://securitylab.github.com/research/fuzzing-software-2](https://securitylab.github.com/research/fuzzing-software-2)
* [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
* [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
* [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
If you are interested in fuzzing structured data (where you define what the
structure is), these links have you covered:
@ -283,9 +289,9 @@ anything below 9 is not recommended.
|
v
+--------------------------------+
| if you want to instrument only | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast)
| parts of the target | see [instrumentation/README.gcc_plugin.md](instrumentation/README.gcc_plugin.md) and
+--------------------------------+ [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
| gcc 5+ is available | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast)
+--------------------------------+ see [instrumentation/README.gcc_plugin.md](instrumentation/README.gcc_plugin.md) and
[instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
|
| if not, or if you do not have a gcc with plugin support
|
@ -298,17 +304,17 @@ Clickable README links for the chosen compiler:
* [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
* [LLVM mode - afl-clang-fast](instrumentation/README.llvm.md)
* [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
* GCC mode (afl-gcc) has no README as it has no own features
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own features
You can select the mode for the afl-cc compiler by:
1. passing --afl-MODE command line options to the compiler via CFLAGS/CXXFLAGS/CPPFLAGS
2. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
1. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
afl-gcc-fast, afl-g++-fast
3. using the environment variable AFL_CC_COMPILER with MODE
afl-gcc-fast, afl-g++-fast (recommended!)
2. using the environment variable AFL_CC_COMPILER with MODE
3. passing --afl-MODE command line options to the compiler via CFLAGS/CXXFLAGS/CPPFLAGS
MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN
(afl-g*-fast) or GCC (afl-gcc/afl-g++).
(afl-g*-fast) or GCC (afl-gcc/afl-g++) or CLANG(afl-clang/afl-clang++).
Because no afl specific command-line options are accepted (beside the
--afl-MODE command), the compile-time tools make fairly broad use of environment
@ -338,14 +344,14 @@ The following options are available when you instrument with LTO mode (afl-clang
You can read more about this in [instrumentation/README.cmplog.md](instrumentation/README.cmplog.md)
If you use LTO, LLVM or GCC_PLUGIN mode (afl-clang-fast/afl-clang-lto/afl-gcc-fast)
you have the option to selectively only instrument parts of the target that you
you have the option to selectively only instrument parts of the target that you
are interested in:
* To instrument only those parts of the target that you are interested in
create a file with all the filenames of the source code that should be
instrumented.
For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if either the clang
version is below 7 or the CLASSIC instrumentation is used - just put one
For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode other than
DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one
filename or function per line (no directory information necessary for
filenames9, and either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or**
`export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per
@ -353,10 +359,6 @@ are interested in:
unless requested (ALLOWLIST).
**NOTE:** During optimization functions might be inlined and then would not match!
See [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
For afl-clang-fast > 6.0 or if PCGUARD instrumentation is used then use the
llvm sancov allow-list feature: [http://clang.llvm.org/docs/SanitizerCoverage.html](http://clang.llvm.org/docs/SanitizerCoverage.html)
The llvm sancov format works with the allowlist/denylist feature of afl++
however afl++'s format is more flexible.
There are many more options and modes available however these are most of the
time less effective. See:
@ -397,10 +399,19 @@ How to do this is described below.
Then build the target. (Usually with `make`)
**NOTE**: sometimes configure and build systems are fickle and do not like
stderr output (and think this means a test failure) - which is something
afl++ like to do to show statistics. It is recommended to disable them via
`export AFL_QUIET=1`.
**NOTES**
1. sometimes configure and build systems are fickle and do not like
stderr output (and think this means a test failure) - which is something
afl++ likes to do to show statistics. It is recommended to disable them via
`export AFL_QUIET=1`.
2. sometimes configure and build systems error on warnings - these should be
disabled (e.g. `--disable-werror` for some configure scripts).
3. in case the configure/build system complains about afl++'s compiler and
aborts then set `export AFL_NOOPT=1` which will then just behave like the
real compiler. This option has to be unset again before building the target!
##### configure
@ -482,8 +493,9 @@ default.
#### c) Minimizing all corpus files
The shorter the input files that still traverse the same path
within the target, the better the fuzzing will be. This is done with `afl-tmin`
however it is a long process as this has to be done for every file:
within the target, the better the fuzzing will be. This minimization
is done with `afl-tmin` however it is a long process as this has to
be done for every file:
```
mkdir input
@ -511,10 +523,6 @@ more useful.
If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
seriously :-)
Pro tip: load the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM)
before the start of afl-fuzz as this improves performance by a x2 speed increase
(less if you use a persistent mode harness)!
#### a) Running afl-fuzz
Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
@ -538,12 +546,10 @@ If you need to stop and re-start the fuzzing, use the same command line options
mutation mode!) and switch the input directory with a dash (`-`):
`afl-fuzz -i - -o output -- bin/target -d @@`
Note that afl-fuzz enforces memory limits to prevent the system to run out
of memory. By default this is 50MB for a process. If this is too little for
the target (which you can usually see by afl-fuzz bailing with the message
that it could not connect to the forkserver), then you can increase this
with the `-m` option, the value is in MB. To disable any memory limits
(beware!) set `-m none` - which is usually required for ASAN compiled targets.
Memory limits are not enforced by afl-fuzz by default and the system may run
out of memory. You can decrease the memory with the `-m` option, the value is
in MB. If this is too small for the target, you can usually see this by
afl-fuzz bailing with the message that it could not connect to the forkserver.
Adding a dictionary is helpful. See the directory [dictionaries/](dictionaries/) if
something is already included for your data format, and tell afl-fuzz to load
@ -556,7 +562,9 @@ afl-fuzz has a variety of options that help to workaround target quirks like
specific locations for the input file (`-f`), not performing deterministic
fuzzing (`-d`) and many more. Check out `afl-fuzz -h`.
afl-fuzz never stops fuzzing. To terminate afl++ simply press Control-C.
By default afl-fuzz never stops fuzzing. To terminate afl++ simply press Control-C
or send a signal SIGINT. You can limit the number of executions or approximate runtime
in seconds with options also.
When you start afl-fuzz you will see a user interface that shows what the status
is:
@ -597,13 +605,17 @@ For every secondary fuzzer there should be a variation, e.g.:
All other secondaries should be used like this:
* A third to a half with the MOpt mutator enabled: `-L 0`
* run with a different power schedule, available are:
`explore (default), fast, coe, lin, quad, exploit, mmopt, rare, seek`
`fast (default), explore, coe, lin, quad, exploit, mmopt, rare, seek`
which you can set with e.g. `-p seek`
Also it is recommended to set `export AFL_IMPORT_FIRST=1` to load testcases
from other fuzzers in the campaign first.
You can also use different fuzzers.
If you are using afl spinoffs or afl conforming fuzzers, then just use the
same -o directory and give it a unique `-S` name.
Examples are:
* [Eclipser](https://github.com/SoftSec-KAIST/Eclipser/)
* [Untracer](https://github.com/FoRTE-Research/UnTracer-AFL)
* [AFLsmart](https://github.com/aflsmart/aflsmart)
* [FairFuzz](https://github.com/carolemieux/afl-rb)
@ -613,7 +625,7 @@ Examples are:
A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
However you can also sync afl++ with honggfuzz, libfuzzer with -entropic, etc.
Just show the main fuzzer (-M) with the `-F` option where the queue
Just show the main fuzzer (-M) with the `-F` option where the queue/work
directory of a different fuzzer is, e.g. `-F /src/target/honggfuzz`.
#### c) The status of the fuzz campaign
@ -678,7 +690,6 @@ switch or honggfuzz.
* Use [persistent mode](instrumentation/README.persistent_mode.md) (x2-x20 speed increase)
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [docs/env_variables.md](docs/env_variables.md)
* Linux: Use the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase)
* Linux: Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure)
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
* Use your cores! [3.b) Using multiple cores/threads](#b-using-multiple-coresthreads)
@ -695,8 +706,11 @@ If you want to know more, the rest of this README and the tons of texts in
Note that there are also a lot of tools out there that help fuzzing with afl++
(some might be deprecated or unsupported):
Speeding up fuzzing:
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the function you want to fuzz requires loading a file, this allows using the shared memory testcase feature :-) - recommended.
Minimization of test cases:
* [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin that tries to speed up the process of the minimization of test case by using many CPU cores.
* [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin that tries to speed up the process of minimization of a single test case by using many CPU cores.
* [afl-ddmin-mod](https://github.com/MarkusTeufelberger/afl-ddmin-mod) - a variation of afl-tmin based on the ddmin algorithm.
* [halfempty](https://github.com/googleprojectzero/halfempty) - is a fast utility for minimizing test cases by Tavis Ormandy based on parallelization.
@ -724,11 +738,57 @@ Crash processing
* [AFLize](https://github.com/d33tah/aflize) - a tool that automatically generates builds of debian packages suitable for AFL.
* [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for working with input data.
## CI Fuzzing
Some notes on CI Fuzzing - this fuzzing is different to normal fuzzing
campaigns as these are much shorter runnings.
1. Always:
* LTO has a much longer compile time which is diametrical to short fuzzing -
hence use afl-clang-fast instead.
* If you compile with CMPLOG then you can save fuzzing time and reuse that
compiled target for both the -c option and the main fuzz target.
This will impact the speed by ~15% though.
* `AFL_FAST_CAL` - Enable fast calibration, this halfs the time the saturated
corpus needs to be loaded.
* `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new found paths, not the
initial corpus as this very likely has been done for them already.
* Keep the generated corpus, use afl-cmin and reuse it everytime!
2. Additionally randomize the afl++ compilation options, e.g.
* 40% for `AFL_LLVM_CMPLOG`
* 10% for `AFL_LLVM_LAF_ALL`
3. Also randomize the afl-fuzz runtime options, e.g.
* 60% for `AFL_DISABLE_TRIM`
* 50% use a dictionary generated by `AFL_LLVM_DICT2FILE`
* 50% use MOpt (`-L 0`)
* 40% for `AFL_EXPAND_HAVOC_NOW`
* 30% for old queue processing (`-Z`)
* for CMPLOG targets, 60% for `-l 2`, 40% for `-l 3`
4. Do *not* run any `-M` modes, just running `-S` modes is better for CI fuzzing.
`-M` enables deterministic fuzzing, old queue handling etc. which is good for
a fuzzing 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/4bb61df7905c6005000f5766e966e6fe30ab4559/infra/base-images/base-builder/compile_afl#L69).
## Fuzzing binary-only targets
When source code is *NOT* available, afl++ offers various support for fast,
on-the-fly instrumentation of black-box binaries.
If you do not have to use Unicorn the following setup is recommended:
* run 1 afl-fuzz -Q instance with CMPLOG (`-c 0` + `AFL_COMPCOV_LEVEL=2`)
* run 1 afl-fuzz -Q instance with QASAN (`AFL_USE_QASAN=1`)
* run 1 afl-fuzz -Q instance with LAF (``AFL_PRELOAD=libcmpcov.so` + `AFL_COMPCOV_LEVEL=2`)
Then run as many instances as you have cores left with either -Q mode or - better -
use a binary rewriter like afl-dyninst, retrowrite, zipr, fibre, etc.
For Qemu mode, check out the persistent mode and snapshot features, they give
a huge speed improvement!
### QEMU
For linux programs and its libraries this is accomplished with a version of
@ -739,7 +799,8 @@ feature by doing:
cd qemu_mode
./build_qemu_support.sh
```
For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md).
For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md) -
check out the snapshot feature! :-)
If possible you should use the persistent mode, see [qemu_mode/README.persistent.md](qemu_mode/README.persistent.md).
The mode is approximately 2-5x slower than compile-time instrumentation, and is
less conducive to parallelization.
@ -747,11 +808,13 @@ less conducive to parallelization.
If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for
your binary, then you can use afl-fuzz normally and it will have twice
the speed compared to qemu_mode (but slower than persistent mode).
Note that several other binary rewriters exist, all with their advantages and
caveats.
### Unicorn
For non-Linux binaries you can use afl++'s unicorn mode which can emulate
anything you want - for the price of speed and the user writing scripts.
anything you want - for the price of speed and user written scripts.
See [unicorn_mode](unicorn_mode/README.md).
It can be easily built by:
@ -763,16 +826,16 @@ cd unicorn_mode
### Shared libraries
If the goal is to fuzz a dynamic library then there are two options available.
For both you need to write a small hardness that loads and calls the library.
For both you need to write a small harness that loads and calls the library.
Faster is the frida solution: [utils/afl_frida/README.md](utils/afl_frida/README.md)
Another, less precise and slower option is using ptrace with debugger interrupt
instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md)
instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md).
### More
A more comprehensive description of these and other options can be found in
[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md)
[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md).
## Challenges of guided fuzzing
@ -1114,7 +1177,7 @@ without feedback, bug reports, or patches from:
Khaled Yakdan Kuang-che Wu
Josephine Calliotte Konrad Welc
Thomas Rooijakkers David Carlier
Ruben ten Hove
Ruben ten Hove Joey Jiao
```
Thank you!
@ -1122,8 +1185,18 @@ Thank you!
## Cite
If you use AFLpluplus to compare to your work, please use either `afl-clang-lto`
or `afl-clang-fast` with `AFL_LLVM_CMPLOG=1` for building targets and
`afl-fuzz` with the command line option `-l 2` for fuzzing.
The most effective setup is the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20:
```
+ Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
Bibtex:
```bibtex
@inproceedings {AFLplusplus-Woot20,
author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse},
title = {{AFL++}: Combining Incremental Steps of Fuzzing Research},

13
TODO.md
View File

@ -2,20 +2,20 @@
## Roadmap 3.00+
- AFL_MAP_SIZE for qemu_mode and unicorn_mode
- CPU affinity for many cores? There seems to be an issue > 96 cores
- afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin()
- afl_custom_splice()
- intel-pt tracer
- better autodetection of shifting runtime timeout values
- cmplog: use colorization input for havoc?
- cmplog: too much tainted bytes, directly add to dict and skip?
## Further down the road
afl-fuzz:
- setting min_len/max_len/start_offset/end_offset limits for mutation output
- add __sanitizer_cov_trace_cmp* support via shmem
llvm_mode:
- add __sanitizer_cov_trace_cmp* support
qemu_mode:
- non colliding instrumentation
@ -26,9 +26,12 @@ qemu_mode:
- add/implement AFL_QEMU_INST_LIBLIST and AFL_QEMU_NOINST_PROGRAM
- add/implement AFL_QEMU_INST_REGIONS as a list of _START/_END addresses
## Ideas
- LTO/sancov: write current edge to prev_loc and use that information when
using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow
up edge numbers that both following cmp paths have been found and then
disable working on this edge id -> cmplog_intelligence branch
- use cmplog colorization taint result for havoc locations?

View File

@ -120,6 +120,7 @@ function usage() {
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
"AFL_SKIP_BIN_CHECK: skip check for target binary\n"
exit 1
@ -182,14 +183,12 @@ BEGIN {
if (_go_c == "Q") {
if (qemu_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
extra_par = extra_par " -Q"
if ( !mem_limit_given ) mem_limit = "250"
qemu_mode = 1
continue
} else
if (_go_c == "U") {
if (unicorn_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
extra_par = extra_par " -U"
if ( !mem_limit_given ) mem_limit = "250"
unicorn_mode = 1
continue
} else
@ -199,7 +198,7 @@ BEGIN {
usage()
} # while options
if (!mem_limit) mem_limit = 200
if (!mem_limit) mem_limit = "none"
if (!timeout) timeout = "none"
# get program args
@ -288,6 +287,10 @@ BEGIN {
exit 1
}
if (0 == system( "test -d "in_dir"/default" )) {
in_dir = in_dir "/default"
}
if (0 == system( "test -d "in_dir"/queue" )) {
in_dir = in_dir "/queue"
}
@ -343,8 +346,10 @@ BEGIN {
} else {
stat_format = "-f '%z %N'" # *BSD, MacOS
}
cmdline = "cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} \\; | sort -k1n -k2r"
cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format") | sort -k1n -k2r"
cmdline = "(cd "in_dir" && find . \\( ! -name . -a -type d -prune \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r)"
#cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r"
#cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r"
#cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"
while (cmdline | getline) {
sub(/^[0-9]+ (\.\/)?/,"",$0)
infilesSmallToBig[i++] = $0
@ -355,44 +360,46 @@ BEGIN {
# Make sure that we're not dealing with a directory.
if (0 == system("test -d "in_dir"/"first_file)) {
print "[-] Error: The input directory contains subdirectories - please fix." > "/dev/stderr"
if (0 == system("test -d ""\""in_dir"/"first_file"\"")) {
print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr"
exit 1
}
if (0 == system("ln "in_dir"/"first_file" "trace_dir"/.link_test")) {
if (0 == system("ln \""in_dir"/"first_file"\" "trace_dir"/.link_test")) {
cp_tool = "ln"
} else {
cp_tool = "cp"
}
# Make sure that we can actually get anything out of afl-showmap before we
# waste too much time.
if (!ENVIRON["AFL_SKIP_BIN_CHECK"]) {
# Make sure that we can actually get anything out of afl-showmap before we
# waste too much time.
print "[*] Testing the target binary..."
print "[*] Testing the target binary..."
if (!stdin_file) {
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
} else {
system("cp "in_dir"/"first_file" "stdin_file)
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -A \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
}
first_count = 0
runtest = trace_dir"/.run_test"
while ((getline < runtest) > 0) {
++first_count
}
if (first_count) {
print "[+] OK, "first_count" tuples recorded."
} else {
print "[-] Error: no instrumentation output detected (perhaps crash or timeout)." > "/dev/stderr"
if (!ENVIRON["AFL_KEEP_TRACES"]) {
system("rm -rf "trace_dir" 2>/dev/null")
if (!stdin_file) {
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
} else {
system("cp \""in_dir"/"first_file"\" "stdin_file)
system( "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -A \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
}
first_count = 0
runtest = trace_dir"/.run_test"
while ((getline < runtest) > 0) {
++first_count
}
if (first_count) {
print "[+] OK, "first_count" tuples recorded."
} else {
print "[-] Error: no instrumentation output detected (perhaps crash or timeout)." > "/dev/stderr"
if (!ENVIRON["AFL_KEEP_TRACES"]) {
system("rm -rf "trace_dir" 2>/dev/null")
}
exit 1
}
exit 1
}
# Let's roll!
@ -410,8 +417,8 @@ BEGIN {
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
} else {
print " Processing "in_count" files (forkserver mode)..."
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string" </dev/null"
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string" </dev/null")
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -A \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null"
retval = system( AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -A \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
}
if (retval && !AFL_CMIN_CRASHES_ONLY) {
@ -495,7 +502,7 @@ BEGIN {
# copy file unless already done
if (! (fn in file_already_copied)) {
system(cp_tool" "in_dir"/"fn" "out_dir"/"fn)
system(cp_tool" \""in_dir"/"fn"\" \""out_dir"/"fn"\"")
file_already_copied[fn] = ""
++out_count
#printf "tuple nr %d (%d cnt=%d) -> %s\n",tcnt,key,key_count[key],fn > trace_dir"/.log"

View File

@ -45,7 +45,7 @@ echo
# Process command-line options...
MEM_LIMIT=200
MEM_LIMIT=none
TIMEOUT=none
unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
@ -85,12 +85,10 @@ while getopts "+i:o:f:m:t:eQUCh" opt; do
;;
"Q")
EXTRA_PAR="$EXTRA_PAR -Q"
test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250
QEMU_MODE=1
;;
"U")
EXTRA_PAR="$EXTRA_PAR -U"
test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250
UNICORN_MODE=1
;;
"?")
@ -225,6 +223,7 @@ if [ ! -d "$IN_DIR" ]; then
exit 1
fi
test -d "$IN_DIR/default" && IN_DIR="$IN_DIR/default"
test -d "$IN_DIR/queue" && IN_DIR="$IN_DIR/queue"
find "$OUT_DIR" -name 'id[:_]*' -maxdepth 1 -exec rm -- {} \; 2>/dev/null

View File

@ -99,7 +99,7 @@ if [ ! -d "$outputdir" ]; then
fi
rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png"
rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png"
mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null
echo "[*] Generating plots..."
@ -152,6 +152,12 @@ set ytics auto
plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
'$inputdir/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
set terminal png truecolor enhanced size 1000,300 butt
set output '$outputdir/edges.png'
set ytics auto
plot '$inputdir/plot_data' using 1:13 with lines title ' edges' linecolor rgb '#0090ff' linewidth 3
_EOF_
) | gnuplot
@ -172,6 +178,7 @@ cat >"$outputdir/index.html" <<_EOF_
<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
</table>
<p>
<img src="edges.png" width=1000 height=300>
<img src="high_freq.png" width=1000 height=300><p>
<img src="low_freq.png" width=1000 height=200><p>
<img src="exec_speed.png" width=1000 height=200>
@ -183,7 +190,7 @@ _EOF_
# sensitive, this seems like a reasonable trade-off.
chmod 755 "$outputdir"
chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/index.html"
chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html"
echo "[+] All done - enjoy your charts!"

View File

@ -34,11 +34,12 @@ if [ "$PLATFORM" = "Linux" ] ; then
test -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
test -e /sys/devices/system/cpu/intel_pstate/no_turbo && echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo
test -e /sys/devices/system/cpu/cpufreq/boost && echo 1 > /sys/devices/system/cpu/cpufreq/boost
test -e /sys/devices/system/cpu/intel_pstate/max_perf_pct && echo 100 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
} > /dev/null
echo Settings applied.
dmesg | egrep -q 'nospectre_v2|spectre_v2=off' || {
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"'
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
}
DONE=1
fi
@ -48,6 +49,12 @@ if [ "$PLATFORM" = "FreeBSD" ] ; then
sysctl kern.elf64.aslr.enable=0
} > /dev/null
echo Settings applied.
cat <<EOF
In order to suppress core file generation during fuzzing it is recommended to set
me:\\
:coredumpsize=0:
in the ~/.login_conf file for the user used for fuzzing.
EOF
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
echo ' sysctl hw.ibrs_disable=1'
echo 'Setting kern.pmap.pg_ps_enabled=0 into /boot/loader.conf might be helpful too.'
@ -58,6 +65,17 @@ if [ "$PLATFORM" = "OpenBSD" ] ; then
echo 'System security features cannot be disabled on OpenBSD.'
DONE=1
fi
if [ "$PLATFORM" = "DragonFly" ] ; then
#/sbin/sysctl kern.corefile=/dev/null
#echo Settings applied.
cat <<EOF
In order to suppress core file generation during fuzzing it is recommended to set
me:\\
:coredumpsize=0:
in the ~/.login_conf file for the user used for fuzzing.
EOF
DONE=1
fi
if [ "$PLATFORM" = "NetBSD" ] ; then
{
#echo It is recommended to enable unprivileged users to set cpu affinity
@ -79,4 +97,14 @@ if [ "$PLATFORM" = "Darwin" ] ; then
fi
DONE=1
fi
if [ "$PLATFORM" = "Haiku" ] ; then
SETTINGS=~/config/settings/system/debug_server/settings
[ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
echo We change the debug_server default_action from user to silently kill; \
[ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
echo Settings applied.; \
}
DONE=1
fi
test -z "$DONE" && echo Error: Unknown platform: $PLATFORM
exit 0

View File

@ -28,9 +28,9 @@ if not os.getenv("AFL_INST_LIBS"):
os.environ["AFL_CODE_END"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode + pe.OPTIONAL_HEADER.SizeOfCode)
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]:
os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so")
os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so") + ",WINEARCH=win64"
else:
os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so")
os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so") + ",WINEARCH=win32"
if os.getenv("WINECOV_QEMU_PATH"):
qemu_path = os.getenv("WINECOV_QEMU_PATH")

115
custom_mutators/Android.bp Normal file
View File

@ -0,0 +1,115 @@
cc_library_shared {
name: "libfuzzer-mutator",
vendor_available: true,
host_supported: true,
cflags: [
"-g",
"-O0",
"-funroll-loops",
"-fPIC",
"-fpermissive",
"-std=c++11",
],
srcs: [
"libfuzzer/FuzzerCrossOver.cpp",
"libfuzzer/FuzzerDataFlowTrace.cpp",
"libfuzzer/FuzzerDriver.cpp",
"libfuzzer/FuzzerExtFunctionsDlsym.cpp",
"libfuzzer/FuzzerExtFunctionsWeak.cpp",
"libfuzzer/FuzzerExtFunctionsWindows.cpp",
"libfuzzer/FuzzerExtraCounters.cpp",
"libfuzzer/FuzzerFork.cpp",
"libfuzzer/FuzzerIO.cpp",
"libfuzzer/FuzzerIOPosix.cpp",
"libfuzzer/FuzzerIOWindows.cpp",
"libfuzzer/FuzzerLoop.cpp",
"libfuzzer/FuzzerMerge.cpp",
"libfuzzer/FuzzerMutate.cpp",
"libfuzzer/FuzzerSHA1.cpp",
"libfuzzer/FuzzerTracePC.cpp",
"libfuzzer/FuzzerUtil.cpp",
"libfuzzer/FuzzerUtilDarwin.cpp",
"libfuzzer/FuzzerUtilFuchsia.cpp",
"libfuzzer/FuzzerUtilLinux.cpp",
"libfuzzer/FuzzerUtilPosix.cpp",
"libfuzzer/FuzzerUtilWindows.cpp",
"libfuzzer/libfuzzer.cpp",
],
header_libs: [
"libafl_headers",
],
}
/*cc_library_shared {
name: "honggfuzz-mutator",
vendor_available: true,
host_supported: true,
cflags: [
"-g",
"-O0",
"-funroll-loops",
"-fPIC",
"-Wl,-Bsymbolic",
],
srcs: [
"honggfuzz/honggfuzz.c",
"honggfuzz/mangle.c",
// "../src/afl-perfomance.c",
],
header_libs: [
"libafl_headers",
],
}*/
cc_library_shared {
name: "radamsa-mutator",
vendor_available: true,
host_supported: true,
cflags: [
"-g",
"-O0",
"-funroll-loops",
"-fPIC",
],
srcs: [
"radamsa/libradamsa.c",
"radamsa/radamsa-mutator.c",
],
header_libs: [
"libafl_headers",
],
}
cc_library_shared {
name: "symcc-mutator",
vendor_available: true,
host_supported: true,
cflags: [
"-g",
"-O0",
"-funroll-loops",
"-fPIC",
],
srcs: [
"symcc/symcc.c",
],
header_libs: [
"libafl_headers",
],
}
subdirs = [
"libprotobuf-mutator-example",
]

View File

@ -39,7 +39,7 @@
#include "libhfcommon/util.h"
#define PROG_NAME "honggfuzz"
#define PROG_VERSION "2.3"
#define PROG_VERSION "2.4"
/* Name of the template which will be replaced with the proper name of the file */
#define _HF_FILE_PLACEHOLDER "___FILE___"
@ -208,6 +208,7 @@ typedef struct {
const char* crashDir;
const char* covDirNew;
bool saveUnique;
bool saveSmaller;
size_t dynfileqMaxSz;
size_t dynfileqCnt;
dynfile_t* dynfileqCurrent;
@ -279,9 +280,9 @@ typedef struct {
cmpfeedback_t* cmpFeedbackMap;
int cmpFeedbackFd;
bool cmpFeedback;
const char* blacklistFile;
uint64_t* blacklist;
size_t blacklistCnt;
const char* blocklistFile;
uint64_t* blocklist;
size_t blocklistCnt;
bool skipFeedbackOnTimeout;
uint64_t maxCov[4];
dynFileMethod_t dynFileMethod;

View File

@ -77,11 +77,11 @@ static inline uint64_t util_rndGet(uint64_t min, uint64_t max) {
}
static inline uint64_t util_rnd64() { return rand_below(afl_struct, 1 << 30); }
static inline size_t input_getRandomInputAsBuf(run_t *run, const uint8_t **buf) {
*buf = queue_input;
static inline const uint8_t* input_getRandomInputAsBuf(run_t* run, size_t* len) {
*len = queue_input_size;
run->dynfile->data = queue_input;
run->dynfile->size = queue_input_size;
return queue_input_size;
return queue_input;
}
static inline void input_setSize(run_t* run, size_t sz) {
run->dynfile->size = sz;

View File

@ -1 +0,0 @@
.

View File

@ -0,0 +1,3 @@
#ifndef LOG_E
#define LOG_E LOG_F
#endif

File diff suppressed because it is too large Load Diff

View File

@ -246,7 +246,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
}
if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
if (FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
return false;
// Read traces.
@ -259,8 +259,8 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
if (!CorporaHashes.count(Name)) continue; // not in the corpus.
NumTraceFiles++;
// Printf("=== %s\n", Name.c_str());
std::ifstream IF(SF.File);
while (std::getline(IF, L, '\n')) {
std::ifstream IF2(SF.File);
while (std::getline(IF2, L, '\n')) {
size_t FunctionNum = 0;
std::string DFTString;
@ -314,8 +314,8 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
// we then request tags in [0,Size/2) and [Size/2, Size), and so on.
// Function number => DFT.
auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File)));
std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
std::unordered_set<std::string> Cov;
// std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
// std::unordered_set<std::string> Cov;
Command Cmd;
Cmd.addArgument(DFTBinary);
Cmd.addArgument(F.File);

View File

@ -46,7 +46,7 @@ template<typename T>
fuzzer_allocator() = default;
template<class U>
fuzzer_allocator(const fuzzer_allocator<U>&) {}
explicit fuzzer_allocator(const fuzzer_allocator<U>&) {}
template<class Other>
struct rebind { typedef fuzzer_allocator<Other> other; };

View File

@ -49,7 +49,7 @@ typedef FixedWord<64> Word;
class DictionaryEntry {
public:
DictionaryEntry() {}
DictionaryEntry(Word W) : W(W) {}
explicit DictionaryEntry(Word W) : W(W) {}
DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
const Word &GetW() const { return W; }
@ -92,7 +92,7 @@ class Dictionary {
assert(Idx < Size);
return DE[Idx];
}
void push_back(DictionaryEntry DE) {
void push_back(const DictionaryEntry &DE) {
if (Size < kMaxDictSize)
this->DE[Size++] = DE;
}

View File

@ -16,7 +16,7 @@
namespace fuzzer {
class Random : public std::minstd_rand {
public:
Random(unsigned int seed) : std::minstd_rand(seed) {}
explicit Random(unsigned int seed) : std::minstd_rand(seed) {}
result_type operator()() { return this->std::minstd_rand::operator()(); }
size_t Rand() { return this->operator()(); }
size_t RandBool() { return Rand() % 2; }

View File

@ -145,10 +145,10 @@ private:
};
Region *Regions;
size_t NumRegions;
uint8_t *Start() { return Regions[0].Start; }
uint8_t *Stop() { return Regions[NumRegions - 1].Stop; }
size_t Size() { return Stop() - Start(); }
size_t Idx(uint8_t *P) {
uint8_t *Start() const { return Regions[0].Start; }
uint8_t *Stop() const { return Regions[NumRegions - 1].Stop; }
size_t Size() const { return Stop() - Start(); }
size_t Idx(uint8_t *P) const {
assert(P >= Start() && P < Stop());
return P - Start();
}

View File

@ -0,0 +1,32 @@
cc_library_shared {
name: "libprotobuf-mutator-example-afl",
vendor_available: true,
host_supported: true,
cflags: [
"-g",
"-O0",
"-fPIC",
"-Wall",
],
srcs: [
"lpm_aflpp_custom_mutator_input.cc",
"test.proto",
],
shared_libs: [
"libprotobuf-cpp-full",
"libprotobuf-mutator",
],
}
cc_binary {
name: "libprotobuf-mutator-vuln",
vendor_available: true,
host_supported: true,
srcs: [
"vuln.c",
],
}

View File

@ -0,0 +1 @@
Ported from [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input)

View File

@ -0,0 +1,118 @@
#include "lpm_aflpp_custom_mutator_input.h"
#include <iostream>
#include <sstream>
#include <fstream>
using std::cin;
using std::cout;
using std::endl;
std::string ProtoToData(const TEST &test_proto) {
std::stringstream all;
const auto &aa = test_proto.a();
const auto &bb = test_proto.b();
all.write((const char*)&aa, sizeof(aa));
if(bb.size() != 0) {
all.write(bb.c_str(), bb.size());
}
std::string res = all.str();
if (bb.size() != 0 && res.size() != 0) {
// set PROTO_FUZZER_DUMP_PATH env to dump the serialized protobuf
if (const char *dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) {
std::ofstream of(dump_path);
of.write(res.data(), res.size());
}
}
return res;
}
/**
* Initialize this custom mutator
*
* @param[in] afl a pointer to the internal state object. Can be ignored for
* now.
* @param[in] seed A seed for this mutator - the same seed should always mutate
* in the same way.
* @return Pointer to the data object this custom mutator instance should use.
* There may be multiple instances of this mutator in one afl-fuzz run!
* Return NULL on error.
*/
extern "C" MyMutator *afl_custom_init(void *afl, unsigned int seed) {
MyMutator *mutator = new MyMutator();
mutator->RegisterPostProcessor(
TEST::descriptor(),
[](google::protobuf::Message* message, unsigned int seed) {
// libprotobuf-mutator's built-in mutator is kind of....crappy :P
// Even a dumb fuzz like `TEST.a = rand();` is better in this case... Q_Q
// We register a post processor to apply our dumb fuzz
TEST *t = static_cast<TEST *>(message);
t->set_a(rand());
});
srand(seed);
return mutator;
}
/**
* Perform custom mutations on a given input
*
* @param[in] data pointer returned in afl_custom_init for this fuzz case
* @param[in] buf Pointer to input data to be mutated
* @param[in] buf_size Size of input data
* @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
* error.
* @param[in] add_buf Buffer containing the additional test case
* @param[in] add_buf_size Size of the additional test case
* @param[in] max_size Maximum size of the mutated output. The mutation must not
* produce data larger than max_size.
* @return Size of the mutated output.
*/
extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_custom_init
uint8_t *buf, size_t buf_size, // input data to be mutated
uint8_t **out_buf, // output buffer
uint8_t *add_buf, size_t add_buf_size, // add_buf can be NULL
size_t max_size) {
// This function can be named either "afl_custom_fuzz" or "afl_custom_mutator"
// A simple test shows that "buf" will be the content of the current test case
// "add_buf" will be the next test case ( from AFL++'s input queue )
TEST input;
// parse input data to TEST
// Notice that input data should be a serialized protobuf data
// Check ./in/ii and test_protobuf_serializer for more detail
bool parse_ok = input.ParseFromArray(buf, buf_size);
if(!parse_ok) {
// Invalid serialize protobuf data. Don't mutate.
// Return a dummy buffer. Also mutated_size = 0
static uint8_t *dummy = new uint8_t[10]; // dummy buffer with no data
*out_buf = dummy;
return 0;
}
// mutate the protobuf
mutator->Mutate(&input, max_size);
// Convert protobuf to raw data
const TEST *p = &input;
std::string s = ProtoToData(*p);
// Copy to a new buffer ( mutated_out )
size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
uint8_t *mutated_out = new uint8_t[mutated_size+1];
memcpy(mutated_out, s.c_str(), mutated_size); // copy the mutated data
// Assign the mutated data and return mutated_size
*out_buf = mutated_out;
return mutated_size;
}
/**
* Deinitialize everything
*
* @param data The data ptr from afl_custom_init
*/
extern "C" void afl_custom_deinit(void *data) {
// Honestly I don't know what to do with this...
return;
}

View File

@ -0,0 +1,5 @@
#include <src/mutator.h>
#include "test.pb.h"
class MyMutator : public protobuf_mutator::Mutator {
};

View File

@ -0,0 +1,7 @@
syntax = "proto2";
message TEST {
required uint32 a = 1;
required string b = 2;
}

View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char str[100]={};
read(0, str, 100);
int *ptr = NULL;
if( str[0] == '\x02' || str[0] == '\xe8') {
*ptr = 123;
}
return 0;
}

10
custom_mutators/rust/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

View File

@ -0,0 +1,8 @@
[workspace]
members = [
"custom_mutator-sys",
"custom_mutator",
"example",
# Lain needs a nightly toolchain
# "example_lain",
]

View File

@ -0,0 +1,11 @@
# Rust Custom Mutators
Bindings to create custom mutators in Rust.
These bindings are documented with rustdoc. To view the documentation run
```cargo doc -p custom_mutator --open```.
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
An example using [lain](https://github.com/microsoft/lain) for structured fuzzing can be found in `example_lain`.
Since lain requires a nightly rust toolchain, you need to set one up before you can play with it.

View File

@ -0,0 +1,12 @@
[package]
name = "custom_mutator-sys"
version = "0.1.0"
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
bindgen = "0.56"

View File

@ -0,0 +1,42 @@
extern crate bindgen;
use std::env;
use std::path::PathBuf;
// this code is largely taken straight from the handbook: https://github.com/fitzgen/bindgen-tutorial-bzip2-sys
fn main() {
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed=wrapper.h");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("wrapper.h")
.whitelist_type("afl_state_t")
.blacklist_type(r"u\d+")
.opaque_type(r"_.*")
.opaque_type("FILE")
.opaque_type("in_addr(_t)?")
.opaque_type("in_port(_t)?")
.opaque_type("sa_family(_t)?")
.opaque_type("sockaddr_in(_t)?")
.opaque_type("time_t")
.rustfmt_bindings(true)
.size_t_is_usize(true)
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}

View File

@ -0,0 +1,5 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

View File

@ -0,0 +1,4 @@
#include "../../../include/afl-fuzz.h"
#include "../../../include/common.h"
#include "../../../include/config.h"
#include "../../../include/debug.h"

View File

@ -0,0 +1,13 @@
[package]
name = "custom_mutator"
version = "0.1.0"
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
afl_internals = ["custom_mutator-sys"]
[dependencies]
custom_mutator-sys = { path = "../custom_mutator-sys", optional=true }

View File

@ -0,0 +1,740 @@
#![cfg(unix)]
//! Somewhat safe and somewhat ergonomic bindings for creating [AFL++](https://github.com/AFLplusplus/AFLplusplus) [custom mutators](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/custom_mutators.md) in Rust.
//!
//! # Usage
//! AFL++ custom mutators are expected to be dynamic libraries which expose a set of symbols.
//! Check out [`CustomMutator`] to see which functions of the API are supported.
//! Then use [`export_mutator`] to export the correct symbols for your mutator.
//! In order to use the mutator, your crate needs to be a library crate and have a `crate-type` of `cdylib`.
//! Putting
//! ```yaml
//! [lib]
//! crate-type = ["cdylib"]
//! ```
//! into your `Cargo.toml` should do the trick.
//! The final executable can be found in `target/(debug|release)/your_crate_name.so`.
//! # Example
//! See [`export_mutator`] for an example.
//!
//! # On `panic`s
//! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++.
//!
//! # Access to AFL++ internals
//! This crate has an optional feature "afl_internals", which gives access to AFL++'s internal state.
//! The state is passed to [`CustomMutator::init`], when the feature is activated.
//!
//! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._
use std::{fmt::Debug, path::Path};
#[cfg(feature = "afl_internals")]
#[doc(hidden)]
pub use custom_mutator_sys::afl_state;
#[allow(unused_variables)]
#[doc(hidden)]
pub trait RawCustomMutator {
#[cfg(feature = "afl_internals")]
fn init(afl: &'static afl_state, seed: u32) -> Self
where
Self: Sized;
#[cfg(not(feature = "afl_internals"))]
fn init(seed: u32) -> Self
where
Self: Sized;
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Option<&'b [u8]>;
fn fuzz_count(&mut self, buffer: &[u8]) -> u32 {
1
}
fn queue_new_entry(&mut self, filename_new_queue: &Path, _filename_orig_queue: Option<&Path>) {}
fn queue_get(&mut self, filename: &Path) -> bool {
true
}
fn describe(&mut self, max_description: usize) -> Option<&str> {
Some(default_mutator_describe::<Self>(max_description))
}
fn introspection(&mut self) -> Option<&str> {
None
}
/*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
int afl_custom_init_trim(&self, buffer: &[u8]);
size_t afl_custom_trim(&self, unsigned char **out_buf);
int afl_custom_post_trim(&self, unsigned char success);
size_t afl_custom_havoc_mutation(&self, buffer: &[u8], unsigned char **out_buf, size_t max_size);
unsigned char afl_custom_havoc_mutation_probability(&self);*/
}
/// Wrappers for the custom mutator which provide the bridging between the C API and CustomMutator.
/// These wrappers are not intended to be used directly, rather export_mutator will use them to publish the custom mutator C API.
#[doc(hidden)]
pub mod wrappers {
#[cfg(feature = "afl_internals")]
use custom_mutator_sys::afl_state;
use std::{
any::Any,
convert::TryInto,
ffi::{c_void, CStr, OsStr},
mem::ManuallyDrop,
os::{raw::c_char, unix::ffi::OsStrExt},
panic::catch_unwind,
path::Path,
process::abort,
ptr::null,
slice,
};
use crate::RawCustomMutator;
/// A structure to be used as the data pointer for our custom mutator. This was used as additional storage and is kept for now in case its needed later.
/// Also has some convenience functions for FFI conversions (from and to ptr) and tries to make misuse hard (see [`FFIContext::from`]).
struct FFIContext<M: RawCustomMutator> {
mutator: M,
/// buffer for storing the description returned by [`RawCustomMutator::describe`] as a CString
description_buffer: Vec<u8>,
/// buffer for storing the introspection returned by [`RawCustomMutator::introspect`] as a CString
introspection_buffer: Vec<u8>,
}
impl<M: RawCustomMutator> FFIContext<M> {
fn from(ptr: *mut c_void) -> ManuallyDrop<Box<Self>> {
assert!(!ptr.is_null());
ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut Self) })
}
fn into_ptr(self: Box<Self>) -> *const c_void {
Box::into_raw(self) as *const c_void
}
#[cfg(feature = "afl_internals")]
fn new(afl: &'static afl_state, seed: u32) -> Box<Self> {
Box::new(Self {
mutator: M::init(afl, seed),
description_buffer: Vec::new(),
introspection_buffer: Vec::new(),
})
}
#[cfg(not(feature = "afl_internals"))]
fn new(seed: u32) -> Box<Self> {
Box::new(Self {
mutator: M::init(seed),
description_buffer: Vec::new(),
introspection_buffer: Vec::new(),
})
}
}
/// panic handler called for every panic
fn panic_handler(method: &str, panic_info: Box<dyn Any + Send + 'static>) -> ! {
use std::ops::Deref;
let cause = panic_info
.downcast_ref::<String>()
.map(String::deref)
.unwrap_or_else(|| {
panic_info
.downcast_ref::<&str>()
.copied()
.unwrap_or("<cause unknown>")
});
eprintln!("A panic occurred at {}: {}", method, cause);
abort()
}
/// Internal function used in the macro
#[cfg(not(feature = "afl_internals"))]
pub fn afl_custom_init_<M: RawCustomMutator>(seed: u32) -> *const c_void {
match catch_unwind(|| FFIContext::<M>::new(seed).into_ptr()) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_init", err),
}
}
/// Internal function used in the macro
#[cfg(feature = "afl_internals")]
pub fn afl_custom_init_<M: RawCustomMutator>(
afl: Option<&'static afl_state>,
seed: u32,
) -> *const c_void {
match catch_unwind(|| {
let afl = afl.expect("mutator func called with NULL afl");
FFIContext::<M>::new(afl, seed).into_ptr()
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_init", err),
}
}
/// Internal function used in the macro
pub unsafe fn afl_custom_fuzz_<M: RawCustomMutator>(
data: *mut c_void,
buf: *mut u8,
buf_size: usize,
out_buf: *mut *const u8,
add_buf: *mut u8,
add_buf_size: usize,
max_size: usize,
) -> usize {
match catch_unwind(|| {
let mut context = FFIContext::<M>::from(data);
if buf.is_null() {
panic!("null buf passed to afl_custom_fuzz")
}
if out_buf.is_null() {
panic!("null out_buf passed to afl_custom_fuzz")
}
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
let add_buff_slice = if add_buf.is_null() {
None
} else {
Some(slice::from_raw_parts(add_buf, add_buf_size))
};
match context
.mutator
.fuzz(buff_slice, add_buff_slice, max_size.try_into().unwrap())
{
Some(buffer) => {
*out_buf = buffer.as_ptr();
buffer.len().try_into().unwrap()
}
None => {
// return the input buffer with 0-length to let AFL skip this mutation attempt
*out_buf = buf;
0
}
}
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_fuzz", err),
}
}
/// Internal function used in the macro
pub unsafe fn afl_custom_fuzz_count_<M: RawCustomMutator>(
data: *mut c_void,
buf: *const u8,
buf_size: usize,
) -> u32 {
match catch_unwind(|| {
let mut context = FFIContext::<M>::from(data);
if buf.is_null() {
panic!("null buf passed to afl_custom_fuzz")
}
let buf_slice = slice::from_raw_parts(buf, buf_size);
// see https://doc.rust-lang.org/nomicon/borrow-splitting.html
let ctx = &mut **context;
let mutator = &mut ctx.mutator;
mutator.fuzz_count(buf_slice)
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_fuzz_count", err),
}
}
/// Internal function used in the macro
pub fn afl_custom_queue_new_entry_<M: RawCustomMutator>(
data: *mut c_void,
filename_new_queue: *const c_char,
filename_orig_queue: *const c_char,
) {
match catch_unwind(|| {
let mut context = FFIContext::<M>::from(data);
if filename_new_queue.is_null() {
panic!("received null filename_new_queue in afl_custom_queue_new_entry");
}
let filename_new_queue = Path::new(OsStr::from_bytes(
unsafe { CStr::from_ptr(filename_new_queue) }.to_bytes(),
));
let filename_orig_queue = if !filename_orig_queue.is_null() {
Some(Path::new(OsStr::from_bytes(
unsafe { CStr::from_ptr(filename_orig_queue) }.to_bytes(),
)))
} else {
None
};
context
.mutator
.queue_new_entry(filename_new_queue, filename_orig_queue);
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_queue_new_entry", err),
}
}
/// Internal function used in the macro
pub unsafe fn afl_custom_deinit_<M: RawCustomMutator>(data: *mut c_void) {
match catch_unwind(|| {
// drop the context
ManuallyDrop::into_inner(FFIContext::<M>::from(data));
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_deinit", err),
}
}
/// Internal function used in the macro
pub fn afl_custom_introspection_<M: RawCustomMutator>(data: *mut c_void) -> *const c_char {
match catch_unwind(|| {
let context = &mut *FFIContext::<M>::from(data);
if let Some(res) = context.mutator.introspection() {
let buf = &mut context.introspection_buffer;
buf.clear();
buf.extend_from_slice(res.as_bytes());
buf.push(0);
// unwrapping here, as the error case should be extremely rare
CStr::from_bytes_with_nul(&buf).unwrap().as_ptr()
} else {
null()
}
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_introspection", err),
}
}
/// Internal function used in the macro
pub fn afl_custom_describe_<M: RawCustomMutator>(
data: *mut c_void,
max_description_len: usize,
) -> *const c_char {
match catch_unwind(|| {
let context = &mut *FFIContext::<M>::from(data);
if let Some(res) = context.mutator.describe(max_description_len) {
let buf = &mut context.description_buffer;
buf.clear();
buf.extend_from_slice(res.as_bytes());
buf.push(0);
// unwrapping here, as the error case should be extremely rare
CStr::from_bytes_with_nul(&buf).unwrap().as_ptr()
} else {
null()
}
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_describe", err),
}
}
/// Internal function used in the macro
pub fn afl_custom_queue_get_<M: RawCustomMutator>(
data: *mut c_void,
filename: *const c_char,
) -> u8 {
match catch_unwind(|| {
let mut context = FFIContext::<M>::from(data);
assert!(!filename.is_null());
context.mutator.queue_get(Path::new(OsStr::from_bytes(
unsafe { CStr::from_ptr(filename) }.to_bytes(),
))) as u8
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_queue_get", err),
}
}
}
/// exports the given Mutator as a custom mutator as the C interface that AFL++ expects.
/// It is not possible to call this macro multiple times, because it would define the custom mutator symbols multiple times.
/// # Example
/// ```
/// # #[macro_use] extern crate custom_mutator;
/// # #[cfg(feature = "afl_internals")]
/// # use custom_mutator::afl_state;
/// # use custom_mutator::CustomMutator;
/// struct MyMutator;
/// impl CustomMutator for MyMutator {
/// /// ...
/// # type Error = ();
/// # #[cfg(feature = "afl_internals")]
/// # fn init(_afl_state: &afl_state, _seed: u32) -> Result<Self,()> {unimplemented!()}
/// # #[cfg(not(feature = "afl_internals"))]
/// # fn init(_seed: u32) -> Result<Self, Self::Error> {unimplemented!()}
/// # fn fuzz<'b,'s:'b>(&'s mut self, _buffer: &'b mut [u8], _add_buff: Option<&[u8]>, _max_size: usize) -> Result<Option<&'b [u8]>, Self::Error> {unimplemented!()}
/// }
/// export_mutator!(MyMutator);
/// ```
#[macro_export]
macro_rules! export_mutator {
($mutator_type:ty) => {
#[cfg(feature = "afl_internals")]
#[no_mangle]
pub extern "C" fn afl_custom_init(
afl: ::std::option::Option<&'static $crate::afl_state>,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed as u32)
}
#[cfg(not(feature = "afl_internals"))]
#[no_mangle]
pub extern "C" fn afl_custom_init(
_afl: *const ::std::os::raw::c_void,
seed: ::std::os::raw::c_uint,
) -> *const ::std::os::raw::c_void {
$crate::wrappers::afl_custom_init_::<$mutator_type>(seed as u32)
}
#[no_mangle]
pub extern "C" fn afl_custom_fuzz_count(
data: *mut ::std::os::raw::c_void,
buf: *const u8,
buf_size: usize,
) -> u32 {
unsafe {
$crate::wrappers::afl_custom_fuzz_count_::<$mutator_type>(data, buf, buf_size)
}
}
#[no_mangle]
pub extern "C" fn afl_custom_fuzz(
data: *mut ::std::os::raw::c_void,
buf: *mut u8,
buf_size: usize,
out_buf: *mut *const u8,
add_buf: *mut u8,
add_buf_size: usize,
max_size: usize,
) -> usize {
unsafe {
$crate::wrappers::afl_custom_fuzz_::<$mutator_type>(
data,
buf,
buf_size,
out_buf,
add_buf,
add_buf_size,
max_size,
)
}
}
#[no_mangle]
pub extern "C" fn afl_custom_queue_new_entry(
data: *mut ::std::os::raw::c_void,
filename_new_queue: *const ::std::os::raw::c_char,
filename_orig_queue: *const ::std::os::raw::c_char,
) {
$crate::wrappers::afl_custom_queue_new_entry_::<$mutator_type>(
data,
filename_new_queue,
filename_orig_queue,
)
}
#[no_mangle]
pub extern "C" fn afl_custom_queue_get(
data: *mut ::std::os::raw::c_void,
filename: *const ::std::os::raw::c_char,
) -> u8 {
$crate::wrappers::afl_custom_queue_get_::<$mutator_type>(data, filename)
}
#[no_mangle]
pub extern "C" fn afl_custom_introspection(
data: *mut ::std::os::raw::c_void,
) -> *const ::std::os::raw::c_char {
$crate::wrappers::afl_custom_introspection_::<$mutator_type>(data)
}
#[no_mangle]
pub extern "C" fn afl_custom_describe(
data: *mut ::std::os::raw::c_void,
max_description_len: usize,
) -> *const ::std::os::raw::c_char {
$crate::wrappers::afl_custom_describe_::<$mutator_type>(data, max_description_len)
}
#[no_mangle]
pub extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) {
unsafe { $crate::wrappers::afl_custom_deinit_::<$mutator_type>(data) }
}
};
}
#[cfg(test)]
/// this sanity test is supposed to just find out whether an empty mutator being exported by the macro compiles
mod sanity_test {
#[cfg(feature = "afl_internals")]
use super::afl_state;
use super::{export_mutator, RawCustomMutator};
struct ExampleMutator;
impl RawCustomMutator for ExampleMutator {
#[cfg(feature = "afl_internals")]
fn init(_afl: &afl_state, _seed: u32) -> Self {
unimplemented!()
}
#[cfg(not(feature = "afl_internals"))]
fn init(_seed: u32) -> Self {
unimplemented!()
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
_buffer: &'b mut [u8],
_add_buff: Option<&[u8]>,
_max_size: usize,
) -> Option<&'b [u8]> {
unimplemented!()
}
}
export_mutator!(ExampleMutator);
}
#[allow(unused_variables)]
/// A custom mutator.
/// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`].
pub trait CustomMutator {
/// The error type. All methods must return the same error type.
type Error: Debug;
/// The method which handles errors.
/// By default, this method will log the error to stderr if the environment variable "`AFL_CUSTOM_MUTATOR_DEBUG`" is set and non-empty.
/// After logging the error, execution will continue on a best-effort basis.
///
/// This default behaviour can be customized by implementing this method.
fn handle_error(err: Self::Error) {
if std::env::var("AFL_CUSTOM_MUTATOR_DEBUG")
.map(|v| !v.is_empty())
.unwrap_or(false)
{
eprintln!("Error in custom mutator: {:?}", err)
}
}
#[cfg(feature = "afl_internals")]
fn init(afl: &'static afl_state, seed: u32) -> Result<Self, Self::Error>
where
Self: Sized;
#[cfg(not(feature = "afl_internals"))]
fn init(seed: u32) -> Result<Self, Self::Error>
where
Self: Sized;
fn fuzz_count(&mut self, buffer: &[u8]) -> Result<u32, Self::Error> {
Ok(1)
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, Self::Error>;
fn queue_new_entry(
&mut self,
filename_new_queue: &Path,
filename_orig_queue: Option<&Path>,
) -> Result<(), Self::Error> {
Ok(())
}
fn queue_get(&mut self, filename: &Path) -> Result<bool, Self::Error> {
Ok(true)
}
fn describe(&mut self, max_description: usize) -> Result<Option<&str>, Self::Error> {
Ok(Some(default_mutator_describe::<Self>(max_description)))
}
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
Ok(None)
}
}
impl<M> RawCustomMutator for M
where
M: CustomMutator,
M::Error: Debug,
{
#[cfg(feature = "afl_internals")]
fn init(afl: &'static afl_state, seed: u32) -> Self
where
Self: Sized,
{
match Self::init(afl, seed) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
panic!("Error in afl_custom_init")
}
}
}
#[cfg(not(feature = "afl_internals"))]
fn init(seed: u32) -> Self
where
Self: Sized,
{
match Self::init(seed) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
panic!("Error in afl_custom_init")
}
}
}
fn fuzz_count(&mut self, buffer: &[u8]) -> u32 {
match self.fuzz_count(buffer) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
0
}
}
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Option<&'b [u8]> {
match self.fuzz(buffer, add_buff, max_size) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
None
}
}
}
fn queue_new_entry(&mut self, filename_new_queue: &Path, filename_orig_queue: Option<&Path>) {
match self.queue_new_entry(filename_new_queue, filename_orig_queue) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
}
}
}
fn queue_get(&mut self, filename: &Path) -> bool {
match self.queue_get(filename) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
false
}
}
}
fn describe(&mut self, max_description: usize) -> Option<&str> {
match self.describe(max_description) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
None
}
}
}
fn introspection(&mut self) -> Option<&str> {
match self.introspection() {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
None
}
}
}
}
/// the default value to return from [`CustomMutator::describe`].
fn default_mutator_describe<T: ?Sized>(max_len: usize) -> &'static str {
truncate_str_unicode_safe(std::any::type_name::<T>(), max_len)
}
#[cfg(all(test, not(feature = "afl_internals")))]
mod default_mutator_describe {
struct MyMutator;
use super::CustomMutator;
impl CustomMutator for MyMutator {
type Error = ();
fn init(_: u32) -> Result<Self, Self::Error> {
Ok(Self)
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
_: &'b mut [u8],
_: Option<&[u8]>,
_: usize,
) -> Result<Option<&'b [u8]>, Self::Error> {
unimplemented!()
}
}
#[test]
fn test_default_describe() {
assert_eq!(
MyMutator::init(0).unwrap().describe(64).unwrap().unwrap(),
"custom_mutator::default_mutator_describe::MyMutator"
);
}
}
/// little helper function to truncate a `str` to a maximum of bytes while retaining unicode safety
fn truncate_str_unicode_safe(s: &str, max_len: usize) -> &str {
if s.len() <= max_len {
s
} else {
if let Some((last_index, _)) = s
.char_indices()
.take_while(|(index, _)| *index <= max_len)
.last()
{
&s[..last_index]
} else {
""
}
}
}
#[cfg(test)]
mod truncate_test {
use super::truncate_str_unicode_safe;
#[test]
fn test_truncate() {
for (max_len, input, expected_output) in &[
(0usize, "a", ""),
(1, "a", "a"),
(1, "ä", ""),
(2, "ä", "ä"),
(3, "äa", "äa"),
(4, "äa", "äa"),
(1, "👎", ""),
(2, "👎", ""),
(3, "👎", ""),
(4, "👎", "👎"),
(1, "abc", "a"),
(2, "abc", "ab"),
] {
let actual_output = truncate_str_unicode_safe(input, *max_len);
assert_eq!(
&actual_output, expected_output,
"{:#?} truncated to {} bytes should be {:#?}, but is {:#?}",
input, max_len, expected_output, actual_output
);
}
}
}

View File

@ -0,0 +1,15 @@
[package]
name = "example_mutator"
version = "0.1.0"
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
custom_mutator = { path = "../custom_mutator" }
[[example]]
name = "example_mutator"
path = "./src/example_mutator.rs"
crate-type = ["cdylib"]

View File

@ -0,0 +1,50 @@
#![cfg(unix)]
#![allow(unused_variables)]
use custom_mutator::{export_mutator, CustomMutator};
struct ExampleMutator;
impl CustomMutator for ExampleMutator {
type Error = ();
fn init(seed: u32) -> Result<Self, Self::Error> {
Ok(Self)
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, Self::Error> {
buffer.reverse();
Ok(Some(buffer))
}
}
struct OwnBufferExampleMutator {
own_buffer: Vec<u8>,
}
impl CustomMutator for OwnBufferExampleMutator {
type Error = ();
fn init(seed: u32) -> Result<Self, Self::Error> {
Ok(Self {
own_buffer: Vec::new(),
})
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, ()> {
self.own_buffer.reverse();
Ok(Some(self.own_buffer.as_slice()))
}
}
export_mutator!(ExampleMutator);

View File

@ -0,0 +1,16 @@
[package]
name = "example_lain"
version = "0.1.0"
authors = ["Julius Hohnerlein <julihoh@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
custom_mutator = { path = "../custom_mutator" }
lain="0.5"
[[example]]
name = "example_lain"
path = "./src/lain_mutator.rs"
crate-type = ["cdylib"]

View File

@ -0,0 +1 @@
nightly

View File

@ -0,0 +1,61 @@
#![cfg(unix)]
use custom_mutator::{export_mutator, CustomMutator};
use lain::{
mutator::Mutator,
prelude::*,
rand::{rngs::StdRng, SeedableRng},
};
#[derive(Debug, Mutatable, NewFuzzed, BinarySerialize)]
struct MyStruct {
field_1: u8,
#[lain(bits = 3)]
field_2: u8,
#[lain(bits = 5)]
field_3: u8,
#[lain(min = 5, max = 10000)]
field_4: u32,
#[lain(ignore)]
ignored_field: u64,
}
struct LainMutator {
mutator: Mutator<StdRng>,
buffer: Vec<u8>,
}
impl CustomMutator for LainMutator {
type Error = ();
fn init(seed: u32) -> Result<Self, ()> {
Ok(Self {
mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)),
buffer: Vec::new(),
})
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
_buffer: &'b mut [u8],
_add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, ()> {
// we just sample an instance of MyStruct, ignoring the current input
let instance = MyStruct::new_fuzzed(&mut self.mutator, None);
let size = instance.serialized_size();
if size > max_size {
return Err(());
}
self.buffer.clear();
self.buffer.reserve(size);
instance.binary_serialize::<_, BigEndian>(&mut self.buffer);
Ok(Some(self.buffer.as_slice()))
}
}
export_mutator!(LainMutator);

View File

@ -8,6 +8,107 @@
Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++3.11c (release)
- afl-fuzz:
- better auto detection of map size
- fix sanitizer settings (bug since 3.10c)
- fix an off-by-one overwrite in cmplog
- add non-unicode variants from unicode-looking dictionary entries
- Rust custom mutator API improvements
- Imported crash stats painted yellow on resume (only new ones are red)
- afl-cc:
- added AFL_NOOPT that will just pass everything to the normal
gcc/clang compiler without any changes - to pass weird configure
scripts
- fixed a crash that can occur with ASAN + CMPLOG together plus
better support for unicode (thanks to @stbergmann for reporting!)
- fixed a crash in LAF transform for empty strings
- handle erroneous setups in which multiple afl-compiler-rt are
compiled into the target. This now also supports dlopen()
instrumented libs loaded before the forkserver and even after the
forkserver is started (then with collisions though)
- the compiler rt was added also in object building (-c) which
should have been fixed years ago but somewhere got lost :(
- Renamed CTX to CALLER, added correct/real CTX implementation to
CLASSIC
- qemu_mode:
- added AFL_QEMU_EXCLUDE_RANGES env by @realmadsci, thanks!
- if no new/updated checkout is wanted, build with:
NO_CHECKOUT=1 ./build_qemu_support.sh
- we no longer perform a "git drop"
- afl-cmin: support filenames with spaces
### Version ++3.10c (release)
- Mac OS ARM64 support
- Android support fixed and updated by Joey Jiaojg - thanks!
- New selective instrumentation option with __AFL_COVERAGE_* commands
to be placed in the source code.
Check out instrumentation/README.instrument_list.md
- afl-fuzz
- Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on
start the target map size
- upgraded cmplog/redqueen: solving for floating point, solving
transformations (e.g. toupper, tolower, to/from hex, xor,
arithmetics, etc.). This is costly hence new command line option
`-l` that sets the intensity (values 1 to 3). Recommended is 2.
- added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial seeds
from `-i` or resumes (these have most likely already been done)
- fix crash for very, very fast targets+systems (thanks to mhlakhani
for reporting)
- on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now
reloaded and used, thanks to Vimal Joseph for this patch!
- changed the meaning of '+' of the '-t' option, it now means to
auto-calculate the timeout with the value given being the max
timeout. The original meaning of skipping timeouts instead of
abort is now inherent to the -t option.
- if deterministic mode is active (`-D`, or `-M` without `-d`) then
we sync after every queue entry as this can take very long time
otherwise
- added minimum SYNC_TIME to include/config.h (30 minutes default)
- better detection if a target needs a large shared map
- fix for `-Z`
- fixed a few crashes
- switched to an even faster RNG
- added hghwng's patch for faster trace map analysis
- printing suggestions for mistyped `AFL_` env variables
- added Rust bindings for custom mutators (thanks @julihoh)
- afl-cc
- allow instrumenting LLVMFuzzerTestOneInput
- fixed endless loop for allow/blocklist lines starting with a
comment (thanks to Zherya for reporting)
- cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit
- cmplog/redqueen can now process basic libc++ and libstdc++
std::string comparisons (no position or length type variants)
- added support for __afl_coverage_interesting() for LTO and our
own PCGUARD (llvm 10.0.1+), read more about this function and
selective coverage in instrumentation/README.instrument_list.md
- added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard
support (less performant than our own), GCC for old afl-gcc and
CLANG for old afl-clang
- fixed a potential crash in the LAF feature
- workaround for llvm bitcast lto bug
- workaround for llvm 13
- qemuafl
- QASan (address sanitizer for Qemu) ported to qemuafl!
See qemu_mode/libqasan/README.md
- solved some persistent mode bugs (thanks Dil4rd)
- solved an issue when dumping the memory maps (thanks wizche)
- Android support for QASan
- unicornafl
- Substantial speed gains in python bindings for certain use cases
- Improved rust bindings
- Added a new example harness to compare python, c and rust bindings
- afl-cmin and afl-showmap now support the -f option
- afl_plot now also generates a graph on the discovered edges
- changed default: no memory limit for afl-cmin and afl-cmin.bash
- warn on any _AFL and __AFL env vars.
- set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars
- added dummy Makefile to instrumentation/
- Updated utils/afl_frida to be 5% faster, 7% on x86_x64
- Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b)
- @Edznux added a nice documentation on how to use rpc.statsd with
afl++ in docs/rpc_statsd.md, thanks!
### Version ++3.00c (release)
- llvm_mode/ and gcc_plugin/ moved to instrumentation/
@ -46,6 +147,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- somewhere we broke -n dumb fuzzing, fixed
- added afl_custom_describe to the custom mutator API to allow for easy
mutation reproduction on crashing inputs
- new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored
console output (when configured with USE_COLOR and not ALWAYS_COLORED)
- instrumentation
- We received an enhanced gcc_plugin module from AdaCore, thank you
very much!!

View File

@ -174,7 +174,7 @@
Pintool and Dynamorio are dynamic instrumentation engines, and they can be
used for getting basic block information at runtime.
Pintool is only available for Intel x32/x64 on Linux, Mac OS and Windows
Pintool is only available for Intel x32/x64 on Linux, Mac OS and Windows,
whereas Dynamorio is additionally available for ARM and AARCH64.
Dynamorio is also 10x faster than Pintool.
@ -182,7 +182,7 @@
Dynamorio has a speed decrease of 98-99%
Pintool has a speed decrease of 99.5%
Hence Dynamorio is the option to go for if everything fails, and Pintool
Hence Dynamorio is the option to go for if everything else fails, and Pintool
only if Dynamorio fails too.
Dynamorio solutions:
@ -205,6 +205,7 @@
* QSYM: [https://github.com/sslab-gatech/qsym](https://github.com/sslab-gatech/qsym)
* Manticore: [https://github.com/trailofbits/manticore](https://github.com/trailofbits/manticore)
* S2E: [https://github.com/S2E](https://github.com/S2E)
* Tinyinst [https://github.com/googleprojectzero/TinyInst](https://github.com/googleprojectzero/TinyInst) (Mac/Windows only)
* ... please send me any missing that are good

View File

@ -4,6 +4,11 @@ This file describes how you can implement custom mutations to be used in AFL.
For now, we support C/C++ library and Python module, collectivelly named as the
custom mutator.
There is also experimental support for Rust in `custom_mutators/rust`.
Please refer to that directory for documentation.
Run ```cargo doc -p custom_mutator --open``` in that directory to view the
documentation in your web browser.
Implemented by
- C/C++ library (`*.so`): Khaled Yakdan from Code Intelligence (<yakdan@code-intelligence.de>)
- Python module: Christian Holler from Mozilla (<choller@mozilla.com>)

122
docs/docs.md Normal file
View File

@ -0,0 +1,122 @@
# Restructure afl++'s documentation
## About us
We are dedicated to everything around fuzzing, our main and most well known
contribution is the fuzzer `afl++` which is part of all major Unix
distributions (e.g. Debian, Arch, FreeBSD, etc.) and is deployed on Google's
oss-fuzz and clusterfuzz. It is rated the top fuzzer on Google's fuzzbench.
We are four individuals from Europe supported by a large community.
All our tools are open source.
## About the afl++ fuzzer project
afl++ inherited it's documentation from the original Google afl project.
Since then it has been massively improved - feature and performance wise -
and although the documenation has likewise been continued it has grown out
of proportion.
The documentation is done by non-natives to the English language, plus
none of us has a writer background.
We see questions on afl++ usage on mailing lists (e.g. afl-users), discord
channels, web forums and as issues in our repository.
This only increases as afl++ has been on the top of Google's fuzzbench
statistics (which measures the performance of fuzzers) and is now being
integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix
packaging repositories, e.g. Debian, FreeBSD, etc.
afl++ now has 44 (!) documentation files with 13k total lines of content.
This is way too much.
Hence afl++ needs a complete overhaul of it's documentation, both on a
organisation/structural level as well as the content.
Overall the following actions have to be performed:
* Create a better structure of documentation so it is easier to find the
information that is being looked for, combining and/or splitting up the
existing documents as needed.
* Rewrite some documentation to remove duplication. Several information is
present several times in the documentation. These should be removed to
where needed so that we have as little bloat as possible.
* The documents have been written and modified by a lot of different people,
most of them non-native English speaker. Hence an overall review where
parts should be rewritten has to be performed and then the rewrite done.
* Create a cheat-sheet for a very short best-setup build and run of afl++
* Pictures explain more than 1000 words. We need at least 4 images that
explain the workflow with afl++:
- the build workflow
- the fuzzing workflow
- the fuzzing campaign management workflow
- the overall workflow that is an overview of the above
- maybe more? where the technical writes seems it necessary for
understanding.
Requirements:
* Documentation has to be in Markdown format
* Images have to be either in SVG or PNG format.
* All documentation should be (moved) in(to) docs/
The project does not require writing new documentation or tutorials beside the
cheat sheet. The technical information for the cheat sheet will be provided by
us.
## Metrics
afl++ is a the highest performant fuzzer publicly available - but is also the
most feature rich and complex. With the publicity of afl++' success and
deployment in Google projects internally and externally and availability as
a package on most Linux distributions we see more and more issues being
created and help requests on our Discord channel that would not be
necessary if people would have read through all our documentation - which
is unrealistic.
We expect the the new documenation after this project to be cleaner, easier
accessible and lighter to digest by our users, resulting in much less
help requests. On the other hand the amount of users using afl++ should
increase as well as it will be more accessible which would also increase
questions again - but overall resulting in a reduction of help requests.
In numbers: we currently have per week on average 5 issues on Github,
10 questions on discord and 1 on mailing lists that would not be necessary
with perfect documentation and perfect people.
We would consider this project a success if afterwards we only have
2 issues on Github and 3 questions on discord anymore that would be answered
by reading the documentation. The mailing list is usually used by the most
novice users and we don't expect any less questions there.
## Project Budget
We have zero experience with technical writers, so this is very hard for us
to calculate. We expect it to be a lot of work though because of the amount
of documentation we have that needs to be restructured and partially rewritten
(44 documents with 13k total lines of content).
We assume the daily rate of a very good and experienced technical writer in
times of a pandemic to be ~500$ (according to web research), and calculate
the overall amout of work to be around 20 days for everything incl. the
graphics (but again - this is basically just guessing).
Technical Writer 10000$
Volunteer stipends 0$ (waved)
T-Shirts for the top 10 contributors and helpers to this documentation project:
10 afl++ logo t-shirts 20$ each 200$
10 shipping cost of t-shirts 10$ each 100$
Total: 10.300$
(in the submission form 10.280$ was entered)
## Additional Information
We have participated in Google Summer of Code in 2020 and hope to be selected
again in 2021.
We have no experience with a technical writer, but we will support that person
with video calls, chats, emails and messaging, provide all necessary information
and write technical contents that is required for the success of this project.
It is clear to us that a technical writer knows how to write, but cannot know
the technical details in a complex tooling like in afl++. This guidance, input,
etc. has to come from us.

View File

@ -5,6 +5,10 @@
users or for some types of custom fuzzing setups. See [README.md](README.md) for the general
instruction manual.
Note that most tools will warn on any unknown AFL environment variables.
This is for warning on typos that can happen. If you want to disable this
check then set the `AFL_IGNORE_UNKNOWN_ENVS` environment variable.
## 1) Settings for all compilers
Starting with afl++ 3.0 there is only one compiler: afl-cc
@ -18,11 +22,21 @@ To select the different instrumentation modes this can be done by
`MODE` can be one of `LTO` (afl-clang-lto*), `LLVM` (afl-clang-fast*), `GCC_PLUGIN`
(afl-g*-fast) or `GCC` (afl-gcc/afl-g++).
Because (with the exception of the --afl-MODE command line option) the
compile-time tools do not accept afl specific command-line options, they
make fairly broad use of environmental variables instead:
- Some build/configure scripts break with afl++ compilers. To be able to
pass them, do:
```
export CC=afl-cc
export CXX=afl-c++
export AFL_NOOPT=1
./configure --disable-shared --disabler-werror
unset AFL_NOOPT
make
```
- Most afl tools do not print any output if stdout/stderr are redirected.
If you want to get the output into a file then set the `AFL_DEBUG`
environment variable.
@ -113,11 +127,15 @@ Then there are a few specific features that are only available in instrumentatio
- `AFL_LLVM_INSTRUMENT` - this configures the instrumentation mode.
Available options:
PCGUARD - our own pcgard based instrumentation (default)
NATIVE - clang's original pcguard based instrumentation
CLASSIC - classic AFL (map[cur_loc ^ prev_loc >> 1]++) (default)
CFG - InsTrim instrumentation (see below)
LTO - LTO instrumentation (see below)
CTX - context sensitive instrumentation (see below)
NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
GCC - outdated gcc instrumentation
CLANG - outdated clang instrumentation
In CLASSIC (default) and CFG/INSTRIM you can also specify CTX and/or
NGRAM, seperate the options with a comma "," then, e.g.:
`AFL_LLVM_INSTRUMENT=CFG,CTX,NGRAM-4`
@ -283,6 +301,11 @@ checks or alter some of the more exotic semantics of the tool:
the target. This must be equal or larger than the size the target was
compiled with.
- `AFL_CMPLOG_ONLY_NEW` will only perform the expensive cmplog feature for
newly found testcases and not for testcases that are loaded on startup
(`-i in`). This is an important feature to set when resuming a fuzzing
session.
- `AFL_TESTCACHE_SIZE` allows you to override the size of `#define TESTCASE_CACHE`
in config.h. Recommended values are 50-250MB - or more if your fuzzing
finds a huge amount of paths for large inputs.
@ -346,6 +369,10 @@ checks or alter some of the more exotic semantics of the tool:
- Note that `AFL_POST_LIBRARY` is deprecated, use `AFL_CUSTOM_MUTATOR_LIBRARY`
instead (see below).
- `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on timeout.
Unless you implement your own targets or instrumentation, you likely don't have to set it.
By default, on timeout and on exit, `SIGKILL` (`AFL_KILL_SIGNAL=9`) will be delivered to the child.
- Setting `AFL_CUSTOM_MUTATOR_LIBRARY` to a shared library with
afl_custom_fuzz() creates additional mutations through this library.
If afl-fuzz is compiled with Python (which is autodetected during builing
@ -381,6 +408,9 @@ checks or alter some of the more exotic semantics of the tool:
some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe.
- Setting `AFL_NO_COLOR` or `AFL_NO_COLOUR` will omit control sequences for
coloring console output when configured with USE_COLOR and not ALWAYS_COLORED.
- Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
no valid terminal was detected (for virtual consoles)
@ -420,13 +450,19 @@ checks or alter some of the more exotic semantics of the tool:
normally done when starting up the forkserver and causes a pretty
significant performance drop.
- Setting `AFL_STATSD` enable StatsD metrics collection.
- Setting `AFL_STATSD` enables StatsD metrics collection.
By default AFL++ will send these metrics over UDP to 127.0.0.1:8125.
The host and port are configurable with `AFL_STATSD_HOST` and `AFL_STATSD_PORT`
respectively.
To get the most out of this, you should provide `AFL_STATSD_TAGS_FLAVOR` that
matches your StatsD server.
Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`.
The host and port are configurable with `AFL_STATSD_HOST` and `AFL_STATSD_PORT` respectively.
To enable tags (banner and afl_version) you should provide `AFL_STATSD_TAGS_FLAVOR` that matches
your StatsD server (see `AFL_STATSD_TAGS_FLAVOR`)
- Setting `AFL_STATSD_TAGS_FLAVOR` to one of `dogstatsd`, `librato`, `signalfx` or `influxdb`
allows you to add tags to your fuzzing instances. This is especially useful when running
multiple instances (`-M/-S` for example). Applied tags are `banner` and `afl_version`.
`banner` corresponds to the name of the fuzzer provided through `-M/-S`.
`afl_version` corresponds to the currently running afl version (e.g `++3.0c`).
Default (empty/non present) will add no tags to the metrics.
See [rpc_statsd.md](rpc_statsd.md) for more information.
- Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash.
For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting
@ -493,6 +529,12 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
stack pointer in which QEMU can find the return address when `start addr` is
hit.
- With `AFL_USE_QASAN` you can enable QEMU AddressSanitizer for dynamically
linked binaries.
- With `AFL_QEMU_FORCE_DFL` you force QEMU to ignore the registered signal
handlers of the target.
## 6) Settings for afl-cmin
The corpus minimization script offers very little customization:
@ -508,7 +550,7 @@ The corpus minimization script offers very little customization:
a modest security risk on multi-user systems with rogue users, but should
be safe on dedicated fuzzing boxes.
# #6) Settings for afl-tmin
## 7) 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

View File

@ -3,6 +3,42 @@
In the following, we describe a variety of ideas that could be implemented
for future AFL++ versions.
# GSoC 2021
All GSoC 2021 projects will be in the Rust development language!
## UI for libaflrs
Write a user interface to libaflrs, the upcoming backend of afl++.
This might look like the afl-fuzz UI, but you can improve on it - and should!
## Schedulers for libaflrs
Schedulers is a mechanism that selects items from the fuzzing corpus based
on strategy and randomness. One scheduler might focus on long paths,
another on rarity of edges disocvered, still another on a combination on
things. Some of the schedulers in afl++ have to be ported, but you are free
to come up with your own if you want to - and see how it performs.
## Forkserver support for libaflrs
The current libaflrs implementation fuzzes in-memory, however obviously we
want to support afl instrumented binaries as well.
Hence a forkserver support needs to be implemented - forking off the target
and talking to the target via a socketpair and the communication protocol
within.
## More Observers for libaflrs
An observer is measuring functionality that looks at the target being fuzzed
and documents something about it. In traditional fuzzing this is the coverage
in the target, however we want to add various more observers, e.g. stack depth,
heap usage, etc. - this is a topic for an experienced Rust developer.
# Generic ideas and wishlist - NOT PART OF GSoC 2021 !
The below list is not part of GSoC 2021.
## Analysis software
Currently analysis is done by using afl-plot, which is rather outdated.
@ -16,6 +52,8 @@ test cases executed.
It should be clickable which value is X and Y axis, zoom factor, log scaling
on-off, etc.
Mentor: vanhauser-thc
## WASM Instrumentation
Currently, AFL++ can be used for source code fuzzing and traditional binaries.
@ -36,19 +74,6 @@ Either improve a single mutator thorugh learning of many different bugs
Mentor: domenukk
## Collision-free Binary-Only Maps
AFL++ supports collison-free maps using an LTO (link-time-optimization) pass.
This should be possible to implement for QEMU and Unicorn instrumentations.
As the forkserver parent caches just in time translated translation blocks,
adding a simple counter between jumps should be doable.
Note: this is already in development for qemu by Andrea, so for people who
want to contribute it might make more sense to port his solution to unicorn.
Mentor: andreafioraldi or domenukk
Issue/idea tracker: [https://github.com/AFLplusplus/AFLplusplus/issues/237](https://github.com/AFLplusplus/AFLplusplus/issues/237)
## Your idea!
Finally, we are open to proposals!

View File

@ -13,8 +13,8 @@ We find that AFL's exploitation-based constant schedule assigns **too much energ
| AFL flag | Power Schedule |
| ------------- | -------------------------- |
| `-p explore` (default)| ![EXPLORE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D) |
| `-p fast` | ![FAST](http://latex.codecogs.com/gif.latex?p(i)=\\min\\left(\\frac{\\alpha(i)}{\\beta}\\cdot\\frac{2^{s(i)}}{f(i)},M\\right)) |
| `-p explore` | ![EXPLORE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D) |
| `-p fast` (default)| ![FAST](http://latex.codecogs.com/gif.latex?p(i)=\\min\\left(\\frac{\\alpha(i)}{\\beta}\\cdot\\frac{2^{s(i)}}{f(i)},M\\right)) |
| `-p coe` | ![COE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cbegin%7Bcases%7D%200%20%26%20%5Ctext%7B%20if%20%7D%20f%28i%29%20%3E%20%5Cmu%5C%5C%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%202%5E%7Bs%28i%29%7D%2C%20M%5Cright%29%20%26%20%5Ctext%7B%20otherwise.%7D%20%5Cend%7Bcases%7D) |
| `-p quad` | ![QUAD](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%5Cfrac%7Bs%28i%29%5E2%7D%7Bf%28i%29%7D%2CM%5Cright%29) |
| `-p lin` | ![LIN](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%5Cfrac%7Bs%28i%29%7D%7Bf%28i%29%7D%2CM%5Cright%29) |

143
docs/rpc_statsd.md Normal file
View File

@ -0,0 +1,143 @@
# Remote monitoring with StatsD
StatsD allows you to receive and aggregate metrics from a wide range of applications and retransmit them to the backend of your choice.
This enables you to create nice and readable dashboards containing all the information you need on your fuzzer instances.
No need to write your own statistics parsing system, deploy and maintain it to all your instances, sync with your graph rendering system...
The available metrics are :
- cycle_done
- cycles_wo_finds
- execs_done
- execs_per_sec
- paths_total
- paths_favored
- paths_found
- paths_imported
- max_depth
- cur_path
- pending_favs
- pending_total
- variable_paths
- unique_crashes
- unique_hangs
- total_crashes
- slowest_exec_ms
- edges_found
- var_byte_count
- havoc_expansion
Compared to the default integrated UI, these metrics give you the opportunity to visualize trends and fuzzing state over time.
By doing so, you might be able to see when the fuzzing process has reached a state of no progress, visualize what are the "best strategies"
(according to your own criteria) for your targets, etc. And doing so without requiring to log into each instance manually.
An example visualisation may look like the following:
![StatsD Grafana](visualization/statsd-grafana.png)
*Notes: The exact same dashboard can be imported with [this JSON template](statsd/grafana-afl++.json).*
## How to use
To enable the StatsD reporting on your fuzzer instances, you need to set the environment variable `AFL_STATSD=1`.
Setting `AFL_STATSD_TAGS_FLAVOR` to the provider of your choice will assign tags / labels to each metric based on their format.
The possible values are `dogstatsd`, `librato`, `signalfx` or `influxdb`.
For more information on these env vars, check out `docs/env_variables.md`.
The simplest way of using this feature is to use any metric provider and change the host/port of your StatsD daemon,
with `AFL_STATSD_HOST` and `AFL_STATSD_PORT`, if required (defaults are `localhost` and port `8125`).
To get started, here are some instructions with free and open source tools.
The following setup is based on Prometheus, statsd_exporter and Grafana.
Grafana here is not mandatory, but gives you some nice graphs and features.
Depending on your setup and infrastructure, you may want to run these applications not on your fuzzer instances.
Only one instance of these 3 application is required for all your fuzzers.
To simplify everything, we will use Docker and docker-compose.
Make sure you have them both installed. On most common Linux distributions, it's as simple as:
```sh
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
```
Once that's done, we can create the infrastructure.
Create and move into the directory of your choice. This will store all the configurations files required.
First, create a `docker-compose.yml` containing the following:
```yml
version: '3'
networks:
statsd-net:
driver: bridge
services:
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus.yml:/prometheus.yml
command:
- '--config.file=/prometheus.yml'
restart: unless-stopped
ports:
- "9090:9090"
networks:
- statsd-net
statsd_exporter:
image: prom/statsd-exporter
container_name: statsd_exporter
volumes:
- ./statsd_mapping.yml:/statsd_mapping.yml
command:
- "--statsd.mapping-config=/statsd_mapping.yml"
ports:
- "9102:9102/tcp"
- "8125:9125/udp"
networks:
- statsd-net
grafana:
image: grafana/grafana
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
networks:
- statsd-net
```
Then `prometheus.yml`
```yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'fuzzing_metrics'
static_configs:
- targets: ['statsd_exporter:9102']
```
And finally `statsd_mapping.yml`
```yml
mappings:
- match: "fuzzing.*"
name: "fuzzing"
labels:
type: "$1"
```
Run `docker-compose up -d`.
Everything should now be setup, you are now able to run your fuzzers with
```
AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o ./bin/my-application @@
AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o o ./bin/my-application @@
...
```
This setup may be modified before use in a production environment. Depending on your needs: adding passwords, creating volumes for storage,
tweaking the metrics gathering to get host metrics (CPU, RAM ...).

File diff suppressed because it is too large Load Diff

View File

@ -29,13 +29,18 @@ With that out of the way, let's talk about what's actually on the screen...
### The status bar
```
american fuzzy lop ++3.01a (default) [fast] {0}
```
The top line shows you which mode afl-fuzz is running in
(normal: "american fuzy lop", crash exploration mode: "peruvian rabbit mode")
and the version of afl++.
Next to the version is the banner, which, if not set with -T by hand, will
either show the binary name being fuzzed, or the -M/-S main/secondary name for
parallel fuzzing.
Finally, the last item is the power schedule mode being run (default: explore).
Second to last is the power schedule mode being run (default: fast).
Finally, the last item is the CPU id.
### Process timing

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@ -37,10 +37,6 @@
#define _FILE_OFFSET_BITS 64
#endif
#ifdef __ANDROID__
#include "android-ashmem.h"
#endif
#include "config.h"
#include "types.h"
#include "debug.h"
@ -134,17 +130,34 @@
// Little helper to access the ptr to afl->##name_buf - for use in afl_realloc.
#define AFL_BUF_PARAM(name) ((void **)&afl->name##_buf)
#ifdef WORD_SIZE_64
#define AFL_RAND_RETURN u64
#else
#define AFL_RAND_RETURN u32
#endif
extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32
interesting_32[INTERESTING_8_LEN + INTERESTING_16_LEN + INTERESTING_32_LEN];
struct tainted {
u32 pos;
u32 len;
struct tainted *next;
struct tainted *prev;
};
struct queue_entry {
u8 *fname; /* File name for the test case */
u32 len; /* Input length */
u32 id; /* entry number in queue_buf */
u8 cal_failed; /* Calibration failed? */
u8 colorized, /* Do not run redqueen stage again */
cal_failed; /* Calibration failed? */
bool trim_done, /* Trimmed? */
was_fuzzed, /* historical, but needed for MOpt */
passed_det, /* Deterministic stages passed? */
@ -152,7 +165,6 @@ struct queue_entry {
var_behavior, /* Variable behavior? */
favored, /* Currently favored? */
fs_redundant, /* Marked as redundant in the fs? */
fully_colorized, /* Do not run redqueen stage again */
is_ascii, /* Is the input just ascii text? */
disabled; /* Is disabled from fuzz selection */
@ -168,12 +180,19 @@ struct queue_entry {
u8 *trace_mini; /* Trace bytes, if kept */
u32 tc_ref; /* Trace bytes ref count */
#ifdef INTROSPECTION
u32 bitsmap_size;
#endif
double perf_score, /* performance score */
weight;
u8 *testcase_buf; /* The testcase buffer, if loaded. */
struct queue_entry *next; /* Next element, if any */
u8 * cmplog_colorinput; /* the result buf of colorization */
struct tainted *taint; /* Taint information from CmpLog */
struct queue_entry *mother; /* queue entry this based on */
};
@ -365,13 +384,13 @@ typedef struct afl_env_vars {
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_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd;
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
*afl_testcache_entries;
*afl_testcache_entries, *afl_kill_signal;
} afl_env_vars_t;
@ -385,7 +404,7 @@ struct afl_pass_stat {
struct foreign_sync {
u8 * dir;
time_t ctime;
time_t mtime;
};
@ -406,7 +425,8 @@ typedef struct afl_state {
really makes no sense to haul them around as function parameters. */
u64 orig_hit_cnt_puppet, last_limit_time_start, tmp_pilot_time,
total_pacemaker_time, total_puppet_find, temp_puppet_find, most_time_key,
most_time, most_execs_key, most_execs, old_hit_count, force_ui_update;
most_time, most_execs_key, most_execs, old_hit_count, force_ui_update,
prev_run_time;
MOpt_globals_t mopt_globals_core, mopt_globals_pilot;
@ -550,6 +570,7 @@ typedef struct afl_state {
blocks_eff_total, /* Blocks subject to effector maps */
blocks_eff_select, /* Blocks selected as fuzzable */
start_time, /* Unix start time (ms) */
last_sync_time, /* Time of last sync */
last_path_time, /* Time for most recent path (ms) */
last_crash_time, /* Time for most recent crash (ms) */
last_hang_time; /* Time for most recent hang (ms) */
@ -563,7 +584,7 @@ typedef struct afl_state {
u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */
s32 stage_cur, stage_max; /* Stage progression */
u32 stage_cur, stage_max; /* Stage progression */
s32 splicing_with; /* Splicing with which test case? */
u32 main_node_id, main_node_max; /* Main instance job splitting */
@ -580,8 +601,9 @@ typedef struct afl_state {
u32 rand_cnt; /* Random number counter */
u64 rand_seed[4];
s64 init_seed;
/* unsigned long rand_seed[3]; would also work */
AFL_RAND_RETURN rand_seed[3];
s64 init_seed;
u64 total_cal_us, /* Total calibration time (us) */
total_cal_cycles; /* Total calibration cycles */
@ -625,6 +647,10 @@ typedef struct afl_state {
/* cmplog forkserver ids */
s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd;
u32 cmplog_prev_timed_out;
u32 cmplog_max_filesize;
u32 cmplog_lvl;
u32 colorize_success;
u8 cmplog_enable_arith, cmplog_enable_transform;
struct afl_pass_stat *pass_stats;
struct cmp_map * orig_cmp_map;
@ -634,10 +660,10 @@ typedef struct afl_state {
unsigned long long int last_avg_exec_update;
u32 last_avg_execs;
float last_avg_execs_saved;
double last_avg_execs_saved;
/* foreign sync */
#define FOREIGN_SYNCS_MAX 32
#define FOREIGN_SYNCS_MAX 32U
u8 foreign_sync_cnt;
struct foreign_sync foreign_syncs[FOREIGN_SYNCS_MAX];
@ -728,6 +754,7 @@ typedef struct afl_state {
char mutation[8072];
char m_tmp[4096];
FILE *introspection_file;
u32 bitsmap_size;
#endif
} afl_state_t;
@ -1014,12 +1041,12 @@ void write_bitmap(afl_state_t *);
u32 count_bits(afl_state_t *, u8 *);
u32 count_bytes(afl_state_t *, u8 *);
u32 count_non_255_bytes(afl_state_t *, u8 *);
void simplify_trace(afl_state_t *, u8 *);
void classify_counts(afl_forkserver_t *);
#ifdef WORD_SIZE_64
void simplify_trace(afl_state_t *, u64 *);
void classify_counts(afl_forkserver_t *);
void discover_word(u8 *ret, u64 *current, u64 *virgin);
#else
void simplify_trace(afl_state_t *, u32 *);
void classify_counts(afl_forkserver_t *);
void discover_word(u8 *ret, u32 *current, u32 *virgin);
#endif
void init_count_class16(void);
void minimize_bits(afl_state_t *, u8 *, u8 *);
@ -1028,12 +1055,14 @@ u8 *describe_op(afl_state_t *, u8, size_t);
#endif
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
u8 has_new_bits(afl_state_t *, u8 *);
u8 has_new_bits_unclassified(afl_state_t *, u8 *);
/* Extras */
void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32);
void load_extras(afl_state_t *, u8 *);
void dedup_extras(afl_state_t *);
void deunicode_extras(afl_state_t *);
void add_extra(afl_state_t *afl, u8 *mem, u32 len);
void maybe_add_auto(afl_state_t *, u8 *, u32);
void save_auto(afl_state_t *);
@ -1042,9 +1071,10 @@ void destroy_extras(afl_state_t *);
/* Stats */
void load_stats_file(afl_state_t *);
void write_setup_file(afl_state_t *, u32, char **);
void write_stats_file(afl_state_t *, double, double, double);
void maybe_update_plot_file(afl_state_t *, double, double);
void write_stats_file(afl_state_t *, u32, double, double, double);
void maybe_update_plot_file(afl_state_t *, u32, double, double);
void show_stats(afl_state_t *);
void show_init_stats(afl_state_t *);
@ -1108,11 +1138,10 @@ void read_foreign_testcases(afl_state_t *, int);
u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len);
/* RedQueen */
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
u64 exec_cksum);
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len);
/* xoshiro256** */
uint64_t rand_next(afl_state_t *afl);
/* our RNG wrapper */
AFL_RAND_RETURN rand_next(afl_state_t *afl);
/* probability between 0.0 and 1.0 */
double rand_next_percent(afl_state_t *afl);

View File

@ -271,7 +271,7 @@ static inline void *DFL_ck_alloc_nozero(u32 size) {
ret = malloc(size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size);
ret += ALLOC_OFF_HEAD;
ret = (char *)ret + ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1;
ALLOC_S(ret) = size;
@ -311,7 +311,7 @@ static inline void DFL_ck_free(void *mem) {
ALLOC_C1(mem) = ALLOC_MAGIC_F;
free(mem - ALLOC_OFF_HEAD);
free((char *)mem - ALLOC_OFF_HEAD);
}
@ -340,7 +340,7 @@ static inline void *DFL_ck_realloc(void *orig, u32 size) {
#endif /* !DEBUG_BUILD */
old_size = ALLOC_S(orig);
orig -= ALLOC_OFF_HEAD;
orig = (char *)orig - ALLOC_OFF_HEAD;
ALLOC_CHECK_SIZE(old_size);
@ -363,10 +363,11 @@ static inline void *DFL_ck_realloc(void *orig, u32 size) {
if (orig) {
memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size));
memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size);
memcpy((char *)ret + ALLOC_OFF_HEAD, (char *)orig + ALLOC_OFF_HEAD,
MIN(size, old_size));
memset((char *)orig + ALLOC_OFF_HEAD, 0xFF, old_size);
ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F;
ALLOC_C1((char *)orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F;
free(orig);
@ -374,13 +375,13 @@ static inline void *DFL_ck_realloc(void *orig, u32 size) {
#endif /* ^!DEBUG_BUILD */
ret += ALLOC_OFF_HEAD;
ret = (char *)ret + ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1;
ALLOC_S(ret) = size;
ALLOC_C2(ret) = ALLOC_MAGIC_C2;
if (size > old_size) memset(ret + old_size, 0, size - old_size);
if (size > old_size) memset((char *)ret + old_size, 0, size - old_size);
return ret;
@ -401,7 +402,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) {
ret = malloc(size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size);
ret += ALLOC_OFF_HEAD;
ret = (char *)ret + ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1;
ALLOC_S(ret) = size;

View File

@ -1,62 +1,34 @@
/*
american fuzzy lop++ - android shared memory compatibility layer
----------------------------------------------------------------
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
This header re-defines the shared memory routines used by AFL++
using the Andoid API.
*/
#ifndef _ANDROID_ASHMEM_H
#define _ANDROID_ASHMEM_H
#ifdef __ANDROID__
#ifndef _ANDROID_ASHMEM_H
#define _ANDROID_ASHMEM_H
#include <fcntl.h>
#include <linux/shm.h>
#include <linux/ashmem.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/ashmem.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#if __ANDROID_API__ >= 26
#define shmat bionic_shmat
#define shmctl bionic_shmctl
#define shmdt bionic_shmdt
#define shmget bionic_shmget
#endif
#if __ANDROID_API__ >= 26
#define shmat bionic_shmat
#define shmctl bionic_shmctl
#define shmdt bionic_shmdt
#define shmget bionic_shmget
#endif
#include <sys/shm.h>
#undef shmat
#undef shmctl
#undef shmdt
#undef shmget
#include <stdio.h>
#include <sys/shm.h>
#undef shmat
#undef shmctl
#undef shmdt
#undef shmget
#include <stdio.h>
#define ASHMEM_DEVICE "/dev/ashmem"
#define ASHMEM_DEVICE "/dev/ashmem"
static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
int ret = 0;
if (__cmd == IPC_RMID) {
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
struct ashmem_pin pin = {0, (unsigned int)length};
struct ashmem_pin pin = {0, length};
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
close(__shmid);
@ -66,7 +38,7 @@ static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
}
static inline int shmget(key_t __key, size_t __size, int __shmflg) {
int shmget(key_t __key, size_t __size, int __shmflg) {
(void)__shmflg;
int fd, ret;
@ -90,7 +62,7 @@ error:
}
static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
(void)__shmflg;
int size;
@ -106,7 +78,6 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
}
#endif /* __ANDROID__ */
#endif
#endif /* !_ANDROID_ASHMEM_H */
#endif /* !__ANDROID__ */

View File

@ -30,24 +30,25 @@
#include "config.h"
#define CMPLOG_LVL_MAX 3
#define CMP_MAP_W 65536
#define CMP_MAP_H 256
#define CMP_MAP_H 32
#define CMP_MAP_RTN_H (CMP_MAP_H / 4)
#define SHAPE_BYTES(x) (x + 1)
#define CMP_TYPE_INS 0
#define CMP_TYPE_RTN 1
#define CMP_TYPE_INS 1
#define CMP_TYPE_RTN 2
struct cmp_header {
unsigned hits : 20;
unsigned cnt : 20;
unsigned id : 16;
unsigned shape : 5; // from 0 to 31
unsigned type : 1;
unsigned hits : 24;
unsigned id : 24;
unsigned shape : 5;
unsigned type : 2;
unsigned attribute : 4;
unsigned reserved : 5;
} __attribute__((packed));
@ -55,6 +56,8 @@ struct cmp_operands {
u64 v0;
u64 v1;
u64 v0_128;
u64 v1_128;
};

View File

@ -39,6 +39,7 @@
#define STRINGIFY_VAL_SIZE_MAX (16)
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin);
void print_suggested_envs(char *mispelled_env);
void check_environment_vars(char **env);
char **argv_cpy_dup(int argc, char **argv);
@ -47,6 +48,7 @@ void argv_cpy_free(char **argv);
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
char * get_afl_env(char *env);
u8 * get_libqasan_path(u8 *own_loc);
extern u8 be_quiet;
extern u8 *doc_path; /* path to documentation dir */
@ -56,6 +58,11 @@ extern u8 *doc_path; /* path to documentation dir */
u8 *find_binary(u8 *fname);
/* Parses the kill signal environment variable, FATALs on error.
If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */
int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal);
/* Read a bitmap from file fname to memory
This is for the -B option again. */

View File

@ -10,7 +10,7 @@
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Copyright 2019-2021 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -23,12 +23,10 @@
#ifndef _HAVE_CONFIG_H
#define _HAVE_CONFIG_H
#include "types.h"
/* Version string: */
// c = release, d = volatile github dev, e = experimental branch
#define VERSION "++3.00c"
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++3.11c"
/******************************************************
* *
@ -36,11 +34,55 @@
* *
******************************************************/
/* CMPLOG/REDQUEEN TUNING
*
* Here you can modify tuning and solving options for CMPLOG.
* Note that these are run-time options for afl-fuzz, no target
* recompilation required.
*
*/
/* if TRANSFORM is enabled with '-l T', this additionally enables base64
encoding/decoding */
// #define CMPLOG_SOLVE_TRANSFORM_BASE64
/* If a redqueen pass finds more than one solution, try to combine them? */
#define CMPLOG_COMBINE
/* Minimum % of the corpus to perform cmplog on. Default: 10% */
#define CMPLOG_CORPUS_PERCENT 5U
/* Number of potential positions from which we decide if cmplog becomes
useless, default 8096 */
#define CMPLOG_POSITIONS_MAX (12 * 1024)
/* Maximum allowed fails per CMP value. Default: 128 */
#define CMPLOG_FAIL_MAX 96
/* Now non-cmplog configuration options */
/* 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
* 2. defined USE_COLOR && !defined ALWAYS_COLORED
* -> depending on env var AFL_NO_COLOR=1 colors can be switched off
* at run-time. Default is to use colors.
* 3. colored outputs fixed off: !defined USE_COLOR
* The env var. AFL_NO_COLOR will have no effect
*/
/* Comment out to disable terminal colors (note that this makes afl-analyze
a lot less nice): */
#define USE_COLOR
#ifdef USE_COLOR
/* Comment in to always enable terminal colors */
/* Comment out to enable runtime controlled terminal colors via AFL_NO_COLOR
*/
#define ALWAYS_COLORED 1
#endif
/* StatsD config
Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment
variable.
@ -52,7 +94,7 @@
/* If you want to have the original afl internal memory corruption checks.
Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */
//#define _WANT_ORIGINAL_AFL_ALLOC
// #define _WANT_ORIGINAL_AFL_ALLOC
/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */
@ -63,11 +105,11 @@
/* Default timeout for fuzzed code (milliseconds). This is the upper bound,
also used for detecting hangs; the actual value is auto-scaled: */
#define EXEC_TIMEOUT 1000
#define EXEC_TIMEOUT 1000U
/* Timeout rounding factor when auto-scaling (milliseconds): */
#define EXEC_TM_ROUND 20
#define EXEC_TM_ROUND 20U
/* 64bit arch MACRO */
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
@ -76,48 +118,48 @@
/* Default memory limit for child process (MB) 0 = disabled : */
#define MEM_LIMIT 0
#define MEM_LIMIT 0U
/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */
#define MEM_LIMIT_QEMU 0
#define MEM_LIMIT_QEMU 0U
/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */
#define MEM_LIMIT_UNICORN 0
#define MEM_LIMIT_UNICORN 0U
/* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */
#define CAL_CYCLES 8
#define CAL_CYCLES_LONG 40
#define CAL_CYCLES 8U
#define CAL_CYCLES_LONG 40U
/* Number of subsequent timeouts before abandoning an input file: */
#define TMOUT_LIMIT 250
#define TMOUT_LIMIT 250U
/* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500
#define KEEP_UNIQUE_CRASH 5000
#define KEEP_UNIQUE_HANG 500U
#define KEEP_UNIQUE_CRASH 5000U
/* Baseline number of random tweaks during a single 'havoc' stage: */
#define HAVOC_CYCLES 256
#define HAVOC_CYCLES_INIT 1024
#define HAVOC_CYCLES 256U
#define HAVOC_CYCLES_INIT 1024U
/* Maximum multiplier for the above (should be a power of two, beware
of 32-bit int overflows): */
#define HAVOC_MAX_MULT 64
#define HAVOC_MAX_MULT_MOPT 64
#define HAVOC_MAX_MULT 64U
#define HAVOC_MAX_MULT_MOPT 64U
/* Absolute minimum number of havoc cycles (after all adjustments): */
#define HAVOC_MIN 12
#define HAVOC_MIN 12U
/* Power Schedule Divisor */
#define POWER_BETA 1
#define POWER_BETA 1U
#define MAX_FACTOR (POWER_BETA * 32)
/* Maximum stacking for havoc-stage tweaks. The actual value is calculated
@ -129,19 +171,19 @@
In other words, the default (n = 4) produces 2, 4, 8, 16
stacked tweaks: */
#define HAVOC_STACK_POW2 4
#define HAVOC_STACK_POW2 4U
/* Caps on block sizes for cloning and deletion operations. Each of these
ranges has a 33% probability of getting picked, except for the first
two cycles where smaller blocks are favored: */
#define HAVOC_BLK_SMALL 32
#define HAVOC_BLK_MEDIUM 128
#define HAVOC_BLK_LARGE 1500
#define HAVOC_BLK_SMALL 32U
#define HAVOC_BLK_MEDIUM 128U
#define HAVOC_BLK_LARGE 1500U
/* Extra-large blocks, selected very rarely (<5% of the time): */
#define HAVOC_BLK_XL 32768
#define HAVOC_BLK_XL 32768U
/* Probabilities of skipping non-favored entries in the queue, expressed as
percentages: */
@ -169,9 +211,11 @@
#define TRIM_START_STEPS 16
#define TRIM_END_STEPS 1024
/* Maximum size of input file, in bytes (keep under 100MB): */
/* Maximum size of input file, in bytes (keep under 100MB, default 1MB):
(note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c
and afl-fuzz-state.c have to be changed as well! */
#define MAX_FILE (1 * 1024 * 1024)
#define MAX_FILE (1 * 1024 * 1024U)
/* The same, for the test case minimizer: */
@ -236,6 +280,11 @@
#define SYNC_INTERVAL 8
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
nodes) - default is 30 minutes: */
#define SYNC_TIME (30 * 60 * 1000)
/* Output directory reuse grace period (minutes): */
#define OUTPUT_GRACE 25
@ -363,7 +412,7 @@
after changing this - otherwise, SEGVs may ensue. */
#define MAP_SIZE_POW2 16
#define MAP_SIZE (1 << MAP_SIZE_POW2)
#define MAP_SIZE (1U << MAP_SIZE_POW2)
/* Maximum allocator request size (keep well under INT_MAX): */

112
include/coverage-32.h Normal file
View File

@ -0,0 +1,112 @@
#include "config.h"
#include "types.h"
u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end);
u32 classify_word(u32 word);
inline u32 classify_word(u32 word) {
u16 mem16[2];
memcpy(mem16, &word, sizeof(mem16));
mem16[0] = count_class_lookup16[mem16[0]];
mem16[1] = count_class_lookup16[mem16[1]];
memcpy(&word, mem16, sizeof(mem16));
return word;
}
void simplify_trace(afl_state_t *afl, u8 *bytes) {
u32 *mem = (u32 *)bytes;
u32 i = (afl->fsrv.map_size >> 2);
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) {
u8 *mem8 = (u8 *)mem;
mem8[0] = simplify_lookup[mem8[0]];
mem8[1] = simplify_lookup[mem8[1]];
mem8[2] = simplify_lookup[mem8[2]];
mem8[3] = simplify_lookup[mem8[3]];
} else
*mem = 0x01010101;
mem++;
}
}
inline void classify_counts(afl_forkserver_t *fsrv) {
u32 *mem = (u32 *)fsrv->trace_bits;
u32 i = (fsrv->map_size >> 2);
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) { *mem = classify_word(*mem); }
mem++;
}
}
/* Updates the virgin bits, then reflects whether a new count or a new tuple is
* seen in ret. */
inline void discover_word(u8 *ret, u32 *current, u32 *virgin) {
/* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap
that have not been already cleared from the virgin map - since this will
almost always be the case. */
if (*current & *virgin) {
if (likely(*ret < 2)) {
u8 *cur = (u8 *)current;
u8 *vir = (u8 *)virgin;
/* Looks like we have not found any new bytes yet; see if any non-zero
bytes in current[] are pristine in virgin[]. */
if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
(cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff))
*ret = 2;
else
*ret = 1;
}
*virgin &= ~*current;
}
}
#define PACK_SIZE 16
inline u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end) {
for (; current < current_end; virgin += 4, current += 4) {
if (current[0] && classify_word(current[0]) & virgin[0]) return 1;
if (current[1] && classify_word(current[1]) & virgin[1]) return 1;
if (current[2] && classify_word(current[2]) & virgin[2]) return 1;
if (current[3] && classify_word(current[3]) & virgin[3]) return 1;
}
return 0;
}

189
include/coverage-64.h Normal file
View File

@ -0,0 +1,189 @@
#include "config.h"
#include "types.h"
#if (defined(__AVX512F__) && defined(__AVX512DQ__)) || defined(__AVX2__)
#include <immintrin.h>
#endif
u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end);
u64 classify_word(u64 word);
inline u64 classify_word(u64 word) {
u16 mem16[4];
memcpy(mem16, &word, sizeof(mem16));
mem16[0] = count_class_lookup16[mem16[0]];
mem16[1] = count_class_lookup16[mem16[1]];
mem16[2] = count_class_lookup16[mem16[2]];
mem16[3] = count_class_lookup16[mem16[3]];
memcpy(&word, mem16, sizeof(mem16));
return word;
}
void simplify_trace(afl_state_t *afl, u8 *bytes) {
u64 *mem = (u64 *)bytes;
u32 i = (afl->fsrv.map_size >> 3);
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) {
u8 *mem8 = (u8 *)mem;
mem8[0] = simplify_lookup[mem8[0]];
mem8[1] = simplify_lookup[mem8[1]];
mem8[2] = simplify_lookup[mem8[2]];
mem8[3] = simplify_lookup[mem8[3]];
mem8[4] = simplify_lookup[mem8[4]];
mem8[5] = simplify_lookup[mem8[5]];
mem8[6] = simplify_lookup[mem8[6]];
mem8[7] = simplify_lookup[mem8[7]];
} else
*mem = 0x0101010101010101ULL;
mem++;
}
}
inline void classify_counts(afl_forkserver_t *fsrv) {
u64 *mem = (u64 *)fsrv->trace_bits;
u32 i = (fsrv->map_size >> 3);
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) { *mem = classify_word(*mem); }
mem++;
}
}
/* Updates the virgin bits, then reflects whether a new count or a new tuple is
* seen in ret. */
inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {
/* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap
that have not been already cleared from the virgin map - since this will
almost always be the case. */
if (*current & *virgin) {
if (likely(*ret < 2)) {
u8 *cur = (u8 *)current;
u8 *vir = (u8 *)virgin;
/* Looks like we have not found any new bytes yet; see if any non-zero
bytes in current[] are pristine in virgin[]. */
if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
(cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) ||
(cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) ||
(cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff))
*ret = 2;
else
*ret = 1;
}
*virgin &= ~*current;
}
}
#if defined(__AVX512F__) && defined(__AVX512DQ__)
#define PACK_SIZE 64
inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
for (; current != current_end; virgin += 8, current += 8) {
__m512i value = *(__m512i *)current;
__mmask8 mask = _mm512_testn_epi64_mask(value, value);
/* All bytes are zero. */
if (mask == 0xff) continue;
/* Look for nonzero bytes and check for new bits. */
#define UNROLL(x) \
if (!(mask & (1 << x)) && classify_word(current[x]) & virgin[x]) return 1
UNROLL(0);
UNROLL(1);
UNROLL(2);
UNROLL(3);
UNROLL(4);
UNROLL(5);
UNROLL(6);
UNROLL(7);
#undef UNROLL
}
return 0;
}
#endif
#if !defined(PACK_SIZE) && defined(__AVX2__)
#define PACK_SIZE 32
inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
__m256i zeroes = _mm256_setzero_si256();
for (; current < current_end; virgin += 4, current += 4) {
__m256i value = *(__m256i *)current;
__m256i cmp = _mm256_cmpeq_epi64(value, zeroes);
u32 mask = _mm256_movemask_epi8(cmp);
/* All bytes are zero. */
if (mask == (u32)-1) continue;
/* Look for nonzero bytes and check for new bits. */
if (!(mask & 0xff) && classify_word(current[0]) & virgin[0]) return 1;
if (!(mask & 0xff00) && classify_word(current[1]) & virgin[1]) return 1;
if (!(mask & 0xff0000) && classify_word(current[2]) & virgin[2]) return 1;
if (!(mask & 0xff000000) && classify_word(current[3]) & virgin[3]) return 1;
}
return 0;
}
#endif
#if !defined(PACK_SIZE)
#define PACK_SIZE 32
inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
for (; current < current_end; virgin += 4, current += 4) {
if (current[0] && classify_word(current[0]) & virgin[0]) return 1;
if (current[1] && classify_word(current[1]) & virgin[1]) return 1;
if (current[2] && classify_word(current[2]) & virgin[2]) return 1;
if (current[3] && classify_word(current[3]) & virgin[3]) return 1;
}
return 0;
}
#endif

View File

@ -168,12 +168,84 @@
* Debug & error macros *
************************/
/* Just print stuff to the appropriate stream. */
#if defined USE_COLOR && !defined ALWAYS_COLORED
#include <unistd.h>
#pragma GCC diagnostic ignored "-Wformat-security"
static inline const char *colorfilter(const char *x) {
static int once = 1;
static int disabled = 0;
if (once) {
/* when there is no tty -> we always want filtering
* when AFL_NO_UI is set filtering depends on AFL_NO_COLOR
* otherwise we want always colors
*/
disabled =
isatty(2) && (!getenv("AFL_NO_UI") ||
(!getenv("AFL_NO_COLOR") && !getenv("AFL_NO_COLOUR")));
once = 0;
}
if (likely(disabled)) return x;
static char monochromestring[4096];
char * d = monochromestring;
int in_seq = 0;
while (*x) {
if (in_seq && *x == 'm') {
in_seq = 0;
} else {
if (!in_seq && *x == '\x1b') { in_seq = 1; }
if (!in_seq) { *d++ = *x; }
}
++x;
}
*d = '\0';
return monochromestring;
}
#ifdef MESSAGES_TO_STDOUT
#define SAYF(x...) printf(x)
#else
#define SAYF(x...) fprintf(stderr, x)
#define colorfilter(x) x /* no filtering necessary */
#endif
/* macro magic to transform the first parameter to SAYF
* through colorfilter which strips coloring */
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, \
_15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, \
_27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, \
_39, _40, NAME, ...) \
NAME
#define SAYF(...) \
GET_MACRO(__VA_ARGS__, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, SAYF_N, \
SAYF_N, SAYF_1) \
(__VA_ARGS__)
#define SAYF_1(x) MY_SAYF(colorfilter(x))
#define SAYF_N(x, ...) MY_SAYF(colorfilter(x), __VA_ARGS__)
/* Just print stuff to the appropriate stream. */
#ifdef MESSAGES_TO_STDOUT
#define MY_SAYF(x...) printf(x)
#else
#define MY_SAYF(x...) fprintf(stderr, x)
#endif /* ^MESSAGES_TO_STDOUT */
/* Show a prefixed warning. */
@ -224,7 +296,7 @@
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__, __LINE__); \
__FILE__, (u32)__LINE__); \
exit(1); \
\
} while (0)
@ -237,7 +309,7 @@
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__, __LINE__); \
__FILE__, (u32)__LINE__); \
abort(); \
\
} while (0)
@ -251,7 +323,7 @@
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__, __LINE__); \
__FILE__, (u32)__LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
exit(1); \
\
@ -272,12 +344,12 @@
/* Show a prefixed debug output. */
#define DEBUGF(x...) \
do { \
\
SAYF(cMGN "[D] " cBRI "DEBUG: " cRST x); \
SAYF(cRST ""); \
\
#define DEBUGF(x...) \
do { \
\
fprintf(stderr, cMGN "[D] " cBRI "DEBUG: " cRST x); \
fprintf(stderr, cRST ""); \
\
} while (0)
/* Error-checking versions of read() and write() that call RPFATAL() as

View File

@ -28,6 +28,7 @@ static char *afl_environment_variables[] = {
"AFL_CC",
"AFL_CMIN_ALLOW_ANY",
"AFL_CMIN_CRASHES_ONLY",
"AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END",
"AFL_CODE_START",
"AFL_COMPCOV_BINNAME",
@ -42,11 +43,13 @@ static char *afl_environment_variables[] = {
"AFL_DEBUG_GDB",
"AFL_DISABLE_TRIM",
"AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV",
"AFL_ENTRYPOINT",
"AFL_EXIT_WHEN_DONE",
"AFL_FAST_CAL",
"AFL_FORCE_UI",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST",
"AFL_GCC_BLOCKLIST",
@ -58,9 +61,11 @@ static char *afl_environment_variables[] = {
"AFL_FORKSRV_INIT_TMOUT",
"AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
"AFL_IGNORE_UNKNOWN_ENVS",
"AFL_IMPORT_FIRST",
"AFL_INST_LIBS",
"AFL_INST_RATIO",
"AFL_KILL_SIGNAL",
"AFL_KEEP_TRACES",
"AFL_KEEP_ASSEMBLY",
"AFL_LD_HARD_FAIL",
@ -75,11 +80,13 @@ static char *afl_environment_variables[] = {
"AFL_LLVM_BLOCKLIST",
"AFL_LLVM_CMPLOG",
"AFL_LLVM_INSTRIM",
"AFL_LLVM_CALLER",
"AFL_LLVM_CTX",
"AFL_LLVM_CTX_K",
"AFL_LLVM_DICT2FILE",
"AFL_LLVM_DOCUMENT_IDS",
"AFL_LLVM_INSTRUMENT",
"AFL_LLVM_INSTRIM_LOOPHEAD",
"AFL_LLVM_INSTRUMENT",
"AFL_LLVM_LTO_AUTODICTIONARY",
"AFL_LLVM_AUTODICTIONARY",
"AFL_LLVM_SKIPSINGLEBLOCK",
@ -103,16 +110,22 @@ static char *afl_environment_variables[] = {
"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_FORKSRV",
"AFL_NO_UI",
"AFL_NO_PYTHON",
"AFL_UNTRACER_FILE",
"AFL_LLVM_USE_TRACE_PC",
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_MAP_SIZE",
"AFL_MAPSIZE",
"AFL_MAX_DET_EXTRAS",
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_NOOPT",
"AFL_PASSTHROUGH",
"AFL_PATH",
"AFL_PERFORMANCE_FILE",
"AFL_PRELOAD",
@ -122,6 +135,7 @@ static char *afl_environment_variables[] = {
"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",
@ -131,6 +145,7 @@ static char *afl_environment_variables[] = {
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
"AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES",
"AFL_QEMU_EXCLUDE_RANGES",
"AFL_QEMU_SNAPSHOT",
"AFL_QUIET",
"AFL_RANDOM_ALLOC_CANARY",
@ -157,6 +172,7 @@ static char *afl_environment_variables[] = {
"AFL_WINE_PATH",
"AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW",
"AFL_USE_QASAN",
NULL
};

View File

@ -64,7 +64,7 @@ typedef struct afl_forkserver {
FILE *plot_file; /* Gnuplot output file */
/* Note: lat_run_timed_out is u32 to send it to the child as 4 byte array */
/* Note: last_run_timed_out is u32 to send it to the child as 4 byte array */
u32 last_run_timed_out; /* Traced process timed out? */
u8 last_kill_signal; /* Signal that killed the child */
@ -83,6 +83,8 @@ typedef struct afl_forkserver {
bool uses_asan; /* Target uses ASAN? */
bool debug; /* debug mode? */
bool uses_crash_exitcode; /* Custom crash exitcode specified? */
u8 crash_exitcode; /* The crash exitcode specified */
@ -99,6 +101,8 @@ typedef struct afl_forkserver {
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
u8 kill_signal;
} afl_forkserver_t;
typedef enum fsrv_run_result {
@ -116,11 +120,14 @@ void afl_fsrv_init(afl_forkserver_t *fsrv);
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output);
u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output);
void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len);
fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
volatile u8 *stop_soon_p);
void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
void afl_fsrv_kill(afl_forkserver_t *fsrv);
#ifdef __APPLE__
#define MSG_FORK_ON_APPLE \

View File

@ -51,6 +51,7 @@ typedef struct sharedmem {
size_t map_size; /* actual allocated size */
int cmplog_mode;
int shmemfuzz_mode;
struct cmp_map *cmp_map;
} sharedmem_t;

View File

@ -25,10 +25,15 @@
#include <stdint.h>
#include <stdlib.h>
#include "config.h"
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#ifdef WORD_SIZE_64
typedef unsigned __int128 uint128_t;
typedef uint128_t u128;
#endif
/* Extended forkserver option values */
@ -50,7 +55,7 @@ typedef uint32_t u32;
#define FS_OPT_SHDMEM_FUZZ 0x01000000
#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1)
#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
#define FS_OPT_SET_MAPSIZE(x) \
(x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1))
@ -61,6 +66,10 @@ typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#ifdef WORD_SIZE_64
typedef __int128 int128_t;
typedef int128_t s128;
#endif
#ifndef MIN
#define MIN(a, b) \
@ -114,6 +123,33 @@ typedef int64_t s64;
\
})
// It is impossible to define 128 bit constants, so ...
#ifdef WORD_SIZE_64
#define SWAPN(_x, _l) \
({ \
\
u128 _res = (_x), _ret; \
char *d = (char *)&_ret, *s = (char *)&_res; \
int i; \
for (i = 0; i < 16; i++) \
d[15 - i] = s[i]; \
u32 sr = 128U - ((_l) << 3U); \
(_ret >>= sr); \
(u128) _ret; \
\
})
#endif
#define SWAPNN(_x, _y, _l) \
({ \
\
char *d = (char *)(_x), *s = (char *)(_y); \
u32 i, l = (_l)-1; \
for (i = 0; i <= l; i++) \
d[l - i] = s[i]; \
\
})
#ifdef AFL_LLVM_PASS
#if defined(__linux__) || !defined(__ANDROID__)
#define AFL_SR(s) (srandom(s))

View File

@ -38,7 +38,7 @@ typedef long double max_align_t;
#include "MarkNodes.h"
#include "afl-llvm-common.h"
#include "llvm-ngram-coverage.h"
#include "llvm-alternative-coverage.h"
#include "config.h"
#include "debug.h"
@ -135,7 +135,7 @@ struct InsTrim : public ModulePass {
unsigned int PrevLocSize = 0;
char * ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
char *ctx_str = getenv("AFL_LLVM_CTX");
char *caller_str = getenv("AFL_LLVM_CALLER");
#ifdef AFL_HAVE_VECTOR_INTRINSICS
unsigned int ngram_size = 0;
@ -197,10 +197,10 @@ struct InsTrim : public ModulePass {
GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
GlobalVariable *AFLPrevLoc;
GlobalVariable *AFLContext = NULL;
LoadInst * PrevCtx = NULL; // for CTX sensitive coverage
LoadInst * PrevCaller = NULL; // for CALLER sensitive coverage
if (ctx_str)
#ifdef __ANDROID__
if (caller_str)
#if defined(__ANDROID__) || defined(__HAIKU__)
AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
#else
@ -211,7 +211,7 @@ struct InsTrim : public ModulePass {
#ifdef AFL_HAVE_VECTOR_INTRINSICS
if (ngram_size)
#ifdef __ANDROID__
#if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
/* Initializer */ nullptr, "__afl_prev_loc");
@ -224,7 +224,7 @@ struct InsTrim : public ModulePass {
#endif
else
#endif
#ifdef __ANDROID__
#if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
#else
@ -398,19 +398,19 @@ struct InsTrim : public ModulePass {
unsigned int cur_loc;
// Context sensitive coverage
if (ctx_str && &BB == &F.getEntryBlock()) {
if (caller_str && &BB == &F.getEntryBlock()) {
PrevCtx = IRB.CreateLoad(AFLContext);
PrevCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None));
PrevCaller = IRB.CreateLoad(AFLContext);
PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None));
// does the function have calls? and is any of the calls larger than
// one basic block?
has_calls = 0;
for (auto &BB : F) {
for (auto &BB2 : F) {
if (has_calls) break;
for (auto &IN : BB) {
for (auto &IN : BB2) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
@ -441,7 +441,7 @@ struct InsTrim : public ModulePass {
}
} // END of ctx_str
} // END of caller_str
if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; }
@ -454,12 +454,12 @@ struct InsTrim : public ModulePass {
auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
DenseMap<BasicBlock *, unsigned> PredMap;
for (auto PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
BasicBlock *PBB = *PI;
auto It = PredMap.insert({PBB, genLabel()});
unsigned Label = It.first->second;
cur_loc = Label;
// cur_loc = Label;
PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB);
}
@ -485,9 +485,9 @@ struct InsTrim : public ModulePass {
#endif
PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
if (ctx_str)
if (caller_str)
PrevLocTrans =
IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCtx), Int32Ty);
IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCaller), Int32Ty);
/* Load SHM pointer */
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
@ -535,16 +535,17 @@ struct InsTrim : public ModulePass {
IRB.CreateStore(Incr, MapPtrIdx)
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
if (ctx_str && has_calls) {
if (caller_str && has_calls) {
// in CTX mode we have to restore the original context for the
// in CALLER mode we have to restore the original context for the
// caller - she might be calling other functions which need the
// correct CTX
// correct CALLER
Instruction *Inst = BB.getTerminator();
if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst)) {
IRBuilder<> Post_IRB(Inst);
StoreInst * RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext);
StoreInst * RestoreCtx =
Post_IRB.CreateStore(PrevCaller, AFLContext);
RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
MDNode::get(C, None));
@ -568,7 +569,7 @@ struct InsTrim : public ModulePass {
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr,
OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
total_rs, total_hs, modeline);
}

2
instrumentation/Makefile Normal file
View File

@ -0,0 +1,2 @@
all:
@echo "no need to do make in the instrumentation/ directory :) - it is all done in the main one"

View File

@ -332,11 +332,11 @@ bool Indistinguish(uint32_t node1, uint32_t node2) {
void MakeUniq(uint32_t now) {
bool StopFlag = false;
if (Marked.find(now) == Marked.end()) {
for (uint32_t pred1 : t_Pred[now]) {
bool StopFlag = false;
for (uint32_t pred2 : t_Pred[now]) {
if (pred1 == pred2) continue;

View File

@ -1,10 +1,11 @@
# CmpLog instrumentation
The CmpLog instrumentation enables the logging of the comparisons operands in a
The CmpLog instrumentation enables logging of comparison operands in a
shared memory.
These values can be used by various mutators built on top of it.
At the moment we support the RedQueen mutator (input-2-state instructions only).
At the moment we support the RedQueen mutator (input-2-state instructions only),
for details see [the RedQueen paper](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf).
## Build
@ -13,7 +14,7 @@ program.
The first version is built using the regular AFL++ instrumentation.
The second one, the CmpLog binary, with setting AFL_LLVM_CMPLOG during the compilation.
The second one, the CmpLog binary, is built with setting AFL_LLVM_CMPLOG during the compilation.
For example:
@ -26,11 +27,12 @@ export AFL_LLVM_CMPLOG=1
./configure --cc=~/path/to/afl-clang-fast
make
cp ./program ./program.cmplog
unset AFL_LLVM_CMPLOG
```
## Use
AFL++ has the new -c option that needs to be used to specify the CmpLog binary (the second
AFL++ has the new `-c` option that needs to be used to specify the CmpLog binary (the second
build).
For example:

View File

@ -4,14 +4,19 @@
This is an LLVM-based implementation of the context sensitive branch coverage.
Basically every function gets its own ID and that ID is combined with the
edges of the called functions.
Basically every function gets its own ID and, every time when an edge is logged,
all the IDs in the callstack are hashed and combined with the edge transition
hash to augment the classic edge coverage with the information about the
calling context.
So if both function A and function B call a function C, the coverage
collected in C will be different.
In math the coverage is collected as follows:
`map[current_location_ID ^ previous_location_ID >> 1 ^ previous_callee_ID] += 1`
`map[current_location_ID ^ previous_location_ID >> 1 ^ hash_callstack_IDs] += 1`
The callstack hash is produced XOR-ing the function IDs to avoid explosion with
recursive functions.
## Usage
@ -20,3 +25,14 @@ Set the `AFL_LLVM_INSTRUMENT=CTX` or `AFL_LLVM_CTX=1` environment variable.
It is highly recommended to increase the MAP_SIZE_POW2 definition in
config.h to at least 18 and maybe up to 20 for this as otherwise too
many map collisions occur.
## Caller Branch Coverage
If the context sensitive coverage introduces too may collisions and becoming
detrimental, the user can choose to augment edge coverage with just the
called function ID, instead of the entire callstack hash.
In math the coverage is collected as follows:
`map[current_location_ID ^ previous_location_ID >> 1 ^ previous_callee_ID] += 1`
Set the `AFL_LLVM_INSTRUMENT=CALLER` or `AFL_LLVM_CALLER=1` environment variable.

View File

@ -3,16 +3,20 @@
See [../README.md](../README.md) for the general instruction manual.
See [README.llvm.md](README.llvm.md) for the LLVM-based instrumentation.
This document describes how to build and use `afl-gcc-fast` and `afl-g++-fast`,
which instrument the target with the help of gcc plugins.
TLDR:
* `apt-get install gcc-VERSION-plugin-dev`
* `make`
* gcc and g++ must point to the gcc-VERSION you you have to set AFL_CC/AFL_CXX
* check the version of your gcc compiler: `gcc --version`
* `apt-get install gcc-VERSION-plugin-dev` or similar to install headers for gcc plugins
* `gcc` and `g++` must match the gcc-VERSION you installed headers for. You can set `AFL_CC`/`AFL_CXX`
to point to these!
* just use afl-gcc-fast/afl-g++-fast normally like you would afl-clang-fast
* `make`
* just use `afl-gcc-fast`/`afl-g++-fast` normally like you would do with `afl-clang-fast`
## 1) Introduction
The code in this directory allows you to instrument programs for AFL using
The code in this directory allows to instrument programs for AFL using
true compiler-level instrumentation, instead of the more crude
assembly-level rewriting approach taken by afl-gcc and afl-clang. This has
several interesting properties:
@ -27,10 +31,10 @@ several interesting properties:
- The instrumentation is CPU-independent. At least in principle, you should
be able to rely on it to fuzz programs on non-x86 architectures (after
building afl-fuzz with AFL_NOX86=1).
building `afl-fuzz` with `AFL_NOX86=1`).
- Because the feature relies on the internals of GCC, it is gcc-specific
and will *not* work with LLVM (see ../llvm_mode for an alternative).
and will *not* work with LLVM (see [README.llvm.md](README.llvm.md) for an alternative).
Once this implementation is shown to be sufficiently robust and portable, it
will probably replace afl-gcc. For now, it can be built separately and
@ -41,29 +45,32 @@ The idea and much of the implementation comes from Laszlo Szekeres.
## 2) How to use
In order to leverage this mechanism, you need to have modern enough GCC
(>= version 4.5.0) and the plugin headers installed on your system. That
(>= version 4.5.0) and the plugin development headers installed on your system. That
should be all you need. On Debian machines, these headers can be acquired by
installing the `gcc-VERSION-plugin-dev` packages.
To build the instrumentation itself, type 'make'. This will generate binaries
called afl-gcc-fast and afl-g++-fast in the parent directory.
To build the instrumentation itself, type `make`. This will generate binaries
called `afl-gcc-fast` and `afl-g++-fast` in the parent directory.
The gcc and g++ compiler links have to point to gcc-VERSION - or set these
by pointing the environment variables AFL_CC/AFL_CXX to them.
If the CC/CXX have been overridden, those compilers will be used from
those wrappers without using AFL_CXX/AFL_CC settings.
by pointing the environment variables `AFL_CC`/`AFL_CXX` to them.
If the `CC`/`CXX` environment variables have been set, those compilers will be
preferred over those from the `AFL_CC`/`AFL_CXX` settings.
Once this is done, you can instrument third-party code in a way similar to the
standard operating mode of AFL, e.g.:
CC=/path/to/afl/afl-gcc-fast ./configure [...options...]
```
CC=/path/to/afl/afl-gcc-fast
CXX=/path/to/afl/afl-g++-fast
export CC CXX
./configure [...options...]
make
```
Note: We also used `CXX` to set the C++ compiler to `afl-g++-fast` for C++ code.
Be sure to also include CXX set to afl-g++-fast for C++ code.
The tool honors roughly the same environmental variables as afl-gcc (see
[env_variables.md](../docs/env_variables.md). This includes AFL_INST_RATIO,
AFL_USE_ASAN, AFL_HARDEN, and AFL_DONT_OPTIMIZE.
The tool honors roughly the same environmental variables as `afl-gcc` (see
[env_variables.md](../docs/env_variables.md). This includes `AFL_INST_RATIO`,
`AFL_USE_ASAN`, `AFL_HARDEN`, and `AFL_DONT_OPTIMIZE`.
Note: if you want the GCC plugin to be installed on your system for all
users, you need to build it before issuing 'make install' in the parent
@ -72,7 +79,7 @@ directory.
## 3) Gotchas, feedback, bugs
This is an early-stage mechanism, so field reports are welcome. You can send bug
reports to afl@aflplus.plus
reports to afl@aflplus.plus.
## 4) Bonus feature #1: deferred initialization
@ -88,7 +95,7 @@ file before getting to the fuzzed data.
In such cases, it's beneficial to initialize the forkserver a bit later, once
most of the initialization work is already done, but before the binary attempts
to read the fuzzed input and parse it; in some cases, this can offer a 10x+
performance gain. You can implement delayed initialization in LLVM mode in a
performance gain. You can implement delayed initialization in GCC mode in a
fairly simple way.
First, locate a suitable location in the code where the delayed cloning can
@ -117,7 +124,7 @@ With the location selected, add this code in the appropriate spot:
```
You don't need the #ifdef guards, but they will make the program still work as
usual when compiled with a tool other than afl-gcc-fast/afl-clang-fast.
usual when compiled with a compiler other than afl-gcc-fast/afl-clang-fast.
Finally, recompile the program with afl-gcc-fast (afl-gcc or afl-clang will
*not* generate a deferred-initialization binary) - and you should be all set!
@ -127,7 +134,7 @@ Finally, recompile the program with afl-gcc-fast (afl-gcc or afl-clang will
Some libraries provide APIs that are stateless, or whose state can be reset in
between processing different input files. When such a reset is performed, a
single long-lived process can be reused to try out multiple test cases,
eliminating the need for repeated fork() calls and the associated OS overhead.
eliminating the need for repeated `fork()` calls and the associated OS overhead.
The basic structure of the program that does this would be:
@ -160,5 +167,9 @@ wary of memory leaks and the state of file descriptors.
When running in this mode, the execution paths will inherently vary a bit
depending on whether the input loop is being entered for the first time or
executed again. To avoid spurious warnings, the feature implies
AFL_NO_VAR_CHECK and hides the "variable path" warnings in the UI.
`AFL_NO_VAR_CHECK` and hides the "variable path" warnings in the UI.
## 6) Bonus feature #3: selective instrumentation
It can be more effective to fuzzing to only instrument parts of the code.
For details see [README.instrument_list.md](README.instrument_list.md).

View File

@ -1,8 +1,9 @@
# Using afl++ with partial instrumentation
This file describes how to selectively instrument only source files
or functions that are of interest to you using the LLVM and GCC_PLUGIN
instrumentation provided by afl++.
This file describes two different mechanisms to selectively instrument
only specific parts in the target.
Both mechanisms work for LLVM and GCC_PLUGIN, but not for afl-clang/afl-gcc.
## 1) Description and purpose
@ -12,28 +13,49 @@ the program, leaving the rest uninstrumented. This helps to focus the fuzzer
on the important parts of the program, avoiding undesired noise and
disturbance by uninteresting code being exercised.
For this purpose, a "partial instrumentation" support en par with llvm sancov
is provided by afl++ that allows to specify on a source file and function
level which function should be compiled with or without instrumentation.
For this purpose, "partial instrumentation" support is provided by afl++ that
allows to specify what should be instrumented and what not.
Note: When using PCGUARD mode - and llvm 12+ - you can use this instead:
https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
Both mechanisms can be used together.
The llvm sancov list format is fully supported by afl++, however afl++ has
more flexibility.
## 2) Selective instrumentation with __AFL_COVERAGE_... directives
## 2a) Building the LLVM module
In this mechanism the selective instrumentation is done in the source code.
The new code is part of the existing afl++ LLVM module in the instrumentation/
subdirectory. There is nothing specifically to do for the build :)
After the includes a special define has to be made, eg.:
## 2b) Building the GCC module
```
#include <stdio.h>
#include <stdint.h>
// ...
__AFL_COVERAGE(); // <- required for this feature to work
```
The new code is part of the existing afl++ GCC_PLUGIN module in the
instrumentation/ subdirectory. There is nothing specifically to do for
the build :)
If you want to disable the coverage at startup until you specify coverage
should be started, then add `__AFL_COVERAGE_START_OFF();` at that position.
## 3) How to use the partial instrumentation mode
From here on out you have the following macros available that you can use
in any function where you want:
* `__AFL_COVERAGE_ON();` - enable coverage from this point onwards
* `__AFL_COVERAGE_OFF();` - disable coverage from this point onwards
* `__AFL_COVERAGE_DISCARD();` - reset all coverage gathered until this point
* `__AFL_COVERAGE_SKIP();` - mark this test case as unimportant. Whatever happens, afl-fuzz will ignore it.
A special function is `__afl_coverage_interesting`.
To use this, you must define `void __afl_coverage_interesting(u8 val, u32 id);`.
Then you can use this function globally, where the `val` parameter can be set
by you, the `id` parameter is for afl-fuzz and will be overwritten.
Note that useful parameters for `val` are: 1, 2, 3, 4, 8, 16, 32, 64, 128.
A value of e.g. 33 will be seen as 32 for coverage purposes.
## 3) Selective instrumentation with AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST
This feature is equivalent to llvm 12 sancov feature and allows to specify
on a filename and/or function name level to instrument these or skip them.
### 3a) How to use the partial instrumentation mode
In order to build with partial instrumentation, you need to build with
afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++.
@ -90,7 +112,7 @@ fun: MallocFoo
```
Note that whitespace is ignored and comments (`# foo`) are supported.
## 4) UNIX-style pattern matching
### 3b) UNIX-style pattern matching
You can add UNIX-style pattern matching in the "instrument file list" entries.
See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.

View File

@ -168,26 +168,7 @@ This is the most powerful and effective fuzzing you can do.
Please see [README.persistent_mode.md](README.persistent_mode.md) for a
full explanation.
## 7) Bonus feature: 'trace-pc-guard' mode
LLVM is shipping with a built-in execution tracing feature
that provides AFL with the necessary tracing data without the need to
post-process the assembly or install any compiler plugins. See:
http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards
If you have not an outdated compiler and want to give it a try, build
targets this way:
```
AFL_LLVM_INSTRUMENT=PCGUARD make
```
Note that this is currently the default if you use LLVM >= 7, as it is the best
mode. Recommended is LLVM >= 9.
If you have llvm 11+ and compiled afl-clang-lto - this is the only better mode.
## 8) Bonus feature: 'dict2file' pass
## 7) Bonus feature: 'dict2file' pass
Just specify `AFL_LLVM_DICT2FILE=/absolute/path/file.txt` and during compilation
all constant string compare parameters will be written to this file to be

View File

@ -88,16 +88,35 @@ apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
### Building llvm yourself (version 12)
Building llvm from github takes quite some long time and is not painless:
```
```sh
sudo apt install binutils-dev # this is *essential*!
git clone https://github.com/llvm/llvm-project
git clone --depth=1 https://github.com/llvm/llvm-project
cd llvm-project
mkdir build
cd build
cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DCMAKE_BUILD_TYPE=Release -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/
make -j $(nproc)
export PATH=`pwd`/bin:$PATH
export LLVM_CONFIG=`pwd`/bin/llvm-config
# Add -G Ninja if ninja-build installed
# "Building with ninja significantly improves your build time, especially with
# incremental builds, and improves your memory usage."
cmake \
-DCLANG_INCLUDE_DOCS="OFF" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BINUTILS_INCDIR=/usr/include/ \
-DLLVM_BUILD_LLVM_DYLIB="ON" \
-DLLVM_ENABLE_BINDINGS="OFF" \
-DLLVM_ENABLE_PROJECTS='clang;compiler-rt;libcxx;libcxxabi;libunwind;lld' \
-DLLVM_ENABLE_WARNINGS="OFF" \
-DLLVM_INCLUDE_BENCHMARKS="OFF" \
-DLLVM_INCLUDE_DOCS="OFF" \
-DLLVM_INCLUDE_EXAMPLES="OFF" \
-DLLVM_INCLUDE_TESTS="OFF" \
-DLLVM_LINK_LLVM_DYLIB="ON" \
-DLLVM_TARGETS_TO_BUILD="host" \
../llvm/
cmake --build . --parallel
export PATH="$(pwd)/bin:$PATH"
export LLVM_CONFIG="$(pwd)/bin/llvm-config"
export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
cd /path/to/AFLplusplus/
make
sudo make install

View File

@ -16,7 +16,7 @@ at a very little cost (one instruction per edge).
(The alternative of saturated counters has been tested also and proved to be
inferior in terms of path discovery.)
This is implemented in afl-gcc, however for llvm_mode this is optional if
This is implemented in afl-gcc and afl-gcc-fast, however for llvm_mode this is optional if
the llvm version is below 9 - as there is a perfomance bug that is only fixed
in version 9 and onwards.

View File

@ -10,8 +10,8 @@ by Jinghan Wang, et. al.
Note that the original implementation (available
[here](https://github.com/bitsecurerlab/afl-sensitive))
is built on top of AFL's QEMU mode.
This is essentially a port that uses LLVM vectorized instructions to achieve
the same results when compiling source code.
This is essentially a port that uses LLVM vectorized instructions (available from
llvm versions 4.0.1 and higher) to achieve the same results when compiling source code.
In math the branch coverage is performed as follows:
`map[current_location ^ prev_location[0] >> 1 ^ prev_location[1] >> 1 ^ ... up to n-1`] += 1`

View File

@ -1,18 +1,16 @@
===========================================
Using afl++ without inlined instrumentation
===========================================
## Using afl++ without inlined instrumentation
This file describes how you can disable inlining of instrumentation.
By default, the GCC plugin will duplicate the effects of calling
__afl_trace (see afl-gcc-rt.o.c) in instrumented code, instead of
`__afl_trace` (see `afl-gcc-rt.o.c`) in instrumented code, instead of
issuing function calls.
The calls are presumed to be slower, more so because the rt file
itself is not optimized by the compiler.
Setting AFL_GCC_OUT_OF_LINE=1 in the environment while compiling code
Setting `AFL_GCC_OUT_OF_LINE=1` in the environment while compiling code
with the plugin will disable this inlining, issuing calls to the
unoptimized runtime instead.

View File

@ -16,7 +16,7 @@ Examples can be found in [utils/persistent_mode](../utils/persistent_mode).
## 2) TLDR;
Example `fuzz_target.c`:
```
```c
#include "what_you_need_for_your_target.h"
__AFL_FUZZ_INIT();
@ -60,14 +60,14 @@ The speed increase is usually x10 to x20.
If you want to be able to compile the target without afl-clang-fast/lto then
add this just after the includes:
```
```c
#ifndef __AFL_FUZZ_TESTCASE_LEN
ssize_t fuzz_len;
#define __AFL_FUZZ_TESTCASE_LEN fuzz_len
unsigned char fuzz_buf[1024000];
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
#define __AFL_FUZZ_INIT() void sync(void);
#define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ?
#define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0)
#define __AFL_INIT() sync()
#endif
```
@ -75,7 +75,7 @@ add this just after the includes:
## 3) Deferred initialization
AFL tries to optimize performance by executing the targeted binary just once,
stopping it just before main(), and then cloning this "main" process to get
stopping it just before `main()`, and then cloning this "main" process to get
a steady supply of targets to fuzz.
Although this approach eliminates much of the OS-, linker- and libc-level
@ -97,7 +97,7 @@ a location after:
- The creation of any vital threads or child processes - since the forkserver
can't clone them easily.
- The initialization of timers via setitimer() or equivalent calls.
- The initialization of timers via `setitimer()` or equivalent calls.
- The creation of temporary files, network sockets, offset-sensitive file
descriptors, and similar shared-state resources - but only provided that
@ -150,9 +150,9 @@ the impact of memory leaks and similar glitches; 1000 is a good starting point,
and going much higher increases the likelihood of hiccups without giving you
any real performance benefits.
A more detailed template is shown in ../utils/persistent_mode/.
Similarly to the previous mode, the feature works only with afl-clang-fast; #ifdef
guards can be used to suppress it when using other compilers.
A more detailed template is shown in `../utils/persistent_mode/.`
Similarly to the previous mode, the feature works only with afl-clang-fast;
`#ifdef` guards can be used to suppress it when using other compilers.
Note that as with the previous mode, the feature is easy to misuse; if you
do not fully reset the critical state, you may end up with false positives or
@ -161,7 +161,7 @@ wary of memory leaks and of the state of file descriptors.
PS. Because there are task switches still involved, the mode isn't as fast as
"pure" in-process fuzzing offered, say, by LLVM's LibFuzzer; but it is a lot
faster than the normal fork() model, and compared to in-process fuzzing,
faster than the normal `fork()` model, and compared to in-process fuzzing,
should be a lot more robust.
## 5) Shared memory fuzzing
@ -174,17 +174,17 @@ Setting this up is very easy:
After the includes set the following macro:
```
```c
__AFL_FUZZ_INIT();
```
Directly at the start of main - or if you are using the deferred forkserver
with `__AFL_INIT()` then *after* `__AFL_INIT? :
```
with `__AFL_INIT()` then *after* `__AFL_INIT()` :
```c
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
```
Then as first line after the `__AFL_LOOP` while loop:
```
```c
int len = __AFL_FUZZ_TESTCASE_LEN;
```
and that is all!

View File

@ -733,7 +733,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
Var->getInitializer())) {
HasStr2 = true;
Str2 = Array->getAsString().str();
Str2 = Array->getRawDataValues().str();
}
@ -760,7 +760,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
if (literalLength + 1 == optLength) {
Str2.append("\0", 1); // add null byte
addedNull = true;
// addedNull = true;
}
@ -809,7 +809,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
Var->getInitializer())) {
HasStr1 = true;
Str1 = Array->getAsString().str();
Str1 = Array->getRawDataValues().str();
}
@ -849,15 +849,18 @@ bool ModuleSanitizerCoverage::instrumentModule(
thestring = Str2;
optLen = thestring.length();
if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; }
if (isMemcmp || isStrncmp || isStrncasecmp) {
Value * op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (ilen) {
uint64_t literalLength = optLen;
optLen = ilen->getZExtValue();
if (optLen < 2) { continue; }
if (literalLength + 1 == optLen) { // add null byte
thestring.append("\0", 1);
addedNull = true;
@ -872,17 +875,21 @@ bool ModuleSanitizerCoverage::instrumentModule(
// was not already added
if (!isMemcmp) {
if (addedNull == false) {
if (addedNull == false && thestring[optLen - 1] != '\0') {
thestring.append("\0", 1); // add null byte
optLen++;
}
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
if (!isStdString) {
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
}
}
@ -1111,7 +1118,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations with no collisions (on average %llu "
"collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
"collisions would be in afl-gcc/vanilla AFL) (%s mode).",
inst, calculateCollisions(inst), modeline);
}
@ -1237,6 +1244,25 @@ void ModuleSanitizerCoverage::instrumentFunction(
for (auto &BB : F) {
for (auto &IN : BB) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
Value *val = ConstantInt::get(Int32Ty, ++afl_global_id);
callInst->setOperand(1, val);
}
}
if (shouldInstrumentBlock(F, &BB, DT, PDT, Options))
BlocksToInstrument.push_back(&BB);
for (auto &Inst : BB) {
@ -1338,6 +1364,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
if (AllBlocks.empty()) return false;
CreateFunctionLocalArrays(F, AllBlocks);
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
// afl++ START
@ -1403,24 +1430,17 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc;
if (IsEntryBB) {
if (auto SP = F.getSubprogram())
EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before
// calls.
IP = PrepareToSplitEntryBlock(BB, IP);
} else {
EntryLoc = IP->getDebugLoc();
}
IRBuilder<> IRB(&*IP);
IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC)

View File

@ -311,7 +311,8 @@ class ModuleSanitizerCoverage {
Function &F, Type *Ty,
const char *Section);
GlobalVariable *CreatePCArray(Function &F, ArrayRef<BasicBlock *> AllBlocks);
void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks);
void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks,
uint32_t special);
void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx,
bool IsLeafFunc = true);
Function *CreateInitCallsForSections(Module &M, const char *CtorName,
@ -970,11 +971,11 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray(
}
void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
Function &F, ArrayRef<BasicBlock *> AllBlocks) {
Function &F, ArrayRef<BasicBlock *> AllBlocks, uint32_t special) {
if (Options.TracePCGuard)
FunctionGuardArray = CreateFunctionLocalArrayInSection(
AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName);
AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName);
if (Options.Inline8bitCounters)
Function8bitCounterArray = CreateFunctionLocalArrayInSection(
@ -993,9 +994,38 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
bool IsLeafFunc) {
if (AllBlocks.empty()) return false;
CreateFunctionLocalArrays(F, AllBlocks);
uint32_t special = 0;
for (auto &BB : F) {
for (auto &IN : BB) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
uint32_t id = 1 + instr + (uint32_t)AllBlocks.size() + special++;
Value * val = ConstantInt::get(Int32Ty, id);
callInst->setOperand(1, val);
}
}
}
CreateFunctionLocalArrays(F, AllBlocks, special);
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
instr += special;
return true;
}
@ -1058,7 +1088,7 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch(
}
llvm::sort(Initializers.begin() + 2, Initializers.end(),
llvm::sort(drop_begin(Initializers, 2),
[](const Constant *A, const Constant *B) {
return cast<ConstantInt>(A)->getLimitedValue() <
@ -1106,10 +1136,10 @@ void ModuleSanitizerCoverage::InjectTraceForGep(
for (auto GEP : GepTraceTargets) {
IRBuilder<> IRB(GEP);
for (auto I = GEP->idx_begin(); I != GEP->idx_end(); ++I)
if (!isa<ConstantInt>(*I) && (*I)->getType()->isIntegerTy())
for (Use &Idx : GEP->indices())
if (!isa<ConstantInt>(Idx) && Idx->getType()->isIntegerTy())
IRB.CreateCall(SanCovTraceGepFunction,
{IRB.CreateIntCast(*I, IntptrTy, true)});
{IRB.CreateIntCast(Idx, IntptrTy, true)});
}
@ -1163,24 +1193,18 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc;
if (IsEntryBB) {
if (auto SP = F.getSubprogram())
EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before
// calls.
IP = PrepareToSplitEntryBlock(BB, IP);
} else {
EntryLoc = IP->getDebugLoc();
}
IRBuilder<> IRB(&*IP);
IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC);

File diff suppressed because it is too large Load Diff

View File

@ -228,7 +228,7 @@ struct afl_pass : gimple_opt_pass {
const bool neverZero;
/* Count instrumented blocks. */
int inst_blocks;
unsigned int inst_blocks;
virtual unsigned int execute(function *fn) {
@ -444,8 +444,10 @@ struct afl_pass : gimple_opt_pass {
DECL_EXTERNAL(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
TREE_STATIC(decl) = 1;
#if !defined(__ANDROID__) && !defined(__HAIKU__)
set_decl_tls_model(
decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC));
#endif
return decl;
}
@ -516,7 +518,9 @@ struct afl_pass : gimple_opt_pass {
"__cmplog",
"__sancov",
"msan.",
"LLVMFuzzer",
"LLVMFuzzerM",
"LLVMFuzzerC",
"LLVMFuzzerI",
"__decide_deferred",
"maybe_duplicate_stderr",
"discard_output",
@ -620,10 +624,11 @@ struct afl_pass : gimple_opt_pass {
allowListFiles.push_back(line);
else
allowListFunctions.push_back(line);
getline(fileStream, line);
}
getline(fileStream, line);
}
if (debug)
@ -694,10 +699,11 @@ struct afl_pass : gimple_opt_pass {
denyListFiles.push_back(line);
else
denyListFunctions.push_back(line);
getline(fileStream, line);
}
getline(fileStream, line);
}
if (debug)
@ -916,8 +922,9 @@ int plugin_init(struct plugin_name_args * info,
struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version))
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"),
GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR);
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
"is %s"),
gcc_version.basever, version->basever);
/* Show a banner. */
bool quiet = false;
@ -927,7 +934,7 @@ int plugin_init(struct plugin_name_args * info,
quiet = true;
/* Decide instrumentation ratio. */
int inst_ratio = 100;
unsigned int inst_ratio = 100U;
if (char *inst_ratio_str = getenv("AFL_INST_RATIO"))
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
inst_ratio > 100)

View File

@ -62,15 +62,19 @@ bool isIgnoreFunction(const llvm::Function *F) {
"sancov.",
"__ubsan_",
"ign.",
"__afl_",
"__afl",
"_fini",
"__libc_csu",
"__libc_",
"__asan",
"__msan",
"__cmplog",
"__sancov",
"__cxx_",
"_GLOBAL",
"msan.",
"LLVMFuzzer",
"LLVMFuzzerM",
"LLVMFuzzerC",
"LLVMFuzzerI",
"__decide_deferred",
"maybe_duplicate_stderr",
"discard_output",
@ -166,10 +170,11 @@ void initInstrumentList() {
allowListFiles.push_back(line);
else
allowListFunctions.push_back(line);
getline(fileStream, line);
}
getline(fileStream, line);
}
if (debug)
@ -240,10 +245,11 @@ void initInstrumentList() {
denyListFiles.push_back(line);
else
denyListFunctions.push_back(line);
getline(fileStream, line);
}
getline(fileStream, line);
}
if (debug)
@ -347,7 +353,7 @@ static std::string getSourceName(llvm::Function *F) {
if (cDILoc) { instFilename = cDILoc->getFilename(); }
if (instFilename.str().empty()) {
if (instFilename.str().empty() && cDILoc) {
/* If the original location is empty, try using the inlined location
*/

View File

@ -90,7 +90,7 @@ void dict2file(int fd, u8 *mem, u32 len) {
j = 1;
for (i = 0; i < len; i++) {
if (isprint(mem[i])) {
if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') {
line[j++] = mem[i];
@ -355,7 +355,9 @@ bool AFLdict2filePass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1);
std::string Str1, Str2;
StringRef TmpStr;
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
bool HasStr1;
getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) {
HasStr1 = false;
@ -367,7 +369,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
}
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
bool HasStr2;
getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) {
HasStr2 = false;
@ -401,7 +404,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
HasStr2 = true;
Str2 = Array->getAsString().str();
Str2 = Array->getRawDataValues().str();
}
@ -428,7 +431,6 @@ bool AFLdict2filePass::runOnModule(Module &M) {
if (literalLength + 1 == optLength) {
Str2.append("\0", 1); // add null byte
addedNull = true;
}
@ -478,7 +480,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
dyn_cast<ConstantDataArray>(Var->getInitializer())) {
HasStr1 = true;
Str1 = Array->getAsString().str();
Str1 = Array->getRawDataValues().str();
}
@ -519,14 +521,18 @@ bool AFLdict2filePass::runOnModule(Module &M) {
optLen = thestring.length();
if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; }
if (isMemcmp || isStrncmp || isStrncasecmp) {
Value * op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (ilen) {
uint64_t literalLength = optLen;
optLen = ilen->getZExtValue();
if (optLen < 2) { continue; }
if (literalLength + 1 == optLen) { // add null byte
thestring.append("\0", 1);
addedNull = true;
@ -541,17 +547,21 @@ bool AFLdict2filePass::runOnModule(Module &M) {
// was not already added
if (!isMemcmp) {
if (addedNull == false) {
if (addedNull == false && thestring[optLen - 1] != '\0') {
thestring.append("\0", 1); // add null byte
optLen++;
}
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
if (!isStdString) {
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
}
}

View File

@ -69,8 +69,9 @@ class AFLLTOPass : public ModulePass {
if (getenv("AFL_DEBUG")) debug = 1;
if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
if ((afl_global_id = atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE)
FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %d\n",
if ((afl_global_id = (uint32_t)atoi(ptr)) < 0 ||
afl_global_id >= MAP_SIZE)
FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %u\n",
ptr, MAP_SIZE - 1);
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
@ -88,7 +89,7 @@ class AFLLTOPass : public ModulePass {
bool runOnModule(Module &M) override;
protected:
int afl_global_id = 1, autodictionary = 1;
uint32_t afl_global_id = 1, autodictionary = 1;
uint32_t function_minimum_size = 1;
uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0;
uint64_t map_addr = 0x10000;
@ -100,9 +101,9 @@ class AFLLTOPass : public ModulePass {
bool AFLLTOPass::runOnModule(Module &M) {
LLVMContext & C = M.getContext();
std::vector<std::string> dictionary;
std::vector<CallInst *> calls;
LLVMContext & C = M.getContext();
std::vector<std::string> dictionary;
// std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap;
std::vector<BasicBlock *> BlockList;
char * ptr;
@ -471,7 +472,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1);
std::string Str1, Str2;
StringRef TmpStr;
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
bool HasStr1;
getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) {
HasStr1 = false;
@ -483,7 +485,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
bool HasStr2;
getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) {
HasStr2 = false;
@ -516,7 +519,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
Var->getInitializer())) {
HasStr2 = true;
Str2 = Array->getAsString().str();
Str2 = Array->getRawDataValues().str();
}
@ -543,7 +546,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (literalLength + 1 == optLength) {
Str2.append("\0", 1); // add null byte
addedNull = true;
// addedNull = true;
}
@ -592,7 +595,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
Var->getInitializer())) {
HasStr1 = true;
Str1 = Array->getAsString().str();
Str1 = Array->getRawDataValues().str();
}
@ -632,15 +635,18 @@ bool AFLLTOPass::runOnModule(Module &M) {
thestring = Str2;
optLen = thestring.length();
if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; }
if (isMemcmp || isStrncmp || isStrncasecmp) {
Value * op2 = callInst->getArgOperand(2);
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
if (ilen) {
uint64_t literalLength = optLen;
optLen = ilen->getZExtValue();
if (optLen < 2) { continue; }
if (literalLength + 1 == optLen) { // add null byte
thestring.append("\0", 1);
addedNull = true;
@ -655,23 +661,26 @@ bool AFLLTOPass::runOnModule(Module &M) {
// was not already added
if (!isMemcmp) {
if (addedNull == false) {
if (addedNull == false && thestring[optLen - 1] != '\0') {
thestring.append("\0", 1); // add null byte
optLen++;
}
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
if (!isStdString) {
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
}
}
if (!be_quiet) {
std::string outstring;
fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
thestring.length());
for (uint8_t i = 0; i < thestring.length(); i++) {
@ -872,7 +881,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
pow2map++;
WARNF(
"We have %u blocks to instrument but the map size is only %u. Either "
"edit config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
"edit config.h and set MAP_SIZE_POW2 from %d to %u, then recompile "
"afl-fuzz and llvm_mode and then make this target - or set "
"AFL_MAP_SIZE with at least size %u when running afl-fuzz with this "
"target.",
@ -922,9 +931,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) {
uint32_t write_loc = afl_global_id;
if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3);
uint32_t write_loc = (((afl_global_id + 63) >> 6) << 6);
GlobalVariable *AFLFinalLoc = new GlobalVariable(
M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc");
@ -937,8 +944,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (dictionary.size()) {
size_t memlen = 0, count = 0, offset = 0;
char * ptr;
size_t memlen = 0, count = 0;
// sort and unique the dictionary
std::sort(dictionary.begin(), dictionary.end());
@ -953,14 +959,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
if (!be_quiet)
printf("AUTODICTIONARY: %lu string%s found\n", count,
printf("AUTODICTIONARY: %zu string%s found\n", count,
count == 1 ? "" : "s");
if (count) {
if ((ptr = (char *)malloc(memlen + count)) == NULL) {
fprintf(stderr, "Error: malloc for %lu bytes failed!\n",
fprintf(stderr, "Error: malloc for %zu bytes failed!\n",
memlen + count);
exit(-1);
@ -968,6 +974,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
count = 0;
size_t offset = 0;
for (auto token : dictionary) {
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
@ -1031,8 +1038,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations with no collisions (on average %llu "
"collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
OKF("Instrumented %d locations with no collisions (on average %llu "
"collisions would be in afl-gcc/vanilla AFL) (%s mode).",
inst_blocks, calculateCollisions(inst_blocks), modeline);
}

Some files were not shown because too many files have changed in this diff Show More