Compare commits

..

192 Commits

Author SHA1 Message Date
c340a022e2 Merge pull request #2401 from AFLplusplus/dev
v4.32c release
2025-04-26 15:36:45 +02:00
06219b4d56 v4.32c 2025-04-26 15:35:47 +02:00
c5b8f4250e code format 2025-04-26 15:30:56 +02:00
779cb5d942 Merge pull request #2400 from AFLplusplus/dev
push to stable
2025-04-26 15:30:18 +02:00
fb1a41f5af fix 2025-04-26 13:24:21 +02:00
8352f0a89f fix LLVM 20 pass pipeline insertion 2025-04-26 13:20:51 +02:00
9935190c7b drop llvm 13 AFL++ plugin support 2025-04-25 18:37:19 +02:00
e3ee26262f fix AFL_OLD_FORKSERVER 2025-04-25 13:42:19 +02:00
737c13b460 Merge pull request #2386 from 5angjun/dev
Add someone else to the "list of contributors" :)
2025-04-25 10:03:37 +02:00
9836598d65 Merge pull request #2398 from kcwu/fix-minor
Minor fixes
2025-04-25 10:03:23 +02:00
63509fb696 fix afl-cmin message output 2025-04-25 11:51:34 +08:00
d1c44e12a8 remove dead comment 2025-04-25 11:51:20 +08:00
f78ed6eabc remove redundent code 2025-04-25 11:51:08 +08:00
64c942d0c9 fix printf format 2025-04-25 11:50:50 +08:00
50e343a0d0 Merge branch 'dev' into dev 2025-04-25 11:23:33 +09:00
55719ab23b Resolve merge conflict in README.md 2025-04-25 11:19:52 +09:00
d12c5edd59 Merge pull request #2395 from ryberger-nvidia/fix-infinite-loop
fix infinite loop when custom mutator rejects smallest_favored
2025-04-24 16:04:41 +02:00
1b82d6b904 fix for nit in afl-tmin 2025-04-24 14:42:32 +02:00
61201fbbb8 fix infinite loop when custom mutator rejects smallest_favored
When running with custom mutators, afl-fuzz delegates the responsibility of queuing to` afl_custom_queue_get`
implemented by the mutator. If any mutator cannot process the input, then it is rejected. After an input is rejected
then a new suitable item to queue must be found. Before this PR, that would be `smallest_favored`. However,
if `smallest_favored` were rejected, it would not be cleared from its position as  `smallest_favored` meaning it
would be attempted to be queued again catching afl-fuzz in an infinite loop.

To fix it, we simply return that we skipped the entry, along with using a `goto abandon_entry` to clean the entry up so that
the fuzzer never considers the input again
2025-04-23 14:47:55 -07:00
b9458e72e7 nit 2025-04-23 16:42:49 +02:00
5045f9e615 code format 2025-04-21 11:45:33 +02:00
6cd8a0168f Merge pull request #2391 from kcwu/fix-__AFL_COVERAGE
fix __AFL_COVERAGE: multiple definition of `__afl_selective_coverage`
2025-04-21 11:45:05 +02:00
448c6c212d fix __AFL_COVERAGE: multiple definition of __afl_selective_coverage
fix #2390
2025-04-21 09:02:23 +00:00
05f4762894 nits 2025-04-21 10:59:59 +02:00
0a06e36788 Merge pull request #2336 from gitToki/stable
Enhancement: Custom Python trimming support to afl-tmin
2025-04-19 15:50:42 +02:00
9b1f80c277 Merge pull request #2388 from kcwu/fix-changelog
fix 4.31c change log
2025-04-19 15:36:42 +02:00
787a332a73 fix 4.31c change log
the splicing auto enable is removed by b2a01936c3
2025-04-19 12:13:36 +00:00
7d85047fd9 update bitmap api 2025-04-17 15:28:31 +02:00
fa8dc2028f Merge branch 'AFLplusplus:stable' into stable 2025-04-17 15:20:31 +02:00
619aa70414 Add someone else to the "list of contributors" :) 2025-04-17 16:28:35 +09:00
247e8241b4 Merge pull request #2360 from AFLplusplus/dev
push to stable
2025-04-16 18:14:35 +02:00
0bb64e4bc9 Merge pull request #2384 from fanquake/ubuntu_20_04_removed
Ubuntu 20.04 removed by GitHub
2025-04-16 17:52:30 +02:00
7b84ec97e2 Merge pull request #2383 from fanquake/fix_lld_version
build: improve lld version parsing
2025-04-16 15:18:09 +02:00
20a6cdabad ci: drop usage of ubuntu:20.04
Support for this has been removed by GitHub:
https://github.com/actions/runner-images/issues/11101.
2025-04-16 14:03:36 +01:00
0d286c9e19 build: improve lld version parsing
Currently, if LLD is in a weird location and has a version string like:
```bash
Ubuntu LLD 18.1.3 (compatible with GNU linkers)
```
or
```bash
Homebrew LLD 20.1.2 (compatible with GNU linkers)
```

The version comparison will fail:
```bash
GNUmakefile.llvm:247: ld.lld found in a weird location (/opt/homebrew/bin/ld.lld) and its of a different version than LLMV (LLD vs. 20.1.2) - cannot enable LTO mode
```

Fix that by replacing the usage of awk, with the same sed command used
to retrieve the version of Clang, which fixes the issue:
```bash
GNUmakefile.llvm:245: ld.lld found in a weird location (/opt/homebrew/bin/ld.lld), but its the same version as LLVM so we will allow it
```
2025-04-16 13:37:15 +01:00
db94ec9cad Merge pull request #2382 from kcwu/fix-performance-unit
fix build for "make PERFORMANCE=1 unit"
2025-04-16 10:14:43 +02:00
05dfb70787 fix build for "make PERFORMANCE=1 unit" 2025-04-16 00:48:30 +00:00
7f2becba72 build fix for asan+performance 2025-04-14 13:57:45 +02:00
13b27bb59e Merge pull request #2375 from kcwu/format-cache
code-format cache
2025-04-14 10:11:50 +02:00
ecdbdc3164 Merge pull request #2377 from kcwu/fix-custom-format
fix in_define in .custom-format.py
2025-04-14 10:10:38 +02:00
788e70a01a Merge pull request #2379 from r3sting/patch-1
Fix linker error
2025-04-14 10:09:43 +02:00
938ed60ea9 Merge pull request #2380 from kcwu/fix-memory-leak
Fix memory leak
2025-04-14 10:09:03 +02:00
5b9d2cc38b code-format cache
This change reduces "make code-format" from 3 minutes to 3 seconds if
large files are not changed.
2025-04-13 08:26:18 +00:00
e305bc15d3 fix memory leaks 2025-04-13 06:46:46 +00:00
0b12c7e0cc Fix linker error 2025-04-12 16:20:33 -06:00
4bd492f212 fix memory leak in check_main_node_exists 2025-04-12 16:56:14 +00:00
be8393f201 fix in_define in .custom-format.py
avoid the extra \ before #define line
2025-04-12 15:56:36 +00:00
aec90c7227 Merge pull request #2376 from kcwu/minor-changes
Minor changes
2025-04-12 16:01:34 +02:00
1960352310 add custom mutator support for afl tmin 2025-04-12 14:55:30 +02:00
03169b2b67 print the file name with variable behavior
Because queue/.state/variable_behavior was removed, print file name in
case some users still want the information.
2025-04-12 11:16:11 +00:00
dee51213a7 update build dependency rule in GNUmakefile 2025-04-12 11:16:11 +00:00
1d2de1cb6d remove dead code in comment 2025-04-12 11:15:25 +00:00
5ed187b517 fix for cycle_schedule change 2025-04-12 12:57:37 +02:00
a845852b98 Merge pull request #2374 from kcwu/fix-memory-leaks
Fix memory leaks
2025-04-12 12:16:16 +02:00
9513397336 free memory when shutdown
With this fix, ASAN_BUILD won't report leaks if ctrl-c (in a short run).
2025-04-12 09:49:24 +00:00
57fa87ce5e only allocate SAND memory if enabled 2025-04-12 09:49:19 +00:00
c6a2cf88bf Merge pull request #2370 from kcwu/dev
code cleanup
2025-04-10 16:57:05 +02:00
8461f860eb code format 2025-04-10 16:28:03 +02:00
7395223512 Merge pull request #2368 from w1redch4d/qbdi_fix
fixed qbdi mode to work out of the box
2025-04-10 16:26:48 +02:00
1121af301b Merge pull request #2369 from 5angjun/dev
add cleanup for top_rated_candidates in afl_state_deinit()
2025-04-10 16:25:18 +02:00
b9c1536283 added safe_length option for portability and clarity 2025-04-10 19:44:54 +05:30
6691ce943a remove unused variable 2025-04-10 21:54:54 +08:00
1dba3a276f remove unused variable 2025-04-10 21:54:54 +08:00
3c8016e071 fixed qbdi mode to work out of the box 2025-04-10 19:21:14 +05:30
b64dd0a1ec add cleanup for top_rated_candidates in afl_state_deinit() 2025-04-10 22:50:42 +09:00
55f758a168 Merge pull request #2366 from 5angjun/dev
fix: correct rescoring logic with minimal executions
2025-04-10 14:01:49 +02:00
bd631c73a2 Enable conditional allocation for cycle schedules 2025-04-10 18:41:32 +09:00
6cbe58ff55 code format 2025-04-10 09:30:18 +02:00
c71d487a4c Merge pull request #2367 from wtdcode/sand-fix
Fix missing classified accidentally removed by 4ff2673
2025-04-10 08:37:06 +02:00
mio
939171952d Fix missing classified accidentally removed by 4ff2673 2025-04-10 12:35:31 +08:00
161905c2fc fix: correct rescoring logic with minimal executions
Previous scoring logic did not correctly rescore all queue entries.

This patch ensures rescoring works under the updated scheduling logic,
while minimizing executions per feedback from PR #2363.

Based on feedback from: https://github.com/AFLplusplus/AFLplusplus/pull/2363
2025-04-09 23:37:16 +09:00
5ff21c9aad Merge pull request #2365 from wtdcode/sand-fix
Fix sand due to default schedule change
2025-04-09 15:58:21 +02:00
mio
112d90656b rebase against dev 2025-04-09 21:34:33 +08:00
mio
bc11bd7661 Fix comments 2025-04-09 21:34:20 +08:00
mio
6b71ca7809 Also remove declaration 2025-04-09 21:34:19 +08:00
mio
eb0b8b2c5c No longer need classify_counts_mem 2025-04-09 21:34:19 +08:00
mio
6223ddf6d2 Changes not saved =( 2025-04-09 21:34:18 +08:00
mio
920c7fe71a Fix sand due to default schedule change 2025-04-09 21:34:18 +08:00
4ff2673895 fix update_bitmap_score when no current trace is present 2025-04-09 14:21:42 +02:00
891b7f48f0 nits 2025-04-09 10:48:34 +02:00
5df3cdbc0b effeciency fix for SAND 2025-04-08 17:43:26 +02:00
57466909e4 remove outdated doc 2025-04-08 11:33:05 +02:00
55c9c4ff19 deprecate some queue/.state files 2025-04-08 11:32:08 +02:00
fe202b5fee Merge pull request #2361 from kcwu/patch-1
Update FAQ.md
2025-04-08 10:18:17 +02:00
c5e511302f Update FAQ.md
the default schedule was changed to EXPLORE since 4.10a
2025-04-08 09:37:20 +08:00
7c349b6cde increase fast resume version 2025-04-07 10:13:13 +02:00
fc38904e25 fix 2025-04-07 10:08:34 +02:00
eee2521eb4 Merge pull request #2358 from kcwu/fix-buffer-overflow
fix potential q->trace_mini off by 1 overflow
2025-04-07 10:08:16 +02:00
192d4817e0 Merge pull request #2357 from wtdcode/fix-sand-comments
Fix comments in for SAND
2025-04-06 13:59:37 +02:00
mio
58e4070573 Update comments 2025-04-06 12:18:49 +08:00
mio
2ecf28440f Fix comments in for SAND 2025-04-06 12:16:34 +08:00
757184e611 adjustment 2025-04-06 01:37:15 +02:00
27b18e6267 refactor/ Use functions from other files instead of creating new ones 2025-04-05 21:08:08 +02:00
f1ee7bc9cd Merge pull request #2354 from kcwu/reduce-skipdet_e-memory-usage
reduce skipdet_e memory usage
2025-04-05 13:03:44 +02:00
969541b54f fix potential q->trace_mini off by 1 overflow
Be careful this change is incompatible with old version of fastresume.bin
2025-04-05 03:06:15 +00:00
ec07f531f8 reduce skipdet_e memory usage
By using bitmaps, the memory requirement for
`q->skipdet_e->skip_eff_map` and `done_inf_map`, which previously scaled
with the corpus size, is reduced to one-eighth of its original size.
2025-04-05 01:49:27 +00:00
56b5983b61 Merge pull request #2353 from 20urc3/patch-2
Patch 2
2025-04-03 18:10:05 +02:00
f17ea60a30 Update afl-cmin
removed `-a ! -path \"*/.state\"`
2025-04-03 16:49:43 +01:00
68634964ef Update afl-cmin 2025-04-03 16:28:31 +01:00
d21804bdd1 Update afl-cmin
Fix patch 1
2025-04-03 15:30:45 +01:00
5a527046a5 Merge pull request #2352 from AFLplusplus/dev
push to stable
2025-04-03 15:27:31 +02:00
b2a8765b1f Merge pull request #2348 from Xeonacid/riscv
Define WORD_SIZE_64 for riscv64
2025-04-03 15:25:44 +02:00
106309492c Merge pull request #2351 from kcwu/fix-double-free
fix double free bug introduced by 73ab495b5d1a99722f4a2c2b1b9507daa73…
2025-04-03 15:20:27 +02:00
58c5e2b96c fix double free bug introduced by 73ab495b5d 2025-04-03 11:09:32 +00:00
5842ba87e5 Define WORD_SIZE_64 for riscv64 2025-04-03 04:17:37 -04:00
5069551778 update changelog 2025-04-03 08:43:14 +02:00
0606d95f86 Merge pull request #2347 from AFLplusplus/dev
push to stable
2025-04-03 08:42:27 +02:00
0e35e56cc9 update changelog 2025-04-03 08:25:21 +02:00
fc860872d6 Merge pull request #2344 from kcwu/fix-sync-foreign
avoid import already imported foreign corpus
2025-04-03 08:25:05 +02:00
735d647e48 Merge pull request #2345 from kcwu/fix-leak-foreign
fix memory leak in read_foreign_testcases
2025-04-03 08:20:30 +02:00
73ab495b5d Merge pull request #2346 from kcwu/fix-memory-leak
fix memory leaks
2025-04-03 08:19:48 +02:00
d1cab470bb fix memory leaks 2025-04-03 04:17:12 +00:00
992349e48a fix memory leak in read_foreign_testcases 2025-04-02 12:48:05 +00:00
950b90abcd avoid import already imported foreign corpus
If no new foreign cases, mtime_max is 0 and this incorrectly reset last
import mtime.
2025-04-02 12:45:47 +00:00
f3b15d6340 fmt 2025-04-01 17:59:59 +02:00
0134a23046 impl normal custom mutators 2025-04-01 17:55:43 +02:00
7c296f099f Merge pull request #2337 from 5angjun/stable
Bug Fix: Crash when using INTROSPECTION=1 with -z (skip deterministic)
2025-03-31 16:15:48 +02:00
919e6226d3 Merge pull request #2338 from r3sting/fix-frida-mode-macos
Fix frida-mode compliation error for MacOS
2025-03-31 14:49:46 +02:00
a85f0c0ef9 Add skip routine before writing det_plot_file 2025-03-30 10:14:02 +09:00
6457e2ea30 Fix frida-mode compliation error for MacOS 2025-03-29 16:12:29 -07:00
542233e1ce custom python mutators in afl-tmin 2025-03-28 00:36:12 +01:00
8e4823e7ed add python flag to gnumakefile 2025-03-27 22:20:13 +01:00
f27c504f29 update afl-*-config 2025-03-25 20:57:32 +01:00
9776e402c3 Merge pull request #2334 from andy-knowles/exit-code
Better handling of exit codes used by sanitzers
2025-03-25 09:28:40 +01:00
4cabb81996 Better handling of exit codes used by sanitzers 2025-03-24 16:30:05 +01:00
42465480ef Merge pull request #2328 from 0xXA/fix-doc
fix(afl-fuzz-init): ensure proper permissions for setting CPU governor
2025-03-11 11:24:16 +01:00
f27f109880 fix(afl-fuzz-init): ensure proper permissions for setting CPU governor
The previous command used tee without sudo, which could fail due to insufficient permissions.

Signed-off-by: Yuvraj Saxena <ysaxenax@gmail.com>
2025-03-10 17:43:18 +05:30
fa9e256e09 Merge pull request #2325 from Evian-Zhang/dev
Add notes about cpu bind in docker
2025-03-06 14:18:07 +01:00
78952e8440 ensure constants are kept for LLVMFuzzerTestOneInput 2025-03-06 14:15:53 +01:00
8b543df04c Add notes about cpu bind in docker 2025-03-05 18:51:37 +08:00
e64c3f8653 code format 2025-03-03 18:03:59 +01:00
f590973387 Merge pull request #2320 from AFLplusplus/dev
push to stable
2025-03-03 13:52:45 +01:00
36338ad08b Merge pull request #2319 from smoelius/add-fflush-before-abort
Add `fflush(stdout);` before `abort` call
2025-03-03 13:29:29 +01:00
73a36ffda3 Add fflush(stdout); before abort call
Fixes #2318
2025-03-03 05:24:36 -05:00
cdf93f4d1f Merge pull request #2317 from AFLplusplus/dev
push to stable
2025-02-28 10:58:59 +01:00
a0d996558b fix doc 2025-02-28 10:57:44 +01:00
21e75d73a6 unicornafl example: fix incorrect comment (#2315) 2025-02-27 14:29:41 +01:00
cc1d41f59d Merge pull request #2313 from vnc0/ios
Add support for iOS builds
2025-02-27 11:46:32 +01:00
9530b4c9d4 fix We need at least one valid input seed that does not crash when fast restart 2025-02-27 09:50:40 +01:00
f1998bb53b Update INSTALL.md 2025-02-26 18:08:36 +01:00
0e3c82e2ea Merge branch 'dev' into ios 2025-02-26 17:59:07 +01:00
c22b06a27d Merge branch 'ios-cross' into ios 2025-02-26 17:51:07 +01:00
1d1aa3edec Add iOS installation instructions 2025-02-26 17:50:20 +01:00
50f6b38530 Add iOS cross-compilation support
- Updated CFLAGS and LDFLAGS.
- Disabled signing of bin2c during cross-compilation.
2025-02-26 16:46:49 +01:00
0cd932c4b5 Add support for iOS builds
- Define IS_IOS variable and add conditional compilation flags for iOS
- Enable binary signing with ldid for iOS builds
2025-02-25 11:58:06 +01:00
a635aa8cba potential macos fix 2025-02-23 13:22:44 +01:00
00577bb32d Merge pull request #2312 from stock1218/stable
Small change to LTO documentation
2025-02-21 20:35:01 +01:00
6aaba974b6 Update LTO documentation to reference LLVM 19 in all examples 2025-02-21 12:06:14 -05:00
6459707f24 Merge pull request #2310 from devnexen/llvm20
preparing for LLVM 20 with new sanitizer.
2025-02-20 16:38:57 +01:00
870e22246a preparing for LLVM 20 with new sanitizer.
note: no real valuable option atm.
2025-02-20 11:22:22 +00:00
66c2bb3994 Merge pull request #2309 from AFLplusplus/dev
push to stable
2025-02-19 10:00:13 +01:00
a482b817af Merge pull request #2307 from intrigus-lgtm/feat/arm-in-ci
feat: use GH hosted ARM runners.
2025-02-19 09:59:37 +01:00
6f433b5d73 feat: re-enable arm64 docker containers. Use GH arm runners 2025-02-18 21:06:51 +00:00
2843b7eb02 feat: enable arm runners in CI 2025-02-18 21:06:51 +00:00
6ed9b6d631 Merge pull request #2308 from AFLplusplus/delete_initial_run
Delete initial call to LLVMFuzzerTestOneInput in aflpp driver
2025-02-18 14:52:15 +01:00
6f018b3d80 del 2025-02-18 14:09:43 +01:00
1318636ae7 Merge pull request #2305 from kdsjZh/dev
add doc for the new default deterministic mode (followup for PR #1972)
2025-02-17 15:10:05 +01:00
29f48ab3e7 update 2025-02-17 09:43:59 +01:00
2c2a0471cd fix 2025-02-17 09:42:56 +01:00
68f5c4811e move to feature 2025-02-17 09:40:58 +01:00
fe6d3990ce Merge pull request #2306 from AFLplusplus/dev
push to stable
2025-02-17 09:37:34 +01:00
2b143688a6 disable arm64 image due workflow problems 2025-02-17 09:01:01 +01:00
f37f0b4ee4 easier LTO CTX activation 2025-02-17 08:40:57 +01:00
bd5ccc6977 add doc for deterministic mode 2025-02-17 08:30:57 +01:00
e0b23dd53d Merge pull request #2304 from wtdcode/c++-alt
Also set /usr/bin/c++ or this fails cc-rs
2025-02-15 17:30:40 +01:00
mio
54890db08e Also set /usr/bin/c++ or this fails cc-rs 2025-02-15 23:50:43 +08:00
6c4b2f0c8e fix compile warnings 2025-02-15 12:15:16 +01:00
bed20d40b1 Merge pull request #2303 from manyhus/debug_path_fix
Fix debug prefix for afl-cc, llvm-rt
2025-02-14 14:49:13 +01:00
ea2f112016 Fix debug prefix for afl-cc, llvm-rt
After the llvm_mode directory was removed in 996986bed5 and compilation
started happening from the root, adding llvm_mode to the debug path is
incorrect and causes source file lookups to fail when debugging e.g.
afl-cc or the llvm pass.
2025-02-14 12:19:36 +01:00
f639668032 Merge pull request #2302 from AFLplusplus/dev
push to stable
2025-02-14 10:52:37 +01:00
1709eb59a8 Merge pull request #2301 from etanner1/fix-issue-2298
Addressed frida-mode exec speed regression on ARM64 for #2298
2025-02-14 10:27:40 +01:00
bbdcfb0e8e not 2025-02-14 10:25:44 +01:00
cab4609e1a Merge pull request #2300 from manyhus/optarg_fix
afl-fuzz: fix -a option
2025-02-14 10:23:38 +01:00
feed691dc0 Addressed frida-mode exec-speed regression on ARM64 for #2298
Co-authored-by: WorksButNotTested <@WorksButNotTested>
2025-02-13 16:23:22 -05:00
e4f7a4738e afl-fuzz: fix -a option
This fixes the option string so -a will be parsed with an argument
again, unbreaking the option. The result of the missing : was that
optarg would always be NULL and we would abort in stricmp.

Introduced in 1c9925c7d7
2025-02-13 14:13:56 +01:00
625df13d0e Merge pull request #2299 from AFLplusplus/dev
push to stable
2025-02-12 16:44:18 +01:00
a3c038efd6 new gcc + llvm in ci 2025-02-12 15:48:02 +01:00
4f3812f00d try docker ci fix 2025-02-12 10:09:55 +01:00
887d104dae update ci to ubuntu 24.04, remove 20.04 2025-02-12 10:00:25 +01:00
47954cd04c try macos fix 2025-02-12 09:16:01 +01:00
a441f517e7 Merge pull request #2297 from SonicStark/dev-ltoctx-0211
Excess `afl_global_id` Increase of LTO-CTX
2025-02-12 09:06:19 +01:00
9cb3fe98dd Merge pull request #2290 from vnc0/FridaGum16.6.0
Update FRIDA mode for Frida Gum 16.6.x API compatibility
2025-02-11 13:42:25 +01:00
e6f15f02e1 fix 32 bit compile 2025-02-11 12:02:40 +01:00
65b99d25e1 make gcc 15 happy 2025-02-11 11:57:57 +01:00
7b86d735df Set default GUM_DEVKIT_VERSION to 16.1.11
Due to a performance regression in Frida Gum 16.2.0, revert the default GUM_DEVKIT_VERSION to 16.1.11. This change ensures that the expected performance levels are maintained until the issues in Frida Gum 16.2.0 are resolved.
2025-02-11 11:30:58 +01:00
b56b24d251 Merge branch 'FridaGum16.6.0-cflag' into FridaGum16.6.0 2025-02-11 08:17:45 +01:00
c2383761cb Set default GUM_DEVKIT_VERSION to 16.5.9
Execution speed seems better than recent versions.
2025-02-11 08:16:39 +01:00
f87a669aa3 Add conditional compiler flag for Frida 16.6+ compatibility 2025-02-11 08:05:21 +01:00
8489112ab1 Fix excess afl_global_id increase
introduced in commit 44a769616
2025-02-11 13:06:09 +08:00
ebd6d4b8bb update qemuafl 2025-02-10 19:45:58 +01:00
125027f5bf v4.32a 2025-02-10 14:40:12 +01:00
fd780e8eba Update FRIDA mode for Frida Gum 16.6.x API compatibility
- Bumped the frida-gum version to 16.6.5.
- Refactored functions to use `GumModule` instead of deprecated `GumModuleDetails`.
2025-01-25 18:26:30 +01:00
69 changed files with 1557 additions and 491 deletions

View File

@ -21,12 +21,15 @@ import os
# import re # TODO: for future use
import shutil
import importlib.metadata
import hashlib
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
FORMAT_CACHE_DIR = '.format-cache'
os.makedirs(FORMAT_CACHE_DIR, exist_ok=True)
def check_clang_format_pip_version():
"""
@ -69,6 +72,8 @@ to install via pip.")
if CLANG_FORMAT_PIP:
CLANG_FORMAT_BIN = shutil.which("clang-format")
CLANG_FORMAT_VERSION = subprocess.check_output([CLANG_FORMAT_BIN, '--version'])
COLUMN_LIMIT = 80
for line in fmt.split("\n"):
line = line.split(":")
@ -86,9 +91,10 @@ def custom_format(filename):
out = ""
for line in src.split("\n"):
define_start = False
if line.lstrip().startswith("#"):
if line[line.find("#") + 1:].lstrip().startswith("define"):
in_define = True
define_start = True
if (
"/*" in line
@ -126,9 +132,7 @@ def custom_format(filename):
and last_line.strip() != ""
):
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
if not line.endswith("\\"):
in_define = False
in_define = (define_start or in_define) and line.endswith("\\")
out += line + "\n"
last_line = line
@ -136,6 +140,38 @@ def custom_format(filename):
return out
def hash_code_and_formatter(code):
hasher = hashlib.sha256()
hasher.update(code.encode())
hasher.update(CLANG_FORMAT_VERSION)
with open(__file__, 'rb') as f:
hasher.update(f.read())
return hasher.hexdigest()
def custom_format_cached(filename):
filename_hash = hashlib.sha256(filename.encode()).hexdigest()
cache_file = os.path.join(FORMAT_CACHE_DIR, filename_hash)
if os.path.exists(cache_file):
with open(filename) as f:
code = f.read()
code_hash = hash_code_and_formatter(code)
with open(cache_file) as f:
if f.read() == code_hash:
return code
code = custom_format(filename)
code_hash = hash_code_and_formatter(code)
with open(cache_file, 'w') as f:
f.write(code_hash)
return code
args = sys.argv[1:]
if len(args) == 0:
print("Usage: ./format.py [-i] <filename>")
@ -151,7 +187,7 @@ if args[0] == "-i":
args = args[1:]
for filename in args:
code = custom_format(filename)
code = custom_format_cached(filename)
if in_place:
with open(filename, "w") as f:
f.write(code)

View File

@ -14,18 +14,18 @@ jobs:
runs-on: "${{ matrix.os }}"
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm]
env:
AFL_SKIP_CPUFREQ: 1
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: update
run: sudo apt-get update && sudo apt-get upgrade -y
- name: debug
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
- name: install packages
run: sudo apt-get install -y -m -f build-essential gcc-10 g++-10 git libtool libtool-bin automake flex bison libglib2.0-0 clang-12 llvm-12-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip gcc-10-plugin-dev
run: sudo apt-get install -y -m -f build-essential gcc-12 g++-12 git libtool libtool-bin automake flex bison libglib2.0-0 clang-15 llvm-15-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip gcc-12-plugin-dev
- name: compiler installed
run: gcc -v; echo; clang -v
- name: install gcc plugin
@ -45,7 +45,7 @@ jobs:
- 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
# run: cd /usr/local/bin; ln -s gcc-12 gcc; ln -s g++-12 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

View File

@ -16,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Build amd64
uses: docker/build-push-action@v3
uses: docker/build-push-action@v6
with:
context: .
tags: aflplusplus:test-amd64
@ -35,20 +35,41 @@ jobs:
apt-get install -y libcmocka-dev &&
make -i tests
"
build-and-test-arm64:
name: Test arm64 image
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build arm64
uses: docker/build-push-action@v6
with:
context: .
tags: aflplusplus:test-arm64
load: true
cache-to: type=gha,mode=max
build-args: |
TEST_BUILD=1
- name: Test arm64
run: >
docker run --rm aflplusplus:test-arm64 bash -c "
apt-get update &&
apt-get install -y libcmocka-dev &&
make -i tests
"
push:
name: Push amd64 and arm64 images
runs-on: ubuntu-latest
needs:
- build-and-test-amd64
- build-and-test-arm64
if: ${{ github.event_name == 'push' && github.repository == 'AFLplusplus/AFLplusplus' }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to docker.io

View File

@ -18,7 +18,7 @@ jobs:
working-directory: custom_mutators/rust
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
os: [ubuntu-22.04]
steps:
- uses: actions/checkout@v3
- name: Install Rust Toolchain

3
.gitignore vendored
View File

@ -7,6 +7,7 @@
*.so
*.swp
.DS_Store
.format-cache
.sync_tmp
.test
.test2
@ -113,4 +114,4 @@ utils/replay_record/persistent_demo_replay_argparse
utils/plot_ui/afl-plot-ui
vuln_prog
argv_fuzz_demo
argv_fuzz_persistent_demo
argv_fuzz_persistent_demo

View File

@ -61,6 +61,7 @@ RUN apt-get update && \
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \
update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_VERSION} 0 && \
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 0

View File

@ -70,6 +70,11 @@ ifdef CODE_COVERAGE
override CFLAGS += -D__AFL_CODE_COVERAGE=1
endif
IS_IOS:=$(findstring ios, $(shell $(CC) --version 2>/dev/null))
ifdef IS_IOS
override CFLAGS += -DTARGET_OS_IPHONE -DTARGET_OS_IOS -isysroot $(IOS_SDK_PATH)
endif
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
CFLAGS_FLTO ?= -flto=full
@ -101,17 +106,19 @@ else
SPECIAL_PERFORMANCE :=
endif
ifneq "$(SYS)" "Darwin"
#ifeq "$(HAVE_MARCHNATIVE)" "1"
# SPECIAL_PERFORMANCE += -march=native
#endif
#ifndef DEBUG
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
#endif
else
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
override LDFLAGS += $(SDK_LD)
ifndef IS_IOS
ifneq "$(SYS)" "Darwin"
#ifeq "$(HAVE_MARCHNATIVE)" "1"
# SPECIAL_PERFORMANCE += -march=native
#endif
#ifndef DEBUG
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
#endif
else
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
override LDFLAGS += $(SDK_LD)
endif
endif
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
@ -282,7 +289,7 @@ ifneq "$(findstring OpenBSD, $(SYS))" ""
override LDFLAGS += -lpthread -lm
endif
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h include/afl-fuzz.h include/hash.h include/sharedmem.h include/forkserver.h include/common.h include/list.h
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
PYTHON_OK=1
@ -465,32 +472,47 @@ endif
ready:
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
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
src/afl-performance.o: $(COMM_HDR) src/afl-performance.c
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
src/afl-common.o: $(COMM_HDR) src/afl-common.c include/envs.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
src/afl-forkserver.o: $(COMM_HDR) src/afl-forkserver.c
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
src/afl-sharedmem.o: $(COMM_HDR) src/afl-sharedmem.c include/android-ashmem.h include/cmplog.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o include/cmplog.h include/envs.h | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
afl-showmap: src/afl-showmap.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o -o $@ $(PYFLAGS) $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
.PHONY: document
document: afl-fuzz-document
@ -498,6 +520,9 @@ document: afl-fuzz-document
# document all mutations and only do one run (use with only one input file!)
afl-fuzz-document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
@ -505,20 +530,29 @@ test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittes
unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_maybe_alloc
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
@$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_hash
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_rand
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
@ -526,6 +560,9 @@ test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list
unit_list: test/unittests/unit_list.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_list
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
@ -533,6 +570,9 @@ test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unitte
unit_preallocable: test/unittests/unit_preallocable.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_preallocable
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
.PHONY: unit_clean
unit_clean:
@ -644,6 +684,7 @@ deepclean: clean
rm -rf unicorn_mode/unicornafl
rm -rf qemu_mode/qemuafl
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
rm -rf .format-cache
ifeq "$(IN_REPO)" "1"
git checkout coresight_mode/coresight-trace
git checkout unicorn_mode/unicornafl

View File

@ -237,20 +237,21 @@ ifeq "$(LLVM_LTO)" "1"
ifeq "$(AFL_REAL_LD)" ""
ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" ""
AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld
else ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
AFL_REAL_LD = $(shell command -v ld.lld)
TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }')
ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)"
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
else
ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
AFL_REAL_LD = $(shell command -v ld.lld)
TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | sed -E -ne '/^.*LLD\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)"
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
else
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode)
AFL_REAL_LD=
LLVM_LTO = 0
endif
else
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode)
AFL_REAL_LD=
$(warning ld.lld not found, cannot enable LTO mode)
LLVM_LTO = 0
endif
undefine TMP_LDLDD_VERSION
else
$(warning ld.lld not found, cannot enable LTO mode)
LLVM_LTO = 0
endif
endif
else
@ -272,11 +273,7 @@ ifeq "$(LLVM_LTO)" "1"
endif
endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fdebug-prefix-map=$(CURDIR)=llvm_mode -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_DEBUG_PREFIX = -fdebug-prefix-map="$(CURDIR)=llvm_mode"
else
AFL_CLANG_DEBUG_PREFIX =
endif
IS_IOS := $(findstring ios, $(shell $(CC) --version 2>/dev/null))
CFLAGS ?= -O3 -funroll-loops -fPIC
# -D_FORTIFY_SOURCE=1
@ -288,11 +285,15 @@ CFLAGS_SAFE := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sig
-DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
-DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) \
-Wno-unused-function $(AFL_CLANG_DEBUG_PREFIX)
-Wno-unused-function
ifndef LLVM_DEBUG
CFLAGS_SAFE += -Wno-deprecated
endif
ifdef IOS_SDK_PATH
override CFLAGS_SAFE += -isysroot $(IOS_SDK_PATH)
endif
ifdef CODE_COVERAGE
override CFLAGS_SAFE += -D__AFL_CODE_COVERAGE=1
override LDFLAGS += -ldl
@ -310,6 +311,10 @@ override CXXFLAGS += -Wall -g -I ./include/ \
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros -Wno-deprecated-copy-with-dtor \
-DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR)
ifdef IOS_SDK_PATH
override CXXFLAGS += -isysroot $(IOS_SDK_PATH)
endif
ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" ""
CLANG_CFL = -I$(shell $(LLVM_CONFIG) --includedir)
endif
@ -356,7 +361,7 @@ ifeq "$(TEST_MMAP)" "1"
LDFLAGS += -Wno-deprecated-declarations
endif
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so ./injection-pass.so
# If prerequisites are not given, warn, do not build anything, and exit with code 0
@ -431,29 +436,44 @@ ifeq "$(LLVM_LTO)" "1"
@ln -sf afl-cc ./afl-lto++
endif
endif
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_MIN_4_0_1)" "0"
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
endif
$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_13_OK)" "1"
-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
endif
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
ifeq "$(LLVM_LTO)" "1"
$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
endif
./afl-ld-lto: src/afl-ld-lto.c
ifeq "$(LLVM_LTO)" "1"
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
endif
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
@ -462,31 +482,58 @@ ifeq "$(LLVM_LTO)" "1"
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
endif
# laf
./split-switches-pass.so: instrumentation/split-switches-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./compare-transform-pass.so: instrumentation/compare-transform-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./split-compares-pass.so: instrumentation/split-compares-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
# /laf
./cmplog-routines-pass.so: instrumentation/cmplog-routines-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./cmplog-switches-pass.so: instrumentation/cmplog-switches-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
./injection-pass.so: instrumentation/injection-pass.cc instrumentation/afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
.PHONY: document
document:
@ -509,6 +556,9 @@ document:
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
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)
ifdef IS_IOS
@ldid -Sentitlements.plist test-instr && echo "[+] Signed test-instr" || echo "[-] Failed to sign test-instr"
endif
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

@ -2,9 +2,9 @@
<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.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.32c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.31c
GitHub version: 4.32c
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -16,7 +16,6 @@ AFL++ is maintained by:
* Andrea Fioraldi <andreafioraldi@gmail.com>
* Heiko "hexcoder-" Eissfeldt <heiko.eissfeldt@hexco.de>
* frida_mode is maintained by @Worksbutnottested
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
Originally developed by Michal "lcamtuf" Zalewski.
@ -230,7 +229,8 @@ 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
Ziqiao Kong Ryan Berger
Sangjun Park
```
</details>

View File

@ -331,7 +331,7 @@ BEGIN {
}
if (0 == system ( "grep -aq AFL_DUMP_MAP_SIZE " target_bin )) {
echo "[!] Trying to obtain the map size of the target ..."
print "[!] Trying to obtain the map size of the target ..."
get_map_size = "AFL_DUMP_MAP_SIZE=1 " target_bin
get_map_size | getline mapsize
close(get_map_size)
@ -432,7 +432,7 @@ BEGIN {
} else {
stat_format = "-f '%z %N'" # *BSD, MacOS
}
cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'"
cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'"
#cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r"
#cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r"
#cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"

View File

@ -121,6 +121,7 @@ kernel.sched_child_runs_first=1
kernel.sched_autogroup_enabled=1
kernel.sched_migration_cost_ns=50000000
kernel.sched_latency_ns=250000000
vm.swappiness=10
EOF
}
@ -129,7 +130,7 @@ EOF
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
echo "Configuring performance boot options"
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
fi

View File

@ -41,6 +41,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
sysctl -w kernel.sched_autogroup_enabled=1
sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null
sysctl -w kernel.sched_latency_ns=250000000 2>/dev/null
sysctl -w vm.swappiness=10 2>/dev/null
echo never > /sys/kernel/mm/transparent_hugepage/enabled
test -e /sys/devices/system/cpu/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/scaling_governor
test -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor
@ -54,7 +55,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
echo
dmesg | grep -E -q 'noibrs pcid nopti' || {
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"'
echo
}
echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.

View File

@ -3,6 +3,25 @@
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.32c (release)
- Fixed a bug where after a fast restart of a full fuzzed corpus afl-fuzz
terminates with "need at least one valid input seed that does not crash"
- Small improvements to afl-*-config
- afl-fuzz:
- memory leak fixes by @kcwu - thanks!
- many more nits and small memory saves thanks to @kcwu
- remove deprecated files from queue/.state
- fix bitmap update function if no current trace is present
- fix for afl_custom_queue_get
- various small nits
- afl-cc:
- fix pass support for LLVM 20 (passes were run too early)
- dropped plugin support for LLVM 13
- fix AFL_OLD_FORKSERVER
- various minor fixes
- frida_mode:
- fixes for new MacOS + M4 hardware
### Version ++4.31c (release)
- SAND mode added (docs/SAND.md) for more effecient fuzzing with sanitizers
@ -10,7 +29,7 @@
- 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.
it.
- Python 3.13+ support
- loose file and shared memory permissions on Android and iPhone
- afl-cc:
@ -22,7 +41,6 @@
- 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:

View File

@ -236,7 +236,7 @@ If you find an interesting or important question missing, submit it via
[AFLFast](https://github.com/mboehme/aflfast), however, modified to be more
effective and several more modes added.
The most effective modes are `-p fast` (default) and `-p explore`.
The most effective modes are `-p explore` (default) and `-p fast`.
If you fuzz with several parallel afl-fuzz instances, then it is beneficial
to assign a different schedule to each instance, however the majority should

View File

@ -169,3 +169,47 @@ and definitely don't look POSIX-compliant. This means two things:
User emulation mode of QEMU does not appear to be supported on macOS, so
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
works on both x86 and arm64 macOS boxes.
## iOS on arm64 and arm64e
**Option 1: Compilation on jailbroken iOS (recommended)**
To compile directly on a jailbroken iOS device, it is recommended to use a jailbreak that supports Procursus,
as Procursus provides up-to-date pre-built packages for the required tools.
Ensure `openssh` is installed on your iOS device, then SSH into it.
Install the following packages:
```shell
sudo apt install wget git make cmake clang gawk llvm ldid coreutils build-essential xz-utils
```
Configure the environment for compilation:
```shell
export IOS_SDK_PATH="/usr/share/SDKs/iPhoneOS.sdk"
export CC=clang
export CXX=clang++
```
Then build following the general Linux instructions.
**Option 2: Cross-Compilation on macOS for Jailbroken iOS**
In addition to the packages required for a macOS build, install `ldid` for signing binaries:
```shell
brew install ldid-procursus
```
Configure the environment for compilation:
```shell
export IOS_SDK_PATH="$(xcrun --sdk iphoneos --show-sdk-path)"
export CC="$(xcrun --sdk iphoneos -f clang) -target arm64-apple-ios14.0"
export CXX="$(xcrun --sdk iphoneos -f clang++) -target arm64-apple-ios14.0"
export HOST_CC=cc
```
Then build following the general Linux instructions.
Finally, transfer the binaries to your iOS device.

View File

@ -385,10 +385,6 @@ there are several things to look at:
subsequent iterations (e.g., due to incomplete clean-up or reinitialization of
the state) and that most of the fuzzing effort goes to waste.
The paths where variable behavior is detected are marked with a matching entry
in the `<out_dir>/queue/.state/variable_behavior/` directory, so you can look
them up easily.
### CPU load
```

View File

@ -107,6 +107,7 @@ fairly broad use of environment variables instead:
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"
. `AFL_USE_RTSAN` . activates the realtime sanitizer (realtime violations in deterministic run time constraints). (clang 20 minimum)
- 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

View File

@ -106,6 +106,7 @@ Among others, the following features and patches have been integrated:
* Win32 PE binary-only fuzzing with QEMU and Wine
* AFLfast's power schedules by Marcel Böhme:
[https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
* The fast deterministic stage by Han Zheng: [https://github.com/hexhive/mendelFuzz-Artifact/](https://github.com/hexhive/mendelFuzz-Artifact/)
* The MOpt mutator:
[https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
* LLVM mode Ngram coverage by Adrian Herrera

View File

@ -247,6 +247,12 @@ CFISAN. You might need to experiment which sanitizers you can combine in a
target (which means more instances can be run without a sanitized target, which
is more effective).
Note that some sanitizers (MSAN and LSAN) exit with a particular exit code
instead of aborting. afl-fuzz treats these exit codes as a crash when these
sanitizers are enabled. If the target uses these exit codes there could be false
positives among the saved crashes. LSAN uses exit code 23 and MSAN uses exit
code 86.
### d) Modifying the target
If the target has features that make fuzzing more difficult, e.g., checksums,
@ -496,6 +502,8 @@ Note:
protection against attacks! So set strong firewall rules and only expose SSH
as a network service if you use these (which is highly recommended).
If you execute afl-fuzz in a Docker container, it is recommended to pass [`--cpuset-cpus`](https://docs.docker.com/engine/containers/resource_constraints/#configure-the-default-cfs-scheduler) option with free CPU cores to docker daemon when starting the container, or pass `AFL_NO_AFFINITY` to afl-fuzz. This is due to the fact that AFL++ will bind to a free CPU core by default, while Docker container will prevent AFL++ instance from seeing processes in other containers or host, which leads to all AFL++ instances trying to bind the same CPU core.
If you have an input corpus from [step 2](#2-preparing-the-fuzzing-campaign),
then specify this directory with the `-i` option. Otherwise, create a new
directory and create a file with any content as test data in there.
@ -627,8 +635,8 @@ The other secondaries should be run like this:
* 40% should run with `-P explore` and 20% with `-P exploit`
* If you use `-a` then set 30% of the instances to not use `-a`; if you did
not set `-a` (why??), then set 30% to `-a ascii` and 30% to `-a binary`.
* run each with a different power schedule, recommended are: `fast` (default),
`explore`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
* run each with a different power schedule, recommended are: `explore` (default),
`fast`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
the `-p` option, e.g., `-p explore`. See the
[FAQ](FAQ.md#what-are-power-schedules) for details.

29
entitlements.plist Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>research.com.apple.license-to-operate</key> <true/>
<key>application-identifier</key> <string>aflplusplus</string>
<key>com.apple.asl.access_as_root</key> <true/>
<key>com.apple.backboardd.launchapplications</key> <true/>
<key>com.apple.companionappd.connect.allow</key> <true/>
<key>com.apple.multitasking.termination</key> <true/>
<key>com.apple.private.security.container-required</key> <false/>
<key>com.apple.seld.cm</key> <true/>
<key>com.apple.sh</key> <true/>
<key>com.apple.private.thread-set-state</key> <true/>
<key>com.apple.private.cs.debugger</key> <true/>
<key>com.apple.springboard.debugapplications</key> <true/>
<key>com.apple.springboard.launchapplications</key> <true/>
<key>com.apple.springboard.opensensitiveurl</key> <true/>
<key>dynamic-codesigning</key> <true/>
<key>get-task-allow</key> <true/>
<key>platform-application</key> <true/>
<key>run-unsigned-code</key> <true/>
<key>task_for_pid-allow</key> <true/>
<key>com.apple.private.skip-library-validation</key> <true/>
<key>com.apple.private.amfi.can-load-cdhash</key> <true/>
<key>com.apple.private.amfi.can-execute-cdhash</key> <true/>
<key>com.apple.private.security.no-container</key> <true/>
</dict>
</plist>

View File

@ -19,11 +19,15 @@ TARGET_CC?=$(CC)
TARGET_CXX?=$(CXX)
HOST_CC?=$(CC)
HOST_CXX?=$(CXX)
IS_ANDROID:=$(findstring android, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_x86:=$(findstring i686, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_x86_64:=$(findstring x86_64, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_ARM:=$(findstring arm, $(shell $(TARGET_CC) --version 2>/dev/null))
IS_ARM64:=$(findstring aarch64, $(shell $(TARGET_CC) --version 2>/dev/null))
TARGET_CC_INFO=$(shell $(TARGET_CC) --version)
IS_IOS:=$(findstring ios, $(TARGET_CC_INFO))
IS_SIMULATOR:=$(findstring sim, $(TARGET_CC_INFO))
IS_ANDROID:=$(findstring android, $(TARGET_CC_INFO))
IS_x86:=$(findstring i686, $(TARGET_CC_INFO))
IS_x86_64:=$(findstring x86_64, $(TARGET_CC_INFO))
IS_ARM:=$(findstring arm, $(TARGET_CC_INFO))
IS_ARM64E:=$(findstring arm64e, $(TARGET_CC_INFO))
IS_ARM64 := $(or $(findstring aarch64,$(TARGET_CC_INFO)), $(findstring arm64,$(TARGET_CC_INFO)))
CFLAGS+=-fPIC \
-D_GNU_SOURCE \
-D_FORTIFY_SOURCE=2 \
@ -95,7 +99,24 @@ endif
GUM_ARCH="-$(ARCH)"
ifeq "$(shell uname)" "Darwin"
ifdef IS_IOS
OS:=ios
ifdef IS_SIMULATOR
ifdef IS_x86_64
ARCH := x86_64-simulator
else ifdef IS_ARM64
ARCH := arm64-simulator
endif
else
ifdef IS_ARM64E
ARCH := arm64e
else ifdef IS_ARM64
ARCH := arm64
endif
endif
override CFLAGS += -isysroot $(IOS_SDK_PATH)
override LDFLAGS += -L$(IOS_SDK_PATH)/usr/lib
else ifeq "$(shell uname)" "Darwin"
OS:=macos
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
GUM_ARCH:=""
@ -165,10 +186,32 @@ ifndef OS
$(error "Operating system unsupported")
endif
GUM_DEVKIT_VERSION=16.0.11
GUM_DEVKIT_VERSION=16.1.11
GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
ifeq ($(OS),macos)
# Extract the major version
GUM_VERSION_MAJOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/\..*//')
# Extract the minor version (assumes format "MAJOR.MINOR[.PATCH...]")
GUM_VERSION_MINOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/^[^.]*\.//; s/\..*//')
# Evaluate the version condition in a separate shell call
IS_GUM_16_6_PLUS := $(shell \
if (( $(GUM_VERSION_MAJOR) > 16 || ( $(GUM_VERSION_MAJOR) == 16 && $(GUM_VERSION_MINOR) >= 6 ) )); then \
echo 1; \
fi)
else
IS_GUM_16_6_PLUS := $(shell VERSION="$(GUM_DEVKIT_VERSION)"; \
MAJOR=$${VERSION%%.*}; \
MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \
if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \
echo 1; \
fi)
endif
CFLAGS += $(if $(IS_GUM_16_6_PLUS),-DGUM_16_6_PLUS)
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
ifdef FRIDA_SOURCE
GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gumjs-1.0.a
@ -373,6 +416,11 @@ $(AFL_PERFORMANCE_OBJ): $(AFL_PERFORMANCE_SRC)
$(BIN2C): $(BIN2C_SRC)
$(HOST_CC) -D_GNU_SOURCE -o $@ $<
ifdef IS_IOS
ifeq ($(HOST_CC),$(TARGET_CC))
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
endif
$(JS_SRC): $(JS) $(BIN2C)| $(BUILD_DIR)
cd $(JS_DIR) && $(BIN2C) api_js $(JS) $@
@ -413,8 +461,10 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL
$(TRACE_LDFLAGS) \
$(LDFLAGS) \
$(LDSCRIPT) \
-o $@ \
-o $@
ifdef IS_IOS
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
cp -v $(FRIDA_TRACE) $(ROOT)
$(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) $(AFL_PERFORMANCE_OBJ) GNUmakefile | $(BUILD_DIR)
@ -430,9 +480,15 @@ $(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $
$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR)
$(TARGET_CC) $(CFLAGS) $(LDFLAGS) -I $(FRIDA_BUILD_DIR) $< -o $@
ifdef IS_IOS
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
$(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR)
$(TARGET_CC) $(CFLAGS) $(LDFLAGS) $< -o $@
ifdef IS_IOS
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)

View File

@ -27,6 +27,27 @@ void asan_init(void) {
}
#ifdef GUM_16_6_PLUS
static gboolean asan_exclude_module(GumModule *module, gpointer user_data) {
gchar *symbol_name = (gchar *)user_data;
GumAddress address;
const GumMemoryRange *range = gum_module_get_range(module);
address = gum_module_find_export_by_name(module, symbol_name);
if (address == 0) { return TRUE; }
/* If the reported address of the symbol is outside of the range of the module
* then ignore it */
if (address < range->base_address) { return TRUE; }
if (address > (range->base_address + range->size)) { return TRUE; }
ranges_add_exclude((GumMemoryRange *)range);
return FALSE;
}
#else
static gboolean asan_exclude_module(const GumModuleDetails *details,
gpointer user_data) {
@ -50,6 +71,8 @@ static gboolean asan_exclude_module(const GumModuleDetails *details,
}
#endif
void asan_exclude_module_by_symbol(gchar *symbol_name) {
gum_process_enumerate_modules(asan_exclude_module, symbol_name);

View File

@ -39,6 +39,25 @@ typedef struct {
static guint64 text_base = 0;
static guint64 text_limit = 0;
#ifdef GUM_16_6_PLUS
static gboolean lib_find_exe(GumModule *module, gpointer user_data) {
lib_details_t *lib_details = (lib_details_t *)user_data;
const gchar *name = gum_module_get_name(module);
const gchar *path = gum_module_get_path(module);
const GumMemoryRange *range = gum_module_get_range(module);
strncpy(lib_details->name, name, PATH_MAX);
strncpy(lib_details->path, path, PATH_MAX);
lib_details->name[PATH_MAX] = '\0';
lib_details->path[PATH_MAX] = '\0';
lib_details->base_address = range->base_address;
lib_details->size = range->size;
return FALSE;
}
#else
static gboolean lib_find_exe(const GumModuleDetails *details,
gpointer user_data) {
@ -54,6 +73,8 @@ static gboolean lib_find_exe(const GumModuleDetails *details,
}
#endif
static void lib_validate_hdr(Elf_Ehdr *hdr) {
if (hdr->e_ident[0] != ELFMAG0) FFATAL("Invalid e_ident[0]");

View File

@ -12,6 +12,25 @@ extern void gum_darwin_enumerate_modules(mach_port_t task,
static guint64 text_base = 0;
static guint64 text_limit = 0;
#ifdef GUM_16_6_PLUS
static gboolean lib_get_main_module(GumModule *module, gpointer user_data) {
GumDarwinModule **ret = (GumDarwinModule **)user_data;
const gchar *path = gum_module_get_path(module);
const GumMemoryRange *range = gum_module_get_range(module);
GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory(
path, mach_task_self(), range->base_address, GUM_DARWIN_MODULE_FLAGS_NONE,
NULL);
FVERBOSE("Found main module: %s", darwin_module->name);
*ret = darwin_module;
return FALSE;
}
#else
static gboolean lib_get_main_module(const GumModuleDetails *details,
gpointer user_data) {
@ -28,6 +47,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
}
#endif
gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
gpointer user_data) {

View File

@ -295,6 +295,8 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
* CALL instrument_afl_persistent_loop
* CALL hook (optionally)
* RESTORE REGS
* CALL INSTRUMENTED PERSISTENT FUNC
* JMP loop
* INSTRUMENTED PERSISTENT FUNC
*/
@ -302,15 +304,25 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
FVERBOSE("Persistent loop reached");
/* This is the location our epilogue should be written below */
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs);
/* Store a pointer to where we should return for our next iteration */
/*
* Store a pointer to where we should return for our next iteration.
* This is the location our epilogue should branch to
*/
persistent_loop = gum_arm64_writer_cur(cw);
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
gconstpointer loop = cw->code + 1;
gum_arm64_writer_put_label(cw, loop);
/*
* call __afl_persistent_loop which will _exit if we have reached our
* loop count. Also reset our previous_pc
*/
instrument_afl_persistent_loop(cw);
/* Optionally call the persistent hook */
@ -319,6 +331,27 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/*
* Call our original code, that way we regain control if our target
* function returns without reaching the epilogue as an additional
* safety net
*/
gum_arm64_writer_put_bl_label(cw, original);
/*
* Return for our next iteration if our original function returns
* and control hasn't reached the epilogue for some reason
*/
gum_arm64_writer_put_b_label(cw, loop);
/*
* The original code for our target function will be emitted
* immediately following this
*/
gum_arm64_writer_put_label(cw, original);
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
}

View File

@ -263,8 +263,13 @@ static int prefetch_on_fork(void) {
static void prefetch_hook_fork(void) {
#ifdef GUM_16_6_PLUS
void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_global_export_by_name("fork"));
#else
void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
#endif
intercept_hook(fork_addr, prefetch_on_fork, NULL);
}

View File

@ -116,6 +116,29 @@ static void convert_address_token(gchar *token, GumMemoryRange *range) {
}
#ifdef GUM_16_6_PLUS
static gboolean convert_name_token_for_module(GumModule *module,
gpointer user_data) {
convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data;
const GumMemoryRange *range = gum_module_get_range(module);
const gchar *path = gum_module_get_path(module);
if (path == NULL) { return true; };
if (!g_str_has_suffix(path, ctx->suffix)) { return true; };
FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x %s",
ctx->suffix, range->base_address, range->base_address + range->size,
path);
*ctx->range = *range;
ctx->done = true;
return false;
}
#else
static gboolean convert_name_token_for_module(const GumModuleDetails *details,
gpointer user_data) {
@ -135,6 +158,8 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details,
}
#endif
static void convert_name_token(gchar *token, GumMemoryRange *range) {
gchar *suffix = g_strconcat("/", token, NULL);

View File

@ -353,6 +353,8 @@ enum {
};
#define FAST_RESUME_VERSION 0x01000000
/* Python stuff */
#ifdef USE_PYTHON
@ -719,6 +721,8 @@ typedef struct afl_state {
struct queue_entry **top_rated; /* Top entries for bitmap bytes */
u32 **top_rated_candidates; /* Candidate IDs per bitmap index */
struct extra_data *extras; /* Extra tokens to fuzz with */
u32 extras_cnt; /* Total number of tokens read */
@ -860,6 +864,8 @@ typedef struct afl_state {
struct skipdet_global *skipdet_g;
s64 last_scored_idx; /* Index of the last queue entry re-scored */
#ifdef INTROSPECTION
char mutation[8072];
char m_tmp[4096];
@ -1182,13 +1188,13 @@ void deinit_py(void *);
/* Queue */
void mark_as_det_done(afl_state_t *, struct queue_entry *);
void mark_as_variable(afl_state_t *, struct queue_entry *);
void mark_as_redundant(afl_state_t *, struct queue_entry *, u8);
void add_to_queue(afl_state_t *, u8 *, u32, u8);
void destroy_queue(afl_state_t *);
void update_bitmap_score(afl_state_t *, struct queue_entry *);
void update_bitmap_score(afl_state_t *, struct queue_entry *, bool);
void cull_queue(afl_state_t *);
u32 calculate_score(afl_state_t *, struct queue_entry *);
void recalculate_all_scores(afl_state_t *);
void update_bitmap_rescore(afl_state_t *, struct queue_entry *, u32);
/* Bitmap */
@ -1338,7 +1344,6 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
"/dev/urandom");
// srandom(afl->rand_seed[0]);
afl->rand_cnt = (RESEED_RNG / 2) + (afl->rand_seed[1] % RESEED_RNG);
}
@ -1452,6 +1457,18 @@ static inline int permissive_create(afl_state_t *afl, const char *fn) {
}
static inline void bitmap_set(u8 *map, u32 index) {
map[index / 8] |= (1u << (index % 8));
}
static inline u8 bitmap_read(u8 *map, u32 index) {
return (map[index / 8] >> (index % 8)) & 1;
}
#if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1
#endif

View File

@ -31,7 +31,8 @@ int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
if (__cmd == IPC_RMID) {
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
struct ashmem_pin pin = {0, length};
unsigned int safe_length = length >= 0 ? length : 0;
struct ashmem_pin pin = {0, safe_length};
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
close(__shmid);

View File

@ -37,11 +37,12 @@
enum SanitizerAbstraction {
SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the
// most sensitive
UNIQUE_TRACE,
SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate
// sensitive and default for SAND. Not missing bugs.
UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive
// and not missing bugs.
COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the
// least sensitive
// least sensitive at a risk of missing ~20% bugs.
};

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.31c"
#define VERSION "++4.32c"
/******************************************************
* *
@ -171,7 +171,8 @@
#define EXEC_TM_ROUND 20U
/* 64bit arch MACRO */
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__) || \
(defined(__riscv) && __riscv_xlen == 64))
#define WORD_SIZE_64 1
#endif
@ -200,8 +201,8 @@
/* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500U
#define KEEP_UNIQUE_CRASH 10000U
#define KEEP_UNIQUE_HANG 512U
#define KEEP_UNIQUE_CRASH 25600U
/* Baseline number of random tweaks during a single 'havoc' stage: */

View File

@ -1,6 +1,12 @@
#ifndef _COVERAGE_H
#define _COVERAGE_H
#include "config.h"
#include "types.h"
#define _AFL_INTSIZEVAR u32
u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end);
u32 classify_word(u32 word);
@ -110,3 +116,5 @@ inline u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end) {
}
#endif

View File

@ -1,6 +1,12 @@
#ifndef _COVERAGE_H
#define _COVERAGE_H
#include "config.h"
#include "types.h"
#define _AFL_INTSIZEVAR u64
#if (defined(__AVX512F__) && defined(__AVX512DQ__)) || defined(__AVX2__)
#include <immintrin.h>
#endif
@ -72,22 +78,6 @@ 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) {
@ -134,7 +124,7 @@ inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
/* All bytes are zero. */
if (likely(mask == 0xff)) continue;
/* Look for nonzero bytes and check for new bits. */
/* Look for nonzero bytes and check for new bits. */
#define UNROLL(x) \
if (unlikely(!(mask & (1 << x)) && classify_word(current[x]) & virgin[x])) \
return 1
@ -208,3 +198,5 @@ inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
#endif
#endif

View File

@ -331,6 +331,7 @@ static inline const char *colorfilter(const char *x) {
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, (u32)__LINE__); \
fflush(stdout); \
abort(); \
\
} while (0)

View File

@ -137,6 +137,8 @@ typedef struct afl_forkserver {
u8 last_kill_signal; /* Signal that killed the child */
u8 last_exit_code; /* Child exit code if counted as a crash */
bool use_shmem_fuzz; /* use shared mem for test cases */
bool support_shmem_fuzz; /* set by afl-fuzz */
@ -155,7 +157,7 @@ typedef struct afl_forkserver {
bool no_unlink; /* do not unlink cur_input */
bool uses_asan; /* Target uses ASAN? */
u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */
bool debug; /* debug mode? */

View File

@ -3169,7 +3169,7 @@ static xxh_u32 XXH32_avalanche(xxh_u32 hash) {
*/
static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8 *ptr,
size_t len, XXH_alignment align) {
\
#define XXH_PROCESS1 \
do { \
\

View File

@ -79,11 +79,11 @@ LLVM 13 to 19 should be available in all current Linux repositories.
That part is easy.
Just set `LLVM_CONFIG` to the llvm-config-VERSION and build AFL++, e.g. for
LLVM 15:
LLVM 19:
```
cd ~/AFLplusplus
export LLVM_CONFIG=llvm-config-15
export LLVM_CONFIG=llvm-config-19
make
sudo make install
```
@ -96,7 +96,7 @@ Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST ->
[README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov
(AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work.
Example (note that you might need to add the version, e.g. `llvm-ar-15`:
Example (note that you might need to add the version, e.g. `llvm-ar-19`:
```
CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure

View File

@ -2005,8 +2005,11 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
}
extra_ctx_inst += inst_in_this_func * (call_counter - 1);
afl_global_id += extra_ctx_inst;
uint32_t extra_ctx_inst_in_this_func =
inst_in_this_func * (call_counter - 1);
extra_ctx_inst += extra_ctx_inst_in_this_func;
afl_global_id += extra_ctx_inst_in_this_func;
}

View File

@ -226,20 +226,28 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM,
OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(ModuleSanitizerCoverageAFL());
});
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(ModuleSanitizerCoverageAFL());
});
#endif
}};
}

View File

@ -891,10 +891,10 @@ 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. */
if (!__afl_old_forkserver) {
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (!__afl_old_forkserver) {
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {

View File

@ -121,15 +121,16 @@ extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo 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
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(AFLCoverage());

View File

@ -130,15 +130,16 @@ 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
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(CompareTransform());

View File

@ -190,15 +190,16 @@ 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
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(SplitComparesTransform());

View File

@ -138,15 +138,17 @@ 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
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(SplitSwitchesTransform());

View File

@ -1 +1 @@
4d837f06d5
ef1cd9a8cb

View File

@ -40,7 +40,7 @@ ALPINE_ROOT=<your-alpine-sysroot-directory>
FUZZ=<your-path-to-the-code>
sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz
CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /fuzz
clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c
clang $(python3-config --embed --cflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c $(python3-config --embed --ldflags)
exit
```

View File

@ -110,8 +110,9 @@ static u8 count_class_lookup[256] = {
};
static void kill_child() {
static void kill_child(int signal) {
(void)signal;
if (fsrv.child_pid > 0) {
kill(fsrv.child_pid, fsrv.child_kill_signal);

View File

@ -181,15 +181,12 @@ typedef struct aflcc_state {
have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp,
have_flto, have_hidden, have_fortify, have_fcf, have_staticasan,
have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan,
have_cfisan;
have_cfisan, have_rtsan;
// u8 *march_opt;
u8 need_aflpplib;
int passthrough;
u8 use_stdin; /* dummy */
u8 *argvnull; /* dummy */
} aflcc_state_t;
void aflcc_state_init(aflcc_state_t *, u8 *argv0);
@ -256,7 +253,11 @@ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
#if LLVM_MAJOR < 16
#if LLVM_MAJOR < 15
insert_param(aflcc, "-fno-legacy-pass-manager");
#else
insert_param(aflcc, "-fexperimental-new-pass-manager");
#endif
#endif
insert_object(aflcc, pass, "-fpass-plugin=%s", 0);
#else
@ -1152,7 +1153,8 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) {
static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) {
if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) &&
(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) {
(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
aflcc->compiler_mode != LTO) {
FATAL("you cannot set CTX and CALLER together");
@ -1536,7 +1538,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
if (aflcc->plusplus_mode) {
insert_param(aflcc,
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
"__attribute__ ((weak)) = 1;"
"extern \"C\" void __afl_coverage_discard();"
"extern \"C\" void __afl_coverage_skip();"
"extern \"C\" void __afl_coverage_on();"
@ -1545,7 +1548,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
} else {
insert_param(aflcc,
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
"__attribute__ ((weak)) = 1;"
"void __afl_coverage_discard();"
"void __afl_coverage_skip();"
"void __afl_coverage_on();"
@ -2031,6 +2035,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
}
if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) {
insert_param(aflcc, "-fsanitize=realtime");
aflcc->have_rtsan = 1;
}
if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) {
if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) {
@ -2156,7 +2167,11 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) {
/* Since LLVM_MAJOR >= 13 we use new pass manager */
#if LLVM_MAJOR < 16
#if LLVM_MAJOR < 15
insert_param(aflcc, "-fno-legacy-pass-manager");
#else
insert_param(aflcc, "-fexperimental-new-pass-manager");
#endif
#endif
insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0);
@ -2971,7 +2986,8 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" AFL_USE_MSAN: activate memory sanitizer\n"
" AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
" AFL_USE_TSAN: activate thread sanitizer\n"
" AFL_USE_LSAN: activate leak-checker sanitizer\n");
" AFL_USE_LSAN: activate leak-checker sanitizer\n"
" AFL_USE_RTSAN: activate realtime sanitizer\n");
if (aflcc->have_gcc_plugin)
SAYF(
@ -3583,6 +3599,64 @@ int main(int argc, char **argv, char **envp) {
}
// We only support plugins with LLVM 14 onwards
#if LLVM_MAJOR < 14
if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE &&
aflcc->compiler_mode != GCC_PLUGIN) {
aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE;
aflcc->compiler_mode = LLVM;
}
if (aflcc->compiler_mode == LLVM) {
if (aflcc->cmplog_mode) {
WARNF("CMPLOG support requires LLVM 14+");
aflcc->cmplog_mode = 0;
}
if (getenv("AFL_LLVM_DICT2FILE")) {
WARNF("DICT2FILE support requires LLVM14+");
unsetenv("AFL_LLVM_DICT2FILE");
}
if (getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_ALL")) {
WARNF("AFL_LLVM_LAF support requires LLVM14+");
unsetenv("AFL_LLVM_LAF_SPLIT_SWITCHES");
unsetenv("AFL_LLVM_LAF_SPLIT_COMPARES");
unsetenv("AFL_LLVM_LAF_SPLIT_FLOATS");
unsetenv("AFL_LLVM_LAF_TRANSFORM_COMPARES");
unsetenv("AFL_LLVM_LAF_ALL");
}
if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
getenv("AFL_LLVM_INJECTIONS_SQL") ||
getenv("AFL_LLVM_INJECTIONS_LDAP") ||
getenv("AFL_LLVM_INJECTIONS_XSS")) {
WARNF("AFL_LLVM_INJECTIONS support requires LLVM14+");
unsetenv("AFL_LLVM_INJECTIONS_ALL");
unsetenv("AFL_LLVM_INJECTIONS_SQL");
unsetenv("AFL_LLVM_INJECTIONS_LDAP");
unsetenv("AFL_LLVM_INJECTIONS_XSS");
}
}
#endif
mode_notification(aflcc);
if (aflcc->debug) debugf_args(argc, argv);

View File

@ -977,11 +977,10 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
inline u64 get_cur_time(void) {
struct timeval tv;
struct timezone tz;
struct timeval tv;
// TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz);
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
@ -991,11 +990,10 @@ inline u64 get_cur_time(void) {
inline u64 get_cur_time_us(void) {
struct timeval tv;
struct timezone tz;
struct timeval tv;
// TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz);
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
@ -1006,7 +1004,7 @@ inline u64 get_cur_time_us(void) {
Will return buf for convenience. */
u8 *stringify_int(u8 *buf, size_t len, u64 val) {
\
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
do { \
\
@ -1170,7 +1168,7 @@ u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
Will return buf for convenience. */
u8 *u_stringify_int(u8 *buf, u64 val) {
\
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
do { \
\

View File

@ -258,7 +258,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->last_run_timed_out = false;
fsrv->debug = false;
fsrv->uses_crash_exitcode = false;
fsrv->uses_asan = false;
fsrv->uses_asan = 0;
#ifdef __AFL_CODE_COVERAGE
fsrv->persistent_trace_bits = NULL;
@ -2087,17 +2087,19 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
/* Did we crash?
In a normal case, (abort) WIFSIGNALED(child_status) will be set.
MSAN in uses_asan mode uses a special exit code as it doesn't support
MSAN & LSAN in uses_asan mode use special exit codes as they doesn't support
abort_on_error. On top, a user may specify a custom AFL_CRASH_EXITCODE.
Handle all three cases here. */
Handle all four cases here. */
if (unlikely(
/* A normal crash/abort */
(WIFSIGNALED(fsrv->child_status)) ||
/* special handling for msan and lsan */
(fsrv->uses_asan &&
(WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||
/* special handling for msan */
((fsrv->uses_asan & 4) &&
WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
/* special handling for lsan */
((fsrv->uses_asan & 2) &&
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR) ||
/* the custom crash_exitcode was returned by the target */
(fsrv->uses_crash_exitcode &&
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
@ -2106,6 +2108,10 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
fsrv->last_kill_signal =
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
/* For a special exit code, set last_exit_code to non-zero */
fsrv->last_exit_code =
WIFSIGNALED(fsrv->child_status) ? 0 : WEXITSTATUS(fsrv->child_status);
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(fsrv->persistent_record)) {

View File

@ -28,6 +28,45 @@
#include <stdio.h>
#include <stdlib.h>
#include "asanfuzz.h"
u16 count_class_lookup16[65536];
/* Destructively simplify trace by eliminating hit count information
and replacing it with 0x80 or 0x01 depending on whether the tuple
is hit or not. Called on every new crash or timeout, should be
reasonably fast. */
static const u8 simplify_lookup[256] = {
[0] = 1, [1 ... 255] = 128
};
/* Destructively classify execution counts in a trace. This is used as a
preprocessing step for any newly acquired traces. Called on every exec,
must be fast. */
static const u8 count_class_lookup8[256] = {
[0] = 0,
[1] = 1,
[2] = 2,
[3] = 4,
[4 ... 7] = 8,
[8 ... 15] = 16,
[16 ... 31] = 32,
[32 ... 127] = 64,
[128 ... 255] = 128
};
/* Import coverage processing routines. */
#ifdef WORD_SIZE_64
#include "coverage-64.h"
#else
#include "coverage-32.h"
#endif
#if !defined NAME_MAX
#define NAME_MAX _XOPEN_NAME_MAX
#endif
@ -146,36 +185,6 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
}
/* Destructively simplify trace by eliminating hit count information
and replacing it with 0x80 or 0x01 depending on whether the tuple
is hit or not. Called on every new crash or timeout, should be
reasonably fast. */
const u8 simplify_lookup[256] = {
[0] = 1, [1 ... 255] = 128
};
/* Destructively classify execution counts in a trace. This is used as a
preprocessing step for any newly acquired traces. Called on every exec,
must be fast. */
const u8 count_class_lookup8[256] = {
[0] = 0,
[1] = 1,
[2] = 2,
[3] = 4,
[4 ... 7] = 8,
[8 ... 15] = 16,
[16 ... 31] = 32,
[32 ... 127] = 64,
[128 ... 255] = 128
};
u16 count_class_lookup16[65536];
void init_count_class16(void) {
u32 b1, b2;
@ -193,14 +202,6 @@ void init_count_class16(void) {
}
/* Import coverage processing routines. */
#ifdef WORD_SIZE_64
#include "coverage-64.h"
#else
#include "coverage-32.h"
#endif
/* Check if the current execution path brings anything new to the table.
Update virgin bits to reflect the finds. Returns 1 if the only change is
the hit-count for a particular tuple; 2 if there are new tuples seen.
@ -461,18 +462,6 @@ void write_crash_readme(afl_state_t *afl) {
}
static inline void bitmap_set(u8 *map, u32 index) {
map[index / 8] |= (1u << (index % 8));
}
static inline u8 bitmap_read(u8 *map, u32 index) {
return (map[index / 8] >> (index % 8)) & 1;
}
/* Check if the result of an execve() during routine fuzzing is interesting,
save or queue the input test case for further analysis if so. Returns 1 if
entry is saved, 0 otherwise. */
@ -480,6 +469,8 @@ static inline u8 bitmap_read(u8 *map, u32 index) {
u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
u32 len, u8 fault) {
u8 classified = 0;
if (unlikely(len == 0)) { return 0; }
if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
@ -488,6 +479,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
classify_counts(&afl->fsrv);
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
classified = 1;
// Saturated increment
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
@ -501,8 +493,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
u8 fn[PATH_MAX];
u8 *queue_fn = "";
u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0,
need_hash = 1;
u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1;
s32 fd;
u64 cksum = 0;
u32 cksum_simplified = 0, cksum_unique = 0;
@ -519,7 +510,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv);
classified = 1;
need_hash = 0;
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@ -538,8 +528,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits,
afl->fsrv.map_size);
classify_counts_mem((u64 *)afl->san_fsrvs[0].trace_bits,
afl->fsrv.map_size);
simplify_trace(afl, afl->san_fsrvs[0].trace_bits);
// Note: Original SAND implementation used XXHASH32
@ -568,6 +556,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->san_binary_length) &&
likely(afl->san_abstraction == UNIQUE_TRACE)) {
// If schedule is not FAST..RARE, we need to classify counts here
// Note: SAND was evaluated under FAST schedule but should also work
// with other scedules.
if (!classified) {
classify_counts(&afl->fsrv);
classified = 1;
}
cksum_unique =
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) &&
@ -630,7 +628,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
/* If we are in coverage increasing abstraction and have fed input to
sanitizers, we are sure it has new bits.*/
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
if (classified) {
/* We could have classified the bits in SAND with UNIQUE_TRACE */
new_bits = has_new_bits(afl, afl->virgin_bits);
} else {
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
}
}
@ -645,7 +652,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
afl->san_case_status |= NON_COV_INCREASE_BUG;
fault = san_fault;
classified = new_bits;
goto may_save_fault;
}
@ -653,7 +659,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
}
fault = san_fault;
classified = new_bits;
save_to_queue:
@ -681,7 +686,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
#else
queue_fn = alloc_printf(
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
"%s/queue/id_%06u%s%s", afl->out_dir, afl->queued_items,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
@ -798,13 +803,6 @@ may_save_fault:
if (likely(!afl->non_instrumented_mode)) {
if (unlikely(!classified)) {
classify_counts(&afl->fsrv);
classified = 1;
}
simplify_trace(afl, afl->fsrv.trace_bits);
if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; }
@ -938,13 +936,6 @@ may_save_fault:
if (likely(!afl->non_instrumented_mode)) {
if (unlikely(!classified)) {
classify_counts(&afl->fsrv);
classified = 1;
}
simplify_trace(afl, afl->fsrv.trace_bits);
if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; }

View File

@ -354,6 +354,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
"Extra '%s' is too big (%s, limit is %s)", fn,
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
ck_free(fn);
continue;
}
@ -742,10 +743,8 @@ void save_auto(afl_state_t *afl) {
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
u8 *fn = alloc_printf(
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
u8 *fn =
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
s32 fd;

View File

@ -567,6 +567,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
}
free(nl);
continue;
}
@ -593,6 +594,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
if (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) {
if (first) PFATAL("Unable to access '%s'", fn2);
ck_free(fn2);
continue;
}
@ -634,19 +636,16 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
// as this could add duplicates of the startup input corpus
int fd = open(fn2, O_RDONLY);
if (fd < 0) {
ck_free(fn2);
ck_free(fn2);
continue;
}
if (fd < 0) { continue; }
u8 fault;
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem == MAP_FAILED) {
ck_free(fn2);
close(fd);
continue;
}
@ -668,7 +667,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
}
afl->foreign_syncs[iter].mtime = mtime_max;
if (mtime_max > afl->foreign_syncs[iter].mtime) {
afl->foreign_syncs[iter].mtime = mtime_max;
}
free(nl); /* not tracked */
}
@ -749,8 +753,6 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
// if (getenv("MYTEST")) afl->in_place_resume = 1;
if (nl_cnt) {
u32 done = 0;
@ -1042,6 +1044,47 @@ void perform_dry_run(afl_state_t *afl) {
if (afl->crash_mode) { break; }
const u8 *msg_exit_code = "";
if (afl->fsrv.uses_asan && !afl->fsrv.last_kill_signal) {
if ((afl->fsrv.uses_asan & 4) &&
afl->fsrv.last_exit_code == MSAN_ERROR) {
msg_exit_code =
" - The test case terminated with the exit code that is "
"used by MSAN to\n"
" indicate an error. This is counted as a crash by "
"afl-fuzz because you\n"
" have compiled the target with MSAN enabled. This could "
"be a false\n"
" positive if the program returns this exit code under "
"normal operation.\n"
" In that case, either disable MSAN or change the test "
"case or program\n"
" to avoid generating this exit code.\n\n";
} else if ((afl->fsrv.uses_asan & 2) &&
afl->fsrv.last_exit_code == LSAN_ERROR) {
msg_exit_code =
" - The test case terminated with the exit code that is "
"used by LSAN to\n"
" indicate an error. This is counted as a crash by "
"afl-fuzz because you\n"
" have compiled the target with LSAN enabled. This could "
"be a false\n"
" positive if the program returns this exit code under "
"normal operation.\n"
" In that case, either disable LSAN or change the test "
"case or program\n"
" to avoid generating this exit code.\n\n";
}
}
if (afl->fsrv.mem_limit) {
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
@ -1056,6 +1099,7 @@ void perform_dry_run(afl_state_t *afl) {
" so, please remove it. The fuzzer should be seeded with "
"interesting\n"
" inputs - but not ones that cause an outright crash.\n\n"
"%s"
" - The current memory limit (%s) is too low for this "
"program, causing\n"
@ -1085,6 +1129,7 @@ void perform_dry_run(afl_state_t *afl) {
"other options\n"
" fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n",
msg_exit_code,
stringify_mem_size(val_buf, sizeof(val_buf),
afl->fsrv.mem_limit << 20),
afl->fsrv.mem_limit - 1);
@ -1101,6 +1146,7 @@ void perform_dry_run(afl_state_t *afl) {
" so, please remove it. The fuzzer should be seeded with "
"interesting\n"
" inputs - but not ones that cause an outright crash.\n\n"
"%s"
" - In QEMU persistent mode the selected address(es) for the "
"loop are not\n"
@ -1113,7 +1159,8 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n"
" fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n");
"troubleshooting tips.\n",
msg_exit_code);
}
@ -2180,10 +2227,17 @@ int check_main_node_exists(afl_state_t *afl) {
fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name);
int res = access(fn, F_OK);
free(fn);
if (res == 0) return 1;
if (res == 0) {
closedir(sd);
return 1;
}
}
closedir(sd);
return 0;
}
@ -2267,18 +2321,6 @@ void setup_dirs_fds(afl_state_t *afl) {
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
/* The set of paths currently deemed redundant. */
tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
/* The set of paths showing variable behavior. */
tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
/* Sync directory for keeping track of cooperating fuzzers. */
if (afl->sync_id) {
@ -2601,7 +2643,7 @@ void check_cpu_governor(afl_state_t *afl) {
" afl-fuzz. To keep things moving, run these commands as root:\n\n"
" cd /sys/devices/system/cpu\n"
" echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
" echo performance | sudo tee cpu*/cpufreq/scaling_governor\n\n"
" You can later go back to the original state by replacing "
"'performance'\n"
@ -3118,11 +3160,23 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
if (afl_memmem(f_data, f_len, "__asan_init", 11) ||
afl_memmem(f_data, f_len, "__msan_init", 11) ||
afl_memmem(f_data, f_len, "__lsan_init", 11)) {
afl->fsrv.uses_asan = 0;
afl->fsrv.uses_asan = 1;
if (afl_memmem(f_data, f_len, "__asan_init", 11)) {
afl->fsrv.uses_asan |= 1;
}
if (afl_memmem(f_data, f_len, "__lsan_init", 11)) {
afl->fsrv.uses_asan |= 2;
}
if (afl_memmem(f_data, f_len, "__msan_init", 11)) {
afl->fsrv.uses_asan |= 4;
}

View File

@ -636,7 +636,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
q->len = out_len;
memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size);
update_bitmap_score(afl, q);
update_bitmap_score(afl, q, true);
}

View File

@ -356,7 +356,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (el->afl_custom_queue_get &&
!el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
return 1;
/* Abandon the entry and return that we skipped it.
If we don't do this then when the entry is smallest_favored then
we get caught in an infinite loop calling afl_custom_queue_get
on smallest_favored */
ret_val = 1;
goto abandon_entry;
}
@ -634,7 +639,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_cur_byte = afl->stage_cur >> 3;
if (!skip_eff_map[afl->stage_cur_byte]) continue;
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -754,7 +759,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_cur_byte = afl->stage_cur >> 3;
if (!skip_eff_map[afl->stage_cur_byte]) continue;
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -793,7 +798,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_cur_byte = afl->stage_cur >> 3;
if (!skip_eff_map[afl->stage_cur_byte]) continue;
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -837,7 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_cur_byte = afl->stage_cur;
if (!skip_eff_map[afl->stage_cur_byte]) continue;
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -858,7 +863,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
for (i = 0; i < len; i++) {
if (skip_eff_map[i]) afl->blocks_eff_select += 1;
if (bitmap_read(skip_eff_map, i)) afl->blocks_eff_select += 1;
}
@ -887,7 +892,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -930,7 +935,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -983,7 +988,7 @@ skip_bitflip:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1067,7 +1072,7 @@ skip_bitflip:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1197,7 +1202,7 @@ skip_bitflip:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1331,7 +1336,7 @@ skip_arith:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1391,7 +1396,7 @@ skip_arith:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1479,7 +1484,7 @@ skip_arith:
/* Let's consult the effector map... */
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1573,7 +1578,7 @@ skip_interest:
u32 last_len = 0;
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1642,7 +1647,7 @@ skip_interest:
for (i = 0; i <= (u32)len; ++i) {
if (!skip_eff_map[i % len]) continue;
if (!bitmap_read(skip_eff_map, i % len)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1708,7 +1713,7 @@ skip_user_extras:
u32 last_len = 0;
if (!skip_eff_map[i]) continue;
if (!bitmap_read(skip_eff_map, i)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1768,7 +1773,7 @@ skip_user_extras:
for (i = 0; i <= (u32)len; ++i) {
if (!skip_eff_map[i % len]) continue;
if (!bitmap_read(skip_eff_map, i % len)) continue;
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }

View File

@ -440,30 +440,6 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
}
/* Mark as variable. Create symlinks if possible to make it easier to examine
the files. */
void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
char fn[PATH_MAX];
char ldest[PATH_MAX];
char *fn_name = strrchr((char *)q->fname, '/') + 1;
sprintf(ldest, "../../%s", fn_name);
sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
if (symlink(ldest, fn)) {
s32 fd = permissive_create(afl, fn);
if (fd >= 0) { close(fd); }
}
q->var_behavior = 1;
}
/* Mark / unmark as redundant (edge-only). This is not used for restoring state,
but may be useful for post-processing datasets. */
@ -471,8 +447,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
if (likely(state == q->fs_redundant)) { return; }
char fn[PATH_MAX];
q->fs_redundant = state;
if (likely(q->fs_redundant)) {
@ -486,22 +460,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
}
sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
strrchr((char *)q->fname, '/') + 1);
if (state) {
s32 fd;
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
fd = permissive_create(afl, fn);
if (fd >= 0) { close(fd); }
} else {
if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/
}
}
@ -805,6 +766,7 @@ void destroy_queue(afl_state_t *afl) {
for (i = 0; i < afl->queued_items; i++) {
q = afl->queue_buf[i];
ck_free(q->testcase_buf);
ck_free(q->fname);
ck_free(q->trace_mini);
if (q->skipdet_e) {
@ -833,7 +795,8 @@ void destroy_queue(afl_state_t *afl) {
previous contender, or if the contender has a more favorable speed x size
factor. */
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
bool have_trace) {
u32 i;
u64 fav_factor;
@ -863,75 +826,80 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
}
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
winner, and how it compares to us. */
for (i = 0; i < afl->fsrv.map_size; ++i) {
if (have_trace) {
if (afl->fsrv.trace_bits[i]) {
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
winner, and how it compares to us. */
for (i = 0; i < afl->fsrv.map_size; ++i) {
if (afl->top_rated[i]) {
if (afl->fsrv.trace_bits[i]) {
/* Faster-executing or smaller test cases are favored. */
u64 top_rated_fav_factor;
u64 top_rated_fuzz_p2;
if (afl->top_rated[i]) {
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
/* Faster-executing or smaller test cases are favored. */
u64 top_rated_fav_factor;
u64 top_rated_fuzz_p2;
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
} else if (unlikely(afl->schedule == RARE)) {
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
top_rated_fuzz_p2 =
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
} else if (unlikely(afl->schedule == RARE)) {
} else {
top_rated_fuzz_p2 =
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
} else {
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
}
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
top_rated_fav_factor = afl->top_rated[i]->len << 2;
} else {
top_rated_fav_factor =
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
}
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; }
if (likely(fav_factor > top_rated_fav_factor)) { continue; }
/* Looks like we're going to win. Decrease ref count for the
previous winner, discard its afl->fsrv.trace_bits[] if necessary.
*/
if (!--afl->top_rated[i]->tc_ref) {
ck_free(afl->top_rated[i]->trace_mini);
afl->top_rated[i]->trace_mini = NULL;
}
}
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
/* Insert ourselves as the new winner. */
top_rated_fav_factor = afl->top_rated[i]->len << 2;
afl->top_rated[i] = q;
++q->tc_ref;
} else {
if (!q->trace_mini) {
top_rated_fav_factor =
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
u32 len = ((afl->fsrv.map_size + 7) >> 3);
q->trace_mini = (u8 *)ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
}
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; }
if (likely(fav_factor > top_rated_fav_factor)) { continue; }
/* Looks like we're going to win. Decrease ref count for the
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
if (!--afl->top_rated[i]->tc_ref) {
ck_free(afl->top_rated[i]->trace_mini);
afl->top_rated[i]->trace_mini = NULL;
}
afl->score_changed = 1;
}
/* Insert ourselves as the new winner. */
afl->top_rated[i] = q;
++q->tc_ref;
if (!q->trace_mini) {
u32 len = (afl->fsrv.map_size >> 3);
q->trace_mini = (u8 *)ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
}
afl->score_changed = 1;
}
}
@ -1025,6 +993,186 @@ void cull_queue(afl_state_t *afl) {
}
/* Re-selects top_rated[] entries based on the current fuzzing schedule.
Each queued entry is executed once to collect trace_bits, and potential
candidates for each bitmap index are stored.
The candidate list format is [count][id1][id2]... as a u32 array,
where 'count' indicates how many queue IDs hit that index. */
void recalculate_all_scores(afl_state_t *afl) {
u8 *in_buf;
u32 i;
u32 j;
for (i = afl->last_scored_idx + 1; i < afl->queued_items; i++) {
if (likely(!afl->queue_buf[i]->disabled)) {
in_buf = queue_testcase_get(afl, afl->queue_buf[i]);
(void)write_to_testcase(afl, (void **)&in_buf, afl->queue_buf[i]->len, 1);
(void)fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
for (j = 0; j < afl->fsrv.map_size; ++j) {
if (afl->fsrv.trace_bits[j]) {
u32 *candidate_ids = afl->top_rated_candidates[j];
u32 id = afl->queue_buf[i]->id;
if (!candidate_ids) {
// first candidate: [count][id]
candidate_ids = ck_alloc(sizeof(u32) * 2);
candidate_ids[0] = 1; // count = 1
candidate_ids[1] = id; // first ID
} else {
u32 count = candidate_ids[0];
candidate_ids =
ck_realloc(candidate_ids, sizeof(u32) * (count + 2));
candidate_ids[0] = count + 1; // increment the count
candidate_ids[count + 1] = id; // append the new ID to the end
// fprintf(stderr, "enroll candidate[%u][%u] %u\n", i, j, id);
}
afl->top_rated_candidates[j] = candidate_ids;
}
}
}
afl->last_scored_idx = i;
}
for (i = 0; i < afl->fsrv.map_size; ++i) {
u32 *candidate_ids = afl->top_rated_candidates[i];
if (candidate_ids) {
u32 count = candidate_ids[0];
for (u32 k = 0; k < count; k++) {
u32 id = candidate_ids[k + 1];
struct queue_entry *entry = afl->queue_buf[id];
update_bitmap_rescore(afl, entry, i);
}
}
}
}
/* Re-evaluates top-rated entries without checking trace_bits.
Unlike update_bitmap_score(), this function assumes the trace
information is already known and only compares entries */
void update_bitmap_rescore(afl_state_t *afl, struct queue_entry *q, u32 index) {
u32 i = index;
u64 fav_factor;
u64 fuzz_p2;
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
fuzz_p2 = 0; // Skip the fuzz_p2 comparison
} else if (unlikely(afl->schedule == RARE)) {
fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]);
} else {
fuzz_p2 = q->fuzz_level;
}
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
fav_factor = q->len << 2;
} else {
fav_factor = q->exec_us * q->len;
}
if (afl->top_rated[i]) {
/* Faster-executing or smaller test cases are favored. */
u64 top_rated_fav_factor;
u64 top_rated_fuzz_p2;
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
} else if (unlikely(afl->schedule == RARE)) {
top_rated_fuzz_p2 =
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
} else {
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
}
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
top_rated_fav_factor = afl->top_rated[i]->len << 2;
} else {
top_rated_fav_factor =
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
}
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { return; }
if (likely(fav_factor > top_rated_fav_factor)) { return; }
/* Looks like we're going to win. Decrease ref count for the
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
if (!--afl->top_rated[i]->tc_ref) {
ck_free(afl->top_rated[i]->trace_mini);
afl->top_rated[i]->trace_mini = NULL;
}
}
/* Insert ourselves as the new winner. */
afl->top_rated[i] = q;
++q->tc_ref;
if (!q->trace_mini) {
u32 len = (afl->fsrv.map_size >> 3);
q->trace_mini = (u8 *)ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
}
afl->score_changed = 1;
}
/* Calculate case desirability score to adjust the length of havoc fuzzing.
A helper function for fuzz_one(). Maybe some of these constants should
go into config.h. */
@ -1330,7 +1478,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
// only realloc if necessary or useful
// (a custom trim can make the testcase larger)
if (unlikely(len > old_len || len < old_len + 1024)) {
if (unlikely(len > old_len || len + 1024 < old_len)) {
afl->q_testcase_cache_size += len - old_len;
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
@ -1364,7 +1512,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
if (likely(in != q->testcase_buf)) {
// only realloc if we save memory
if (unlikely(len < old_len + 1024)) {
if (unlikely(len + 1024 < old_len)) {
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);

View File

@ -592,11 +592,11 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
// note: from_queue seems to only be set during initialization
if (afl->afl_env.afl_no_ui || from_queue) {
WARNF("instability detected during calibration");
WARNF("instability detected during calibration: %s", q->fname);
} else if (afl->debug) {
DEBUGF("instability detected during calibration\n");
DEBUGF("instability detected during calibration: %s\n", q->fname);
}
@ -652,7 +652,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
afl->total_bitmap_size += q->bitmap_size;
++afl->total_bitmap_entries;
update_bitmap_score(afl, q);
update_bitmap_score(afl, q, true);
/* If this case didn't result in new output from the instrumentation, tell
parent. This is a non-critical problem, but something to warn the user
@ -682,12 +682,7 @@ abort_calibration:
afl->var_byte_count = count_bytes(afl, afl->var_bytes);
if (!q->var_behavior) {
mark_as_variable(afl, q);
++afl->queued_variable;
}
if (!q->var_behavior) { ++afl->queued_variable; }
}
@ -872,7 +867,14 @@ void sync_fuzzers(afl_state_t *afl) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) { goto close_sync; }
if (afl->stop_soon) {
munmap(mem, st.st_size);
close(fd);
goto close_sync;
}
afl->syncing_party = sd_ent->d_name;
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
@ -1166,7 +1168,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len);
memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size);
update_bitmap_score(afl, q);
update_bitmap_score(afl, q, true);
}

View File

@ -154,7 +154,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
flip_range(out_buf, pos, flip_block_size);
if (common_fuzz_stuff(afl, out_buf, len)) return 0;
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
flip_range(out_buf, pos, flip_block_size);
@ -237,26 +237,26 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
if (!skip_eff_map) {
skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len);
skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8);
afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map;
} else {
memset(skip_eff_map, 0, sizeof(u8) * len);
memset(skip_eff_map, 0, sizeof(u8) * (len + 7) / 8);
}
/* restore the starting point */
if (!done_inf_map) {
done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len);
done_inf_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8);
afl->queue_cur->skipdet_e->done_inf_map = done_inf_map;
} else {
for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) {
if (done_inf_map[afl->stage_cur] == 0) break;
if (bitmap_read(done_inf_map, afl->stage_cur) == 0) break;
}
@ -278,7 +278,13 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len);
// clean exec cksum
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
if (common_fuzz_stuff(afl, out_buf, len)) {
ck_free(non_eff_bytes);
return 0;
}
prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
}
@ -294,7 +300,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
afl->stage_cur_byte = afl->stage_cur;
if (!inf_eff_map[afl->stage_cur_byte] ||
skip_eff_map[afl->stage_cur_byte])
bitmap_read(skip_eff_map, afl->stage_cur_byte))
continue;
if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; }
@ -311,7 +317,12 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
before_skip_inf = afl->queued_items;
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
if (common_fuzz_stuff(afl, out_buf, len)) {
ck_free(non_eff_bytes);
return 0;
}
out_buf[afl->stage_cur_byte] = orig;
@ -328,7 +339,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
if (afl->queued_items != before_skip_inf) {
skip_eff_map[afl->stage_cur_byte] = 1;
bitmap_set(skip_eff_map, afl->stage_cur_byte);
afl->queue_cur->skipdet_e->quick_eff_bytes += 1;
if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; }
@ -338,7 +349,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
}
done_inf_map[afl->stage_cur_byte] = 1;
bitmap_set(done_inf_map, afl->stage_cur_byte);
}
@ -364,7 +375,7 @@ cleanup_skipdet:
while (i < len) {
// assume DWORD size, from i - 3 -> i + 3
if (skip_eff_map[i]) {
if (bitmap_read(skip_eff_map, i)) {
u32 fill_length = (i + 3 < len) ? 7 : len - i + 2;
memset(nearby_bytes + i - 3, 1, fill_length);
@ -378,7 +389,7 @@ cleanup_skipdet:
for (i = 0; i < len; i++) {
if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1;
if (nearby_bytes[i] && !non_eff_bytes[i]) bitmap_set(skip_eff_map, i);
}

View File

@ -106,6 +106,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000;
afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL;
afl->q_testcase_max_cache_entries = 64 * 1024;
afl->last_scored_idx = -1;
#ifdef HAVE_AFFINITY
afl->cpu_aff = -1; /* Selected CPU core */
@ -738,6 +739,21 @@ void afl_state_deinit(afl_state_t *afl) {
if (afl->pass_stats) { ck_free(afl->pass_stats); }
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
if (afl->cmplog_binary) { ck_free(afl->cmplog_binary); }
if (afl->cycle_schedules) {
for (u32 i = 0; i < afl->fsrv.map_size; i++) {
if (afl->top_rated_candidates[i]) {
ck_free(afl->top_rated_candidates[i]);
}
}
ck_free(afl->top_rated_candidates);
}
afl_free(afl->queue_buf);
afl_free(afl->out_buf);
@ -746,6 +762,8 @@ void afl_state_deinit(afl_state_t *afl) {
afl_free(afl->in_buf);
afl_free(afl->in_scratch_buf);
afl_free(afl->ex_buf);
afl_free(afl->alias_table);
afl_free(afl->alias_probability);
ck_free(afl->virgin_bits);
ck_free(afl->virgin_tmout);
@ -757,6 +775,11 @@ void afl_state_deinit(afl_state_t *afl) {
ck_free(afl->first_trace);
ck_free(afl->map_tmp_buf);
ck_free(afl->skipdet_g->inf_prof);
ck_free(afl->skipdet_g->virgin_det_bits);
ck_free(afl->skipdet_g);
ck_free(afl->havoc_prof);
list_remove(&afl_states, afl);
}

View File

@ -604,6 +604,8 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
void plot_profile_data(afl_state_t *afl, struct queue_entry *q) {
if (afl->skip_deterministic) { return; }
u64 current_ms = get_cur_time() - afl->start_time;
u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits);

View File

@ -612,11 +612,11 @@ int main(int argc, char **argv_orig, char **envp) {
afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
// still available: HjJkKqruvwz
// still available: HjJkKqrv
while (
(opt = getopt(argc, argv,
"+aw:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
"T:uUV:WXx:YzZ")) > 0) {
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:T:"
"uUV:w:WXx:YzZ")) > 0) {
switch (opt) {
@ -1555,13 +1555,6 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
// silently disable deterministic mutation if custom mutators are used
if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
afl->skip_deterministic = 1;
}
if (afl->fixed_seed) {
OKF("Running with fixed seed: %u", (u32)afl->init_seed);
@ -1750,8 +1743,27 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
if (afl->cycle_schedules) {
afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32));
}
if (afl->san_binary_length) {
if (afl->san_abstraction == UNIQUE_TRACE) {
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
}
if (afl->san_abstraction == SIMPLIFY_TRACE) {
afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
}
}
if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
@ -1759,16 +1771,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
if (afl->afl_env.afl_autoresume) {
afl->autoresume = 1;
if (afl->in_place_resume) {
SAYF("AFL_AUTORESUME has no effect for '-i -'");
}
}
if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; }
if (afl->afl_env.afl_hang_tmout) {
@ -2326,8 +2329,8 @@ int main(int argc, char **argv_orig, char **envp) {
u8 ver_string[8];
u64 *ver = (u64 *)ver_string;
u64 expect_ver =
afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
u64 expect_ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode +
(sizeof(struct queue_entry) << 1);
if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) !=
sizeof(ver_string))
@ -2605,7 +2608,7 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
WARNF("Unknown abstraction: %s, fallback to unique trace.\n",
WARNF("Unknown abstraction: %s, fallback to simplified trace.\n",
san_abstraction);
afl->san_abstraction = SIMPLIFY_TRACE;
@ -2843,12 +2846,13 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
u32 r = 8 + afl->fsrv.map_size * 4;
u32 q_len = o_end - o_start;
u32 m_len = (afl->fsrv.map_size >> 3);
u32 m_len = ((afl->fsrv.map_size + 7) >> 3);
struct queue_entry *q;
for (u32 i = 0; i < afl->queued_items; i++) {
q = afl->queue_buf[i];
// this is very dirty and assumes nice memory :-)
ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
ZLIBREAD(fr_fd, res, 1, "check map");
if (res[0]) {
@ -2865,7 +2869,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->total_bitmap_size += q->bitmap_size;
++afl->total_bitmap_entries;
update_bitmap_score(afl, q);
update_bitmap_score(afl, q, false);
if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
@ -2943,7 +2947,7 @@ int main(int argc, char **argv_orig, char **envp) {
for (entry = 0; entry < afl->queued_items; ++entry)
if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
if (!afl->pending_not_fuzzed || !valid_seeds) {
if (!valid_seeds) {
FATAL("We need at least one valid input seed that does not crash!");
@ -3235,15 +3239,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
// we must recalculate the scores of all queue entries
for (u32 i = 0; i < afl->queued_items; i++) {
if (likely(!afl->queue_buf[i]->disabled)) {
update_bitmap_score(afl, afl->queue_buf[i]);
}
}
recalculate_all_scores(afl);
}
@ -3545,7 +3541,8 @@ stop_fuzzing:
u8 ver_string[8];
u32 w = 0;
u64 *ver = (u64 *)ver_string;
*ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
*ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode +
(sizeof(struct queue_entry) << 1);
ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string");
ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
@ -3558,7 +3555,7 @@ stop_fuzzing:
u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
u32 q_len = o_end - o_start;
u32 m_len = (afl->fsrv.map_size >> 3);
u32 m_len = ((afl->fsrv.map_size + 7) >> 3);
struct queue_entry *q;
afl->pending_not_fuzzed = afl->queued_items;
@ -3625,6 +3622,10 @@ stop_fuzzing:
}
ck_free(afl->n_fuzz);
ck_free(afl->n_fuzz_dup);
ck_free(afl->simplified_n_fuzz);
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
ck_free(afl->fsrv.target_path);
ck_free(afl->fsrv.out_file);

View File

@ -131,8 +131,9 @@ static const u8 count_class_binary[256] = {
};
static void kill_child() {
static void kill_child(int signal) {
(void)signal;
timed_out = 1;
if (fsrv->child_pid > 0) {
@ -158,10 +159,11 @@ void show_stats(afl_state_t *afl) {
}
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q, bool x) {
(void)afl;
(void)q;
(void)x;
}
@ -1259,8 +1261,6 @@ int main(int argc, char **argv_orig, char **envp) {
break;
/* FIXME: We want to use -P for consistency, but it is already unused for
* undocumenetd feature "Another afl-cmin specific feature." */
case 'A': /* CoreSight mode */
#if !defined(__aarch64__) || !defined(__linux__)

View File

@ -37,6 +37,8 @@
#include "forkserver.h"
#include "sharedmem.h"
#include "common.h"
#include "afl-fuzz.h"
#include "list.h"
#include <stdio.h>
#include <unistd.h>
@ -48,6 +50,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <libgen.h>
#include <sys/wait.h>
#include <sys/time.h>
@ -57,8 +60,30 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#ifdef USE_PYTHON
#include <Python.h>
#endif
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
extern void destroy_custom_mutators(afl_state_t *);
void list_init(list_t *list) {
if (list) {
list->element_prealloc_count = 0;
memset(list->element_prealloc_buf, 0, sizeof(list->element_prealloc_buf));
}
}
void setup_custom_mutators(afl_state_t *);
struct custom_mutator *load_custom_mutator(afl_state_t *, const char *);
#ifdef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
#endif
static afl_state_t *afl; /* State for custom mutators */
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
static u8 *in_file, /* Minimizer input test case */
*out_file, *output_file; /* Minimizer output file */
@ -111,8 +136,9 @@ static const u8 count_class_lookup[256] = {
};
static void kill_child() {
static void kill_child(int signal) {
(void)signal;
if (fsrv->child_pid > 0) {
kill(fsrv->child_pid, fsrv->child_kill_signal);
@ -134,6 +160,52 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
}
/* dummy functions */
u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
(void)afl;
(void)mem;
return a + b;
}
void show_stats(afl_state_t *afl) {
(void)afl;
}
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
bool add_to_queue) {
(void)afl;
(void)q;
(void)add_to_queue;
}
fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
u32 i) {
(void)afl;
(void)fsrv;
(void)i;
return 0;
}
#ifndef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module) {
(void)afl;
(void)module;
FATAL("Python support not available in this build");
return NULL;
}
#endif
/* Apply mask to classified bitmap (if set). */
static void apply_mask(u32 *mem, u32 *mask) {
@ -152,7 +224,7 @@ static void apply_mask(u32 *mem, u32 *mask) {
}
static void classify_counts(afl_forkserver_t *fsrv) {
void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
u32 i = map_size;
@ -208,6 +280,13 @@ static void at_exit_handler(void) {
afl_fsrv_killall();
if (remove_out_file) unlink(out_file);
if (afl) {
destroy_custom_mutators(afl);
ck_free(afl);
}
}
/* Read initial file. */
@ -258,14 +337,72 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
}
/* Helper function to handle custom mutators for testcase writing */
static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
static u8 buf[MAX_FILE];
u32 sent = 0;
if (afl && afl->custom_mutators_count) {
ssize_t new_size = len;
u8 *new_mem = mem;
u8 *new_buf = NULL;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_post_process) {
new_size =
el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
if (!new_buf || new_size <= 0) {
return;
} else {
new_mem = new_buf;
len = new_size;
}
}
});
if (new_mem != mem && new_mem != NULL) {
mem = buf;
memcpy(mem, new_mem, new_size);
}
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz_send) {
el->afl_custom_fuzz_send(el->data, mem, len);
sent = 1;
}
});
}
if (!sent) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
}
/* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */
static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
u8 first_run) {
afl_fsrv_write_to_testcase(fsrv, mem, len);
pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
@ -356,14 +493,132 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
static void minimize(afl_forkserver_t *fsrv) {
static u32 alpha_map[256];
u8 *tmp_buf = ck_alloc_nozero(in_len);
u32 orig_len = in_len, stage_o_len;
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
u8 *tmp_buf = ck_alloc_nozero(in_len);
u32 orig_len = in_len, stage_o_len;
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0;
u8 changed_any, prev_del;
#ifdef USE_PYTHON
// Try to load python module
char *py_module = getenv("AFL_PYTHON_MODULE");
if (py_module) {
// We cannot use Python custom mutators in tmin
if (debug) WARNF("Python custom mutator support not available in afl-tmin");
}
#endif
// Custom mutator trimming
if (afl && afl->custom_mutators_count) {
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_init_trim && el->afl_custom_trim &&
el->afl_custom_post_trim) {
ACTF("Performing custom trim with %s...", el->name);
// Initialize the trimmer
s32 initial_steps = el->afl_custom_init_trim(el->data, in_data, in_len);
if (initial_steps <= 0) {
WARNF("Custom trimmer %s returned %d, skipping", el->name,
initial_steps);
continue;
}
ACTF("Custom trimmer initialized, %d steps planned", initial_steps);
u32 trim_rounds = 0;
u32 trimmed_successfully = 0;
// Trim loop
s32 cur_step = 0;
while (cur_step < initial_steps) {
u8 *trimmed_buf = NULL;
size_t trimmed_size;
u8 *retbuf = NULL;
trimmed_size = el->afl_custom_trim(el->data, &retbuf);
// If trimmed_size equals or exceeds original size, skip
if (trimmed_size >= in_len) {
SAYF("[Custom trim] Round %u: no improvements over %u bytes.\n",
trim_rounds, in_len);
el->afl_custom_post_trim(el->data, 0);
cur_step++;
trim_rounds++;
continue;
}
trimmed_buf = retbuf;
// Test if the trimmed case still works
if (!tmin_run_target(fsrv, trimmed_buf, trimmed_size, 0)) {
SAYF(
"[Custom trim] But the testcase no longer reproduces - "
"skipping this reduction.\n");
el->afl_custom_post_trim(el->data, 0);
if (trimmed_buf != in_data) { ck_free(trimmed_buf); }
} else {
// Accept the reduction
u8 *old_in_data = in_data;
in_data = trimmed_buf;
in_len = trimmed_size;
trimmed_successfully = 1;
el->afl_custom_post_trim(el->data, 1);
SAYF("[Custom trim] Successful reduction to %u bytes\n", in_len);
if (old_in_data != in_data && old_in_data != trimmed_buf) {
ck_free(old_in_data);
}
}
cur_step++;
trim_rounds++;
}
ACTF("Custom trimming with %s complete after %u rounds, reduced: %s",
el->name, trim_rounds, trimmed_successfully ? "yes" : "no");
if (trimmed_successfully) {
if (tmp_buf) { ck_free(tmp_buf); }
return; // Skip standard minimization if successful
}
}
});
}
// Skip built-in minimization if in_len is too small
if (in_len <= 1) {
if (tmp_buf) { ck_free(tmp_buf); }
return;
}
/***********************
* BLOCK NORMALIZATION *
***********************/
@ -746,7 +1001,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
/* Setup signal handlers, duh. */
static void setup_signal_handlers(void) {
void setup_signal_handlers(void) {
struct sigaction sa;
@ -1242,6 +1497,29 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
// Initialize AFL state for custom mutators
afl = calloc(1, sizeof(afl_state_t));
if (afl) {
list_init(&afl->custom_mutator_list);
afl->custom_mutators_count = 0;
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
afl->afl_env.afl_custom_mutator_library =
getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
afl->shm = shm;
afl->out_dir = dirname(in_file);
memcpy(&afl->fsrv, fsrv, sizeof(afl_forkserver_t));
setup_custom_mutators(afl);
}
#ifdef __linux__
if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
#else

View File

@ -114,6 +114,7 @@ def main():
# ---------------------------------------------------
# Load the binary to emulate and map it into memory
# Load the binary to emulate
print("Loading data input from {}".format(args.input_file))
binary_file = open(BINARY_FILE, "rb")
binary_code = binary_file.read()
@ -124,7 +125,7 @@ def main():
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
return
# Write the mutated command into the data buffer
# Map the binary into memory
uc.mem_map(CODE_ADDRESS, CODE_SIZE_MAX)
uc.mem_write(CODE_ADDRESS, binary_code)

View File

@ -142,6 +142,7 @@ def main():
# ---------------------------------------------------
# Load the binary to emulate and map it into memory
# Load the binary to emulate
print("Loading data input from {}".format(args.input_file))
binary_file = open(BINARY_FILE, "rb")
binary_code = binary_file.read()
@ -152,7 +153,7 @@ def main():
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
return
# Write the mutated command into the data buffer
# Map the binary into memory
uc.mem_map(CODE_ADDRESS, CODE_SIZE_MAX)
uc.mem_write(CODE_ADDRESS, binary_code)

View File

@ -20,6 +20,10 @@ endif
CFLAGS := -O3 -funroll-loops -g -fPIC
ifdef IOS_SDK_PATH
CFLAGS += -isysroot $(IOS_SDK_PATH)
endif
all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so
aflpp_driver.o: aflpp_driver.c

View File

@ -106,12 +106,16 @@ __attribute__((weak)) void __asan_unpoison_memory_region(
__attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size);
// Notify AFL about persistent mode.
static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
int __afl_persistent_loop(unsigned int);
__attribute__((section(".rodata"), used,
retain)) static const char AFL_PERSISTENT[] =
"##SIG_AFL_PERSISTENT##";
int __afl_persistent_loop(unsigned int);
// Notify AFL about deferred forkserver.
static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
void __afl_manual_init();
__attribute__((section(".rodata"), used,
retain)) static const char AFL_DEFER_FORKSVR[] =
"##SIG_AFL_DEFER_FORKSRV##";
void __afl_manual_init();
// Use this optionally defined function to output sanitizer messages even if
// user asks to close stderr.
@ -350,11 +354,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
// Do any other expensive one-time initialization here.
uint8_t dummy_input[64] = {0};
memcpy(dummy_input, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT));
memcpy(dummy_input + 32, (void *)AFL_DEFER_FORKSVR,
sizeof(AFL_DEFER_FORKSVR));
int N = INT_MAX;
if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {
@ -392,10 +391,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
__afl_manual_init();
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
// on the first execution of LLVMFuzzerTestOneInput is ignored.
callback(dummy_input, 4);
__asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE);
size_t prev_length = 0;

View File

@ -11,12 +11,12 @@
#include <dlfcn.h>
#ifdef __ANDROID__
#include "../include/android-ashmem.h"
#include "../../include/android-ashmem.h"
#endif
#include <sys/ipc.h>
#include <sys/shm.h>
#include "../config.h"
#include "../../config.h"
#include <QBDI.h>
@ -80,8 +80,8 @@ static void afl_forkserver() {
while (1) {
int status;
u32 was_killed;
int status;
unsigned int was_killed;
// wait for afl-fuzz
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);