Compare commits

...

242 Commits

Author SHA1 Message Date
4f53803dfe Merge pull request #2261 from AFLplusplus/dev
v4.30c
2024-12-03 15:47:49 +01:00
ed06b3bc9f v4.30c 2024-12-03 15:46:45 +01:00
3081f589cc Merge pull request #2260 from AFLplusplus/dev
fix readme
2024-12-03 09:50:27 +01:00
5d08f33a5f fix readme 2024-12-03 09:47:49 +01:00
46cbe22feb Merge pull request #2258 from AFLplusplus/dev
push to stable
2024-12-02 15:47:30 +01:00
6cba007c76 finishing touches of removing afl-gcc 2024-12-02 15:14:38 +01:00
1461f3a0ee remove afl-as 2024-12-02 15:04:16 +01:00
03d306a97f code format 2024-12-02 14:58:43 +01:00
0278eb5351 Merge pull request #2259 from AFLplusplus/removeoutdated
Remove outdated afl-gcc/afl-clang
2024-12-02 14:54:58 +01:00
8e88ef02ad keep symlinks 2024-12-02 14:54:16 +01:00
ad2eaf54ad fix multiple loading of allow/denylist and do proper counting 2024-12-02 11:59:32 +01:00
a287076ac0 Merge pull request #2257 from S0fr/S0fr-patch-1
Update afl-analyze.c
2024-11-27 22:27:29 +01:00
c352943aa5 Update afl-analyze.c
To fix the issue with fields splitting in the afl-analysis.
2024-11-27 09:06:03 +08:00
bd3900c084 Remove reference to ZAFL's license
Lincense changed. See #2253
2024-11-22 12:02:06 -03:00
48002fe146 remove symlinks 2024-11-21 16:15:04 +01:00
31c8a052a6 Merge pull request #2252 from StepanGulyaev/dev
Added CFISAN option for verbose output on crash
2024-11-21 15:51:51 +01:00
46b87a6d62 adding details 2024-11-21 17:36:30 +03:00
b4208dde94 little fix for docs 2024-11-21 17:23:30 +03:00
4a492d5d8e Code formatting 2024-11-21 17:23:30 +03:00
945309c316 Typing fix 2024-11-21 17:23:30 +03:00
41de569353 Adding envs to docs 2024-11-21 17:22:30 +03:00
7aecf14c07 Added AFL_UBSAN_VERBOSE variable 2024-11-21 16:37:24 +03:00
7b24f4a329 remove afl-gcc/afl-clang 2024-11-21 14:31:36 +01:00
ebb919f771 Code formatted 2024-11-21 15:31:34 +03:00
b43f37456f Adding AFL_CFISAN_VERBOSE variable 2024-11-21 15:14:54 +03:00
701e89bbcd fixes 2024-11-21 10:39:49 +01:00
e3fae3e9b0 Added CFISAN option for verbose output on crash 2024-11-21 12:32:48 +03:00
464ec516d5 check afl-clang/gcc with sanitize-fuzzer 2024-11-21 09:43:20 +01:00
3af042d5bf Merge pull request #2248 from AFLplusplus/dev
push to stable
2024-11-20 16:34:35 +01:00
c1e4b8f7f6 idea cmplog 2024-11-20 15:53:04 +01:00
79deeb46dd add missing envs 2024-11-20 15:44:18 +01:00
9cf260ca1f remove outdated sanitize-undefined-trap-on-error 2024-11-20 15:38:17 +01:00
82752fe38d code format 2024-11-19 16:25:50 +01:00
d11ade56e2 remove compiler warning 2024-11-18 19:20:37 +01:00
665d32a0dc -g/-G value checks 2024-11-15 09:48:34 +01:00
e1bd9fc6ac update docs on asan instances 2024-11-15 09:48:34 +01:00
2c6f2c970d Merge pull request #2242 from abhigargrepo/dev
Unsetting AFL_LLVM_ALLOWLIST and AFL_LLVM_DENYLIST environment variables in make files
2024-11-11 15:24:40 +01:00
0e3157375b Unsetting AFL_LLVM_ALLOWLIST and AFL_LLVM_DENYLIST environment variables 2024-11-11 01:24:11 -08:00
f39cf57eac enhance backward compatibility and portability 2024-11-09 22:31:07 +01:00
e62999c95f install all includes 2024-11-09 16:28:26 +01:00
jma
0b22665391 Add support for post_process in Rust custom mutator + associated example with lain (#2241) 2024-11-08 17:15:51 +01:00
5777ceaf23 Merge pull request #2240 from AFLplusplus/dev
Push to stable
2024-11-07 15:42:48 +01:00
21916a7f60 changes 2024-11-07 15:41:48 +01:00
6c83a9ccc1 update unicorn checkout 2024-11-07 15:39:51 +01:00
bc9fda61a3 Merge pull request #2239 from wtdcode/fix-uc2-breakage
Force 2.0.1.post1 for unicornal temporarily
2024-11-07 15:37:51 +01:00
mio
4e0b8beba8 Force 2.0.1.post1 for unicornal temporarily 2024-11-07 22:20:17 +08:00
1448eab8ec Merge pull request #2235 from CowBoy4mH3LL/patch-3
Update README: Link to OpenSSF talk added
2024-11-04 11:08:59 +01:00
55aec64038 Update README: Link to OpenSSF talk added 2024-11-04 12:14:11 +05:30
42fc9acf5b Merge pull request #2234 from McSinyx/include
Install {config,types}.h
2024-11-01 07:58:26 +01:00
cdbd86a112 Install {config,types}.h 2024-11-01 12:01:21 +09:00
1aa58a1972 update qemuafl 2024-10-30 13:24:15 +01:00
d0587a3ac4 Merge pull request #2226 from AFLplusplus/dev
push to stable
2024-10-30 13:20:48 +01:00
d1fd072b79 fix 2024-10-30 10:55:44 +01:00
c282156451 Merge pull request #2232 from michaelmior/jsonschema-dict
Add JSON Schema dictionary
2024-10-30 10:55:07 +01:00
a9bda37d18 Add JSON Schema dictionary 2024-10-29 12:31:09 -04:00
577b286508 fix explanation how to obtain the map size 2024-10-28 09:53:01 +01:00
009f663e2c Merge pull request #2231 from dergoegge/2024-08-fix-start-off
Make `__AFL_COVERAGE_START_OFF` work for targets with "small" maps
2024-10-25 17:47:27 +02:00
1efb7c8a8b Make __AFL_COVERAGE_START_OFF work for targets with "small" maps 2024-10-25 11:37:55 +01:00
7f614be3a5 Merge pull request #2229 from g0ku704/feat/disable_gcc_version_check
Introduce `AFL_GCC_DISABLE_VERSION_CHECK` to disable GCC version check
2024-10-20 09:23:56 +02:00
04d2476b32 doc: add description for AFL_GCC_DISABLE_VERSION_CHECK 2024-10-20 16:00:17 +09:00
c1d9a4fab9 feat: introduce GCC disable environment variable
This change is to disable the GCC plugin version check for
GCC plugin and CMPLOG, to overcome the issues with incompatability
with expected GCC version and actual GCC version used to compile
using `AFL_GCC_DISABLE_VERSION_CHECK` environment variable.
2024-10-19 22:19:41 +09:00
8a060a4b68 fix the cleanup of previous generated SHA1 files in function handle_existing_out_dir() 2024-10-19 13:54:48 +02:00
a11488b9dc changelog 2024-10-16 18:27:10 +02:00
4cc9232485 add AFL_OPT_LEVEL support 2024-10-16 18:26:08 +02:00
20c46c0ed6 nits 2024-10-15 15:18:51 +02:00
b3d16f7b8c update how AFL_EXIT_WHEN_DONE and colors of cycles done are working 2024-10-14 09:45:59 +02:00
c0837409bd fix cycles_wo_finds count 2024-10-14 09:29:10 +02:00
78b7e14c73 Merge pull request #2222 from AFLplusplus/dev
push to stable
2024-10-07 16:46:12 +02:00
f9a8b60b3b add LLVMFuzzerTestOneInput -1 support for non-asan 2024-10-07 16:44:24 +02:00
4a1cf0b9af code format 2024-10-07 13:43:19 +02:00
c1e40c5fb7 Merge pull request #2220 from AFLplusplus/dev
push to stable
2024-10-07 10:12:51 +02:00
d6a2edb42a update nyx 2024-10-07 10:11:16 +02:00
5e8e233755 Merge pull request #2217 from carlocab/macos-flags
Update macOS linker flags in GNUmakefile.llvm
2024-10-07 10:01:25 +02:00
31ed850c4b Merge pull request #2218 from ea/stable
Fix uninitialized alloc_canary in libdislocator
2024-10-07 10:00:04 +02:00
ea
994ac55878 Fix uninitialized alloc_canary in libdislocator
When random alloc_canary env var option was introduced, a possibility for use of uninitialized alloc_canary value was made. 

In most cases, constructor will be called during shared library load and the alloc_canary would be initialized to either its default value or a randomly generated one if forced by AFL_RANDOM_ALLOC_CANARY env var.

However, in some cases, libraries loaded before libdislocator will make allocations (still using libdislocator's allocation functions) while alloc_canary is still uninitialized. In such cases, canary value is usually NULL. 
If such allocated value is then free()'d after libdislocator's constructor has been run, call to free() will fail causing a false positive. This condition usually happens while calling library destructors at process termination. 

The patch ensures the canary value is initialized in all cases, and introduces a destructor that reverts it to default value. 

This  does mean that certain number of early allocations will use the default canary value rather than the random one set afterwards.  This seems like a reasonable tradeoff as I haven't found a surefire way of forcing libdislocator's constructor to run first in all possible cases (if nothing else, libphtread usually  has priority).
2024-10-02 13:08:24 -05:00
cb5a61d8a1 Update macOS linker flags in GNUmakefile.llvm
`-flat_namespace` is effectively deprecated and doesn't really work as
expected these days. Omitting the `-flat_namespace` means that binaries
are built with a two-level namespace, which don't support
`-undefined suppress`.

The idiomatic way of telling the linker to look up undefined symbols at
runtime is using `-undefined dynamic_lookup`, which is supported by a
two-level namespace.

See also:
ocaml/ocaml#10723
mono/mono#21257
2024-10-02 17:56:43 +08:00
146e535f7b persistent record for frida and qmeu 2024-10-01 10:13:35 +02:00
b88f132975 llvm20 fix 2024-09-29 17:11:07 +02:00
12271064f8 fix fix 2024-09-27 09:20:08 +02:00
55b67f1372 fix postprocess for calibration 2024-09-26 14:42:59 +02:00
d21fb1a558 Merge pull request #2214 from AFLplusplus/dev
push to stable
2024-09-24 11:57:36 +03:00
2e6c74f9b9 2nd macos ci attempt 2024-09-24 09:55:35 +02:00
2a4281ce8d update qemuafl 2024-09-24 09:50:14 +02:00
9cd702e75d try macos ci 2024-09-24 09:41:27 +02:00
8b35dd49be Fix macOS build 2024-09-23 21:22:17 +02:00
703fd0b610 Merge pull request #2212 from nj00001/dev
Save crash log returned by nyx when AFL_CRASHING_SEEDS_AS_NEW_CRASH e…
2024-09-23 17:02:47 +03:00
db172473b5 Save crash log returned by nyx when AFL_CRASHING_SEEDS_AS_NEW_CRASH environment variable is enabled
nyx also returns a crash log when reporting a crash, both files are saved in the afl++ fuzzing run, whereas with the AFL_CRASHING_SEEDS_AS_NEW_CRASH setting, only the crash file is saved in the dry run phase if crashes are included in the supplied seeds.
This commit adds crash log saving to keep the behavior consistent
2024-09-23 15:50:20 +08:00
5b44067e9c Update fuzzing_in_depth.md for a typo (#2209) 2024-09-16 12:23:10 +02:00
8531928fa4 Merge pull request #2207 from schumilo/dev
fix AFL_AUTORESUME=1 for Nyx mode
2024-09-14 16:02:21 +02:00
804c98a1e8 Merge pull request #2208 from 20urc3/patch-1
Update COMPARISON.md
2024-09-14 16:01:32 +02:00
1792ce2825 Update COMPARISON.md
- Add Ampere Altra Q80-30 benchmark
2024-09-14 15:33:55 +02:00
1d6cd5dd19 fix AFL_AUTORESUME=1 for Nyx mode 2024-09-14 03:51:20 +02:00
7e9abf1bba Merge pull request #2206 from smoelius/afl-sha1-filenames-test
Add `AFL_SHA1_FILENAMES` test
2024-09-12 21:50:20 +02:00
6a28502191 Adjust cmplog test to use AFL_SHA1_FILENAMES=1 2024-09-12 10:05:23 -04:00
fc7c95e9f4 nits 2024-09-12 10:24:05 +02:00
4086b93ad7 Merge pull request #2205 from ktpss95112/patch-1
Update env_variables.md
2024-09-09 09:02:09 +02:00
837a9693ab Update env_variables.md 2024-09-09 11:32:32 +08:00
60d3ecab63 Fix broken link in CONTRIBUTING.md (#2196)
* Fix broken link in CONTRIBUTING.md

* Also change link text
2024-09-06 23:26:03 +02:00
d0f39849c2 update qemu persisten readme 2024-09-06 12:36:57 +02:00
8820bf4758 update qemu persisten readme 2024-09-06 12:36:57 +02:00
75d8c47a6b Merge pull request #2204 from AFLplusplus/dev
push to stable
2024-09-06 12:16:31 +02:00
3ec794c806 Merge pull request #2203 from ktpss95112/patch-1
Update the doc string of read_foreign_testcases()
2024-09-06 11:50:33 +02:00
bf46ff8823 Merge pull request #2202 from smoelius/permissive_create-in-mark_as_variable
Use `permissive_create` in `mark_as_variable`
2024-09-06 11:48:34 +02:00
6f61fca15a Update the doc string of read_foreign_testcases() 2024-09-06 11:39:49 +08:00
b8cb35fa8c Use permissive_create in mark_as_variable 2024-09-05 09:56:38 -04:00
dfc9b3dba0 already support LLVMFuzzerCleanup 2024-09-04 16:34:09 +02:00
ab5f95e17a enhance autotokens standalone 2024-08-29 14:12:32 +02:00
fe66a95d96 add autotokens-standalone 2024-08-28 15:31:15 +02:00
72a24e6439 improve aflpp-standalone 2024-08-28 13:17:49 +02:00
088dd6476c Merge pull request #2195 from intrigus-lgtm/patch-4
Install package without asking for confirmation
2024-08-22 18:32:08 +02:00
30df52cd8c Merge pull request #2193 from ncoghlan/core-dump-notice-rewording
Offer more explicit core dump handling tip
2024-08-22 18:30:28 +02:00
74d262c7b5 Install package without asking for confirmation 2024-08-21 15:50:00 +02:00
d7c99007ff No longer need the extra line break 2024-08-21 20:04:30 +10:00
bdb5622bd4 Skip the save/restore example 2024-08-21 20:03:33 +10:00
cf2ddf437b Wording tweaks 2024-08-21 19:05:41 +10:00
2b7aae66b6 Offer more explicit core dump handling tip 2024-08-21 19:02:38 +10:00
598a3c6b5e Merge pull request #2192 from AFLplusplus/dev
fix unicorn build
2024-08-20 12:51:03 +02:00
0978283915 fix unicorn build 2024-08-20 12:49:49 +02:00
f27cbdb793 Merge pull request #2190 from AFLplusplus/dev
push to stable
2024-08-19 16:51:42 +02:00
1689a8e053 code format, llvm 18 2024-08-19 16:25:32 +02:00
6edc3b51ba fix AFL_OLD_FORKSERVER 2024-08-18 16:06:57 +02:00
93fb1d1a24 fix custom post process with custom send 2024-08-16 10:46:01 +02:00
bf7a6d69cf update changelog 2024-08-15 11:52:01 +02:00
6ddd5ecf4a fix missing trace_mini check 2024-08-14 18:47:44 +02:00
e2099114aa Merge pull request #2186 from R9295/fix/unicorn-mode-build
fix unicorn and unicornafl build script
2024-08-14 14:00:15 +02:00
db84f75a81 remove deprecated -d option in unicorn CI test 2024-08-14 13:45:10 +02:00
9111035495 fix incorrect check for unicorn CI 2024-08-14 13:44:44 +02:00
d78a8698e4 fix rebuild message 2024-08-13 16:56:22 +02:00
7b2f983bf3 fix unicorn and unicornafl build script 2024-08-13 16:54:53 +02:00
1910b0ad42 Merge pull request #2183 from NareshBiradar1/fix/image-tag-typo
#2182 - Fix Typo in Image Tag `heigh` Attribute in `README.md`
2024-08-11 16:59:39 +02:00
9a04df5d97 Corrected the 'heigh' attribute to 'height' in the HTML image tag for the AFL++ logo to ensure proper display. 2024-08-11 19:55:01 +05:30
4f03f380ea Merge pull request #2180 from tchebb/fix-shell-errors
Fix `/bin/sh:` errors when building without LLVM
2024-08-08 09:30:19 +02:00
e3b08d430c Merge pull request #2173 from ahuo1/dev
To support AFL instrumentation, add default settings of map_size in forkserver.
2024-08-08 09:21:38 +02:00
4f35c30371 Merge pull request #2181 from tchebb/fix-no-zlib
Fix syntax error when compiling without zlib
2024-08-07 12:28:08 +02:00
9df9064549 Fix syntax error when compiling without zlib
commit ecb5854be0 ("add zlib compression for fast resume") added new
logic selected at compile-time when zlib is present. Unfortunately, it
also broke the existing logic by removing the last line of a multi-line
if statement, resulting in a syntax error when zlib isn't present.

Restore the line as it was.
2024-08-06 11:37:19 -07:00
256bc6ab42 Fix "/bin/sh:" errors when building without LLVM
In GNUmakefile.llvm, several variables are unconditionally populated
by expanding $(LLVMVER) and $(LLVM_CONFIG) inside shell commands.
However, when LLVM is not present, both those variables are empty,
meaning that the shell commands end up malformed and emit harmless, but
noisy, errors like this one:

  /bin/sh: --: invalid option
  Usage:	/bin/sh [GNU long option] [option] ...
  	/bin/sh [GNU long option] [option] script-file ...
  GNU long options:
  	--debug
  	--debugger
  	--dump-po-strings
  	--dump-strings
  	--help
  	--init-file
  	--login
  	--noediting
  	--noprofile
  	--norc
  	--posix
  	--pretty-print
  	--rcfile
  	--rpm-requires
  	--restricted
  	--verbose
  	--version
  Shell options:
  	-ilrsD or -c command or -O shopt_option		(invocation only)
  	-abefhkmnptuvxBCHP or -o option
  /bin/sh: line 1: test: -gt: unary operator expected
  /bin/sh: line 1: test: -lt: unary operator expected
  /bin/sh: line 1: test: -ge: unary operator expected
  /bin/sh: line 1: test: -ge: unary operator expected

Fix the problem by only populating the "downstream" variables if the
upstream ones have values.
2024-08-06 11:27:01 -07:00
614c5127ca Merge pull request #2179 from fish98/revise_docs
Update local building docs with missing dependencies
2024-08-06 14:01:49 +02:00
5bb894f1ee remove redundant tracked tmp files during building
Signed-off-by: TTFISH <jiongchiyu@gmail.com>
2024-08-05 23:35:22 +08:00
8d72f41e20 update build dependencies for source-only/distrib
Otherwise the building of nyx_mode, frida_mode, unicorn_mode with source_only/all/distrib flag will fail due to missing dependencies.

Signed-off-by: TTFISH <jiongchiyu@gmail.com>
2024-08-05 23:33:31 +08:00
b928303dd0 Merge branch 'AFLplusplus:dev' into dev 2024-08-05 22:21:52 +08:00
76b26ac2c6 Merge pull request #2174 from killerra/dev
Fixed lsan defaults evaluation
2024-08-03 10:19:15 +02:00
dd16be405a Handle detect_leaks 0 and false 2024-08-02 14:51:42 +01:00
2e57d86576 lower mem usage attempt 2024-08-02 15:27:57 +02:00
4369d6209f Removed bogus free in instrument_coverage_unstable_find_output 2024-07-28 19:57:55 +01:00
26ae4124f3 fixed lasan defaults evaluation 2024-07-28 11:30:48 +01:00
25945d51a4 To support AFL instrumentation, add default settings. 2024-07-28 16:45:45 +08:00
db23931e7c Merge pull request #2172 from AFLplusplus/dev
push to stable
2024-07-24 14:50:57 +02:00
6e37f9b237 new cmplog map 2024-07-24 14:48:23 +02:00
2f2ddbbd79 fix afl-whatup time calc 2024-07-24 10:19:57 +02:00
ba7c012427 Merge pull request #2169 from killerra/dev
Fixed AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE to work for instances that are  not named "default"
2024-07-23 22:42:01 +02:00
5bfe0c1a15 added free for new strings 2024-07-23 20:52:15 +01:00
bb72cc752a Fixed frida unstable coverage for instances not named "default" 2024-07-23 17:31:13 +02:00
8c4ecd90a8 Merge pull request #2168 from AFLplusplus/fix_macos
Fix LLVM mode on MacOS
2024-07-23 15:44:05 +02:00
c0d53a1aa7 oops 2024-07-23 14:42:43 +02:00
31a1fbae33 Fix LLVM mode build on MacOS 2024-07-23 14:06:19 +02:00
09f1854cd1 Merge pull request #2165 from meowmeowxw/fix-fasan-arm64
Fix FASAN operand access on aarch64
2024-07-21 21:01:04 +02:00
4a6b751b93 frida_mode: fix fasan operand access order 2024-07-21 18:26:13 +02:00
bbcb3dd53e mini performance opt 2024-07-17 13:01:39 +02:00
eac53afe7b fix autodict 2024-07-15 23:42:55 +02:00
19ca7b3761 Merge pull request #2158 from AFLplusplus/dev
push to stable
2024-07-14 11:23:51 +02:00
55a2362348 code format 2024-07-14 10:33:12 +02:00
8afb60d2f9 Merge pull request #2160 from exoosh/dev
Fixing change from PR#2152, misspelled variable names
2024-07-14 10:21:24 +02:00
69a596c089 ensure this does not happen again 2024-07-14 10:20:53 +02:00
ccb952dde8 Revert "Replace gettimeofday with clock_gettime (#2159)"
This reverts commit 7c380a6612.
2024-07-14 10:18:23 +02:00
7c380a6612 Replace gettimeofday with clock_gettime (#2159) 2024-07-14 00:25:58 +02:00
88e2affe73 Fixing change from PR#2152, misspelled variable names 2024-07-13 21:29:41 +00:00
3f26818d97 Merge pull request #2157 from trail-of-forks/fix-syncid-len
check the sync_id length once
2024-07-12 23:05:30 +02:00
bd83eb0f42 check the sync_id length once 2024-07-12 16:22:17 -04:00
c5acf3f137 Merge pull request #2156 from choller/patch-1
Initialize max_length in afl_fsrv_init #2155
2024-07-12 20:13:14 +02:00
ea42feb06a Initialize max_length in afl_fsrv_init #2155 2024-07-12 20:08:52 +02:00
a09720665d Merge pull request #2154 from hazohelet/fix-missed-alias-table-recreation
Fix missed updates of alias table when INTROSPECTION is on
2024-07-10 16:53:39 +02:00
6f394842be Merge pull request #2152 from exoosh/exocad/stable
Some fixups to the GNUmakefile.llvm
2024-07-10 14:39:31 +02:00
02f4f75526 Fix missed updates of alias table when INTROSPECTION is on
In src/afl-fuzz.c `prev_queued_items` is used to decide whether the alias table should be recreated through the comparison with `afl->queued_items`.
43f462c91b/src/afl-fuzz.c (L3103-L3117)

However, this variable is also updated to `afl->queued_items` when INTROSPECTION is enabled and the `fuzz_one` appends seeds.
43f462c91b/src/afl-fuzz.c (L3135-L3140)

Due to the update of `prev_queued_items` when INTROSPECTION is on, alias table may not be recreated when it actually should be.

This can lead to potential heap buffer-overflow in `select_next_queue_entry` due to the lack of `afl_realloc` called in `create_alias_table`.

This patch fixes this bug by utilizing another variable for the INTROSPECTION part like other variables such as `prev_saved_tmouts`.
2024-07-10 21:39:04 +09:00
43f462c91b Merge pull request #2138 from meowmeowxw/ijon-set
IJON SET
2024-07-10 13:51:08 +02:00
77bad3ad23 ijon set: use __afl_coverage_interesting 2024-07-10 10:16:14 +02:00
835a4b6497 Some fixups to the GNUmakefile.llvm
* rely less on the shell and more on GNU make to parse the versions
* fixed retrieval of minor version (for 18.1.8 it gave 8 instead of 1!)
* auto-detection of llvm-config within the supported version range
* replaced backticks by `$(...)` syntax
* tested against `busybox static-sh`, `bash`, `dash` and `csh`
2024-07-10 07:55:37 +00:00
d1a7b6988c update timeout for custom mutator tests 2024-07-08 09:46:51 +02:00
365129d811 Update sample_all.sh (#2146)
Incorrect shell syntax
2024-07-08 08:34:06 +02:00
b840ac91dc Fixed the syntax errors in unicorn_loader.py within unicorn_mode. (#2144)
Replaced a Chinese comma "," with an English comma "," to ensure the code runs correctly.
2024-07-05 10:43:20 +02:00
dcd2f9ac77 Merge pull request #2143 from r-barnes/patch-1
Make fallthroughs explicit in afl-fuzz-extras.c
2024-07-01 17:12:42 +02:00
37d9afc5cc Make fallthroughs explicit in afl-fuzz-extras.c
Using `__attribute__((fallthrough))` makes fallthroughs explicit in a way the compiler can understand. This allows the enablement of `-Wimplicit-fallthrough`.
2024-07-01 06:59:37 -07:00
62b3a1e800 Merge pull request #2142 from CowBoy4mH3LL/patch-2
Update README.md to reflect latest changes
2024-07-01 11:35:53 +02:00
9c54be6cf1 Update README.md to reflect latest changes
1. fixed hook name length to 16
2. no native debug logging at this time -- will bridge with AFL++ macros latter
2024-07-01 14:54:01 +05:30
53409530b3 Merge pull request #2141 from AFLplusplus/dev
push to stable
2024-07-01 08:57:38 +02:00
43014cd465 changelog 2024-07-01 08:57:26 +02:00
e27e3622d4 Merge pull request #2140 from CowBoy4mH3LL/dev
Adding of QEMU hooking bridge
2024-07-01 08:55:00 +02:00
b169629dbd Fresh commit with all -- post revertion due to unicornafl update 2024-07-01 05:52:06 +00:00
8fbeeb1439 ijon set: discard source code instrumentation 2024-06-30 15:50:37 +02:00
2a489f844b ijon set: remove gdb_history 2024-06-29 23:08:51 +02:00
a161aac7c1 ijon set: init 2024-06-29 22:05:22 +02:00
a7f928ac31 update qemuafl 2024-06-29 16:45:01 +02:00
50ae95cee4 add AFL_OLD_FORKSERVER feature 2024-06-29 16:31:08 +02:00
f6bfa96a96 todo 2024-06-29 03:32:37 +02:00
e86dcc9f18 update qemu mode 2024-06-29 02:15:35 +02:00
9d33580aac code format 2024-06-28 16:46:42 +02:00
77cfd504cf update grammar mutator 2024-06-28 16:33:48 +02:00
f7bbd467b5 add custom_send_tcp 2024-06-28 16:00:19 +02:00
8993ba4305 add ruby dict 2024-06-27 19:42:58 +02:00
ba7313b521 AFL_CUSTOM_MUTATOR_LATE_SEND added 2024-06-27 18:51:58 +02:00
e2d30641be Merge pull request #2136 from jakelamberson/enhance-nyx-instructions
Enhance Nyx mode instructions
2024-06-27 03:26:56 +02:00
2248773566 Add nyx_mode to contribution instructions 2024-06-26 20:21:05 -04:00
5f43d0ad42 Fix and enhance Nyx mode instructions 2024-06-26 20:21:05 -04:00
af47531745 improved seed selection algorithm 2024-06-26 01:12:10 +02:00
e80bd2d30c Merge pull request #2133 from visitorckw/optimize-bit-counting
Optimize bit counting using __builtin_popcount
2024-06-24 01:37:09 +02:00
ac5815d994 Optimize bit counting using __builtin_popcount
Use the __builtin_popcount intrinsic to optimize the bit counting
function if the compiler supports it. This change replaces the manual
bit counting algorithm with the more efficient built-in function, which
leverages hardware support on compatible processors.

This modification ensures that the code remains backward-compatible by
falling back to the original implementation when __builtin_popcount is
not available.
2024-06-24 06:52:07 +08:00
540d741df0 nits atnwalk 2024-06-22 22:22:01 +02:00
ecb5854be0 add zlib compression for fast resume 2024-06-21 14:40:23 +02:00
25b650f59d Merge pull request #2132 from tylzh97/stable
Fix typo in unicorn_mode
2024-06-21 09:22:38 +02:00
ed6f19d3d8 Fix typo in unicorn_mode
in `unicorn_mode/samples`, python example floder's name is `python_simple`, there is a typo in README file.
2024-06-21 09:52:28 +08:00
aecd157244 nit 2024-06-20 18:49:40 +02:00
43a98b0ec2 todos 2024-06-20 18:49:40 +02:00
3b00cee858 Merge pull request #2130 from killerra/dev
Auto disable memory limits for FASAN
2024-06-20 08:47:20 +02:00
2fbc0aefb1 Auto disable memory limits for FASAN 2024-06-20 00:10:40 +02:00
2276a2f5c3 Merge pull request #2129 from choller/persist-code-cov
Collect persistent coverage data and dump it at the end of the run
2024-06-19 14:09:06 +02:00
8fcca6fb41 Collect persistent coverage data and dump it at the end of the run
With CODE_COVERAGE builds, we need to collect the coverage data of each
iteration in a persistant buffer that has the same size as the regular
trace buffer used for fuzzing. We dump this information at the end of
the run and when combined with pointer data and module info, this can be
used to calculate code coverage.
2024-06-19 12:36:58 +02:00
b8568034f0 code format and changelog 2024-06-18 15:42:34 +02:00
3ebf41ba34 Merge pull request #2128 from AFLplusplus/fastrestart
Fastrestart
2024-06-18 15:28:56 +02:00
304e84502d fast resume option 2024-06-18 15:24:38 +02:00
a6e42d98d9 llvm 19 fixes 2024-06-18 15:09:11 +02:00
de176a10bc nit 2024-06-17 09:31:42 +02:00
e3183f7cda Merge pull request #2125 from visitorckw/fix-libradamsa-signed-integer-overflow
Fix signed integer overflow in radamsa
2024-06-14 08:14:03 +02:00
b5e0fff6b9 Fix signed integer overflow in radamsa
When UBSan was enabled and 'make test' was executed, the following
runtime error was observed:

libradamsa.c:26055:29: runtime error: left shift of 16777215 by 8 places cannot be represented in type 'int'

This issue was caused by a left shift operation on a signed integer.
The fix involved changing the integer literal to an unsigned integer by
adding a 'U' suffix, ensuring the left shift operation produces the
correct value without overflow.

Fixes: 8178f4df ("remove radamsa, add radamsa custom mutator")
2024-06-14 09:53:57 +08:00
36db3428ab Merge pull request #2123 from AFLplusplus/dev
push to stable
2024-06-13 09:20:42 +02:00
e7da8b9d6b Revert "MONOTONIC"
This reverts commit 0c9b460cc4.
2024-06-13 09:19:11 +02:00
c134df30db Merge pull request #2121 from visitorckw/remove-Wno-shift-count-overflow
Remove -Wno-shift-count-overflow flag and hashmap from compilation
2024-06-13 07:57:06 +02:00
b5e6c2d6e2 Remove -Wno-shift-count-overflow flag and hashmap from compilation
After commit 0c9d8e59 ("Fix undefined behavior by casting to uint64_t
before left shift"), the -Wno-shift-count-overflow flag is no longer
necessary to suppress compilation warnings. This commit removes the
flag, allowing the compiler to provide appropriate warnings for any
potential future cases of shifting too many bits.

Additionally, after commit eaf4a299 ("make redqueen hashmap not
default"), the hashmap is no longer in use. Therefore, this commit also
removes the hashmap from the GNUmakefile.
2024-06-13 09:34:03 +08:00
b6f8509234 Merge pull request #2122 from visitorckw/fix-realloc-check
Fix memory allocation check in aflpp custom mutators
2024-06-12 19:27:13 +02:00
d45cd63583 Fix memory allocation check in aflpp custom mutators
The memory allocation check in afl_custom_fuzz function was incorrect.
The condition was erroneously checking if ptr was non-null, whereas it
should return 0 when ptr is null. Correct the condition to properly
handle memory allocation failures.

Fixes: 32ffa266 ("max_len support")
2024-06-13 00:42:12 +08:00
0c9b460cc4 MONOTONIC 2024-06-12 09:17:07 +02:00
dd762726dc fastresume implementation 2024-06-12 09:10:35 +02:00
e68d57feec Merge pull request #2120 from visitorckw/fix-shift-too-many-bits
Fix undefined behavior by casting to uint64_t before left shift
2024-06-12 08:23:14 +02:00
0c9d8e5929 Fix undefined behavior by casting to uint64_t before left shift
According to the C standard, left-shifting a value by an amount greater
than or equal to the width of its promoted type results in undefined
behavior. To prevent potential unexpected results, explicitly cast the
uint8_t variable type to uint64_t before performing the left shift
operation by 56 bits. This ensures the operation is well-defined and
adheres to the standard.

Fixes: 40df85d1 ("adjust cmplog header")
2024-06-12 12:48:13 +08:00
75c3fa91dc update changelog 2024-06-10 22:25:38 +02:00
a37c7e1246 Merge pull request #2119 from WorksButNotTested/frida-persistent
Frida persistent
2024-06-10 22:24:25 +02:00
392dcd57c6 Fixes to build on arm32 2024-06-10 18:16:30 +01:00
1369cf7176 Fixes for arm/arm64 2024-06-10 18:16:30 +01:00
eccd0985a0 Fixes for x86 2024-06-10 18:16:30 +01:00
0617b8898a Update comment 2024-06-10 18:16:30 +01:00
fbcdeb8439 Improve persistent mode 2024-06-10 18:16:30 +01:00
6ed0a2b4aa fast resume setup detection 2024-06-10 18:22:06 +02:00
8e50c0c103 frida verbose 2024-06-10 09:08:44 +02:00
f2cd5e1d8e v4.22a init 2024-06-09 19:15:12 +02:00
163 changed files with 8900 additions and 2861 deletions

View File

@ -24,7 +24,7 @@ import importlib.metadata
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
CURRENT_LLVM = os.getenv('LLVM_VERSION', 17)
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")

View File

@ -34,23 +34,25 @@ jobs:
run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 distrib
- name: run tests
run: sudo -E ./afl-system-config; make tests
# macos:
# runs-on: macOS-latest
# env:
# AFL_MAP_SIZE: 65536
# AFL_SKIP_CPUFREQ: 1
# AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
# steps:
# - uses: actions/checkout@v3
# - name: install
# run: brew install make gcc llvm
# - name: fix install
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
# - name: build
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
# - name: frida
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
# - name: run tests
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
# - name: force frida test for MacOS
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
macos:
runs-on: macOS-latest
env:
AFL_MAP_SIZE: 65536
AFL_SKIP_CPUFREQ: 1
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
steps:
- uses: actions/checkout@v3
- name: install
run: brew install make gcc llvm
# - name: fix install
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
# - name: build
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
- name: build
run: sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
# - name: frida
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
# - name: run tests
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
# - name: force frida test for MacOS
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr

3
.gitignore vendored
View File

@ -6,6 +6,7 @@
*.pyc
*.so
*.swp
.DS_Store
.sync_tmp
.test
.test2
@ -111,3 +112,5 @@ utils/replay_record/persistent_demo_replay_compat
utils/replay_record/persistent_demo_replay_argparse
utils/plot_ui/afl-plot-ui
vuln_prog
argv_fuzz_demo
argv_fuzz_persistent_demo

View File

@ -34,6 +34,7 @@ file in one the following folders:
* [docs/](docs/) (this is where you can find most of our docs content)
* [frida_mode/](frida_mode/)
* [instrumentation/](instrumentation/)
* [nyx_mode/](nyx_mode/)
* [qemu_mode/](qemu_mode/)
* [unicorn_mode/](unicorn_mode/)
@ -47,7 +48,7 @@ When working on the docs, please keep the following guidelines in mind:
* Don't: fuzzing-network-service.md
* Use a maximum of 80 characters per line to make reading in a console easier.
* Make all pull requests against `dev`, see
[#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl).
[#how-to-submit-a-pull-request](#how-to-submit-a-pull-request).
And finally, here are some best practices for writing docs content:
@ -56,4 +57,4 @@ And finally, here are some best practices for writing docs content:
* Use bulleted lists to present similar content in a way that makes it easy to
scan.
* Use numbered lists for procedures or prioritizing.
* Link to related content, for example, prerequisites or in-depth discussions.
* Link to related content, for example, prerequisites or in-depth discussions.

View File

@ -19,21 +19,21 @@
# so use a variable for '#'
HASH=\#
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/share/man/man8
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/share/man/man8
INCLUDE_PATH = $(PREFIX)/include/afl
PROGNAME = afl
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
# PROGS intentionally omit afl-as, which gets installed elsewhere.
PROGS = afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-addseeds afl-system-config afl-persistent-config afl-cc
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
HEADERS = include/afl-fuzz.h include/afl-mutations.h include/afl-persistent-replay.h include/afl-prealloc.h include/afl-record-compat.h include/alloc-inl.h include/android-ashmem.h include/cmplog.h include/common.h include/config.h include/coverage-32.h include/coverage-64.h include/debug.h include/envs.h include/forkserver.h include/hash.h include/list.h include/sharedmem.h include/snapshot-inl.h include/t1ha.h include/t1ha0_ia32aes_b.h include/t1ha_bits.h include/t1ha_selfcheck.h include/types.h include/xxhash.h
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8)
ASAN_OPTIONS=detect_leaks=0
SYS = $(shell uname -s)
@ -117,7 +117,7 @@ endif
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
ifneq "$(COMPILER_TYPE)" ""
#$(info gcc is being used)
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
override CFLAGS_OPT += -Wno-format-truncation
endif
ifeq "$(SYS)" "SunOS"
@ -325,10 +325,12 @@ ifdef TEST_MMAP
endif
.PHONY: all
all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_build all_done
all: test_x86 test_shm test_python ready $(PROGS) llvm gcc_plugin test_build all_done
-$(MAKE) -C utils/aflpp_driver
@echo
@echo
@echo
@echo
@echo Build Summary:
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@ -337,6 +339,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
ifneq "$(SYS)" "Darwin"
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif
@test -e afl-cc || echo "[-] AFL++ instrumentation compilers could not be built! Install llvm-VERSION-dev or gcc-VERSION-plugin-dev, see docs/INSTALL.md!"
@echo
.PHONY: llvm
@ -441,6 +444,14 @@ test_shm:
@echo "[-] shmat seems not to be working, switching to mmap implementation"
endif
ifeq "$(shell echo '$(HASH)include <zlib.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
override SPECIAL_PERFORMANCE += -DHAVE_ZLIB
override LDFLAGS += -lz
$(info [+] ZLIB detected)
else
$(info [!] Warning: no ZLIB detected)
endif
.PHONY: test_python
ifeq "$(PYTHON_OK)" "1"
test_python:
@ -455,10 +466,6 @@ endif
ready:
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
@ln -sf afl-as as
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
@ -471,8 +478,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
@ -566,27 +573,27 @@ code-format:
.PHONY: test_build
ifndef AFL_NO_X86
test_build: afl-cc afl-gcc afl-as afl-showmap
test_build: afl-cc afl-showmap
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
-ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
-echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
@echo
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
# @echo "[*] Testing the CC wrapper and its instrumentation output..."
# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-clang-fast test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-clang-fast failed"; exit 1 )
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
# @rm -f test-instr
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-gcc does not seem to be behaving correctly!"; \
# @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-clang-fast does not seem to be behaving correctly!"; \
# gcc -v 2>&1 | grep -q -- --with-as= && ( echo; echo "Gcc is configured not to use an external assembler with the -B option." ) || \
# ( echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
# @echo
# @echo "[+] All right, the instrumentation of afl-gcc seems to be working!"
# @echo "[+] All right, the instrumentation of afl-clang-fast seems to be working!"
else
test_build: afl-cc afl-as afl-showmap
test_build: afl-cc afl-showmap
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
endif
@ -596,7 +603,8 @@ all_done: test_build
@test -e cmplog-instructions-pass.so && echo "[+] LLVM mode for 'afl-cc' successfully built!" || echo "[-] LLVM mode for 'afl-cc' failed to build, likely you either don't have llvm installed, or you need to set LLVM_CONFIG, to point to e.g. llvm-config-11. See instrumentation/README.llvm.md how to do this. Highly recommended!"
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
@test -e afl-cc && echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
@test -e afl-cc || echo "[-] ERROR - neither afl-clang-fast or afl-gcc-fast could be compiled - YOU ARE MISSING PACKAGES! Read docs/INSTALL.md!"
@if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
@ -604,7 +612,7 @@ all_done: test_build
.PHONY: clean
clean:
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
rm -rf $(PROGS) afl-fuzz-document as afl-as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a
-$(MAKE) -f GNUmakefile.llvm clean
-$(MAKE) -f GNUmakefile.gcc_plugin clean
-$(MAKE) -C utils/libdislocator clean
@ -817,10 +825,10 @@ endif
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-g++
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang++
@mkdir -m 755 -p $${DESTDIR}$(INCLUDE_PATH)
install -m 644 $(HEADERS) $${DESTDIR}$(INCLUDE_PATH)
@mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
@ -828,12 +836,14 @@ endif
.PHONY: uninstall
uninstall:
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-ld-lto afl-c* afl-lto*
-cd $${DESTDIR}$(INCLUDE_PATH) && rm -f $(HEADERS:include/%=%)
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt injections.dic
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
-rmdir $${DESTDIR}$(BIN_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(INCLUDE_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(HELPER_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(MISC_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(DOC_PATH) 2>/dev/null

View File

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

View File

@ -32,6 +32,9 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2
SYS = $(shell uname -s)
override LLVM_TOO_NEW_DEFAULT := 18
override LLVM_TOO_OLD_DEFAULT := 13
ifeq "$(SYS)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
@ -39,24 +42,36 @@ ifeq "$(SYS)" "OpenBSD"
$(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
endif
else
LLVM_CONFIG ?= llvm-config
# Small function to use Bash to detect the latest available clang and clang++ binaries, if using them by that name fails
override _CLANG_VERSIONS_TO_TEST := $(patsubst %,-%,$(shell seq $(LLVM_TOO_NEW_DEFAULT) -1 $(LLVM_TOO_OLD_DEFAULT)))
detect_newest=$(shell for v in "" $(_CLANG_VERSIONS_TO_TEST); do test -n "$$(command -v -- $1$$v)" && { echo "$1$$v"; break; }; done)
LLVM_CONFIG ?= $(call detect_newest,llvm-config)
endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 )
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
LLVM_STDCXX = gnu++11
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
LLVM_LTO = 0
ifneq "$(LLVM_CONFIG)" ""
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
endif
ifneq "$(LLVMVER)" ""
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
endif
LLVM_STDCXX := gnu++11
LLVM_LTO := 0
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.' && echo 1 || echo 0)
# Uncomment to see the values assigned above
# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
ifeq "$(LLVMVER)" ""
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
@ -103,10 +118,6 @@ ifeq "$(LLVM_LTO)" "0"
$(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.)
endif
ifeq "$(LLVM_APPLE_XCODE)" "1"
$(warning llvm_mode will not compile with Xcode clang...)
endif
# We were using llvm-config --bindir to get the location of clang, but
# this seems to be busted on some distros, so using the one in $PATH is
# probably better.
@ -114,6 +125,11 @@ endif
CC = $(LLVM_BINDIR)/clang
CXX = $(LLVM_BINDIR)/clang++
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
ifeq "$(LLVM_APPLE_XCODE)" "1"
$(warning llvm_mode will not compile with Xcode clang...)
endif
# llvm-config --bindir may not providing a valid path, so ...
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
# however we must ensure that this is not a "CC=gcc make"
@ -147,7 +163,7 @@ endif
# sanity check.
# Are versions of clang --version and llvm-config --version equal?
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
# I disable this because it does not make sense with what we did before (marc)
# We did exactly set these 26 lines above with these values, and it would break
@ -245,7 +261,7 @@ endif
AFL_CLANG_FUSELD=
ifeq "$(LLVM_LTO)" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=$$(command -v ld) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_FUSELD=1
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_LDPATH=1
@ -300,8 +316,8 @@ endif
ifneq "$(LLVM_CONFIG)" ""
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
endif
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS)
# wasm fuzzing: disable thread-local storage and unset LLVM debug flag
ifdef WAFL_MODE
@ -311,7 +327,7 @@ endif
# User teor2345 reports that this is required to make things work on MacOS X.
ifeq "$(SYS)" "Darwin"
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
CLANG_LFL += -Wl,-undefined,dynamic_lookup
override LLVM_HAVE_LTO := 0
override LLVM_LTO := 0
else
@ -319,7 +335,7 @@ else
endif
ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline
# Needed for unwind symbols
@ -417,7 +433,7 @@ endif
endif
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_MIN_4_0_1)" "0"
@ -492,7 +508,7 @@ document:
.PHONY: test_build
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr

View File

@ -1,10 +1,10 @@
# American Fuzzy Lop plus plus (AFL++)
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.30c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.21c
GitHub version: 4.31a
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -2,7 +2,7 @@
## Must
- fast restart of afl-fuzz if cmdline + target hash is the same
- ijon support?
- check for null ptr for xml/curl/g_ string transform functions
- hardened_usercopy=0 page_alloc.shuffle=0
- add value_profile but only enable after 15 minutes without finds

View File

@ -112,12 +112,12 @@ if [ -z "$NO_COLOR" ]; then
fi
PLATFORM=`uname -s`
if [ "$PLATFORM" = "Linux" ] ; then
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
else
#if [ "$PLATFORM" = "Linux" ] ; then
# CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
#else
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
CUR_TIME=`date +%s`
fi
#fi
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
trap "rm -f $TMP" 1 2 3 13 15

View File

@ -11,3 +11,4 @@
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|Ampere Altra Q80-30 | 0 | 80 | 54477 | 1604482 | system |

View File

@ -48,7 +48,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 *ptr = realloc(data->buf, max_size);
if (ptr) {
if (!ptr) {
return 0;

View File

@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC
all: aflpp-standalone
aflpp-standalone: aflpp-standalone.c
$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c ../../../src/afl-fuzz-extras.c ../../../src/afl-common.c
clean:
rm -f *.o *~ aflpp-standalone core

View File

@ -5,6 +5,6 @@ this is the AFL++ havoc mutator as a standalone mutator
just type `make` to build.
```
aflpp-standalone inputfile outputfile [splicefile]
aflpp-standalone -h # to see all parameteres
cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example
```

View File

@ -1,6 +1,12 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
#include <unistd.h>
#include <getopt.h>
static int max_havoc = 16, verbose;
static unsigned char *dict;
typedef struct my_mutator {
afl_state_t *afl;
@ -21,14 +27,14 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
}
if ((data->buf = malloc(1024*1024)) == NULL) {
if ((data->buf = malloc(1024 * 1024)) == NULL) {
perror("afl_custom_init alloc");
return NULL;
} else {
data->buf_size = 1024*1024;
data->buf_size = 1024 * 1024;
}
@ -36,9 +42,23 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
data->afl = calloc(1, sizeof(afl_state_t));
data->afl->queue_cycle = 1;
data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
if (data->afl->fsrv.dev_urandom_fd < 0) {
PFATAL("Unable to open /dev/urandom");
}
rand_set_seed(data->afl, getpid());
if (dict) {
load_extras(data->afl, dict);
if (verbose)
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
data->afl->extras_cnt);
}
return data;
}
@ -53,7 +73,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 *ptr = realloc(data->buf, max_size);
if (ptr) {
if (!ptr) {
return 0;
@ -66,14 +86,20 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
}
u32 havoc_steps = 1 + rand_below(data->afl, 16);
u32 havoc_steps = 1 + rand_below(data->afl, max_havoc);
if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps);
/* set everything up, costly ... :( */
memcpy(data->buf, buf, buf_size);
/* the mutation */
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
false, true, add_buf, add_buf_size, max_size);
u32 out_buf_len;
do {
out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, false,
true, add_buf, add_buf_size, max_size);
} while (out_buf_len == buf_size && memcmp(buf, data->buf, buf_size) == 0);
/* return size of mutated data */
*out_buf = data->buf;
@ -84,80 +110,143 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
int main(int argc, char *argv[]) {
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]);
printf("Reads a testcase from stdin when no input file (or '-') is specified,\n");
printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n");
printf("no output filename is given. As an optional third parameter you can give a file\n");
printf(
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
"[splicefile]]]\n\n",
argv[0]);
printf(
"Reads a testcase from stdin when no input file (or '-') is "
"specified,\n");
printf(
"mutates according to AFL++'s mutation engine, and write to stdout "
"when '-' or\n");
printf(
"no output filename is given. As an optional third parameter you can "
"give a file\n");
printf("for splicing. Maximum input and output length is 1MB.\n");
printf("The -v verbose option prints debug output to stderr.\n");
printf("Options:\n");
printf(" -v verbose debug output to stderr.\n");
printf(" -m val max mutations (1-val, val default is 16)\n");
printf(" -x file dictionary file (AFL++ format)\n");
return 0;
}
FILE *in = stdin, *out = stdout, *splice = NULL;
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL;
int verbose = 0, splicelen = 0;
FILE *in = stdin, *out = stdout, *splice = NULL;
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
int splicelen = 0, opt;
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
switch (opt) {
case 'm':
max_havoc = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'x':
dict = optarg;
break;
default:
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
exit(-1);
}
}
if (max_havoc < 1) {
fprintf(stderr, "Error: illegal -m value\n");
exit(-1);
if (argc > 1 && strcmp(argv[1], "-v") == 0) {
verbose = 1;
argc--;
argv++;
fprintf(stderr, "Verbose active\n");
}
my_mutator_t *data = afl_custom_init(NULL, 0);
if (argc > 1 && strcmp(argv[1], "-") != 0) {
if ((in = fopen(argv[1], "r")) == NULL) {
if (argc > optind && strcmp(argv[optind], "-") != 0) {
if ((in = fopen(argv[optind], "r")) == NULL) {
perror(argv[1]);
return -1;
}
if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
}
size_t inlen = fread(inbuf, 1, 1024*1024, in);
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
if (!inlen) {
fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
fprintf(stderr, "Error: empty file %s\n",
argv[optind] ? argv[optind] : "stdin");
return -1;
}
if (argc > 2 && strcmp(argv[2], "-") != 0) {
if ((out = fopen(argv[2], "w")) == NULL) {
perror(argv[2]);
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
perror(argv[optind + 1]);
return -1;
}
if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
}
if (argc > 3) {
if ((splice = fopen(argv[3], "r")) == NULL) {
perror(argv[3]);
if (argc > optind + 2) {
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
perror(argv[optind + 2]);
return -1;
}
if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
splicebuf = malloc(1024*1024);
size_t splicelen = fread(splicebuf, 1, 1024*1024, splice);
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
splicebuf = malloc(1024 * 1024);
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
if (!splicelen) {
fprintf(stderr, "Error: empty file %s\n", argv[3]);
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
return -1;
}
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
}
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024);
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
splicelen, 1024 * 1024);
if (outlen == 0 || !outbuf) {
fprintf(stderr, "Error: no mutation data returned.\n");
return -1;
}
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n");
return -1;
}
return 0;
}

View File

@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`.
**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
```bash
# create the required a random seed first
# create the required random seed first
mkdir -p ~/campaign/example/seeds
cd ~/campaign/example/seeds
head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded

View File

@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
if (fd_socket != -1) { close(fd_socket); }
*out_buf = NULL;
return 0;
fprintf(stderr, "atnwalk.socket not found in current directory!\n");
exit(-1);
}

View File

@ -39,6 +39,7 @@ extern "C" {
#ifndef AFL_TXT_MAX_LEN
#define AFL_TXT_MAX_LEN 65535
#endif
#define AUTOTOKENS_TXT_MIN_LEN 1
#if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN
#error SPLICE_MIN must be lower than SIZE_MIN
@ -57,8 +58,9 @@ typedef struct my_mutator {
if (unlikely(debug)) fprintf
#define IFDEBUG if (unlikely(debug))
int module_disabled = 0;
static afl_state *afl_ptr;
static int module_disabled = 0;
static int auto_disable = AUTOTOKENS_AUTO_DISABLE;
static int debug = AUTOTOKENS_DEBUG;
static int only_fav = AUTOTOKENS_ONLY_FAV;
@ -104,9 +106,9 @@ static void first_run(void *data) {
if (afl_ptr->custom_only || !auto_disable) { return; }
if (unlikely(afl_ptr->active_items == 1 &&
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) {
afl_ptr->queue_cur->len < AUTOTOKENS_TXT_MIN_LEN)) {
if (afl_ptr->extras_cnt > 8) {
if (afl_ptr->extras_cnt) {
u32 valid = 0;
@ -237,7 +239,7 @@ extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf,
}
extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
extern "C" size_t afl_custom_fuzz(void *data, u8 *buf, size_t buf_size,
u8 **out_buf, u8 *add_buf,
size_t add_buf_size, size_t max_size) {
@ -655,6 +657,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 &&
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) {
retry_thin_air:
DEBUGF(stderr, "Creating an entry from thin air...\n");
structure = new vector<u32>();
u32 item, prev, cnt = current_id >> 1;
@ -684,8 +687,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
}
create_from_thin_air = 0;
}
if (entry == file_mapping.end()) {
@ -693,7 +694,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
// this input file was not analyzed for tokens yet, so let's do it!
size_t len = afl_ptr->queue_cur->len;
if (len < AFL_TXT_MIN_LEN) {
if (len < AUTOTOKENS_TXT_MIN_LEN) {
file_mapping[fn] = structure; // NULL ptr so we don't read the file again
s = NULL;
@ -895,6 +896,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
if (tokens.size() < AUTOTOKENS_SIZE_MIN) {
if (create_from_thin_air) { goto retry_thin_air; }
file_mapping[fn] = NULL;
s = NULL;
DEBUGF(stderr, "too few tokens\n");
@ -955,7 +957,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
}
extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) {
(void)(seed);
my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t));
@ -1070,7 +1072,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
id_to_token[current_id] = "'";
++current_id;
return data;
return (void *)data;
}

View File

@ -0,0 +1,19 @@
CFLAGS = -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1 -Wno-implicit-function-declaration
CXXFLAGS= -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1
all: autotokens-standalone
autotokens.o: ../autotokens.cpp
$(CXX) $(CXXFLAGS) -I../../../include -I. -I../.. -c ../autotokens.cpp
autotokens-standalone: autotokens-standalone.c autotokens.o
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c autotokens-standalone.c
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-performance.c
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-extras.c
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-queue.c
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-common.c
$(CXX) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o autotokens-standalone *.o
clean:
rm -f *.o *~ autotokens-standalone core

View File

@ -0,0 +1,12 @@
# Autotokens standalone mutator
this is a standalone version of the AFL++ autotokens custom mutator.
just type `make` to build.
You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer!
```
autotokens-standalone -h # to see all parameteres
autotokens-standalone -x foo.dict inputfile outputfile # example
```

View File

@ -0,0 +1,192 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
#include <unistd.h>
#include <getopt.h>
static int max_havoc = 16, verbose;
static unsigned char *dict, *mh = "16";
extern int module_disabled;
void *afl_custom_init(afl_state_t *, unsigned int);
int main(int argc, char *argv[]) {
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
printf(
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
"[splicefile]]]\n\n",
argv[0]);
printf("Reads a testcase from a file (not stdin!),\n");
printf("writes to stdout when '-' or\n");
printf(
"no output filename is given. As an optional third parameter you can "
"give a file\n");
printf("for splicing. Maximum input and output length is 1MB.\n");
printf("Options:\n");
printf(" -v verbose debug output to stderr.\n");
printf(" -m val max mutations (1-val, val default is 16)\n");
printf(" -x file dictionary file (AFL++ format)\n");
printf("You can set the following environment variable parameters:\n");
printf("AUTOTOKENS_COMMENT` - what character or string starts a comment which will be\n");
printf(" removed. Default: \"/* ... */\"\n");
return 0;
}
FILE *in = stdin, *out = stdout, *splice = NULL;
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
int splicelen = 0, opt;
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
switch (opt) {
case 'm':
max_havoc = atoi(optarg);
mh = optarg;
break;
case 'v':
verbose = 1;
break;
case 'x':
dict = optarg;
break;
default:
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
exit(-1);
}
}
if (max_havoc < 1) {
fprintf(stderr, "Error: illegal -m value\n");
exit(-1);
}
if (argc > optind && strcmp(argv[optind], "-") != 0) {
if ((in = fopen(argv[optind], "r")) == NULL) {
perror(argv[1]);
return -1;
}
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
}
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
if (!inlen) {
fprintf(stderr, "Error: empty file %s\n",
argv[optind] ? argv[optind] : "stdin");
return -1;
}
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
perror(argv[optind + 1]);
return -1;
}
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
}
if (argc > optind + 2) {
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
perror(argv[optind + 2]);
return -1;
}
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
splicebuf = malloc(1024 * 1024);
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
if (!splicelen) {
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
return -1;
}
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
}
/* configure autotokens */
setenv("AUTOTOKENS_LEARN_DICT", "1", 0);
setenv("AUTOTOKENS_CREATE_FROM_THIN_AIR", "1", 0);
setenv("AUTOTOKENS_CHANGE_MAX", mh, 0);
/* fake AFL++ state */
afl_state_t *afl = (afl_state_t *)calloc(1, sizeof(afl_state_t));
afl->queue_cycle = afl->havoc_div = afl->active_items = afl->queued_items = 1;
afl->shm.cmplog_mode = 0;
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
rand_set_seed(afl, getpid());
if (dict) {
load_extras(afl, dict);
if (verbose)
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
afl->extras_cnt);
}
// setup a fake queue entry
afl->queue_buf = malloc(64);
afl->queue_buf[0] = afl->queue_cur =
(struct queue_entry *)malloc(sizeof(struct queue_entry));
afl->queue_cur->testcase_buf = inbuf;
afl->queue_cur->fname = (u8 *)argv[optind];
afl->queue_cur->len = inlen;
afl->queue_cur->perf_score = 100;
afl->queue_cur->favored = afl->queue_cur->is_ascii = 1;
// afl->custom_only = 1;
void *data = (void *)afl_custom_init(afl, (u32)0);
u8 res = afl_custom_queue_get(inbuf, (u8 *)argv[optind]);
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
splicelen, 1024 * 1024);
if (outlen == 0 || !outbuf) {
fprintf(stderr, "Error: no mutation data returned.\n");
return -1;
}
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n");
return -1;
}
return 0;
}

View File

@ -0,0 +1,7 @@
all: custom_send_tcp.so
custom_send_tcp.so:
$(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c
clean:
rm -f custom_send_tcp.so *.o *~ core

View File

@ -0,0 +1,13 @@
# Send testcases via TCP custom mutator
This custom mutator sends the fuzzing testcases via TCP.
`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set!
`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense)
`CUSTOM_SEND_PORT` - the TCP port to send to
`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target
Example:
```
CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ...
```

View File

@ -0,0 +1,113 @@
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include "afl-fuzz.h"
static int my_debug = 0;
static int my_read = 0;
#define DEBUG(...) if (my_debug) printf(__VA_ARGS__)
typedef struct tcp_send_mutator {
afl_state_t* afl;
struct sockaddr_in server_addr;
} tcp_send_mutator_t;
void *afl_custom_init(afl_state_t* afl, uint32_t seed) {
const char* ip = getenv("CUSTOM_SEND_IP");
const char* port = getenv("CUSTOM_SEND_PORT");
if (getenv("AFL_DEBUG")) my_debug = 1;
if (getenv("CUSTOM_SEND_READ")) my_read = 1;
if (!ip || !port) {
fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n");
exit(1);
}
tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t));
if (!mutator) {
fprintf(stderr, "Failed to allocate mutator struct\n");
exit(1);
}
mutator->afl = afl;
bzero(&mutator->server_addr, sizeof(mutator->server_addr));
mutator->server_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) {
fprintf(stderr, "Could not convert target ip address!\n");
exit(1);
}
mutator->server_addr.sin_port = htons(atoi(port));
printf("[+] Custom tcp send mutator setup ready to go!\n");
return mutator;
}
int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) {
while (max_attempts > 0) {
if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) {
return 0;
}
// Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the
// application under test having started to listen for connections and
// afl_custom_fuzz_send being called. To address this race, we attempt
// to connect N times and sleep a short period of time in between
// connection attempts.
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = 100;
nanosleep(&t, NULL);
--max_attempts;
}
return 1;
}
void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
int written = 0;
if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) {
DEBUG("connected, write()\n");
written = write(sock, buf, buf_size);
} else {
DEBUG("socket() or connect() error: %d\n", errno);
}
if (written < 0) {
DEBUG("write() error: %d\n", errno);
} else if (my_read) {
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int select_res = select(sock + 1, &set, NULL, NULL, &timeout);
if (select_res == -1) {
DEBUG("select() error: %d\n", errno);
} else if (select_res == 0) {
DEBUG("read() timeout!\n");
} else {
uint8_t buf[64];
(void)read(sock, buf, sizeof(buf));
}
}
close(sock);
}
void afl_custom_deinit(tcp_send_mutator_t* mutator) {
free(mutator);
}

View File

@ -1 +1 @@
95a6857
05d8f53

View File

@ -3707,7 +3707,7 @@ typedef intptr_t wdiff;
1024 * 1024 * 8 /* static malloc'd heap size if used as a library */
#define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */
#define FMAX \
((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
*/
#define MAXOBJ 0xffff /* max words in tuple including header */
#define MAXPAYL \

View File

@ -5,4 +5,5 @@ members = [
"example",
# Lain needs a nightly toolchain
# "example_lain",
]
# "example_lain_post_process",
]

View File

@ -5,7 +5,15 @@ Bindings to create custom mutators in Rust.
These bindings are documented with rustdoc. To view the documentation run
```cargo doc -p custom_mutator --open```.
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
An example using [lain](https://github.com/microsoft/lain) for structured fuzzing can be found in `example_lain`.
Since lain requires a nightly rust toolchain, you need to set one up before you can play with it.
An example for the use of the post_process function, using [lain](https://github.com/microsoft/lain) with [serde](https://github.com/serde-rs/serde) and [bincode](https://github.com/bincode-org/bincode) can be found in `example_lain_post_process`.
In order for it to work you need to:
- disable input trimming with `AFL_DISABLE_TRIM=1`
- provide an initial instance serialized with `bincode` or use the `AFL_NO_STARTUP_CALIBRATION=1` environment variable.
Note that `bincode` can also be used to serialize/deserialize the lain-generated structure and mutate it rather than generating a new one at each iteration, but it requires some structure serialized with `bincode` as input seed.

View File

@ -73,6 +73,8 @@ pub trait RawCustomMutator {
None
}
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]>;
/*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
int afl_custom_init_trim(&self, buffer: &[u8]);
size_t afl_custom_trim(&self, unsigned char **out_buf);
@ -353,6 +355,33 @@ pub mod wrappers {
Err(err) => panic_handler("afl_custom_queue_get", &err),
}
}
/// Internal function used in the macro
pub unsafe fn afl_custom_post_process<M: RawCustomMutator>(
data: *mut c_void,
buf: *mut u8,
buf_size: usize,
out_buf: *mut *const u8,
) -> usize {
match catch_unwind(|| {
let mut context = FFIContext::<M>::from(data);
assert!(!buf.is_null(), "null buf passed to afl_custom_post_process");
assert!(
!out_buf.is_null(),
"null out_buf passed to afl_custom_post_process"
);
let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
if let Some(buffer) = context.mutator.post_process(buff_slice) {
*out_buf = buffer.as_ptr();
return buffer.len();
}
0
}) {
Ok(ret) => ret,
Err(err) => panic_handler("afl_custom_post_process", &err),
}
}
}
/// An exported macro to defined afl_custom_init meant for insternal usage
@ -480,6 +509,16 @@ macro_rules! export_mutator {
pub unsafe extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) {
$crate::wrappers::afl_custom_deinit_::<$mutator_type>(data)
}
#[no_mangle]
pub unsafe extern "C" fn afl_custom_post_process(
data: *mut ::std::os::raw::c_void,
buf: *mut u8,
buf_size: usize,
out_buf: *mut *const u8,
) -> usize {
$crate::wrappers::afl_custom_post_process::<$mutator_type>(data, buf, buf_size, out_buf)
}
};
}
@ -512,6 +551,10 @@ mod sanity_test {
) -> Option<&'b [u8]> {
unimplemented!()
}
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
unimplemented!()
}
}
export_mutator!(ExampleMutator);
@ -579,6 +622,13 @@ pub trait CustomMutator {
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
Ok(None)
}
fn post_process<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
) -> Result<Option<&'b [u8]>, Self::Error> {
Ok(Some(buffer))
}
}
impl<M> RawCustomMutator for M
@ -682,6 +732,16 @@ where
}
}
}
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
match self.post_process(buffer) {
Ok(r) => r,
Err(e) => {
Self::handle_error(e);
None
}
}
}
}
/// the default value to return from [`CustomMutator::describe`].

View File

@ -8,9 +8,9 @@ edition = "2021"
[dependencies]
custom_mutator = { path = "../custom_mutator" }
lain="0.5"
lain = { git = "https://github.com/AFLplusplus/lain.git" }
[[example]]
name = "example_lain"
path = "./src/lain_mutator.rs"
crate-type = ["cdylib"]
crate-type = ["cdylib"]

View File

@ -0,0 +1,21 @@
[package]
name = "example_lain_post_process"
version = "0.1.0"
authors = [
"Julius Hohnerlein <julihoh@users.noreply.github.com>",
"jma <94166787+jma-qb@users.noreply.github.com>",
]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
custom_mutator = { path = "../custom_mutator" }
lain = { git = "https://github.com/AFLplusplus/lain.git" }
bincode = "1.3.3"
serde = { version = "1.0.214", features = ["derive"] }
[[example]]
name = "example_lain_post_process"
path = "./src/lain_mutator.rs"
crate-type = ["cdylib"]

View File

@ -0,0 +1 @@
nightly

View File

@ -0,0 +1,70 @@
#![cfg(unix)]
use custom_mutator::{export_mutator, CustomMutator};
use lain::{
mutator::Mutator,
prelude::*,
rand::{rngs::StdRng, SeedableRng},
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Mutatable, NewFuzzed, BinarySerialize)]
struct MyStruct {
tag: u8,
#[lain(ignore)]
length: u32,
#[lain(min = 0, max = 10)]
data: Vec<u8>,
}
struct LainMutator {
mutator: Mutator<StdRng>,
buffer: Vec<u8>,
post_buffer: Vec<u8>,
}
impl CustomMutator for LainMutator {
type Error = ();
fn init(seed: u32) -> Result<Self, ()> {
Ok(Self {
mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)),
buffer: Vec::new(),
post_buffer: Vec::new(),
})
}
fn fuzz<'b, 's: 'b>(
&'s mut self,
_buffer: &'b mut [u8],
_add_buff: Option<&[u8]>,
max_size: usize,
) -> Result<Option<&'b [u8]>, ()> {
// we just sample an instance of MyStruct, ignoring the current input
let instance = MyStruct::new_fuzzed(&mut self.mutator, None);
let serialized = bincode::serialize(&instance).unwrap();
let size = serialized.len();
if size > max_size {
return Err(());
}
self.buffer.clear();
self.buffer.reserve(size);
self.buffer.extend_from_slice(&serialized);
Ok(Some(self.buffer.as_slice()))
}
fn post_process<'b, 's: 'b>(
&'s mut self,
buffer: &'b mut [u8],
) -> Result<Option<&'b [u8]>, Self::Error> {
let mut instance = bincode::deserialize::<MyStruct>(&buffer).unwrap();
instance.length = instance.data.len() as u32;
let size = instance.serialized_size();
self.post_buffer.clear();
self.post_buffer.reserve(size);
instance.binary_serialize::<_, BigEndian>(&mut self.post_buffer);
Ok(Some(&self.post_buffer))
}
}
export_mutator!(LainMutator);

View File

@ -0,0 +1,120 @@
#
# AFL dictionary for JSON Schema
# https://json-schema.org/
# -----------------------
#
"\"$schema\""
"\"$id\""
"\"$ref\""
"\"$defs\""
"\"definitions\""
"\"enum\""
"\"const\""
"\"type\""
# Annotations
"\"title\""
"\"description\""
"\"default\""
"\"examples\""
"\"$comment\""
"\"readOnly\""
"\"writeOnly\""
"\"deprecated\""
# Types
"\"string\""
"\"integer\""
"\"number\""
"\"object\""
"\"array\""
"\"null\""
"\"boolean\""
# String
"\"minLength\""
"\"maxLength\""
"\"pattern\""
"\"format\""
"\"contentMediaType\""
"\"contentEncoding\""
"\"contentSchema\""
# Formats
"\"date-time\""
"\"time\""
"\"date\""
"\"duration\""
"\"email\""
"\"idn-email\""
"\"hostname\""
"\"idn-hostname\""
"\"ipv4\""
"\"ipv6\""
"\"uuid\""
"\"uri\""
"\"uri-reference\""
"\"iri\""
"\"iri-reference\""
"\"uri-template\""
"\"json-pointer\""
"\"relative-json-pointer\""
"\"regex\""
# Numeric
"\"multipleOf\""
"\"minimum\""
"\"exclusiveMinimum\""
"\"maximum\""
"\"exclusiveMaximum\""
# Object
"\"properties\""
"\"patternProperties\""
"\"additionalProperties\""
"\"unevaluatedProperties\""
"\"required\""
"\"propertyNames\""
"\"minProperties\""
"\"maxProperties\""
"\"dependencies\""
# Array
"\"items\""
"\"prefixItems\""
"\"additionalItems\""
"\"unevaluatedItems\""
"\"contains\""
"\"minContains\""
"\"maxContains\""
"\"minItems\""
"\"maxItems\""
"\"uniqueItems\""
# Booleans
"true"
"false"
# Composition
"\"allOf\""
"\"anyOf\""
"\"oneOf\""
"\"not\""
# Conditions
"\"dependentRequired\""
"\"dependentSchemas\""
"\"if\""
"\"then\""
"\"else\""

5713
dictionaries/ruby.dict Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,51 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.30c (release)
! afl-gcc and afl-clang funcionality is now removed !
- afl-fuzz:
- fastresume feature added. if you abort fuzzing and resume fuzzing
with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed
then a dump will be loaded and the calibration phase skipped.
to disable this feature set `AFL_NO_FASTRESUME=1`
zlib compression is used if zlib is found at compile time
- improved seed selection algorithm
- added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send()
function after the target has been restarted.
- because of bad math and undefined behaviour fixes we have to change
the CMPLOG map. **YOU NEED TO RECOMPILE CMPLOG TARGETS**
- fixed custom_post_process for calibration
- fixes for AFL_EXIT_ON_TIME and AFL_EXIT_WHEN_DONE, changed behaviour of
AFL_EXIT_WHEN_DONE to finish when really done :-)
- frida_mode:
- AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just
a function entry
- AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE
- AFL_FRIDA_DEBUG_MAPS now works as expected
- qemu_mode:
- new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to
@CowBoy4mH3LL
- unicorn_mode:
- fix install and forkserver (thanks aarnav!)
- pin unicorn version
- nyx_mode:
- bugfixes
- custom mutators:
- custom_send_tcp custom mutator added, thanks to @dergoegge
- afl-cc
- fix to support pointless changes in LLVM 20
- new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla
AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with
AFL_LLVM_INSTRUMENT=CLASSIC
- new compile time variable: `AFL_OPT_LEVEL` to set a specific optimization
level, default is `3`
- correctly explain how to get the correct map size for large targets
- small fix for weird LLVM defines in redhat
- code formatting updated to llvm 18
- improved custom_mutators/aflpp/standalone/aflpp-standalone
- added custom_mutators/autotokens/standalone/autotokens-standalone
- AFL++ headers are now installed to $PREFIX/include/afl
### Version ++4.21c (release)
* afl-fuzz
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
@ -42,7 +87,6 @@
* Fixed a shmem mmap bug (that rarely came up on MacOS)
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built

View File

@ -30,6 +30,9 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
sudo apt-get install -y ninja-build # for QEMU mode
sudo apt-get install -y cpio libcapstone-dev # for Nyx mode
sudo apt-get install -y wget curl # for Frida mode
sudo apt-get install -y python3-pip # for Unicorn mode
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib

View File

@ -38,9 +38,8 @@ For PCGUARD instrumentation `abort()` is called if this is detected, for LTO
there will either be no coverage for the instrumented dlopen()'ed libraries or
you will see lots of crashes in the UI.
Note that this is not an issue if you use the inferiour `afl-gcc-fast`,
`afl-gcc` or`AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast`
instrumentation.
Note that this is not an issue if you use the inferiour `afl-gcc-fast`, or
`AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast` instrumentation.
### Fuzzing a binary-only target

View File

@ -198,6 +198,11 @@ def deinit(): # optional for Python
This method can be used if you want to send data to the target yourself,
e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
that you start the target with afl-fuzz.
Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
function after the target has been restarted. (This is needed for e.g. TCP
services.)
Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
- `queue_new_entry` (optional):

View File

@ -24,7 +24,6 @@ To select the different instrumentation modes, use one of the following options:
- Use the `AFL_CC_COMPILER` environment variable with `MODE`. To select
`MODE`, use one of the following values:
- `GCC` (afl-gcc/afl-g++)
- `GCC_PLUGIN` (afl-g*-fast)
- `LLVM` (afl-clang-fast*)
- `LTO` (afl-clang-lto*).
@ -45,14 +44,10 @@ fairly broad use of environment variables instead:
make
```
- Setting `AFL_AS`, `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
compilation tools, rather than the default 'as', 'clang', or 'gcc' binaries
- Setting `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
compilation tools, rather than the default 'clang', or 'gcc' binaries
in your `$PATH`.
- If you are a weird person that wants to compile and instrument asm text
files, then use the `AFL_AS_FORCE_INSTRUMENT` variable:
`AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo`
- Most AFL tools do not print any output if stdout/stderr are redirected. If
you want to get the output into a file, then set the `AFL_DEBUG` environment
variable. This is sadly necessary for various build processes which fail
@ -64,6 +59,9 @@ fairly broad use of environment variables instead:
optimizations, set `AFL_DONT_OPTIMIZE`. However, if `-O...` and/or
`-fno-unroll-loops` are set, these are not overridden.
- The optimization level can also be set with `AFL_OPT_LEVEL`, e.g.
`AFL_OPT_LEVEL=z` for `-Oz`, default is `3`
- Setting `AFL_HARDEN` automatically adds code hardening options when invoking
the downstream compiler. This currently includes `-D_FORTIFY_SOURCE=2` and
`-fstack-protector-all`. The setting is useful for catching non-crashing
@ -80,17 +78,13 @@ fairly broad use of environment variables instead:
Setting `AFL_INST_RATIO` to 0 is a valid choice. This will instrument only
the transitions between function entry points, but not individual branches.
Note that this is an outdated variable. A few instances (e.g., afl-gcc)
still support these, but state-of-the-art (e.g., LLVM LTO and LLVM PCGUARD)
do not need this.
Note that this is an outdated variable. Only LLVM CLASSIC pass can use this.
- `AFL_NO_BUILTIN` causes the compiler to generate code suitable for use with
libtokencap.so (but perhaps running a bit slower than without the flag).
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
One possible use of this is utils/clang_asm_normalize/, which lets you
instrument hand-written assembly when compiling clang code by plugging a
normalizer into the chain. (There is no equivalent feature for GCC.)
- `AFL_PATH` can be used to point a directory that contains LLVM/GCC plugins
for AFL++, AFL++'s runtime objects and QEMU/Frida support files.
- Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being
displayed during compilation, in case you find them distracting.
@ -101,6 +95,7 @@ fairly broad use of environment variables instead:
detection)
- `AFL_USE_CFISAN=1` - activates the Control Flow Integrity sanitizer (e.g.
type confusion vulnerabilities)
- `AFL_CFISAN_VERBOSE=1` - outputs detailed information when control flow integrity violations occur, instead of simply terminating with "Illegal Instruction"
- `AFL_USE_LSAN` - activates the leak sanitizer. To perform a leak check
within your program at a certain point (such as at the end of an
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
@ -111,6 +106,9 @@ fairly broad use of environment variables instead:
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
conditions
- `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer
- `AFL_UBSAN_VERBOSE=1` - outputs detailed diagnostic information when undefined behavior is detected, instead of simply terminating with "Illegal Instruction"
- Note: both `AFL_CFISAN_VERBOSE=1` and `AFL_UBSAN_VERBOSE=1` are disabled by default as verbose output can significantly slow down fuzzing performance. Use these options only during debugging or when additional crash diagnostics are required
- `TMPDIR` is used by afl-as for temporary files; if this variable is not set,
the tool defaults to /tmp.
@ -323,6 +321,11 @@ mode.
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
for more information.
Setting `AFL_GCC_DISABLE_VERSION_CHECK=1` will disable the GCC plugin
version check if the target GCC plugin differs from the system-installed
version, resolving issues caused by version mismatches between GCC and
the plugin.
Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the
code with calls to an injected subroutine instead of the much more efficient
inline instrumentation.
@ -331,7 +334,26 @@ mode.
the target performs only a few loops, then this will give a small
performance boost.
## 4) Settings for afl-fuzz
## 4) Runtime settings
The following environment variables are for a compiled AFL++ target.
- Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will
dump the map size of the target and exit.
- Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver.
This makes only sense when you
a) compile in a classic colliding coverage mode (e.g.
AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is
below MAP_SIZE (65536 by default), AND
b) you want to use this compiled AFL++ target with a different tool
that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc.
You would use this option together with the target fuzzing application.
- Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting
instrumentation. (More of an internal option.)
## 5) Settings for afl-fuzz
The main fuzzer binary accepts several options that disable a couple of sanity
checks or alter some of the more exotic semantics of the tool:
@ -368,6 +390,10 @@ checks or alter some of the more exotic semantics of the tool:
XML or other highly flexible structured input. For details, see
[custom_mutators.md](custom_mutators.md).
- Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
function after the target has been restarted. (This is needed for e.g. TCP
services.)
- Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time
a cycle is finished.
@ -401,9 +427,8 @@ checks or alter some of the more exotic semantics of the tool:
types of automated jobs.
- `AFL_EXIT_WHEN_DONE` causes afl-fuzz to terminate when all existing paths
have been fuzzed and there were no new finds for a while. This would be
normally indicated by the cycle counter in the UI turning green. May be
convenient for some types of automated jobs.
have been fuzzed and there were no new finds for a while. This is basically
when the fuzzing state says `state: finished`
- Setting `AFL_EXPAND_HAVOC_NOW` will start in the extended havoc mode that
includes costly mutations. afl-fuzz automatically enables this mode when
@ -514,6 +539,8 @@ checks or alter some of the more exotic semantics of the tool:
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
the snapshot lkm is loaded.
- `AFL_NO_FASTRESUME` will not try to read or write a fast resume file.
- Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints
some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe.
@ -585,7 +612,7 @@ checks or alter some of the more exotic semantics of the tool:
see [rpc_statsd.md](rpc_statsd.md).
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes)
between fuzzing instances synchronization. Default sync time is 30 minutes,
between fuzzing instances synchronization. Default sync time is 20 minutes,
note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
@ -636,7 +663,7 @@ checks or alter some of the more exotic semantics of the tool:
Note that will not be exact and with slow targets it can take seconds
until there is a slice for the time test.
## 5) Settings for afl-qemu-trace
## 6) Settings for afl-qemu-trace
The QEMU wrapper used to instrument binary-only code supports several settings:
@ -708,7 +735,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when
counting crashes based on a file count in that directory.
## 7) Settings for afl-frida-trace
## 8) Settings for afl-frida-trace
The FRIDA wrapper used to instrument binary-only code supports many of the same
options as `afl-qemu-trace`, but also has a number of additional advanced
@ -798,7 +825,7 @@ support.
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
killing the process whilst it is being dumped.
## 8) Settings for afl-cmin
## 9) Settings for afl-cmin
The corpus minimization script offers very little customization:
@ -816,7 +843,7 @@ The corpus minimization script offers very little customization:
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed.
This can help when embedding `afl-cmin` or `afl-showmap` in other scripts.
## 9) Settings for afl-tmin
## 10) Settings for afl-tmin
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be
searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a
@ -827,12 +854,12 @@ to match when minimizing crashes. This will make minimization less useful, but
may prevent the tool from "jumping" from one crashing condition to another in
very buggy software. You probably want to combine it with the `-e` flag.
## 10) Settings for afl-analyze
## 11) Settings for afl-analyze
You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
of decimal.
## 11) Settings for libdislocator
## 12) Settings for libdislocator
The library honors these environment variables:
@ -854,12 +881,12 @@ The library honors these environment variables:
- `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that
may be useful for pinpointing the cause of any observed issues.
## 11) Settings for libtokencap
## 13) Settings for libtokencap
This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
discovered tokens should be written.
## 12) Third-party variables set by afl-fuzz & other tools
## 14) Third-party variables set by afl-fuzz & other tools
Several variables are not directly interpreted by afl-fuzz, but are set to
optimal values if not already present in the environment:

View File

@ -6,20 +6,22 @@ QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
## Features and instrumentation
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
| Threadsafe counters [A] | | x(3) | | | | | x | |
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | |
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
| CmpLog [E] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
| Selective Instrumentation [F] | | x | x | x | x | | | |
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | |
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | |
| Context Coverage [I] | | x(6) | | | | | | |
| Auto Dictionary [J] | | x(7) | | | | | | |
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | |
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | |
Note that afl-gcc and afl-clang have been removed because their instrumentation is absolutely outdated.
| Feature/Instrumentation | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
| ------------------------------|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
| Threadsafe counters [A] | x(3) | | | | | x | |
| NeverZero [B] | x(1) | x | x | x | x | | |
| Persistent Mode [C] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
| LAF-Intel / CompCov [D] | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
| CmpLog [E] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
| Selective Instrumentation [F] | x | x | x | x | | | |
| Non-Colliding Coverage [G] | x(4) | | | (x)(5) | | | |
| Ngram prev_loc Coverage [H] | x(6) | | | | | | |
| Context Coverage [I] | x(6) | | | | | | |
| Auto Dictionary [J] | x(7) | | | | | | |
| Snapshot Support [K] | (x)(8) | (x)(8) | | (x)(5) | | x | |
| Shared Memory Test cases [L] | x | x | x86[_64]/arm64 | x | x | x | |
## More information about features
@ -94,7 +96,7 @@ L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase
Among others, the following features and patches have been integrated:
* NeverZero patch for afl-gcc, instrumentation, QEMU mode and unicorn_mode which
* NeverZero for llvm/gcc instrumentation, QEMU mode and unicorn_mode which
prevents a wrapping map value to zero, increases coverage
* Persistent mode, deferred forkserver and in-memory fuzzing for QEMU mode
* Unicorn mode which allows fuzzing of binaries from completely different

View File

@ -46,10 +46,9 @@ The following setup to use QEMU mode is recommended:
`AFL_COMPCOV_LEVEL=2`), alternatively you can use FRIDA mode, just switch `-Q`
with `-O` and remove the LAF instance
Then run as many instances as you have cores left with either -Q mode or - even
better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
The binary rewriters all have their own advantages and caveats.
ZAFL is the best but cannot be used in a business/commercial context.
Then run as many instances as you have cores left with either `-Q` mode or use
a static binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
The binary rewriters all have their own advantages and caveats, but ZAFL is a good choice.
If a binary rewriter works for your target then you can use afl-fuzz normally
and it will have twice the speed compared to QEMU mode (but slower than QEMU
@ -200,6 +199,7 @@ have an x86_64 or arm64 binary that does not contain C++ exceptions and - if
x86_64 - still has it's symbols and compiled with position independent code
(PIC/PIE), then the RetroWrite solution might be for you.
It decompiles to ASM files which can then be instrumented with afl-gcc.
Note that afl-gcc is only present until AFL++ v4.21c and was subsequently removed as it is obsolete.
Binaries that are statically instrumented for fuzzing using RetroWrite are close
in performance to compiler-instrumented binaries and outperform the QEMU-based

View File

@ -61,6 +61,8 @@ evaluation flow will help you to select the best possible.
It is highly recommended to have the newest llvm version possible installed,
anything below 9 is not recommended.
IMPORTANT NOTICE: afl-gcc/afl-clang have been removed from AFL++ as they are obsolete.
```
+--------------------------------+
| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
@ -84,7 +86,7 @@ anything below 9 is not recommended.
| if not, or if you do not have a gcc with plugin support
|
v
use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)
GAME OVER! Install gcc-VERSION-plugin-dev or llvm-VERSION-dev
```
Clickable README links for the chosen compiler:
@ -92,14 +94,12 @@ Clickable README links for the chosen compiler:
* [LTO mode - afl-clang-lto](../instrumentation/README.lto.md)
* [LLVM mode - afl-clang-fast](../instrumentation/README.llvm.md)
* [GCC_PLUGIN mode - afl-gcc-fast](../instrumentation/README.gcc_plugin.md)
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
features
You can select the mode for the afl-cc compiler by one of the following methods:
* Using a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
* Using a symlink to afl-cc:
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
afl-gcc-fast, afl-g++-fast (recommended!).
afl-gcc-fast, afl-g++-fast.
* Using the environment variable `AFL_CC_COMPILER` with `MODE`.
* Passing --afl-`MODE` command line options to the compiler via
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`.
@ -108,8 +108,7 @@ You can select the mode for the afl-cc compiler by one of the following methods:
* LTO (afl-clang-lto*)
* LLVM (afl-clang-fast*)
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++)
* CLANG(afl-clang/afl-clang++)
* GCC_PLUGIN (afl-g*-fast)
Because no AFL++ specific command-line options are accepted (beside the
--afl-MODE command), the compile-time tools make fairly broad use of environment
@ -201,6 +200,9 @@ type. This is enough because e.g. a use-after-free bug will be picked up by ASAN
(address sanitizer) anyway after syncing test cases from other fuzzing
instances, so running more than one address sanitized target would be a waste.
*IF* you are running a saturated corpus, then you can run up to half of the
instances with sanitizers.
The following sanitizers have built-in support in AFL++:
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
@ -632,7 +634,7 @@ crash or timeout during startup.
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
from other fuzzers in the campaign first. But note that can slow down the start
of the first fuzz by quite a lot of you have many fuzzers and/or many seeds.
of the first fuzz by quite a lot if you have many fuzzers and/or many seeds.
If you have a large corpus, a corpus from a previous run or are fuzzing in a CI,
then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.

View File

@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE
arm:
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all
arm64:
ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

View File

@ -6,34 +6,39 @@
#define UNUSED_PARAMETER(x) (void)(x)
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
{
UNUSED_PARAMETER (size);
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
ElfW(Addr) * base = data;
UNUSED_PARAMETER(size);
ElfW(Addr) *base = data;
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
return 0;
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
return 0;
}
int main (int argc, char** argv, char** envp) {
UNUSED_PARAMETER (argc);
int main(int argc, char **argv, char **envp) {
ElfW(Addr) base = 0;
UNUSED_PARAMETER(argc);
int persona = personality(ADDR_NO_RANDOMIZE);
if (persona == -1) {
ElfW(Addr) base = 0;
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
return 1;
}
int persona = personality(ADDR_NO_RANDOMIZE);
if (persona == -1) {
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
return 1;
dl_iterate_phdr(phdr_callback, &base);
}
printf("%p\n", (void *)base);
if (base == 0) { return 1; }
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
dl_iterate_phdr(phdr_callback, &base);
printf("%p\n", (void *)base);
if (base == 0) { return 1; }
return 0;
return 0;
}

View File

@ -45,6 +45,7 @@
js_api_set_stdout;
js_api_set_traceable;
js_api_set_verbose;
js_api_ijon_set;
local:
*;

View File

@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
// do a length check matching the target!
void **esp = (void **)regs->esp;
void *arg1 = esp[0];
void **arg2 = &esp[1];
void *arg1 = esp[1];
void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;

View File

@ -36,7 +36,7 @@ struct x86_64_regs {
void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
memcpy((void *)regs->rdi, input_buf, input_buf_len);
regs->rsi = input_buf_len;
@ -76,14 +76,15 @@ struct x86_regs {
void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
void **esp = (void **)regs->esp;
void * arg1 = esp[1];
void *arg1 = esp[1];
void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;
}
#elif defined(__aarch64__)
struct arm64_regs {
@ -177,9 +178,10 @@ struct arm64_regs {
void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */
(void)guest_base; /* unused */
memcpy((void *)regs->x0, input_buf, input_buf_len);
regs->x1 = input_buf_len;
}
#else
@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) {
return 1;
}

View File

@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed;
extern uint8_t *__afl_area_ptr;
extern uint32_t __afl_map_size;
extern void __afl_coverage_interesting(uint8_t, uint32_t);
extern __thread guint64 *instrument_previous_pc_addr;
@ -72,5 +73,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data);
void instrument_regs_format(int fd, char *format, ...);
void ijon_set(uint32_t edge);
#endif

View File

@ -39,18 +39,18 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
address = base + index + mem->disp;
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
asan_loadN(address, asan_ctx->size);
}
if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) {
asan_storeN(address, asan_ctx->size);
}
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
asan_loadN(address, asan_ctx->size);
}
}
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {

View File

@ -449,3 +449,9 @@ void instrument_regs_format(int fd, char *format, ...) {
}
void ijon_set(uint32_t edge) {
__afl_coverage_interesting(1, edge);
}

View File

@ -818,6 +818,9 @@ void instrument_coverage_unstable_find_output(void) {
GDir *dir = g_dir_open(fds_name, 0, NULL);
gchar *path_tmp = getenv("AFL_CUSTOM_INFO_OUT");
gchar *instance_name = g_path_get_basename(path_tmp);
FVERBOSE("Coverage Unstable - fds: %s", fds_name);
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
@ -829,7 +832,7 @@ void instrument_coverage_unstable_find_output(void) {
if (link == NULL) { FFATAL("Failed to read link: %s", fullname); }
gchar *basename = g_path_get_basename(link);
if (g_strcmp0(basename, "default") != 0) {
if (g_strcmp0(basename, instance_name) != 0) {
g_free(basename);
g_free(link);
@ -874,6 +877,7 @@ void instrument_coverage_unstable_find_output(void) {
}
g_dir_close(dir);
g_free(instance_name);
g_free(fds_name);
if (unstable_coverage_fuzzer_stats == NULL) {

View File

@ -326,6 +326,12 @@ class Afl {
static jsApiGetSymbol(name) {
return Afl.module.getExportByName(name);
}
static IJON = class {
static set(addr, val) {
Afl.jsApiIjonSet((addr ^ val) & 0xffffffff);
}
}
}
/**
* Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode
@ -377,3 +383,4 @@ Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
Afl.jsApiWrite = new NativeFunction(
/* tslint:disable-next-line:no-null-keyword */
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
Afl.jsApiIjonSet = Afl.jsApiGetFunction("js_api_ijon_set", "void", ["uint32"]);

View File

@ -316,3 +316,9 @@ __attribute__((visibility("default"))) void js_api_set_verbose(void) {
}
__attribute__((visibility("default"))) void js_api_ijon_set(uint32_t edge) {
ijon_set(edge);
}

View File

@ -33,7 +33,7 @@
// r15 - pc
static GumCpuContext saved_regs = {0};
static gpointer saved_lr = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
}
static void instrument_exit(GumArmWriter *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0);
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
GUM_ARG_REGISTER, ARM_REG_R0);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE);
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_ret));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0);
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumArmWriter *cw = output->writer.arm;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_arm_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_arm_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0);
gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm_writer_put_b_label(cw, loop);
/* done: */
gum_arm_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_loop));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);

View File

@ -16,7 +16,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_lr = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
}
static void instrument_exit(GumArm64Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
gum_arm64_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
GUM_INDEX_PRE_ADJUST);
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr));
GUM_ADDRESS(&persistent_ret));
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumArm64Writer *cw = output->writer.arm64;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_arm64_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_arm64_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm64_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm64_writer_put_b_label(cw, loop);
/* done: */
gum_arm64_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm64_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr));
GUM_ADDRESS(&persistent_loop));
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0);

View File

@ -17,7 +17,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
}
static void instrument_exit(GumX86Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
-(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE));
@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
/*
* If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
}
void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
gum_x86_writer_put_label(cw, zero);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
}

View File

@ -16,8 +16,7 @@ typedef struct {
} persistent_ctx_t;
static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL;
static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) {
@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
}
static void instrument_exit(GumX86Writer *cw) {
static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit));
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0);
gum_x86_writer_put_push_reg(cw, GUM_X86_EDI);
gum_x86_writer_put_call_reg(cw, GUM_X86_EAX);
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized");
@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) {
}
*instrument_previous_pc_addr = instrument_hash_zero;
return ret;
}
@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
}
@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS
* SAVE RET
* POP RET
* loop:
* loop: (Save address of where the eiplogue should jump back to)
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* CALL hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached");
/* Pop the return value */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
/*
* If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */
gum_x86_writer_put_label(cw, loop);
/* Store a pointer to where we should return for our next iteration */
persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
}
void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
/* The stack should be aligned when we re-enter our loop */
gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0);
gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
}

View File

@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) {
if (!initialized) {
initialized = TRUE;
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) {
util_verbose = TRUE;
}
}

View File

@ -6,46 +6,45 @@
void LLVMFuzzerTestOneInput(char *buf, int len);
__asm__ (
"LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n"
" nop\n"
" nop\n"
"call_target:\n"
" ret\n"
" nop\n"
" nop\n"
"jmp_target:\n"
" callq *call_offset(%rip)\n"
" nop\n"
" nop\n"
" leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n"
" nop\n"
" ud2\n"
" nop\n"
"rax_target:\n"
" ret\n"
"\n"
"\n"
".global jmp_offset\n"
".p2align 3\n"
"jmp_offset:\n"
" .quad jmp_target\n"
"call_offset:\n"
" .quad call_target\n"
"rax_offset:\n"
" .quad rax_target\n"
);
__asm__(
"LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n"
" nop\n"
" nop\n"
"call_target:\n"
" ret\n"
" nop\n"
" nop\n"
"jmp_target:\n"
" callq *call_offset(%rip)\n"
" nop\n"
" nop\n"
" leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n"
" nop\n"
" ud2\n"
" nop\n"
"rax_target:\n"
" ret\n"
"\n"
"\n"
".global jmp_offset\n"
".p2align 3\n"
"jmp_offset:\n"
" .quad jmp_target\n"
"call_offset:\n"
" .quad call_target\n"
"rax_offset:\n"
" .quad rax_target\n");
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -6,8 +6,8 @@
static bool cmov_test(char *x, char *y, size_t len) {
register char * __rdi __asm__("rdi") = x;
register char * __rsi __asm__("rsi") = y;
register char *__rdi __asm__("rdi") = x;
register char *__rsi __asm__("rsi") = y;
register size_t __rcx __asm__("rcx") = len;
register long __rax __asm__("rax");
@ -49,10 +49,10 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -41,7 +41,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
@ -51,6 +51,7 @@ int run(char *file) {
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
break;
@ -110,8 +111,10 @@ void slow() {
}
TESTINSTR_SECTION int do_run(char * file) {
TESTINSTR_SECTION int do_run(char *file) {
return run(file);
}
int main(int argc, char **argv) {

View File

@ -19,32 +19,40 @@
typedef void (*fntestinstrlib)(char *buf, int len);
void testinstr(char *buf, int len) {
void *lib = dlopen("testinstrlib.so", RTLD_NOW);
if (lib == NULL) {
puts("Library not found");
abort();
}
fntestinstrlib fn = (fntestinstrlib)(dlsym(lib, "testinstrlib"));
if (fn == NULL) {
puts("Function not found");
abort();
}
fn(buf, len);
}
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
if (argc != 2) { return 1; }
do {
file = argv[1];
printf("file: %s\n", file);
@ -52,33 +60,43 @@ int main(int argc, char **argv) {
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
break;
}
len = lseek(fd, 0, SEEK_END);
if (len < 0) {
perror("lseek (SEEK_END)");
break;
}
if (lseek(fd, 0, SEEK_SET) != 0) {
perror("lseek (SEEK_SET)");
break;
}
printf("len: %ld\n", len);
buf = malloc(len);
if (buf == NULL) {
perror("malloc");
break;
}
n_read = read(fd, buf, len);
if (n_read != len) {
perror("read");
break;
}
dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read);
@ -95,4 +113,6 @@ int main(int argc, char **argv) {
if (fd != -1) { close(fd); }
return result;
}

View File

@ -1,6 +1,7 @@
#include <stdio.h>
void testinstrlib(char *buf, int len) {
if (len < 1) return;
buf[len] = 0;
@ -11,4 +12,6 @@ void testinstrlib(char *buf, int len) {
printf("Pretty sure that is a one!\n");
else
printf("Neither one or zero? How quaint!\n");
}

View File

@ -41,7 +41,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -35,7 +35,7 @@ int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -22,60 +22,60 @@
#define IGNORED_RETURN(x) (void)!(x)
const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t
crc32(const void *buf, size_t size)
{
const uint8_t *p = buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
uint32_t crc32(const void *buf, size_t size) {
const uint8_t *p = buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
/*
@ -83,11 +83,13 @@ crc32(const void *buf, size_t size)
* FRIDA to patch this function out and always return success. Otherwise, we
* could change it to actually correct the checksum.
*/
int crc32_check (char * buf, int len) {
int crc32_check(char *buf, int len) {
if (len < sizeof(uint32_t)) { return 0; }
uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)];
uint32_t calculated = crc32(buf, len - sizeof(uint32_t));
return expected == calculated;
}
/*
@ -97,27 +99,31 @@ int crc32_check (char * buf, int len) {
* cloud your output unnecessarily. Again, we can use FRIDA to patch it out.
*/
void some_boring_bug(char c) {
switch (c) {
case 'A'...'Z':
case 'a'...'z':
case 'A' ... 'Z':
case 'a' ... 'z':
__builtin_trap();
break;
}
}
extern void some_boring_bug2(char c);
__asm__ (
".text \n"
"some_boring_bug2: \n"
".global some_boring_bug2 \n"
".type some_boring_bug2, @function \n"
"mov %edi, %eax \n"
"cmp $0xb4, %al \n"
"jne ok \n"
"ud2 \n"
"ok: \n"
"ret \n");
__asm__(
".text \n"
"some_boring_bug2: \n"
".global some_boring_bug2 \n"
".type some_boring_bug2, @function \n"
"mov %edi, %eax \n"
"cmp $0xb4, %al \n"
"jne ok \n"
"ud2 \n"
"ok: \n"
"ret \n");
void LLVMFuzzerTestOneInput(char *buf, int len) {
@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
some_boring_bug2(buf[0]);
if (buf[0] == '0') {
printf("Looks like a zero to me!\n");
}
else if (buf[0] == '1') {
} else if (buf[0] == '1') {
printf("Pretty sure that is a one!\n");
}
else if (buf[0] == '2') {
} else if (buf[0] == '2') {
printf("Oh we, weren't expecting that!");
__builtin_trap();
}
else
} else
printf("Neither one or zero? How quaint!\n");
}
@ -145,7 +155,7 @@ int main(int argc, char **argv) {
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;
@ -173,5 +183,6 @@ int main(int argc, char **argv) {
printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
return 0;
}

View File

@ -4,66 +4,68 @@
#include <stdlib.h>
#include <dlfcn.h>
//typedef for our exported target function.
// typedef for our exported target function.
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
//globals
// globals
CRASHME fpn_crashme = NULL;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
fpn_crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
fpn_crashme(data, size);
return 0;
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char*)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
return 0;
return 0;
}
__attribute__((constructor()))
void constructor(void) {
// handles to required libs
void *dylib = NULL;
__attribute__((constructor())) void constructor(void) {
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
if (dylib == NULL)
{
// handles to required libs
void *dylib = NULL;
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
if (dylib == NULL) {
}
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
printf("[+] Resolve function\n");
}
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme)
{
printf("[+] Resolve function\n");
printf("[-] Failed to find function\n");
exit(1);
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme) {
}
printf("[-] Failed to find function\n");
exit(1);
}
printf("[+] Found function.\n");
printf("[+] Found function.\n");
}

View File

@ -4,66 +4,68 @@
#include <stdlib.h>
#include <dlfcn.h>
//typedef for our exported target function.
// typedef for our exported target function.
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
//globals
// globals
CRASHME fpn_crashme = NULL;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
fpn_crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
fpn_crashme(data, size);
return 0;
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char*)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
return 0;
return 0;
}
__attribute__((constructor()))
void constructor(void) {
// handles to required libs
void *dylib = NULL;
__attribute__((constructor())) void constructor(void) {
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
if (dylib == NULL)
{
// handles to required libs
void *dylib = NULL;
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
if (dylib == NULL) {
}
printf("[-] Failed to load lib\n");
printf("[-] Dlerror: %s\n", dlerror());
exit(1);
printf("[+] Resolve function\n");
}
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme)
{
printf("[+] Resolve function\n");
printf("[-] Failed to find function\n");
exit(1);
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
if (!fpn_crashme) {
}
printf("[-] Failed to find function\n");
exit(1);
}
printf("[+] Found function.\n");
printf("[+] Found function.\n");
}

View File

@ -4,37 +4,42 @@
#include <stdlib.h>
#include <dlfcn.h>
extern void crashme(const uint8_t *Data, size_t Size);
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
crashme(data, size);
return 0;
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
crashme(data, size);
return 0;
}
void run (int argc, const char * argv[])
{
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char*)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
void run(int argc, const char *argv[]) {
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
}
int main(int argc, const char * argv[])
{
int main(int argc, const char *argv[]) {
run(argc, argv);
run(argc, argv);
return 0;
return 0;
}

View File

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <stdint.h>
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 5) return;
@ -13,5 +12,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Data[3] == '$')
if (Data[4] == '$') abort();
}

View File

@ -3,7 +3,6 @@
#include <stdint.h>
#include <string.h>
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 1) return;
@ -56,6 +55,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
}
}

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -20,22 +20,32 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
int ret = 0;
for (int i = 0; i < 1000; i++) {
switch(buf[i]) {
case 'A': ret += 2; break;
case '1': ret += 3; break;
default: ret++;
switch (buf[i]) {
case 'A':
ret += 2;
break;
case '1':
ret += 3;
break;
default:
ret++;
}
}
printf("ret: %d\n", ret);
}
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -18,7 +18,7 @@
void LLVMFuzzerTestOneInput(char *buf, int len) {
printf (">>> LLVMFuzzerTestOneInput >>>\n");
printf(">>> LLVMFuzzerTestOneInput >>>\n");
if (len < 1) return;
buf[len] = 0;
@ -40,10 +40,10 @@ void slow() {
int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -48,7 +48,7 @@ all: $(TEST_BIN)
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
arm:
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN)
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN)
$(BUILD_DIR):
mkdir -p $@
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
cd $(LIBZ_DIR) && \
CFLAGS="$(CFLAGS) -fPIC" \
./configure \
--static \
--archs="$(ARCH)"
--static
$(LIBZ_LIB): | $(LIBZ_PC)
CFLAGS="$(CFLAGS) -fPIC" \
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
LDFLAGS="-L$(LIBZ_DIR)" \
./configure \
--host="$(ARCH)"
--host="$(PNG_ARCH)"
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \

View File

@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
TESTINSTR_SECTION int main(int argc, char **argv) {
char * file;
char *file;
int fd = -1;
off_t len;
char * buf = NULL;
char *buf = NULL;
size_t n_read;
int result = -1;

View File

@ -22,7 +22,7 @@
#define TESTINSTR_SECTION __attribute__((section(".testinstr")))
#endif
void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
void LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 1) return;
@ -30,9 +30,13 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (gettimeofday(&tv, NULL) < 0) return;
if ((tv.tv_usec % 2) == 0) {
printf ("Hooray all even\n");
printf("Hooray all even\n");
} else {
printf ("Hmm that's odd\n");
printf("Hmm that's odd\n");
}
// we support three input cases
@ -45,26 +49,33 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
}
void run_test(char * file) {
void run_test(char *file) {
fprintf(stderr, "Running: %s\n", file);
FILE *f = fopen(file, "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char*)malloc(len);
size_t n_read = fread(buf, 1, len, f);
unsigned char *buf = (unsigned char *)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", file, n_read);
}
int main(int argc, char **argv) {
srand(1);
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
for (int i = 1; i < argc; i++) {
run_test(argv[i]);
}
}

View File

@ -1,775 +0,0 @@
/*
american fuzzy lop++ - injectable parts
---------------------------------------
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://www.apache.org/licenses/LICENSE-2.0
This file houses the assembly-level instrumentation injected into fuzzed
programs. The instrumentation stores XORed pairs of data: identifiers of the
currently executing branch and the one that executed immediately before.
TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++
The code is designed for 32-bit and 64-bit x86 systems. Both modes should
work everywhere except for Apple systems. Apple does relocations differently
from everybody else, so since their OSes have been 64-bit for a longer while,
I didn't go through the mental effort of porting the 32-bit code.
In principle, similar code should be easy to inject into any well-behaved
binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural
targets for instrumentation, and should offer comparable probe density.
*/
#ifndef _HAVE_AFL_AS_H
#define _HAVE_AFL_AS_H
#include "config.h"
#include "types.h"
/*
------------------
Performances notes
------------------
Contributions to make this code faster are appreciated! Here are some
rough notes that may help with the task:
- Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are
really worth optimizing; the setup / fork server stuff matters a lot less
and should be mostly just kept readable.
- We're aiming for modern CPUs with out-of-order execution and large
pipelines; the code is mostly follows intuitive, human-readable
instruction ordering, because "textbook" manual reorderings make no
substantial difference.
- Interestingly, instrumented execution isn't a lot faster if we store a
variable pointer to the setup, log, or return routine and then do a reg
call from within trampoline_fmt. It does speed up non-instrumented
execution quite a bit, though, since that path just becomes
push-call-ret-pop.
- There is also not a whole lot to be gained by doing SHM attach at a
fixed address instead of retrieving __afl_area_ptr. Although it allows us
to have a shorter log routine inserted for conditional jumps and jump
labels (for a ~10% perf gain), there is a risk of bumping into other
allocations created by the program or by tools such as ASAN.
- popf is *awfully* slow, which is why we're doing the lahf / sahf +
overflow test trick. Unfortunately, this forces us to taint eax / rax, but
this dependency on a commonly-used register still beats the alternative of
using pushf / popf.
One possible optimization is to avoid touching flags by using a circular
buffer that stores just a sequence of current locations, with the XOR stuff
happening offline. Alas, this doesn't seem to have a huge impact:
https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ
- Preforking one child a bit sooner, and then waiting for the "go" command
from within the child, doesn't offer major performance gains; fork() seems
to be relatively inexpensive these days. Preforking multiple children does
help, but badly breaks the "~1 core per fuzzer" design, making it harder to
scale up. Maybe there is some middle ground.
Perhaps of note: in the 64-bit version for all platforms except for Apple,
the instrumentation is done slightly differently than on 32-bit, with
__afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm),
rather than global (.comm). This is to avoid GOTRELPC lookups in the critical
code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to
work; simple relocations between .bss and .text won't work on most 64-bit
platforms in such a case.
(Fun fact: on Apple systems, .lcomm can segfault the linker.)
The side effect is that state transitions are measured in a somewhat
different way, with previous tuple being recorded separately within the scope
of every .c file. This should have no impact in any practical sense.
Another side effect of this design is that getenv() will be called once per
every .o file when running in non-instrumented mode; and since getenv() tends
to be optimized in funny ways, we need to be very careful to save every
oddball register it may touch.
*/
static const u8 *trampoline_fmt_32 =
"\n"
"/* --- AFL TRAMPOLINE (32-BIT) --- */\n"
"\n"
".align 4\n"
"\n"
"leal -16(%%esp), %%esp\n"
"movl %%edi, 0(%%esp)\n"
"movl %%edx, 4(%%esp)\n"
"movl %%ecx, 8(%%esp)\n"
"movl %%eax, 12(%%esp)\n"
"movl $0x%08x, %%ecx\n"
"call __afl_maybe_log\n"
"movl 12(%%esp), %%eax\n"
"movl 8(%%esp), %%ecx\n"
"movl 4(%%esp), %%edx\n"
"movl 0(%%esp), %%edi\n"
"leal 16(%%esp), %%esp\n"
"\n"
"/* --- END --- */\n"
"\n";
static const u8 *trampoline_fmt_64 =
"\n"
"/* --- AFL TRAMPOLINE (64-BIT) --- */\n"
"\n"
".align 4\n"
"\n"
"leaq -(128+24)(%%rsp), %%rsp\n"
"movq %%rdx, 0(%%rsp)\n"
"movq %%rcx, 8(%%rsp)\n"
"movq %%rax, 16(%%rsp)\n"
"movq $0x%08x, %%rcx\n"
"call __afl_maybe_log\n"
"movq 16(%%rsp), %%rax\n"
"movq 8(%%rsp), %%rcx\n"
"movq 0(%%rsp), %%rdx\n"
"leaq (128+24)(%%rsp), %%rsp\n"
"\n"
"/* --- END --- */\n"
"\n";
static const u8 *main_payload_32 =
"\n"
"/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n"
"\n"
".text\n"
".att_syntax\n"
".code32\n"
".align 8\n"
"\n"
"__afl_maybe_log:\n"
"\n"
" lahf\n"
" seto %al\n"
"\n"
" /* Check if SHM region is already mapped. */\n"
"\n"
" movl __afl_area_ptr, %edx\n"
" testl %edx, %edx\n"
" je __afl_setup\n"
"\n"
"__afl_store:\n"
"\n"
" /* Calculate and store hit for the code location specified in ecx. There\n"
" is a double-XOR way of doing this without tainting another register,\n"
" and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n"
"\n"
#ifndef COVERAGE_ONLY
" movl __afl_prev_loc, %edi\n"
" xorl %ecx, %edi\n"
" shrl $1, %ecx\n"
" movl %ecx, __afl_prev_loc\n"
#else
" movl %ecx, %edi\n"
#endif /* ^!COVERAGE_ONLY */
"\n"
#ifdef SKIP_COUNTS
" orb $1, (%edx, %edi, 1)\n"
#else
" addb $1, (%edx, %edi, 1)\n"
" adcb $0, (%edx, %edi, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
#endif /* ^SKIP_COUNTS */
"\n"
"__afl_return:\n"
"\n"
" addb $127, %al\n"
" sahf\n"
" ret\n"
"\n"
".align 8\n"
"\n"
"__afl_setup:\n"
"\n"
" /* Do not retry setup if we had previous failures. */\n"
"\n"
" cmpb $0, __afl_setup_failure\n"
" jne __afl_return\n"
"\n"
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n"
" We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n"
" will notice this early in the game. */\n"
"\n"
" pushl %eax\n"
" pushl %ecx\n"
"\n"
" pushl $.AFL_SHM_ENV\n"
" call getenv\n"
" addl $4, %esp\n"
"\n"
" testl %eax, %eax\n"
" je __afl_setup_abort\n"
"\n"
#ifdef USEMMAP
" pushl $384 /* shm_open mode 0600 */\n"
" pushl $2 /* flags O_RDWR */\n"
" pushl %eax /* SHM file path */\n"
" call shm_open\n"
" addl $12, %esp\n"
"\n"
" cmpl $-1, %eax\n"
" je __afl_setup_abort\n"
"\n"
" pushl $0 /* mmap off */\n"
" pushl %eax /* shm fd */\n"
" pushl $1 /* mmap flags */\n"
" pushl $3 /* mmap prot */\n"
" pushl $"STRINGIFY(MAP_SIZE)" /* mmap len */\n"
" pushl $0 /* mmap addr */\n"
" call mmap\n"
" addl $12, %esp\n"
"\n"
" cmpl $-1, %eax\n"
" je __afl_setup_abort\n"
"\n"
#else
" pushl %eax\n"
" call atoi\n"
" addl $4, %esp\n"
"\n"
" pushl $0 /* shmat flags */\n"
" pushl $0 /* requested addr */\n"
" pushl %eax /* SHM ID */\n"
" call shmat\n"
" addl $12, %esp\n"
"\n"
" cmpl $-1, %eax\n"
" je __afl_setup_abort\n"
"\n"
#endif
" movb $1, (%eax)\n"
" /* Store the address of the SHM region. */\n"
"\n"
" movl %eax, __afl_area_ptr\n"
" movl %eax, %edx\n"
"\n"
" popl %ecx\n"
" popl %eax\n"
"\n"
"__afl_forkserver:\n"
"\n"
" /* Enter the fork server mode to avoid the overhead of execve() calls. */\n"
"\n"
" pushl %eax\n"
" pushl %ecx\n"
" pushl %edx\n"
"\n"
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
" closed because we were execve()d from an instrumented binary, or because\n"
" the parent doesn't want to use the fork server. */\n"
"\n"
" pushl $4 /* length */\n"
" pushl $__afl_temp /* data */\n"
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
" call write\n"
" addl $12, %esp\n"
"\n"
" cmpl $4, %eax\n"
" jne __afl_fork_resume\n"
"\n"
"__afl_fork_wait_loop:\n"
"\n"
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
"\n"
" pushl $4 /* length */\n"
" pushl $__afl_temp /* data */\n"
" pushl $" STRINGIFY(FORKSRV_FD) " /* file desc */\n"
" call read\n"
" addl $12, %esp\n"
"\n"
" cmpl $4, %eax\n"
" jne __afl_die\n"
"\n"
" /* Once woken up, create a clone of our process. This is an excellent use\n"
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
" caches getpid() results and offers no way to update the value, breaking\n"
" abort(), raise(), and a bunch of other things :-( */\n"
"\n"
" call fork\n"
"\n"
" cmpl $0, %eax\n"
" jl __afl_die\n"
" je __afl_fork_resume\n"
"\n"
" /* In parent process: write PID to pipe, then wait for child. */\n"
"\n"
" movl %eax, __afl_fork_pid\n"
"\n"
" pushl $4 /* length */\n"
" pushl $__afl_fork_pid /* data */\n"
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
" call write\n"
" addl $12, %esp\n"
"\n"
" pushl $0 /* no flags */\n"
" pushl $__afl_temp /* status */\n"
" pushl __afl_fork_pid /* PID */\n"
" call waitpid\n"
" addl $12, %esp\n"
"\n"
" cmpl $0, %eax\n"
" jle __afl_die\n"
"\n"
" /* Relay wait status to pipe, then loop back. */\n"
"\n"
" pushl $4 /* length */\n"
" pushl $__afl_temp /* data */\n"
" pushl $" STRINGIFY((FORKSRV_FD + 1)) " /* file desc */\n"
" call write\n"
" addl $12, %esp\n"
"\n"
" jmp __afl_fork_wait_loop\n"
"\n"
"__afl_fork_resume:\n"
"\n"
" /* In child process: close fds, resume execution. */\n"
"\n"
" pushl $" STRINGIFY(FORKSRV_FD) "\n"
" call close\n"
"\n"
" pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n"
" call close\n"
"\n"
" addl $8, %esp\n"
"\n"
" popl %edx\n"
" popl %ecx\n"
" popl %eax\n"
" jmp __afl_store\n"
"\n"
"__afl_die:\n"
"\n"
" xorl %eax, %eax\n"
" call _exit\n"
"\n"
"__afl_setup_abort:\n"
"\n"
" /* Record setup failure so that we don't keep calling\n"
" shmget() / shmat() over and over again. */\n"
"\n"
" incb __afl_setup_failure\n"
" popl %ecx\n"
" popl %eax\n"
" jmp __afl_return\n"
"\n"
".AFL_VARS:\n"
"\n"
" .comm __afl_area_ptr, 4, 32\n"
" .comm __afl_setup_failure, 1, 32\n"
#ifndef COVERAGE_ONLY
" .comm __afl_prev_loc, 4, 32\n"
#endif /* !COVERAGE_ONLY */
" .comm __afl_final_loc, 4, 32\n"
" .comm __afl_fork_pid, 4, 32\n"
" .comm __afl_temp, 4, 32\n"
"\n"
".AFL_SHM_ENV:\n"
" .asciz \"" SHM_ENV_VAR "\"\n"
"\n"
"/* --- END --- */\n"
"\n";
/* The OpenBSD hack is due to lahf and sahf not being recognized by some
versions of binutils: https://marc.info/?l=openbsd-cvs&m=141636589924400
The Apple code is a bit different when calling libc functions because
they are doing relocations differently from everybody else. We also need
to work around the crash issue with .lcomm and the fact that they don't
recognize .string. */
#ifdef __APPLE__
#define CALL_L64(str) "call _" str "\n"
#else
#define CALL_L64(str) "call " str "@PLT\n"
#endif /* ^__APPLE__ */
static const u8 *main_payload_64 =
"\n"
"/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n"
"\n"
".text\n"
".att_syntax\n"
".code64\n"
".align 8\n"
"\n"
"__afl_maybe_log:\n"
"\n"
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
" .byte 0x9f /* lahf */\n"
#else
" lahf\n"
#endif /* ^__OpenBSD__, etc */
" seto %al\n"
"\n"
" /* Check if SHM region is already mapped. */\n"
"\n"
" movq __afl_area_ptr(%rip), %rdx\n"
" testq %rdx, %rdx\n"
" je __afl_setup\n"
"\n"
"__afl_store:\n"
"\n"
" /* Calculate and store hit for the code location specified in rcx. */\n"
"\n"
#ifndef COVERAGE_ONLY
" xorq __afl_prev_loc(%rip), %rcx\n"
" xorq %rcx, __afl_prev_loc(%rip)\n"
" shrq $1, __afl_prev_loc(%rip)\n"
#endif /* ^!COVERAGE_ONLY */
"\n"
#ifdef SKIP_COUNTS
" orb $1, (%rdx, %rcx, 1)\n"
#else
" addb $1, (%rdx, %rcx, 1)\n"
" adcb $0, (%rdx, %rcx, 1)\n" // never zero counter implementation. slightly better path discovery and little performance impact
#endif /* ^SKIP_COUNTS */
"\n"
"__afl_return:\n"
"\n"
" addb $127, %al\n"
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && (__FreeBSD__ < 9))
" .byte 0x9e /* sahf */\n"
#else
" sahf\n"
#endif /* ^__OpenBSD__, etc */
" ret\n"
"\n"
".align 8\n"
"\n"
"__afl_setup:\n"
"\n"
" /* Do not retry setup if we had previous failures. */\n"
"\n"
" cmpb $0, __afl_setup_failure(%rip)\n"
" jne __afl_return\n"
"\n"
" /* Check out if we have a global pointer on file. */\n"
"\n"
#ifndef __APPLE__
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
" movq (%rdx), %rdx\n"
#else
" movq __afl_global_area_ptr(%rip), %rdx\n"
#endif /* !^__APPLE__ */
" testq %rdx, %rdx\n"
" je __afl_setup_first\n"
"\n"
" movq %rdx, __afl_area_ptr(%rip)\n"
" jmp __afl_store\n"
"\n"
"__afl_setup_first:\n"
"\n"
" /* Save everything that is not yet saved and that may be touched by\n"
" getenv() and several other libcalls we'll be relying on. */\n"
"\n"
" leaq -352(%rsp), %rsp\n"
"\n"
" movq %rax, 0(%rsp)\n"
" movq %rcx, 8(%rsp)\n"
" movq %rdi, 16(%rsp)\n"
" movq %rsi, 32(%rsp)\n"
" movq %r8, 40(%rsp)\n"
" movq %r9, 48(%rsp)\n"
" movq %r10, 56(%rsp)\n"
" movq %r11, 64(%rsp)\n"
"\n"
" movq %xmm0, 96(%rsp)\n"
" movq %xmm1, 112(%rsp)\n"
" movq %xmm2, 128(%rsp)\n"
" movq %xmm3, 144(%rsp)\n"
" movq %xmm4, 160(%rsp)\n"
" movq %xmm5, 176(%rsp)\n"
" movq %xmm6, 192(%rsp)\n"
" movq %xmm7, 208(%rsp)\n"
" movq %xmm8, 224(%rsp)\n"
" movq %xmm9, 240(%rsp)\n"
" movq %xmm10, 256(%rsp)\n"
" movq %xmm11, 272(%rsp)\n"
" movq %xmm12, 288(%rsp)\n"
" movq %xmm13, 304(%rsp)\n"
" movq %xmm14, 320(%rsp)\n"
" movq %xmm15, 336(%rsp)\n"
"\n"
" /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n"
"\n"
" /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n"
" original stack ptr in the callee-saved r12. */\n"
"\n"
" pushq %r12\n"
" movq %rsp, %r12\n"
" subq $16, %rsp\n"
" andq $0xfffffffffffffff0, %rsp\n"
"\n"
" leaq .AFL_SHM_ENV(%rip), %rdi\n"
CALL_L64("getenv")
"\n"
" testq %rax, %rax\n"
" je __afl_setup_abort\n"
"\n"
#ifdef USEMMAP
" movl $384, %edx /* shm_open mode 0600 */\n"
" movl $2, %esi /* flags O_RDWR */\n"
" movq %rax, %rdi /* SHM file path */\n"
CALL_L64("shm_open")
"\n"
" cmpq $-1, %rax\n"
" je __afl_setup_abort\n"
"\n"
" movl $0, %r9d\n"
" movl %eax, %r8d\n"
" movl $1, %ecx\n"
" movl $3, %edx\n"
" movl $"STRINGIFY(MAP_SIZE)", %esi\n"
" movl $0, %edi\n"
CALL_L64("mmap")
"\n"
" cmpq $-1, %rax\n"
" je __afl_setup_abort\n"
"\n"
#else
" movq %rax, %rdi\n"
CALL_L64("atoi")
"\n"
" xorq %rdx, %rdx /* shmat flags */\n"
" xorq %rsi, %rsi /* requested addr */\n"
" movq %rax, %rdi /* SHM ID */\n"
CALL_L64("shmat")
"\n"
" cmpq $-1, %rax\n"
" je __afl_setup_abort\n"
"\n"
#endif
" movb $1, (%rax)\n"
" /* Store the address of the SHM region. */\n"
"\n"
" movq %rax, %rdx\n"
" movq %rax, __afl_area_ptr(%rip)\n"
"\n"
#ifdef __APPLE__
" movq %rax, __afl_global_area_ptr(%rip)\n"
#else
" movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n"
" movq %rax, (%rdx)\n"
#endif /* ^__APPLE__ */
" movq %rax, %rdx\n"
"\n"
"__afl_forkserver:\n"
"\n"
" /* Enter the fork server mode to avoid the overhead of execve() calls. We\n"
" push rdx (area ptr) twice to keep stack alignment neat. */\n"
"\n"
" pushq %rdx\n"
" pushq %rdx\n"
"\n"
" /* Phone home and tell the parent that we're OK. (Note that signals with\n"
" no SA_RESTART will mess it up). If this fails, assume that the fd is\n"
" closed because we were execve()d from an instrumented binary, or because\n"
" the parent doesn't want to use the fork server. */\n"
"\n"
" movq $4, %rdx /* length */\n"
" leaq __afl_temp(%rip), %rsi /* data */\n"
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
CALL_L64("write")
"\n"
" cmpq $4, %rax\n"
" jne __afl_fork_resume\n"
"\n"
"__afl_fork_wait_loop:\n"
"\n"
" /* Wait for parent by reading from the pipe. Abort if read fails. */\n"
"\n"
" movq $4, %rdx /* length */\n"
" leaq __afl_temp(%rip), %rsi /* data */\n"
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi /* file desc */\n"
CALL_L64("read")
" cmpq $4, %rax\n"
" jne __afl_die\n"
"\n"
" /* Once woken up, create a clone of our process. This is an excellent use\n"
" case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n"
" caches getpid() results and offers no way to update the value, breaking\n"
" abort(), raise(), and a bunch of other things :-( */\n"
"\n"
CALL_L64("fork")
" cmpq $0, %rax\n"
" jl __afl_die\n"
" je __afl_fork_resume\n"
"\n"
" /* In parent process: write PID to pipe, then wait for child. */\n"
"\n"
" movl %eax, __afl_fork_pid(%rip)\n"
"\n"
" movq $4, %rdx /* length */\n"
" leaq __afl_fork_pid(%rip), %rsi /* data */\n"
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
CALL_L64("write")
"\n"
" movq $0, %rdx /* no flags */\n"
" leaq __afl_temp(%rip), %rsi /* status */\n"
" movq __afl_fork_pid(%rip), %rdi /* PID */\n"
CALL_L64("waitpid")
" cmpq $0, %rax\n"
" jle __afl_die\n"
"\n"
" /* Relay wait status to pipe, then loop back. */\n"
"\n"
" movq $4, %rdx /* length */\n"
" leaq __afl_temp(%rip), %rsi /* data */\n"
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi /* file desc */\n"
CALL_L64("write")
"\n"
" jmp __afl_fork_wait_loop\n"
"\n"
"__afl_fork_resume:\n"
"\n"
" /* In child process: close fds, resume execution. */\n"
"\n"
" movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n"
CALL_L64("close")
"\n"
" movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n"
CALL_L64("close")
"\n"
" popq %rdx\n"
" popq %rdx\n"
"\n"
" movq %r12, %rsp\n"
" popq %r12\n"
"\n"
" movq 0(%rsp), %rax\n"
" movq 8(%rsp), %rcx\n"
" movq 16(%rsp), %rdi\n"
" movq 32(%rsp), %rsi\n"
" movq 40(%rsp), %r8\n"
" movq 48(%rsp), %r9\n"
" movq 56(%rsp), %r10\n"
" movq 64(%rsp), %r11\n"
"\n"
" movq 96(%rsp), %xmm0\n"
" movq 112(%rsp), %xmm1\n"
" movq 128(%rsp), %xmm2\n"
" movq 144(%rsp), %xmm3\n"
" movq 160(%rsp), %xmm4\n"
" movq 176(%rsp), %xmm5\n"
" movq 192(%rsp), %xmm6\n"
" movq 208(%rsp), %xmm7\n"
" movq 224(%rsp), %xmm8\n"
" movq 240(%rsp), %xmm9\n"
" movq 256(%rsp), %xmm10\n"
" movq 272(%rsp), %xmm11\n"
" movq 288(%rsp), %xmm12\n"
" movq 304(%rsp), %xmm13\n"
" movq 320(%rsp), %xmm14\n"
" movq 336(%rsp), %xmm15\n"
"\n"
" leaq 352(%rsp), %rsp\n"
"\n"
" jmp __afl_store\n"
"\n"
"__afl_die:\n"
"\n"
" xorq %rax, %rax\n"
CALL_L64("_exit")
"\n"
"__afl_setup_abort:\n"
"\n"
" /* Record setup failure so that we don't keep calling\n"
" shmget() / shmat() over and over again. */\n"
"\n"
" incb __afl_setup_failure(%rip)\n"
"\n"
" movq %r12, %rsp\n"
" popq %r12\n"
"\n"
" movq 0(%rsp), %rax\n"
" movq 8(%rsp), %rcx\n"
" movq 16(%rsp), %rdi\n"
" movq 32(%rsp), %rsi\n"
" movq 40(%rsp), %r8\n"
" movq 48(%rsp), %r9\n"
" movq 56(%rsp), %r10\n"
" movq 64(%rsp), %r11\n"
"\n"
" movq 96(%rsp), %xmm0\n"
" movq 112(%rsp), %xmm1\n"
" movq 128(%rsp), %xmm2\n"
" movq 144(%rsp), %xmm3\n"
" movq 160(%rsp), %xmm4\n"
" movq 176(%rsp), %xmm5\n"
" movq 192(%rsp), %xmm6\n"
" movq 208(%rsp), %xmm7\n"
" movq 224(%rsp), %xmm8\n"
" movq 240(%rsp), %xmm9\n"
" movq 256(%rsp), %xmm10\n"
" movq 272(%rsp), %xmm11\n"
" movq 288(%rsp), %xmm12\n"
" movq 304(%rsp), %xmm13\n"
" movq 320(%rsp), %xmm14\n"
" movq 336(%rsp), %xmm15\n"
"\n"
" leaq 352(%rsp), %rsp\n"
"\n"
" jmp __afl_return\n"
"\n"
".AFL_VARS:\n"
"\n"
#ifdef __APPLE__
" .comm __afl_area_ptr, 8\n"
#ifndef COVERAGE_ONLY
" .comm __afl_prev_loc, 8\n"
#endif /* !COVERAGE_ONLY */
" .comm __afl_fork_pid, 4\n"
" .comm __afl_temp, 4\n"
" .comm __afl_setup_failure, 1\n"
#else
" .lcomm __afl_area_ptr, 8\n"
#ifndef COVERAGE_ONLY
" .lcomm __afl_prev_loc, 8\n"
#endif /* !COVERAGE_ONLY */
" .lcomm __afl_fork_pid, 4\n"
" .lcomm __afl_temp, 4\n"
" .lcomm __afl_setup_failure, 1\n"
#endif /* ^__APPLE__ */
" .comm __afl_global_area_ptr, 8, 8\n"
"\n"
".AFL_SHM_ENV:\n"
" .asciz \"" SHM_ENV_VAR "\"\n"
"\n"
"/* --- END --- */\n"
"\n";
#endif /* !_HAVE_AFL_AS_H */

View File

@ -116,6 +116,10 @@
#include <TargetConditionals.h>
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#undef LIST_FOREACH /* clashes with FreeBSD */
#include "list.h"
#ifndef SIMPLE_FILES
@ -236,7 +240,6 @@ struct queue_entry {
custom, /* Marker for custom mutators */
stats_mutated; /* stats: # of mutations performed */
u8 *trace_mini; /* Trace bytes, if kept */
u32 tc_ref; /* Trace bytes ref count */
#ifdef INTROSPECTION
@ -246,13 +249,11 @@ struct queue_entry {
double perf_score, /* performance score */
weight;
u8 *testcase_buf; /* The testcase buffer, if loaded. */
u8 *cmplog_colorinput; /* the result buf of colorization */
struct tainted *taint; /* Taint information from CmpLog */
struct queue_entry *mother; /* queue entry this based on */
struct queue_entry *mother; /* queue entry this based on */
u8 *trace_mini; /* Trace bytes, if kept */
u8 *testcase_buf; /* The testcase buffer, if loaded. */
u8 *cmplog_colorinput; /* the result buf of colorization */
struct tainted *taint; /* Taint information from CmpLog */
struct skipdet_entry *skipdet_e;
};
@ -448,8 +449,9 @@ extern char *power_names[POWER_SCHEDULES_NUM];
typedef struct afl_env_vars {
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only,
afl_custom_mutator_late_send, afl_no_ui, afl_force_ui,
afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
@ -457,7 +459,7 @@ typedef struct afl_env_vars {
afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames, afl_no_sync;
afl_sha1_filenames, afl_no_sync, afl_no_fastresume;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,

View File

@ -53,21 +53,24 @@ struct cmp_header { // 16 bit = 2 bytes
struct cmp_operands {
u64 v0;
u64 v1;
u64 v0_128;
u64 v0_256_0; // u256 is unsupported by any compiler for now, so future use
u64 v0_256_1;
u64 v1;
u64 v1_128;
u64 unused;
u8 unused1;
u8 unused2;
u64 v1_256_0;
u64 v1_256_1;
u8 unused[8]; // 2 bits could be used for "is constant operand"
} __attribute__((packed));
struct cmpfn_operands {
u8 v0[32];
u8 v0_len;
u8 v1[32];
u8 v0_len;
u8 v1_len;
u8 unused[6]; // 2 bits could be used for "is constant operand"
} __attribute__((packed));

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.21c"
#define VERSION "++4.30c"
/******************************************************
* *

View File

@ -314,8 +314,8 @@ static inline const char *colorfilter(const char *x) {
#define FATAL(x...) \
do { \
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, (u32)__LINE__); \
exit(1); \
@ -327,8 +327,8 @@ static inline const char *colorfilter(const char *x) {
#define ABORT(x...) \
do { \
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, (u32)__LINE__); \
abort(); \
@ -341,8 +341,8 @@ static inline const char *colorfilter(const char *x) {
do { \
\
fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
__FILE__, (u32)__LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \

View File

@ -20,10 +20,12 @@ static char *afl_environment_variables[] = {
"AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CMPLOG_DEBUG", "AFL_CTX_K", "AFL_LLVM_DONTWRITEID", "AFL_PC_FILTER",
"AFL_PC_FILTER_FILE", "AFL_CODE_END", "AFL_CODE_START",
"AFL_COMPCOV_BINNAME", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_MUTATOR_LATE_SEND",
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
@ -39,8 +41,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE",
"AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
"AFL_FRIDA_INST_NO_SUPPRESS"
"AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE",
"AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE",
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR",
@ -49,12 +50,12 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE",
"AFL_FRIDA_VERBOSE",
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER", "AFL_OPT_LEVEL",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
"AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO", "AFL_GCJ",
"AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_DISABLE_VERSION_CHECK",
"AFL_GCC_INSTRUMENT_FILE", "AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO",
"AFL_GCJ", "AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS",
"AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS",
"AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST",
@ -113,9 +114,10 @@ static char *afl_environment_variables[] = {
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
"AFL_USE_UBSAN", "AFL_UBSAN_VERBOSE", "AFL_USE_TSAN", "AFL_USE_CFISAN",
"AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL
};

View File

@ -89,11 +89,14 @@ typedef struct {
bool (*nyx_config_set_aux_buffer_size)(void *config,
uint32_t aux_buffer_size);
uint64_t (*nyx_get_target_hash64)(void *config);
void (*nyx_config_free)(void *config);
} nyx_plugin_handler_t;
/* Imports helper functions to enable Nyx mode (Linux only )*/
nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
#endif
typedef struct afl_forkserver {
@ -204,8 +207,18 @@ typedef struct afl_forkserver {
bool nyx_use_tmp_workdir;
char *nyx_tmp_workdir_path;
s32 nyx_log_fd;
u64 nyx_target_hash64;
#endif
#ifdef __AFL_CODE_COVERAGE
u8 *persistent_trace_bits; /* Persistent copy of bitmap */
#endif
void *custom_data_ptr;
u8 *custom_input;
u32 custom_input_len;
void (*late_send)(void *, const u8 *, size_t);
} afl_forkserver_t;
typedef enum fsrv_run_result {
@ -232,6 +245,10 @@ void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
void afl_fsrv_kill(afl_forkserver_t *fsrv);
#ifdef __linux__
void nyx_load_target_hash(afl_forkserver_t *fsrv);
#endif
#ifdef __APPLE__
#define MSG_FORK_ON_APPLE \
" - On MacOS X, the semantics of fork() syscalls are non-standard and " \

View File

@ -455,9 +455,10 @@ typedef struct {
} __attribute__((__packed__)) t1ha_unaligned_proxy;
#define read_unaligned(ptr, bits) \
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
t1ha_unaligned_proxy, unaligned_##bits))) \
#define read_unaligned(ptr, bits) \
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \
offsetof(t1ha_unaligned_proxy, \
unaligned_##bits))) \
->unaligned_##bits)
#elif defined(_MSC_VER)
#pragma warning( \
@ -477,9 +478,10 @@ typedef struct {
} t1ha_unaligned_proxy;
#pragma pack(pop)
#define read_unaligned(ptr, bits) \
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
t1ha_unaligned_proxy, unaligned_##bits))) \
#define read_unaligned(ptr, bits) \
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \
offsetof(t1ha_unaligned_proxy, \
unaligned_##bits))) \
->unaligned_##bits)
#endif
#endif /* read_unaligned */
@ -496,21 +498,24 @@ typedef struct {
#elif __has_attribute(__assume_aligned__)
static __always_inline const uint16_t *__attribute__((
__assume_aligned__(ALIGNMENT_16))) cast_aligned_16(const void *ptr) {
__assume_aligned__(ALIGNMENT_16)))
cast_aligned_16(const void *ptr) {
return (const uint16_t *)ptr;
}
static __always_inline const uint32_t *__attribute__((
__assume_aligned__(ALIGNMENT_32))) cast_aligned_32(const void *ptr) {
__assume_aligned__(ALIGNMENT_32)))
cast_aligned_32(const void *ptr) {
return (const uint32_t *)ptr;
}
static __always_inline const uint64_t *__attribute__((
__assume_aligned__(ALIGNMENT_64))) cast_aligned_64(const void *ptr) {
__assume_aligned__(ALIGNMENT_64)))
cast_aligned_64(const void *ptr) {
return (const uint64_t *)ptr;

View File

@ -155,7 +155,7 @@ typedef int128_t s128;
({ \
\
char *d = (char *)(_x), *s = (char *)(_y); \
u32 i, l = (_l)-1; \
u32 i, l = (_l) - 1; \
for (i = 0; i <= l; i++) \
d[l - i] = s[i]; \
\

View File

@ -6616,12 +6616,14 @@ static XXH64_hash_t XXH3_mergeAccs(const xxh_u64 *XXH_RESTRICT acc,
}
#define XXH3_INIT_ACC \
{ \
\
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 \
\
#define XXH3_INIT_ACC \
{ \
\
\
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, \
XXH_PRIME64_3, XXH_PRIME64_4, XXH_PRIME32_2, \
XXH_PRIME64_5, XXH_PRIME32_1 \
\
}
XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal(

View File

@ -21,7 +21,7 @@ TL;DR:
The code in this directory allows to instrument programs for AFL++ using true
compiler-level instrumentation, instead of the more crude assembly-level
rewriting approach taken by afl-gcc and afl-clang. This has several interesting
rewriting approach taken by obsolete afl-gcc and afl-clang. This has several interesting
properties:
- The compiler can make many optimizations that are hard to pull off when
@ -40,10 +40,6 @@ properties:
will *not* work with LLVM (see [README.llvm.md](README.llvm.md) for an
alternative).
Once this implementation is shown to be sufficiently robust and portable, it
will probably replace afl-gcc. For now, it can be built separately and co-exists
with the original code.
The idea and much of the implementation comes from Laszlo Szekeres.
## 2) How to use
@ -51,7 +47,10 @@ The idea and much of the implementation comes from Laszlo Szekeres.
In order to leverage this mechanism, you need to have modern enough GCC (>=
version 4.5.0) and the plugin development headers installed on your system. That
should be all you need. On Debian machines, these headers can be acquired by
installing the `gcc-VERSION-plugin-dev` packages.
installing the `gcc-VERSION-plugin-dev` packages. If you're compiling a GCC
plugin that differs from the system-installed version and encounter issues
with version checks, you can use the `AFL_GCC_DISABLE_VERSION_CHECK` environment
variable.
To build the instrumentation itself, type `make`. This will generate binaries
called `afl-gcc-fast` and `afl-g++-fast` in the parent directory.
@ -74,7 +73,7 @@ standard operating mode of AFL++, e.g.:
Note: We also used `CXX` to set the C++ compiler to `afl-g++-fast` for C++ code.
The tool honors roughly the same environmental variables as `afl-gcc` (see
The tool honors some environmental variables of `afl-clang-fast` (see
[docs/env_variables.md](../docs/env_variables.md). This includes
`AFL_INST_RATIO`, `AFL_USE_ASAN`, `AFL_HARDEN`, and `AFL_DONT_OPTIMIZE`.

View File

@ -3,7 +3,7 @@
This file describes two different mechanisms to selectively instrument only
specific parts in the target.
Both mechanisms work for LLVM and GCC_PLUGIN, but not for afl-clang/afl-gcc.
Both mechanisms work for LLVM and GCC_PLUGIN.
## 1) Description and purpose

View File

@ -11,7 +11,7 @@ For the GCC-based instrumentation, see
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
rewriting approach taken by obsolete afl-gcc and afl-clang. This has several interesting
properties:
- The compiler can make many optimizations that are hard to pull off when
@ -32,10 +32,6 @@ properties:
will *not* work with GCC (see ../gcc_plugin/ for an alternative once it is
available).
Once this implementation is shown to be sufficiently robust and portable, it
will probably replace afl-clang. For now, it can be built separately and
co-exists with the original code.
The idea and much of the initial implementation came from Laszlo Szekeres.
## 2a) How to use this - short
@ -105,7 +101,7 @@ also use afl-cc/afl-c++ and instead direct it to use LLVM instrumentation by
either setting `AFL_CC_COMPILER=LLVM` or pass the parameter `--afl-llvm` via
CFLAGS/CXXFLAGS/CPPFLAGS.
The tool honors roughly the same environmental variables as afl-gcc (see
The tool supports a lot of environmental variables(see
[docs/env_variables.md](../docs/env_variables.md)). This includes
`AFL_USE_ASAN`, `AFL_HARDEN`, and `AFL_DONT_OPTIMIZE`. However, `AFL_INST_RATIO`
is not honored as it does not serve a good purpose with the more effective
@ -255,10 +251,6 @@ low cost (one instruction per edge).
(The alternative of saturated counters has been tested also and proved to be
inferior in terms of path discovery.)
This is implemented in afl-gcc and afl-gcc-fast, however, for llvm_mode this is
optional if multithread safe counters are selected or the llvm version is below
9 - as there are severe performance costs in these cases.
If you want to enable this for llvm versions below 9 or thread safe counters,
then set

View File

@ -57,23 +57,23 @@ libtool: link: afl-clang-lto -g -O2 -Wall -W -o thumbnail thumbnail.o ../libtif
afl-clang-lto++2.63d by Marc "vanHauser" Heuse <mh@mh-sec.de> in mode LTO
afl-llvm-lto++2.63d by Marc "vanHauser" Heuse <mh@mh-sec.de>
AUTODICTIONARY: 11 strings found
[+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode).
[+] Instrumented 12071 locations with no collisions (on average 1046 collisions would be in afl-clang-fast CLASSIC) (non-hardened mode).
```
## Getting LLVM 12+
## Getting LLVM 13+
### Installing llvm
The best way to install LLVM is to follow [https://apt.llvm.org/](https://apt.llvm.org/)
e.g. for LLVM 15:
e.g. for LLVM 19:
```
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 15 all
sudo ./llvm.sh 19 all
```
LLVM 12 to 18 should be available in all current Linux repositories.
LLVM 13 to 19 should be available in all current Linux repositories.
## How to build afl-clang-lto
@ -90,7 +90,7 @@ sudo make install
## How to use afl-clang-lto
Just use afl-clang-lto like you did with afl-clang-fast or afl-gcc.
Just use afl-clang-lto like you did with afl-clang-fast.
Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST ->
[README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov

View File

@ -124,7 +124,6 @@ will keep working normally when compiled with a tool other than afl-clang-fast/
afl-clang-lto/afl-gcc-fast.
Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
(afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
and you should be all set!
## 4) Persistent mode

View File

@ -50,7 +50,11 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#if LLVM_VERSION_MAJOR < 20
#include "llvm/Transforms/Instrumentation.h"
#else
#include "llvm/Transforms/Utils/Instrumentation.h"
#endif
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
@ -214,8 +218,12 @@ class ModuleSanitizerCoverageLTO
void SetNoSanitizeMetadata(Instruction *I) {
#if LLVM_VERSION_MAJOR >= 19
I->setNoSanitizeMetadata();
#else
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
MDNode::get(*C, None));
#endif
}
@ -225,7 +233,7 @@ class ModuleSanitizerCoverageLTO
FunctionCallee SanCovTracePCIndir;
FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
Module *CurModule;
std::string CurModuleUniqueId;
Triple TargetTriple;
@ -416,6 +424,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
PtrTy = PointerType::getUnqual(*C);
/* AFL++ START */
char *ptr;
@ -1350,7 +1359,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
if (F.empty()) return;
if (F.getName().find(".module_ctor") != std::string::npos)
if (F.getName().contains(".module_ctor"))
return; // Should not instrument sanitizer init functions.
#if LLVM_VERSION_MAJOR >= 18
if (F.getName().starts_with("__sanitizer_"))
@ -1372,6 +1381,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return;
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
#if LLVM_VERSION_MAJOR >= 19
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
#endif
// if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))
// return;
// if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
@ -2023,16 +2036,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
if (&F.getEntryBlock() == AllBlocks[i]) {
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
} else {
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
BlockAddress::get(AllBlocks[i]), PtrTy));
#if LLVM_VERSION_MAJOR >= 16
PCs.push_back(Constant::getNullValue(PtrTy));
#else
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy));
#endif
}

View File

@ -23,6 +23,10 @@
#include "llvm/IR/CFG.h"
#endif
#include "llvm/IR/Constant.h"
#if LLVM_VERSION_MAJOR >= 20
#include "llvm/IR/Constants.h"
#include "llvm/IR/ValueSymbolTable.h"
#endif
#include "llvm/IR/DataLayout.h"
#if LLVM_VERSION_MAJOR < 15
#include "llvm/IR/DebugInfo.h"
@ -63,11 +67,16 @@
#if LLVM_VERSION_MAJOR < 15
#include "llvm/Support/raw_ostream.h"
#endif
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/Instrumentation.h"
#if LLVM_VERSION_MAJOR < 20
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/Instrumentation.h"
#else
#include "llvm/TargetParser/Triple.h"
#endif
#else
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@ -161,7 +170,9 @@ class ModuleSanitizerCoverageAFL
void SetNoSanitizeMetadata(Instruction *I) {
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 19
I->setNoSanitizeMetadata();
#elif LLVM_VERSION_MAJOR >= 16
I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
#else
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@ -179,7 +190,7 @@ class ModuleSanitizerCoverageAFL
FunctionCallee SanCovTraceSwitchFunction;
GlobalVariable *SanCovLowestStack;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
Module *CurModule;
std::string CurModuleUniqueId;
Triple TargetTriple;
@ -272,13 +283,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
if (!TargetTriple.isOSBinFormatCOFF())
return std::make_pair(SecStart, SecEnd);
// Account for the fact that on windows-msvc __start_* symbols actually
// point to a uint64_t before the start of the array.
// Account for the fact that on windows-msvc __start_* symbols actually
// point to a uint64_t before the start of the array.
#if LLVM_VERSION_MAJOR >= 19
auto GEP =
IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
return std::make_pair(GEP, SecEnd);
#else
auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
ConstantInt::get(IntptrTy, sizeof(uint64_t)));
return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)),
SecEnd);
#endif
}
@ -293,7 +310,7 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
Type *PtrTy = PointerType::getUnqual(Ty);
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd});
assert(CtorFunc->getName() == CtorName);
// assert(CtorFunc->getName() == CtorName);
if (TargetTriple.supportsCOMDAT()) {
@ -370,6 +387,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
PtrTy = PointerType::getUnqual(*C);
LLVMContext &Ctx = M.getContext();
AFLMapPtr =
@ -572,7 +590,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
if (F.empty()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
if (F.getName().find(".module_ctor") != std::string::npos)
// if (F.getName().find(".module_ctor") != std::string::npos)
if (F.getName().contains(".module_ctor"))
return; // Should not instrument sanitizer init functions.
#if LLVM_VERSION_MAJOR >= 18
if (F.getName().starts_with("__sanitizer_"))
@ -595,6 +614,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return;
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
#if LLVM_VERSION_MAJOR >= 19
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
#endif
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@ -692,16 +714,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
if (&F.getEntryBlock() == AllBlocks[i]) {
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
PCs.push_back(
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
} else {
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
BlockAddress::get(AllBlocks[i]), PtrTy));
#if LLVM_VERSION_MAJOR >= 16
PCs.push_back(Constant::getNullValue(IntptrPtrTy));
PCs.push_back(Constant::getNullValue(PtrTy));
#else
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
@ -711,10 +733,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
}
auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy,
SanCovPCsSectionName);
auto *PCArray =
CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
PCArray->setInitializer(
ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs));
ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
PCArray->setConstant(true);
return PCArray;
@ -822,7 +844,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
StringRef FuncName = Callee->getName();
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
#if LLVM_VERSION_MAJOR >= 20
// test canary
InstrumentationIRBuilder IRB(callInst);
#else
IRBuilder<> IRB(callInst);
#endif
if (!FunctionGuardArray) {

View File

@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE;
u32 __afl_dictionary_len;
u64 __afl_map_addr;
u32 __afl_first_final_loc;
u32 __afl_old_forkserver;
#ifdef __AFL_CODE_COVERAGE
typedef struct afl_module_info_t afl_module_info_t;
@ -366,6 +367,12 @@ static void __afl_map_shm(void) {
}
if (__afl_debug) {
fprintf(stderr, "DEBUG: AFL_MAP_SIZE=%u\n", __afl_map_size);
}
if (__afl_final_loc > MAP_SIZE) {
char *ptr;
@ -412,7 +419,7 @@ static void __afl_map_shm(void) {
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
if (val > MAP_INITIAL_SIZE) {
if (val > MAP_INITIAL_SIZE && val > __afl_final_loc) {
__afl_map_size = val;
@ -616,7 +623,7 @@ static void __afl_map_shm(void) {
fprintf(stderr,
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
"%u, __afl_final_loc %u, __afl_map_size %u",
"%u, __afl_final_loc %u, __afl_map_size %u\n",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
__afl_final_loc, __afl_map_size);
@ -629,22 +636,22 @@ static void __afl_map_shm(void) {
__afl_area_ptr_dummy = (u8 *)malloc(__afl_map_size);
if (__afl_area_ptr_dummy) {
}
if (__afl_selective_coverage_start_off) {
if (__afl_area_ptr_dummy) {
__afl_area_ptr = __afl_area_ptr_dummy;
if (__afl_selective_coverage_start_off) {
}
} else {
fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
__afl_selective_coverage = 0;
// continue;
__afl_area_ptr = __afl_area_ptr_dummy;
}
} else {
fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
__afl_selective_coverage = 0;
// continue;
}
}
@ -856,7 +863,7 @@ static void __afl_start_forkserver(void) {
signal(SIGTERM, at_exit);
u32 already_read_first = 0;
u32 was_killed;
u32 was_killed = 0;
u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
u32 tmp = version ^ 0xffffffff, status2, status = version;
u8 *msg = (u8 *)&status;
@ -866,75 +873,95 @@ static void __afl_start_forkserver(void) {
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
if (getenv("AFL_OLD_FORKSERVER")) {
__afl_old_forkserver = 1;
status = 0;
if (__afl_final_loc > MAP_SIZE) {
fprintf(stderr,
"Warning: AFL_OLD_FORKSERVER is used with a target compiled with "
"non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - "
"this target may crash!\n");
}
}
/* 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. */
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (!__afl_old_forkserver) {
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
write_error("wrong forkserver message from AFL++ tool");
_exit(1);
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
}
// send the set/requested options to forkserver
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
if (__afl_dictionary_len && __afl_dictionary) {
status |= FS_NEW_OPT_AUTODICT;
}
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// Now send the parameters for the set options, increasing by option number
// FS_NEW_OPT_MAPSIZE - we always send the map size
status = __afl_map_size;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// FS_NEW_OPT_SHDMEM_FUZZ - no data
// FS_NEW_OPT_AUTODICT - send autodictionary
if (__afl_dictionary_len && __afl_dictionary) {
// pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
write(2, "Error: could not send dictionary len\n",
strlen("Error: could not send dictionary len\n"));
write_error("wrong forkserver message from AFL++ tool");
_exit(1);
}
while (len != 0) {
// send the set/requested options to forkserver
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
if (__afl_dictionary_len && __afl_dictionary) {
s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
status |= FS_NEW_OPT_AUTODICT;
if (ret < 1) {
}
write_error("could not send dictionary");
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// Now send the parameters for the set options, increasing by option number
// FS_NEW_OPT_MAPSIZE - we always send the map size
status = __afl_map_size;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// FS_NEW_OPT_SHDMEM_FUZZ - no data
// FS_NEW_OPT_AUTODICT - send autodictionary
if (__afl_dictionary_len && __afl_dictionary) {
// pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
write(2, "Error: could not send dictionary len\n",
strlen("Error: could not send dictionary len\n"));
_exit(1);
}
len -= ret;
offset += ret;
while (len != 0) {
s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
if (ret < 1) {
write_error("could not send dictionary");
_exit(1);
}
len -= ret;
offset += ret;
}
}
}
// send welcome message as final message
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// send welcome message as final message
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
}
// END forkserver handshake
@ -948,13 +975,13 @@ static void __afl_start_forkserver(void) {
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (already_read_first) {
if (unlikely(already_read_first)) {
already_read_first = 0;
} else {
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
if (unlikely(read(FORKSRV_FD, &was_killed, 4) != 4)) {
write_error("read from AFL++ tool");
_exit(1);
@ -993,10 +1020,10 @@ static void __afl_start_forkserver(void) {
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
if (unlikely(child_stopped && was_killed)) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) {
if (unlikely(waitpid(child_pid, &status, 0) < 0)) {
write_error("child_stopped && was_killed");
_exit(1);
@ -1005,12 +1032,12 @@ static void __afl_start_forkserver(void) {
}
if (!child_stopped) {
if (unlikely(!child_stopped)) {
/* Once woken up, create a clone of our process. */
child_pid = fork();
if (child_pid < 0) {
if (unlikely(child_pid < 0)) {
write_error("fork");
_exit(1);
@ -1019,7 +1046,7 @@ static void __afl_start_forkserver(void) {
/* In child process: close fds, resume execution. */
if (!child_pid) {
if (unlikely(!child_pid)) { // just to signal afl-fuzz faster
//(void)nice(-20);
@ -1044,14 +1071,15 @@ static void __afl_start_forkserver(void) {
/* In parent process: write PID to pipe, then wait for child. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
if (unlikely(write(FORKSRV_FD + 1, &child_pid, 4) != 4)) {
write_error("write to afl-fuzz");
_exit(1);
}
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) {
if (unlikely(waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) <
0)) {
write_error("waitpid");
_exit(1);
@ -1062,11 +1090,11 @@ static void __afl_start_forkserver(void) {
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status)) child_stopped = 1;
if (likely(WIFSTOPPED(status))) { child_stopped = 1; }
/* Relay wait status to pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) {
if (unlikely(write(FORKSRV_FD + 1, &status, 4) != 4)) {
write_error("writing to afl-fuzz");
_exit(1);
@ -2704,7 +2732,7 @@ void __afl_coverage_skip() {
// mark this area as especially interesting
void __afl_coverage_interesting(u8 val, u32 id) {
__afl_area_ptr[id] = val;
__afl_area_ptr[id % __afl_map_size] = val;
}

View File

@ -370,7 +370,8 @@ Set AFL_QUIET in the environment to silence it.\n\
int plugin_init(struct plugin_name_args *info,
struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version))
if (!plugin_default_version_check(version, &gcc_version) &&
!getenv("AFL_GCC_DISABLE_VERSION_CHECK"))
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
"is %s"),
gcc_version.basever, version->basever);

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