Compare commits

...

361 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
9f6b012fbf Merge pull request #2117 from AFLplusplus/dev
push to stable
2024-06-09 19:09:17 +02:00
ec0b83f127 4.21c 2024-06-09 18:39:56 +02:00
0c81982e67 nit 2024-06-09 18:32:36 +02:00
5014b86c3c fix AFL_FRIDA_DEBUG_MAPS 2024-06-09 15:44:10 +02:00
44b5e1f488 fix no_forkserver mode 2024-06-09 12:26:48 +02:00
31652eeb2a nit 2024-06-09 12:19:58 +02:00
4bb4d4ad00 fix -n 2024-06-09 12:16:32 +02:00
5331eca5d9 allow multiple -m 2024-06-09 12:02:59 +02:00
74e264a20a move function 2024-06-07 13:46:15 +02:00
f0937f96d4 target hash 2024-06-07 11:48:58 +02:00
92cbdb9f45 update unicorn 2024-06-07 11:41:35 +02:00
fe36ceaa55 minor testcache optimizations 2024-06-07 11:16:42 +02:00
0618bfd4ae fix 2024-06-07 09:58:27 +02:00
bdfd38771a add cmplog_time measurement 2024-06-07 09:47:29 +02:00
477063e9ee memory adjustments 2024-06-06 17:52:21 +02:00
e46c106b89 new seed selection algorithm 2024-06-06 10:25:23 +02:00
69630338ff Merge pull request #2114 from WorksButNotTested/frida-rlimit
Fix issue for setrlimit
2024-06-05 20:21:51 +02:00
112759cd39 Merge pull request #2113 from AFLplusplus/fix_mmap_cmplog
Fix cmplog shared memory size when USEMMAP=1
2024-06-05 20:19:38 +02:00
f8767c397b Fix issue for setrlimit 2024-06-05 18:43:20 +01:00
e8d098335b Fix cmplog shared memory size when USEMMAP=1 2024-06-05 19:33:02 +02:00
12a87cfacb nits 2024-06-05 10:40:12 +02:00
2806d6be2f optimize syncing 2024-06-05 09:20:30 +02:00
2d9b793dbb AFL_NO_SYNC 2024-06-04 14:48:02 +02:00
7f02f0da61 Merge pull request #2106 from a-shvedov/stable
feature: Added (generate_libtoken_dict.sh) script for simplified work with `libtokencap`
2024-06-04 11:29:27 +02:00
bc2ccf464f Update README.md 2024-06-03 19:14:04 +03:00
b8536ced09 Update generate_libtoken_dict.sh 2024-06-03 19:01:50 +03:00
1db82f3303 update grammar mutator 2024-06-03 09:23:43 +02:00
fd713413e8 Merge pull request #2109 from AFLplusplus/dev
fix afl-showmap
2024-06-01 16:56:35 +02:00
2d4a4ba73f fix afl-showmap 2024-06-01 16:55:56 +02:00
348f980f21 Merge pull request #2108 from AFLplusplus/dev
push to stable
2024-06-01 16:37:28 +02:00
ca55858aa7 Merge pull request #2107 from AFLplusplus/reg
fix regression
2024-06-01 16:34:50 +02:00
e639521b01 changelog 2024-06-01 16:34:23 +02:00
894339c5d7 try regression fix 2024-06-01 12:26:26 +02:00
e13dc9b7e6 todo 2024-06-01 12:17:53 +02:00
5fb657f569 Rename make_dict_v2.sh to generate_libtoken_dict.sh 2024-06-01 13:03:55 +03:00
d2700c7525 Update README.md 2024-06-01 13:03:22 +03:00
4cf358b589 Update README.md 2024-06-01 02:06:20 +03:00
5e708b23c6 Update make_dict_v2.sh
(-) removed default vars ;
(+) added LD_PRELOAD_PATH check
2024-06-01 01:18:03 +03:00
9419e39fdf nits 2024-05-31 18:32:31 +02:00
c202d80dea Update make_dict_v2.sh 2024-05-30 22:38:37 +03:00
eecbdd99e1 Update and rename make_dict.sh to make_dict_v2.sh 2024-05-30 22:26:24 +03:00
64293cdc82 Create make_dict.sh 2024-05-30 11:13:56 +03:00
f8a5f1cd9e Merge branch 'AFLplusplus:stable' into stable 2024-05-30 10:43:01 +03:00
a3125c38f4 fix afl-showmap shmmemleak 2024-05-29 12:55:28 +02:00
224add0222 update unicorn 2024-05-28 11:12:33 +02:00
19636f748c Unicornafl: Fix incorrect comment (#2103) 2024-05-28 02:24:43 +02:00
7aa5e1c443 Merge pull request #2104 from Evian-Zhang/fix-unicorn-lldb-dumper
Make lldb dumper of unicorn_mode work in modern LLDB
2024-05-27 21:18:28 +02:00
93279db71b Make lldb dumper of unicorn_mode work in modern LLDB 2024-05-27 19:15:35 +08:00
5bf760510e Merge pull request #2102 from ndrewh/testcache-fix
fix: testcache hangs for large test cases
2024-05-26 08:12:29 +02:00
03dc80afc4 fix: testcache hangs for large test cases 2024-05-25 23:44:57 +00:00
fda3106fd9 Merge pull request #2099 from Atlante45/dev
Fix dynamic_lookup linker flag for Apple clang
2024-05-24 01:33:55 +02:00
9721a77204 Fix dynamic_lookup linker flag for Apple clang 2024-05-23 11:14:53 -07:00
92a8c2804f fix the fix for symcc 2024-05-21 16:31:42 +02:00
e1521fa8eb fix symcc custom mutator 2024-05-21 11:04:25 +02:00
4e3cd8ac3f nit 2024-05-20 14:02:22 +02:00
31a8beb449 support new llvm 19 changes 2024-05-19 13:47:53 +02:00
e7d871c8bf Merge pull request #2093 from AFLplusplus/dev
push to stable
2024-05-17 23:55:55 +02:00
56d5aa3101 log 2024-05-17 23:55:43 +02:00
c6a2a4046e Merge pull request #2092 from fbeqv/dev
Fix runtime underflow & -V exiting before syncing
2024-05-17 23:41:39 +02:00
6dd5e931fc Fix runtime underflow & -V exiting before syncing
print_stats sets exit_soon even while syncing, this leaves -V 0 still broken, as we don't finish syncing.

Additionally, the change that introduced the previous -V fix also broke the runtime tracking, as runtime needs to include all time including sync, splice etc. This caused an underflow in the reported runtime.
2024-05-17 14:33:32 -07:00
635140ba43 help qemu build for some linux platforms 2024-05-17 09:45:56 +02:00
497f341eac Revert "no weights"
This reverts commit 068aa13c6b.
2024-05-16 14:27:33 +02:00
068aa13c6b no weights 2024-05-16 14:27:04 +02:00
ba7ae6c59d nits 2024-05-16 14:21:00 +02:00
6ae95271be nits 2024-05-16 09:17:59 +02:00
a2e0163cc1 Merge pull request #2091 from bet4it/collect_coverage
Fix bug of `afl-showmap` in `collect_coverage` mode
2024-05-16 09:14:15 +02:00
1db3b81d2e dump cc 2024-05-15 14:16:44 +02:00
0a16ea7487 better cmplog ci test for low memory machines 2024-05-15 10:57:46 +02:00
a26bb0b0f2 Merge pull request #2090 from AFLplusplus/dev
push to stable
2024-05-14 13:18:22 +02:00
7d3530a22e nit 2024-05-14 13:07:47 +02:00
a87ea96913 make slow systems pass our test suite 2024-05-14 12:58:45 +02:00
81609a0f42 Merge pull request #2089 from nj00001/dev
Fix afl-fuzz -G option not configuring maximum input data size for nyx
2024-05-14 12:48:16 +02:00
938edab25f consider llvm 18 stable 2024-05-14 12:45:09 +02:00
29c9870658 disable xml/curl/g_ string transform compare 2024-05-14 12:35:32 +02:00
b6c4f3775a disable xml/curl/g_ string transform compare 2024-05-14 12:34:51 +02:00
5ee5564ae2 backup afl->max_length to afl->fsrv.max_length 2024-05-14 18:28:18 +08:00
ab36756061 change MAX_FILE to fsrv->max_length 2024-05-14 18:27:12 +08:00
831b8f35d5 Keep a backup of max_length in the afl_forkserver_t structure 2024-05-14 18:23:53 +08:00
0cf78b7748 Fix bug of afl-showmap in collect_coverage mode 2024-05-14 17:17:58 +08:00
0892a2245e float laf check 2024-05-13 20:28:50 +02:00
622474e9e4 disable -> no variants 2024-05-13 19:51:38 +02:00
0cabc12f91 Merge pull request #2086 from smoelius/dev
Add `AFL_SHA1_FILENAMES` option
2024-05-13 19:32:44 +02:00
b282ce999d post_process after trim 2024-05-13 13:42:58 +02:00
24b9d74e70 compcov int fix 2024-05-13 08:44:43 +02:00
c03f2897d0 Add AFL_SHA1_FILENAMES option 2024-05-12 05:44:14 -04:00
90fbf59bf1 Merge pull request #2084 from AFLplusplus/dev
push to stable
2024-05-11 09:16:21 +02:00
93c7cbd496 update unicorn 2024-05-11 09:01:33 +02:00
db60555c1b update changelog 2024-05-11 08:59:01 +02:00
45117a3384 Merge pull request #2083 from elboulangero/i386
Re-enable i386
2024-05-11 08:55:59 +02:00
4d4880b428 afl-cc: Re-enable i386
Was disabled in 136febaf68

Closes: #2081
2024-05-11 00:48:04 +07:00
ac6ccd53df stat update during syncing 2024-05-07 16:46:24 +02:00
4ec376bd6a Merge pull request #2076 from louismerlin/fix-whatsup-time
Fix `afl_whatsup` findings timer
2024-05-02 17:30:59 +02:00
3c0448305b Guard /proc/uptime cat with a uname check 2024-05-02 17:19:37 +02:00
a6029a10cc Fix CUR_TIME computation 2024-05-02 16:12:50 +02:00
26eaf53a83 AFL_DISABLE_REDUNDANT 2024-05-02 08:35:24 +02:00
5d623a27ed try enhanced asan support 2024-04-30 11:59:49 +02:00
69e554b941 Merge pull request #2074 from Kiprey/patch-2
Fix wrong warning in SanitizerCoverageLTO.so.cc
2024-04-29 17:11:41 +02:00
7340374a7c Fix wrong warning in SanitizerCoverageLTO.so.cc 2024-04-29 16:14:49 +08:00
67d356b73f update qemuafl 2024-04-28 15:41:24 +02:00
da18f1f722 Merge pull request #2073 from Acture/dev
Fix: Removed the redundant `id` field from redqueen.c
2024-04-28 15:39:32 +02:00
58abcceff5 Bug fix: Removed the redundant id field from the debug output in the afl-fuzz-redqueen.c file since cmp_header no longer have this field. 2024-04-28 16:24:52 +08:00
ad0d0c77fb Merge pull request #2071 from AFLplusplus/dev
Push to stable
2024-04-26 16:17:41 +02:00
2c3f761ede changes 2024-04-26 16:16:21 +02:00
70c60cfba7 work with spaces in filenames 2024-04-26 16:14:50 +02:00
f3b6d64ad3 Merge pull request #2066 from ahuo1/dev
fix: initialize n_fuzz_entry in perform_dry_run.
2024-04-26 09:44:49 +02:00
43e9a13921 add schedule check. 2024-04-26 07:45:58 +08:00
526dbe8f16 fix: initialize n_fuzz_entry in perform_dry_run. 2024-04-25 21:28:58 +08:00
951a0e5225 fix AFL_PERSISTENT_RECORD 2024-04-25 10:04:58 +02:00
458b939bc4 LTO fix 2024-04-19 17:34:50 +02:00
476aca5b67 nits 2024-04-19 15:45:00 +02:00
96bf0f8323 Merge pull request #2061 from jschwartzentruber/change_smm_vis
Specify shared memory visibility
2024-04-18 17:30:51 +02:00
58206a3180 Set explicit visibility on shared memory variables. 2024-04-17 14:40:41 -04:00
f138ab8ac6 Merge pull request #2059 from elboulangero/afl-gcc
Fix afl-gcc
2024-04-17 12:55:34 +02:00
50839cf6e9 afl-cc: Complete fix for afl-as
Look for afl-as, and then make sure that there's a 'as' binary in the
same directory, that seems to be either a symlink to, or a copy of,
afl-as.
2024-04-17 16:41:03 +07:00
626a4434ed afl-cc: Use afl-as (rather than as) to find obj path 2024-04-17 16:40:58 +07:00
d84cc73d13 afl-cc: Add missing debug statement
For each path that is tried, there's a debug log printed, _except_ for
this one. Fix it.
2024-04-17 16:40:55 +07:00
6b049536f1 v4.21 init 2024-04-13 11:54:08 +02:00
629edb1e78 Merge pull request #2 from AFLplusplus/stable
push to stable (#1734)
2023-05-22 16:57:45 +03:00
8012b555a8 Merge pull request #1 from AFLplusplus/stable
sync
2023-05-05 23:27:13 +03:00
192 changed files with 10284 additions and 3330 deletions

View File

@ -24,7 +24,7 @@ import importlib.metadata
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use # 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", "") CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")

View File

@ -5,7 +5,6 @@ on:
branches: branches:
- stable - stable
- dev - dev
- 420
pull_request: pull_request:
branches: branches:
- dev # No need for stable-pull-request, as that equals dev-push - dev # No need for stable-pull-request, as that equals dev-push
@ -35,23 +34,25 @@ jobs:
run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 distrib 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 - name: run tests
run: sudo -E ./afl-system-config; make tests run: sudo -E ./afl-system-config; make tests
# macos: macos:
# runs-on: macOS-latest runs-on: macOS-latest
# env: env:
# AFL_MAP_SIZE: 65536 AFL_MAP_SIZE: 65536
# AFL_SKIP_CPUFREQ: 1 AFL_SKIP_CPUFREQ: 1
# AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
# steps: steps:
# - uses: actions/checkout@v3 - uses: actions/checkout@v3
# - name: install - name: install
# run: brew install make gcc llvm run: brew install make gcc llvm
# - name: fix install # - name: fix install
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v # run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
# - name: build # - 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 # 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: frida - name: build
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake run: sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
# - name: run tests # - name: frida
# 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 # run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
# - name: force frida test for MacOS # - name: run tests
# 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 # 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 *.pyc
*.so *.so
*.swp *.swp
.DS_Store
.sync_tmp .sync_tmp
.test .test
.test2 .test2
@ -111,3 +112,5 @@ utils/replay_record/persistent_demo_replay_compat
utils/replay_record/persistent_demo_replay_argparse utils/replay_record/persistent_demo_replay_argparse
utils/plot_ui/afl-plot-ui utils/plot_ui/afl-plot-ui
vuln_prog 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) * [docs/](docs/) (this is where you can find most of our docs content)
* [frida_mode/](frida_mode/) * [frida_mode/](frida_mode/)
* [instrumentation/](instrumentation/) * [instrumentation/](instrumentation/)
* [nyx_mode/](nyx_mode/)
* [qemu_mode/](qemu_mode/) * [qemu_mode/](qemu_mode/)
* [unicorn_mode/](unicorn_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 * Don't: fuzzing-network-service.md
* Use a maximum of 80 characters per line to make reading in a console easier. * Use a maximum of 80 characters per line to make reading in a console easier.
* Make all pull requests against `dev`, see * 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: 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 * Use bulleted lists to present similar content in a way that makes it easy to
scan. scan.
* Use numbered lists for procedures or prioritizing. * 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 '#' # so use a variable for '#'
HASH=\# HASH=\#
PREFIX ?= /usr/local PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/share/man/man8 MAN_PATH = $(PREFIX)/share/man/man8
INCLUDE_PATH = $(PREFIX)/include/afl
PROGNAME = afl PROGNAME = afl
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) 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 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 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 ASAN_OPTIONS=detect_leaks=0
SYS = $(shell uname -s) SYS = $(shell uname -s)
@ -117,7 +117,7 @@ endif
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation") COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
ifneq "$(COMPILER_TYPE)" "" ifneq "$(COMPILER_TYPE)" ""
#$(info gcc is being used) #$(info gcc is being used)
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation override CFLAGS_OPT += -Wno-format-truncation
endif endif
ifeq "$(SYS)" "SunOS" ifeq "$(SYS)" "SunOS"
@ -325,10 +325,12 @@ ifdef TEST_MMAP
endif endif
.PHONY: all .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 -$(MAKE) -C utils/aflpp_driver
@echo @echo
@echo @echo
@echo
@echo
@echo Build Summary: @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-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" @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" ifneq "$(SYS)" "Darwin"
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this" @test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif 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 @echo
.PHONY: llvm .PHONY: llvm
@ -441,6 +444,14 @@ test_shm:
@echo "[-] shmat seems not to be working, switching to mmap implementation" @echo "[-] shmat seems not to be working, switching to mmap implementation"
endif 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 .PHONY: test_python
ifeq "$(PYTHON_OK)" "1" ifeq "$(PYTHON_OK)" "1"
test_python: test_python:
@ -455,10 +466,6 @@ endif
ready: ready:
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))" @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 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 $(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 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 $(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 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) -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 $(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 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) $(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 .PHONY: test_build
ifndef AFL_NO_X86 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..." @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 -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 -echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f 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 @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
@echo "[+] All right, the instrumentation of afl-cc seems to be working!" @echo "[+] All right, the instrumentation of afl-cc seems to be working!"
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..." # @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-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 ) # @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 # 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 # echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
# @rm -f 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." ) || \ # 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 "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue." ); echo; exit 0; fi
# @echo # @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 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)." @echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
endif 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 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 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" @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 @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 @! 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 .PHONY: clean
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.llvm clean
-$(MAKE) -f GNUmakefile.gcc_plugin clean -$(MAKE) -f GNUmakefile.gcc_plugin clean
-$(MAKE) -C utils/libdislocator 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-g++
ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang
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) @mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
install -m0644 *.8 ${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) install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
cp -r testcases/ $${DESTDIR}$(MISC_PATH) cp -r testcases/ $${DESTDIR}$(MISC_PATH)
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH) cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
@ -828,12 +836,14 @@ endif
.PHONY: uninstall .PHONY: uninstall
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 -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 -rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f" -sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES) -cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
-rmdir $${DESTDIR}$(BIN_PATH) 2>/dev/null -rmdir $${DESTDIR}$(BIN_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(INCLUDE_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(HELPER_PATH) 2>/dev/null -rmdir $${DESTDIR}$(HELPER_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(MISC_PATH) 2>/dev/null -rmdir $${DESTDIR}$(MISC_PATH) 2>/dev/null
-rmdir $${DESTDIR}$(DOC_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 .PHONY: test_build
test_build: $(PROGS) test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..." @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 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 echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f 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) SYS = $(shell uname -s)
override LLVM_TOO_NEW_DEFAULT := 18
override LLVM_TOO_OLD_DEFAULT := 13
ifeq "$(SYS)" "OpenBSD" ifeq "$(SYS)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1) 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") $(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
endif endif
else 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 endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' ) ifneq "$(LLVM_CONFIG)" ""
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' ) override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' ) LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 ) LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 ) LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) endif
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 ) ifneq "$(LLVMVER)" ""
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 ) LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
LLVM_STDCXX = gnu++11 LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0) LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
LLVM_LTO = 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)" "" ifeq "$(LLVMVER)" ""
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.) $(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.) $(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.)
endif 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 # 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 # this seems to be busted on some distros, so using the one in $PATH is
# probably better. # probably better.
@ -114,6 +125,11 @@ endif
CC = $(LLVM_BINDIR)/clang CC = $(LLVM_BINDIR)/clang
CXX = $(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 ... # llvm-config --bindir may not providing a valid path, so ...
ifeq "$(shell test -e $(CC) || echo 1 )" "1" ifeq "$(shell test -e $(CC) || echo 1 )" "1"
# however we must ensure that this is not a "CC=gcc make" # however we must ensure that this is not a "CC=gcc make"
@ -147,7 +163,7 @@ endif
# sanity check. # sanity check.
# Are versions of clang --version and llvm-config --version equal? # 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) # 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 # We did exactly set these 26 lines above with these values, and it would break
@ -245,7 +261,7 @@ endif
AFL_CLANG_FUSELD= AFL_CLANG_FUSELD=
ifeq "$(LLVM_LTO)" "1" 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 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" 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 AFL_CLANG_LDPATH=1
@ -300,8 +316,8 @@ endif
ifneq "$(LLVM_CONFIG)" "" ifneq "$(LLVM_CONFIG)" ""
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
endif endif
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS) CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS)
# wasm fuzzing: disable thread-local storage and unset LLVM debug flag # wasm fuzzing: disable thread-local storage and unset LLVM debug flag
ifdef WAFL_MODE ifdef WAFL_MODE
@ -311,7 +327,7 @@ endif
# User teor2345 reports that this is required to make things work on MacOS X. # User teor2345 reports that this is required to make things work on MacOS X.
ifeq "$(SYS)" "Darwin" ifeq "$(SYS)" "Darwin"
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress CLANG_LFL += -Wl,-undefined,dynamic_lookup
override LLVM_HAVE_LTO := 0 override LLVM_HAVE_LTO := 0
override LLVM_LTO := 0 override LLVM_LTO := 0
else else
@ -319,7 +335,7 @@ else
endif endif
ifeq "$(SYS)" "OpenBSD" ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
CLANG_CPPFL += -mno-retpoline CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline CFLAGS += -mno-retpoline
# Needed for unwind symbols # Needed for unwind symbols
@ -417,7 +433,7 @@ endif
endif endif
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h 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 ./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_MIN_4_0_1)" "0" ifeq "$(LLVM_MIN_4_0_1)" "0"
@ -492,7 +508,7 @@ document:
.PHONY: test_build .PHONY: test_build
test_build: $(PROGS) test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..." @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 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 echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr @rm -f test-instr

View File

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

View File

@ -2,6 +2,8 @@
## Must ## Must
- ijon support?
- check for null ptr for xml/curl/g_ string transform functions
- hardened_usercopy=0 page_alloc.shuffle=0 - hardened_usercopy=0 page_alloc.shuffle=0
- add value_profile but only enable after 15 minutes without finds - add value_profile but only enable after 15 minutes without finds
- cmplog max items env? - cmplog max items env?
@ -16,6 +18,7 @@
## Should ## Should
- afl-crash-analysis - afl-crash-analysis
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
- support persistent and deferred fork server in afl-showmap? - support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values - better autodetection of shifting runtime timeout values
- afl-plot to support multiple plot_data - afl-plot to support multiple plot_data

View File

@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
# awk script to minimize a test corpus of input files # awk script to minimize a test corpus of input files
# #
# based on afl-cmin bash script written by Michal Zalewski # based on afl-cmin bash script written by Michal Zalewski
# rewritten by Heiko Eißfeldt (hexcoder-) # rewritten by Heiko Eissfeldt (hexcoder-)
# tested with: # tested with:
# gnu awk (x86 Linux) # gnu awk (x86 Linux)
# bsd awk (x86 *BSD) # bsd awk (x86 *BSD)
@ -603,8 +603,8 @@ BEGIN {
# create path for the trace file from afl-showmap # create path for the trace file from afl-showmap
tracefile_path = trace_dir"/"fn tracefile_path = trace_dir"/"fn
# ensure the file size is not zero # ensure the file size is not zero
cmd = "du -b "tracefile_path cmd = "du -b \""tracefile_path"\""
"ls -l "tracefile_path # "ls -l \""tracefile_path"\""
cmd | getline output cmd | getline output
close(cmd) close(cmd)
split(output, result, "\t") split(output, result, "\t")

View File

@ -152,6 +152,7 @@ Minimization settings:
-e - solve for edge coverage only, ignore hit counts -e - solve for edge coverage only, ignore hit counts
For additional tips, please consult README.md. For additional tips, please consult README.md.
This script cannot read filenames that end with a space ' '.
Environment variables used: Environment variables used:
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory

View File

@ -111,7 +111,13 @@ if [ -z "$NO_COLOR" ]; then
RESET="$NC" RESET="$NC"
fi fi
CUR_TIME=`date +%s` PLATFORM=`uname -s`
#if [ "$PLATFORM" = "Linux" ] ; then
# CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
#else
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
CUR_TIME=`date +%s`
#fi
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1 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 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 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 | 5400 | 32 | 71566 | 1566279 | system |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both | |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); u8 *ptr = realloc(data->buf, max_size);
if (ptr) { if (!ptr) {
return 0; return 0;

View File

@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC
all: aflpp-standalone all: aflpp-standalone
aflpp-standalone: aflpp-standalone.c 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: clean:
rm -f *.o *~ aflpp-standalone core 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. 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-fuzz.h"
#include "afl-mutations.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 { typedef struct my_mutator {
afl_state_t *afl; 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"); perror("afl_custom_init alloc");
return NULL; return NULL;
} else { } 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 = calloc(1, sizeof(afl_state_t));
data->afl->queue_cycle = 1; data->afl->queue_cycle = 1;
data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); 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()); 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; 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); u8 *ptr = realloc(data->buf, max_size);
if (ptr) { if (!ptr) {
return 0; 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 ... :( */ /* set everything up, costly ... :( */
memcpy(data->buf, buf, buf_size); memcpy(data->buf, buf, buf_size);
/* the mutation */ /* the mutation */
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, u32 out_buf_len;
false, true, add_buf, add_buf_size, max_size); 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 */ /* return size of mutated data */
*out_buf = data->buf; *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[]) { int main(int argc, char *argv[]) {
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) { 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(
printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n"); "Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
printf("no output filename is given. As an optional third parameter you can give a file\n"); "[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("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; return 0;
} }
FILE *in = stdin, *out = stdout, *splice = NULL; FILE *in = stdin, *out = stdout, *splice = NULL;
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL; unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
int verbose = 0, splicelen = 0; 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); my_mutator_t *data = afl_custom_init(NULL, 0);
if (argc > 1 && strcmp(argv[1], "-") != 0) { if (argc > optind && strcmp(argv[optind], "-") != 0) {
if ((in = fopen(argv[1], "r")) == NULL) {
if ((in = fopen(argv[optind], "r")) == NULL) {
perror(argv[1]); perror(argv[1]);
return -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) { 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; return -1;
} }
if (argc > 2 && strcmp(argv[2], "-") != 0) { if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
if ((out = fopen(argv[2], "w")) == NULL) {
perror(argv[2]); if ((out = fopen(argv[optind + 1], "w")) == NULL) {
perror(argv[optind + 1]);
return -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 (argc > optind + 2) {
if ((splice = fopen(argv[3], "r")) == NULL) {
perror(argv[3]); if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
perror(argv[optind + 2]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
splicebuf = malloc(1024*1024); if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
size_t splicelen = fread(splicebuf, 1, 1024*1024, splice); splicebuf = malloc(1024 * 1024);
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
if (!splicelen) { if (!splicelen) {
fprintf(stderr, "Error: empty file %s\n", argv[3]);
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen); if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
} }
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen); 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) { if (outlen == 0 || !outbuf) {
fprintf(stderr, "Error: no mutation data returned.\n"); fprintf(stderr, "Error: no mutation data returned.\n");
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen); if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) { if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n"); fprintf(stderr, "Warning: incomplete write.\n");
return -1; return -1;
} }
return 0; 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) **NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
```bash ```bash
# create the required a random seed first # create the required random seed first
mkdir -p ~/campaign/example/seeds mkdir -p ~/campaign/example/seeds
cd ~/campaign/example/seeds cd ~/campaign/example/seeds
head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded 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); } if (fd_socket != -1) { close(fd_socket); }
*out_buf = NULL; *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 #ifndef AFL_TXT_MAX_LEN
#define AFL_TXT_MAX_LEN 65535 #define AFL_TXT_MAX_LEN 65535
#endif #endif
#define AUTOTOKENS_TXT_MIN_LEN 1
#if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN #if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN
#error SPLICE_MIN must be lower than SIZE_MIN #error SPLICE_MIN must be lower than SIZE_MIN
@ -57,8 +58,9 @@ typedef struct my_mutator {
if (unlikely(debug)) fprintf if (unlikely(debug)) fprintf
#define IFDEBUG if (unlikely(debug)) #define IFDEBUG if (unlikely(debug))
int module_disabled = 0;
static afl_state *afl_ptr; static afl_state *afl_ptr;
static int module_disabled = 0;
static int auto_disable = AUTOTOKENS_AUTO_DISABLE; static int auto_disable = AUTOTOKENS_AUTO_DISABLE;
static int debug = AUTOTOKENS_DEBUG; static int debug = AUTOTOKENS_DEBUG;
static int only_fav = AUTOTOKENS_ONLY_FAV; 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 (afl_ptr->custom_only || !auto_disable) { return; }
if (unlikely(afl_ptr->active_items == 1 && 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; 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, u8 **out_buf, u8 *add_buf,
size_t add_buf_size, size_t max_size) { 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 && if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 &&
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) { afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) {
retry_thin_air:
DEBUGF(stderr, "Creating an entry from thin air...\n"); DEBUGF(stderr, "Creating an entry from thin air...\n");
structure = new vector<u32>(); structure = new vector<u32>();
u32 item, prev, cnt = current_id >> 1; 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()) { 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! // this input file was not analyzed for tokens yet, so let's do it!
size_t len = afl_ptr->queue_cur->len; 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 file_mapping[fn] = structure; // NULL ptr so we don't read the file again
s = NULL; s = NULL;
@ -895,6 +896,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
if (tokens.size() < AUTOTOKENS_SIZE_MIN) { if (tokens.size() < AUTOTOKENS_SIZE_MIN) {
if (create_from_thin_air) { goto retry_thin_air; }
file_mapping[fn] = NULL; file_mapping[fn] = NULL;
s = NULL; s = NULL;
DEBUGF(stderr, "too few tokens\n"); 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); (void)(seed);
my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t)); 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] = "'"; id_to_token[current_id] = "'";
++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 @@
5ed4f8d 05d8f53

View File

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

View File

@ -5,4 +5,5 @@ members = [
"example", "example",
# Lain needs a nightly toolchain # Lain needs a nightly toolchain
# "example_lain", # "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 These bindings are documented with rustdoc. To view the documentation run
```cargo doc -p custom_mutator --open```. ```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`. 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. 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 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; /*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
int afl_custom_init_trim(&self, buffer: &[u8]); int afl_custom_init_trim(&self, buffer: &[u8]);
size_t afl_custom_trim(&self, unsigned char **out_buf); 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), 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 /// 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) { pub unsafe extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) {
$crate::wrappers::afl_custom_deinit_::<$mutator_type>(data) $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]> { ) -> Option<&'b [u8]> {
unimplemented!() unimplemented!()
} }
fn post_process<'b, 's: 'b>(&'s mut self, buffer: &'b mut [u8]) -> Option<&'b [u8]> {
unimplemented!()
}
} }
export_mutator!(ExampleMutator); export_mutator!(ExampleMutator);
@ -579,6 +622,13 @@ pub trait CustomMutator {
fn introspection(&mut self) -> Result<Option<&str>, Self::Error> { fn introspection(&mut self) -> Result<Option<&str>, Self::Error> {
Ok(None) 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 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`]. /// the default value to return from [`CustomMutator::describe`].

View File

@ -8,9 +8,9 @@ edition = "2021"
[dependencies] [dependencies]
custom_mutator = { path = "../custom_mutator" } custom_mutator = { path = "../custom_mutator" }
lain="0.5" lain = { git = "https://github.com/AFLplusplus/lain.git" }
[[example]] [[example]]
name = "example_lain" name = "example_lain"
path = "./src/lain_mutator.rs" 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

@ -22,10 +22,10 @@ afl_state_t *afl_struct;
typedef struct my_mutator { typedef struct my_mutator {
afl_state_t *afl; afl_state_t *afl;
u8 * mutator_buf; u8 *mutator_buf;
u8 * out_dir; u8 *out_dir;
u8 * tmp_dir; u8 *tmp_dir;
u8 * target; u8 *target;
uint32_t seed; uint32_t seed;
} my_mutator_t; } my_mutator_t;
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
/* When a new queue entry is added we run this input with the symcc /* When a new queue entry is added we run this input with the symcc
instrumented binary */ instrumented binary */
uint8_t afl_custom_queue_new_entry(my_mutator_t * data, uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
const uint8_t *filename_new_queue, const uint8_t *filename_new_queue,
const uint8_t *filename_orig_queue) { const uint8_t *filename_orig_queue) {
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
struct dirent **nl; struct dirent **nl;
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL); int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
u8 * origin_name = basename(filename_new_queue); u8 *origin_name = basename(filename_new_queue);
int32_t i; int32_t i;
if (items > 0) { if (items > 0) {
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
DBG("test=%s\n", fn); DBG("test=%s\n", fn);
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
u8 *destination_name = u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name); origin_name, nl[i]->d_name);
rename(source_name, destination_name); rename(source_name, destination_name);
ck_free(destination_name); ck_free(destination_name);
DBG("found=%s\n", source_name); DBG("found=%s\n", source_name);
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
for (i = 0; i < (u32)items; ++i) { for (i = 0; i < (u32)items; ++i) {
struct stat st; struct stat st;
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name); u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
DBG("test=%s\n", fn); DBG("test=%s\n", fn);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
if (items <= 0) return 0; if (items <= 0) return 0;
for (i = 0; i < (u32)items; ++i) { for (i = 0; i < (s32)items; ++i) {
struct stat st; if (!done) {
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (done == 0) { struct stat st;
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) { if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
} }
unlink(fn); unlink(fn);
ck_free(fn);
} }
ck_free(fn);
free(nl[i]); free(nl[i]);
} }

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,90 @@
This is the list of all noteworthy changes made in every public This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual. 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
do a switch from gettimeofday() to clock_gettime() which should be rather
three times faster. The reason for this is unknown.
- new queue selection algorithm based on 2 core years of queue data
analysis. gives a noticable improvement on coverage although the results
seem counterintuitive :-)
- added AFL_DISABLE_REDUNDANT for huge queues
- added `AFL_NO_SYNC` environment variable that does what you think it does
- fix AFL_PERSISTENT_RECORD
- run custom_post_process after standard trimming
- prevent filenames in the queue that have spaces
- minor fix for FAST schedules
- more frequent stats update when syncing (todo: check performance impact)
- now timing of calibration, trimming and syncing is measured seperately,
thanks to @eqv!
- -V timing is now accurately the fuzz time (without syncing), before
long calibration times and syncing could result in now fuzzing being
made when the time was already run out until then, thanks to @eqv!
- fix -n uninstrumented mode when ending fuzzing
- enhanced the ASAN configuration
- make afl-fuzz use less memory with cmplog and fix a memleak
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode for i386
- fix COMPCOV split compare for old LLVMs
- disable xml/curl/g_ string transform functions because we do not check
for null pointers ... TODO
- ensure shared memory variables are visible in weird build setups
- compatability to new LLVM 19 changes
* afl-cmin
- work with input files that have a space
* afl-showmap
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
- minor fix to collect coverage -C (thanks to @bet4it)
* Fixed a shmem mmap bug (that rarely came up on MacOS)
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
### Version ++4.20c (release) ### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is ! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built backward compatible to old compiled targets if they are not built
@ -36,12 +120,13 @@
- afl-whatsup: - afl-whatsup:
- now also displays current average speed - now also displays current average speed
- small bugfixes - small bugfixes
- Fixes for aflpp custom mutator and standalone tool - custom mutators:
- fixes for aflpp custom mutator and standalone tool
- important fix to the symcc custom mutator
- Minor edits to afl-persistent-config - Minor edits to afl-persistent-config
- Prevent temporary files being left behind on aborted afl-whatsup - Prevent temporary files being left behind on aborted afl-whatsup
- More CPU benchmarks added to benchmark/ - More CPU benchmarks added to benchmark/
### Version ++4.10c (release) ### Version ++4.10c (release)
- afl-fuzz: - afl-fuzz:
- default power schedule is now EXPLORE, due a fix in fast schedules - default power schedule is now EXPLORE, due a fix in fast schedules

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 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 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 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 git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus cd AFLplusplus
make distrib 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 there will either be no coverage for the instrumented dlopen()'ed libraries or
you will see lots of crashes in the UI. you will see lots of crashes in the UI.
Note that this is not an issue if you use the inferiour `afl-gcc-fast`, Note that this is not an issue if you use the inferiour `afl-gcc-fast`, or
`afl-gcc` or`AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast` `AFL_LLVM_INSTRUMENT=CLASSIC/NGRAM/CTX afl-clang-fast` instrumentation.
instrumentation.
### Fuzzing a binary-only target ### 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, 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 e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
that you start the target with afl-fuzz. 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) Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
- `queue_new_entry` (optional): - `queue_new_entry` (optional):
@ -266,6 +271,11 @@ trimmed input. Here's a quick API description:
Omitting any of three trimming methods will cause the trimming to be disabled Omitting any of three trimming methods will cause the trimming to be disabled
and trigger a fallback to the built-in default trimming routine. and trigger a fallback to the built-in default trimming routine.
**IMPORTANT** If you have a custom post process mutator that needs to be run
after trimming, you must call it yourself at the end of your successful
trimming!
### Environment Variables ### Environment Variables
Optionally, the following environment variables are supported: Optionally, the following environment variables are supported:

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 - Use the `AFL_CC_COMPILER` environment variable with `MODE`. To select
`MODE`, use one of the following values: `MODE`, use one of the following values:
- `GCC` (afl-gcc/afl-g++)
- `GCC_PLUGIN` (afl-g*-fast) - `GCC_PLUGIN` (afl-g*-fast)
- `LLVM` (afl-clang-fast*) - `LLVM` (afl-clang-fast*)
- `LTO` (afl-clang-lto*). - `LTO` (afl-clang-lto*).
@ -45,14 +44,10 @@ fairly broad use of environment variables instead:
make make
``` ```
- Setting `AFL_AS`, `AFL_CC`, and `AFL_CXX` lets you use alternate downstream - Setting `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
compilation tools, rather than the default 'as', 'clang', or 'gcc' binaries compilation tools, rather than the default 'clang', or 'gcc' binaries
in your `$PATH`. 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 - 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 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 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 optimizations, set `AFL_DONT_OPTIMIZE`. However, if `-O...` and/or
`-fno-unroll-loops` are set, these are not overridden. `-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 - Setting `AFL_HARDEN` automatically adds code hardening options when invoking
the downstream compiler. This currently includes `-D_FORTIFY_SOURCE=2` and the downstream compiler. This currently includes `-D_FORTIFY_SOURCE=2` and
`-fstack-protector-all`. The setting is useful for catching non-crashing `-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 Setting `AFL_INST_RATIO` to 0 is a valid choice. This will instrument only
the transitions between function entry points, but not individual branches. the transitions between function entry points, but not individual branches.
Note that this is an outdated variable. A few instances (e.g., afl-gcc) Note that this is an outdated variable. Only LLVM CLASSIC pass can use this.
still support these, but state-of-the-art (e.g., LLVM LTO and LLVM PCGUARD)
do not need this.
- `AFL_NO_BUILTIN` causes the compiler to generate code suitable for use with - `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). 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. - `AFL_PATH` can be used to point a directory that contains LLVM/GCC plugins
One possible use of this is utils/clang_asm_normalize/, which lets you for AFL++, AFL++'s runtime objects and QEMU/Frida support files.
instrument hand-written assembly when compiling clang code by plugging a
normalizer into the chain. (There is no equivalent feature for GCC.)
- Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being - Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being
displayed during compilation, in case you find them distracting. displayed during compilation, in case you find them distracting.
@ -101,6 +95,7 @@ fairly broad use of environment variables instead:
detection) detection)
- `AFL_USE_CFISAN=1` - activates the Control Flow Integrity sanitizer (e.g. - `AFL_USE_CFISAN=1` - activates the Control Flow Integrity sanitizer (e.g.
type confusion vulnerabilities) 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 - `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 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 `__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 - `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
conditions conditions
- `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer - `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, - `TMPDIR` is used by afl-as for temporary files; if this variable is not set,
the tool defaults to /tmp. the tool defaults to /tmp.
@ -323,6 +321,11 @@ mode.
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
for more information. 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 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 code with calls to an injected subroutine instead of the much more efficient
inline instrumentation. inline instrumentation.
@ -331,7 +334,26 @@ mode.
the target performs only a few loops, then this will give a small the target performs only a few loops, then this will give a small
performance boost. 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 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: 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 XML or other highly flexible structured input. For details, see
[custom_mutators.md](custom_mutators.md). [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 - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time
a cycle is finished. a cycle is finished.
@ -381,6 +407,9 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is - Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
usually a bad idea! usually a bad idea!
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
This can be useful with huge queues.
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach - Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
new coverage new coverage
@ -398,9 +427,8 @@ checks or alter some of the more exotic semantics of the tool:
types of automated jobs. types of automated jobs.
- `AFL_EXIT_WHEN_DONE` causes afl-fuzz to terminate when all existing paths - `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 have been fuzzed and there were no new finds for a while. This is basically
normally indicated by the cycle counter in the UI turning green. May be when the fuzzing state says `state: finished`
convenient for some types of automated jobs.
- Setting `AFL_EXPAND_HAVOC_NOW` will start in the extended havoc mode that - Setting `AFL_EXPAND_HAVOC_NOW` will start in the extended havoc mode that
includes costly mutations. afl-fuzz automatically enables this mode when includes costly mutations. afl-fuzz automatically enables this mode when
@ -511,6 +539,8 @@ checks or alter some of the more exotic semantics of the tool:
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if - `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
the snapshot lkm is loaded. 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 - Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints
some basic stats. This behavior is also automatically triggered when the some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe. output from afl-fuzz is redirected to a file or to a pipe.
@ -547,6 +577,9 @@ checks or alter some of the more exotic semantics of the tool:
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
arguments. arguments.
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
of their contents, rather than use the standard `id:000000,...` names.
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested - `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
by some users for unorthodox parallelized fuzzing setups, but not advisable by some users for unorthodox parallelized fuzzing setups, but not advisable
otherwise. otherwise.
@ -579,9 +612,12 @@ checks or alter some of the more exotic semantics of the tool:
see [rpc_statsd.md](rpc_statsd.md). see [rpc_statsd.md](rpc_statsd.md).
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes) - `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. note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
other syncing parameters.
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would ... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
@ -627,7 +663,7 @@ checks or alter some of the more exotic semantics of the tool:
Note that will not be exact and with slow targets it can take seconds Note that will not be exact and with slow targets it can take seconds
until there is a slice for the time test. 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: The QEMU wrapper used to instrument binary-only code supports several settings:
@ -699,7 +735,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when
counting crashes based on a file count in that directory. 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 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 options as `afl-qemu-trace`, but also has a number of additional advanced
@ -789,7 +825,7 @@ support.
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
killing the process whilst it is being dumped. 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: The corpus minimization script offers very little customization:
@ -807,7 +843,7 @@ The corpus minimization script offers very little customization:
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed. - `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. 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 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 searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a
@ -818,12 +854,12 @@ to match when minimizing crashes. This will make minimization less useful, but
may prevent the tool from "jumping" from one crashing condition to another in 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. 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 You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
of decimal. of decimal.
## 11) Settings for libdislocator ## 12) Settings for libdislocator
The library honors these environment variables: The library honors these environment variables:
@ -845,12 +881,12 @@ The library honors these environment variables:
- `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that - `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that
may be useful for pinpointing the cause of any observed issues. 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 This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
discovered tokens should be written. 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 Several variables are not directly interpreted by afl-fuzz, but are set to
optimal values if not already present in the environment: 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 ## 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) | Note that afl-gcc and afl-clang have been removed because their instrumentation is absolutely outdated.
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
| Threadsafe counters [A] | | x(3) | | | | | x | | | Feature/Instrumentation | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | | | ------------------------------|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | | | Threadsafe counters [A] | x(3) | | | | | x | |
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | | | NeverZero [B] | x(1) | x | x | x | x | | |
| CmpLog [E] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | | | Persistent Mode [C] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
| Selective Instrumentation [F] | | x | x | x | x | | | | | LAF-Intel / CompCov [D] | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | | | CmpLog [E] | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | | | Selective Instrumentation [F] | x | x | x | x | | | |
| Context Coverage [I] | | x(6) | | | | | | | | Non-Colliding Coverage [G] | x(4) | | | (x)(5) | | | |
| Auto Dictionary [J] | | x(7) | | | | | | | | Ngram prev_loc Coverage [H] | x(6) | | | | | | |
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | | | Context Coverage [I] | x(6) | | | | | | |
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | | | 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 ## 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: 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 prevents a wrapping map value to zero, increases coverage
* Persistent mode, deferred forkserver and in-memory fuzzing for QEMU mode * Persistent mode, deferred forkserver and in-memory fuzzing for QEMU mode
* Unicorn mode which allows fuzzing of binaries from completely different * 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` `AFL_COMPCOV_LEVEL=2`), alternatively you can use FRIDA mode, just switch `-Q`
with `-O` and remove the LAF instance with `-O` and remove the LAF instance
Then run as many instances as you have cores left with either -Q mode or - even Then run as many instances as you have cores left with either `-Q` mode or use
better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc. a static binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
The binary rewriters all have their own advantages and caveats. The binary rewriters all have their own advantages and caveats, but ZAFL is a good choice.
ZAFL is the best but cannot be used in a business/commercial context.
If a binary rewriter works for your target then you can use afl-fuzz normally 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 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 x86_64 - still has it's symbols and compiled with position independent code
(PIC/PIE), then the RetroWrite solution might be for you. (PIC/PIE), then the RetroWrite solution might be for you.
It decompiles to ASM files which can then be instrumented with afl-gcc. 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 Binaries that are statically instrumented for fuzzing using RetroWrite are close
in performance to compiler-instrumented binaries and outperform the QEMU-based 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, It is highly recommended to have the newest llvm version possible installed,
anything below 9 is not recommended. 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++) | 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 | if not, or if you do not have a gcc with plugin support
| |
v 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: 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) * [LTO mode - afl-clang-lto](../instrumentation/README.lto.md)
* [LLVM mode - afl-clang-fast](../instrumentation/README.llvm.md) * [LLVM mode - afl-clang-fast](../instrumentation/README.llvm.md)
* [GCC_PLUGIN mode - afl-gcc-fast](../instrumentation/README.gcc_plugin.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: 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-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`. * Using the environment variable `AFL_CC_COMPILER` with `MODE`.
* Passing --afl-`MODE` command line options to the compiler via * Passing --afl-`MODE` command line options to the compiler via
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`. `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*) * LTO (afl-clang-lto*)
* LLVM (afl-clang-fast*) * LLVM (afl-clang-fast*)
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++) * GCC_PLUGIN (afl-g*-fast)
* CLANG(afl-clang/afl-clang++)
Because no AFL++ specific command-line options are accepted (beside the Because no AFL++ specific command-line options are accepted (beside the
--afl-MODE command), the compile-time tools make fairly broad use of environment --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 (address sanitizer) anyway after syncing test cases from other fuzzing
instances, so running more than one address sanitized target would be a waste. 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++: The following sanitizers have built-in support in AFL++:
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like * 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 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 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, 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`. 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: arm:
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all 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): $(BUILD_DIR):
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)

View File

@ -6,34 +6,39 @@
#define UNUSED_PARAMETER(x) (void)(x) #define UNUSED_PARAMETER(x) (void)(x)
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
{
UNUSED_PARAMETER (size);
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) { int main(int argc, char **argv, char **envp) {
UNUSED_PARAMETER (argc);
ElfW(Addr) base = 0; UNUSED_PARAMETER(argc);
int persona = personality(ADDR_NO_RANDOMIZE); ElfW(Addr) base = 0;
if (persona == -1) {
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno); int persona = personality(ADDR_NO_RANDOMIZE);
return 1; 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 ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
if (base == 0) { return 1; }
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_stdout;
js_api_set_traceable; js_api_set_traceable;
js_api_set_verbose; js_api_set_verbose;
js_api_ijon_set;
local: local:
*; *;

View File

@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
// do a length check matching the target! // do a length check matching the target!
void **esp = (void **)regs->esp; void **esp = (void **)regs->esp;
void *arg1 = esp[0]; void *arg1 = esp[1];
void **arg2 = &esp[1]; void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len); memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)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, void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) { 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); memcpy((void *)regs->rdi, input_buf, input_buf_len);
regs->rsi = 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, void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) { uint8_t *input_buf, uint32_t input_buf_len) {
(void)guest_base; /* unused */ (void)guest_base; /* unused */
void **esp = (void **)regs->esp; void **esp = (void **)regs->esp;
void * arg1 = esp[1]; void *arg1 = esp[1];
void **arg2 = &esp[2]; void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len); memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len; *arg2 = (void *)input_buf_len;
} }
#elif defined(__aarch64__) #elif defined(__aarch64__)
struct arm64_regs { struct arm64_regs {
@ -177,9 +178,10 @@ struct arm64_regs {
void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base, void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) { 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); memcpy((void *)regs->x0, input_buf, input_buf_len);
regs->x1 = input_buf_len; regs->x1 = input_buf_len;
} }
#else #else
@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) {
return 1; return 1;
} }

View File

@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed;
extern uint8_t *__afl_area_ptr; extern uint8_t *__afl_area_ptr;
extern uint32_t __afl_map_size; extern uint32_t __afl_map_size;
extern void __afl_coverage_interesting(uint8_t, uint32_t);
extern __thread guint64 *instrument_previous_pc_addr; 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_write_regs(GumCpuContext *cpu_context, gpointer user_data);
void instrument_regs_format(int fd, char *format, ...); void instrument_regs_format(int fd, char *format, ...);
void ijon_set(uint32_t edge);
#endif #endif

View File

@ -39,18 +39,18 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
address = base + index + mem->disp; 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) { if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) {
asan_storeN(address, asan_ctx->size); 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) { 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); 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); FVERBOSE("Coverage Unstable - fds: %s", fds_name);
for (const gchar *filename = g_dir_read_name(dir); filename != NULL; 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); } if (link == NULL) { FFATAL("Failed to read link: %s", fullname); }
gchar *basename = g_path_get_basename(link); 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(basename);
g_free(link); g_free(link);
@ -874,6 +877,7 @@ void instrument_coverage_unstable_find_output(void) {
} }
g_dir_close(dir); g_dir_close(dir);
g_free(instance_name);
g_free(fds_name); g_free(fds_name);
if (unstable_coverage_fuzzer_stats == NULL) { if (unstable_coverage_fuzzer_stats == NULL) {

View File

@ -49,14 +49,23 @@ void instrument_cache_init(void) {
if (setrlimit(RLIMIT_AS, &data_limit) != 0) { if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
FFATAL("Failed to setrlimit: %d", errno); FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
errno);
} }
map_base = map_base =
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size, gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
GUM_PAGE_READ | GUM_PAGE_WRITE); GUM_PAGE_READ | GUM_PAGE_WRITE);
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); } if (map_base == MAP_FAILED) {
FFATAL(
"Failed to map segment: %d. This can be caused by failure to setrlimit."
"Disabling or reducing the size of the allocation using "
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
errno);
}
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]", FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
GUM_ADDRESS(map_base)); GUM_ADDRESS(map_base));

View File

@ -326,6 +326,12 @@ class Afl {
static jsApiGetSymbol(name) { static jsApiGetSymbol(name) {
return Afl.module.getExportByName(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 * 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( Afl.jsApiWrite = new NativeFunction(
/* tslint:disable-next-line:no-null-keyword */ /* tslint:disable-next-line:no-null-keyword */
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); 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 // r15 - pc
static GumCpuContext saved_regs = {0}; static GumCpuContext saved_regs = {0};
static gpointer saved_lr = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { 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); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
GUM_ARG_REGISTER, ARM_REG_R0);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); 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; *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_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE); 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_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, 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) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumArmWriter *cw = output->writer.arm; GumArmWriter *cw = output->writer.arm;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_arm_writer_put_label(cw, loop); 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); 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 */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); 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); } 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); } 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); 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; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer saved_lr = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { 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); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_arm64_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); 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; *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_INDEX_PRE_ADJUST);
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, 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); 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) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumArm64Writer *cw = output->writer.arm64; GumArm64Writer *cw = output->writer.arm64;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_arm64_writer_put_label(cw, loop); 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); 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 */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); 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); } 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); } if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, 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); 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; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { 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)); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); 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; *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_RED_ZONE_SIZE));
gum_x86_writer_put_call_address_with_arguments( gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); 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_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE)); (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_RAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX); 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, gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
offset); offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX); 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) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumX86Writer *cw = output->writer.x86; GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); 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); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_x86_writer_put_label(cw, loop); 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); 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 */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); 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); } if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
} }
void persistent_epilogue_arch(GumStalkerOutput *output) { 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_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
gum_x86_writer_put_label(cw, zero); 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); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
} }

View File

@ -16,8 +16,7 @@ typedef struct {
} persistent_ctx_t; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer persistent_loop = NULL;
static gpointer saved_ret = NULL;
gboolean persistent_is_supported(void) { 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)); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
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);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); 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; *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( gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); 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_EAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX); 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, gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
offset); offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX); 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) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumX86Writer *cw = output->writer.x86; GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); 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); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_x86_writer_put_label(cw, loop); 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); 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 */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); 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); } if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
} }
void persistent_epilogue_arch(GumStalkerOutput *output) { 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); } 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); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
} }

View File

@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
if (details->file == NULL) { if (details->file == NULL) {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
"X %c%c%c", details->range->base_address,
details->range->base_address, details->range->base_address + details->range->size,
details->range->base_address + details->range->size, details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_READ ? 'R' : '-', details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-', details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
} else { } else {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address, details->range->base_address,
details->range->base_address + details->range->size, details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-', details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-', details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
details->file->path, details->file->offset); details->file->offset);
} }
@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) {
void ranges_print_debug_maps(void) { void ranges_print_debug_maps(void) {
FVERBOSE("Maps"); OKF("Maps");
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL); gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
} }

View File

@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) {
if (!initialized) { if (!initialized) {
initialized = TRUE; 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); void LLVMFuzzerTestOneInput(char *buf, int len);
__asm__ ( __asm__(
"LLVMFuzzerTestOneInput:\n" "LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n" ".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n" ".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n" " jmpq *jmp_offset(%rip)\n"
" nop\n" " nop\n"
" nop\n" " nop\n"
"call_target:\n" "call_target:\n"
" ret\n" " ret\n"
" nop\n" " nop\n"
" nop\n" " nop\n"
"jmp_target:\n" "jmp_target:\n"
" callq *call_offset(%rip)\n" " callq *call_offset(%rip)\n"
" nop\n" " nop\n"
" nop\n" " nop\n"
" leaq rax_offset(%rip), %rax\n" " leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n" " jmp (%rax)\n"
" nop\n" " nop\n"
" ud2\n" " ud2\n"
" nop\n" " nop\n"
"rax_target:\n" "rax_target:\n"
" ret\n" " ret\n"
"\n" "\n"
"\n" "\n"
".global jmp_offset\n" ".global jmp_offset\n"
".p2align 3\n" ".p2align 3\n"
"jmp_offset:\n" "jmp_offset:\n"
" .quad jmp_target\n" " .quad jmp_target\n"
"call_offset:\n" "call_offset:\n"
" .quad call_target\n" " .quad call_target\n"
"rax_offset:\n" "rax_offset:\n"
" .quad rax_target\n" " .quad rax_target\n");
);
int main(int argc, char **argv) { int main(int argc, char **argv) {
char * file; char *file;
int fd = -1; int fd = -1;
off_t len; off_t len;
char * buf = NULL; char *buf = NULL;
size_t n_read; size_t n_read;
int result = -1; int result = -1;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,60 +22,60 @@
#define IGNORED_RETURN(x) (void)!(x) #define IGNORED_RETURN(x) (void)!(x)
const uint32_t crc32_tab[] = { 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 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
crc32(const void *buf, size_t size) 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
{ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
const uint8_t *p = buf; 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
uint32_t crc; 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
crc = ~0U; 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
while (size--) 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
return crc ^ ~0U; 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 * FRIDA to patch this function out and always return success. Otherwise, we
* could change it to actually correct the checksum. * 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; } if (len < sizeof(uint32_t)) { return 0; }
uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)]; uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)];
uint32_t calculated = crc32(buf, len - sizeof(uint32_t)); uint32_t calculated = crc32(buf, len - sizeof(uint32_t));
return expected == calculated; 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. * cloud your output unnecessarily. Again, we can use FRIDA to patch it out.
*/ */
void some_boring_bug(char c) { void some_boring_bug(char c) {
switch (c) { switch (c) {
case 'A'...'Z':
case 'a'...'z': case 'A' ... 'Z':
case 'a' ... 'z':
__builtin_trap(); __builtin_trap();
break; break;
} }
} }
extern void some_boring_bug2(char c); extern void some_boring_bug2(char c);
__asm__ ( __asm__(
".text \n" ".text \n"
"some_boring_bug2: \n" "some_boring_bug2: \n"
".global some_boring_bug2 \n" ".global some_boring_bug2 \n"
".type some_boring_bug2, @function \n" ".type some_boring_bug2, @function \n"
"mov %edi, %eax \n" "mov %edi, %eax \n"
"cmp $0xb4, %al \n" "cmp $0xb4, %al \n"
"jne ok \n" "jne ok \n"
"ud2 \n" "ud2 \n"
"ok: \n" "ok: \n"
"ret \n"); "ret \n");
void LLVMFuzzerTestOneInput(char *buf, int len) { void LLVMFuzzerTestOneInput(char *buf, int len) {
@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
some_boring_bug2(buf[0]); some_boring_bug2(buf[0]);
if (buf[0] == '0') { if (buf[0] == '0') {
printf("Looks like a zero to me!\n"); 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"); 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!"); printf("Oh we, weren't expecting that!");
__builtin_trap(); __builtin_trap();
}
else } else
printf("Neither one or zero? How quaint!\n"); printf("Neither one or zero? How quaint!\n");
} }
@ -145,7 +155,7 @@ int main(int argc, char **argv) {
int fd = -1; int fd = -1;
off_t len; off_t len;
char * buf = NULL; char *buf = NULL;
size_t n_read; size_t n_read;
int result = -1; int result = -1;
@ -173,5 +183,6 @@ int main(int argc, char **argv) {
printf("Done: %s: (%zd bytes)\n", argv[1], n_read); printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
return 0; return 0;
} }

View File

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

View File

@ -3,7 +3,6 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
if (Size < 1) return; 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) { TESTINSTR_SECTION int main(int argc, char **argv) {
char * file; char *file;
int fd = -1; int fd = -1;
off_t len; off_t len;
char * buf = NULL; char *buf = NULL;
size_t n_read; size_t n_read;
int result = -1; int result = -1;

View File

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

View File

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

View File

@ -48,7 +48,7 @@ all: $(TEST_BIN)
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN) CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
arm: 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): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
cd $(LIBZ_DIR) && \ cd $(LIBZ_DIR) && \
CFLAGS="$(CFLAGS) -fPIC" \ CFLAGS="$(CFLAGS) -fPIC" \
./configure \ ./configure \
--static \ --static
--archs="$(ARCH)"
$(LIBZ_LIB): | $(LIBZ_PC) $(LIBZ_LIB): | $(LIBZ_PC)
CFLAGS="$(CFLAGS) -fPIC" \ CFLAGS="$(CFLAGS) -fPIC" \
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
LDFLAGS="-L$(LIBZ_DIR)" \ LDFLAGS="-L$(LIBZ_DIR)" \
./configure \ ./configure \
--host="$(ARCH)" --host="$(PNG_ARCH)"
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE) $(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ 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) { TESTINSTR_SECTION int main(int argc, char **argv) {
char * file; char *file;
int fd = -1; int fd = -1;
off_t len; off_t len;
char * buf = NULL; char *buf = NULL;
size_t n_read; size_t n_read;
int result = -1; int result = -1;

View File

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

View File

@ -116,6 +116,10 @@
#include <TargetConditionals.h> #include <TargetConditionals.h>
#endif #endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#undef LIST_FOREACH /* clashes with FreeBSD */ #undef LIST_FOREACH /* clashes with FreeBSD */
#include "list.h" #include "list.h"
#ifndef SIMPLE_FILES #ifndef SIMPLE_FILES
@ -139,6 +143,10 @@
#define AFL_RAND_RETURN u32 #define AFL_RAND_RETURN u32
#endif #endif
#ifndef INTERESTING_32_LEN
#error INTERESTING_32_LEN not defined - BUG!
#endif
extern s8 interesting_8[INTERESTING_8_LEN]; extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN]; extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32 extern s32
@ -232,7 +240,6 @@ struct queue_entry {
custom, /* Marker for custom mutators */ custom, /* Marker for custom mutators */
stats_mutated; /* stats: # of mutations performed */ stats_mutated; /* stats: # of mutations performed */
u8 *trace_mini; /* Trace bytes, if kept */
u32 tc_ref; /* Trace bytes ref count */ u32 tc_ref; /* Trace bytes ref count */
#ifdef INTROSPECTION #ifdef INTROSPECTION
@ -242,13 +249,11 @@ struct queue_entry {
double perf_score, /* performance score */ double perf_score, /* performance score */
weight; weight;
u8 *testcase_buf; /* The testcase buffer, if loaded. */ struct queue_entry *mother; /* queue entry this based on */
u8 *trace_mini; /* Trace bytes, if kept */
u8 *cmplog_colorinput; /* the result buf of colorization */ u8 *testcase_buf; /* The testcase buffer, if loaded. */
struct tainted *taint; /* Taint information from CmpLog */ 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 skipdet_entry *skipdet_e; struct skipdet_entry *skipdet_e;
}; };
@ -444,15 +449,17 @@ extern char *power_names[POWER_SCHEDULES_NUM];
typedef struct afl_env_vars { typedef struct afl_env_vars {
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check, 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_dumb_forksrv, afl_import_first, afl_custom_mutator_only,
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, 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_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
afl_no_startup_calibration, afl_no_warn_instability, afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems; afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames, afl_no_sync, afl_no_fastresume;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -651,6 +658,7 @@ typedef struct afl_state {
switch_fuzz_mode, /* auto or fixed fuzz mode */ switch_fuzz_mode, /* auto or fixed fuzz mode */
calibration_time_us, /* Time spend on calibration */ calibration_time_us, /* Time spend on calibration */
sync_time_us, /* Time spend on sync */ sync_time_us, /* Time spend on sync */
cmplog_time_us, /* Time spend on cmplog */
trim_time_us; /* Time spend on trimming */ trim_time_us; /* Time spend on trimming */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
@ -1221,6 +1229,7 @@ void show_init_stats(afl_state_t *);
void update_calibration_time(afl_state_t *afl, u64 *time); void update_calibration_time(afl_state_t *afl, u64 *time);
void update_trim_time(afl_state_t *afl, u64 *time); void update_trim_time(afl_state_t *afl, u64 *time);
void update_sync_time(afl_state_t *afl, u64 *time); void update_sync_time(afl_state_t *afl, u64 *time);
void update_cmplog_time(afl_state_t *afl, u64 *time);
/* StatsD */ /* StatsD */
@ -1271,6 +1280,7 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *); void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *); void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *); void check_binary(afl_state_t *, u8 *);
u64 get_binary_hash(u8 *fn);
void check_if_tty(afl_state_t *); void check_if_tty(afl_state_t *);
void save_cmdline(afl_state_t *, u32, char **); void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int); void read_foreign_testcases(afl_state_t *, int);
@ -1404,6 +1414,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem); void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
char *sha1_hex(const u8 *data, size_t len);
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
char *sha1_hex_for_file(const char *fname, u32 len);
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
* enabled. */
static inline int permissive_create(afl_state_t *afl, const char *fn) {
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) {
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
PFATAL("Unable to create '%s'", fn);
}
}
return fd;
}
#if TESTCASE_CACHE == 1 #if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1 #error define of TESTCASE_CACHE must be zero or larger than 1
#endif #endif

View File

@ -33,6 +33,10 @@
#define MUT_STRATEGY_ARRAY_SIZE 256 #define MUT_STRATEGY_ARRAY_SIZE 256
#ifndef INTERESTING_32
#error INTERESTING_32 is not defined - BUG!
#endif
s8 interesting_8[] = {INTERESTING_8}; s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16}; s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32}; s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com> Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>
@ -53,21 +53,24 @@ struct cmp_header { // 16 bit = 2 bytes
struct cmp_operands { struct cmp_operands {
u64 v0; u64 v0;
u64 v1;
u64 v0_128; u64 v0_128;
u64 v0_256_0; // u256 is unsupported by any compiler for now, so future use
u64 v0_256_1;
u64 v1;
u64 v1_128; u64 v1_128;
u64 unused; u64 v1_256_0;
u8 unused1; u64 v1_256_1;
u8 unused2; u8 unused[8]; // 2 bits could be used for "is constant operand"
} __attribute__((packed)); } __attribute__((packed));
struct cmpfn_operands { struct cmpfn_operands {
u8 v0[32]; u8 v0[32];
u8 v0_len;
u8 v1[32]; u8 v1[32];
u8 v0_len;
u8 v1_len; u8 v1_len;
u8 unused[6]; // 2 bits could be used for "is constant operand"
} __attribute__((packed)); } __attribute__((packed));

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

View File

@ -26,7 +26,7 @@
/* Version string: */ /* Version string: */
// c = release, a = volatile github dev, e = experimental branch // c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.20c" #define VERSION "++4.30c"
/****************************************************** /******************************************************
* * * *
@ -324,9 +324,9 @@
#define SYNC_INTERVAL 8 #define SYNC_INTERVAL 8
/* Sync time (minimum time between syncing in ms, time is halfed for -M main /* Sync time (minimum time between syncing in ms, time is halfed for -M main
nodes) - default is 30 minutes: */ nodes) - default is 20 minutes: */
#define SYNC_TIME (30 * 60 * 1000) #define SYNC_TIME (20 * 60 * 1000)
/* Output directory reuse grace period (minutes): */ /* Output directory reuse grace period (minutes): */
@ -464,7 +464,7 @@
/* Do not change this unless you really know what you are doing. */ /* Do not change this unless you really know what you are doing. */
#define MAP_SIZE (1U << MAP_SIZE_POW2) #define MAP_SIZE (1U << MAP_SIZE_POW2)
#if MAP_SIZE <= 65536 #if MAP_SIZE <= 2097152
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152 #define MAP_INITIAL_SIZE (2 << 20) // = 2097152
#else #else
#define MAP_INITIAL_SIZE MAP_SIZE #define MAP_INITIAL_SIZE MAP_SIZE

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>
@ -314,8 +314,8 @@ static inline const char *colorfilter(const char *x) {
#define FATAL(x...) \ #define FATAL(x...) \
do { \ do { \
\ \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \ "\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \ SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, (u32)__LINE__); \ __FILE__, (u32)__LINE__); \
exit(1); \ exit(1); \
@ -327,8 +327,8 @@ static inline const char *colorfilter(const char *x) {
#define ABORT(x...) \ #define ABORT(x...) \
do { \ do { \
\ \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \ "\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, (u32)__LINE__); \ __FILE__, (u32)__LINE__); \
abort(); \ abort(); \
@ -341,8 +341,8 @@ static inline const char *colorfilter(const char *x) {
do { \ do { \
\ \
fflush(stdout); \ fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \ "\n[-] SYSTEM ERROR : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
__FILE__, (u32)__LINE__); \ __FILE__, (u32)__LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \

View File

@ -20,26 +20,28 @@ static char *afl_environment_variables[] = {
"AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE", "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER", "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_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME", "AFL_CMPLOG_DEBUG", "AFL_CTX_K", "AFL_LLVM_DONTWRITEID", "AFL_PC_FILTER",
"AFL_PC_FILTER_FILE", "AFL_CODE_END", "AFL_CODE_START",
"AFL_COMPCOV_BINNAME", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_MUTATOR_LATE_SEND",
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", "AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", "AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", "AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", "AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", "AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", "AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE", "AFL_FRIDA_INST_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_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
"AFL_FRIDA_INST_NO_SUPPRESS" "AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE", "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_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE",
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR", "AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR",
@ -48,12 +50,12 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", "AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH", "AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE", "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_ARGS", // oss-fuzz
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST", "AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE", "AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_DISABLE_VERSION_CHECK",
"AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO", "AFL_GCJ", "AFL_GCC_INSTRUMENT_FILE", "AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO",
"AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", "AFL_GCJ", "AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS",
"AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS", "AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS",
"AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST",
@ -80,14 +82,13 @@ static char *afl_environment_variables[] = {
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
"AFL_LLVM_LTO_SKIPINIT" "AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
"AFL_LLVM_LTO_STARTID", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
#if defined USE_COLOR && !defined ALWAYS_COLORED #if defined USE_COLOR && !defined ALWAYS_COLORED
"AFL_NO_COLOR", "AFL_NO_COLOUR", "AFL_NO_COLOR", "AFL_NO_COLOUR",
#endif #endif
"AFL_NO_CPU_RED", "AFL_NO_CPU_RED", "AFL_NO_SYNC",
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option "AFL_NO_CFG_FUZZING", // afl.rs rust crate option
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY", "AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
@ -107,15 +108,16 @@ static char *afl_environment_variables[] = {
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
"AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
"AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
"AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
"AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_USE_UBSAN", "AFL_UBSAN_VERBOSE", "AFL_USE_TSAN", "AFL_USE_CFISAN",
"AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN", "AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL
}; };

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com> Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>> Dominik Maier <mail@dmnk.co>>
@ -89,11 +89,14 @@ typedef struct {
bool (*nyx_config_set_aux_buffer_size)(void *config, bool (*nyx_config_set_aux_buffer_size)(void *config,
uint32_t aux_buffer_size); uint32_t aux_buffer_size);
uint64_t (*nyx_get_target_hash64)(void *config);
void (*nyx_config_free)(void *config);
} nyx_plugin_handler_t; } nyx_plugin_handler_t;
/* Imports helper functions to enable Nyx mode (Linux only )*/ /* Imports helper functions to enable Nyx mode (Linux only )*/
nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary); nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
#endif #endif
typedef struct afl_forkserver { typedef struct afl_forkserver {
@ -188,6 +191,8 @@ typedef struct afl_forkserver {
u8 persistent_mode; u8 persistent_mode;
u32 max_length;
#ifdef __linux__ #ifdef __linux__
nyx_plugin_handler_t *nyx_handlers; nyx_plugin_handler_t *nyx_handlers;
char *out_dir_path; /* path to the output directory */ char *out_dir_path; /* path to the output directory */
@ -202,8 +207,18 @@ typedef struct afl_forkserver {
bool nyx_use_tmp_workdir; bool nyx_use_tmp_workdir;
char *nyx_tmp_workdir_path; char *nyx_tmp_workdir_path;
s32 nyx_log_fd; s32 nyx_log_fd;
u64 nyx_target_hash64;
#endif #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; } afl_forkserver_t;
typedef enum fsrv_run_result { typedef enum fsrv_run_result {
@ -230,6 +245,10 @@ void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv); void afl_fsrv_deinit(afl_forkserver_t *fsrv);
void afl_fsrv_kill(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__ #ifdef __APPLE__
#define MSG_FORK_ON_APPLE \ #define MSG_FORK_ON_APPLE \
" - On MacOS X, the semantics of fork() syscalls are non-standard and " \ " - On MacOS X, the semantics of fork() syscalls are non-standard and " \

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com> Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com> Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>, Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co> Dominik Maier <mail@dmnk.co>

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