Compare commits

...

344 Commits
2.57c ... 2.60c

Author SHA1 Message Date
842cd9dec3 final touches before 2.60 2019-12-31 12:52:10 +01:00
4b4effe343 Update README.md 2019-12-30 23:38:50 +01:00
c3bb0a3421 added testcases for afl-tmin and afl-cmin 2019-12-30 22:21:51 +01:00
878a80de7f critical bugfix for afl-tmin 2019-12-30 22:01:36 +01:00
f7e1397d98 Merge pull request #160 from devnexen/timingsafe_flavors_libtoken
libtokencap adding timingsafe* string comparators
2019-12-30 20:09:57 +01:00
e90fa623d9 libtokencap adding timingsafe* string comparators 2019-12-30 17:23:23 +00:00
9829c5eb95 really ensure that all .test files are removed after they are not needed anymore 2019-12-30 15:14:00 +01:00
3f23f40a56 makefile clean fix 2019-12-30 13:26:39 +01:00
cd2cae720b added AFL_AS_FORCE_INSTRUMENT env 2019-12-29 19:38:45 +01:00
65b4141cd3 make clean beautification 2019-12-28 19:04:05 +01:00
58c7a0f8fe Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-12-28 18:22:15 +01:00
9a2f2f1ee9 remove docs when building qemu static 2019-12-28 15:56:29 +01:00
c983e2c5b1 code format 2019-12-28 11:42:06 +01:00
2eb88d31a4 Update README.md
fix some typos
2019-12-28 09:56:39 +01:00
0fb68cbbfa Merge pull request #156 from n0pFlux/master
Fixed memory leak in afl-fuzz-python.c - trim_case_python.
2019-12-27 20:50:04 +01:00
064cd3315c fix issue #155 AFL_LLVM_LAF_SPLIT_FLOATS breaks bogofilter
added some forgotten floating point comparison types
2019-12-27 20:13:00 +01:00
n0p
cc3bf762ec Fixed memory leak in afl-fuzz-python.c - trim_case_python. 2019-12-27 18:50:14 +01:00
29bbe0aebe Merge pull request #154 from devnexen/setsockopt_socket_fuzzing
socket fuzzing build warning fixes proposal / setsockopt no-op
2019-12-26 14:56:38 +01:00
33ce5829c3 socket fuzzing build warning fixes proposal / setsockopt no-op 2019-12-26 13:50:50 +01:00
a05bd3e477 code format 2019-12-25 10:42:23 +01:00
9ed4bfbca8 AFL_PRELOAD -> QEMU_SET_ENV for afl-fuzz,afl-showmap,afl-analyze,afl-tmin 2019-12-25 10:35:49 +01:00
67b6298895 qemu ld_preload support and added socket_fuzzing ld_preload library 2019-12-24 20:56:10 +01:00
3122790295 Merge pull request #152 from afflux/argvfuzz
argvfuzz preload for fuzzing binaries' argv
2019-12-24 20:16:39 +01:00
5aa089d1b2 argv_fuzzing: should also compile with AFL_NO_X86 2019-12-24 16:09:48 +01:00
b0a2160c3a be sure to have directories for install targets 2019-12-24 10:45:39 +01:00
4f343e791a restore llvm DebugInfo 2019-12-21 22:02:50 +01:00
7db87ec74b argvfuzz preload for fuzzing binaries' argv 2019-12-21 21:42:35 +01:00
8679f3d757 try to work with llvm < 3.7 2019-12-21 21:14:01 +01:00
65bafe7192 Merge pull request #150 from afflux/master
minor fix for llvm_mode build with non-standard paths
2019-12-21 21:09:19 +01:00
49b3c9e0a0 remove remainder of git submodule
commit 7028c9b59d only removed the
.gitmodules entry. this commit removes the corresponding directory, so
`git submodule status` won't fail anymore.
2019-12-21 17:49:39 +01:00
e244f85c0b use llvm-config from env for version check 2019-12-21 17:46:29 +01:00
cc151388a1 Merge pull request #148 from devnexen/make_distrib_non_linux_fix_proposal
On non Linux systems, (g)make distrib stops halfway
2019-12-20 18:15:07 +01:00
5f0a252fae On non Linux systems, (g)make distrib stops halfway
because of QEMU not supported.
Symplifying cores counting data gathering.
2019-12-20 16:37:48 +00:00
d8fb4a8e19 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-12-19 14:35:37 +01:00
5e53d337db split havoc/custom line in status screen 2019-12-19 14:35:26 +01:00
b91000fc9e llvm_mode for Android 2019-12-19 01:53:32 +01:00
ce3cd71dc0 Merge pull request #146 from domenukk/unmapping
Tidied up python examles and fixed bug in uc_afl_fuzz
2019-12-18 15:33:25 +01:00
c283487d94 removed debug print 2019-12-18 13:49:36 +01:00
fe74c68c42 afl_fuzz unmapping 2019-12-18 12:23:35 +01:00
a521bfdfd8 fix travis bug? 2019-12-18 11:58:25 +01:00
d7b6b810d1 fix potential make clean error 2019-12-18 11:50:59 +01:00
7028c9b59d remove git submodule 2019-12-18 11:23:04 +01:00
891f067051 v2.59d init 2019-12-18 11:22:18 +01:00
939721e2cb v2.59c release 2019-12-18 11:14:12 +01:00
6226e38451 beautified error log when -m32 is not available on unsigaction 2019-12-18 11:05:52 +01:00
64435284ce added Android PR from afl, left some ifdefs commented out though 2019-12-18 09:17:49 +01:00
cf70fe0c9e updated docs 2019-12-17 12:10:45 +01:00
7218afdd8e typo 2019-12-16 14:31:16 +01:00
0627336466 unicornafl readme & changelog 2019-12-16 11:18:59 +01:00
2b9ad9acb6 Merge pull request #138 from domenukk/unicornafl
Moved unicorn_mode to unicornafl
2019-12-16 10:47:50 +01:00
17d364c8a0 fix alloc_canary should not be on TLS. thread #0 malloc=a -> thread #1 free(a) results in a wringly detected canary mistmatch 2019-12-16 10:42:34 +01:00
6ccfc2df56 update unicorn submodule 2019-12-16 10:11:29 +01:00
26d27d9121 skip unicorn tests if cannot import unicornafl 2019-12-16 09:44:17 +01:00
7832daf969 update unicorn submodule 2019-12-16 09:05:46 +01:00
860bce8a80 Merge branch 'unicornafl' of https://github.com/domenukk/AFLplusplus into unicornafl 2019-12-16 09:05:08 +01:00
eb61134bed fixed unicorn deps for python2 2019-12-16 01:36:37 +01:00
c5d4e8d0c7 more prints, ignoring crashdumps 2019-12-16 00:32:33 +01:00
201287f60f Merge branch 'unicornafl' of https://github.com/domenukk/AFLplusplus into unicornafl 2019-12-15 22:47:09 +01:00
d0d0405676 latest unicornafl version 2019-12-15 22:46:57 +01:00
42f992303e re-update submodule 2019-12-15 22:43:14 +01:00
e79a4faf10 Revert "make travis happy"
This reverts commit fc1a52b1c6.
2019-12-15 22:25:06 +01:00
2863d6205b fix travis build errors (hopefully) 2019-12-15 22:04:00 +01:00
624f0da6c0 slight fix for llvm_mode Makefile 2019-12-15 21:42:30 +01:00
c3423d81d0 Merge pull request #140 from devnexen/llvm_mode_no_apple_build_fix
Concealing the no build test to apple devices.
2019-12-15 21:39:55 +01:00
fc1a52b1c6 make travis happy 2019-12-15 21:39:38 +01:00
05825a888e Fixes for unicorn testscases 2019-12-15 18:48:57 +01:00
bc6c5d6be2 QEMU_LD_PREFIX in readme for clarity 2019-12-15 15:06:44 +01:00
6bf9855342 solve typing error on QEMU with host arch i386 2019-12-15 14:17:54 +01:00
0db7b39e62 Updating llvm_unsupported policy 2019-12-15 12:44:21 +00:00
49c9b68e4e Moved unicorn_mode to unicornafl 2019-12-15 05:03:32 +01:00
d40b670388 solve #134 2019-12-12 22:18:52 +01:00
01f0af64da malloc_context_size=0 as default options for sanitizers to have faster malloc/free 2019-12-12 14:00:22 +01:00
31f7404272 fixes for FreeBSD: libtokencap, free cpu detection threshold 2019-12-10 11:00:39 +01:00
cb4a20ba6d fix libtokencap for OpenBSD 2019-12-10 09:12:20 +01:00
8c841a068a fix machine description for NetBSD 'amd64' 2019-12-10 07:43:19 +01:00
f3fb1d3411 avoid rebuilding libdislocator on every make 2019-12-10 07:33:53 +01:00
22452da2a7 fix libtokencap Makefile for NetBSD, add VPATH to avoid rebuilding
the lib on every make.
2019-12-10 07:23:58 +01:00
cd165b18f0 fix warn -> warning, no targets when prerequisites are not met 2019-12-10 06:50:02 +01:00
7515e1edb5 Merge branch 'master' of https://github.com/vanhauser-thc/AFLplusplus 2019-12-10 06:44:20 +01:00
a49384f23c undo ignoring errors for optional components 2019-12-10 06:41:05 +01:00
9b39900c30 Merge pull request #133 from RootUp/patch-1
Updating regexp.dict
2019-12-09 23:34:15 +01:00
8817c66e98 Update regexp.dict 2019-12-09 22:57:35 +05:30
2038f86016 documented llvm 10 support 2019-12-09 15:16:10 +01:00
b8b0ba004b fix tests on MacOS, radamsa test could not find an instrumented
binary.
2019-12-09 13:15:31 +01:00
41165c0e68 continue make targets 'distrib'i, 'binary-only' and 'clean', even
there was an error for optional actions like qemu_mode and
unicorn_mode
2019-12-09 12:25:40 +01:00
30e4e7340e on MacOS llvm is not installed by default, add a test for that. Before this fix
the make run proceeded, producing meaningless error messages.
2019-12-09 12:19:57 +01:00
aa95728c35 Merge pull request #131 from devnexen/ios_build_fix
IOS build fix.
2019-12-09 10:59:42 +01:00
b262c5478c support universal mach-o binaries 2019-12-07 11:42:26 +01:00
ef43a4f82e IOS build fix.
system call is disabled on this platform.
2019-12-06 18:43:15 +00:00
8bc0b646f0 more travis 2019-12-05 16:10:39 +01:00
65bee44d6d non-intel test.sh support 2019-12-05 15:59:01 +01:00
7d585059e7 test script changes for arm64 2019-12-05 15:41:25 +01:00
d08504a667 travis enhancement 2019-12-05 15:12:28 +01:00
08f2a35b9b Merge pull request #130 from devnexen/last_nit_before_rel
Suppress noisy little build compiler plugins warning on platforms != …
2019-12-05 15:00:33 +01:00
8e64b13bc0 travis changes ... travis you suck 2019-12-05 15:00:00 +01:00
983abf359c Suppress noisy little build compiler plugins warning on platforms != Linux 2019-12-05 13:05:17 +00:00
233112c9b6 Changelog beautification 2019-12-05 11:24:41 +01:00
37dbccb674 changelog 2019-12-05 10:38:56 +01:00
c8524ad363 show travis state in readme.md 2019-12-03 15:02:23 +01:00
30435ee1f5 python3 support - even better :) 2019-12-03 14:51:41 +01:00
ac322253ca shut up travis. seriously. 2019-12-03 14:39:59 +01:00
05bb4252bf travis, finally? please? 2019-12-03 14:25:39 +01:00
e5326e797e travis oh my travis ... sigh 2019-12-03 10:31:14 +01:00
ca203d413f code format 2019-12-03 10:21:35 +01:00
a1e5a2e607 Merge pull request #129 from devnexen/libdislocator_typo
libdislocator, typo fix.
2019-12-03 10:19:50 +01:00
674fbc39f8 python3.7 support for afl-fuzz py mutator 2019-12-03 10:11:39 +01:00
948a83ef9f libdislocator, typo fix. 2019-12-03 09:01:23 +00:00
2b0cfe1ab5 final touches 2019-12-03 01:45:01 +01:00
6b6aa23645 Merge pull request #127 from devnexen/llvm_mode_build_fix
LLVM 10 build fix proposal
2019-12-03 01:41:31 +01:00
4231c49839 Merge branch 'master' into llvm_mode_build_fix 2019-12-03 01:40:41 +01:00
ef2dc98773 maybe we can work with xcode? 2019-12-03 00:30:35 +01:00
984faca4e8 Merge pull request #128 from devnexen/libtokencap_dflybsd
Enable libtokencap on DragonFlyBSD
2019-12-02 22:02:53 +01:00
70ad97d739 Enable libtokencap on DragonFlyBSD 2019-12-02 21:00:37 +00:00
1ab2a0cce9 getting very close with travis 2019-12-02 17:48:17 +01:00
c19b6fb260 getting very close with travis 2019-12-02 17:33:09 +01:00
dbdd9dbbde getting very close with travis 2019-12-02 17:32:31 +01:00
a3416b1571 nearing final travis config 2019-12-02 17:07:34 +01:00
e12b71773d nearing final travis config 2019-12-02 17:05:40 +01:00
f576c87e3a further travis tweaking 2019-12-02 16:38:20 +01:00
c5e231a711 support gcc-4.x 2019-12-02 16:36:18 +01:00
57334a44c1 further travis tweaking 2019-12-02 16:31:04 +01:00
523859f37c further travis tweaking 2019-12-02 16:27:03 +01:00
0894f8cf7a further travis tweaking 2019-12-02 16:07:35 +01:00
d8234e58a4 further travis tweaking 2019-12-02 16:00:47 +01:00
f6a6df7279 new travis 2019-12-02 15:44:14 +01:00
b0d590fef4 LLVM 10 build fix proposal
c++14 is the minimum for this version, thus the hardcoded gnu++11
standard flag makes the build fails.
Missing header only for this version seemingly for the option.
2019-12-02 14:26:29 +00:00
f8bc9b54da added -N no_unlink option 2019-12-02 15:25:17 +01:00
60c8121c1d add code-format target to make help 2019-12-02 14:50:00 +01:00
124ec8d297 code format (contributors, do it!) 2019-12-02 14:34:21 +01:00
e9ed056913 libcompcov common cmp funcs from honggfuzz 2019-12-02 14:30:23 +01:00
99b0860835 tokencap now wraps common routines and uses RTLD_NEXT 2019-12-02 14:22:42 +01:00
25b435060c Merge pull request #125 from devnexen/libtokencap_memmem
libtokencap, simple optimised memmem implementation enough for this l…
2019-12-02 13:55:51 +01:00
ba1b04be1e fix of fix of fix in libdislocator 2019-12-02 13:34:32 +01:00
2ccf5323c2 increase time for radamsa test 2019-12-02 11:05:09 +01:00
891aadaaca Merge pull request #126 from devnexen/libdislocator_build_fix_andrea
fix old linux kernel/Andrea approach
2019-12-02 10:23:38 +01:00
2e07261f57 fix old linux kernel/Andrea approach 2019-12-02 07:29:35 +00:00
5178a0cbba libtokencap, simple optimised memmem implementation enough for this lib proposal 2019-12-01 16:00:44 +00:00
8d5fded4d8 Merge pull request #124 from devnexen/old_linux_libdislocator_build_fix
getrandom available only from GLIBC 2.25
2019-12-01 15:26:22 +01:00
8e85b9cbf3 getrandom available only from GLIBC 2.25 2019-12-01 06:16:24 +00:00
d4da9b805a Merge pull request #121 from devnexen/libdislocator_little_upd
libdislocator updates improvements proposal.
2019-11-30 14:48:16 +01:00
ae4f770dad Merge pull request #112 from devnexen/unicorn_mode_obsd
unicorn mode, parallel job cmd fix for openbsd
2019-11-30 14:37:56 +01:00
cbe38ff905 Merge pull request #120 from devnexen/py2_mod_build_fix
Python module build fix in exotic oses
2019-11-30 14:30:53 +01:00
9c2e27a026 Merge pull request #122 from bmwiedemann/date
Allow to override build date with SOURCE_DATE_EPOCH
2019-11-30 14:21:14 +01:00
644bdd220e Allow to override build date with SOURCE_DATE_EPOCH
in order to make builds reproducible.
See https://reproducible-builds.org/ for why this is good
and https://reproducible-builds.org/specs/source-date-epoch/
for the definition of this variable.

Note: This date call is designed to work with different flavors
of date (GNU, BSD and others).
2019-11-28 20:01:50 +01:00
93a9e2daf3 libdislocator updates improvements proposal.
- optional tls alloc_canary value.
- slight change of memory limit value checking.
2019-11-28 08:33:36 +00:00
b2896c79c6 env var to disable qemu caching 2019-11-27 17:02:43 +01:00
8c0d247126 qemu readme reserved va trick 2019-11-27 16:16:17 +01:00
39dc0cca37 Python module build fix in exotic oses 2019-11-26 09:10:39 +00:00
7f0fe3b7d2 Merge pull request #116 from geeksonsecurity/unicorn-build-error
Fix unicorn build error on macOS
2019-11-24 23:02:06 +01:00
2f209414ef Fix build error on macOS 2019-11-24 22:12:15 +01:00
ccb156c704 Merge pull request #114 from devnexen/cmp_plugin_create_constants_once
compiler plugins, just create const constants once.
2019-11-22 13:30:47 +01:00
8a2f2e1792 compiler plugins, just create const constants once. 2019-11-22 11:03:45 +00:00
79490e75be Merge pull request #113 from devnexen/empty_plot_values_when_exec_stop
the plot data does not generate proper gnuplot data
2019-11-20 15:04:44 +01:00
e8b576fb9f the plot data does not generate proper gnuplot data
when killed or for a defined amount of time.
2019-11-20 13:36:07 +00:00
d96b27b603 update documentation 2019-11-17 12:01:37 +01:00
c8d94e88a7 Merge pull request #109 from hac425xxx/qbdi_mode
Qbdi mode
2019-11-17 11:49:07 +01:00
f3a23e51fa . 2019-11-17 11:41:44 +01:00
7e022a09cc adjust qbdi mode 2019-11-17 11:39:21 +01:00
b6e51a5cd6 unicorn mode, parallel job cmd fix for openbsd 2019-11-17 10:12:15 +00:00
a8f6ce5475 fix wrong commit 2019-11-17 10:54:16 +01:00
c96efdcb36 not all CPUs understand ondemand 2019-11-17 10:51:56 +01:00
55ef73ed57 not all CPUs understand ondemand 2019-11-17 10:51:15 +01:00
4b3deaf28b not all CPUs know ondemand 2019-11-15 14:46:01 +01:00
d8264390d2 typos 2019-11-15 11:26:10 +01:00
0071e537f3 format code for demo-so.c and template.cpp 2019-11-14 14:38:04 +00:00
5efd936e1e add image 2019-11-14 14:32:36 +00:00
c8c004d568 modify build.sh and add document 2019-11-14 14:30:29 +00:00
a9972fe559 add notes about code style in contributing 2019-11-14 10:46:38 +01:00
1f7f9fa9ec Merge pull request #110 from k0ss/patch-1
Fix docker build
2019-11-14 09:11:59 +01:00
a9d0cad485 old gcc produces not so good code ... 2019-11-13 16:02:36 +01:00
f85b0d421a added instrumentation count test cases 2019-11-13 15:19:31 +01:00
88384c89f3 Added workdir
Last addition I swear.  Now you can just run, for example: `docker run --rm -v $PWD:/work -it aflplusplus:latest ./build_script_in_working_dir.sh'.  Had forgotten this but figured this would make things easier for folks.
2019-11-13 05:33:20 +00:00
22cfd595ef Shaved 600mB off resulting Docker image
By removing the build files after the build is complete, we save 600mB of unnecessary bulk.  The total image size will now be 1gB.
2019-11-13 03:42:39 +00:00
e235c02e1e Fix docker build
The docker build has never worked for me.  I fixed all the build errors, mostly due to missing dependencies.  I also fixed silent errors that would allow for the build to finish but wouldn't contain features such as python mutators or QEMU's unsigaction module.
2019-11-13 02:56:14 +00:00
02548197e8 radamsa bsd fix 2019-11-12 23:41:14 +01:00
c2ba6e4503 fix linking error with tls storage, WIP for inline (not working yet) 2019-11-12 23:16:00 +01:00
7f017aa724 enabled neverZero feature again 2019-11-12 23:12:14 +01:00
d51719fbd9 better do not rely on config info from gcc 2019-11-12 23:02:56 +01:00
1392a6dba7 install afl-fuzz-document if present 2019-11-12 11:30:36 +01:00
7413ca9589 finding libradamsa fix 2019-11-12 11:28:49 +01:00
2b1e56331d finding libradamsa fix 2019-11-12 11:24:58 +01:00
cc5e69816f upgraded radamsa to newest version 2019-11-12 11:17:31 +01:00
c59e07581d Merge pull request #107 from devnexen/gcc_plugin_pass_real_cmp_naming
gcc plugin little update proposal.
2019-11-12 10:31:49 +01:00
c15053d1f8 Merge pull request #108 from devnexen/radamsa_mutator_upd
libradamsa forgotten possible undefined symbol.
2019-11-12 10:27:41 +01:00
5939727b66 A bit of user awareness 2019-11-12 09:26:59 +00:00
3ceb679465 libradamsa forgotten possible undefined symbol.
Note: do not know if it should be upstreamed first or not though...
2019-11-12 09:24:16 +00:00
8f188194c1 gcc plugin little update proposal.
like its llvm counterpart, passing the compiler chain used
to avoid using necessarily AFL_CC/AFL_CXX.
2019-11-12 09:13:13 +00:00
760d4991f3 Android PR integration 2019-11-11 23:50:31 +01:00
613ab3ba2a changelog 2019-11-11 18:12:06 +01:00
9477967c54 link radasma doc 2019-11-11 16:55:41 +01:00
388f4ae302 Merge pull request #106 from vanhauser-thc/radamsa
Radamsa
2019-11-11 15:53:24 +01:00
f1fbea96f6 radamsa in readme 2019-11-11 15:51:21 +01:00
f0aaee2044 add test case 2019-11-11 15:23:14 +01:00
ac7d210b6b Makefile - add radamsa to targets 2019-11-11 15:06:48 +01:00
659db7e421 Merge branch 'master' into radamsa 2019-11-11 14:36:06 +01:00
cd84339bcc libradamsa dlopen 2019-11-11 14:32:50 +01:00
01d5537244 /sbin in path 2019-11-09 16:48:01 +01:00
ab8fb271f7 add support for android x86, x86-64 in qbdi mode 2019-11-09 15:18:24 +00:00
58a18ea50b not all sysctl are in /sbin, e.g. with busybox 2019-11-09 15:23:16 +01:00
574de9ff4c add basic supprt for qbdi_mode, test x86_64 Linux 2019-11-09 14:21:39 +00:00
9d8458bb6d Merge pull request #105 from devnexen/gcc_plugin_upd
gcc plugin llittle update proposal to match better LLVM's
2019-11-09 12:20:46 +01:00
b22145d0c4 gcc plugin llittle update proposal to match better LLVM's 2019-11-09 10:37:44 +00:00
99e623ef0b Merge pull request #104 from devnexen/test_linux_chg
test, /sbin not necessarily in the path os casual users.
2019-11-08 19:49:57 +01:00
7a20cc2f58 additional test, if afl-as is called by afl-gcc/afl-clang (seen in OpenIndiana) 2019-11-08 19:27:25 +01:00
8290bb3374 test, /sbin not necessarily in the path os casual users. 2019-11-08 13:46:08 +00:00
a3932d7f00 raise limit for free core detection on FreeBSD and dragonFlyBSD 2019-11-08 04:39:22 +01:00
8082dd43bc Merge pull request #103 from devnexen/libdislocator_sp
libdislocator, optional huge pages support.
2019-11-07 19:50:02 +01:00
642a756b66 Merge pull request #99 from devnexen/unicorn_mode_bsd
Unicorn mode for BSD proposal.
2019-11-07 19:48:14 +01:00
f6c44a83bc typo for the checksum 2019-11-07 15:06:48 +00:00
b92da08ae8 Taking in account last changes 2019-11-07 11:52:04 +00:00
499f078c37 f*ckin travis 2019-11-07 11:48:39 +01:00
92669e65ee we only do one vm for the testing. having 3 just gives headache 2019-11-07 10:38:16 +01:00
7b82ef22be Little tweks for BSD 2019-11-07 05:05:55 +00:00
3ce808688f Little additions from feedback 2019-11-07 04:58:18 +00:00
cc301c18d5 libdislocator, optional huge pages support. 2019-11-06 22:33:39 +00:00
db7c990346 even easier test case solving :) 2019-11-06 13:41:23 +01:00
7c99027c31 unicorn libcompcov testcase made easier 2019-11-06 13:31:58 +01:00
5cb0012c83 test travis 2019-11-06 13:08:07 +01:00
a09cfd57a4 Unicorn mode for BSD proposal.
Darwin fix
2019-11-06 04:46:49 +00:00
62d9729629 travis is drunk 2019-11-05 20:06:11 +01:00
ed16281737 mmmm travis doh 2019-11-05 19:48:17 +01:00
4d9a463297 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-11-05 18:41:35 +01:00
e13fdfb2ce reduce time for unicorn compcov test 2019-11-05 18:41:23 +01:00
73cb587266 test unicorn && AFL_DISABLE_TRIM env var 2019-11-05 18:39:16 +01:00
48388b9eaa Merge pull request #101 from devnexen/libtoken_catch_pid_before_all
catching current pid before library usage in case implementations rel…
2019-11-05 12:09:44 +01:00
61e46a636c catching current pid before library usage in case implementations rely on those string calls 2019-11-05 10:59:22 +00:00
dede2e9764 dockerfile additions 2019-11-05 09:16:04 +01:00
c9c7e4777e Merge pull request #100 from devnexen/docker
Basic docker build proposal.
2019-11-05 09:01:37 +01:00
67ae54c957 Using LLVM/GCC 9 tooling 2019-11-04 17:15:56 +00:00
14c359700b Basic docker build proposal. 2019-11-04 15:37:56 +00:00
c11b8883e0 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-11-04 15:46:59 +01:00
adae07d013 restored big-endian compcov in unicorn 2019-11-04 15:46:49 +01:00
1c7b6a5e05 travis 2019-11-04 13:10:52 +01:00
fbeba570e6 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-11-03 13:02:41 +01:00
c3b2fee074 Unicorn mode for BSD proposal.
Darwin fix
2019-11-01 14:45:03 +00:00
e2442f7471 Merge pull request #98 from devnexen/sub_readme_renaming
libtokencap/libdislocator README rename proposals
2019-10-31 17:15:56 +01:00
b33bb0943a libtokencap/libdislocator README rename proposals
and fixing the install tasks in the process.
2019-10-31 15:50:58 +00:00
58fe2f2c76 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-10-31 16:19:26 +01:00
664f603a31 better wine trace with winepath on .cur_input 2019-10-31 16:19:12 +01:00
b17afc10a2 travis update 2019-10-31 13:27:48 +01:00
74f7576313 travis update 2019-10-31 13:24:15 +01:00
e8d0ffa8b4 travis update 2019-10-31 12:56:59 +01:00
ceb2d99732 Merge pull request #97 from devnexen/llvm_mode_build_silent_warn
Fix some silent warnings and put some var to some usage...
2019-10-31 12:53:47 +01:00
822a3e505a travis update 2019-10-31 12:49:33 +01:00
7b0ab778e3 travis update 2019-10-31 12:46:55 +01:00
744910ad1b travis update 2019-10-31 12:43:51 +01:00
7fdc7e01a5 Fix some silent warnings and put some var to some usage... 2019-10-31 11:41:50 +00:00
c7c622377a travis debug 2019-10-31 12:25:20 +01:00
ae990ce8dc travis updates 2019-10-31 11:38:01 +01:00
7ab2e1d184 travis update 2019-10-31 11:29:22 +01:00
c21b78b297 travis updates 2019-10-31 11:24:47 +01:00
94a7102d3a travis updates 2019-10-31 11:21:41 +01:00
fce7a0c78c update travis 2019-10-31 11:17:18 +01:00
98b27d0c64 travis: added make tests 2019-10-31 11:01:00 +01:00
2d0b90b423 Merge pull request #96 from devnexen/llvm_mode_other_oses_llvm_cfg
LLVM mode passing the full path of the LLVM config bindir.
2019-10-31 10:53:05 +01:00
070ccae4dd Little tweaks 2019-10-31 09:25:43 +00:00
4620d31e2a travis 2019-10-31 10:10:15 +01:00
16953b5cfa LLVM mode passing the full path of the LLVM config bindir.
On FreeBSD the system compiler does not have llvm-config
however system packages provides several version of the
LLVM toolchain thus forcing to pass AFL_CC/AFL_CXX to make
it work fully.
2019-10-30 17:09:01 +00:00
cfccadcdc4 Merge pull request #95 from devnexen/gcc_plugin_tokencap
copying LLVM mode no builtins.
2019-10-29 16:44:35 +01:00
67533cf7c3 copying LLVM mode no builtins. 2019-10-29 15:35:54 +00:00
8a10f3f22f Merge pull request #94 from devnexen/libtokencap_upd
libtokencap update proposal
2019-10-29 16:16:54 +01:00
c87210820c libtokencap update proposal
- bcmp interception.
- FreeBSD using default argument to get current pid for the mapping
data gathering, getpid seems to cause some issues under certain
conditions (getenv call).
2019-10-29 15:06:20 +00:00
66791a5dad more radamsa optimization 2019-10-29 14:22:13 +01:00
ee9b2522a3 Merge pull request #93 from devnexen/few_warnings_fix_proposal_libtokencap
libtokencap, respect constness also considering pointer arithmetic
2019-10-29 12:04:50 +01:00
df5c7eef39 libtokencap, respect constness also considering pointer arithmetic
is non C standard, some compilers might not have GNU extensions.
2019-10-29 10:49:16 +00:00
ccbb0d37b3 removed warning 2019-10-29 10:44:57 +01:00
66f123fb66 Merge pull request #92 from devnexen/alloc_aligned_c11_libdislocator
adding aligned_alloc + little changes proposal for posix_memalign
2019-10-29 10:41:55 +01:00
87b599f4a8 adding aligned_alloc + little changes proposal for posix_memalign 2019-10-29 08:09:43 +00:00
6238df88a2 fixed warning and return 2019-10-28 22:36:29 +01:00
38d74f0ad5 second forgotten place, we need to filter out float vector types 2019-10-28 20:48:45 +01:00
25443918c4 silence some compiler warnings 2019-10-28 16:45:30 +01:00
8035968516 silence some compiler warnings 2019-10-28 16:32:26 +01:00
f9bf0bd90e Merge pull request #90 from devnexen/libtokencap_netbsd_fix
Fix proposal for libtokencap
2019-10-28 16:16:54 +01:00
0df37d0fa1 Merge pull request #91 from devnexen/posix_memalign_prop
memalign/posix_memalign proposal for libdislocator
2019-10-28 15:49:43 +01:00
fbb131da73 memalign/posix_memalign proposal for libdislocator 2019-10-28 14:44:28 +00:00
942f8d0ec9 Fix proposal for libtokencap
Avoiding fopen API seems buggy on NetBSD.
2019-10-28 11:01:37 +00:00
64fa11d204 updated changelog, afl-analyze AFL_SKIP_BIN_CHECK support 2019-10-28 11:52:31 +01:00
3ad5316dd1 fix issue #86, we exclude floating point vectors from splitting 2019-10-27 23:54:44 +01:00
f8e0e9ab1f updated todos 2019-10-27 11:35:40 +01:00
10af76a50c added a TODO item for posix_memalign wrapper 2019-10-27 08:12:01 +01:00
2fafb9f2fb Merge branch 'master' of https://github.com/vanhauser-thc/AFLplusplus 2019-10-27 07:29:07 +01:00
4de38fe40a docs update 2019-10-27 09:04:40 +01:00
74df3e2491 WIP for NetBSD port, iteration has an unknown problem causing a seg fault 2019-10-27 07:27:48 +01:00
8e41a59e2e Merge pull request #87 from devnexen/gcc_llvm_plugins_little_cjg
Little compiler plugins rework regarding block location picked up.
2019-10-26 17:31:01 +02:00
17729ce856 Merge pull request #89 from devnexen/dfbsd_porting
Porting cpu affinity to DragonFly.
2019-10-26 10:45:20 +02:00
cfd7b906cb Porting cpu affinity to DragonFly.
Thanks their API is very similar in this area.
2019-10-26 08:39:13 +01:00
a1f7de2bc3 Merge pull request #88 from domenukk/unicorn_nowarn
No Longer Warns for Absolute Binaries for Unicorn
2019-10-26 09:25:52 +02:00
f2b3f01759 make initial inputs names consistent with others using time:0 2019-10-26 09:24:09 +02:00
3eaf5560be AFL_LLVM_LAF_SPLIT_FLOATS 2019-10-26 09:03:46 +02:00
c66633ccc5 no longer warns on python as path for unicorn 2019-10-26 01:43:25 +02:00
a2f911dbb1 typo 2019-10-26 01:14:39 +02:00
060579b73a Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-10-26 01:12:36 +02:00
09c26fed20 Merge branch 'master' of https://github.com/vanhauser-thc/AFLplusplus 2019-10-26 00:18:56 +02:00
3e9e7e1750 libtokencap ported to OpenBSD 2019-10-26 00:17:51 +02:00
94548d2284 float compcov readme 2019-10-25 20:12:24 +02:00
4ec4e5b394 floating point compcov 2019-10-25 20:04:16 +02:00
15c920a612 Little compiler plugins rework regarding block location picked up. 2019-10-25 14:40:04 +01:00
e7871b2c76 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-10-25 14:02:38 +02:00
644efa2905 remove redundand setenv of SHM_ENV_VAR 2019-10-25 14:02:30 +02:00
7e9b6fe0aa Update sister_projects.txt
status updates for python mutators and whitelist selective instrumentation feature.
2019-10-25 10:44:34 +02:00
b8abf27b86 Update README.md
remove Linux-only :-), list supported OSes
2019-10-25 09:36:17 +02:00
e0ff20dd37 cosmetics 2019-10-25 01:51:53 +02:00
0af42727f5 Merge pull request #84 from devnexen/libtokencap_darwin
Porting libtokencap to Darwin.
2019-10-24 23:32:03 +02:00
b0036759fa portability fix: use cc instead of gcc for test-compcov 2019-10-25 01:22:20 +02:00
b4b26d4207 FreeBSD implementation 2019-10-24 22:26:18 +01:00
cb7ada2e78 fix libtokencap test for Darwin 2019-10-24 22:32:37 +02:00
6e5143681c enhanced radamsa integration 2019-10-24 16:53:30 +02:00
8142422257 Porting libtokencap to Darwin.
Reading only main addresses and read only's.
2019-10-23 20:07:16 +01:00
0f03226656 Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus 2019-10-23 19:48:26 +02:00
297e9e3cf5 move is_valid_addr in afl-qemu-common.h 2019-10-23 19:48:18 +02:00
39b7f48870 performance doc enhancements 2019-10-23 17:01:05 +02:00
b9bc81544a debugged and fixed libdislocator malfunction on MacOSX 2019-10-23 14:53:05 +02:00
7d9eed0ed5 no functional change, avoid conditional jump 2019-10-23 11:33:20 +02:00
1398d8d5a6 gcc sucks 2019-10-23 03:23:14 +02:00
6bc874088f readme update 2019-10-23 02:58:16 +02:00
3ec1baee65 gcc_plugin adaptions Makefile help, man page SYNOPSIS 2019-10-22 20:21:04 +02:00
374f661027 help output adjustment 2019-10-22 13:23:00 +02:00
7ab11c3da9 compile fix 2019-10-22 13:19:08 +02:00
cc2f3afdf8 sync llvm_mode/Makefile to gcc_plugin/Makefile 2019-10-21 23:53:56 +02:00
9a5882a290 sync afl-gcc-rt.o.c from its more current llvm cousin 2019-10-21 23:35:09 +02:00
a033364d55 implement neverZero counter for __afl_trace() 2019-10-21 23:07:05 +02:00
bc3ce26e0e -V/-E not precise 2019-10-21 17:18:41 +02:00
ebea44029e 2.58d 2019-10-21 11:30:28 +02:00
be6bc155eb v2.58c 2019-10-21 11:28:32 +02:00
d0bbef74ef loading dynamical libraries on Darwin/MacOSX is done with DYLD_INSERT_LIBRARIES 2019-10-20 02:35:06 +02:00
a282ae22af In OpenBSD initial thread local storage is allocated with calloc(),
which leads to locked mutexes and a stall. So no thread support
(and no tls) here.
2019-10-20 03:34:46 +02:00
c83e8e1e62 Remove lcamtuf's old email from Google (not valid anymore), also remove maintainance from him. 2019-10-19 18:23:01 +02:00
452ec28761 Merge pull request #82 from devnexen/darwin_gotcpu_portage
afl-gotcpu: porting to Darwin using mach API.
Thanks! Looks good!
2019-10-19 17:37:40 +02:00
8a78637719 add gcc_plugin to code formatter and run it 2019-10-19 16:19:46 +02:00
1fdb75068d afl-gotcpu: porting to Darwin using mach API. 2019-10-19 11:44:09 +01:00
230c135d4e typo in names 2019-10-18 22:43:30 +02:00
bf544af690 new entries for gcc_plugin 2019-10-18 21:21:17 +02:00
e7ab8be0cd sync afl-fast-gcc with afl-clang-fast, add tests for gcc_plugin 2019-10-18 19:53:10 +02:00
b1822f2602 reintegrate gcc_plugin 2019-10-18 18:01:33 +02:00
f4a74a3405 added test/test-performance.sh 2019-10-18 10:10:47 +02:00
73da639654 revert patch 2019-10-18 08:25:43 +02:00
f2a1456e94 needed increased unicorn test time 2019-10-17 11:31:12 +02:00
c75abda571 return instead of exit in test-instr 2019-10-17 09:30:50 +02:00
1aec670c43 add forgotten floating point comparisons in laf-intel/llvm_mode 2019-10-16 20:37:58 +02:00
77695d75bb test.sh check to see if qemu persistent mode is faster 2019-10-15 17:14:59 +02:00
3dec452a8a v2.57d 2019-10-15 16:50:48 +02:00
4183bc35b2 doh 2019-10-10 19:50:16 +02:00
4700800770 upload libradamsa 2019-10-10 19:49:38 +02:00
9de74cce92 radamsa mutator as havoc cycle replacement with probability 1/24 2019-10-10 19:46:46 +02:00
144 changed files with 37622 additions and 765 deletions

View File

@ -27,12 +27,15 @@ with open(".clang-format") as f:
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
if CLANG_FORMAT_BIN is None:
p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
o, _ = p.communicate()
o = str(o, "utf-8")
o = o[len("clang-format version "):].strip()
o = o[:o.find(".")]
o = int(o)
o = 0
try:
p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
o, _ = p.communicate()
o = str(o, "utf-8")
o = o[len("clang-format version "):].strip()
o = o[:o.find(".")]
o = int(o)
except: pass
if o < 7:
if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
CLANG_FORMAT_BIN = 'clang-format-7'

6
.gitignore vendored
View File

@ -23,6 +23,8 @@ afl-clang-fast.8
afl-cmin.8
afl-fuzz.8
afl-gcc.8
afl-gcc-fast.8
afl-g++-fast.8
afl-gotcpu.8
afl-plot.8
afl-showmap.8
@ -32,6 +34,4 @@ afl-whatsup.8
qemu_mode/libcompcov/compcovtest
as
qemu_mode/qemu-*
unicorn_mode/unicorn
unicorn_mode/unicorn-*
unicorn_mode/*.tar.gz
core\.*

View File

@ -1,11 +1,49 @@
language: c
branches:
only:
- master
matrix:
include:
- 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
dist: trusty
env: NAME="trusty-amd64" MODERN="no" GCC="4.8"
- os: linux
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
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_STOP_MANUALLY=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 libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev ; fi
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev ; fi
script:
- make
- ./afl-gcc ./test-instr.c -o test-instr
- mkdir seeds; mkdir out
- echo "" > seeds/nil_seed
- timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-instr
- gcc -v
- clang -v
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ; fi
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then make ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
- make tests

140
Android.bp Normal file
View File

@ -0,0 +1,140 @@
cc_defaults {
name: "afl-defaults",
cflags: [
"-funroll-loops",
"-Wno-pointer-sign",
"-Wno-pointer-arith",
"-Wno-sign-compare",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-Wno-format",
"-Wno-user-defined-warnings",
"-DUSE_TRACE_PC=1",
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
"-D__USE_GNU",
],
}
cc_binary {
name: "afl-fuzz",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-fuzz.c",
],
}
cc_binary {
name: "afl-showmap",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-showmap.c",
],
}
cc_binary {
name: "afl-tmin",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-tmin.c",
],
}
cc_binary {
name: "afl-analyze",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-analyze.c",
],
}
cc_binary {
name: "afl-gotcpu",
static_executable: true,
host_supported: true,
defaults: [
"afl-defaults",
],
srcs: [
"afl-gotcpu.c",
],
}
cc_binary_host {
name: "afl-clang-fast",
static_executable: true,
defaults: [
"afl-defaults",
],
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
],
srcs: [
"llvm_mode/afl-clang-fast.c",
],
}
cc_binary_host {
name: "afl-clang-fast++",
static_executable: true,
defaults: [
"afl-defaults",
],
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
],
srcs: [
"llvm_mode/afl-clang-fast.c",
],
}
cc_library_static {
name: "afl-llvm-rt",
compile_multilib: "both",
vendor_available: true,
host_supported: true,
recovery_available: true,
defaults: [
"afl-defaults",
],
srcs: [
"llvm_mode/afl-llvm-rt.o.c",
],
}

View File

@ -6,9 +6,14 @@ Each modified source file, before merging, must be formatted.
make code-formatter
```
This should be fine if you modified one of the file already present in the
This should be fine if you modified one of the files already present in the
project, otherwise run:
```
./.custom-format.py -i file-that-you-have-created.c
```
Regarding the coding style, please follow the AFL style.
No camel case at all and use the AFL's macros when possible (e.g. WARNF, FATAL, ...).
Remember that AFLplusplus has to build and run on many platforms, so generalize your Makefiles (or your patches to our pre-existing Makefiles) to be as much general as possible.

32
Dockerfile Normal file
View File

@ -0,0 +1,32 @@
FROM ubuntu:eoan
MAINTAINER David Carlier <devnexen@gmail.com>
LABEL "about"="AFLplusplus docker image"
RUN apt-get update && apt-get install -y \
--no-install-suggests --no-install-recommends \
automake \
bison \
build-essential \
clang \
clang-9 \
flex \
gcc-9 \
gcc-9-plugin-dev \
gcc-9-multilib \
libc++-9-dev \
libtool \
libtool-bin \
libglib2.0-dev \
llvm-9-dev \
python-setuptools \
python2.7-dev \
wget \
ca-certificates \
libpixman-1-dev \
&& rm -rf /var/lib/apt/lists/*
ARG CC=gcc-9
ARG CXX=g++-9
ARG LLVM_CONFIG=llvm-config-9
COPY . /app
RUN cd /app && make clean && make distrib && \
make install && cd .. && rm -rf /app
WORKDIR /work

133
Makefile
View File

@ -2,7 +2,7 @@
# american fuzzy lop - makefile
# -----------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
#
@ -16,9 +16,6 @@
# For Heiko:
#TEST_MMAP=1
PROGNAME = afl
VERSION = $(shell grep '^\#define VERSION ' include/config.h | cut -d '"' -f2)
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
@ -26,6 +23,9 @@ DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/man/man8
PROGNAME = afl
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
# PROGS intentionally omit afl-as, which gets installed elsewhere.
PROGS = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
@ -34,12 +34,54 @@ MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8)
CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -Wno-unused-function
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
PYTHON_INCLUDE ?= /usr/include/python2.7
ifneq "($filter %3.7m, $(shell python3.7m-config --includes 2>/dev/null)" ""
PYTHON_INCLUDE ?= $(shell python3.7m-config --includes)
PYTHON_LIB ?= $(shell python3.7m-config --ldflags)
PYTHON_VERSION = 3.7m
else
ifneq "($filter %3.7, $(shell python3.7-config --includes) 2> /dev/null" ""
PYTHON_INCLUDE ?= $(shell python3.7-config --includes)
PYTHON_LIB ?= $(shell python3.7-config --ldflags)
PYTHON_VERSION = 3.7
else
ifneq "($filter %2.7, $(shell python2.7-config --includes) 2> /dev/null" ""
PYTHON_INCLUDE ?= $(shell python2.7-config --includes)
PYTHON_LIB ?= $(shell python2.7-config --ldflags)
PYTHON_VERSION = 2.7
endif
endif
endif
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7m && echo /usr/include/python3.7m)
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7 && echo /usr/include/python3.7)
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python2.7 && echo /usr/include/python2.7)
ifneq "($filter %3.7m, $(PYTHON_INCLUDE))" ""
PYTHON_VERSION ?= 3.7m
PYTHON_LIB ?= -lpython3.7m
else
ifneq "($filter %3.7, $(PYTHON_INCLUDE))" ""
PYTHON_VERSION ?= 3.7
else
ifneq "($filter %2.7, $(PYTHON_INCLUDE))" ""
PYTHON_VERSION ?= 2.7
PYTHON_LIB ?= -lpython2.7
else
PYTHON_VERSION ?= none
endif
endif
endif
ifdef SOURCE_DATE_EPOCH
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -I)
else
BUILD_DATE ?= $(shell date -I)
endif
ifneq "$(filter Linux GNU%,$(shell uname))" ""
LDFLAGS += -ldl
@ -62,9 +104,9 @@ endif
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) -lpython2.7 2>/dev/null && echo 1 || echo 0 )" "1"
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
PYTHON_OK=1
PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) -lpython2.7
PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB)
else
PYTHON_OK=0
PYFLAGS=
@ -80,7 +122,7 @@ ifdef STATIC
LDFLAGS += -lm -lrt -lpthread -lz -lutil
endif
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
SHMAT_OK=1
else
SHMAT_OK=0
@ -99,20 +141,30 @@ all: test_x86 test_shm test_python27 ready $(PROGS) afl-as test_build all_done
man: $(MANPAGES)
-$(MAKE) -C llvm_mode
-$(MAKE) -C gcc_plugin
tests: source-only
@cd test ; ./test.sh
@rm -f test/errors
performance-tests: performance-test
test-performance: performance-test
performance-test: source-only
@cd test ; ./test-performance.sh
help:
@echo "HELP --- the following make targets exist:"
@echo "=========================================="
@echo "all: just the main afl++ binaries"
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap"
@echo "source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap"
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
@echo "distrib: everything (for both binary-only and source code fuzzing)"
@echo "man: creates simple man pages from the help option of the programs"
@echo "install: installs everything you have compiled with the build option above"
@echo "clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well"
@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
@echo "code-format: format the code, do this before you commit and send a PR please!"
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
@echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
@echo "help: shows these build options :-)"
@ -123,6 +175,8 @@ help:
ifndef AFL_NO_X86
test_x86:
@echo "[*] Checking for the default compiler cc..."
@which $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
@echo "[*] Checking for the ability to compile x86 code..."
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
@rm -f .test1
@ -153,12 +207,12 @@ ifeq "$(PYTHON_OK)" "1"
test_python27:
@rm -f .test 2> /dev/null
@echo "[+] Python 2.7 support seems to be working."
@echo "[+] Python $(PYTHON_VERSION) support seems to be working."
else
test_python27:
@echo "[-] You seem to need to install the package python2.7-dev, but it is optional so we continue"
@echo "[-] You seem to need to install the package python3.7-dev or python2.7-dev (and perhaps python[23]-apt), but it is optional so we continue"
endif
@ -183,6 +237,12 @@ src/afl-forkserver.o : src/afl-forkserver.c include/forkserver.h
src/afl-sharedmem.o : src/afl-sharedmem.c include/sharedmem.h
$(CC) $(CFLAGS) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
radamsa: src/third_party/libradamsa/libradamsa.so
cp src/third_party/libradamsa/libradamsa.so .
src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
$(MAKE) -C src/third_party/libradamsa/
afl-fuzz: include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
@ -212,11 +272,17 @@ code-format:
./.custom-format.py -i llvm_mode/*.c
./.custom-format.py -i llvm_mode/*.h
./.custom-format.py -i llvm_mode/*.cc
./.custom-format.py -i gcc_plugin/*.c
#./.custom-format.py -i gcc_plugin/*.h
./.custom-format.py -i gcc_plugin/*.cc
./.custom-format.py -i experimental/*/*.c
./.custom-format.py -i experimental/*/*.h
./.custom-format.py -i qemu_mode/patches/*.h
./.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 unicorn_mode/patches/*.h
./.custom-format.py -i qbdi_mode/*.c
./.custom-format.py -i qbdi_mode/*.cpp
./.custom-format.py -i *.h
./.custom-format.py -i *.c
@ -225,7 +291,7 @@ ifndef AFL_NO_X86
test_build: afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS)
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@ -249,34 +315,45 @@ all_done: test_build
.NOTPARALLEL: clean
clean:
rm -f $(PROGS) afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast *.so unicorn_mode/24f55a7973278f20f0de21b904851d99d4716263.tar.gz *.8
rm -rf out_dir qemu_mode/qemu-3.1.1 unicorn_mode/unicorn *.dSYM */*.dSYM
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast *.so *.8
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
-$(MAKE) -C llvm_mode clean
-$(MAKE) -C gcc_plugin clean
$(MAKE) -C libdislocator clean
$(MAKE) -C libtokencap clean
$(MAKE) -C experimental/socket_fuzzing clean
$(MAKE) -C experimental/argv_fuzzing clean
$(MAKE) -C qemu_mode/unsigaction clean
$(MAKE) -C qemu_mode/libcompcov clean
$(MAKE) -C src/third_party/libradamsa/ clean
-rm -rf unicorn_mode/unicorn
distrib: all
distrib: all radamsa
-$(MAKE) -C llvm_mode
-$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
$(MAKE) -C experimental/socket_fuzzing
$(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_support.sh
binary-only: all
binary-only: all radamsa
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
$(MAKE) -C experimental/socket_fuzzing
$(MAKE) -C experimental/argv_fuzzing
cd qemu_mode && sh ./build_qemu_support.sh
cd unicorn_mode && sh ./build_unicorn_support.sh
source-only: all
source-only: all radamsa
-$(MAKE) -C llvm_mode
-$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
%.8: %
@echo .TH $* 8 `date -I` "afl++" > $@
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@echo .SH NAME >> $@
@echo .B $* >> $@
@echo >> $@
@ -288,19 +365,19 @@ source-only: all
@./$* -h 2>&1 | tail -n +4 >> $@
@echo >> $@
@echo .SH AUTHOR >> $@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexc0der\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> $@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> $@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> $@
@echo >> $@
@echo .SH LICENSE >> $@
@echo Apache License Version 2.0, January 2004 >> $@
install: all $(MANPAGES)
mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
#if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
ifndef AFL_TRACE_PC
if [ -f afl-clang-fast -a -f libLLVMInsTrim.so -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 libLLVMInsTrim.so afl-llvm-pass.so afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
else
@ -314,6 +391,10 @@ endif
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 libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
$(MAKE) -C experimental/socket_fuzzing install
$(MAKE) -C experimental/argv_fuzzing install
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi

View File

@ -1,8 +1,10 @@
# american fuzzy lop plus plus (afl++)
Release Version: 2.57c
![Travis State](https://api.travis-ci.com/vanhauser-thc/AFLplusplus.svg?branch=master)
Github Version: 2.57d
Release Version: 2.59c
Github Version: 2.59d
includes all necessary/interesting changes from Google's afl 2.56b
@ -25,10 +27,10 @@
get any feature improvements since November 2017.
Among other changes afl++ has a more performant llvm_mode, supports
llvm up to version 9, QEMU 3.1, more speed and crashfixes for QEMU,
llvm up to version 10, QEMU 3.1, more speed and crashfixes for QEMU,
better *BSD and Android support and much, much more.
Additionally the following patches have been integrated:
Additionally the following features and patches have been integrated:
* AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
@ -50,18 +52,26 @@
* Win32 PE binary-only fuzzing with QEMU and Wine
* Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly).
* qbdi_mode: fuzz android native libraries via QBDI framework
A more thorough list is available in the PATCHES file.
| Feature/Instrumentation | LLVM | GCC | QEMU | Unicorn |
| ----------------------- |:----:|:---:|:----:| -------:|
| laf-intel / CompCov | x | | x | x |
| NeverZero | x(1)| x | x | x |
| Persistent mode | x | | x | |
| Whitelist | x | | | |
| InsTrim | x | | | |
| Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode |
| ----------------------- |:-------:|:---------:|:----------:|:---------:|:------------:|
| laf-intel / CompCov | | x | | x86/arm | x86/arm |
| NeverZero | x | x(1) | (2) | x | x |
| Persistent mode | | x | x | x86 | x |
| Whitelist | | x | x | | |
| InsTrim | | x | | | |
neverZero:
(1) only in LLVM >= 9.0 due to a bug in llvm in previous versions
(2) gcc create non-performant code, hence it is disabled in gcc_plugin
So all in all this is the best-of AFL that is currently out there :-)
@ -98,11 +108,12 @@ is what you should choose.
These build options exist:
* all: just the main afl++ binaries
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap, radamsa
* distrib: everything (for both binary-only and source code fuzzing)
* install: installs everything you have compiled with the build options above
* clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well
* code-format: format the code, do this before you commit and send a PR please!
* tests: runs test cases to ensure that all features are still working as they should
* help: shows these build options
@ -113,6 +124,14 @@ afl++ binaries by passing the STATIC=1 argument to make:
$ make all STATIC=1
```
Note that afl++ is faster and better the newer the compilers used are.
Hence gcc-9 and especially llvm-9 should be the compilers of choice.
If your distribution does not have them, you can use the Dockerfile:
```shell
$ docker build -t aflplusplus
```
## 1) Challenges of guided fuzzing
@ -185,7 +204,7 @@ superior to blind fuzzing or coverage-only tools.
PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++
instead of afl-gcc/afl-g++ is much faster and has a few cool features.
See llvm_mode/ - however few code does not compile with llvm.
We support llvm versions 3.8.0 to 9.
We support llvm versions 3.8.0 to 10.
When source code is available, instrumentation can be injected by a companion
tool that works as a drop-in replacement for gcc or clang in any standard build
@ -208,7 +227,7 @@ For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`.
The clang wrappers (afl-clang and afl-clang++) can be used in the same way;
clang users may also opt to leverage a higher-performance instrumentation mode,
as described in [llvm_mode/README.md](llvm_mode/README.md).
Clang/LLVM has a much better performance and works with LLVM version 3.8.0 to 9.
Clang/LLVM has a much better performance and works with LLVM version 3.8.0 to 10.
Using the LAF Intel performance enhancements are also recommended, see
[llvm_mode/README.laf-intel.md](llvm_mode/README.laf-intel.md)
@ -455,7 +474,7 @@ parsers and grammars, but isn't nearly as good as the -x mode.
If a dictionary is really hard to come by, another option is to let AFL run
for a while, and then use the token capture library that comes as a companion
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.md).
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
## 11) Crash triage

10
TODO
View File

@ -3,15 +3,13 @@ Roadmap 2.60:
=============
afl-fuzz:
- radamsa mutator
- test the libmutator actually works and does not run infinite (need an example though)
- radamsa mutator (via dlopen())
gcc_plugin:
- needs to be rewritten
- whitelist support
- skip over uninteresting blocks
- laf-intel
- neverZero
libdislocator:
- add a wrapper for posix_memalign
qemu_mode:
- update to 4.x (probably this will be skipped :( )

View File

@ -3,7 +3,7 @@
# american fuzzy lop - corpus minimization tool
# ---------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2014, 2015 Google Inc. All rights reserved.
#
@ -36,7 +36,7 @@
# array sizes.
#
echo "corpus minimization tool for afl-fuzz by <lcamtuf@google.com>"
echo "corpus minimization tool for afl-fuzz by Michal Zalewski"
echo
#########

View File

@ -3,7 +3,7 @@
# american fuzzy lop - Advanced Persistent Graphing
# -------------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
# Based on a design & prototype by Michael Rash.
#
# Copyright 2014, 2015 Google Inc. All rights reserved.
@ -15,7 +15,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
echo "progress plotting utility for afl-fuzz by <lcamtuf@google.com>"
echo "progress plotting utility for afl-fuzz by Michal Zalewski"
echo
if [ ! "$#" = "2" ]; then

View File

@ -3,7 +3,7 @@
# american fuzzy lop - status check tool
# --------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2015 Google Inc. All rights reserved.
#
@ -17,7 +17,7 @@
# instances of afl-fuzz.
#
echo "status check tool for afl-fuzz by <lcamtuf@google.com>"
echo "status check tool for afl-fuzz by Michal Zalewski"
echo
test "$1" = "-h" && {
echo $0
@ -61,7 +61,7 @@ fi
CUR_TIME=`date +%s`
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
ALIVE_CNT=0
DEAD_CNT=0

View File

@ -4,9 +4,10 @@ import os
import sys
import pefile
import shutil
import subprocess
if len(sys.argv) < 2:
print("[afl-wine-trace] usage: wine-cov binary [args...]\n")
print("[afl-wine-trace] usage: ./afl-wine-trace binary [args...]\n")
exit(1)
if os.getenv("AFL_PATH"):
@ -42,14 +43,20 @@ else:
elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]:
qemu_path += "i386"
else:
print ("[wine-cov] unsuppoted architecture\n")
print ("[afl-wine-trace] unsuppoted architecture\n")
exit(1)
qemu_path = shutil.which(qemu_path)
if os.getenv("WINECOV_WINE_PATH"):
wine_path = os.getenv("WINECOV_WINE_PATH")
wine_path = None
if os.getenv("AFL_WINE_PATH"):
wine_path = os.getenv("AFL_WINE_PATH")
else:
wine_path = "/usr/lib/wine/wine"
if not wine_path and shutil.which("wine"):
wine_path = shutil.which("wine")
if not wine_path and os.path.exists("/usr/bin/wine"):
wine_path = "/usr/bin/wine"
if not wine_path and os.path.exists("/usr/lib/wine/wine"):
wine_path = "/usr/lib/wine/wine"
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]:
wine_path += "64"
elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]:
@ -58,4 +65,11 @@ else:
print ("[afl-wine-trace] unsopported architecture\n")
exit(1)
os.execve(qemu_path, [qemu_path, wine_path] + sys.argv[1:], os.environ)
argv = sys.argv[1:]
for i in range(len(argv)):
if ".cur_input" in argv[i]:
argv[i] = subprocess.run([os.path.join(os.path.dirname(wine_path), "winepath"), "--windows", argv[i]], universal_newlines=True, stdout=subprocess.PIPE).stdout
break
print("[afl-wine-trace] exec:", " ".join([qemu_path, wine_path] + argv))
os.execve(qemu_path, [qemu_path, wine_path] + argv, os.environ)

View File

@ -2,7 +2,7 @@
# AFL dictionary for GIF images
# -----------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_87a="87a"

View File

@ -5,7 +5,7 @@
# A basic collection of HTML tags likely to matter to HTML parsers. Does *not*
# include any attributes or attribute values.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
tag_a="<a>"

View File

@ -2,7 +2,7 @@
# AFL dictionary for JPEG images
# ------------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_jfif="JFIF\x00"

View File

@ -4,7 +4,7 @@
#
# Contains basic reserved keywords and syntax building blocks.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
keyword_arguments="arguments"

View File

@ -5,7 +5,7 @@
# Just the basic, standard-originating sections; does not include vendor
# extensions.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_png="\x89PNG\x0d\x0a\x1a\x0a"

596
dictionaries/regexp.dict Normal file
View File

@ -0,0 +1,596 @@
#
# AFL dictionary for regex
# --------------------------
#
# Contains various regular expressions.
#
# Created by Yang Guo <yangguo@chromium.org>
#
# Contributed by Dhiraj Mishra <dhiraj@inputzero.io>
#
"?"
"abc"
"()"
"[]"
"abc|def"
"abc|def|ghi"
"^xxx$"
"ab\\b\\d\\bcd"
"\\w|\\d"
"a*?"
"abc+"
"abc+?"
"xyz?"
"xyz??"
"xyz{0,1}"
"xyz{0,1}?"
"xyz{93}"
"xyz{1,32}"
"xyz{1,32}?"
"xyz{1,}"
"xyz{1,}?"
"a\\fb\\nc\\rd\\te\\vf"
"a\\nb\\bc"
"(?:foo)"
"(?: foo )"
"foo|(bar|baz)|quux"
"foo(?=bar)baz"
"foo(?!bar)baz"
"foo(?<=bar)baz"
"foo(?<!bar)baz"
"()"
"(?=)"
"[]"
"[x]"
"[xyz]"
"[a-zA-Z0-9]"
"[-123]"
"[^123]"
"]"
"}"
"[a-b-c]"
"[x\\dz]"
"[\\d-z]"
"[\\d-\\d]"
"[z-\\d]"
"\\cj\\cJ\\ci\\cI\\ck\\cK"
"\\c!"
"\\c_"
"\\c~"
"[\\c!]"
"[\\c_]"
"[\\c~]"
"[\\ca]"
"[\\cz]"
"[\\cA]"
"[\\cZ]"
"[\\c1]"
"\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ "
"[\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ]"
"\\8"
"\\9"
"\\11"
"\\11a"
"\\011"
"\\118"
"\\111"
"\\1111"
"(x)(x)(x)\\1"
"(x)(x)(x)\\2"
"(x)(x)(x)\\3"
"(x)(x)(x)\\4"
"(x)(x)(x)\\1*"
"(x)(x)(x)\\3*"
"(x)(x)(x)\\4*"
"(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\10"
"(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\11"
"(a)\\1"
"(a\\1)"
"(\\1a)"
"(\\2)(\\1)"
"(?=a){0,10}a"
"(?=a){1,10}a"
"(?=a){9,10}a"
"(?!a)?a"
"\\1(a)"
"(?!(a))\\1"
"(?!\\1(a\\1)\\1)\\1"
"\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1"
"[\\0]"
"[\\11]"
"[\\11a]"
"[\\011]"
"[\\00011]"
"[\\118]"
"[\\111]"
"[\\1111]"
"\\x60"
"\\x3z"
"\\c"
"\\u0034"
"\\u003z"
"foo[z]*"
"\\u{12345}"
"\\u{12345}\\u{23456}"
"\\u{12345}{3}"
"\\u{12345}*"
"\\ud808\\udf45*"
"[\\ud808\\udf45-\\ud809\\udccc]"
"a"
"a|b"
"a\\n"
"a$"
"a\\b!"
"a\\Bb"
"a*?"
"a?"
"a??"
"a{0,1}?"
"a{1,2}?"
"a+?"
"(a)"
"(a)\\1"
"(\\1a)"
"\\1(a)"
"a\\s"
"a\\S"
"a\\D"
"a\\w"
"a\\W"
"a."
"a\\q"
"a[a]"
"a[^a]"
"a[a-z]"
"a(?:b)"
"a(?=b)"
"a(?!b)"
"\\x60"
"\\u0060"
"\\cA"
"\\q"
"\\1112"
"(a)\\1"
"(?!a)?a\\1"
"(?:(?=a))a\\1"
"a{}"
"a{,}"
"a{"
"a{z}"
"a{12z}"
"a{12,"
"a{12,3b"
"{}"
"{,}"
"{"
"{z}"
"{1z}"
"{12,"
"{12,3b"
"a"
"abc"
"a[bc]d"
"a|bc"
"ab|c"
"a||bc"
"(?:ab)"
"(?:ab|cde)"
"(?:ab)|cde"
"(ab)"
"(ab|cde)"
"(ab)\\1"
"(ab|cde)\\1"
"(?:ab)?"
"(?:ab)+"
"a?"
"a+"
"a??"
"a*?"
"a+?"
"(?:a?)?"
"(?:a+)?"
"(?:a?)+"
"(?:a*)+"
"(?:a+)+"
"(?:a?)*"
"(?:a*)*"
"(?:a+)*"
"a{0}"
"(?:a+){0,0}"
"a*b"
"a+b"
"a*b|c"
"a+b|c"
"(?:a{5,1000000}){3,1000000}"
"(?:ab){4,7}"
"a\\bc"
"a\\sc"
"a\\Sc"
"a(?=b)c"
"a(?=bbb|bb)c"
"a(?!bbb|bb)c"
"\xe2\x81\xa3"
"[\xe2\x81\xa3]"
"\xed\xb0\x80"
"\xed\xa0\x80"
"(\xed\xb0\x80)\x01"
"((\xed\xa0\x80))\x02"
"\xf0\x9f\x92\xa9"
"\x01"
"\x0f"
"[-\xf0\x9f\x92\xa9]+"
"[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\xbf]"
"(?<=)"
"(?<=a)"
"(?<!)"
"(?<!a)"
"(?<a>)"
"(?<a>.)"
"(?<a>.)\\k<a>"
"\\p{Script=Greek}"
"\\P{sc=Greek}"
"\\p{Script_Extensions=Greek}"
"\\P{scx=Greek}"
"\\p{General_Category=Decimal_Number}"
"\\P{gc=Decimal_Number}"
"\\p{gc=Nd}"
"\\P{Decimal_Number}"
"\\p{Nd}"
"\\P{Any}"
"\\p{Changes_When_NFKC_Casefolded}"
"L~"
"P{scx=Greek}??"
"Q~"
"R??"
"R!??oo(E=?ar)baz-"
"Sc?Sc{?{?"
"U~"
"V~"
"W~"
"Xdtc"
"X~"
"X?"
"[-123],}"
"[-????]+,}"
"[00011],}"
"[011],}"
"[0],}"
"[1111],}"
"[111],}"
"[118],}"
"[11],}"
"[11a],}"
"[[]{}()%^# ],}"
"[]"
"[],}"
"[]{}()%^# ,}"
"[^123],}"
"[a-b-c],}"
"[a-zA-Z0-9],}"
"[b"
"[bfoo(?!bar)baz"
"[c!],}"
"[c1],}"
"[cA],}"
"[cZ],}"
"[c_],}"
"[ca],}"
"[cz],}"
"[c~],}"
"[c~]w"
"[d-d],}"
"[d-z],}"
"[u???[11<([c?]?:u??<a>)dccc]"
"[ud808udf45-ud809udccc],}"
"[x"
"[x],}"
"[xdz],}"
"[xyz],}"
"[x?"
"[x?n4n4"
"[x??19?"
"[z-d],}"
"[~?"
"[?????"
"[?"
"[???],}"
"[????-????],}"
"[????"
"]"
"],}"
"]QrC[w~]Qr"
"]}"
"]~"
"^?000???????????????????????????x60?"
"^12(a(?:1(b12))2)1dyb?9"
"^xi!q"
"^xxx$,}"
"abc"
"abc60,0}?{?"
"aic"
"b~"
"c"
"c!,}"
"c,}"
"cA,}"
"c_,}"
"cjcJcicIckcK,}"
"c~"
"c~,}"
"d"
"d?"
"d??"
"d(?:ab[]?9}"
"dpN?(?<a>.)?"
"duu{123a?"
"d{1,9"
"d~"
"e"
"e~"
"e?}"
"f~"
"g~"
"h~"
"i~"
"j~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xx?~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxb~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxc~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxd~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxe~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxf~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxg~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxh~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxi~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxj~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxk~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxl~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxm~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxn~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxo~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxp~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxr~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxs~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxt~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxu~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxv~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxw~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxx~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxy~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxz~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xx?~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxn~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxo~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxp~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxq~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxr~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxs~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxt~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxu~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxv~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxw~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxx~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxy~"
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxz~"
"k?@a(?=bbb.~"
"k?@a(?=bbbb~"
"k?@a(?=bbbc~"
"k?@a(?=bbbd~"
"k?@a(?=bbbe~"
"k?@a(?=bbbf~"
"k?@a(?=bbbg~"
"k?@a(?=bbbh~"
"k?@a(?=bbbi~"
"k?@a(?=bbbj~"
"k?@a(?=bbbk~"
"k?@a(?=bbbl~"
"k?@a(?=bbbm~"
"k?@a(?=bbbn~"
"k?@a(?=bbbo~"
"k?@a(?=bbbp~"
"k?@a(?=bbbq~"
"k?@a(?=bbbr~"
"k?@a(?=bbbs~"
"k?@a(?=bbbt~"
"k?@a(?=bbbu~"
"k?@a(?=bbbv~"
"k?@a(?=bbbw~"
"k?@a(?=bbbx~"
"k?@a(?=bbby~"
"k?@a(?=bbbz~"
"k?@a(?=by?bC?:!k??????????????b~"
"k?@a(?=by?bC?:!k??????????????c~"
"k?@a(?=by?bC?:!k??????????????d~"
"k?@a(?=by?bC?:!k??????????????e~"
"k?@a(?=by?bC?:!k??????????????f~"
"k?@a(?=by?bC?:!k??????????????g~"
"k?@a(?=by?bC?:!k??????????????h~"
"k?@a(?=by?bC?:!k??????????????i~"
"k?@a(?=by?bC?:!k??????????????j~"
"k?@a(?=by?bC?:!k??????????????k~"
"k?@a(?=by?bC?:!k??????????????l~"
"k?@a(?=by?bC?:!k??????????????m~"
"k?@a(?=by?bC?:!k??????????????n~"
"k?@a(?=by?bC?:!k??????????????o~"
"k?@a(?=by?bC?:!k??????????????p~"
"k?@a(?=by?bC?:!k??????????????q~"
"k?@a(?=by?bC?:!k??????????????r~"
"k?@a(?=by?bC?:!k??????????????s~"
"k?@a(?=by?bC?:!k??????????????t~"
"k?@a(?=by?bC?:!k??????????????u~"
"k?@a(?=by?bC?:!k??????????????v~"
"k?@a(?=by?bC?:!k??????????????w~"
"k?@a(?=by?bC?:!k??????????????x~"
"k?@a(?=by?bC?:!k??????????????y~"
"k?@a(?=by?bC?:!k??????????????z~"
"k?@a(?=by?bC?:!k???????????????~"
"k?@a(?~"
"k?@a(b~"
"k?@a(c~"
"k?@a(d~"
"k?@a(e~"
"k?@a(f~"
"k?@a(g~"
"k?@a(h~"
"k?@a(i~"
"k?@a(j~"
"k?@a(k~"
"k?@a(l~"
"k?@a(m~"
"k?@a(n~"
"k?@a(o~"
"k?@a(p~"
"k?@a(q~"
"k?@a(r~"
"k?@a(s~"
"k?@a(t~"
"k?@a(u~"
"k?@a(v~"
"k?@a(w~"
"k?@a(x~"
"k?@a(y~"
"k?@a(z~"
"k0X@ab~"
"k0X@ac~"
"k0X@ad~"
"k0X@ae~"
"k0X@af~"
"k0X@ag~"
"k0X@ah~"
"k0X@ai~"
"k0X@aj~"
"k0X@ak~"
"k0X@al~"
"k0X@am~"
"k0X@an~"
"k0X@ao~"
"k0X@ap~"
"k0X@aq~"
"k0X@ar~"
"k0X@as~"
"k0X@at~"
"k0X@au~"
"k0X@av~"
"k0X@aw~"
"k0X@ax~"
"k0X@ay~"
"k0X@az~"
"k0X@a?~"
"k~"
"l~"
"m~"
"n~"
"o~"
"p~"
"q,}"
"q~"
"r~"
"r?[c~]"
"s~"
"t~"
"u0034,}"
"u003z,}"
"u0060,}"
"ud808udf45*,}"
"u~"
"v~"
"w"
"w~"
"x3z,}"
"x60,}"
"xyz?9"
"x~"
"y~"
"z~"
"{"
"{??"
"{ ,,?"
"{-"
"{0,d?????!"
"{12345}pu{234:P}?"
"{1?5"
"{@"
"{M,??"
"{M,P{scx=Greek}???sn"
"{M,??"
"{M,??"
"{M,?M,??"
"{O"
"{r~"
"{s~"
"{t~"
"{u~"
"{v~"
"{w~"
"{x~"
"{y~"
"{z~"
"{}"
"{}~"
"{??@"
"{?~"
"},}"
"}}"
"}}}}}?}!}}}}}}}}}}}}}}}}}?},}"
"}~"
"}?w~???"
"~~"
"?!~"
"?$"
"?*?9?nnRnnn?"
"?.~"
"?123222222??"
"?:??"
"?R"
"?b~"
"?c~"
"?d~"
"?d???"
"?e~"
"?f~"
"?g~"
"?h~"
"?i~"
"?j~"
"?k~"
"?l~"
"?m~"
"?n~"
"?o~"
"?p~"
"?q~"
"?r~"
"?s~"
"?t~"
"?u~"
"?v~"
"?v~?v"
"?w~"
"?x~"
"?y~"
"?z~"
"?}"
"??~"
"?????????dadi(?!bbb"
"??~"
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~>>>>>>>>>>>>>>>>>>"
"?f??123222222??"
"?fP{gc=Decimal_Number}"
"?f2jq?oo@ooooh??"
"?[???],}f?"
"?[???],}nbbc2jocom"
"?[]"
"?[],}?"
"?[],}f?"
"?[]f?"
"?[]{}()%^#"
"?[^123],}f?"
"?[^123]nbbc2jocom"
"?[a-b-c],}f?"
"?[a-b-c]nbbc2jocom"
"?[a-zA-Z0-9],}f?"
"?[a-zA-Z0-9],}jocom"
"?[a-zA-Z0-9]c2jocom"
"?[bfoo(?!bar)bazcom"
"?[bfoo(?!bar)bazf?"

View File

@ -11,7 +11,7 @@
# standpoint, because they are usually not allowed in non-privileged
# contexts).
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
function_abs=" abs(1)"

View File

@ -5,7 +5,7 @@
# Just the basic, standard-originating sections; does not include vendor
# extensions.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_ii="II*\x00"

View File

@ -2,7 +2,7 @@
# AFL dictionary for WebP images
# ------------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_RIFF="RIFF"

View File

@ -4,7 +4,7 @@
#
# Several basic syntax elements and attributes, modeled on libxml2.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
attr_encoding=" encoding=\"1\""

View File

@ -13,6 +13,66 @@ 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 ++2.59d (develop):
--------------------------
- fixed a critical bug in afl-tmin that was introduced during ++2.53d
- added test cases for afl-cmin and afl-tmin to test/test.sh
- added ./experimental/argv_fuzzing ld_preload library by Kjell Braden
- added preeny's desock_dup ld_preload library as
./experimental/socket_fuzzing for network fuzzing
- added AFL_AS_FORCE_INSTRUMENT environment variable for afl-as - this is
for the retrorewrite project
- we now set QEMU_SET_ENV from AFL_PRELOAD when qemu_mode is used
--------------------------
Version ++2.59c (release):
--------------------------
- qbdi_mode: fuzz android native libraries via QBDI framework
- unicorn_mode: switched to the new unicornafl, thanks domenukk
(see https://github.com/vanhauser-thc/unicorn)
- afl-fuzz:
- added radamsa as (an optional) mutator stage (-R[R])
- added -u command line option to not unlink the fuzz input file
- Python3 support (autodetect)
- AFL_DISABLE_TRIM env var to disable the trim stage
- CPU affinity support for DragonFly
- llvm_mode:
- float splitting is now configured via AFL_LLVM_LAF_SPLIT_FLOATS
- support for llvm 10 included now (thanks to devnexen)
- libtokencap:
- support for *BSD/OSX/Dragonfly added
- hook common *cmp functions from widely used libraries
- compcov:
- hook common *cmp functions from widely used libraries
- floating point splitting support for QEMU on x86 targets
- qemu_mode: AFL_QEMU_DISABLE_CACHE env to disable QEMU TranslationBlocks caching
- afl-analyze: added AFL_SKIP_BIN_CHECK support
- better random numbers for gcc_plugin and llvm_mode (thanks to devnexen)
- Dockerfile by courtesy of devnexen
- added regex.dictionary
- qemu and unicorn download scripts now try to download until the full
download succeeded. f*ckin travis fails downloading 40% of the time!
- more support for Android (please test!)
- added the few Android stuff we didnt have already from Google afl repository
- removed unnecessary warnings
--------------------------
Version ++2.58c (release):
--------------------------
- reverted patch to not unlink and recreate the input file, it resulted in
performance loss of ~10%
- added test/test-performance.sh script
- (re)added gcc_plugin, fast inline instrumentation is not yet finished,
however it includes the whitelisting and persistance feature! by hexcoder-
- gcc_plugin tests added to testing framework
--------------------------------
Version ++2.54d-2.57c (release):
--------------------------------
@ -42,6 +102,7 @@ Version ++2.54d-2.57c (release):
- updated documentation
- Wine mode to run Win32 binaries with the QEMU instrumentation (-W)
- CompareCoverage for ARM target in QEMU/Unicorn
- laf-intel in llvm_mode now also handles floating point comparisons
--------------------------

View File

@ -45,6 +45,8 @@ how to hit the ground running:
7) compile and use llvm_mode (afl-clang-fast/afl-clang-fast++) as it is way
faster and has a few cool features
8) There is a basic docker build with 'docker build -t aflplusplus .'
That's it. Sit back, relax, and - time permitting - try to skim through the
following files:

1
docs/README.radamsa.md Symbolic link
View File

@ -0,0 +1 @@
../src/third_party/libradamsa/README.md

View File

@ -65,17 +65,21 @@ tools make fairly broad use of environmental variables:
mkdir assembly_here
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
- If you are a weird person that wants to compile and instrument asm
text files then use the AFL_AS_FORCE_INSTRUMENT variable:
AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo
- Setting AFL_QUIET will prevent afl-cc and afl-as banners from being
displayed during compilation, in case you find them distracting.
- Setting AFL_CAL_FAST will speed up the initial calibration, if the
application is very slow
2) Settings for afl-clang-fast / afl-clang-fast++
-------------------------------------------------
2) Settings for afl-clang-fast / afl-clang-fast++ / afl-gcc-fast / afl-g++-fast
---------------------------------------------------------------------------------
The native LLVM instrumentation helper accepts a subset of the settings
discussed in section #1, with the exception of:
The native instrumentation helpers (llvm_mode and gcc_plugin) accept a subset
of the settings discussed in section #1, with the exception of:
- AFL_AS, since this toolchain does not directly invoke GNU as.
@ -100,7 +104,7 @@ Then there are a few specific features that are only available in llvm_mode:
- Setting AFL_LLVM_LAF_SPLIT_COMPARES will split all floating point and
64, 32 and 16 bit integer CMP instructions
See llvm_mode/README.laf-intel for more information.
See llvm_mode/README.laf-intel.md for more information.
WHITELIST
=========
@ -109,7 +113,7 @@ Then there are a few specific features that are only available in llvm_mode:
- Setting AFL_LLVM_WHITELIST with a filename will only instrument those
files that match the names listed in this file.
See llvm_mode/README.whitelist for more information.
See llvm_mode/README.whitelist.md for more information.
INSTRIM
=======
@ -122,7 +126,7 @@ Then there are a few specific features that are only available in llvm_mode:
afl-fuzz will only be able to see the path the loop took, but not how
many times it was called (unless it is a complex loop).
See llvm_mode/README.instrim
See llvm_mode/README.instrim.md
NOT_ZERO
========
@ -133,7 +137,18 @@ Then there are a few specific features that are only available in llvm_mode:
slowdown due a performance issue that is only fixed in llvm 9+.
This feature increases path discovery by a little bit.
See llvm_mode/README.neverzero
See llvm_mode/README.neverzero.md
Then there are a few specific features that are only available in the gcc_plugin:
WHITELIST
=========
This feature allows selective instrumentation of the source
- Setting AFL_GCC_WHITELIST with a filename will only instrument those
files that match the names listed in this file (one filename per line).
See gcc_plugin/README.whitelist.md for more information.
3) Settings for afl-fuzz
------------------------
@ -257,7 +272,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
- Setting AFL_COMPCOV_LEVEL enables the CompareCoverage tracing of all cmp
and sub in x86 and x86_64 and memory comparions functions (e.g. strcmp,
memcmp, ...) when libcompcov is preloaded using AFL_PRELOAD.
More info at qemu_mode/libcompcov/README.compcov.
More info at qemu_mode/libcompcov/README.md.
There are two levels at the moment, AFL_COMPCOV_LEVEL=1 that instruments
only comparisons with immediate values / read-only memory and
AFL_COMPCOV_LEVEL=2 that instruments all the comparions. Level 2 is more
@ -318,7 +333,7 @@ of decimal.
8) Settings for libdislocator.so
--------------------------------
The library honors three environmental variables:
The library honors these environmental variables:
- AFL_LD_LIMIT_MB caps the size of the maximum heap usage permitted by the
library, in megabytes. The default value is 1 GB. Once this is exceeded,

View File

@ -34,7 +34,7 @@ Note that ASAN is incompatible with -static, so be mindful of that.
There is also the option of generating a corpus using a non-ASAN binary, and
then feeding it to an ASAN-instrumented one to check for bugs. This is faster,
and can give you somewhat comparable results. You can also try using
libdislocator (see libdislocator/README.dislocator in the parent directory) as a
libdislocator (see libdislocator/README.dislocator.md in the parent directory) as a
lightweight and hassle-free (but less thorough) alternative.
2) Long version

View File

@ -50,12 +50,15 @@ Even if you don't have a lightweight harness for a particular target, remember
that you can always use another, related library to generate a corpus that will
be then manually fed to a more resource-hungry program later on.
Also note that reading the fuzzing input via stdin is faster than reading from
a file.
3) Use LLVM instrumentation
---------------------------
When fuzzing slow targets, you can gain 2x performance improvement by using
the LLVM-based instrumentation mode described in llvm_mode/README.llvm. Note
that this mode requires the use of clang and will not work with GCC.
When fuzzing slow targets, you can gain 20-100% performance improvement by
using the LLVM-based instrumentation mode described in llvm_mode/README.llvm.
Note that this mode requires the use of clang and will not work with GCC.
The LLVM mode also offers a "persistent", in-process fuzzing mode that can
work well for certain types of self-contained libraries, and for fast targets,
@ -72,6 +75,9 @@ If you are only intested in specific parts of the code being fuzzed, you can
whitelist the files that are actually relevant. This improves the speed and
accuracy of afl. See llvm_mode/README.whitelist
Also use the InsTrim mode on larger binaries, this improves performance and
coverage a lot.
4) Profile and optimize the binary
----------------------------------
@ -161,6 +167,11 @@ and not waste CPU time.
There are several OS-level factors that may affect fuzzing speed:
- If you have no risk of power loss then run your fuzzing on a tmpfs
partition. This increases the performance noticably.
Alternatively you can use AFL_TMPDIR to point to a tmpfs location to
just write the input file to a tmpfs.
- High system load. Use idle machines where possible. Kill any non-essential
CPU hogs (idle browser windows, media players, complex screensavers, etc).

View File

@ -2,7 +2,7 @@ afl++'s power schedules based on AFLfast
<a href="https://comp.nus.edu.sg/~mboehme/paper/CCS16.pdf"><img src="https://comp.nus.edu.sg/~mboehme/paper/CCS16.png" align="right" width="250"></a>
Power schedules implemented by Marcel Böhme \<marcel.boehme@acm.org\>.
AFLFast is an extension of AFL which was written by Michal Zalewski \<lcamtuf@google.com\>.
AFLFast is an extension of AFL which was written by Michal Zalewski.
AFLfast has helped in the success of Team Codejitsu at the finals of the DARPA Cyber Grand Challenge where their bot Galactica took **2nd place** in terms of #POVs proven (see red bar at https://www.cybergrandchallenge.com/event#results). AFLFast exposed several previously unreported CVEs that could not be exposed by AFL in 24 hours and otherwise exposed vulnerabilities significantly faster than AFL while generating orders of magnitude more unique crashes.

View File

@ -9,8 +9,9 @@ Adding custom mutators to AFL using Python modules
Implemented by Christian Holler (:decoder) <choller@mozilla.com>.
NOTE: This is for Python 2.7 !
Anyone who wants to add Python 3.7 support is happily welcome :)
NOTE: Python 3.7 and 2.7 are supported so far (3.8 upcomming).
Depending on with which version afl-fuzz was compiled, you must use
python2 or python3 syntax in your scripts!
For an example and a template see ../python_mutators/
@ -56,16 +57,20 @@ further information about this feature.
3) How to compile AFLFuzz with Python support
---------------------------------------------
You must install the python 2.7 development package of your Linux distribution
before this will work. On Debian/Ubuntu/Kali this can be done with:
You must install the python 3.7 or 2.7 development package of your Linux
distribution before this will work. On Debian/Ubuntu/Kali this can be done
with either:
apt install python3.7-dev
or
apt install python2.7-dev
Note that for some distributions you might also need the package python[23]-apt
A prerequisite for using this mode is to compile AFLFuzz with Python support.
The afl Makefile performs some magic and detects Python 2.7 if it is in the
default path and compiles afl-fuzz with the feature if available (which is
/usr/include/python2.7 for the Python.h include and /usr/lib/x86_64-linux-gnu
for the libpython2.7.a library)
The afl Makefile performs some magic and detects Python 3.7 and 2.7 if it is
in the default path and compiles afl-fuzz with the feature if available (which
is /usr/include/python2.7 for the Python.h include and
/usr/lib/x86_64-linux-gnu for the libpython2.7.a library)
In case your setup is different set the necessary variables like this:
PYTHON_INCLUDE=/path/to/python2.7/include LDFLAGS=-L/path/to/python2.7/lib make

View File

@ -319,11 +319,13 @@ Fuzzer shell for SQLite (Richard Hipp)
Support for Python mutation modules (Christian Holler)
------------------------------------------------------
now integrated in AFL++, originally from here
https://github.com/choller/afl/blob/master/docs/mozilla/python_modules.txt
Support for selective instrumentation (Christian Holler)
--------------------------------------------------------
now integrated in AFL++, originally from here
https://github.com/choller/afl/blob/master/docs/mozilla/partial_instrumentation.txt
Kernel fuzzing (Dmitry Vyukov)

View File

@ -165,7 +165,7 @@ of new tuples, and the remainder is associated with changes in hit counts.
The following table compares the relative ability to discover file syntax and
explore program states when using several different approaches to guided
fuzzing. The instrumented target was GNU patch 2.7.3 compiled with -O3 and
fuzzing. The instrumented target was GNU patch 2.7k.3 compiled with -O3 and
seeded with a dummy text file; the session consisted of a single pass over the
input queue with afl-fuzz:

View File

@ -0,0 +1,37 @@
#
# american fuzzy lop - argvfuzz
# --------------------------------
#
# Copyright 2019 Kjell Braden <afflux@pentabarf.de>
#
# 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
#
.PHONY: all install clean
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
CFLAGS = -fPIC -Wall -Wextra
LDFLAGS = -shared -ldl
all: argvfuzz32.so argvfuzz64.so
argvfuzz32.so: argvfuzz.c
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
argvfuzz64.so: argvfuzz.c
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
install: argvfuzz32.so argvfuzz64.so
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/
clean:
rm -f argvfuzz32.so argvfuzz64.so

View File

@ -0,0 +1,16 @@
# argvfuzz
afl supports fuzzing file inputs or stdin. When source is available,
`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin.
`argvfuzz` tries to provide the same functionality for binaries. When loaded
using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace
argv using the same logic of `argv-fuzz-inl.h`.
A few conditions need to be fulfilled for this mechanism to work correctly:
1. As it relies on hooking the loader, it cannot work on static binaries.
2. If the target binary does not use the default libc's `_start` implementation
(crt1.o), the hook may not run.
3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the
target binary expects argv to be living on the stack, things may go wrong.

View File

@ -2,7 +2,7 @@
american fuzzy lop - sample argv fuzzing wrapper
------------------------------------------------
Written by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.
@ -17,7 +17,7 @@
#include "/path/to/argv-fuzz-inl.h"
...to the file containing main(), ideally placing it after all the
...to the file containing main(), ideally placing it after all the
standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of
main().
@ -36,12 +36,20 @@
#include <unistd.h>
#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0)
#define AFL_INIT_SET0(_p) do { \
#define AFL_INIT_ARGV() \
do { \
\
argv = afl_init_argv(&argc); \
argv[0] = (_p); \
if (!argc) argc = 1; \
\
} while (0)
#define AFL_INIT_SET0(_p) \
do { \
\
argv = afl_init_argv(&argc); \
argv[0] = (_p); \
if (!argc) argc = 1; \
\
} while (0)
#define MAX_CMDLINE_LEN 100000
@ -53,9 +61,9 @@ static char** afl_init_argv(int* argc) {
static char* ret[MAX_CMDLINE_PAR];
char* ptr = in_buf;
int rc = 0;
int rc = 0;
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0);
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {}
while (*ptr) {
@ -63,7 +71,8 @@ static char** afl_init_argv(int* argc) {
if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
rc++;
while (*ptr) ptr++;
while (*ptr)
ptr++;
ptr++;
}
@ -77,4 +86,5 @@ static char** afl_init_argv(int* argc) {
#undef MAX_CMDLINE_LEN
#undef MAX_CMDLINE_PAR
#endif /* !_HAVE_ARGV_FUZZ_INL */
#endif /* !_HAVE_ARGV_FUZZ_INL */

View File

@ -0,0 +1,49 @@
/*
american fuzzy lop - LD_PRELOAD for fuzzing argv in binaries
------------------------------------------------------------
Copyright 2019 Kjell Braden <afflux@pentabarf.de>
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
*/
#define _GNU_SOURCE /* for RTLD_NEXT */
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "argv-fuzz-inl.h"
int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
void (*init)(void), void (*fini)(void),
void (*rtld_fini)(void), void *stack_end) {
int (*orig)(int (*main)(int, char **, char **), int argc, char **argv,
void (*init)(void), void (*fini)(void), void (*rtld_fini)(void),
void *stack_end);
int sub_argc;
char **sub_argv;
(void)argc;
(void)argv;
orig = dlsym(RTLD_NEXT, __func__);
if (!orig) {
fprintf(stderr, "hook did not find original %s: %s\n", __func__, dlerror());
exit(EXIT_FAILURE);
}
sub_argv = afl_init_argv(&sub_argc);
return orig(main, sub_argc, sub_argv, init, fini, rtld_fini, stack_end);
}

View File

@ -7,7 +7,7 @@
# David A. Wheeler <dwheeler@ida.org>
#
# Edits to bring the script in line with afl-cmin and other companion scripts
# by Michal Zalewski <lcamtuf@google.com>. All bugs are my fault.
# by Michal Zalewski. All bugs are my fault.
#
# Copyright 2015 Institute for Defense Analyses.
#

View File

@ -4,7 +4,7 @@
american fuzzy lop - <canvas> harness
-------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2013, 2014 Google Inc. All rights reserved.

View File

@ -3,7 +3,7 @@
# american fuzzy lop - clang assembly normalizer
# ----------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
# The idea for this wrapper comes from Ryan Govostes.
#
# Copyright 2013, 2014 Google Inc. All rights reserved.

View File

@ -3,7 +3,7 @@
# american fuzzy lop - crash triage utility
# -----------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2013, 2014, 2017 Google Inc. All rights reserved.
#
@ -22,7 +22,7 @@
# necessary.
#
echo "crash triage utility for afl-fuzz by <lcamtuf@google.com>"
echo "crash triage utility for afl-fuzz by Michal Zalewski"
echo
ulimit -v 100000 2>/dev/null

View File

@ -3,7 +3,7 @@
# american fuzzy lop - fuzzer synchronization tool
# ------------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -2,7 +2,7 @@
american fuzzy lop - persistent mode example
--------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.
@ -28,12 +28,11 @@
#include <signal.h>
#include <string.h>
/* Main entry point. */
int main(int argc, char** argv) {
ssize_t len; /* how much input did we read? */
ssize_t len; /* how much input did we read? */
char buf[100]; /* Example-only buffer, you'd replace it with other global or
local variables appropriate for your use case. */
@ -64,21 +63,28 @@ int main(int argc, char** argv) {
We just have some trivial inline code that faults on 'foo!'. */
/* do we have enough data? */
if (len < 4)
return 0;
if (len < 4) return 0;
if (buf[0] == 'f') {
printf("one\n");
if (buf[1] == 'o') {
printf("two\n");
if (buf[2] == 'o') {
printf("three\n");
if (buf[3] == '!') {
printf("four\n");
abort();
}
}
}
}
/*** END PLACEHOLDER CODE ***/
@ -92,3 +98,4 @@ int main(int argc, char** argv) {
return 0;
}

View File

@ -2,7 +2,7 @@
american fuzzy lop - postprocessor library example
--------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.
@ -21,9 +21,9 @@
in the targeted binary (as shown in ../libpng_no_checksum/). One possible
exception is the process of fuzzing binary-only software in QEMU mode.
2) The use of postprocessors for anything other than checksums is questionable
and may cause more harm than good. AFL is normally pretty good about
dealing with length fields, magic values, etc.
2) The use of postprocessors for anything other than checksums is
questionable and may cause more harm than good. AFL is normally pretty good
about dealing with length fields, magic values, etc.
3) Postprocessors that do anything non-trivial must be extremely robust to
gracefully handle malformed data and other error conditions - otherwise,
@ -77,10 +77,10 @@
/* The actual postprocessor routine called by afl-fuzz: */
const unsigned char* afl_postprocess(const unsigned char* in_buf,
unsigned int* len) {
unsigned int* len) {
static unsigned char* saved_buf;
unsigned char* new_buf;
unsigned char* new_buf;
/* Skip execution altogether for buffers shorter than 6 bytes (just to
show how it's done). We can trust *len to be sane. */
@ -117,3 +117,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
return new_buf;
}

View File

@ -2,7 +2,7 @@
american fuzzy lop - postprocessor for PNG
------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.
@ -36,13 +36,13 @@
#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
const unsigned char* afl_postprocess(const unsigned char* in_buf,
unsigned int* len) {
unsigned int* len) {
static unsigned char* saved_buf;
static unsigned int saved_len;
unsigned char* new_buf = (unsigned char*)in_buf;
unsigned int pos = 8;
unsigned int pos = 8;
/* Don't do anything if there's not enough room for the PNG header
(8 bytes). */
@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
return new_buf;
}

View File

@ -0,0 +1,35 @@
#
# american fuzzy lop++ - socket_fuzz
# ----------------------------------
#
# 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
#
.PHONY: all install clean
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
CFLAGS = -fPIC -Wall -Wextra
LDFLAGS = -shared -ldl
all: socketfuzz32.so socketfuzz64.so
socketfuzz32.so: socketfuzz.c
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
socketfuzz64.so: socketfuzz.c
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
install: socketfuzz32.so socketfuzz64.so
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/
clean:
rm -f socketfuzz32.so socketfuzz64.so

View File

@ -0,0 +1,11 @@
# socketfuzz
when you want to fuzz a network service and you can not/do not want to modify
the source (or just have a binary), then this LD_PRELOAD library will allow
for sending input to stdin which the target binary will think is coming from
a network socket.
This is desock_dup.c from the amazing preeny project
https://github.com/zardus/preeny
It is packaged in afl++ to have it at hand if needed

View File

@ -0,0 +1,110 @@
/*
* This is desock_dup.c from the amazing preeny project
* https://github.com/zardus/preeny
*
* It is packaged in afl++ to have it at hand if needed
*
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> //
#include <sys/socket.h> //
#include <sys/stat.h> //
#include <fcntl.h> //
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <poll.h>
//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: "
//
// originals
//
int (*original_close)(int);
int (*original_dup2)(int, int);
__attribute__((constructor)) void preeny_desock_dup_orig() {
original_close = dlsym(RTLD_NEXT, "close");
original_dup2 = dlsym(RTLD_NEXT, "dup2");
}
int close(int sockfd) {
if (sockfd <= 2) {
fprintf(stderr, "Info: Disabling close on %d\n", sockfd);
return 0;
} else {
return original_close(sockfd);
}
}
int dup2(int old, int new) {
if (new <= 2) {
fprintf(stderr, "Info: Disabling dup from %d to %d\n", old, new);
return 0;
} else {
return original_dup2(old, new);
}
}
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
(void)sockfd;
(void)addr;
(void)addrlen;
fprintf(stderr, "Info: Emulating accept on %d\n", sockfd);
return 0;
}
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
(void)sockfd;
(void)addr;
(void)addrlen;
fprintf(stderr, "Info: Emulating bind on port %d\n",
ntohs(((struct sockaddr_in *)addr)->sin_port));
return 0;
}
int listen(int sockfd, int backlog) {
(void)sockfd;
(void)backlog;
return 0;
}
int setsockopt(int sockfd, int level, int optid, const void *optdata,
socklen_t optdatalen) {
(void)sockfd;
(void)level;
(void)optid;
(void)optdata;
(void)optdatalen;
return 0;
}

130
gcc_plugin/Makefile Normal file
View File

@ -0,0 +1,130 @@
#
# american fuzzy lop - GCC plugin instrumentation
# -----------------------------------------------
#
# Written by Austin Seipp <aseipp@pobox.com> and
# Laszlo Szekeres <lszekeres@google.com> and
# Michal Zalewski and
# Heiko Eißfeldt <heiko@hexco.de>
#
# GCC integration design is based on the LLVM design, which comes
# from Laszlo Szekeres.
#
# Copyright 2015 Google Inc. 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
#
PREFIX ?= /usr/local
HELPER_PATH = $(PREFIX)/lib/afl
BIN_PATH = $(PREFIX)/bin
CFLAGS ?= -O3 -g -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
CXXFLAGS ?= -O3 -g -funroll-loops
CXXEFLAGS := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2
CC ?= gcc
CXX ?= g++
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
SHMAT_OK=1
else
SHMAT_OK=0
CFLAGS+=-DUSEMMAP=1
LDFLAGS += -lrt
endif
ifeq "$(TEST_MMAP)" "1"
SHMAT_OK=0
CFLAGS+=-DUSEMMAP=1
LDFLAGS += -lrt
endif
PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
ifeq "$(SHMAT_OK)" "1"
test_shm:
@echo "[+] shmat seems to be working."
@rm -f .test2
else
test_shm:
@echo "[-] shmat seems not to be working, switching to mmap implementation"
endif
test_deps:
@echo "[*] Checking for working '$(CC)'..."
@which $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
# @echo "[*] Checking for gcc for plugin support..."
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
@echo "[*] Checking for gcc plugin development header files..."
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
@echo "[*] Checking for '../afl-showmap'..."
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
@echo "[+] All set and ready to build."
../afl-gcc-fast: afl-gcc-fast.c | test_deps
$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< -o $@ $(LDFLAGS)
ln -sf afl-gcc-fast ../afl-g++-fast
../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps
$(CC) $(CFLAGS) -fPIC -c $< -o $@
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) ../test-instr.c -o test-instr $(LDFLAGS)
# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
../afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
echo 1 | ../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 does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/vanhauser-thc/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
@echo "[+] All right, the instrumentation seems to be working!"
all_done: test_build
@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
.NOTPARALLEL: clean
vpath % ..
%.8: %
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
@echo .SH NAME >> ../$@
@echo .B $* >> ../$@
@echo >> ../$@
@echo .SH SYNOPSIS >> ../$@
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
@echo >> ../$@
@echo .SH OPTIONS >> ../$@
@echo .nf >> ../$@
@../$* -h 2>&1 | tail -n +4 >> ../$@
@echo >> ../$@
@echo .SH AUTHOR >> ../$@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> ../$@
@echo >> ../$@
@echo .SH LICENSE >> ../$@
@echo Apache License Version 2.0, January 2004 >> ../$@
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
clean:
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
rm -f $(PROGS) ../afl-g++-fast ../afl-g*-fast.8

160
gcc_plugin/README.gcc.md Normal file
View File

@ -0,0 +1,160 @@
===========================================
GCC-based instrumentation for afl-fuzz
======================================
(See ../docs/README.md for the general instruction manual.)
(See ../llvm_mode/README.md for the LLVM-based instrumentation.)
!!! TODO items are:
!!! => inline instrumentation has to work!
!!!
## 1) Introduction
The code in this directory allows you 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:
- The compiler can make many optimizations that are hard to pull off when
manually inserting assembly. As a result, some slow, CPU-bound programs will
run up to around faster.
The gains are less pronounced for fast binaries, where the speed is limited
chiefly by the cost of creating new processes. In such cases, the gain will
probably stay within 10%.
- 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).
- 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).
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
co-exists with the original code.
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
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.
If the CC/CXX have been overridden, those compilers will be used from
those wrappers without using AFL_CXX/AFL_CC 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...]
make
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
../docs/env_variables.txt). 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
directory.
## 3) Gotchas, feedback, bugs
This is an early-stage mechanism, so field reports are welcome. You can send bug
reports to <hexcoder-@github.com>.
## 4) Bonus feature #1: deferred initialization
AFL tries to optimize performance by executing the targeted binary just once,
stopping it just before main(), and then cloning this "master" process to get
a steady supply of targets to fuzz.
Although this approach eliminates much of the OS-, linker- and libc-level
costs of executing the program, it does not always help with binaries that
perform other time-consuming initialization steps - say, parsing a large config
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
fairly simple way.
First, locate a suitable location in the code where the delayed cloning can
take place. This needs to be done with *extreme* care to avoid breaking the
binary. In particular, the program will probably malfunction if you select
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 creation of temporary files, network sockets, offset-sensitive file
descriptors, and similar shared-state resources - but only provided that
their state meaningfully influences the behavior of the program later on.
- Any access to the fuzzed input, including reading the metadata about its
size.
With the location selected, add this code in the appropriate spot:
```
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif
```
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.
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!
## 5) Bonus feature #2: persistent mode
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.
The basic structure of the program that does this would be:
```
while (__AFL_LOOP(1000)) {
/* Read input data. */
/* Call library code to be fuzzed. */
/* Reset state. */
}
/* Exit normally */
```
The numerical value specified within the loop controls the maximum number
of iterations before AFL will restart the process from scratch. This minimizes
the impact of memory leaks and similar glitches; 1000 is a good starting point.
A more detailed template is shown in ../experimental/persistent_demo/.
Similarly to the previous mode, the feature works only with afl-gcc-fast or
afl-clang-fast; #ifdef guards can be used to suppress it when using other
compilers.
Note that as with the previous mode, the feature is easy to misuse; if you
do not reset the critical state fully, you may end up with false positives or
waste a whole lot of CPU power doing nothing useful at all. Be particularly
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.

View File

@ -0,0 +1,73 @@
========================================
Using afl++ with partial instrumentation
========================================
This file describes how you can selectively instrument only the source files
that are interesting to you using the gcc instrumentation provided by
afl++.
Plugin by hexcoder-.
## 1) Description and purpose
When building and testing complex programs where only a part of the program is
the fuzzing target, it often helps to only instrument the necessary parts of
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, I have added a "partial instrumentation" support to the gcc
plugin of AFLFuzz that allows you to specify on a source file level which files
should be compiled with or without instrumentation.
## 2) Building the gcc plugin
The new code is part of the existing afl++ gcc plugin in the gcc_plugin/
subdirectory. There is nothing specifically to do :)
## 3) How to use the partial instrumentation mode
In order to build with partial instrumentation, you need to build with
afl-gcc-fast and afl-g++-fast respectively. The only required change is
that you need to set the environment variable AFL_GCC_WHITELIST when calling
the compiler.
The environment variable must point to a file containing all the filenames
that should be instrumented. For matching, the filename that is being compiled
must end in the filename entry contained in this whitelist (to avoid breaking
the matching when absolute paths are used during compilation).
For example if your source tree looks like this:
```
project/
project/feature_a/a1.cpp
project/feature_a/a2.cpp
project/feature_b/b1.cpp
project/feature_b/b2.cpp
```
and you only want to test feature_a, then create a whitelist file containing:
```
feature_a/a1.cpp
feature_a/a2.cpp
```
However if the whitelist file contains only this, it works as well:
```
a1.cpp
a2.cpp
```
but it might lead to files being unwantedly instrumented if the same filename
exists somewhere else in the project directories.
The created whitelist file is then set to AFL_GCC_WHITELIST when you compile
your program. For each file that didn't match the whitelist, the compiler will
issue a warning at the end stating that no blocks were instrumented. If you
didn't intend to instrument that file, then you can safely ignore that warning.

357
gcc_plugin/afl-gcc-fast.c Normal file
View File

@ -0,0 +1,357 @@
/*
american fuzzy lop - GCC wrapper for GCC plugin
------------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> and
Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres.
Copyright 2015 Google Inc. 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 program is a drop-in replacement for gcc, similar in most
respects to ../afl-gcc, but with compiler instrumentation through a
plugin. It tries to figure out compilation mode, adds a bunch of
flags, and then calls the real compiler.
*/
#define AFL_MAIN
#include "../config.h"
#include "../types.h"
#include "../include/debug.h"
#include "../include/alloc-inl.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
static u8* obj_path; /* Path to runtime libraries */
static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
/* Try to find the runtime libraries. If that fails, abort. */
static void find_obj(u8* argv0) {
u8* afl_path = getenv("AFL_PATH");
u8 *slash, *tmp;
if (afl_path) {
tmp = alloc_printf("%s/afl-gcc-rt.o", afl_path);
if (!access(tmp, R_OK)) {
obj_path = afl_path;
ck_free(tmp);
return;
}
ck_free(tmp);
}
slash = strrchr(argv0, '/');
if (slash) {
u8* dir;
*slash = 0;
dir = ck_strdup(argv0);
*slash = '/';
tmp = alloc_printf("%s/afl-gcc-rt.o", dir);
if (!access(tmp, R_OK)) {
obj_path = dir;
ck_free(tmp);
return;
}
ck_free(tmp);
ck_free(dir);
}
if (!access(AFL_PATH "/afl-gcc-rt.o", R_OK)) {
obj_path = AFL_PATH;
return;
}
FATAL(
"Unable to find 'afl-gcc-rt.o' or 'afl-gcc-pass.so'. Please set "
"AFL_PATH");
}
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1;
u8* name;
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
name = strrchr(argv[0], '/');
if (!name)
name = argv[0];
else
++name;
if (!strcmp(name, "afl-g++-fast")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)AFL_GCC_CXX;
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)AFL_GCC_CC;
}
char* fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
cc_params[cc_par_cnt++] = fplugin_arg;
/* Detect stray -v calls from ./configure scripts. */
if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
while (--argc) {
u8* cur = *(++argv);
#if defined(__x86_64__)
if (!strcmp(cur, "-m32")) FATAL("-m32 is not supported");
#endif
if (!strcmp(cur, "-x")) x_set = 1;
if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E") ||
!strcmp(cur, "-v"))
maybe_linking = 0;
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
asan_set = 1;
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
if (!strcmp(cur, "-shared")) maybe_linking = 0;
cc_params[cc_par_cnt++] = cur;
}
if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all";
if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
}
if (!asan_set) {
if (getenv("AFL_USE_ASAN")) {
if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive");
if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address";
} else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive");
if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory";
}
}
if (!getenv("AFL_DONT_OPTIMIZE")) {
cc_params[cc_par_cnt++] = "-g";
cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops";
}
if (getenv("AFL_NO_BUILTIN")) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
}
#ifdef USEMMAP
cc_params[cc_par_cnt++] = "-lrt";
#endif
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
/* When the user tries to use persistent or deferred forkserver modes by
appending a single line to the program, we want to reliably inject a
signature into the binary (to be picked up by afl-fuzz) and we want
to call a function from the runtime .o file. This is unnecessarily
painful for three reasons:
1) We need to convince the compiler not to optimize out the signature.
This is done with __attribute__((used)).
2) We need to convince the linker, when called with -Wl,--gc-sections,
not to do the same. This is done by forcing an assignment to a
'volatile' pointer.
3) We need to declare __afl_persistent_loop() in the global namespace,
but doing this within a method in a class is hard - :: and extern "C"
are forbidden and __attribute__((alias(...))) doesn't work. Hence the
__asm__ aliasing trick.
*/
cc_params[cc_par_cnt++] =
"-D__AFL_LOOP(_A)="
"({ static volatile char *_B __attribute__((used)); "
" _B = (char*)\"" PERSIST_SIG
"\"; "
#ifdef __APPLE__
"int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
#else
"int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
"_L(_A); })";
cc_params[cc_par_cnt++] =
"-D__AFL_INIT()="
"do { static volatile char *_A __attribute__((used)); "
" _A = (char*)\"" DEFER_SIG
"\"; "
#ifdef __APPLE__
"void _I(void) __asm__(\"___afl_manual_init\"); "
#else
"void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
"_I(); } while (0)";
if (maybe_linking) {
if (x_set) {
cc_params[cc_par_cnt++] = "-x";
cc_params[cc_par_cnt++] = "none";
}
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-gcc-rt.o", obj_path);
}
cc_params[cc_par_cnt] = NULL;
}
/* Main entry point */
int main(int argc, char** argv) {
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
printf(
cCYA
"afl-gcc-fast" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"
"\n"
"afl-gcc-fast [options]\n"
"\n"
"This is a helper application for afl-fuzz. It serves as a drop-in "
"replacement\n"
"for gcc, letting you recompile third-party code with the required "
"runtime\n"
"instrumentation. A common use pattern would be one of the "
"following:\n\n"
" CC=%s/afl-gcc-fast ./configure\n"
" CXX=%s/afl-g++-fast ./configure\n\n"
"In contrast to the traditional afl-gcc tool, this version is "
"implemented as\n"
"a GCC plugin and tends to offer improved performance with slow "
"programs\n"
"(similarly to the LLVM plugin used by afl-clang-fast).\n\n"
"You can specify custom next-stage toolchain via AFL_CC and AFL_CXX. "
"Setting\n"
"AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
BIN_PATH, BIN_PATH);
exit(1);
} else if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(cCYA "afl-gcc-fast" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n");
if (getenv("AFL_GCC_WHITELIST") == NULL) {
SAYF(cYEL "Warning:" cRST
" using afl-gcc-fast without using AFL_GCC_WHITELIST currently "
"produces worse results than afl-gcc. Even better, use "
"llvm_mode for now.\n");
}
}
find_obj(argv[0]);
edit_params(argc, argv);
/*if (isatty(2) && !getenv("AFL_QUIET")) {
printf("Calling \"%s\" with:\n", cc_params[0]);
for(int i=1; i<cc_par_cnt; i++) printf("%s\n", cc_params[i]);
}
*/
execvp(cc_params[0], (char**)cc_params);
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
return 0;
}

View File

@ -0,0 +1,593 @@
//
// There are some TODOs in this file:
// - fix instrumentation via external call
// - fix inline instrumentation
// - implement whitelist feature
// - dont instrument blocks that are uninteresting
// - implement neverZero
//
/*
american fuzzy lop - GCC instrumentation pass
---------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> with bits from
Emese Revfy <re.emese@gmail.com>
Fixed by Heiko Eißfeldt 2019 for AFL++
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres. Some of the boilerplate code below for
afl_pass to adapt to different GCC versions was taken from Emese
Revfy's Size Overflow plugin for GCC, licensed under the GPLv2/v3.
(NOTE: this plugin code is under GPLv3, in order to comply with the
GCC runtime library exception, which states that you may distribute
"Target Code" from the compiler under a license of your choice, as
long as the "Compilation Process" is "Eligible", and contains no
GPL-incompatible software in GCC "during the process of
transforming high level code to target code". In this case, the
plugin will be used to generate "Target Code" during the
"Compilation Process", and thus it must be GPLv3 to be "eligible".)
Copyright (C) 2015 Austin Seipp
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define BUILD_INLINE_INST
#include "../config.h"
#include "../include/debug.h"
/* clear helper AFL types pulls in, which intervene with gcc-plugin geaders from
* GCC-8 */
#ifdef likely
#undef likely
#endif
#ifdef unlikely
#undef unlikely
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <list>
#include <string>
#include <fstream>
#include <gcc-plugin.h>
#include <plugin-version.h>
#include <diagnostic.h>
#include <tree.h>
#include <tree-ssa.h>
#include <tree-pass.h>
#include <tree-ssa-alias.h>
#include <basic-block.h>
#include <gimple-expr.h>
#include <gimple.h>
#include <gimple-iterator.h>
#include <gimple-ssa.h>
#include <version.h>
#include <toplev.h>
#include <intl.h>
#include <context.h>
#include <stringpool.h>
#include <cgraph.h>
#include <cfgloop.h>
/* -------------------------------------------------------------------------- */
/* -- AFL instrumentation pass ---------------------------------------------- */
static int be_quiet = 0;
static unsigned int inst_ratio = 100;
static bool inst_ext = true;
static std::list<std::string> myWhitelist;
static unsigned int ext_call_instrument(function *fun) {
/* Instrument all the things! */
basic_block bb;
unsigned finst_blocks = 0;
unsigned fcnt_blocks = 0;
tree fntype = build_function_type_list(void_type_node, /* return */
uint32_type_node, /* args */
NULL_TREE); /* done */
tree fndecl = build_fn_decl("__afl_trace", fntype);
TREE_STATIC(fndecl) = 1; /* Defined elsewhere */
TREE_PUBLIC(fndecl) = 1; /* Public */
DECL_EXTERNAL(fndecl) = 1; /* External linkage */
DECL_ARTIFICIAL(fndecl) = 1; /* Injected by compiler */
FOR_EACH_BB_FN(bb, fun) {
gimple_seq fcall;
gimple_seq seq = NULL;
gimple_stmt_iterator bentry;
++fcnt_blocks;
// only instrument if this basic block is the destination of a previous
// basic block that has multiple successors
// this gets rid of ~5-10% of instrumentations that are unnecessary
// result: a little more speed and less map pollution
int more_than_one = -1;
edge ep;
edge_iterator eip;
FOR_EACH_EDGE(ep, eip, bb->preds) {
int count = 0;
if (more_than_one == -1) more_than_one = 0;
basic_block Pred = ep->src;
edge es;
edge_iterator eis;
FOR_EACH_EDGE(es, eis, Pred->succs) {
basic_block Succ = es->dest;
if (Succ != NULL) count++;
}
if (count > 1) more_than_one = 1;
}
if (more_than_one != 1) continue;
/* Bail on this block if we trip the specified ratio */
if (R(100) >= inst_ratio) continue;
/* Make up cur_loc */
unsigned int rand_loc = R(MAP_SIZE);
tree cur_loc = build_int_cst(uint32_type_node, rand_loc);
/* Update bitmap via external call */
/* to quote:
* /+ Trace a basic block with some ID +/
* void __afl_trace(u32 x);
*/
fcall = gimple_build_call(
fndecl, 1,
cur_loc); /* generate the function _call_ to above built reference, with
*1* parameter -> the random const for the location */
gimple_seq_add_stmt(&seq, fcall); /* and insert into a sequence */
/* Done - grab the entry to the block and insert sequence */
bentry = gsi_after_labels(bb);
gsi_insert_seq_before(&bentry, seq, GSI_SAME_STMT);
++finst_blocks;
}
/* Say something nice. */
if (!be_quiet) {
if (!finst_blocks)
WARNF(G_("No instrumentation targets found in " cBRI "%s" cRST),
function_name(fun));
else if (finst_blocks < fcnt_blocks)
OKF(G_("Instrumented %2u /%2u locations in " cBRI "%s" cRST),
finst_blocks, fcnt_blocks, function_name(fun));
else
OKF(G_("Instrumented %2u locations in " cBRI "%s" cRST), finst_blocks,
function_name(fun));
}
return 0;
}
static unsigned int inline_instrument(function *fun) {
/* Instrument all the things! */
basic_block bb;
unsigned finst_blocks = 0;
unsigned fcnt_blocks = 0;
tree one = build_int_cst(unsigned_char_type_node, 1);
// tree zero = build_int_cst(unsigned_char_type_node, 0);
/* Set up global type declarations */
tree map_type = build_pointer_type(unsigned_char_type_node);
tree map_ptr_g =
build_decl(UNKNOWN_LOCATION, VAR_DECL,
get_identifier_with_length("__afl_area_ptr", 14), map_type);
TREE_USED(map_ptr_g) = 1;
TREE_STATIC(map_ptr_g) = 1; /* Defined elsewhere */
DECL_EXTERNAL(map_ptr_g) = 1; /* External linkage */
DECL_PRESERVE_P(map_ptr_g) = 1;
DECL_ARTIFICIAL(map_ptr_g) = 1; /* Injected by compiler */
rest_of_decl_compilation(map_ptr_g, 1, 0);
tree prev_loc_g = build_decl(UNKNOWN_LOCATION, VAR_DECL,
get_identifier_with_length("__afl_prev_loc", 14),
uint32_type_node);
TREE_USED(prev_loc_g) = 1;
TREE_STATIC(prev_loc_g) = 1; /* Defined elsewhere */
DECL_EXTERNAL(prev_loc_g) = 1; /* External linkage */
DECL_PRESERVE_P(prev_loc_g) = 1;
DECL_ARTIFICIAL(prev_loc_g) = 1; /* Injected by compiler */
set_decl_tls_model(prev_loc_g, TLS_MODEL_REAL); /* TLS attribute */
rest_of_decl_compilation(prev_loc_g, 1, 0);
FOR_EACH_BB_FN(bb, fun) {
gimple_seq seq = NULL;
gimple_stmt_iterator bentry;
++fcnt_blocks;
// only instrument if this basic block is the destination of a previous
// basic block that has multiple successors
// this gets rid of ~5-10% of instrumentations that are unnecessary
// result: a little more speed and less map pollution
int more_than_one = -1;
edge ep;
edge_iterator eip;
FOR_EACH_EDGE(ep, eip, bb->preds) {
int count = 0;
if (more_than_one == -1) more_than_one = 0;
basic_block Pred = ep->src;
edge es;
edge_iterator eis;
FOR_EACH_EDGE(es, eis, Pred->succs) {
basic_block Succ = es->dest;
if (Succ != NULL) count++;
}
if (count > 1) more_than_one = 1;
}
if (more_than_one != 1) continue;
/* Bail on this block if we trip the specified ratio */
if (R(100) >= inst_ratio) continue;
/* Make up cur_loc */
unsigned int rand_loc = R(MAP_SIZE);
tree cur_loc = build_int_cst(uint32_type_node, rand_loc);
/* Load prev_loc, xor with cur_loc */
// gimple_assign <var_decl, prev_loc.0_1, prev_loc, NULL, NULL>
tree prev_loc = create_tmp_var_raw(uint32_type_node, "prev_loc");
gassign *g = gimple_build_assign(prev_loc, VAR_DECL, prev_loc_g);
gimple_seq_add_stmt(&seq, g); // load prev_loc
update_stmt(g);
// gimple_assign <bit_xor_expr, _2, prev_loc.0_1, 47231, NULL>
tree area_off = create_tmp_var_raw(uint32_type_node, "area_off");
g = gimple_build_assign(area_off, BIT_XOR_EXPR, prev_loc, cur_loc);
gimple_seq_add_stmt(&seq, g); // area_off = prev_loc ^ cur_loc
update_stmt(g);
/* Update bitmap */
// gimple_assign <addr_expr, p_6, &map[_2], NULL, NULL>
tree map_ptr = create_tmp_var(map_type, "map_ptr");
tree map_ptr2 = create_tmp_var(map_type, "map_ptr2");
g = gimple_build_assign(map_ptr, map_ptr_g);
gimple_seq_add_stmt(&seq, g); // map_ptr = __afl_area_ptr
update_stmt(g);
#if 1
#if 0
tree addr = build2(ADDR_EXPR, map_type, map_ptr, area_off);
g = gimple_build_assign(map_ptr2, MODIFY_EXPR, addr);
gimple_seq_add_stmt(&seq, g); // map_ptr2 = map_ptr + area_off
update_stmt(g);
#else
g = gimple_build_assign(map_ptr2, PLUS_EXPR, map_ptr, area_off);
gimple_seq_add_stmt(&seq, g); // map_ptr2 = map_ptr + area_off
update_stmt(g);
#endif
// gimple_assign <mem_ref, _3, *p_6, NULL, NULL>
tree tmp1 = create_tmp_var_raw(unsigned_char_type_node, "tmp1");
g = gimple_build_assign(tmp1, MEM_REF, map_ptr2);
gimple_seq_add_stmt(&seq, g); // tmp1 = *map_ptr2
update_stmt(g);
#else
tree atIndex = build2(PLUS_EXPR, uint32_type_node, map_ptr, area_off);
tree array_address = build1(ADDR_EXPR, map_type, atIndex);
tree array_access = build1(INDIRECT_REF, map_type, array_address);
tree tmp1 = create_tmp_var(unsigned_char_type_node, "tmp1");
g = gimple_build_assign(tmp1, array_access);
gimple_seq_add_stmt(&seq, g); // tmp1 = *(map_ptr + area_off)
update_stmt(g);
#endif
// gimple_assign <plus_expr, _4, _3, 1, NULL>
tree tmp2 = create_tmp_var_raw(unsigned_char_type_node, "tmp2");
g = gimple_build_assign(tmp2, PLUS_EXPR, tmp1, one);
gimple_seq_add_stmt(&seq, g); // tmp2 = tmp1 + 1
update_stmt(g);
// TODO: neverZero: here we have to check if tmp3 == 0
// and add 1 if so
// gimple_assign <ssa_name, *p_6, _4, NULL, NULL>
// tree map_ptr3 = create_tmp_var_raw(map_type, "map_ptr3");
g = gimple_build_assign(map_ptr2, INDIRECT_REF, tmp2);
gimple_seq_add_stmt(&seq, g); // *map_ptr2 = tmp2
update_stmt(g);
/* Set prev_loc to cur_loc >> 1 */
// gimple_assign <integer_cst, prev_loc, 23615, NULL, NULL>
tree shifted_loc = build_int_cst(TREE_TYPE(prev_loc_g), rand_loc >> 1);
tree prev_loc2 = create_tmp_var_raw(uint32_type_node, "prev_loc2");
g = gimple_build_assign(prev_loc2, shifted_loc);
gimple_seq_add_stmt(&seq, g); // __afl_prev_loc = cur_loc >> 1
update_stmt(g);
g = gimple_build_assign(prev_loc_g, prev_loc2);
gimple_seq_add_stmt(&seq, g); // __afl_prev_loc = cur_loc >> 1
update_stmt(g);
/* Done - grab the entry to the block and insert sequence */
bentry = gsi_after_labels(bb);
gsi_insert_seq_before(&bentry, seq, GSI_NEW_STMT);
++finst_blocks;
}
/* Say something nice. */
if (!be_quiet) {
if (!finst_blocks)
WARNF(G_("No instrumentation targets found in " cBRI "%s" cRST),
function_name(fun));
else if (finst_blocks < fcnt_blocks)
OKF(G_("Instrumented %2u /%2u locations in " cBRI "%s" cRST),
finst_blocks, fcnt_blocks, function_name(fun));
else
OKF(G_("Instrumented %2u locations in " cBRI "%s" cRST), finst_blocks,
function_name(fun));
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -- Boilerplate and initialization ---------------------------------------- */
static const struct pass_data afl_pass_data = {
.type = GIMPLE_PASS,
.name = "afl-inst",
.optinfo_flags = OPTGROUP_NONE,
.tv_id = TV_NONE,
.properties_required = 0,
.properties_provided = 0,
.properties_destroyed = 0,
.todo_flags_start = 0,
// NOTE(aseipp): it's very, very important to include
// at least 'TODO_update_ssa' here so that GCC will
// properly update the resulting SSA form, e.g., to
// include new PHI nodes for newly added symbols or
// names. Do not remove this. Do not taunt Happy Fun
// Ball.
.todo_flags_finish = TODO_update_ssa | TODO_verify_il | TODO_cleanup_cfg,
};
namespace {
class afl_pass : public gimple_opt_pass {
private:
bool do_ext_call;
public:
afl_pass(bool ext_call, gcc::context *g)
: gimple_opt_pass(afl_pass_data, g), do_ext_call(ext_call) {
}
unsigned int execute(function *fun) override {
if (!myWhitelist.empty()) {
bool instrumentBlock = false;
std::string instFilename;
unsigned int instLine = 0;
/* EXPR_FILENAME
This macro returns the name of the file in which the entity was declared,
as a char*. For an entity declared implicitly by the compiler (like
__builtin_ memcpy), this will be the string "<internal>".
*/
const char *fname = DECL_SOURCE_FILE(fun->decl);
if (0 != strncmp("<internal>", fname, 10) &&
0 != strncmp("<built-in>", fname, 10)) {
instFilename = fname;
instLine = DECL_SOURCE_LINE(fun->decl);
/* Continue only if we know where we actually are */
if (!instFilename.empty()) {
for (std::list<std::string>::iterator it = myWhitelist.begin();
it != myWhitelist.end(); ++it) {
/* We don't check for filename equality here because
* filenames might actually be full paths. Instead we
* check that the actual filename ends in the filename
* specified in the list. */
if (instFilename.length() >= it->length()) {
if (instFilename.compare(instFilename.length() - it->length(),
it->length(), *it) == 0) {
instrumentBlock = true;
break;
}
}
}
}
}
/* Either we couldn't figure out our location or the location is
* not whitelisted, so we skip instrumentation. */
if (!instrumentBlock) {
if (!be_quiet) {
if (!instFilename.empty())
SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s line %u...\n",
instFilename.c_str(), instLine);
else
SAYF(cYEL "[!] " cBRI "No filename information found, skipping it");
}
return 0;
}
}
return do_ext_call ? ext_call_instrument(fun) : inline_instrument(fun);
}
}; /* class afl_pass */
} // namespace
static struct opt_pass *make_afl_pass(bool ext_call, gcc::context *ctxt) {
return new afl_pass(ext_call, ctxt);
}
/* -------------------------------------------------------------------------- */
/* -- Initialization -------------------------------------------------------- */
int plugin_is_GPL_compatible = 1;
static struct plugin_info afl_plugin_info = {
.version = "20191015",
.help = "AFL++ gcc plugin\n",
};
int plugin_init(struct plugin_name_args * plugin_info,
struct plugin_gcc_version *version) {
struct register_pass_info afl_pass_info;
struct timeval tv;
struct timezone tz;
u32 rand_seed;
/* Setup random() so we get Actually Random(TM) outputs from R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
SR(rand_seed);
/* Pass information */
afl_pass_info.pass = make_afl_pass(inst_ext, g);
afl_pass_info.reference_pass_name = "ssa";
afl_pass_info.ref_pass_instance_number = 1;
afl_pass_info.pos_op = PASS_POS_INSERT_AFTER;
if (!plugin_default_version_check(version, &gcc_version)) {
FATAL(G_("Incompatible gcc/plugin versions!"));
}
/* Show a banner */
if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(G_(cCYA "afl-gcc-pass" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"));
} else
be_quiet = 1;
/* Decide instrumentation ratio */
char *inst_ratio_str = getenv("AFL_INST_RATIO");
if (inst_ratio_str) {
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
inst_ratio > 100)
FATAL(G_("Bad value of AFL_INST_RATIO (must be between 1 and 100)"));
else {
if (!be_quiet)
ACTF(G_("%s instrumentation at ratio of %u%% in %s mode."),
inst_ext ? G_("Call-based") : G_("Inline"), inst_ratio,
getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"));
}
}
char *instWhiteListFilename = getenv("AFL_GCC_WHITELIST");
if (instWhiteListFilename) {
std::string line;
std::ifstream fileStream;
fileStream.open(instWhiteListFilename);
if (!fileStream) fatal_error(0, "Unable to open AFL_GCC_WHITELIST");
getline(fileStream, line);
while (fileStream) {
myWhitelist.push_back(line);
getline(fileStream, line);
}
} else if (!be_quiet && getenv("AFL_LLVM_WHITELIST"))
SAYF(cYEL "[-] " cRST
"AFL_LLVM_WHITELIST environment variable detected - did you mean "
"AFL_GCC_WHITELIST?\n");
/* Go go gadget */
register_callback(plugin_info->base_name, PLUGIN_INFO, NULL,
&afl_plugin_info);
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
&afl_pass_info);
return 0;
}

300
gcc_plugin/afl-gcc-rt.o.c Normal file
View File

@ -0,0 +1,300 @@
/*
american fuzzy lop - GCC plugin instrumentation bootstrap
---------------------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> and
Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres.
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 code is the rewrite of afl-as.h's main_payload.
*/
#ifdef __ANDROID__
#include "android-ashmem.h"
#endif
#include "../config.h"
#include "../types.h"
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
/* Globals needed by the injected instrumentation. The __afl_area_initial region
is used for instrumentation output before __afl_map_shm() has a chance to
run. It will end up as .comm, so it shouldn't be too wasteful. */
u8 __afl_area_initial[MAP_SIZE];
u8 *__afl_area_ptr = __afl_area_initial;
#ifdef __ANDROID__
u32 __afl_prev_loc;
#else
__thread u32 __afl_prev_loc;
#endif
/* Trace a basic block with some ID */
void __afl_trace(const u32 x) {
#if 1 /* enable for neverZero feature. */
__afl_area_ptr[__afl_prev_loc ^ x] +=
1 + ((u8)(1 + __afl_area_ptr[__afl_prev_loc ^ x]) == 0);
#else
++__afl_area_ptr[__afl_prev_loc ^ x];
#endif
__afl_prev_loc = (x >> 1);
return;
}
/* Running in persistent mode? */
static u8 is_persistent;
/* SHM setup. */
static void __afl_map_shm(void) {
u8 *id_str = getenv(SHM_ENV_VAR);
/* If we're running under AFL, attach to the appropriate region, replacing the
early-stage __afl_area_initial region that is needed to allow some really
hacky .init code to work correctly in projects such as OpenSSL. */
if (id_str) {
#ifdef USEMMAP
const char * shm_file_path = id_str;
int shm_fd = -1;
unsigned char *shm_base = NULL;
/* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
if (shm_fd == -1) {
printf("shm_open() failed\n");
exit(1);
}
/* map the shared memory segment to the address space of the process */
shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_base == MAP_FAILED) {
close(shm_fd);
shm_fd = -1;
printf("mmap() failed\n");
exit(2);
}
__afl_area_ptr = shm_base;
#else
u32 shm_id = atoi(id_str);
__afl_area_ptr = shmat(shm_id, NULL, 0);
#endif
/* Whooooops. */
if (__afl_area_ptr == (void *)-1) exit(1);
/* Write something into the bitmap so that even with low AFL_INST_RATIO,
our parent doesn't give up on us. */
__afl_area_ptr[0] = 1;
}
}
/* Fork server logic. */
static void __afl_start_forkserver(void) {
static u8 tmp[4];
s32 child_pid;
u8 child_stopped = 0;
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
while (1) {
u32 was_killed;
int status;
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(1);
/* If we stopped the child in persistent mode, but there was a race
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) exit(1);
}
if (!child_stopped) {
/* Once woken up, create a clone of our process. */
child_pid = fork();
if (child_pid < 0) exit(1);
/* In child process: close fds, resume execution. */
if (!child_pid) {
signal(SIGCHLD, old_sigchld_handler);
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
return;
}
} else {
/* Special handling for persistent mode: if the child is alive but
currently stopped, simply restart it with SIGCONT. */
kill(child_pid, SIGCONT);
child_stopped = 0;
}
/* In parent process: write PID to pipe, then wait for child. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(1);
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) exit(1);
/* In persistent mode, the child stops itself with SIGSTOP to indicate
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status)) child_stopped = 1;
/* Relay wait status to pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);
}
}
/* A simplified persistent mode handler, used as explained in README.llvm. */
int __afl_persistent_loop(unsigned int max_cnt) {
static u8 first_pass = 1;
static u32 cycle_cnt;
if (first_pass) {
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
On subsequent calls, the parent will take care of that, but on the first
iteration, it's our job to erase any trace of whatever happened
before the loop. */
if (is_persistent) {
memset(__afl_area_ptr, 0, MAP_SIZE);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
}
cycle_cnt = max_cnt;
first_pass = 0;
return 1;
}
if (is_persistent) {
if (--cycle_cnt) {
raise(SIGSTOP);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
return 1;
} else {
/* When exiting __AFL_LOOP(), make sure that the subsequent code that
follows the loop is not traced. We do that by pivoting back to the
dummy output region. */
__afl_area_ptr = __afl_area_initial;
}
}
return 0;
}
/* This one can be called from user code when deferred forkserver mode
is enabled. */
void __afl_manual_init(void) {
static u8 init_done;
if (!init_done) {
__afl_map_shm();
__afl_start_forkserver();
init_done = 1;
}
}
/* Proper initialization routine. */
__attribute__((constructor(101))) void __afl_auto_init(void) {
is_persistent = !!getenv(PERSIST_ENV_VAR);
if (getenv(DEFER_ENV_VAR)) return;
__afl_manual_init();
}

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - injectable parts
---------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - fuzzer header
------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -72,18 +72,21 @@
#include <sys/file.h>
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
defined(__NetBSD__)
defined(__NetBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
/* For systems that have sched_setaffinity; right now just Linux, but one
can hope... */
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
#define HAVE_AFFINITY 1
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/param.h>
#if defined(__FreeBSD__)
#include <sys/cpuset.h>
#endif
#include <sys/user.h>
#include <pthread.h>
#include <pthread_np.h>
@ -93,6 +96,10 @@
#endif
#endif /* __linux__ */
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
#ifndef SIMPLE_FILES
#define CASE_PREFIX "id:"
#else
@ -160,7 +167,8 @@ enum {
/* 15 */ STAGE_HAVOC,
/* 16 */ STAGE_SPLICE,
/* 17 */ STAGE_PYTHON,
/* 18 */ STAGE_CUSTOM_MUTATOR
/* 18 */ STAGE_RADAMSA,
/* 19 */ STAGE_CUSTOM_MUTATOR
};
@ -252,7 +260,7 @@ extern u8 *in_dir, /* Input directory with test cases */
*file_extension, /* File extension */
*orig_cmdline, /* Original command line */
*doc_path, /* Path to documentation dir */
*infoexec, /* Command to execute on a new crash */
*infoexec, /* Command to execute on a new crash */
*out_file; /* File to fuzz, if any */
extern u32 exec_tmout; /* Configurable exec timeout (ms) */
@ -261,7 +269,10 @@ extern u32 hang_tmout; /* Timeout used for hang det (ms) */
extern u64 mem_limit; /* Memory cap for child (MB) */
extern u8 cal_cycles, /* Calibration cycles defaults */
cal_cycles_long, debug, /* Debug mode */
cal_cycles_long, /* Calibration cycles defaults */
no_unlink, /* do not unlink cur_input */
use_stdin, /* use stdin for sending data */
debug, /* Debug mode */
custom_only, /* Custom mutator only mode */
python_only; /* Python-only mode */
@ -285,6 +296,9 @@ extern char* power_names[POWER_SCHEDULES_NUM];
extern u8 schedule; /* Power schedule (default: EXPLORE)*/
extern u8 havoc_max_mult;
extern u8 use_radamsa;
extern size_t (*radamsa_mutate_ptr)(u8*, size_t, u8*, size_t, u32);
extern u8 skip_deterministic, /* Skip deterministic stages? */
force_deterministic, /* Force deterministic stages? */
use_splicing, /* Recombine input files? */
@ -312,7 +326,8 @@ extern u8 skip_deterministic, /* Skip deterministic stages? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal, /* Try to calibrate faster? */
uses_asan; /* Target uses ASAN? */
uses_asan, /* Target uses ASAN? */
disable_trim; /* Never trim in fuzz_one */
extern s32 out_fd, /* Persistent fd for out_file */
#ifndef HAVE_ARC4RANDOM
@ -400,6 +415,9 @@ extern u64 stage_finds[32], /* Patterns found per fuzz stage */
extern u32 rand_cnt; /* Random number counter */
#endif
extern u32 rand_seed[2];
extern s64 init_seed;
extern u64 total_cal_us, /* Total calibration time (us) */
total_cal_cycles; /* Total calibration cycles */
@ -541,7 +559,7 @@ u8 has_new_bits(u8*);
u32 count_bits(u8*);
u32 count_bytes(u8*);
u32 count_non_255_bytes(u8*);
#ifdef __x86_64__
#ifdef WORD_SIZE_64
void simplify_trace(u64*);
void classify_counts(u64*);
#else
@ -643,11 +661,9 @@ static inline u32 UR(u32 limit) {
#else
if (!fixed_seed && unlikely(!rand_cnt--)) {
u32 seed[2];
ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom");
srandom(seed[0]);
rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG);
ck_read(dev_urandom_fd, &rand_seed, sizeof(rand_seed), "/dev/urandom");
srandom(rand_seed[0]);
rand_cnt = (RESEED_RNG / 2) + (rand_seed[1] % RESEED_RNG);
}
@ -656,6 +672,13 @@ static inline u32 UR(u32 limit) {
}
static inline u32 get_rand_seed() {
if (fixed_seed) return (u32)init_seed;
return rand_seed[0];
}
/* Find first power of two greater or equal to val (assuming val under
2^63). */

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - error-checking, memory-zeroing alloc routines
--------------------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

6
include/android-ashmem.h Normal file → Executable file
View File

@ -2,7 +2,7 @@
american fuzzy lop++ - android shared memory compatibility layer
----------------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -52,7 +52,7 @@ static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
if (__cmd == IPC_RMID) {
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
struct ashmem_pin pin = {0, length};
struct ashmem_pin pin = {0, (unsigned int)length};
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
close(__shmid);
@ -64,6 +64,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) {
(void)__shmflg;
int fd, ret;
char ourkey[11];
@ -87,6 +88,7 @@ error:
static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
(void)__shmflg;
int size;
void *ptr;

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - common routines header
---------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - vaguely configurable bits
------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -26,7 +26,7 @@
/* Version string: */
#define VERSION "++2.57c" // c = release, d = volatile github dev
#define VERSION "++2.59d" // c = release, d = volatile github dev
/******************************************************
* *
@ -41,7 +41,9 @@
/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */
#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb
#define FANCY_BOXES
#endif
/* Default timeout for fuzzed code (milliseconds). This is the upper bound,
also used for detecting hangs; the actual value is auto-scaled: */
@ -52,13 +54,18 @@
#define EXEC_TM_ROUND 20
/* 64bit arch MACRO */
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
#define WORD_SIZE_64 1
#endif
/* Default memory limit for child process (MB): */
#ifndef __x86_64__
#ifndef WORD_SIZE_64
#define MEM_LIMIT 25
#else
#define MEM_LIMIT 50
#endif /* ^!__x86_64__ */
#endif /* ^!WORD_SIZE_64 */
/* Default memory limit when running in QEMU mode (MB): */

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - debug / error handling macros
----------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - forkserver header
----------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>

View File

@ -12,7 +12,7 @@
Austin's original code is public domain.
Other code written and maintained by Michal Zalewski <lcamtuf@google.com>
Other code written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - shared memory related header
---------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - type definitions and minor macros
--------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -79,9 +79,21 @@ typedef int64_t s64;
})
#ifdef AFL_LLVM_PASS
#if defined(__linux__)
#define AFL_SR(s) (srandom(s))
#define AFL_R(x) (random() % (x))
#else
#define AFL_SR(s) ((void)s)
#define AFL_R(x) (arc4random_uniform(x))
#endif
#else
#if defined(__linux__)
#define SR(s) (srandom(s))
#define R(x) (random() % (x))
#else
#define SR(s) ((void)s)
#define R(x) (arc4random_uniform(x))
#endif
#endif /* ^AFL_LLVM_PASS */
#define STRINGIFY_INTERNAL(x) #x

View File

@ -2,7 +2,7 @@
# american fuzzy lop - libdislocator
# ----------------------------------
#
# Written by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2016 Google Inc. All rights reserved.
#
@ -21,8 +21,13 @@ VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
CFLAGS ?= -O3 -funroll-loops -I ../include/
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
ifdef USEHUGEPAGE
CFLAGS += -DUSEHUGEPAGE
endif
all: libdislocator.so
VPATH = ..
libdislocator.so: libdislocator.so.c ../config.h
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
@ -33,6 +38,7 @@ clean:
rm -f ../libdislocator.so
install: all
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
install -m 644 README.dislocator $${DESTDIR}$(HELPER_PATH)
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)

View File

@ -25,6 +25,8 @@ heap-related security bugs in several ways:
- It checks for calloc() overflows and can cause soft or hard failures
of alloc requests past a configurable memory limit (AFL_LD_LIMIT_MB,
AFL_LD_HARD_FAIL).
- Optionally, in platforms supporting it, huge pages can be used by passing
USEHUGEPAGE=1 to make.
Basically, it is inspired by some of the non-default options available for the
OpenBSD allocator - see malloc.conf(5) on that platform for reference. It is

View File

@ -3,7 +3,7 @@
american fuzzy lop - dislocator, an abusive allocator
-----------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.
@ -14,7 +14,7 @@
http://www.apache.org/licenses/LICENSE-2.0
This is a companion library that can be used as a drop-in replacement
for the libc allocator in the fuzzed binaries. See README.dislocator for
for the libc allocator in the fuzzed binaries. See README.dislocator.md for
more info.
*/
@ -23,8 +23,41 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
#ifdef __APPLE__
#include <mach/vm_statistics.h>
#endif
#ifdef __linux__
#include <unistd.h>
#include <sys/syscall.h>
#ifdef __NR_getrandom
#define arc4random_buf(p, l) \
do { \
\
ssize_t rd = syscall(__NR_getrandom, p, l, 0); \
if (rd != l) DEBUGF("getrandom failed"); \
\
} while (0)
#else
#include <time.h>
#define arc4random_buf(p, l) \
do { \
\
srand(time(NULL)); \
u32 i; \
u8* ptr = (u8*)p; \
for (i = 0; i < l; i++) \
ptr[i] = rand() % INT_MAX; \
\
} while (0)
#endif
#endif
#include "config.h"
#include "types.h"
@ -36,6 +69,8 @@
#define MAP_ANONYMOUS MAP_ANON
#endif /* !MAP_ANONYMOUS */
#define SUPER_PAGE_SIZE 1 << 21
/* Error / message handling: */
#define DEBUGF(_x...) \
@ -88,9 +123,14 @@ static u8 alloc_verbose, /* Additional debug messages */
hard_fail, /* abort() when max_mem exceeded? */
no_calloc_over; /* abort() on calloc() overflows? */
#if defined __OpenBSD__ || defined __APPLE__
#define __thread
#warning no thread support available
#endif
static __thread size_t total_mem; /* Currently allocated mem */
static __thread u32 call_depth; /* To avoid recursion via fprintf() */
static u32 alloc_canary;
/* This is the main alloc function. It allocates one page more than necessary,
sets that tailing page to PROT_NONE, and then increments the return address
@ -99,7 +139,9 @@ static __thread u32 call_depth; /* To avoid recursion via fprintf() */
static void* __dislocator_alloc(size_t len) {
void* ret;
void* ret;
size_t tlen;
int flags, fd, sp;
if (total_mem + len > max_mem || total_mem + len < total_mem) {
@ -111,13 +153,45 @@ static void* __dislocator_alloc(size_t len) {
}
tlen = (1 + PG_COUNT(len + 8)) * PAGE_SIZE;
flags = MAP_PRIVATE | MAP_ANONYMOUS;
fd = -1;
#if defined(USEHUGEPAGE)
sp = (len >= SUPER_PAGE_SIZE && !(len % SUPER_PAGE_SIZE));
#if defined(__APPLE__)
if (sp) fd = VM_FLAGS_SUPERPAGE_SIZE_2MB;
#elif defined(__linux__)
if (sp) flags |= MAP_HUGETLB;
#elif defined(__FreeBSD__)
if (sp) flags |= MAP_ALIGNED_SUPER;
#endif
#else
(void)sp;
#endif
/* We will also store buffer length and a canary below the actual buffer, so
let's add 8 bytes for that. */
ret = mmap(NULL, (1 + PG_COUNT(len + 8)) * PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ret = mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0);
#if defined(USEHUGEPAGE)
/* We try one more time with regular call */
if (ret == MAP_FAILED) {
if (ret == (void*)-1) {
#if defined(__APPLE__)
fd = -1;
#elif defined(__linux__)
flags &= -MAP_HUGETLB;
#elif defined(__FreeBSD__)
flags &= -MAP_ALIGNED_SUPER;
#endif
ret = mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0);
}
#endif
if (ret == MAP_FAILED) {
if (hard_fail) FATAL("mmap() failed on alloc (OOM?)");
@ -142,7 +216,7 @@ static void* __dislocator_alloc(size_t len) {
ret += 8;
PTR_L(ret) = len;
PTR_C(ret) = ALLOC_CANARY;
PTR_C(ret) = alloc_canary;
total_mem += len;
@ -184,6 +258,10 @@ void* calloc(size_t elem_len, size_t elem_cnt) {
}
/* TODO: add a wrapper for posix_memalign, otherwise apps who use it,
will fail when freeing the memory.
*/
/* The wrapper for malloc(). Roughly the same, also clobbers the returned
memory (unlike calloc(), malloc() is not guaranteed to return zeroed
memory). */
@ -214,7 +292,7 @@ void free(void* ptr) {
if (!ptr) return;
if (PTR_C(ptr) != ALLOC_CANARY) FATAL("bad allocator canary on free()");
if (PTR_C(ptr) != alloc_canary) FATAL("bad allocator canary on free()");
len = PTR_L(ptr);
@ -243,7 +321,7 @@ void* realloc(void* ptr, size_t len) {
if (ret && ptr) {
if (PTR_C(ptr) != ALLOC_CANARY) FATAL("bad allocator canary on realloc()");
if (PTR_C(ptr) != alloc_canary) FATAL("bad allocator canary on realloc()");
memcpy(ret, ptr, MIN(len, PTR_L(ptr)));
free(ptr);
@ -256,17 +334,86 @@ void* realloc(void* ptr, size_t len) {
}
/* posix_memalign we mainly check the proper alignment argument
if the requested size fits within the alignment we do
a normal request */
int posix_memalign(void** ptr, size_t align, size_t len) {
// if (*ptr == NULL) return EINVAL; // (andrea) Why? I comment it out for now
if ((align % 2) || (align % sizeof(void*))) return EINVAL;
if (len == 0) {
*ptr = NULL;
return 0;
}
size_t rem = len % align;
if (rem) len += align - rem;
*ptr = __dislocator_alloc(len);
if (*ptr && len) memset(*ptr, ALLOC_CLOBBER, len);
DEBUGF("posix_memalign(%p %zu, %zu) [*ptr = %p]", ptr, align, len, *ptr);
return 0;
}
/* just the non-posix fashion */
void* memalign(size_t align, size_t len) {
void* ret = NULL;
if (posix_memalign(&ret, align, len)) {
DEBUGF("memalign(%zu, %zu) failed", align, len);
}
return ret;
}
/* sort of C11 alias of memalign only more severe, alignment-wise */
void* aligned_alloc(size_t align, size_t len) {
void* ret = NULL;
if ((len % align)) return NULL;
if (posix_memalign(&ret, align, len)) {
DEBUGF("aligned_alloc(%zu, %zu) failed", align, len);
}
return ret;
}
__attribute__((constructor)) void __dislocator_init(void) {
u8* tmp = getenv("AFL_LD_LIMIT_MB");
u8* tmp = (u8*)getenv("AFL_LD_LIMIT_MB");
if (tmp) {
max_mem = atoi(tmp) * 1024 * 1024;
if (!max_mem) FATAL("Bad value for AFL_LD_LIMIT_MB");
u8* tok;
s32 mmem = (s32)strtol((char*)tmp, (char**)&tok, 10);
if (*tok != '\0' || errno == ERANGE) FATAL("Bad value for AFL_LD_LIMIT_MB");
max_mem = mmem * 1024 * 1024;
}
alloc_canary = ALLOC_CANARY;
tmp = (u8*)getenv("AFL_RANDOM_ALLOC_CANARY");
if (tmp) arc4random_buf(&alloc_canary, sizeof(alloc_canary));
alloc_verbose = !!getenv("AFL_LD_VERBOSE");
hard_fail = !!getenv("AFL_LD_HARD_FAIL");
no_calloc_over = !!getenv("AFL_LD_NO_CALLOC_OVER");

View File

@ -2,7 +2,7 @@
# american fuzzy lop - libtokencap
# --------------------------------
#
# Written by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2016 Google Inc. All rights reserved.
#
@ -23,9 +23,28 @@ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
ifeq "$(shell uname)" "Linux"
TARGETS = libtokencap.so
LDFLAGS += -ldl
endif
ifeq "$(shell uname)" "Darwin"
TARGETS = libtokencap.so
LDFLAGS += -ldl
endif
ifeq "$(shell uname)" "FreeBSD"
TARGETS = libtokencap.so
endif
ifeq "$(shell uname)" "OpenBSD"
TARGETS = libtokencap.so
endif
ifeq "$(shell uname)" "NetBSD"
TARGETS = libtokencap.so
endif
ifeq "$(shell uname)" "DragonFly"
TARGETS = libtokencap.so
LDFLAGS += -ldl
endif
all: $(TARGETS)
VPATH = ..
libtokencap.so: libtokencap.so.c ../config.h
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
@ -36,6 +55,7 @@ clean:
rm -f ../libtokencap.so
install: all
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
install -m 644 README.tokencap $${DESTDIR}$(HELPER_PATH)
install -m 644 README.tokencap.md $${DESTDIR}$(HELPER_PATH)

View File

@ -2,7 +2,7 @@
(See ../docs/README for the general instruction manual.)
This Linux-only companion library allows you to instrument `strcmp()`, `memcmp()`,
This companion library allows you to instrument `strcmp()`, `memcmp()`,
and related functions to automatically extract syntax tokens passed to any of
these libcalls. The resulting list of tokens may be then given as a starting
dictionary to afl-fuzz (the -x option) to improve coverage on subsequent
@ -55,9 +55,10 @@ If you don't get any results, the target library is probably not using strcmp()
and memcmp() to parse input; or you haven't compiled it with -fno-builtin; or
the whole thing isn't dynamically linked, and LD_PRELOAD is having no effect.
PS. The library is Linux-only because there is probably no particularly portable
and non-invasive way to distinguish between read-only and read-write memory
mappings. The `__tokencap_load_mappings()` function is the only thing that would
need to be changed for other OSes. Porting to platforms with /proc/<pid>/maps
(e.g., FreeBSD) should be trivial.
Portability hints: There is probably no particularly portable and non-invasive
way to distinguish between read-only and read-write memory mappings.
The `__tokencap_load_mappings()` function is the only thing that would
need to be changed for other OSes.
Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen)

View File

@ -3,7 +3,7 @@
american fuzzy lop - extract tokens passed to strcmp / memcmp
-------------------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.
@ -15,20 +15,55 @@
This Linux-only companion library allows you to instrument strcmp(),
memcmp(), and related functions to automatically extract tokens.
See README.tokencap for more info.
See README.tokencap.md for more info.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include "../types.h"
#include "../config.h"
#ifndef __linux__
#error "Sorry, this library is Linux-specific for now!"
#endif /* !__linux__ */
#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ && \
!defined __OpenBSD__ && !defined __NetBSD__ && !defined __DragonFly__
#error "Sorry, this library is unsupported in this platform for now!"
#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && \
!__NetBSD__*/
#if defined __APPLE__
#include <mach/vm_map.h>
#include <mach/mach_init.h>
#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/mman.h>
#endif
#include <dlfcn.h>
#ifdef RTLD_NEXT
/* The libc functions are a magnitude faster than our replacements.
Use them when RTLD_NEXT is available. */
int (*__libc_strcmp)(const char* str1, const char* str2);
int (*__libc_strncmp)(const char* str1, const char* str2, size_t len);
int (*__libc_strcasecmp)(const char* str1, const char* str2);
int (*__libc_strncasecmp)(const char* str1, const char* str2, size_t len);
int (*__libc_memcmp)(const void* mem1, const void* mem2, size_t len);
int (*__libc_bcmp)(const void* mem1, const void* mem2, size_t len);
char* (*__libc_strstr)(const char* haystack, const char* needle);
char* (*__libc_strcasestr)(const char* haystack, const char* needle);
void* (*__libc_memmem)(const void* haystack, size_t haystack_len,
const void* needle, size_t needle_len);
#endif
/* Mapping data and such */
@ -38,7 +73,8 @@ static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS];
static u32 __tokencap_ro_cnt;
static u8 __tokencap_ro_loaded;
static FILE* __tokencap_out_file;
static int __tokencap_out_file = -1;
static pid_t __tokencap_pid = -1;
/* Identify read-only regions in memory. Only parameters that fall into these
ranges are worth dumping when passed to strcmp() and so on. Read-write
@ -46,6 +82,8 @@ static FILE* __tokencap_out_file;
static void __tokencap_load_mappings(void) {
#if defined __linux__
u8 buf[MAX_LINE];
FILE* f = fopen("/proc/self/maps", "r");
@ -70,6 +108,124 @@ static void __tokencap_load_mappings(void) {
fclose(f);
#elif defined __APPLE__
struct vm_region_submap_info_64 region;
mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64;
vm_address_t base = 0;
vm_size_t size = 0;
natural_t depth = 0;
__tokencap_ro_loaded = 1;
while (1) {
if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth,
(vm_region_info_64_t)&region,
&cnt) != KERN_SUCCESS)
break;
if (region.is_submap) {
depth++;
} else {
/* We only care of main map addresses and the read only kinds */
if ((region.protection & VM_PROT_READ) &&
!(region.protection & VM_PROT_WRITE)) {
__tokencap_ro[__tokencap_ro_cnt].st = (void*)base;
__tokencap_ro[__tokencap_ro_cnt].en = (void*)(base + size);
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
}
}
}
#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
#if defined __FreeBSD__
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid};
#elif defined __OpenBSD__
int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid};
#elif defined __NetBSD__
int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid,
sizeof(struct kinfo_vmentry)};
#endif
char * buf, *low, *high;
size_t miblen = sizeof(mib) / sizeof(mib[0]);
size_t len;
if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) return;
#if defined __FreeBSD__ || defined __NetBSD__
len = len * 4 / 3;
#elif defined __OpenBSD__
len -= len % sizeof(struct kinfo_vmentry);
#endif
buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (buf == MAP_FAILED) return;
if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) {
munmap(buf, len);
return;
}
low = buf;
high = low + len;
__tokencap_ro_loaded = 1;
while (low < high) {
struct kinfo_vmentry* region = (struct kinfo_vmentry*)low;
#if defined __FreeBSD__ || defined __NetBSD__
#if defined __FreeBSD__
size_t size = region->kve_structsize;
if (size == 0) break;
#elif defined __NetBSD__
size_t size = sizeof(*region);
#endif
/* We go through the whole mapping of the process and track read-only
* addresses */
if ((region->kve_protection & KVME_PROT_READ) &&
!(region->kve_protection & KVME_PROT_WRITE)) {
#elif defined __OpenBSD__
size_t size = sizeof(*region);
/* We go through the whole mapping of the process and track read-only
* addresses */
if ((region->kve_protection & KVE_PROT_READ) &&
!(region->kve_protection & KVE_PROT_WRITE)) {
#endif
__tokencap_ro[__tokencap_ro_cnt].st = (void*)region->kve_start;
__tokencap_ro[__tokencap_ro_cnt].en = (void*)region->kve_end;
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
}
low += size;
}
munmap(buf, len);
#endif
}
/* Check an address against the list of read-only mappings. */
@ -96,7 +252,7 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
u32 i;
u32 pos = 0;
if (len < MIN_AUTO_EXTRA || len > MAX_AUTO_EXTRA || !__tokencap_out_file)
if (len < MIN_AUTO_EXTRA || len > MAX_AUTO_EXTRA || __tokencap_out_file == -1)
return;
for (i = 0; i < len; i++) {
@ -122,7 +278,9 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
buf[pos] = 0;
fprintf(__tokencap_out_file, "\"%s\"\n", buf);
int wrt_ok = (1 == write(__tokencap_out_file, "\"", 1));
wrt_ok &= (pos == write(__tokencap_out_file, buf, pos));
wrt_ok &= (2 == write(__tokencap_out_file, "\"\n", 2));
}
@ -136,9 +294,13 @@ int strcmp(const char* str1, const char* str2) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
#ifdef RTLD_NEXT
if (__libc_strcmp) return __libc_strcmp(str1, str2);
#endif
while (1) {
unsigned char c1 = *str1, c2 = *str2;
const unsigned char c1 = *str1, c2 = *str2;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
@ -156,6 +318,10 @@ int strncmp(const char* str1, const char* str2, size_t len) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
#ifdef RTLD_NEXT
if (__libc_strncmp) return __libc_strncmp(str1, str2, len);
#endif
while (len--) {
unsigned char c1 = *str1, c2 = *str2;
@ -178,9 +344,13 @@ int strcasecmp(const char* str1, const char* str2) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
#ifdef RTLD_NEXT
if (__libc_strcasecmp) return __libc_strcasecmp(str1, str2);
#endif
while (1) {
unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
@ -198,9 +368,13 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
#ifdef RTLD_NEXT
if (__libc_strncasecmp) return __libc_strncasecmp(str1, str2, len);
#endif
while (len--) {
unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
if (!c1) return 0;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
@ -220,12 +394,46 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
#ifdef RTLD_NEXT
if (__libc_memcmp) return __libc_memcmp(mem1, mem2, len);
#endif
const char* strmem1 = (const char*)mem1;
const char* strmem2 = (const char*)mem2;
while (len--) {
unsigned char c1 = *(const char*)mem1, c2 = *(const char*)mem2;
const unsigned char c1 = *strmem1, c2 = *strmem2;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
mem1++;
mem2++;
strmem1++;
strmem2++;
}
return 0;
}
#undef bcmp
int bcmp(const void* mem1, const void* mem2, size_t len) {
if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
#ifdef RTLD_NEXT
if (__libc_bcmp) return __libc_bcmp(mem1, mem2, len);
#endif
const char* strmem1 = (const char*)mem1;
const char* strmem2 = (const char*)mem2;
while (len--) {
int diff = *strmem1 ^ *strmem2;
if (diff != 0) return 1;
strmem1++;
strmem2++;
}
@ -242,6 +450,10 @@ char* strstr(const char* haystack, const char* needle) {
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
#ifdef RTLD_NEXT
if (__libc_strstr) return __libc_strstr(haystack, needle);
#endif
do {
const char* n = needle;
@ -267,6 +479,10 @@ char* strcasestr(const char* haystack, const char* needle) {
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
#ifdef RTLD_NEXT
if (__libc_strcasestr) return __libc_strcasestr(haystack, needle);
#endif
do {
const char* n = needle;
@ -283,13 +499,235 @@ char* strcasestr(const char* haystack, const char* needle) {
}
#undef memmem
void* memmem(const void* haystack, size_t haystack_len, const void* needle,
size_t needle_len) {
if (__tokencap_is_ro(haystack)) __tokencap_dump(haystack, haystack_len, 1);
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, needle_len, 1);
#ifdef RTLD_NEXT
if (__libc_memmem)
return __libc_memmem(haystack, haystack_len, needle, needle_len);
#endif
const char* n = (const char*)needle;
const char* h = (const char*)haystack;
if (haystack_len < needle_len) return 0;
if (needle_len == 0) return (void*)haystack;
if (needle_len == 1) return memchr(haystack, *n, haystack_len);
const char* end = h + (haystack_len - needle_len);
do {
if (*h == *n) {
if (memcmp(h, n, needle_len) == 0) return (void*)h;
}
} while (h++ <= end);
return 0;
}
/* Common libraries wrappers (from honggfuzz) */
/*
* Apache's httpd wrappers
*/
int ap_cstr_casecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
const char* ap_strcasestr(const char* s1, const char* s2) {
return strcasestr(s1, s2);
}
int apr_cstr_casecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
/*
* *SSL wrappers
*/
int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) {
return memcmp(m1, m2, len);
}
int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) {
return memcmp(m1, m2, len);
}
int OPENSSL_strcasecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) {
return strncasecmp(s1, s2, len);
}
int32_t memcmpct(const void* s1, const void* s2, size_t len) {
return memcmp(s1, s2, len);
}
/*
* libXML wrappers
*/
int xmlStrncmp(const char* s1, const char* s2, int len) {
if (len <= 0) { return 0; }
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strncmp(s1, s2, (size_t)len);
}
int xmlStrcmp(const char* s1, const char* s2) {
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strcmp(s1, s2);
}
int xmlStrEqual(const char* s1, const char* s2) {
if (s1 == s2) { return 1; }
if (s1 == NULL) { return 0; }
if (s2 == NULL) { return 0; }
if (strcmp(s1, s2) == 0) { return 1; }
return 0;
}
int xmlStrcasecmp(const char* s1, const char* s2) {
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strcasecmp(s1, s2);
}
int xmlStrncasecmp(const char* s1, const char* s2, int len) {
if (len <= 0) { return 0; }
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strncasecmp(s1, s2, (size_t)len);
}
const char* xmlStrstr(const char* haystack, const char* needle) {
if (haystack == NULL) { return NULL; }
if (needle == NULL) { return NULL; }
return strstr(haystack, needle);
}
const char* xmlStrcasestr(const char* haystack, const char* needle) {
if (haystack == NULL) { return NULL; }
if (needle == NULL) { return NULL; }
return strcasestr(haystack, needle);
}
/*
* Samba wrappers
*/
int memcmp_const_time(const void* s1, const void* s2, size_t n) {
return memcmp(s1, s2, n);
}
bool strcsequal(const void* s1, const void* s2) {
if (s1 == s2) { return true; }
if (!s1 || !s2) { return false; }
return (strcmp(s1, s2) == 0);
}
/* bcmp/memcmp BSD flavors, similar to CRYPTO_memcmp */
int timingsafe_bcmp(const void* mem1, const void* mem2, size_t len) {
return bcmp(mem1, mem2, len);
}
int timingsafe_memcmp(const void* mem1, const void* mem2, size_t len) {
return memcmp(mem1, mem2, len);
}
/* Init code to open the output file (or default to stderr). */
__attribute__((constructor)) void __tokencap_init(void) {
u8* fn = getenv("AFL_TOKEN_FILE");
if (fn) __tokencap_out_file = fopen(fn, "a");
if (!__tokencap_out_file) __tokencap_out_file = stderr;
if (fn) __tokencap_out_file = open(fn, O_RDWR | O_CREAT | O_APPEND, 0655);
if (__tokencap_out_file == -1) __tokencap_out_file = STDERR_FILENO;
__tokencap_pid = getpid();
#ifdef RTLD_NEXT
__libc_strcmp = dlsym(RTLD_NEXT, "strcmp");
__libc_strncmp = dlsym(RTLD_NEXT, "strncmp");
__libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp");
__libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp");
__libc_memcmp = dlsym(RTLD_NEXT, "memcmp");
__libc_bcmp = dlsym(RTLD_NEXT, "bcmp");
__libc_strstr = dlsym(RTLD_NEXT, "strstr");
__libc_strcasestr = dlsym(RTLD_NEXT, "strcasestr");
__libc_memmem = dlsym(RTLD_NEXT, "memmem");
#endif
}
/* closing as best as we can the tokens file */
__attribute__((destructor)) void __tokencap_shutdown(void) {
if (__tokencap_out_file != STDERR_FILENO) close(__tokencap_out_file);
}

View File

@ -13,6 +13,7 @@
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/DebugInfo.h"
@ -146,6 +147,9 @@ struct InsTrim : public ModulePass {
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
GlobalVariable::GeneralDynamicTLSModel, 0, false);
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
u64 total_rs = 0;
u64 total_hs = 0;
@ -155,9 +159,10 @@ struct InsTrim : public ModulePass {
if (!myWhitelist.empty()) {
bool instrumentBlock = false;
DebugLoc Loc;
StringRef instFilename;
bool instrumentBlock = false;
DebugLoc Loc;
StringRef instFilename;
unsigned int instLine = 0;
for (auto &BB : F) {
@ -171,7 +176,7 @@ struct InsTrim : public ModulePass {
DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
unsigned int instLine = cDILoc->getLine();
instLine = cDILoc->getLine();
instFilename = cDILoc->getFilename();
if (instFilename.str().empty()) {
@ -217,11 +222,18 @@ struct InsTrim : public ModulePass {
* not whitelisted, so we skip instrumentation. */
if (!instrumentBlock) {
if (!instFilename.str().empty())
SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s ...\n",
instFilename.str().c_str());
else
SAYF(cYEL "[!] " cBRI "No filename information found, skipping it");
if (!be_quiet) {
if (!instFilename.str().empty())
SAYF(cYEL "[!] " cBRI
"Not in whitelist, skipping %s line %u...\n",
instFilename.str().c_str(), instLine);
else
SAYF(cYEL "[!] " cBRI
"No filename information found, skipping it");
}
continue;
}
@ -365,7 +377,7 @@ struct InsTrim : public ModulePass {
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
Value *Incr = IRB.CreateAdd(Counter, One);
#if LLVM_VERSION_MAJOR < 9
if (neverZero_counters_str !=
@ -387,7 +399,7 @@ struct InsTrim : public ModulePass {
* Counter + 1 -> {Counter, OverflowFlag}
* Counter + OverflowFlag -> Counter
*/
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
auto cf = IRB.CreateICmpEQ(Incr, Zero);
auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry);

View File

@ -3,7 +3,7 @@
# -----------------------------------------
#
# Written by Laszlo Szekeres <lszekeres@google.com> and
# Michal Zalewski <lcamtuf@google.com>
# Michal Zalewski
#
# LLVM integration design comes from Laszlo Szekeres.
#
@ -29,30 +29,45 @@ ifeq "$(shell uname)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
ifeq "$(HAS_OPT)" "1"
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 9) -> e.g. "pkg_add llvm-7.0.1p9")
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 10) -> e.g. "pkg_add llvm-7.0.1p9")
endif
else
LLVM_CONFIG ?= llvm-config
endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[12]|^3\.0|^1[0-9]' && echo 1 || echo 0 )
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[1-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_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_STDCXX = gnu++11
LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
ifeq "$(LLVM_UNSUPPORTED)" "1"
$(warn llvm_mode only supports versions 3.8.0 up to 9)
ifeq "$(LLVMVER)" ""
$(warning llvm_mode needs llvm-config, which was not found)
endif
ifeq "$(LLVM_UNSUPPORTED)" "1"
$(warning llvm_mode only supports llvm versions 3.8.0 up to 10)
endif
# this is not visible yet:
ifeq "$(LLVM_MAJOR)" "9"
$(info llvm_mode detected llvm 9, enabling neverZero implementation)
endif
ifeq "$(LLVM_NEW_API)" "1"
$(info llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
LLVM_STDCXX = c++14
endif
ifeq "$(LLVM_APPLE)" "1"
$(warning llvm_mode will not compile with Xcode clang...)
endif
CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-DVERSION=\"$(VERSION)\"
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\"
ifdef AFL_TRACE_PC
CFLAGS += -DUSE_TRACE_PC=1
endif
@ -89,7 +104,7 @@ ifeq "$(shell test -e $(CC) || echo 1 )" "1"
CXX = $(BIN_DIR)/clang++
else
# hope for the best
$(warn we have trouble finding clang/clang++ - llvm-config is not helping us)
$(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
CC = clang
CXX = clang++
endif
@ -100,7 +115,7 @@ endif
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
SHMAT_OK=1
else
SHMAT_OK=0
@ -121,12 +136,26 @@ else
endif
ifneq "$(CLANGVER)" "$(LLVMVER)"
CC = $(shell llvm-config --bindir)/clang
CXX = $(shell llvm-config --bindir)/clang++
CC = $(shell $(LLVM_CONFIG) --bindir)/clang
CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
endif
all: test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
# If prerequisites are not given, warn, do not build anything, and exit with code 0
ifeq "$(LLVMVER)" ""
NO_BUILD = 1
endif
ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
NO_BUILD = 1
endif
ifeq "$(NO_BUILD)" "1"
TARGETS = no_build
else
TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
endif
all: $(TARGETS)
ifeq "$(SHMAT_OK)" "1"
@ -141,11 +170,15 @@ test_shm:
endif
no_build:
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
test_deps:
ifndef AFL_TRACE_PC
@echo "[*] Checking for working 'llvm-config'..."
ifneq "$(LLVM_APPLE)" "1"
@which $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
endif
else
@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
endif
@ -167,10 +200,10 @@ endif
ln -sf afl-clang-fast ../afl-clang-fast++
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=gnu++11 -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=gnu++11 -shared $< -o $@ $(CLANG_LFL)
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
# laf
../split-switches-pass.so: split-switches-pass.so.cc | test_deps
@ -220,7 +253,7 @@ vpath % ..
@../$* -h 2>&1 | tail -n +4 >> ../$@
@echo >> ../$@
@echo .SH AUTHOR >> ../$@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexc0der\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> ../$@
@echo >> ../$@
@echo .SH LICENSE >> ../$@

View File

@ -35,4 +35,5 @@ bit_width may be 64, 32 or 16.
A new experimental feature is splitting floating point comparisons into a
series of sign, exponent and mantissa comparisons followed by splitting each
of them into 8 bit comparisons when necessary.
It is activated with the `AFL_LLVM_LAF_SPLIT_COMPARES` setting.
It is activated with the `AFL_LLVM_LAF_SPLIT_FLOATS` setting, available only
when `AFL_LLVM_LAF_SPLIT_COMPARES` is set.

View File

@ -5,7 +5,7 @@
## 1) Introduction
! llvm_mode works with llvm versions 3.8.0 up to 9 !
! llvm_mode works with llvm versions 3.8.0 up to 10 !
The code in this directory allows you to instrument programs for AFL using
true compiler-level instrumentation, instead of the more crude

View File

@ -64,7 +64,7 @@ a2.cpp
but it might lead to files being unwantedly instrumented if the same filename
exists somewhere else in the project directories.
The created whitelist file is then set to AFL_INST_WHITELIST when you compile
The created whitelist file is then set to AFL_LLVM_WHITELIST when you compile
your program. For each file that didn't match the whitelist, the compiler will
issue a warning at the end stating that no blocks were instrumented. If you
didn't intend to instrument that file, then you can safely ignore that warning.

View File

@ -3,7 +3,7 @@
------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres.
@ -32,11 +32,13 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
static u8* obj_path; /* Path to runtime libraries */
static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
static u8 llvm_fullpath[PATH_MAX];
/* Try to find the runtime libraries. If that fails, abort. */
@ -47,7 +49,11 @@ static void find_obj(u8* argv0) {
if (afl_path) {
#ifdef __ANDROID__
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
#else
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);
#endif
if (!access(tmp, R_OK)) {
@ -71,7 +77,11 @@ static void find_obj(u8* argv0) {
dir = ck_strdup(argv0);
*slash = '/';
#ifdef __ANDROID__
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
#else
tmp = alloc_printf("%s/afl-llvm-rt.o", dir);
#endif
if (!access(tmp, R_OK)) {
@ -86,8 +96,14 @@ static void find_obj(u8* argv0) {
}
#ifdef __ANDROID__
if (!access(AFL_PATH "/afl-llvm-rt.so", R_OK)) {
#else
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
#endif
obj_path = AFL_PATH;
return;
@ -104,6 +120,7 @@ static void find_obj(u8* argv0) {
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0;
u8 has_llvm_config = 0;
u8* name;
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
@ -112,23 +129,33 @@ static void edit_params(u32 argc, char** argv) {
if (!name)
name = argv[0];
else
name++;
++name;
has_llvm_config = (strlen(LLVM_BINDIR) > 0);
if (!strcmp(name, "afl-clang-fast++")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";
if (has_llvm_config)
snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", LLVM_BINDIR);
else
sprintf(llvm_fullpath, "clang++");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)llvm_fullpath;
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";
if (has_llvm_config)
snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", LLVM_BINDIR);
else
sprintf(llvm_fullpath, "clang");
cc_params[0] = alt_cc ? alt_cc : (u8*)llvm_fullpath;
}
/* There are three ways to compile with afl-clang-fast. In the traditional
mode, we use afl-llvm-pass.so, then there is libLLVMInsTrim.so which is
much faster but has less coverage. Finally tere is the experimental
much faster but has less coverage. Finally there is the experimental
'trace-pc-guard' mode, we use native LLVM instrumentation callbacks
instead. For trace-pc-guard see:
http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards
@ -196,6 +223,7 @@ static void edit_params(u32 argc, char** argv) {
u8* cur = *(++argv);
if (!strcmp(cur, "-m32")) bit_mode = 32;
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
if (!strcmp(cur, "-x")) x_set = 1;
@ -273,6 +301,9 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
}
@ -341,6 +372,7 @@ static void edit_params(u32 argc, char** argv) {
}
#ifndef __ANDROID__
switch (bit_mode) {
case 0:
@ -365,6 +397,8 @@ static void edit_params(u32 argc, char** argv) {
}
#endif
}
cc_params[cc_par_cnt] = NULL;
@ -424,7 +458,9 @@ int main(int argc, char** argv) {
}
#ifndef __ANDROID__
find_obj(argv[0]);
#endif
edit_params(argc, argv);

View File

@ -3,7 +3,7 @@
---------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
from afl-as.c are Michal's fault.
@ -34,6 +34,7 @@
#include <list>
#include <string>
#include <fstream>
#include <sys/time.h>
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/BasicBlock.h"
@ -93,9 +94,17 @@ bool AFLCoverage::runOnModule(Module &M) {
LLVMContext &C = M.getContext();
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
unsigned int cur_loc = 0;
IntegerType * Int8Ty = IntegerType::getInt8Ty(C);
IntegerType * Int32Ty = IntegerType::getInt32Ty(C);
struct timeval tv;
struct timezone tz;
u32 rand_seed;
unsigned int cur_loc = 0;
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
AFL_SR(rand_seed);
/* Show a banner */
@ -141,6 +150,8 @@ bool AFLCoverage::runOnModule(Module &M) {
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
GlobalVariable::GeneralDynamicTLSModel, 0, false);
#endif
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
/* Instrument all the things! */
@ -181,6 +192,8 @@ bool AFLCoverage::runOnModule(Module &M) {
}
(void)instLine;
/* Continue only if we know where we actually are */
if (!instFilename.str().empty()) {
@ -276,7 +289,7 @@ bool AFLCoverage::runOnModule(Module &M) {
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
Value *Incr = IRB.CreateAdd(Counter, One);
#if LLVM_VERSION_MAJOR < 9
if (neverZero_counters_str !=
@ -320,7 +333,7 @@ bool AFLCoverage::runOnModule(Module &M) {
*/
// this is the solution we choose because llvm9 should do the right
// thing here
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
auto cf = IRB.CreateICmpEQ(Incr, Zero);
auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry);
/*

View File

@ -3,7 +3,7 @@
---------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres.

View File

@ -234,6 +234,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
sizedLen = ilen->getZExtValue();
} else {
sizedLen = 0;
}
if (HasStr1) {

View File

@ -50,6 +50,8 @@ class SplitComparesTransform : public ModulePass {
}
private:
int enableFPSplit;
size_t splitIntCompares(Module &M, unsigned bitw);
size_t splitFPCompares(Module &M);
bool simplifyCompares(Module &M);
@ -101,10 +103,11 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
}
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE) {
if (enableFPSplit &&
(selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE)) {
auto op0 = selectcmpInst->getOperand(0);
auto op1 = selectcmpInst->getOperand(1);
@ -115,6 +118,8 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
/* this is probably not needed but we do it anyway */
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
fcomps.push_back(selectcmpInst);
}
@ -465,7 +470,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLT) {
auto op0 = selectcmpInst->getOperand(0);
@ -476,6 +483,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
fcomps.push_back(selectcmpInst);
}
@ -648,6 +657,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, m_e0, m_e1);
break;
case CmpInst::FCMP_OGT:
case CmpInst::FCMP_UGT:
Instruction *icmp_exponent;
icmp_exponent =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
@ -657,6 +667,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
break;
case CmpInst::FCMP_OLT:
case CmpInst::FCMP_ULT:
icmp_exponent =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
signequal_bb->getInstList().insert(
@ -748,6 +759,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
break;
case CmpInst::FCMP_OGT:
case CmpInst::FCMP_UGT:
Instruction *icmp_fraction;
icmp_fraction =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
@ -757,6 +769,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
break;
case CmpInst::FCMP_OLT:
case CmpInst::FCMP_ULT:
icmp_fraction =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
middle_bb->getInstList().insert(
@ -795,6 +808,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
PN->addIncoming(icmp_fraction_result, middle_bb);
break;
case CmpInst::FCMP_OGT:
case CmpInst::FCMP_UGT:
/* if op1 is negative goto true branch,
else go on comparing */
PN->addIncoming(t_s1, bb);
@ -802,6 +816,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
PN->addIncoming(icmp_fraction_result, middle_bb);
break;
case CmpInst::FCMP_OLT:
case CmpInst::FCMP_ULT:
/* if op0 is negative goto true branch,
else go on comparing */
PN->addIncoming(t_s0, bb);
@ -1040,6 +1055,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
if (!bitw_env) bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW");
if (bitw_env) { bitw = atoi(bitw_env); }
enableFPSplit = getenv("AFL_LLVM_LAF_SPLIT_FLOATS") != NULL;
simplifyCompares(M);
simplifyIntSignedness(M);
@ -1048,8 +1065,9 @@ bool SplitComparesTransform::runOnModule(Module &M) {
errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
"heiko@hexco.de\n";
errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M)
<< " FP comparisons splitted\n";
if (enableFPSplit)
errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M)
<< " FP comparisons splitted\n";
switch (bitw) {

View File

@ -1,6 +1,9 @@
These are example and helper files for the AFL_PYTHON_MODULE feature.
See docs/python_mutators.txt for more information
Note that if you compile with python3.7 you must use python3 scripts, and if
you use pyton2.7 to compile python2 scripts!
example.py - this is the template you can use, the functions are there
but they are empty

199
qbdi_mode/README.md Executable file
View File

@ -0,0 +1,199 @@
# qbdi-based binary-only instrumentation for afl-fuzz
## 1) Introduction
The code in ./qbdi_mode allows you to build a standalone feature that
using the QBDI framework to fuzz android native library.
## 2) Build
First download the Android NDK
```
https://developer.android.com/ndk/downloads
https://dl.google.com/android/repository/android-ndk-r20-linux-x86_64.zip
```
Then unzip it and build the standalone-toolchain
For x86_64 standalone-toolchain
```
unzip android-ndk-r20-linux-x86_64.zip
cd android-ndk-r20/
./build/tools/make_standalone_toolchain.py --arch x86_64 --api 21 --install-dir ../android-standalone-toolchain-x86_64
```
For x86 standalone-toolchain
```
./build/tools/make_standalone_toolchain.py --arch x86 --api 21 --install-dir ../android-standalone-toolchain-x86
```
In alternative you can also use the prebuilt toolchain, in that case make sure to set the proper CC and CXX env variables because there are many different compilers for each API version in the prebuilt toolchain.
For example:
```
export STANDALONE_TOOLCHAIN_PATH=~/Android/Sdk/ndk/20.1.5948944/toolchains/llvm/prebuilt/linux-x86_64/
export CC=x86_64-linux-android21-clang
export CXX=x86_64-linux-android21-clang++
```
Then download the QBDI SDK from website
```
https://qbdi.quarkslab.com/
```
For Android x86_64
```
https://github.com/QBDI/QBDI/releases/download/v0.7.0/QBDI-0.7.0-android-X86_64.tar.gz
```
Then decompress the sdk
```
mkdir android-qbdi-sdk-x86_64
cp QBDI-0.7.0-android-X86_64.tar.gz android-qbdi-sdk-x86_64/
cd android-qbdi-sdk-x86_64/
tar xvf QBDI-0.7.0-android-X86_64.tar.gz
```
Now set the `STANDALONE_TOOLCHAIN_PATH` to the path of standalone-toolchain
```
export STANDALONE_TOOLCHAIN_PATH=/home/hac425/workspace/android-standalone-toolchain-x86_64
```
set the `QBDI_SDK_PATH` to the path of QBDI SDK
```
export QBDI_SDK_PATH=/home/hac425/workspace/AFLplusplus/qbdi_mode/android-qbdi-sdk-x86_64/
```
Then run the build.sh
```
./build.sh x86_64
```
this could build the afl-fuzz and also the qbdi template for android x86_64
### Example
The demo-so.c is an vulnerable library, it has a function for test
```c
int target_func(char *buf, int size) {
printf("buffer:%p, size:%p\n", buf, size);
switch (buf[0]) {
case 1:
puts("222");
if (buf[1] == '\x44') {
puts("null ptr deference");
*(char *)(0) = 1;
}
break;
case 0xff:
if (buf[2] == '\xff') {
if (buf[1] == '\x44') {
puts("crash....");
*(char *)(0xdeadbeef) = 1;
}
}
break;
default: puts("default action"); break;
}
return 1;
}
```
This could be build to `libdemo.so`.
Then we should load the library in template.cpp and find the `target` function address.
```c
void *handle = dlopen(lib_path, RTLD_LAZY);
..........................................
..........................................
..........................................
p_target_func = (target_func)dlsym(handle, "target_func");
```
then we read the data from file and call the function in `fuzz_func`
```c
QBDI_NOINLINE int fuzz_func() {
if (afl_setup()) { afl_forkserver(); }
/* Read the input from file */
unsigned long len = 0;
char * data = read_file(input_pathname, &len);
/* Call the target function with the input data */
p_target_func(data, len);
return 1;
}
```
Just compile it
```
./build.sh x86_64
```
Then push the `afl-fuzz`, `loader`, `libdemo.so`, the `libQBDI.so` from the QBDI SDK and the `libc++_shared.so` from android-standalone-toolchain to android device
```
adb push afl-fuzz /data/local/tmp
adb push libdemo.so /data/local/tmp
adb push loader /data/local/tmp
adb push android-qbdi-sdk-x86_64/usr/local/lib/libQBDI.so /data/local/tmp
adb push ../../android-standalone-toolchain-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so
/data/local/tmp
```
In android adb shell, run the loader to test if it runs
```
cd /data/local/tmp
export LD_LIBRARY_PATH=/data/local/tmp
mkdir in
echo 0000 > in/1
./loader libdemo.so in/1
p_target_func:0x716d96a98600
offset:0x600
offset:0x580
buffer:0x716d96609050, size:0x5
offset:0x628
offset:0x646
offset:0x64b
offset:0x65c
offset:0x6df
offset:0x590
default action
offset:0x6eb
```
Now run `afl-fuzz` to fuzz the demo library
```
./afl-fuzz -i in -o out -- ./loader /data/local/tmp/libdemo.so @@
```
![screen1](assets/screen1.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

57
qbdi_mode/build.sh Executable file
View File

@ -0,0 +1,57 @@
if [ -z ${STANDALONE_TOOLCHAIN_PATH} ]; then
echo "please set the android-standalone-toolchain path in STANDALONE_TOOLCHAIN_PATH environmental variable"
echo "for example: "
echo " export STANDALONE_TOOLCHAIN_PATH=/home/android-standalone-toolchain-21/"
exit
fi
if [ -z ${QBDI_SDK_PATH} ]; then
echo "please set the qbdi sdk path in QBDI_SDK_PATH environmental variable"
echo "for example: "
echo " export QBDI_SDK_PATH=/home/QBDI-Android/"
exit
fi
if [ "$1" = "x86" ]; then
echo "build x86 qbdi"
compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/"
if [ -z ${CC} ]; then
export CC=i686-linux-android-gcc
fi
if [ -z ${CXX} ]; then
export CXX=i686-linux-android-g++
fi
elif [ "$1" = "x86_64" ]; then
echo "build x86_64 qbdi"
compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/"
if [ -z ${CC} ]; then
export CC=x86_64-linux-android-gcc
fi
if [ -z ${CXX} ]; then
export CXX=x86_64-linux-android-g++
fi
else
echo "usage: ./build.sh arch[x86, x86_64]"
exit
fi
CFLAGS="-I${QBDI_SDK_PATH}/usr/local/include/ -L${QBDI_SDK_PATH}/usr/local/lib/"
echo "[+] Building the QBDI template"
# build the qbdi template
${compiler_prefix}${CXX} -o loader template.cpp -lQBDI -ldl -w -g ${CFLAGS}
echo "[+] Building the demo library"
# build the demo share library
${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g
echo "[+] Building afl-fuzz for Android"
# build afl-fuzz
cd ..
${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w
echo "[+] All done. Enjoy!"

39
qbdi_mode/demo-so.c Executable file
View File

@ -0,0 +1,39 @@
#include <stdio.h>
// gcc -shared -o libdemo.so demo-so.c -w
int target_func(char *buf, int size) {
printf("buffer:%p, size:%p\n", buf, size);
switch (buf[0]) {
case 1:
puts("222");
if (buf[1] == '\x44') {
puts("null ptr deference");
*(char *)(0) = 1;
}
break;
case 0xff:
if (buf[2] == '\xff') {
if (buf[1] == '\x44') {
puts("crash....");
*(char *)(0xdeadbeef) = 1;
}
}
break;
default: puts("default action"); break;
}
return 1;
}

251
qbdi_mode/template.cpp Executable file
View File

@ -0,0 +1,251 @@
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <dlfcn.h>
#ifdef __ANDROID__
#include "../include/android-ashmem.h"
#endif
#include <sys/ipc.h>
#include <sys/shm.h>
#include "../config.h"
#include <QBDI.h>
/* NeverZero */
#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO)
#define INC_AFL_AREA(loc) \
asm volatile( \
"incb (%0, %1, 1)\n" \
"adcb $0, (%0, %1, 1)\n" \
: /* no out */ \
: "r"(afl_area_ptr), "r"(loc) \
: "memory", "eax")
#else
#define INC_AFL_AREA(loc) afl_area_ptr[loc]++
#endif
using namespace QBDI;
typedef int (*target_func)(char *buf, int size);
static const size_t STACK_SIZE = 0x100000; // 1MB
static const QBDI::rword FAKE_RET_ADDR = 0x40000;
target_func p_target_func = NULL;
rword module_base = 0;
rword module_end = 0;
static unsigned char
dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */
unsigned char *afl_area_ptr = NULL; /* Exported for afl_gen_trace */
unsigned long afl_prev_loc = 0;
char input_pathname[PATH_MAX];
/* Set up SHM region and initialize other stuff. */
int afl_setup(void) {
char *id_str = getenv(SHM_ENV_VAR);
int shm_id;
if (id_str) {
shm_id = atoi(id_str);
afl_area_ptr = (unsigned char *)shmat(shm_id, NULL, 0);
if (afl_area_ptr == (void *)-1) return 0;
memset(afl_area_ptr, 0, MAP_SIZE);
}
return 1;
}
/* Fork server logic, invoked once we hit _start. */
static void afl_forkserver() {
static unsigned char tmp[4];
pid_t child_pid;
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
while (1) {
int status;
u32 was_killed;
// wait for afl-fuzz
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
child_pid = fork();
if (child_pid < 0) exit(4);
if (!child_pid) {
// child return to execute code
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
return;
}
// write child pid to afl-fuzz
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
// wait child stop
if (waitpid(child_pid, &status, 0) < 0) exit(6);
// send child stop status to afl-fuzz
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
}
}
void afl_maybe_log(unsigned long cur_loc) {
if (afl_area_ptr == NULL) { return; }
unsigned long afl_idx = cur_loc ^ afl_prev_loc;
afl_idx &= MAP_SIZE - 1;
INC_AFL_AREA(afl_idx);
afl_prev_loc = cur_loc >> 1;
}
char *read_file(char *path, unsigned long *length) {
unsigned long len;
char * buf;
FILE *fp = fopen(path, "rb");
fseek(fp, 0, SEEK_END);
len = ftell(fp);
buf = (char *)malloc(len);
rewind(fp);
fread(buf, 1, len, fp);
fclose(fp);
*length = len;
return buf;
}
QBDI_NOINLINE int fuzz_func() {
if (afl_setup()) { afl_forkserver(); }
unsigned long len = 0;
char * data = read_file(input_pathname, &len);
// printf("In fuzz_func\n");
p_target_func(data, len);
return 1;
}
static QBDI::VMAction bbcallback(QBDI::VMInstanceRef vm,
const QBDI::VMState *state,
QBDI::GPRState * gprState,
QBDI::FPRState *fprState, void *data) {
// errno = SAVED_ERRNO;
#ifdef __x86_64__
unsigned long pc = gprState->rip;
#elif defined(i386)
unsigned long pc = gprState->eip;
#elif defined(__arm__)
unsigned long pc = gprState->pc;
#endif
// just log the module path
if (pc >= module_base && pc <= module_end) {
unsigned long offset = pc - module_base;
printf("\toffset:%p\n", offset);
afl_maybe_log(offset);
}
return QBDI::VMAction::CONTINUE;
}
int main(int argc, char **argv) {
if (argc < 3) {
puts("usage: ./loader library_path input_file_path");
exit(0);
}
const char *lib_path;
lib_path = argv[1];
strcpy(input_pathname, argv[2]);
void *handle = dlopen(lib_path, RTLD_LAZY);
if (handle == nullptr) {
perror("Cannot load library");
exit(EXIT_FAILURE);
}
const char *lib_name = lib_path;
if (strrchr(lib_name, '/') != nullptr) lib_name = strrchr(lib_name, '/') + 1;
// printf("library name:%s\n", lib_name);
// load library module address for log path
for (MemoryMap &map : getCurrentProcessMaps()) {
// printf("module:%s\n", map.name.c_str());
if ((map.permission & PF_EXEC) &&
strstr(map.name.c_str(), lib_name) != NULL) {
module_base = map.range.start;
module_end = map.range.end;
}
}
if (module_base == 0) {
std::cerr << "Fail to find base address" << std::endl;
return -1;
}
// printf("module base:%p, module end:%p\n", module_base, module_end);
p_target_func = (target_func)dlsym(handle, "target_func");
// p_target_func = (target_func)(module_base + 0x61a);
printf("p_target_func:%p\n", p_target_func);
VM vm;
uint8_t *fakestack = nullptr;
GPRState *state = vm.getGPRState();
allocateVirtualStack(state, STACK_SIZE, &fakestack);
vm.addInstrumentedModuleFromAddr(module_base);
vm.addInstrumentedModuleFromAddr((rword)&main);
vm.addVMEventCB(BASIC_BLOCK_ENTRY, bbcallback, nullptr);
// QBDI::simulateCall(state, FAKE_RET_ADDR);
// vm.run((rword)&fuzz_func, (rword)FAKE_RET_ADDR);
rword ret;
vm.call(&ret, (rword)&fuzz_func, {});
return 0;
}

View File

@ -46,10 +46,18 @@ You can also compile statically-linked binaries by setting STATIC=1. This
can be useful when compiling QEMU on a different system than the one you're
planning to run the fuzzer on and is most often used with the HOST variable.
Note: when targetting the i386 architecture, on some bianries the forkserver
handshake may fail due to the lack of reversed memory. Fix it with
export QEMU_RESERVED_VA=0x1000000
Note: if you want the QEMU helper to be installed on your system for all
users, you need to build it before issuing 'make install' in the parent
directory.
If you want to specify a different path for libraries (e.g. to run an arm64
binary on x86_64) use QEMU_LD_PREFIX.
## 3) Bonus feature #1: deferred initialization
As for LLVM mode (refer to its README for mode details) QEMU mode supports
@ -100,7 +108,11 @@ afl-fuzz).
AFL_COMPCOV_LEVEL=1 is to instrument comparisons with only immediate
values / read-only memory. AFL_COMPCOV_LEVEL=2 instruments all
comparison instructions and memory comparison functions when libcompcov
is preloaded. Comparison instructions are currently instrumented only
is preloaded.
AFL_COMPCOV_LEVEL=3 has the same effects of AFL_COMPCOV_LEVEL=2 but enables also
the instrumentation of the floating-point comparisons on x86 and x86_64 (experimental).
Integer comparison instructions are currently instrumented only
on the x86, x86_64 and ARM targets.
Highly recommended.

View File

@ -4,7 +4,7 @@
# --------------------------------------
#
# Originally written by Andrew Griffiths <agriffiths@google.com> and
# Michal Zalewski <lcamtuf@google.com>
# Michal Zalewski
#
# TCG instrumentation and block chaining support by Andrea Biondo
# <andrea.biondo965@gmail.com>
@ -44,7 +44,7 @@ echo "[*] Performing basic sanity checks..."
if [ ! "`uname -s`" = "Linux" ]; then
echo "[-] Error: QEMU instrumentation is supported only on Linux."
exit 1
exit 0
fi
@ -100,7 +100,10 @@ if [ ! "$CKSUM" = "$QEMU_SHA384" ]; then
echo "[*] Downloading QEMU ${VERSION} from the web..."
rm -f "$ARCHIVE"
wget -O "$ARCHIVE" -- "$QEMU_URL" || exit 1
OK=
while [ -z "$OK" ]; do
wget -c -O "$ARCHIVE" -- "$QEMU_URL" && OK=1
done
CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1`
@ -150,13 +153,16 @@ patch -p1 <../patches/translate-all.diff || exit 1
patch -p1 <../patches/tcg.diff || exit 1
patch -p1 <../patches/i386-translate.diff || exit 1
patch -p1 <../patches/arm-translate.diff || exit 1
patch -p1 <../patches/i386-ops_sse.diff || exit 1
patch -p1 <../patches/i386-fpu_helper.diff || exit 1
patch -p1 <../patches/softfloat.diff || exit 1
echo "[+] Patching done."
if [ "$STATIC" = "1" ]; then
CFLAGS="-O3 -ggdb" ./configure --disable-bsd-user --disable-guest-agent --disable-strip --disable-werror \
--disable-gcrypt --disable-debug-info --disable-debug-tcg --enable-docs --disable-tcg-interpreter \
--disable-gcrypt --disable-debug-info --disable-debug-tcg --disable-tcg-interpreter \
--enable-attr --disable-brlapi --disable-linux-aio --disable-bzip2 --disable-bluez --disable-cap-ng \
--disable-curl --disable-fdt --disable-glusterfs --disable-gnutls --disable-nettle --disable-gtk \
--disable-rdma --disable-libiscsi --disable-vnc-jpeg --enable-kvm --disable-lzo --disable-curses \
@ -237,10 +243,9 @@ else
fi
echo "[+] Building libcompcov ..."
make -C libcompcov
make -C libcompcov && echo "[+] libcompcov ready"
echo "[+] Building unsigaction ..."
make -C unsigaction
echo "[+] libcompcov ready"
make -C unsigaction && echo "[+] unsigaction ready"
echo "[+] All done for qemu_mode, enjoy!"
exit 0

View File

@ -22,7 +22,7 @@ CFLAGS ?= -O3 -funroll-loops -I ../../include/
CFLAGS += -Wall -Wno-unused-result -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
LDFLAGS += -ldl
all: libcompcov.so compcovtest
all: libcompcov.so
libcompcov.so: libcompcov.so.c ../../config.h
$(CC) $(CFLAGS) -shared -fPIC $< -o ../../$@ $(LDFLAGS)
@ -34,7 +34,7 @@ clean:
rm -f ../../libcompcov.so compcovtest
compcovtest: compcovtest.cc
$(CXX) $< -o $@
$(CXX) -std=c++11 $< -o $@
install: all
install -m 755 ../../libcompcov.so $${DESTDIR}$(HELPER_PATH)

View File

@ -19,13 +19,16 @@
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <stdbool.h>
#include "types.h"
#include "config.h"
@ -335,6 +338,146 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
}
// TODO bcmp
/* Common libraries wrappers (from honggfuzz) */
/*
* Apache's httpd wrappers
*/
int ap_cstr_casecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
int apr_cstr_casecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
/*
* *SSL wrappers
*/
int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) {
return memcmp(m1, m2, len);
}
int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) {
return memcmp(m1, m2, len);
}
int OPENSSL_strcasecmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) {
return strncasecmp(s1, s2, len);
}
int32_t memcmpct(const void* s1, const void* s2, size_t len) {
return memcmp(s1, s2, len);
}
/*
* libXML wrappers
*/
int xmlStrncmp(const char* s1, const char* s2, int len) {
if (len <= 0) { return 0; }
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strncmp(s1, s2, (size_t)len);
}
int xmlStrcmp(const char* s1, const char* s2) {
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strcmp(s1, s2);
}
int xmlStrEqual(const char* s1, const char* s2) {
if (s1 == s2) { return 1; }
if (s1 == NULL) { return 0; }
if (s2 == NULL) { return 0; }
if (strcmp(s1, s2) == 0) { return 1; }
return 0;
}
int xmlStrcasecmp(const char* s1, const char* s2) {
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strcasecmp(s1, s2);
}
int xmlStrncasecmp(const char* s1, const char* s2, int len) {
if (len <= 0) { return 0; }
if (s1 == s2) { return 0; }
if (s1 == NULL) { return -1; }
if (s2 == NULL) { return 1; }
return strncasecmp(s1, s2, (size_t)len);
}
const char* xmlStrcasestr(const char* haystack, const char* needle) {
if (haystack == NULL) { return NULL; }
if (needle == NULL) { return NULL; }
return strcasestr(haystack, needle);
}
/*
* Samba wrappers
*/
int memcmp_const_time(const void* s1, const void* s2, size_t n) {
return memcmp(s1, s2, n);
}
bool strcsequal(const void* s1, const void* s2) {
if (s1 == s2) { return true; }
if (!s1 || !s2) { return false; }
return (strcmp(s1, s2) == 0);
}
/* Init code to open init the library. */
__attribute__((constructor)) void __compcov_init(void) {

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
@ -31,6 +31,9 @@
*/
#ifndef __AFL_QEMU_COMMON
#define __AFL_QEMU_COMMON
#include "../../config.h"
#ifndef CPU_NB_REGS
@ -76,8 +79,35 @@ void afl_debug_dump_saved_regs();
void afl_persistent_loop();
void tcg_gen_afl_call0(void *func);
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc, TCGv arg1,
TCGv arg2);
void tcg_gen_afl_maybe_log_call(target_ulong cur_loc);
void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
void *status);
void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
void *status);
void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
floatx80 arg2);
/* Check if an address is valid in the current mapping */
static inline int is_valid_addr(target_ulong addr) {
int l, flags;
target_ulong page;
void * p;
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) return 0;
return 1;
}
#endif

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
@ -83,7 +83,9 @@ __thread abi_ulong afl_prev_loc;
/* Set in the child process in forkserver mode: */
static int forkserver_installed = 0;
static int forkserver_installed = 0;
static int disable_caching = 0;
unsigned char afl_fork_child;
unsigned int afl_forksrv_pid;
unsigned char is_persistent;
@ -206,6 +208,8 @@ static void afl_setup(void) {
rcu_disable_atfork();
disable_caching = getenv("AFL_QEMU_DISABLE_CACHE") != NULL;
is_persistent = getenv("AFL_QEMU_PERSISTENT_ADDR") != NULL;
if (is_persistent) {
@ -422,6 +426,8 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags,
uint32_t cf_mask, TranslationBlock *last_tb,
int tb_exit) {
if (disable_caching) return;
struct afl_tsl t;
struct afl_chain c;
@ -451,24 +457,6 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags,
}
/* Check if an address is valid in the current mapping */
static inline int is_valid_addr(target_ulong addr) {
int l, flags;
target_ulong page;
void * p;
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) return 0;
return 1;
}
/* This is the other side of the same channel. Since timeouts are handled by
afl-fuzz simply killing the child, we can just wait until the pipe breaks. */

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>

View File

@ -0,0 +1,223 @@
/*
american fuzzy lop++ - high-performance binary-only instrumentation
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
QEMU 3.1.1 port, TCG thread-safety, CompareCoverage and NeverZero
counters by Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019 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 code is a shim patched into the separately-distributed source
code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality
to implement AFL-style instrumentation and to take care of the remaining
parts of the AFL fork server logic.
The resulting QEMU binary is essentially a standalone instrumentation
tool; for an example of how to leverage it for other purposes, you can
have a look at afl-showmap.c.
*/
#include "tcg.h"
#include "afl-qemu-common.h"
union afl_float32 {
float32 f;
struct {
u64 sign : 1;
u64 exp : 7;
u64 frac : 24;
};
};
union afl_float64 {
float64 f;
struct {
u64 sign : 1;
u64 exp : 11;
u64 frac : 52;
};
};
// TODO 16 and 128 bits floats
// TODO figure out why float*_unpack_canonical does not work
void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
void* status) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
// float_status* s = (float_status*)status;
// FloatParts a = float32_unpack_canonical(arg1, s);
// FloatParts b = float32_unpack_canonical(arg2, s);
union afl_float32 a = {.f = arg1};
union afl_float32 b = {.f = arg2};
// if (is_nan(a.cls) || is_nan(b.cls)) return;
register uintptr_t idx = cur_loc;
if (a.sign != b.sign) return;
INC_AFL_AREA(idx);
if (a.exp != b.exp) return;
INC_AFL_AREA(idx + 1);
if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
INC_AFL_AREA(idx + 2);
if ((a.frac & 0xff00) == (b.frac & 0xff00)) { INC_AFL_AREA(idx + 3); }
}
}
void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
void* status) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
// float_status* s = (float_status*)status;
// FloatParts a = float64_unpack_canonical(arg1, s);
// FloatParts b = float64_unpack_canonical(arg2, s);
union afl_float64 a = {.f = arg1};
union afl_float64 b = {.f = arg2};
// if (is_nan(a.cls) || is_nan(b.cls)) return;
register uintptr_t idx = cur_loc;
if (a.sign == b.sign) INC_AFL_AREA(idx);
if ((a.exp & 0xff00) == (b.exp & 0xff00)) {
INC_AFL_AREA(idx + 1);
if ((a.exp & 0xff) == (b.exp & 0xff)) INC_AFL_AREA(idx + 2);
}
if ((a.frac & 0xff000000000000) == (b.frac & 0xff000000000000)) {
INC_AFL_AREA(idx + 3);
if ((a.frac & 0xff0000000000) == (b.frac & 0xff0000000000)) {
INC_AFL_AREA(idx + 4);
if ((a.frac & 0xff00000000) == (b.frac & 0xff00000000)) {
INC_AFL_AREA(idx + 5);
if ((a.frac & 0xff000000) == (b.frac & 0xff000000)) {
INC_AFL_AREA(idx + 6);
if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
INC_AFL_AREA(idx + 7);
if ((a.frac & 0xff00) == (b.frac & 0xff00)) INC_AFL_AREA(idx + 8);
}
}
}
}
}
}
void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
floatx80 arg2) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
if (floatx80_invalid_encoding(arg1) || floatx80_invalid_encoding(arg2))
return;
flag a_sign = extractFloatx80Sign(arg1);
flag b_sign = extractFloatx80Sign(arg2);
/*if (((extractFloatx80Exp(arg1) == 0x7fff) &&
(extractFloatx80Frac(arg1) << 1)) ||
((extractFloatx80Exp(arg2) == 0x7fff) &&
(extractFloatx80Frac(arg2) << 1)))
return;*/
register uintptr_t idx = cur_loc;
if (a_sign == b_sign) INC_AFL_AREA(idx);
if ((arg1.high & 0x7f00) == (arg2.high & 0x7f00)) {
INC_AFL_AREA(idx + 1);
if ((arg1.high & 0xff) == (arg2.high & 0xff)) INC_AFL_AREA(idx + 2);
}
if ((arg1.low & 0xff00000000000000) == (arg2.low & 0xff00000000000000)) {
INC_AFL_AREA(idx + 3);
if ((arg1.low & 0xff000000000000) == (arg2.low & 0xff000000000000)) {
INC_AFL_AREA(idx + 4);
if ((arg1.low & 0xff0000000000) == (arg2.low & 0xff0000000000)) {
INC_AFL_AREA(idx + 5);
if ((arg1.low & 0xff00000000) == (arg2.low & 0xff00000000)) {
INC_AFL_AREA(idx + 6);
if ((arg1.low & 0xff000000) == (arg2.low & 0xff000000)) {
INC_AFL_AREA(idx + 7);
if ((arg1.low & 0xff0000) == (arg2.low & 0xff0000)) {
INC_AFL_AREA(idx + 8);
if ((arg1.low & 0xff00) == (arg2.low & 0xff00)) {
INC_AFL_AREA(idx + 9);
// if ((arg1.low & 0xff) == (arg2.low & 0xff))
// INC_AFL_AREA(idx + 10);
}
}
}
}
}
}
}
}

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
@ -42,10 +42,15 @@ void tcg_gen_afl_maybe_log_call(target_ulong cur_loc) {
unsigned sizemask, flags;
TCGOp * op;
#if TARGET_LONG_BITS == 64
TCGTemp *arg = tcgv_i64_temp(tcg_const_tl(cur_loc));
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1);
#else
TCGTemp *arg = tcgv_i32_temp(tcg_const_tl(cur_loc));
sizemask = dh_sizemask(void, 0) | dh_sizemask(i32, 1);
#endif
flags = 0;
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1);
#if defined(__sparc__) && !defined(__arch64__) && \
!defined(CONFIG_TCG_INTERPRETER)
@ -371,20 +376,27 @@ void tcg_gen_afl_call0(void *func) {
}
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
TCGv_i64 arg1, TCGv_i64 arg2) {
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc, TCGv arg1,
TCGv arg2) {
int i, real_args, nb_rets, pi;
unsigned sizemask, flags;
TCGOp * op;
const int nargs = 3;
#if TARGET_LONG_BITS == 64
TCGTemp *args[3] = {tcgv_i64_temp(tcg_const_tl(cur_loc)), tcgv_i64_temp(arg1),
tcgv_i64_temp(arg2)};
flags = 0;
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1) | dh_sizemask(i64, 2) |
dh_sizemask(i64, 3);
#else
TCGTemp *args[3] = {tcgv_i32_temp(tcg_const_tl(cur_loc)), tcgv_i32_temp(arg1),
tcgv_i32_temp(arg2)};
sizemask = dh_sizemask(void, 0) | dh_sizemask(i32, 1) | dh_sizemask(i32, 2) |
dh_sizemask(i32, 3);
#endif
flags = 0;
#if defined(__sparc__) && !defined(__arch64__) && \
!defined(CONFIG_TCG_INTERPRETER)

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>

View File

@ -0,0 +1,54 @@
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index ea5a0c48..89901315 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -384,10 +384,16 @@ void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
+#include "../patches/afl-qemu-common.h"
+
void helper_fcom_ST0_FT0(CPUX86State *env)
{
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
}
@@ -396,6 +402,10 @@ void helper_fucom_ST0_FT0(CPUX86State *env)
{
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
}
@@ -407,6 +417,10 @@ void helper_fcomi_ST0_FT0(CPUX86State *env)
int eflags;
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
@@ -418,6 +432,10 @@ void helper_fucomi_ST0_FT0(CPUX86State *env)
int eflags;
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];

View File

@ -0,0 +1,61 @@
diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index ed059897..a5296caa 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -997,6 +997,8 @@ SSE_HELPER_CMP(cmpord, FPU_CMPORD)
static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
+#include "../patches/afl-qemu-common.h"
+
void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
{
int ret;
@@ -1004,6 +1006,11 @@ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
s0 = d->ZMM_S(0);
s1 = s->ZMM_S(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
+
ret = float32_compare_quiet(s0, s1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1015,6 +1022,11 @@ void helper_comiss(CPUX86State *env, Reg *d, Reg *s)
s0 = d->ZMM_S(0);
s1 = s->ZMM_S(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
+
ret = float32_compare(s0, s1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1026,6 +1038,11 @@ void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s)
d0 = d->ZMM_D(0);
d1 = s->ZMM_D(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
+
ret = float64_compare_quiet(d0, d1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1037,6 +1054,11 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s)
d0 = d->ZMM_D(0);
d1 = s->ZMM_D(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
+
ret = float64_compare(d0, d1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}

View File

@ -0,0 +1,10 @@
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e1eef954..2f8d0d62 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -7205,3 +7205,5 @@ float128 float128_scalbn(float128 a, int n, float_status *status)
, status);
}
+
+#include "../../patches/afl-qemu-floats.h"

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