Compare commits

...

226 Commits

Author SHA1 Message Date
9cac7ced05 Merge pull request #2294 from AFLplusplus/dev
push to stable
2025-02-10 13:42:28 +01:00
ecaddc09e8 code format 2025-02-10 13:29:22 +01:00
287edf2754 v4.31c release 2025-02-10 13:22:37 +01:00
7765d4ac33 Fix various spelling errors (#2293)
* Fix spelling errors in log messages

* Fix doc comment syntax

* Fix spelling errors in Markdown documentation

* Fix spelling errors in comments
2025-02-10 00:32:42 +01:00
6a4b5807b6 Merge pull request #2288 from wtdcode/upstream
[RFC] Upstream "SAND: Decoupling Sanitization from Fuzzing for Low Overhead"
2025-01-27 16:39:37 +01:00
mio
72d248ae57 cmplog is working! 2025-01-27 19:41:33 +08:00
mio
c78643f566 Add an example 2025-01-27 19:37:21 +08:00
mio
0b53a5a8aa Fix typo 2025-01-27 19:30:52 +08:00
mio
80e1a95378 Remove the unused field 2025-01-27 19:24:46 +08:00
mio
5fa1a9c365 Add inline 2025-01-27 19:24:31 +08:00
mio
522da5e9b5 Update docs accordingly 2025-01-27 19:23:21 +08:00
mio
c7e919333e Update help usage of afl-fuzz 2025-01-26 18:40:37 +08:00
mio
c64813b7d5 Update more instructions 2025-01-26 15:52:29 +08:00
mio
b96047d7b0 Fix typo 2025-01-26 15:51:35 +08:00
mio
604cf2cf80 Use AFL hash32 2025-01-26 15:46:25 +08:00
mio
c7c66bd0d6 Fix plot_file header 2025-01-26 15:34:56 +08:00
mio
40991801bd Fix cmplog srv not deinit 2025-01-26 15:28:56 +08:00
mio
96dc77e410 Fix typos 2025-01-24 22:31:21 +08:00
mio
60b92dcef3 Fix incorrect docs 2025-01-24 22:25:15 +08:00
mio
12a88c52df Update docs 2025-01-24 22:24:10 +08:00
mio
be3c665eee Fix integration 2025-01-23 23:18:35 +08:00
mio
f905087e8e Remove var bytes makeups 2025-01-23 19:17:44 +08:00
mio
99cf15bd30 Fix building 2025-01-23 19:12:48 +08:00
mio
5c239d9207 nit with code formatt-ed 2025-01-23 19:11:45 +08:00
mio
c4d576b4e0 Add myself to contributor 2025-01-23 19:04:53 +08:00
mio
efa2120935 Update help 2025-01-20 00:09:32 +08:00
mio
967b81736d Fix pass 2025-01-19 23:55:44 +08:00
mio
f4346e423d No AFL_SAN_RECOVER 2025-01-19 23:53:03 +08:00
mio
a60003e3cf Fix 2025-01-19 23:51:44 +08:00
mio
1c9925c7d7 Initial integration 2025-01-19 23:49:52 +08:00
635cd7374e fix unicorn test 2025-01-16 15:48:04 +01:00
fb52b8edf8 Merge pull request #2287 from AFLplusplus/dev
push to stable
2025-01-16 15:34:48 +01:00
30861b5d54 llvm 20 support 2025-01-16 15:32:58 +01:00
b2a01936c3 do not auto-enable splicing 2025-01-16 14:07:41 +01:00
8dbfcde798 Merge pull request #2286 from AFLplusplus/dev
push to stable
2025-01-13 14:08:30 +01:00
7ad694716b no splicing is the new default 2025-01-13 11:57:19 +01:00
e93ab23823 python 3.13+ support 2025-01-13 11:38:38 +01:00
79a24685b2 update unicorn mode 2025-01-06 20:26:32 +01:00
cad7536036 Mutation Chain Tool (#2281)
* Mutation Chain Tool

* Address comments domenukk

* Address comments domenukk 2
2025-01-05 12:35:50 +01:00
1ddfb1fec2 Merge pull request #2282 from vnc0/stable
Enhance compatibility in update_frida_version.sh
2025-01-03 11:28:09 +01:00
ae8df744ee Merge branch 'AFLplusplus:stable' into stable 2024-12-30 01:09:48 +01:00
aaaa96af6d Merge pull request #2280 from GAP-dev/dev
Fix macOS env optimization
2024-12-28 15:46:29 +01:00
2e2a3a2718 Fix macOS env optimization 2024-12-26 17:46:10 +09:00
eee4be90c1 Merge pull request #2279 from jschwartzentruber/upd-filter-docs
update dynamic covfilter readme
2024-12-24 21:12:25 +01:00
5fe21c3797 update dynamic covfilter readme 2024-12-24 10:49:33 -05:00
4eaacfb095 Merge pull request #2278 from AFLplusplus/dev
Push to stable
2024-12-24 14:08:20 +01:00
82b0cf0540 Fix fuzz targets killing on exit (#2277) 2024-12-24 11:11:10 +01:00
5a352adb19 Merge pull request #2276 from martinus/dev
Fix overflow in execs_ps_last_min calculation
2024-12-19 10:34:54 +01:00
9afba51ec1 renamed last_avg_execs -> last_avg_total_execs
This should make it a bit more clear that it stores the total number of executions from the previous update
2024-12-19 07:59:45 +01:00
99402aa31c Fix overflow in execs_ps_last_min calculation
last_avg_execs should be 64bit, same as total_execs, otherwise there is an overflow once total_execs reaches 2^32. Which can happen in practice for long-running fuzzing campaigns.
2024-12-19 07:56:15 +01:00
af11b80fda Enhance compatibility in update_frida_version.sh
Modify sed command to support FreeBSD and macOS
2024-12-18 17:50:55 +01:00
10db3a35cf Merge pull request #2274 from AFLplusplus/dev
Dev
2024-12-17 19:18:52 +01:00
af44b07b31 Merge pull request #2273 from vnc0/stable
Fix macro syntax error in config.h
2024-12-17 19:18:12 +01:00
9b433e2d8c Fix macro syntax error in config.h 2024-12-17 17:55:29 +01:00
85e14cf8d1 Merge pull request #2272 from AFLplusplus/dev
fix gcc plugin test
2024-12-15 18:07:00 +01:00
f2f417325f fix gcc plugin test 2024-12-15 18:06:02 +01:00
3e18b1a10c Merge pull request #2270 from AFLplusplus/dev
fix map size difference bug
2024-12-14 08:17:46 +01:00
1d3e885441 fix map size difference bug 2024-12-13 18:59:26 +01:00
0c69d0a0d8 Merge pull request #2269 from AFLplusplus/dev
push to stable
2024-12-13 12:28:39 +01:00
bbffece7d7 nit 2024-12-13 11:27:26 +01:00
2956b9cc4c support LLVMFuzzerTestOneInput archive targets 2024-12-13 11:05:17 +01:00
9160805f4a add __sanitizer_weak_hook_ support 2024-12-12 15:26:39 +01:00
50e2f9d46c loose file and shared memory permissions on Android and iPhone 2024-12-11 10:36:31 +01:00
223b14134c Merge pull request #2265 from AFLplusplus/dev
push to stable
2024-12-04 11:14:01 +01:00
f5a672f9d8 update makefile for llvm 2024-12-04 08:45:54 +01:00
9ce45665d7 Merge pull request #2264 from exoosh/bump-llvm-version-to-20
Bump LLVM version to 20 available in prerelease, 19 being latest stable
2024-12-04 08:43:12 +01:00
10883b1392 Bumping the upper version boundary for LLVM to 20, which is currently available in prerelease, 19 being latest stable 2024-12-03 15:57:50 +00:00
d206d5fc46 v4.31a 2024-12-03 15:53:01 +01:00
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
19ca7b3761 Merge pull request #2158 from AFLplusplus/dev
push to stable
2024-07-14 11:23:51 +02:00
179 changed files with 2817 additions and 2589 deletions

View File

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

View File

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

3
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

@ -28,11 +28,11 @@ MAN_PATH ?= $(PREFIX)/share/man/man8
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
VERSION = $(shell grep '^ *$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
SYS = $(shell uname -s)
override LLVM_TOO_NEW_DEFAULT := 18
override LLVM_TOO_NEW_DEFAULT := 19
override LLVM_TOO_OLD_DEFAULT := 13
ifeq "$(SYS)" "OpenBSD"
@ -48,31 +48,37 @@ else
LLVM_CONFIG ?= $(call detect_newest,llvm-config)
endif
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
ifneq "$(LLVM_CONFIG)" ""
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
endif
ifneq "$(LLVMVER)" ""
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
endif
LLVM_STDCXX := gnu++11
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
LLVM_LTO := 0
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-8]\.' && echo 1 || echo 0)
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.|^2[1-9]\.' && 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))))
# $(foreach var,_CLANG_VERSIONS_TO_TEST LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
ifeq "$(LLVMVER)" ""
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
endif
ifeq "$(LLVM_UNSUPPORTED)" "1"
$(error llvm_mode only supports llvm from version 3.8 onwards)
$(error llvm_mode only supports llvm from version 3.8 onwards - or your version is too new. Upgrade AFL++ if possible or downgrade LLVM.)
endif
ifeq "$(LLVM_TOO_NEW)" "1"
@ -112,10 +118,6 @@ ifeq "$(LLVM_LTO)" "0"
$(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.)
endif
ifeq "$(LLVM_APPLE_XCODE)" "1"
$(warning llvm_mode will not compile with Xcode clang...)
endif
# We were using llvm-config --bindir to get the location of clang, but
# this seems to be busted on some distros, so using the one in $PATH is
# probably better.
@ -123,6 +125,11 @@ endif
CC = $(LLVM_BINDIR)/clang
CXX = $(LLVM_BINDIR)/clang++
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
ifeq "$(LLVM_APPLE_XCODE)" "1"
$(warning llvm_mode will not compile with Xcode clang...)
endif
# llvm-config --bindir may not providing a valid path, so ...
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
# however we must ensure that this is not a "CC=gcc make"
@ -156,7 +163,7 @@ endif
# sanity check.
# Are versions of clang --version and llvm-config --version equal?
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
# I disable this because it does not make sense with what we did before (marc)
# We did exactly set these 26 lines above with these values, and it would break
@ -320,7 +327,7 @@ endif
# User teor2345 reports that this is required to make things work on MacOS X.
ifeq "$(SYS)" "Darwin"
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
CLANG_LFL += -Wl,-undefined,dynamic_lookup
override LLVM_HAVE_LTO := 0
override LLVM_LTO := 0
else
@ -328,7 +335,7 @@ else
endif
ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
CLANG_LFL += $(LLVM_LIBDIR)/libLLVM.so
CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline
# Needed for unwind symbols
@ -501,7 +508,7 @@ document:
.PHONY: test_build
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr

View File

@ -1,10 +1,10 @@
# American Fuzzy Lop plus plus (AFL++)
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.22a
GitHub version: 4.31c
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -230,6 +230,7 @@ Thank you! (For people sending pull requests - please add yourself to this list
Ruben ten Hove Joey Jiao
fuzzah @intrigus-lgtm
Yaakov Saxon Sergej Schumilo
Ziqiao Kong
```
</details>

View File

@ -2,6 +2,7 @@
## Must
- afl_fsrv_deinit cmplog
- ijon support?
- check for null ptr for xml/curl/g_ string transform functions
- hardened_usercopy=0 page_alloc.shuffle=0

View File

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

View File

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

View File

@ -1,4 +1,4 @@
# custum mutator: AFL++
# custom mutator: AFL++
this is the AFL++ havoc mutator as a custom mutator module for AFL++.

View File

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

View File

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

View File

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

View File

@ -409,7 +409,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size,
} else {
// new_size fits into buf, so re-use it
// new_size fits into buf, so reuse it
*out_buf = buf;
}

View File

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

View File

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

View File

@ -0,0 +1,12 @@
# Autotokens standalone mutator
this is a standalone version of the AFL++ autotokens custom mutator.
just type `make` to build.
You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer!
```
autotokens-standalone -h # to see all parameters
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

@ -304,7 +304,7 @@ class XmlMutatorMin:
# Log something
if self.verbose:
print("Reseting tag #%i '%s'" % (rand_elem_id, rand_elem.tag))
print("Resetting tag #%i '%s'" % (rand_elem_id, rand_elem.tag))
# Reset the node
rand_elem.clear()

View File

@ -80,12 +80,12 @@ def fuzz(buf, add_buf, max_size):
via_buffer = False
log("fuzz(): Can't initialize mutator with AFL buffer")
# If init from AFL buffer wasn't succesful
# If init from AFL buffer wasn't successful
if not via_buffer:
log("fuzz(): Returning unmodified AFL buffer")
return buf
# Sucessful initialization -> mutate
# Successful initialization -> mutate
try:
__mutator__.mutate(max=5)
log("fuzz(): Input mutated")

View File

@ -143,7 +143,7 @@ test -e json-c/.libs/libjson-c.a || {
echo
echo
echo "[+] Json-c successfully prepared!"
echo "[+] Builing gramatron now."
echo "[+] Building gramatron now."
$CC -O3 -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o gramatron.so -shared -I. -I/prg/dev/include gramfuzz.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c ../../src/afl-performance.o json-c/.libs/libjson-c.a || exit 1
echo
echo "[+] gramatron successfully built!"

View File

@ -1,4 +1,4 @@
# custum mutator: honggfuzz mangle
# custom mutator: honggfuzz mangle
this is the honggfuzz mutator in mangle.c as a custom mutator
module for AFL++. It is the original mangle.c, mangle.h and honggfuzz.h

View File

@ -850,7 +850,7 @@ static void mangle_ASCIINumChange(run_t *run, bool printable) {
size_t len = 0;
uint64_t val = 0;
/* 20 is maximum lenght of a string representing a 64-bit unsigned value */
/* 20 is maximum length of a string representing a 64-bit unsigned value */
for (len = 0; (len < 20) && (len < left); len++) {
char c = run->dynfile->data[off + len];

View File

@ -40,7 +40,7 @@ bool BlockCoverage::AppendCoverage(const std::string &S) {
// Coverage lines have this form:
// CN X Y Z T
// where N is the number of the function, T is the total number of instrumented
// BBs, and X,Y,Z, if present, are the indecies of covered BB.
// BBs, and X,Y,Z, if present, are the indices of covered BB.
// BB #0, which is the entry block, is not explicitly listed.
bool BlockCoverage::AppendCoverage(std::istream &IN) {

View File

@ -106,7 +106,7 @@ private:
};
// Parses one dictionary entry.
// If successful, write the enty to Unit and returns true,
// If successful, write the entry to Unit and returns true,
// otherwise returns false.
bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
// Parses the dictionary file, fills Units, returns true iff all lines

View File

@ -427,7 +427,7 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options,
Env.RunOneMergeJob(Job.get());
// Continue if our crash is one of the ignorred ones.
// Continue if our crash is one of the ignored ones.
if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode)
Env.NumTimeouts++;
else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode)

View File

@ -452,7 +452,7 @@ void CrashResistantMerge(const Vector<std::string> &Args,
auto ExitCode = ExecuteCommand(Cmd);
if (!ExitCode) {
VPrintf(V, "MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt);
VPrintf(V, "MERGE-OUTER: succesful in %zd attempt(s)\n", Attempt);
break;
}

View File

@ -498,9 +498,9 @@ size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
T Add = Rand(21);
Add -= 10;
if (Rand.RandBool())
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endianness.
else
Val = Val + Add; // Add assuming current endiannes.
Val = Val + Add; // Add assuming current endianness.
if (Add == 0 || Rand.RandBool()) // Maybe negate.
Val = -Val;

View File

@ -460,7 +460,7 @@ static size_t InternalStrnlen(const char *S, size_t MaxLen) {
}
// Finds min of (strlen(S1), strlen(S2)).
// Needed bacause one of these strings may actually be non-zero terminated.
// Needed because one of these strings may actually be non-zero terminated.
static size_t InternalStrnlen2(const char *S1, const char *S2) {
size_t Len = 0;

View File

@ -1,4 +1,4 @@
# custum mutator: libfuzzer LLVMFuzzerMutate()
# custom mutator: libfuzzer LLVMFuzzerMutate()
This uses the libfuzzer LLVMFuzzerMutate() function in llvm 12.

View File

@ -2,7 +2,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
all: radamsa-mutator.so
# These can be overriden:
# These can be overridden:
CFLAGS ?= $(CFLAGS_FLTO)
# These are required: (otherwise radamsa gets very very slooooow)

View File

@ -1,4 +1,4 @@
# custum mutator: libradamsa
# custom mutator: libradamsa
Pretranslated radamsa library. This code belongs to the radamsa author.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
nightly

View File

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

View File

@ -1,4 +1,4 @@
# custum mutator: symcc
# custom mutator: symcc
This uses the symcc to find new paths into the target.

View File

@ -1,4 +1,4 @@
# custum mutator: symqemu
# custom mutator: symqemu
This uses the symcc to find new paths into the target.

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\""

View File

@ -3,7 +3,28 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.22a (dev)
### Version ++4.31c (release)
- SAND mode added (docs/SAND.md) for more effecient fuzzing with sanitizers
(thanks to @wtdcode !)
- afl-fuzz:
- splicing phase is now DISABLED by default because research showed
it is counterproductive. New command line parameter `-u` to enable
it. Splicing is auto-enabled if two cycles without finds happen.
- Python 3.13+ support
- loose file and shared memory permissions on Android and iPhone
- afl-cc:
- LLVM 20 support (again - please don't change the API all the time ...)
- -fsanitize=fuzzer now inserts libAFLDriver.a addtionally early to help
compiling if LLVMFuzzerTestOneOnput is in an .a archive
- added __sanitizer_weak_hook_* functions (in case that is helpful in
weird setups)
- fix bug with large map sizes when multiple libraries are loaded after
the shared memory was obtained.
### 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
@ -13,6 +34,11 @@
- 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
@ -21,13 +47,26 @@
- 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

View File

@ -106,7 +106,7 @@ If you find an interesting or important question missing, submit it via
<details>
<summary id="should-you-ever-stop-afl-fuzz-minimize-the-corpus-and-restart">Should you ever stop afl-fuzz, minimize the corpus and restart?</summary><p>
To stop afl-fuzz, minimize it's corpus and restart you would usually do:
To stop afl-fuzz, minimize its corpus and restart you would usually do:
```
Control-C # to terminate afl-fuzz
@ -274,7 +274,7 @@ If you find an interesting or important question missing, submit it via
the existing map will be used also for the newly loaded libraries, which
allows it to work, however, the efficiency of the fuzzing will be partially
degraded. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to
additionally tell AFL++ to ignore any coverage from the late loaded libaries.
additionally tell AFL++ to ignore any coverage from the late loaded libraries.
</p></details>
<details>

View File

@ -30,6 +30,9 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
sudo apt-get install -y ninja-build # for QEMU mode
sudo apt-get install -y cpio libcapstone-dev # for Nyx mode
sudo apt-get install -y wget curl # for Frida mode
sudo apt-get install -y python3-pip # for Unicorn mode
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
@ -87,7 +90,6 @@ These build options exist:
* PROFILING - compile afl-fuzz with profiling information
* INTROSPECTION - compile afl-fuzz with mutation introspection
* NO_PYTHON - disable python support
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
* NO_UTF - do not use UTF-8 for line rendering in status screen (fallback to G1 box drawing, of vanilla AFL)
* NO_NYX - disable building nyx mode dependencies
* NO_CORESIGHT - disable building coresight (arm64 only)

81
docs/SAND.md Normal file
View File

@ -0,0 +1,81 @@
# SAND: Decoupling Sanitization from Fuzzing for Low Overhead
- Authors: Ziqiao Kong, Shaohua Li, Heqing Huang, Zhendong Su
- Maintainer: [Ziqiao Kong](https://github.com/wtdcode)
- Preprint: [arXiv](https://arxiv.org/abs/2402.16497), accepted by ICSE 2025
- Main repo (for paper, reproduction, reference or cite): https://github.com/wtdcode/sand-aflpp
## Motivation
SAND introduces a new fuzzing workflow that can greatly reduce (or even eliminate) sanitizer overhead and combine different sanitizers in one fuzzing campaign.
The key point of SAND is that: sanitizing all inputs is wasting fuzzing power, because bug-triggering inputs are extremely rare (~1%). Obviously, not all inputs worth going through sanitizers. Therefore, if we can somehow "predict" if an input could trigger bugs (defined as "execution pattern"), we could greatly save fuzzing power by only sanitizing a small proportion of all inputs. That's exactly how SAND works.
## Usage
For a normal fuzzing workflow, we have:
1. Build target project with AFL_USE_ASAN=1 to get `target_asan`
2. Fuzz the target with `afl-fuzz -i seeds -o out -- ./target_asan`
For SAND fuzzing workflow, this is slightly different:
1. Build target project _without_ any sanitizers to get `target_native`, which we will define as a "native binary". It is usually done by using `afl-clang-fast/lto(++)` to compile your project _without_ `AFL_USE_ASAN/UBSAN/MSAN`.
2. Build target project with AFL_USE_ASAN=1 AFL_SAN_NO_INST=1 to get `target_asan`. Do note this step can be repeated for multiple sanitizers, like MSAN, UBSAN etc. It is also possible to have ASAN and UBSAN to build together.
3. Fuzz the target with `afl-fuzz -i seeds -o out -w ./target_asan -- ./target_native`. Note `-w` can be specified multiple times.
Then you get:
- almost the same performance as `afl-fuzz -i seeds -o out -- ./target_native`
- and the same bug-finding capability as `afl-fuzz -i seeds -o out -- ./target_asan`
## Example Workflow
Take [test-instr.c](../test-instr.c) as an example.
1. Build the native binary
```bash
afl-clang-fast test-instr.c -o ./native
```
Just like the normal building process, except using `afl-clang-fast`
2. Build the sanitizers-enabled binaries.
```bash
AFL_SAN_NO_INST=1 AFL_USE_UBSAN=1 AFL_USE_ASAN=1 afl-clang-fast test-instr.c -o ./asanubsan
AFL_SAN_NO_INST=1 AFL_USE_MSAN=1 afl-clang-fast test-instr.c -o ./msan
```
Do note `AFL_SAN_NO_INST=1` is crucial, this enables forkservers but disables pc instrumentation. Do not reuse sanitizers-enabled binaries built _without_ `AFL_SAN_NO_INST=1`. This will mess up SAND execution pattern.
3. Start fuzzing
```bash
mkdir /tmp/test
echo "a" > /tmp/test/a
AFL_NO_UI=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -i /tmp/test -o /tmp/out -w ./asanubsan -w ./msan -- ./native @@
```
That's it!
## Tips
### Alternative execution patterns
By default, SAND uses the hash value of the simplified coverage map as execution pattern, i.e. if an input has a unique simplefied coverage map, it will be sent to sanitizers for inspection. This shall work for most cases. However, if you are strongly worried about missing bugs, try `AFL_SAN_ABSTRACTION=unique_trace afl-fuzz ...`, which filters inputs having a _unique coverage map_. Do note this significantly increases the number of inputs by 4-10 times, leading to much lower throughput. Alternatively, SAND also supports `AFL_SAN_ABSTRACTION=coverage_increase`, which essentially equals to running sanitizers on the corpus and thus having almost zero overhead, but at a cost of missing ~15% bugs in our evaluation.
### Run as many sanitizers as possible
Though we just used ASAN as an example, SAND works best if you provide more sanitizers, for example, UBSAN and MSAN.
You might do it via `afl-fuzz -i seeds -o out -w ./target_asan -w ./target_msan -w ./target_ubsan -- ./target_native`. Don't worry about the slow sanitizers like MSAN, SAND could still run very fast because only rather a few inputs are sanitized.
### Bugs types
The execution pattern evaluated in our papers is targeting the common bugs, as ASAN/MSAN/UBSAN catches. For other bug types, you probably need to define new execution patterns and re-evaluate.
### My throughput is greatly impacted
Generally, this is due to too many inputs going through sanitizers, for example, because of unstable targets. You could check stats from `plot_file` to confirm this. Try to switch execution patterns as stated above.

View File

@ -6,7 +6,7 @@ coverage to effortlessly pick up subtle, local-scale changes to program control
flow.
Note: If you are interested in a more current up-to-date deep dive how AFL++
works then we commend this blog post:
works then we recommend this blog post:
[https://blog.ritsec.club/posts/afl-under-hood/](https://blog.ritsec.club/posts/afl-under-hood/)
Simplifying a bit, the overall algorithm can be summed up as:

View File

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

View File

@ -151,7 +151,7 @@ def deinit(): # optional for Python
splicing - or anything else - and can also be ignored. If you are not
using this additional data then define `splice_optout` (see above).
This function is optional.
Returing a length of 0 is valid and is interpreted as skipping this
Returning a length of 0 is valid and is interpreted as skipping this
one mutation result.
For non-Python: the returned output buffer is under **your** memory
management!

View File

@ -24,7 +24,6 @@ To select the different instrumentation modes, use one of the following options:
- Use the `AFL_CC_COMPILER` environment variable with `MODE`. To select
`MODE`, use one of the following values:
- `GCC` (afl-gcc/afl-g++)
- `GCC_PLUGIN` (afl-g*-fast)
- `LLVM` (afl-clang-fast*)
- `LTO` (afl-clang-lto*).
@ -45,14 +44,10 @@ fairly broad use of environment variables instead:
make
```
- Setting `AFL_AS`, `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
compilation tools, rather than the default 'as', 'clang', or 'gcc' binaries
- Setting `AFL_CC`, and `AFL_CXX` lets you use alternate downstream
compilation tools, rather than the default 'clang', or 'gcc' binaries
in your `$PATH`.
- If you are a weird person that wants to compile and instrument asm text
files, then use the `AFL_AS_FORCE_INSTRUMENT` variable:
`AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo`
- Most AFL tools do not print any output if stdout/stderr are redirected. If
you want to get the output into a file, then set the `AFL_DEBUG` environment
variable. This is sadly necessary for various build processes which fail
@ -64,6 +59,9 @@ fairly broad use of environment variables instead:
optimizations, set `AFL_DONT_OPTIMIZE`. However, if `-O...` and/or
`-fno-unroll-loops` are set, these are not overridden.
- The optimization level can also be set with `AFL_OPT_LEVEL`, e.g.
`AFL_OPT_LEVEL=z` for `-Oz`, default is `3`
- Setting `AFL_HARDEN` automatically adds code hardening options when invoking
the downstream compiler. This currently includes `-D_FORTIFY_SOURCE=2` and
`-fstack-protector-all`. The setting is useful for catching non-crashing
@ -80,17 +78,13 @@ fairly broad use of environment variables instead:
Setting `AFL_INST_RATIO` to 0 is a valid choice. This will instrument only
the transitions between function entry points, but not individual branches.
Note that this is an outdated variable. A few instances (e.g., afl-gcc)
still support these, but state-of-the-art (e.g., LLVM LTO and LLVM PCGUARD)
do not need this.
Note that this is an outdated variable. Only LLVM CLASSIC pass can use this.
- `AFL_NO_BUILTIN` causes the compiler to generate code suitable for use with
libtokencap.so (but perhaps running a bit slower than without the flag).
- `AFL_PATH` can be used to point afl-gcc to an alternate location of afl-as.
One possible use of this is utils/clang_asm_normalize/, which lets you
instrument hand-written assembly when compiling clang code by plugging a
normalizer into the chain. (There is no equivalent feature for GCC.)
- `AFL_PATH` can be used to point a directory that contains LLVM/GCC plugins
for AFL++, AFL++'s runtime objects and QEMU/Frida support files.
- Setting `AFL_QUIET` will prevent afl-as and afl-cc banners from being
displayed during compilation, in case you find them distracting.
@ -101,6 +95,7 @@ fairly broad use of environment variables instead:
detection)
- `AFL_USE_CFISAN=1` - activates the Control Flow Integrity sanitizer (e.g.
type confusion vulnerabilities)
- `AFL_CFISAN_VERBOSE=1` - outputs detailed information when control flow integrity violations occur, instead of simply terminating with "Illegal Instruction"
- `AFL_USE_LSAN` - activates the leak sanitizer. To perform a leak check
within your program at a certain point (such as at the end of an
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
@ -111,6 +106,9 @@ fairly broad use of environment variables instead:
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
conditions
- `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer
- `AFL_UBSAN_VERBOSE=1` - outputs detailed diagnostic information when undefined behavior is detected, instead of simply terminating with "Illegal Instruction"
- Note: both `AFL_CFISAN_VERBOSE=1` and `AFL_UBSAN_VERBOSE=1` are disabled by default as verbose output can significantly slow down fuzzing performance. Use these options only during debugging or when additional crash diagnostics are required
- `TMPDIR` is used by afl-as for temporary files; if this variable is not set,
the tool defaults to /tmp.
@ -249,7 +247,7 @@ used if several separated instrumentations are performed which are then later
combined.
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
- `AFL_LLVM_LTO_CALLER` sets the maximum number of single block functions
to dig deeper into a real function. Default 0.
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
to which function. This helps to identify functions with variable bytes or
@ -323,6 +321,11 @@ mode.
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
for more information.
Setting `AFL_GCC_DISABLE_VERSION_CHECK=1` will disable the GCC plugin
version check if the target GCC plugin differs from the system-installed
version, resolving issues caused by version mismatches between GCC and
the plugin.
Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the
code with calls to an injected subroutine instead of the much more efficient
inline instrumentation.
@ -424,9 +427,8 @@ checks or alter some of the more exotic semantics of the tool:
types of automated jobs.
- `AFL_EXIT_WHEN_DONE` causes afl-fuzz to terminate when all existing paths
have been fuzzed and there were no new finds for a while. This would be
normally indicated by the cycle counter in the UI turning green. May be
convenient for some types of automated jobs.
have been fuzzed and there were no new finds for a while. This is basically
when the fuzzing state says `state: finished`
- Setting `AFL_EXPAND_HAVOC_NOW` will start in the extended havoc mode that
includes costly mutations. afl-fuzz automatically enables this mode when
@ -610,7 +612,7 @@ checks or alter some of the more exotic semantics of the tool:
see [rpc_statsd.md](rpc_statsd.md).
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes)
between fuzzing instances synchronization. Default sync time is 30 minutes,
between fuzzing instances synchronization. Default sync time is 20 minutes,
note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ is *VERY* important to carry out these basic steps first before taking on the
additional complexity of debugging with FRIDA mode or `afl-fuzz`.
- Run your harness outside of the fuzzer, passing it a representative seed as
it's input `./harness <input>`.
its input `./harness <input>`.
- Pass your harness multiple seeds to check that it is stable when running
multiple tests as it will when running in fork server mode `./harness <input1>
<intput2>`.

View File

@ -107,7 +107,7 @@ every block of code we execute, performance is critical.
However, the design of the binary instrumentation modes of AFL++ has moved on.
Both QEMU and FRIDA modes use a two stage process when executing a target
application. Each block is first compiled or instrumented, and then it is
executed. The compiled blocks can be re-used each time the target executes them.
executed. The compiled blocks can be reused each time the target executes them.
Since a blocks ID is based on its address, and this is known at compile time, we
only need to generate this ID once per block and so this ID generation no longer

View File

@ -200,10 +200,10 @@ instrumented address block translations.
* `AFL_FRIDA_INST_NO_SUPPRESS` - Disable deterministic branch suppression.
Deterministic branch suppression skips the preamble which generates coverage
information at the start of each block, if the block is reached by a
deterministic branch. This reduces map polution, and may improve performance
deterministic branch. This reduces map pollution, and may improve performance
when all the executing blocks have been prefetched and backpatching applied.
However, in the event that backpatching is incomplete, this may incur a
performance penatly as branch instructions are disassembled on each branch.
performance penalty as branch instructions are disassembled on each branch.
* `AFL_FRIDA_INST_SEED` - Sets the initial seed for the hash function used to
generate block (and hence edge) IDs. Setting this to a constant value may be
useful for debugging purposes, e.g., investigating unstable edges.
@ -215,7 +215,7 @@ instrumented address block translations.
coverage information for unstable edges (e.g., to be loaded within IDA
lighthouse).
* `AFL_FRIDA_JS_SCRIPT` - Set the script to be loaded by the FRIDA scripting
engine. See [Scipting.md](Scripting.md) for details.
engine. See [Scripting.md](Scripting.md) for details.
* `AFL_FRIDA_OUTPUT_STDOUT` - Redirect the standard output of the target
application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`).
* `AFL_FRIDA_OUTPUT_STDERR` - Redirect the standard error of the target

View File

@ -724,16 +724,16 @@ class Afl {
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to exclude several ranges.
*/
static addExcludedRange(addressess, size) {
Afl.jsApiAddExcludeRange(addressess, size);
static addExcludedRange(addresses, size) {
Afl.jsApiAddExcludeRange(addresses, size);
}
/**
* This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to include several ranges.
*/
static addIncludedRange(addressess, size) {
Afl.jsApiAddIncludeRange(addressess, size);
static addIncludedRange(addresses, size) {
Afl.jsApiAddIncludeRange(addresses, size);
}
/**
* This must always be called at the end of your script. This lets
@ -771,7 +771,7 @@ class Afl {
}
/**
* Print a message to the STDOUT. This should be preferred to
* FRIDA's `console.log` since FRIDA will queue it's log messages.
* FRIDA's `console.log` since FRIDA will queue its log messages.
* If `console.log` is used in a callback in particular, then there
* may no longer be a thread running to service this queue.
*/
@ -893,14 +893,14 @@ class Afl {
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
static setPersistentAddress(address) {
Afl.jsApiSetPersistentAddress(address);
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
* `number` should be provided as it's argument.
* `number` should be provided as its argument.
*/
static setPersistentCount(count) {
Afl.jsApiSetPersistentCount(count);
@ -920,7 +920,7 @@ class Afl {
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
static setPersistentReturn(address) {
Afl.jsApiSetPersistentReturn(address);

View File

@ -4,6 +4,6 @@ This folder contains a Docker image to allow the building of
`afl-frida-trace.so` using the `many-linux` docker image. This docker image is
based on CentOS Linux 5. By building `afl-frida-trace.so` for such an old
version of Linux, given the strong backward compatibility of Linux, this should
work on the majority of Linux environments. This may be useful for targetting
work on the majority of Linux environments. This may be useful for targeting
Linux distributions other than your development environment. `many-local` builds
`AFLplusplus` from the local working copy in the `many-linux` environment.

View File

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

View File

@ -166,7 +166,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
*/
if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
/* Check our addres/length don't wrap around */
/* Check our address/length don't wrap around */
if (SIZE_MAX - addr < size) { return false; }
GumAddress inner_base = addr;

View File

@ -186,7 +186,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
* execution), we instead ensure that we honour the additional
* instrumentation requested (e.g. coverage, asan and complog) when a block
* is compiled no matter where we are during initialization. We will end up
* re-using these blocks if the code under test calls a block which is also
* reusing these blocks if the code under test calls a block which is also
* used during initialization.
*
* Coverage data generated during initialization isn't a problem since the

View File

@ -285,7 +285,7 @@ static void instrument_coverage_switch(GumStalkerObserver *self,
/*
* If the branch is deterministic, then we should start execution at the
* begining of the block. From here, we will branch and skip the coverage
* beginning of the block. From here, we will branch and skip the coverage
* code and jump right to the target code of the instrumented block.
* Otherwise, if the branch is non-deterministic, then we need to branch
* part way into the block to where the coverage instrumentation starts.
@ -516,7 +516,7 @@ void instrument_coverage_optimize(const cs_insn *instr,
* an instruction to load x16,x17 from beyond the red-zone on the stack. A
* pair of registers are saved/restored because on AARCH64, the stack pointer
* must be 16 byte aligned. This instruction is emitted into the block before
* the tranformer (from which we are called) is executed. If is is possible
* the transformer (from which we are called) is executed. If is is possible
* for Stalker to make a direct branch (the target block is close enough), it
* can forego pushing the registers and instead branch at an offset into the
* block to skip this restoration prolog.

View File

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

View File

@ -5,16 +5,16 @@ class Afl {
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to exclude several ranges.
*/
static addExcludedRange(addressess, size) {
Afl.jsApiAddExcludeRange(addressess, size);
static addExcludedRange(addresses, size) {
Afl.jsApiAddExcludeRange(addresses, size);
}
/**
* This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to include several ranges.
*/
static addIncludedRange(addressess, size) {
Afl.jsApiAddIncludeRange(addressess, size);
static addIncludedRange(addresses, size) {
Afl.jsApiAddIncludeRange(addresses, size);
}
/**
* This must always be called at the end of your script. This lets
@ -52,7 +52,7 @@ class Afl {
}
/**
* Print a message to the STDOUT. This should be preferred to
* FRIDA's `console.log` since FRIDA will queue it's log messages.
* FRIDA's `console.log` since FRIDA will queue its log messages.
* If `console.log` is used in a callback in particular, then there
* may no longer be a thread running to service this queue.
*/
@ -205,14 +205,14 @@ class Afl {
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
static setPersistentAddress(address) {
Afl.jsApiSetPersistentAddress(address);
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
* `number` should be provided as it's argument.
* `number` should be provided as its argument.
*/
static setPersistentCount(count) {
Afl.jsApiSetPersistentCount(count);
@ -232,7 +232,7 @@ class Afl {
}
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
static setPersistentReturn(address) {
Afl.jsApiSetPersistentReturn(address);

View File

@ -37,7 +37,7 @@ static void convert_address_token(gchar *token, GumMemoryRange *range) {
if (token_count != 2) {
FFATAL("Invalid range (should have two addresses seperated by a '-'): %s\n",
FFATAL("Invalid range (should have two addresses separated by a '-'): %s\n",
token);
}

View File

@ -11,8 +11,8 @@ class Afl {
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to exclude several ranges.
*/
public static addExcludedRange(addressess: NativePointer, size: number): void {
Afl.jsApiAddExcludeRange(addressess, size);
public static addExcludedRange(addresses: NativePointer, size: number): void {
Afl.jsApiAddExcludeRange(addresses, size);
}
/**
@ -20,8 +20,8 @@ class Afl {
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to include several ranges.
*/
public static addIncludedRange(addressess: NativePointer, size: number): void {
Afl.jsApiAddIncludeRange(addressess, size);
public static addIncludedRange(addresses: NativePointer, size: number): void {
Afl.jsApiAddIncludeRange(addresses, size);
}
/**
@ -66,7 +66,7 @@ class Afl {
/**
* Print a message to the STDOUT. This should be preferred to
* FRIDA's `console.log` since FRIDA will queue it's log messages.
* FRIDA's `console.log` since FRIDA will queue its log messages.
* If `console.log` is used in a callback in particular, then there
* may no longer be a thread running to service this queue.
*/
@ -241,7 +241,7 @@ class Afl {
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
public static setPersistentAddress(address: NativePointer): void {
Afl.jsApiSetPersistentAddress(address);
@ -249,7 +249,7 @@ class Afl {
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
* `number` should be provided as it's argument.
* `number` should be provided as its argument.
*/
public static setPersistentCount(count: number): void {
Afl.jsApiSetPersistentCount(count);
@ -272,7 +272,7 @@ class Afl {
/**
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
* `NativePointer` should be provided as it's argument.
* `NativePointer` should be provided as its argument.
*/
public static setPersistentReturn(address: NativePointer): void {
Afl.jsApiSetPersistentReturn(address);

View File

@ -9,5 +9,11 @@ echo Newest available version: $NEW
test -z "$OLD" -o -z "$NEW" -o "$OLD" = "$NEW" && { echo Nothing to be done. ; exit 0 ; }
sed -i "s/=$OLD/=$NEW/" GNUmakefile || exit 1
# Determine the correct sed command
case $(sed --help 2>&1) in
*GNU*) set sed -i;;
*) set sed -i '';;
esac
"$@" "s/=$OLD/=$NEW/" GNUmakefile || exit 1
echo Successfully updated GNUmakefile

View File

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

View File

@ -75,6 +75,7 @@
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/types.h>
#include "asanfuzz.h"
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
defined(__NetBSD__) || defined(__DragonFly__)
@ -610,7 +611,11 @@ typedef struct afl_state {
u8 *var_bytes; /* Bytes that appear to be variable */
#define N_FUZZ_SIZE (1 << 21)
#define N_FUZZ_SIZE_BITMAP (1 << 29)
u32 *n_fuzz;
u8 *n_fuzz_dup;
u8 *classified_n_fuzz;
u8 *simplified_n_fuzz;
volatile u8 stop_soon, /* Ctrl-C pressed? */
clear_screen; /* Window resized? */
@ -728,6 +733,13 @@ typedef struct afl_state {
char *cmplog_binary;
afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */
/* ASAN Fuzing */
char *san_binary[MAX_EXTRA_SAN_BINARY];
afl_forkserver_t san_fsrvs[MAX_EXTRA_SAN_BINARY];
u8 san_binary_length; /* 0 means extra san binaries not given */
u32 san_case_status;
enum SanitizerAbstraction san_abstraction;
/* Custom mutators */
struct custom_mutator *mutator;
@ -747,7 +759,7 @@ typedef struct afl_state {
up to 256 */
unsigned long long int last_avg_exec_update;
u32 last_avg_execs;
u64 last_avg_total_execs;
double last_avg_execs_saved;
/* foreign sync */
@ -908,7 +920,7 @@ struct custom_mutator {
/**
* Opt-out of a splicing input for the fuzz mutator
*
* Empty dummy function. It's presence tells afl-fuzz not to pass a
* Empty dummy function. Its presence tells afl-fuzz not to pass a
* splice data pointer and len.
*
* @param data pointer returned in afl_custom_init by this custom mutator
@ -940,12 +952,12 @@ struct custom_mutator {
/**
* Describe the current testcase, generated by the last mutation.
* This will be called, for example, to give the written testcase a name
* after a crash ocurred. It can help to reproduce crashing mutations.
* after a crash occurred. It can help to reproduce crashing mutations.
*
* (Optional)
*
* @param data pointer returned by afl_customm_init for this custom mutator
* @paramp[in] max_description_len maximum size avaliable for the description.
* @paramp[in] max_description_len maximum size available for the description.
* A longer return string is legal, but will be truncated.
* @return A valid ptr to a 0-terminated string.
* An empty or NULL return will result in a default description
@ -1122,7 +1134,7 @@ struct custom_mutator {
void afl_state_init(afl_state_t *, uint32_t map_size);
void afl_state_deinit(afl_state_t *);
/* Set stop_soon flag on all childs, kill all childs */
/* Set stop_soon flag on all children, kill all children */
void afl_states_stop(void);
/* Set clear_screen flag on all states */
void afl_states_clear_screen(void);

54
include/asanfuzz.h Normal file
View File

@ -0,0 +1,54 @@
/*
american fuzzy lop++ - cmplog header
------------------------------------
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Dominik Maier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2023 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
Shared code to handle the shared memory. This is used by the fuzzer
as well the other components like afl-tmin, afl-showmap, etc...
*/
#ifndef _AFL_ASAMFUZZ_H
#define _AFL_ASAMFUZZ_H
#include "config.h"
// new_bits for describe_op
// new_bits value 1, 2 and 0x80 are already used!
#define SAN_CRASH_ONLY (1 << 4)
#define NON_COV_INCREASE_BUG (1 << 5)
enum SanitizerAbstraction {
SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the
// most sensitive
UNIQUE_TRACE,
COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the
// least sensitive
};
/* Execs the child */
struct afl_forkserver;
void sanfuzz_exec_child(struct afl_forkserver *fsrv, char **argv);
#endif

View File

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

View File

@ -76,8 +76,9 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname);
int parse_afl_kill_signal(u8 *numeric_signal_as_str, int default_signal);
/* Configure the signals that are used to kill the forkserver
and the forked childs. If `afl_kill_signal_env` or `afl_fsrv_kill_signal_env`
is NULL, the appropiate values are read from the environment. */
and the forked children. If `afl_kill_signal_env` or
`afl_fsrv_kill_signal_env` is NULL, the appropriate values are read from the
environment. */
void configure_afl_kill_signals(afl_forkserver_t *fsrv,
char *afl_kill_signal_env,
char *afl_fsrv_kill_signal_env,

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.22a"
#define VERSION "++4.31c"
/******************************************************
* *
@ -39,7 +39,7 @@
However if a target has problematic constructors and init arrays then
this can fail. Hence afl-fuzz deploys a larger default map. The largest
map seen so far is the xlsx fuzzer for libreoffice which is 5MB.
At runtime this value can be overriden via AFL_MAP_SIZE.
At runtime this value can be overridden via AFL_MAP_SIZE.
Default: 8MB (defined in bytes) */
#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024)
@ -52,6 +52,18 @@
/* Default file permission umode when creating files (default: 0600) */
#define DEFAULT_PERMISSION 0600
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_IOS
#undef DEFAULT_PERMISSION
#define DEFAULT_PERMISSION 0666
#endif
#endif
#ifdef __ANDROID__
#undef DEFAULT_PERMISSION
#define DEFAULT_PERMISSION 0666
#endif
/* SkipDet's global configuration */
#define MINIMAL_BLOCK_SIZE 64
@ -85,11 +97,17 @@
/* Maximum allowed fails per CMP value. Default: 96 */
#define CMPLOG_FAIL_MAX 96
/*
* Effective fuzzing with selective feeding inputs
*/
#define MAX_EXTRA_SAN_BINARY 4
/* -------------------------------------*/
/* Now non-cmplog configuration options */
/* -------------------------------------*/
/* If a persistent target keeps state and found crashes are not reproducable
/* If a persistent target keeps state and found crashes are not reproducible
then enable this option and set the AFL_PERSISTENT_RECORD env variable
to a number. These number of testcases prior and including the crash case
will be kept and written to the crash/ directory as RECORD:... files.
@ -492,6 +510,9 @@
#define CMPLOG_SHM_ENV_VAR "__AFL_CMPLOG_SHM_ID"
/* ASAN SHM ID */
#define AFL_ASAN_FUZZ_SHM_ENV_VAR "__AFL_ASAN_SHM_ID"
/* CPU Affinity lockfile env var */
#define CPU_AFFINITY_ENV_VAR "__AFL_LOCKFILE"
@ -523,7 +544,7 @@
#define AFL_TXT_MAX_LEN 65535
/* What is the minimum percentage of ascii characters present to be classifed
/* What is the minimum percentage of ascii characters present to be classified
as "is_ascii"? */
#define AFL_TXT_MIN_PERCENT 99

View File

@ -72,6 +72,22 @@ inline void classify_counts(afl_forkserver_t *fsrv) {
}
inline static void classify_counts_mem(u64 *mem, u32 size) {
u32 i = (size >> 3);
while (i--) {
/* Optimize for sparse bitmaps. */
if (unlikely(*mem)) { *mem = classify_word(*mem); }
mem++;
}
}
/* Updates the virgin bits, then reflects whether a new count or a new tuple is
* seen in ret. */
inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {

View File

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

View File

@ -20,20 +20,21 @@ static char *afl_environment_variables[] = {
"AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN",
"AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM",
"AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_CMPLOG_DEBUG", "AFL_CTX_K", "AFL_LLVM_DONTWRITEID", "AFL_PC_FILTER",
"AFL_PC_FILTER_FILE", "AFL_CODE_END", "AFL_CODE_START",
"AFL_COMPCOV_BINNAME", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_MUTATOR_LATE_SEND",
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
"AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
"AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
@ -49,12 +50,12 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE",
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER",
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER", "AFL_OPT_LEVEL",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
"AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO", "AFL_GCJ",
"AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_DISABLE_VERSION_CHECK",
"AFL_GCC_INSTRUMENT_FILE", "AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO",
"AFL_GCJ", "AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS",
"AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS",
"AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST",
@ -113,12 +114,11 @@ static char *afl_environment_variables[] = {
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE",
"AFL_NO_FASTRESUME", NULL
};
"AFL_USE_UBSAN", "AFL_UBSAN_VERBOSE", "AFL_USE_TSAN", "AFL_USE_CFISAN",
"AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME",
"AFL_SAN_ABSTRACTION", "AFL_SAN_NO_INST", "AFL_SAN_RECOVER", NULL};
extern char *afl_environment_variables[];

View File

@ -89,11 +89,14 @@ typedef struct {
bool (*nyx_config_set_aux_buffer_size)(void *config,
uint32_t aux_buffer_size);
uint64_t (*nyx_get_target_hash64)(void *config);
void (*nyx_config_free)(void *config);
} nyx_plugin_handler_t;
/* Imports helper functions to enable Nyx mode (Linux only )*/
nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
#endif
typedef struct afl_forkserver {
@ -156,6 +159,9 @@ typedef struct afl_forkserver {
bool debug; /* debug mode? */
u8 san_but_not_instrumented; /* Is it sanitizer enabled but not instrumented?
*/
bool uses_crash_exitcode; /* Custom crash exitcode specified? */
u8 crash_exitcode; /* The crash exitcode specified */
@ -164,6 +170,7 @@ typedef struct afl_forkserver {
u8 *shmem_fuzz; /* allocated memory for fuzzing */
char *cmplog_binary; /* the name of the cmplog binary */
char *asanfuzz_binary; /* the name of the ASAN binary */
/* persistent mode replay functionality */
u32 persistent_record; /* persistent replay setting */
@ -204,6 +211,7 @@ typedef struct afl_forkserver {
bool nyx_use_tmp_workdir;
char *nyx_tmp_workdir_path;
s32 nyx_log_fd;
u64 nyx_target_hash64;
#endif
#ifdef __AFL_CODE_COVERAGE
@ -241,6 +249,10 @@ void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
void afl_fsrv_kill(afl_forkserver_t *fsrv);
#ifdef __linux__
void nyx_load_target_hash(afl_forkserver_t *fsrv);
#endif
#ifdef __APPLE__
#define MSG_FORK_ON_APPLE \
" - On MacOS X, the semantics of fork() syscalls are non-standard and " \

View File

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

View File

@ -63,7 +63,7 @@
* // To enable unaligned access, but indicate that it significantly slow.
* #define T1HA_SYS_UNALIGNED_ACCESS 1
*
* // To enable unaligned access, and indicate that it effecient.
* // To enable unaligned access, and indicate that it's efficient.
* #define T1HA_SYS_UNALIGNED_ACCESS 2
*
*
@ -512,7 +512,7 @@ T1HA_API uint64_t t1ha2_atonce128(uint64_t *__restrict extra_result,
uint64_t seed);
/* The init/update/final trinity for streaming.
* Return 64 or 128-bit result depentently from `extra_result` argument. */
* Return 64 or 128-bit result dependently from `extra_result` argument. */
T1HA_API void t1ha2_init(t1ha_context_t *ctx, uint64_t seed_x, uint64_t seed_y);
T1HA_API void t1ha2_update(t1ha_context_t *__restrict ctx,
const void *__restrict data, size_t length);

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,7 @@ Alternatively you can set `AFL_LLVM_INJECTIONS_ALL` to enable all.
## How to modify
If you want to add more fuctions to check for e.g. SQL injections:
If you want to add more functions to check for e.g. SQL injections:
Add these to `instrumentation/injection-pass.cc` and recompile.
If you want to test for more injection inputs:

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ most effective way to fuzz, as the speed can easily be x10 or x20 times faster
without any disadvantages. *All professional fuzzing uses this mode.*
Persistent mode requires that the target can be called in one or more functions,
and that it's state can be completely reset so that multiple calls can be
and that its state can be completely reset so that multiple calls can be
performed without resource leaks, and that earlier runs will have no impact on
future runs. An indicator for this is the `stability` value in the `afl-fuzz`
UI. If this decreases to lower values in persistent mode compared to
@ -124,7 +124,6 @@ will keep working normally when compiled with a tool other than afl-clang-fast/
afl-clang-lto/afl-gcc-fast.
Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
(afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
and you should be all set!
## 4) Persistent mode

View File

@ -50,7 +50,11 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation.h"
#if LLVM_VERSION_MAJOR < 20
#include "llvm/Transforms/Instrumentation.h"
#else
#include "llvm/Transforms/Utils/Instrumentation.h"
#endif
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
@ -323,7 +327,16 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
};
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
if (!getenv("AFL_SAN_NO_INST")) {
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
} else {
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
return false;
}
}
@ -376,8 +389,16 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
};
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
if (!getenv("AFL_SAN_NO_INST")) {
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
} else {
if (debug) { DEBUGF("Instrument disabled\n"); }
}
return PreservedAnalyses::all();
@ -496,7 +517,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
// we make this the default as the fixed map has problems with
// defered forkserver, early constructors, ifuncs and maybe more
// deferred forkserver, early constructors, ifuncs and maybe more
/*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
map_addr = 0;

View File

@ -23,6 +23,10 @@
#include "llvm/IR/CFG.h"
#endif
#include "llvm/IR/Constant.h"
#if LLVM_VERSION_MAJOR >= 20
#include "llvm/IR/Constants.h"
#include "llvm/IR/ValueSymbolTable.h"
#endif
#include "llvm/IR/DataLayout.h"
#if LLVM_VERSION_MAJOR < 15
#include "llvm/IR/DebugInfo.h"
@ -63,11 +67,16 @@
#if LLVM_VERSION_MAJOR < 15
#include "llvm/Support/raw_ostream.h"
#endif
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/Instrumentation.h"
#if LLVM_VERSION_MAJOR < 20
#if LLVM_VERSION_MAJOR < 17
#include "llvm/Transforms/Instrumentation.h"
#else
#include "llvm/TargetParser/Triple.h"
#endif
#else
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@ -217,7 +226,11 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
#endif
#else
PB.registerOptimizerLastEPCallback(
#endif
@ -248,8 +261,20 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
};
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
// TODO: Support LTO or llvm classic?
// Note we still need afl-compiler-rt so we just disable the instrumentation
// here.
if (!getenv("AFL_SAN_NO_INST")) {
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
} else {
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
}
return PreservedAnalyses::all();
}
@ -301,7 +326,7 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
Type *PtrTy = PointerType::getUnqual(Ty);
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd});
assert(CtorFunc->getName() == CtorName);
// assert(CtorFunc->getName() == CtorName);
if (TargetTriple.supportsCOMDAT()) {
@ -317,7 +342,7 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
if (TargetTriple.isOSBinFormatCOFF()) {
// In COFF files, if the contructors are set as COMDAT (they are because
// In COFF files, if the constructors are set as COMDAT (they are because
// COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced
// functions and data) is used, the constructors get stripped. To prevent
// this, give the constructors weak ODR linkage and ensure the linker knows

View File

@ -11,7 +11,6 @@
https://www.apache.org/licenses/LICENSE-2.0
*/
#ifdef __AFL_CODE_COVERAGE
@ -358,7 +357,7 @@ static void __afl_map_shm(void) {
if (__afl_final_loc) {
__afl_map_size = ++__afl_final_loc; // as we count starting 0
__afl_map_size = __afl_final_loc + 1; // as we count starting 0
if (getenv("AFL_DUMP_MAP_SIZE")) {
@ -367,6 +366,12 @@ static void __afl_map_shm(void) {
}
if (__afl_debug) {
fprintf(stderr, "DEBUG: AFL_MAP_SIZE=%u\n", __afl_map_size);
}
if (__afl_final_loc > MAP_SIZE) {
char *ptr;
@ -413,7 +418,7 @@ static void __afl_map_shm(void) {
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
if (val > MAP_INITIAL_SIZE) {
if (val > MAP_INITIAL_SIZE && val > __afl_final_loc) {
__afl_map_size = val;
@ -595,9 +600,9 @@ static void __afl_map_shm(void) {
}
__afl_area_ptr_dummy = (u8 *)malloc(__afl_final_loc);
__afl_map_size = __afl_final_loc + 1;
__afl_area_ptr_dummy = (u8 *)malloc(__afl_map_size);
__afl_area_ptr = __afl_area_ptr_dummy;
__afl_map_size = __afl_final_loc;
if (!__afl_area_ptr_dummy) {
@ -630,22 +635,22 @@ static void __afl_map_shm(void) {
__afl_area_ptr_dummy = (u8 *)malloc(__afl_map_size);
if (__afl_area_ptr_dummy) {
}
if (__afl_selective_coverage_start_off) {
if (__afl_area_ptr_dummy) {
__afl_area_ptr = __afl_area_ptr_dummy;
if (__afl_selective_coverage_start_off) {
}
} else {
fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
__afl_selective_coverage = 0;
// continue;
__afl_area_ptr = __afl_area_ptr_dummy;
}
} else {
fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
__afl_selective_coverage = 0;
// continue;
}
}
@ -886,11 +891,11 @@ static void __afl_start_forkserver(void) {
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (!__afl_old_forkserver) {
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
@ -2664,6 +2669,89 @@ void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
}
/* llvm weak hooks */
void __sanitizer_weak_hook_memcmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_n((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_memmem(void *pc, const void *s1, size_t len1,
const void *s2, size_t len2, void *result) {
__cmplog_rtn_hook_n((u8 *)s1, (u8 *)s2, len1 < len2 ? (u64)len1 : (u64)len2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncasecmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncasestr(void *pc, const void *s1, const void *s2,
size_t n, char *result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strncmp(void *pc, const void *s1, const void *s2,
size_t n, int result) {
__cmplog_rtn_hook_strn((u8 *)s1, (u8 *)s2, (u64)n);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcasecmp(void *pc, const void *s1, const void *s2,
int result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcasestr(void *pc, const void *s1, const void *s2,
size_t n, char *result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strcmp(void *pc, const void *s1, const void *s2,
int result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
void __sanitizer_weak_hook_strstr(void *pc, const void *s1, const void *s2,
char *result) {
__cmplog_rtn_hook_str((u8 *)s1, (u8 *)s2);
(void)pc;
(void)result;
}
/* COVERAGE manipulation features */
// this variable is then used in the shm setup to create an additional map

View File

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

View File

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

View File

@ -478,7 +478,8 @@ Specify -frandom-seed for reproducible instrumentation.\n\
int plugin_init(struct plugin_name_args *info,
struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version))
if (!plugin_default_version_check(version, &gcc_version) &&
!getenv("AFL_GCC_DISABLE_VERSION_CHECK"))
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
"is %s"),
gcc_version.basever, version->basever);

View File

@ -157,7 +157,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
// mangled name of the user-written function
for (auto const &ignoreListFunc : ignoreSubstringList) {
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
// hexcoder: F->getName().contains() not available in llvm 3.8.0
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
}
@ -168,6 +168,10 @@ bool isIgnoreFunction(const llvm::Function *F) {
void initInstrumentList() {
static int init = 0;
if (init) return;
init = 1;
char *allowlist = getenv("AFL_LLVM_ALLOWLIST");
if (!allowlist) allowlist = getenv("AFL_LLVM_INSTRUMENT_FILE");
if (!allowlist) allowlist = getenv("AFL_LLVM_WHITELIST");
@ -250,7 +254,7 @@ void initInstrumentList() {
if (debug)
DEBUGF("loaded allowlist with %zu file and %zu function entries\n",
allowListFiles.size() / 4, allowListFunctions.size() / 4);
allowListFiles.size(), allowListFunctions.size());
}
@ -325,7 +329,7 @@ void initInstrumentList() {
if (debug)
DEBUGF("loaded denylist with %zu file and %zu function entries\n",
denyListFiles.size() / 4, denyListFunctions.size() / 4);
denyListFiles.size(), denyListFunctions.size());
}

View File

@ -8,7 +8,13 @@
#include <list>
#include <string>
#include <fstream>
#include <optional>
#ifdef __has_include
#if __has_include(<optional>)
#include <optional>
#endif
#endif
#include <sys/time.h>
#include "llvm/Config/llvm-config.h"

View File

@ -120,12 +120,17 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(AFLdict2filePass());
MPM.addPass(AFLdict2filePass());
});
});
}};

View File

@ -5,9 +5,6 @@
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
from afl-as.c are Michal's fault.
Copyright 2015, 2016 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -17,10 +14,6 @@
https://www.apache.org/licenses/LICENSE-2.0
This library is plugged into LLVM when invoking clang through afl-clang-fast.
It tells the compiler to add code roughly equivalent to the bits discussed
in ../afl-as.h.
*/
#define AFL_LLVM_PASS
@ -90,12 +83,17 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(AFLcheckIfInstrument());
MPM.addPass(AFLcheckIfInstrument());
});
});
}};

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