Compare commits

...

195 Commits

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

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

Closes: #2081
2024-05-11 00:48:04 +07:00
ac6ccd53df stat update during syncing 2024-05-07 16:46:24 +02:00
4ec376bd6a Merge pull request #2076 from louismerlin/fix-whatsup-time
Fix `afl_whatsup` findings timer
2024-05-02 17:30:59 +02:00
3c0448305b Guard /proc/uptime cat with a uname check 2024-05-02 17:19:37 +02:00
a6029a10cc Fix CUR_TIME computation 2024-05-02 16:12:50 +02:00
26eaf53a83 AFL_DISABLE_REDUNDANT 2024-05-02 08:35:24 +02:00
5d623a27ed try enhanced asan support 2024-04-30 11:59:49 +02:00
69e554b941 Merge pull request #2074 from Kiprey/patch-2
Fix wrong warning in SanitizerCoverageLTO.so.cc
2024-04-29 17:11:41 +02:00
7340374a7c Fix wrong warning in SanitizerCoverageLTO.so.cc 2024-04-29 16:14:49 +08:00
67d356b73f update qemuafl 2024-04-28 15:41:24 +02:00
da18f1f722 Merge pull request #2073 from Acture/dev
Fix: Removed the redundant `id` field from redqueen.c
2024-04-28 15:39:32 +02:00
58abcceff5 Bug fix: Removed the redundant id field from the debug output in the afl-fuzz-redqueen.c file since cmp_header no longer have this field. 2024-04-28 16:24:52 +08:00
ad0d0c77fb Merge pull request #2071 from AFLplusplus/dev
Push to stable
2024-04-26 16:17:41 +02:00
2c3f761ede changes 2024-04-26 16:16:21 +02:00
70c60cfba7 work with spaces in filenames 2024-04-26 16:14:50 +02:00
f3b6d64ad3 Merge pull request #2066 from ahuo1/dev
fix: initialize n_fuzz_entry in perform_dry_run.
2024-04-26 09:44:49 +02:00
43e9a13921 add schedule check. 2024-04-26 07:45:58 +08:00
526dbe8f16 fix: initialize n_fuzz_entry in perform_dry_run. 2024-04-25 21:28:58 +08:00
951a0e5225 fix AFL_PERSISTENT_RECORD 2024-04-25 10:04:58 +02:00
458b939bc4 LTO fix 2024-04-19 17:34:50 +02:00
476aca5b67 nits 2024-04-19 15:45:00 +02:00
96bf0f8323 Merge pull request #2061 from jschwartzentruber/change_smm_vis
Specify shared memory visibility
2024-04-18 17:30:51 +02:00
58206a3180 Set explicit visibility on shared memory variables. 2024-04-17 14:40:41 -04:00
f138ab8ac6 Merge pull request #2059 from elboulangero/afl-gcc
Fix afl-gcc
2024-04-17 12:55:34 +02:00
50839cf6e9 afl-cc: Complete fix for afl-as
Look for afl-as, and then make sure that there's a 'as' binary in the
same directory, that seems to be either a symlink to, or a copy of,
afl-as.
2024-04-17 16:41:03 +07:00
626a4434ed afl-cc: Use afl-as (rather than as) to find obj path 2024-04-17 16:40:58 +07:00
d84cc73d13 afl-cc: Add missing debug statement
For each path that is tried, there's a debug log printed, _except_ for
this one. Fix it.
2024-04-17 16:40:55 +07:00
6b049536f1 v4.21 init 2024-04-13 11:54:08 +02:00
1d17210d9f Merge pull request #2052 from AFLplusplus/dev
4.20 release pre-PR
2024-04-13 11:50:49 +02:00
1582aa9da2 Merge pull request #2027 from choller/nyx-handler-fix
Add optional handling of Nyx InvalidWriteToPayload event
2024-04-13 11:40:28 +02:00
e01307a993 v4.20c 2024-04-13 11:39:26 +02:00
beb9f95359 Merge pull request #2051 from Phasip/patch-1
Clarify that oss-fuzz doesn't randomize builds anymore
2024-04-12 11:07:33 +02:00
c49a4c7027 Clarify that oss-fuzz doesn't randomize builds anymore 2024-04-12 09:28:38 +02:00
b08df87f5c fix syncing with custom mutator 2024-04-11 09:40:28 +02:00
72226d6f89 fix shared memory test cases 2024-04-09 16:20:42 +02:00
40adc34413 fix -V, code format 2024-04-09 09:24:19 +02:00
eeae114b76 Merge pull request #2034 from fbeqv/add_effective_fuzzing_time_tracker
Adds stats tracking for time spend actually mutating & running test i…
2024-04-09 09:04:53 +02:00
48a862c503 :Adds stats tracking time spend in calibration/trim/sync
This currently does not affect statsd nor the UI. Only the fuzzer_stats file is updated
2024-04-08 11:54:19 -07:00
29544e4d2b fix time 2024-04-07 18:44:21 +02:00
420a90ff75 code format 2024-04-07 12:53:41 +02:00
45603367bf fix llvm modules 2024-04-07 09:44:33 +02:00
f7ea0f569f fix aflpp custom mutator + standalone tool 2024-04-05 14:53:02 +02:00
2bf92848ff Fixed unicorn_dumper_gdb.py for updated version of gef (#2045)
Updated unicorn_dumper_gdb.py to support new gef api and replaced deprecated functions . The functions that are not in the new gef api are read_memory(), and current_arch(). Also replaced some deprecated functions with the updated versions of them.

    replaced read_memory() with GefMemoryManager.read() as read_memory(). read_memory() is in legacy-gef-api
    replaced current_arch with gef.arch.registers
    replaced get_process_maps() with gef.memory.maps (just depreacated)
    replaced get_register() with gef.arch.register()
2024-04-03 11:57:09 +02:00
ad65cfb400 Merge pull request #2043 from ligurio/ligurio/fix-clock_gettime
src: fix calculation of fuzzing time in statistics
2024-03-31 18:41:26 +07:00
5ffc8c7076 src: fix calculation of fuzzing time in statistics
When the computer is suspended during a fuzzing session,
the time spent in suspended state is counted as a "run time"
on a statistics screen.

The time returned by `gettimeofday(2)` is affected by discontinuous
jumps in the system time. It is better using `clock_gettime(2)`.

The patch replace `gettimeofday` with `clock_gettime` [1].
`clock_gettime` uses a CLOCK_MONOTONIC_COARSE clock type,
it is faster than CLOCK_MONOTONIC, but still has resolution (~1ms)
that is adequate for our purposes. However, CLOCK_MONOTONIC_COARSE
is a Linux-specific clock variant, so on macOS it is replaced
with CLOCK_MONOTONIC, and with CLOCK_MONOTONIC_FAST on FreeBSD [2].

Closes #1241

1. https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html
2. https://man.freebsd.org/cgi/man.cgi?query=clock_gettime
2024-03-31 11:11:29 +03:00
8943ba0249 Merge pull request #2042 from ligurio/patch-1
citation: fix typo
2024-03-28 18:58:02 +07:00
b02adf6b3f citation: fix typo 2024-03-28 12:46:49 +03:00
6ef5d7c135 Merge pull request #2038 from SonicStark/dev-makefile-0322
bugfix: override directive and recipe echoing in GNUmakefile
2024-03-23 16:19:49 +07:00
9ece2e3f2c Merge pull request #2040 from flk0/stable
Fix build_qemu_support.sh static builds
2024-03-23 15:17:42 +07:00
4b2cdaf47c Fix build_qemu_support.sh static builds
The recently added config option 'enable-plugins' breaks static builds of qemuafl. Override the enable for static builds.
2024-03-23 15:39:54 +10:00
9b5b71b61b fix override directive and recipe echoing 2024-03-22 03:24:53 +00:00
59465bd249 Merge pull request #2035 from Resery/patch-6
bugfix: update_firda_version can't get the newest version of frida
2024-03-15 12:57:50 +07:00
ed50f37c79 bugfix: update_firda_version can't get the newest version of frida
The method of getting the newest version of Frida is invalid. Need update.
2024-03-15 12:03:01 +08:00
a96bda82f9 Merge pull request #2033 from gnbon/stable
Add -l option for adjustable block deletion performance in tmin
2024-03-15 08:39:39 +07:00
1860f6e594 Fix invalid range for del_len_limit 2024-03-14 11:00:59 +09:00
c9ad3acc9b Add -l option for adjustable block deletion
- Introduce the -l option to set min block deletion length using
powers of 2 (e.g., 1, 2, 4, 8, 16, ...).
- This enables a trade-off between minimization thoroughness and speed.
- Adjusting del_len_limit allows for faster processing, as doubling it
roughly halves the minimization time.
2024-03-13 12:10:38 +09:00
93c7a42453 Merge pull request #2029 from ocean1/minor_ver_fix
support parsing of llvm rc minor version
2024-03-12 15:30:27 +07:00
=
ee07fc9f6d fix rc minor version parsing 2024-03-12 08:20:08 +00:00
443edcd771 nits 2024-03-12 07:42:16 +01:00
6650ef4274 Merge pull request #2030 from ocean1/replay_loop_fix
Replay record loop fix
2024-03-12 10:08:29 +07:00
b85174fc8d nit 2024-03-12 04:00:19 +01:00
=
08f6d59f50 correct fix 2024-03-11 12:01:06 +00:00
=
2ed2ac80bc fix record compat loop to replay correct number of inputs, and at least one input 2024-03-11 10:30:35 +00:00
=
2300088446 support parsing of llvm rc minor version 2024-03-11 10:12:53 +00:00
306a917956 UI fix 2024-03-07 12:09:22 +01:00
0ea53ea5b5 likely 2024-03-06 12:41:00 +01:00
092260e9f9 Merge pull request #2026 from choller/pcmap_fix2
Fix delayed pcmap writing for code coverage with pc-table
2024-03-06 17:56:24 +07:00
52e19d35fa Add optional handling of Nyx InvalidWriteToPayload event 2024-03-06 10:55:53 +01:00
bf17953353 Code formating 2024-03-06 10:50:29 +01:00
e46fac6063 Fix delayed pcmap writing for code coverage with pc-table 2024-03-06 10:19:52 +01:00
6062668679 fix not using autodict 2024-02-29 14:31:47 +01:00
acc178e5dd log 2024-02-29 14:16:56 +01:00
31adb57fd7 Merge pull request #2014 from seanm/issue2007
Issue #2007: add filename extension to /crashes files
2024-02-29 14:16:07 +01:00
7652406c12 nit 2024-02-29 13:34:04 +01:00
a607adb7a3 Merge pull request #2019 from zidel/fork_server_fix
Load autodictionary when using new forkserver
2024-02-29 09:14:38 +01:00
036a79268b gcc cmplog fix 2024-02-29 09:10:29 +01:00
335b2d4542 Load autodictionary when using new forkserver
Fixes a bug where the new fork server would decrement dict_size until
zero then try to use it as the upper bound for the number of bytes to
pass to add_extra_func, causing it to never store any of the tokens.
2024-02-28 22:29:55 +01:00
603136efa0 unicornafl: Fix dump_regs() type errors in pwndbg dumper (#2005)
* push to stable (#1983)

* Output afl-clang-fast stuffs only if necessary (#1912)

* afl-cc header

* afl-cc common declarations

 - Add afl-cc-state.c
 - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c
 - Use debugf_args in main
 - Modify execvp stuffs to fit new aflcc struct

* afl-cc show usage

* afl-cc mode selecting

1. compiler_mode by callname in argv[0]
2. compiler_mode by env "AFL_CC_COMPILER"
3. compiler_mode/instrument_mode by command line options "--afl-..."
4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT"
5. final checking steps
6. print "... - mode: %s-%s\n"
7. determine real argv[0] according to compiler_mode

* afl-cc macro defs

* afl-cc linking behaviors

* afl-cc fsanitize behaviors

* afl-cc misc

* afl-cc body update

* afl-cc all-in-one

formated with custom-format.py

* nits

---------

Co-authored-by: vanhauser-thc <vh@thc.org>

* changelog

* update grammar mutator

* lto llvm 12+

* docs(custom_mutators): fix missing ':' (#1953)

* Fix broken LTO mode and response file support (#1948)

* Strip `-Wl,-no-undefined` during compilation (#1952)

Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`.
Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix).

* Remove dead code in write_to_testcase (#1955)

The custom_mutators_count check in if case is duplicate with if condition.
The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed.

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>

* update qemuafl

* WIP: Add ability to generate drcov trace using QEMU backend (#1956)

* Document new drcov QEMU plugin

* Add link to lightkeeper for QEMU drcov file loading

---------

Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>

* code format

* changelog

* sleep on uid != 0 afl-system-config

* fix segv about skip_next, warn on unsupported cases of linking options (#1958)

* todos

* ensure afl-cc only allows available compiler modes

* update grammar mutator

* disable aslr on apple

* fix for arm64

* help selective instrumentation

* typos

* macos

* add compiler test script

* apple fixes

* bump nyx submodules (#1963)

* fix docs

* update changelog

* update grammar mutator

* improve compiler test script

* gcc asan workaround (#1966)

* fix github merge fuckup

* fix

* Fix afl-cc (#1968)

- Check if too many cmdline params here, each time before insert a new param.
 - Check if it is "-fsanitize=..." before we do sth.
 - Remove improper param_st transfer.

* Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969)

* Dynamic instrumentation filtering for LLVM native (#1971)

* Add two dynamic instrumentation filter methods to runtime

* Always use pc-table with native pcguard

* Add make_symbol_list.py and README

* changelog

* todos

* new forkserver check

* fix

* nyx test for CI

* improve nyx docs

* Fixes to afl-cc and documentation (#1974)

* Always compile with -ldl when building for CODE_COVERAGE

When building with CODE_COVERAGE, the afl runtime contains code that
calls `dladdr` which requires -ldl. Under most circumstances, clang
already adds this (e.g. when building with pc-table), but there are some
circumstances where it isn't added automatically.

* Add visibility declaration to __afl_connected

When building with hidden visibility, the use of __AFL_LOOP inside such
code can cause linker errors due to __afl_connected being declared
"hidden".

* Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter

* nits

* nyx build script updates

* test error output

* debug ci

* debug ci

* Improve afl-cc (#1975)

* update response file support

 - full support of rsp file
 - fix some segv issues

* Improve afl-cc

 - remove dead code about allow/denylist options of sancov
 - missing `if (!aflcc->have_msan)`
 - add docs for each function
 - typo

* enable nyx

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* fix ci

* clean test script

* NO_NYX

* NO_NYX

* fix ci

* debug ci

* fix ci

* finalize ci fix

* Enhancement on Deterministic stage (#1972)

* fuzzer: init commit based on aflpp 60dc37a8cf

* fuzzers: adding the skip variables and initialize

* log: profile the det/havoc finding

* log: add profile log output

* fuzzers: sperate log/skipdet module

* fuzzers: add quick eff_map calc

* fuzzers: add skip_eff_map in fuzz_one

* fuzzers: mark whole input space in eff_map

* fuzzers: add undet bit threshold to skip some seeds

* fuzzers: fix one byte overflow

* fuzzers: fix overflow

* fix code format

* add havoc only again

* code format

* remove log to INTROSPECTION, rename skipdet module

* rename skipdet module

* remove log to stats

* clean redundant code

* code format

* remove redundant code format check

* remove redundant doc

* remove redundant objects

* clean files

* change -d to default skipdet

* disable deterministic when using CUSTOM_MUTATOR

* revert fix

* final touches for skipdet

* remove unused var

* remove redundant eff struct (#1977)

* update QEMU-Nyx submodule (#1978)

* update QEMU-Nyx submodule (#1980)

* Fix type in AFL_NOOPT env variable in afl-cc help message (#1982)

* nits

* 2024 v4.10c release

* fixes

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>

* Fix dump_regs() type errors in Python

TypeError will occur as gdb api return some strange type of values that json can't serialize, this would fix this issue

* Update reg_val is None condition

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>
2024-02-27 09:46:07 +01:00
1e01ccc8fd unicornafl: Add UAF chcker to loader (#2009)
* impl uaf chcker

By adding a list of freed chunks, add the chunk to the list during free, check whether the allocated block is in the freed chunk list during malloc, and if so, remove the chunk from the freed chunk list, in __check_mem_access check whether the address is in the freed chunk list. This enables the detection of uaf.

* make uaf_check be configruable
2024-02-27 09:43:50 +01:00
9f6d27ddce Merge pull request #2018 from hyrathon/patch-2
Add -ldl flag
2024-02-27 08:57:23 +01:00
8fcd404352 Update GNUmakefile
The linker flags lacks a -ldl so the dlopen series of func symbols can't be found
2024-02-27 15:34:42 +08:00
b2b887d04d Issue #2007: add filename extension to /crashes files
This is very helpful for code that inpects a file name extension when determining what code to run.

It's also useful for applications that constrain the user to choose files by extension.
2024-02-26 14:07:49 -05:00
849994dedd update changelog 2024-02-23 14:09:22 +01:00
1286d1906f Merge pull request #2012 from clesmian/dev
Fix bug where `-t 1000+` may result in enormous timeouts
2024-02-23 13:53:15 +01:00
fae760fc9e Add upper and lower safety margins 2024-02-23 13:39:46 +01:00
01f442d810 Be specific about the unit of time 2024-02-23 12:53:20 +01:00
eaedf2e62f Adhere to documented behavior 2024-02-23 12:52:11 +01:00
07e0b39126 Do not circumvent sanity checks from arg parsing 2024-02-22 15:55:18 +01:00
98238ed763 Convert from microseconds (us) to milliseconds (ms) 2024-02-22 15:28:55 +01:00
340d6aa97c unicornafl: fix malloc of size 0 (#2010)
* bugfix: free a chunk with a size of 0, it will cause 1 byte oob.

Malloc does not check the size. Generally, malloc(0) should return 0 but there will return two pages. Free will use is_buffer_in_chunk to check whether the address is in the chunk. At that time, the chunk.data_addr == total_size . Free pass address and "1" to is_buffer_in_chunk. So cause 1 byte out-of-bound.

* typo
2024-02-21 12:42:55 +01:00
5ae4a7ae02 afl-whatsup current speed 2024-02-20 15:48:48 +01:00
80158de3e8 Catch invalid frees (#2008)
1. There isn't a need to check all chunks when address == 0
2. If the address is not in chunks, the program may want to free an object that doesn't exist. There may be a "double-free" or "invalid-free" vulnerability. (This patch is from the repo named "Battelle/afl-unicorn")
2024-02-20 14:01:37 +01:00
730713193a replaced unicornafl with unicorn (#2003)
* push to stable (#1983)

* Output afl-clang-fast stuffs only if necessary (#1912)

* afl-cc header

* afl-cc common declarations

 - Add afl-cc-state.c
 - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c
 - Use debugf_args in main
 - Modify execvp stuffs to fit new aflcc struct

* afl-cc show usage

* afl-cc mode selecting

1. compiler_mode by callname in argv[0]
2. compiler_mode by env "AFL_CC_COMPILER"
3. compiler_mode/instrument_mode by command line options "--afl-..."
4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT"
5. final checking steps
6. print "... - mode: %s-%s\n"
7. determine real argv[0] according to compiler_mode

* afl-cc macro defs

* afl-cc linking behaviors

* afl-cc fsanitize behaviors

* afl-cc misc

* afl-cc body update

* afl-cc all-in-one

formated with custom-format.py

* nits

---------

Co-authored-by: vanhauser-thc <vh@thc.org>

* changelog

* update grammar mutator

* lto llvm 12+

* docs(custom_mutators): fix missing ':' (#1953)

* Fix broken LTO mode and response file support (#1948)

* Strip `-Wl,-no-undefined` during compilation (#1952)

Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`.
Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix).

* Remove dead code in write_to_testcase (#1955)

The custom_mutators_count check in if case is duplicate with if condition.
The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed.

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>

* update qemuafl

* WIP: Add ability to generate drcov trace using QEMU backend (#1956)

* Document new drcov QEMU plugin

* Add link to lightkeeper for QEMU drcov file loading

---------

Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>

* code format

* changelog

* sleep on uid != 0 afl-system-config

* fix segv about skip_next, warn on unsupported cases of linking options (#1958)

* todos

* ensure afl-cc only allows available compiler modes

* update grammar mutator

* disable aslr on apple

* fix for arm64

* help selective instrumentation

* typos

* macos

* add compiler test script

* apple fixes

* bump nyx submodules (#1963)

* fix docs

* update changelog

* update grammar mutator

* improve compiler test script

* gcc asan workaround (#1966)

* fix github merge fuckup

* fix

* Fix afl-cc (#1968)

- Check if too many cmdline params here, each time before insert a new param.
 - Check if it is "-fsanitize=..." before we do sth.
 - Remove improper param_st transfer.

* Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969)

* Dynamic instrumentation filtering for LLVM native (#1971)

* Add two dynamic instrumentation filter methods to runtime

* Always use pc-table with native pcguard

* Add make_symbol_list.py and README

* changelog

* todos

* new forkserver check

* fix

* nyx test for CI

* improve nyx docs

* Fixes to afl-cc and documentation (#1974)

* Always compile with -ldl when building for CODE_COVERAGE

When building with CODE_COVERAGE, the afl runtime contains code that
calls `dladdr` which requires -ldl. Under most circumstances, clang
already adds this (e.g. when building with pc-table), but there are some
circumstances where it isn't added automatically.

* Add visibility declaration to __afl_connected

When building with hidden visibility, the use of __AFL_LOOP inside such
code can cause linker errors due to __afl_connected being declared
"hidden".

* Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter

* nits

* nyx build script updates

* test error output

* debug ci

* debug ci

* Improve afl-cc (#1975)

* update response file support

 - full support of rsp file
 - fix some segv issues

* Improve afl-cc

 - remove dead code about allow/denylist options of sancov
 - missing `if (!aflcc->have_msan)`
 - add docs for each function
 - typo

* enable nyx

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* fix ci

* clean test script

* NO_NYX

* NO_NYX

* fix ci

* debug ci

* fix ci

* finalize ci fix

* Enhancement on Deterministic stage (#1972)

* fuzzer: init commit based on aflpp 60dc37a8cf

* fuzzers: adding the skip variables and initialize

* log: profile the det/havoc finding

* log: add profile log output

* fuzzers: sperate log/skipdet module

* fuzzers: add quick eff_map calc

* fuzzers: add skip_eff_map in fuzz_one

* fuzzers: mark whole input space in eff_map

* fuzzers: add undet bit threshold to skip some seeds

* fuzzers: fix one byte overflow

* fuzzers: fix overflow

* fix code format

* add havoc only again

* code format

* remove log to INTROSPECTION, rename skipdet module

* rename skipdet module

* remove log to stats

* clean redundant code

* code format

* remove redundant code format check

* remove redundant doc

* remove redundant objects

* clean files

* change -d to default skipdet

* disable deterministic when using CUSTOM_MUTATOR

* revert fix

* final touches for skipdet

* remove unused var

* remove redundant eff struct (#1977)

* update QEMU-Nyx submodule (#1978)

* update QEMU-Nyx submodule (#1980)

* Fix type in AFL_NOOPT env variable in afl-cc help message (#1982)

* nits

* 2024 v4.10c release

* fixes

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>

* replaced unicornafl with unicorn

The submodule of unicorn cannot be imported through unicornafl.*_const here. If we want to use the *_const module, we should reference `from unicorn.*_const import *` like this instead of importing the entire contents of the *_const module via unicornafl。

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>
2024-02-19 22:44:05 +01:00
fea76dff23 Merge pull request #1999 from seanm/issue1865
Fixed #1865: create symlinks for afl-clang-fast
2024-02-19 19:07:30 +01:00
808022d3e0 Fixed #1865: many updates to INSTALL.md for macOS
- moved shared mem instructions to before building so that tests during build don't fail
- corrected path to README.llvm.md
- updated some macOS spelling
- added missing sudo
- misc other changes from reading the document carefully
2024-02-19 12:06:11 -05:00
eee78077e2 Merge pull request #1998 from trail-of-forks/grub-cmdline
afl-persistent-config: Use GRUB_CMDLINE_LINUX instead of GRUB_CMDLINE_LINUX_DEFAULT
2024-02-16 18:22:30 +01:00
ca91d3fbc0 Revert other changes 2024-02-16 13:54:05 +00:00
ad4a776fc6 Change both 2024-02-16 12:01:50 +00:00
ebdb71aeb0 Merge pull request #2002 from seanm/issue2001
issue #2001: fix passing rpath to linker on macOS
2024-02-16 10:14:56 +01:00
6dc58750cf issue #2001: fix passing rpath to linker on macOS
Seems on macOS, `ld` does not want an `=` when specifying `-rpath`.
2024-02-15 19:19:51 -05:00
1b84448be3 afl-persistent-config: Use GRUB_CMDLINE_LINUX instead of GRUB_CMDLINE_LINUX_DEFAULT.
The latter is often overwritten in images used in cloud setups. For example DigitalOcean sets GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0" in /etc/default/grub.d/
2024-02-14 15:55:32 +00:00
61ceef64b1 valid comparison.md 2024-02-13 20:14:35 +01:00
775861ea94 Merge pull request #1985 from AFLplusplus/dev
push to stable
2024-02-03 11:57:27 +01:00
602eceed8b push to stable (#1983)
* Output afl-clang-fast stuffs only if necessary (#1912)

* afl-cc header

* afl-cc common declarations

 - Add afl-cc-state.c
 - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c
 - Use debugf_args in main
 - Modify execvp stuffs to fit new aflcc struct

* afl-cc show usage

* afl-cc mode selecting

1. compiler_mode by callname in argv[0]
2. compiler_mode by env "AFL_CC_COMPILER"
3. compiler_mode/instrument_mode by command line options "--afl-..."
4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT"
5. final checking steps
6. print "... - mode: %s-%s\n"
7. determine real argv[0] according to compiler_mode

* afl-cc macro defs

* afl-cc linking behaviors

* afl-cc fsanitize behaviors

* afl-cc misc

* afl-cc body update

* afl-cc all-in-one

formated with custom-format.py

* nits

---------

Co-authored-by: vanhauser-thc <vh@thc.org>

* changelog

* update grammar mutator

* lto llvm 12+

* docs(custom_mutators): fix missing ':' (#1953)

* Fix broken LTO mode and response file support (#1948)

* Strip `-Wl,-no-undefined` during compilation (#1952)

Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`.
Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix).

* Remove dead code in write_to_testcase (#1955)

The custom_mutators_count check in if case is duplicate with if condition.
The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed.

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>

* update qemuafl

* WIP: Add ability to generate drcov trace using QEMU backend (#1956)

* Document new drcov QEMU plugin

* Add link to lightkeeper for QEMU drcov file loading

---------

Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>

* code format

* changelog

* sleep on uid != 0 afl-system-config

* fix segv about skip_next, warn on unsupported cases of linking options (#1958)

* todos

* ensure afl-cc only allows available compiler modes

* update grammar mutator

* disable aslr on apple

* fix for arm64

* help selective instrumentation

* typos

* macos

* add compiler test script

* apple fixes

* bump nyx submodules (#1963)

* fix docs

* update changelog

* update grammar mutator

* improve compiler test script

* gcc asan workaround (#1966)

* fix github merge fuckup

* fix

* Fix afl-cc (#1968)

- Check if too many cmdline params here, each time before insert a new param.
 - Check if it is "-fsanitize=..." before we do sth.
 - Remove improper param_st transfer.

* Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969)

* Dynamic instrumentation filtering for LLVM native (#1971)

* Add two dynamic instrumentation filter methods to runtime

* Always use pc-table with native pcguard

* Add make_symbol_list.py and README

* changelog

* todos

* new forkserver check

* fix

* nyx test for CI

* improve nyx docs

* Fixes to afl-cc and documentation (#1974)

* Always compile with -ldl when building for CODE_COVERAGE

When building with CODE_COVERAGE, the afl runtime contains code that
calls `dladdr` which requires -ldl. Under most circumstances, clang
already adds this (e.g. when building with pc-table), but there are some
circumstances where it isn't added automatically.

* Add visibility declaration to __afl_connected

When building with hidden visibility, the use of __AFL_LOOP inside such
code can cause linker errors due to __afl_connected being declared
"hidden".

* Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter

* nits

* nyx build script updates

* test error output

* debug ci

* debug ci

* Improve afl-cc (#1975)

* update response file support

 - full support of rsp file
 - fix some segv issues

* Improve afl-cc

 - remove dead code about allow/denylist options of sancov
 - missing `if (!aflcc->have_msan)`
 - add docs for each function
 - typo

* enable nyx

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* fix ci

* clean test script

* NO_NYX

* NO_NYX

* fix ci

* debug ci

* fix ci

* finalize ci fix

* Enhancement on Deterministic stage (#1972)

* fuzzer: init commit based on aflpp 60dc37a8cf

* fuzzers: adding the skip variables and initialize

* log: profile the det/havoc finding

* log: add profile log output

* fuzzers: sperate log/skipdet module

* fuzzers: add quick eff_map calc

* fuzzers: add skip_eff_map in fuzz_one

* fuzzers: mark whole input space in eff_map

* fuzzers: add undet bit threshold to skip some seeds

* fuzzers: fix one byte overflow

* fuzzers: fix overflow

* fix code format

* add havoc only again

* code format

* remove log to INTROSPECTION, rename skipdet module

* rename skipdet module

* remove log to stats

* clean redundant code

* code format

* remove redundant code format check

* remove redundant doc

* remove redundant objects

* clean files

* change -d to default skipdet

* disable deterministic when using CUSTOM_MUTATOR

* revert fix

* final touches for skipdet

* remove unused var

* remove redundant eff struct (#1977)

* update QEMU-Nyx submodule (#1978)

* update QEMU-Nyx submodule (#1980)

* Fix type in AFL_NOOPT env variable in afl-cc help message (#1982)

* nits

* 2024 v4.10c release

* fixes

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>
2024-02-03 10:55:51 +00:00
629edb1e78 Merge pull request #2 from AFLplusplus/stable
push to stable (#1734)
2023-05-22 16:57:45 +03:00
8012b555a8 Merge pull request #1 from AFLplusplus/stable
sync
2023-05-05 23:27:13 +03:00
98 changed files with 2010 additions and 799 deletions

View File

@ -5,7 +5,6 @@ on:
branches:
- stable
- dev
- 420
pull_request:
branches:
- dev # No need for stable-pull-request, as that equals dev-push

View File

@ -27,5 +27,5 @@ keywords:
- qemu
- llvm
- unicorn-emulator
- securiy
- security
license: AGPL-3.0-or-later

View File

@ -52,7 +52,7 @@ endif
ifdef ASAN_BUILD
$(info Compiling ASAN version of binaries)
override CFLAGS += $(ASAN_CFLAGS)
LDFLAGS += $(ASAN_LDFLAGS)
override LDFLAGS += $(ASAN_LDFLAGS)
endif
ifdef UBSAN_BUILD
$(info Compiling UBSAN version of binaries)
@ -106,22 +106,22 @@ ifneq "$(SYS)" "Darwin"
# SPECIAL_PERFORMANCE += -march=native
#endif
#ifndef DEBUG
# CFLAGS_OPT += -D_FORTIFY_SOURCE=1
# 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
LDFLAGS += $(SDK_LD)
override LDFLAGS += $(SDK_LD)
endif
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
ifneq "$(COMPILER_TYPE)" ""
#$(info gcc is being used)
CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
endif
ifeq "$(SYS)" "SunOS"
LDFLAGS = -lkstat -lrt -lsocket -lnsl
override LDFLAGS = -lkstat -lrt -lsocket -lnsl
endif
ifdef STATIC
@ -131,8 +131,8 @@ ifdef STATIC
PYFLAGS=
PYTHON_INCLUDE = /
CFLAGS_OPT += -static
LDFLAGS += -lm -lpthread -lz -lutil
override CFLAGS_OPT += -static
override LDFLAGS += -lm -lpthread -lz -lutil
endif
ifdef PROFILING
@ -759,7 +759,7 @@ endif
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
ifneq "$(SYS)" "Darwin"
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX

View File

@ -44,9 +44,9 @@ endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )

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" heigh="250">
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.20a
GitHub version: 4.21c
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

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

View File

@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
# awk script to minimize a test corpus of input files
#
# based on afl-cmin bash script written by Michal Zalewski
# rewritten by Heiko Eißfeldt (hexcoder-)
# rewritten by Heiko Eissfeldt (hexcoder-)
# tested with:
# gnu awk (x86 Linux)
# bsd awk (x86 *BSD)
@ -108,7 +108,7 @@ function usage() {
"\n" \
"Execution control settings:\n" \
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
" -f file - location read by the fuzzed program (stdin)\n" \
" -f file - location read by the fuzzed program (default: stdin)\n" \
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
" -t msec - run time limit for child process (default: 5000)\n" \
" -O - use binary-only instrumentation (FRIDA mode)\n" \
@ -603,8 +603,8 @@ BEGIN {
# create path for the trace file from afl-showmap
tracefile_path = trace_dir"/"fn
# ensure the file size is not zero
cmd = "du -b "tracefile_path
"ls -l "tracefile_path
cmd = "du -b \""tracefile_path"\""
# "ls -l \""tracefile_path"\""
cmd | getline output
close(cmd)
split(output, result, "\t")

View File

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

View File

@ -124,17 +124,26 @@ kernel.sched_latency_ns=250000000
EOF
}
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
grub_try_disable_mitigation () {
KEY="$1"
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
echo "Configuring performance boot options"
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
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"
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
}
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
fi
}
if grep -E -q '^GRUB_CMDLINE_LINUX=' /etc/default/grub || grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub; then
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX_DEFAULT"
# We also overwrite GRUB_CMDLINE_LINUX because some distributions already overwrite GRUB_CMDLINE_LINUX_DEFAULT
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX"
else
echo "Error: /etc/default/grub with GRUB_CMDLINE_LINUX is not present, cannot set boot options"
fi
echo
echo "Reboot and enjoy your fuzzing"
exit 0

View File

@ -111,7 +111,13 @@ if [ -z "$NO_COLOR" ]; then
RESET="$NC"
fi
CUR_TIME=`date +%s`
PLATFORM=`uname -s`
if [ "$PLATFORM" = "Linux" ] ; then
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
else
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
CUR_TIME=`date +%s`
fi
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
trap "rm -f $TMP" 1 2 3 13 15
@ -123,6 +129,7 @@ START_CNT=0
TOTAL_TIME=0
TOTAL_EXECS=0
TOTAL_EPS=0
TOTAL_EPLM=0
TOTAL_CRASHES=0
TOTAL_HANGS=0
TOTAL_PFAV=0
@ -182,6 +189,8 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
if [ -f "$i" ]; then
IS_STARTING=
IS_DEAD=
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
. "$TMP"
DIRECTORY=$DIR
@ -212,9 +221,6 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
IS_STARTING=
IS_DEAD=
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
if [ "$i" -ot "$j" ]; then
@ -273,11 +279,15 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
ALIVE_CNT=$((ALIVE_CNT + 1))
EXEC_SEC=0
EXEC_MIN=0
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
PATH_PERC=$((cur_item * 100 / corpus_count))
test "$IS_DEAD" = 1 || EXEC_MIN=$(echo $execs_ps_last_min|sed 's/\..*//')
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
TOTAL_EPLM=$((TOTAL_EPLM + EXEC_MIN))
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
@ -399,41 +409,44 @@ if [ -z "$SUMMARY_ONLY" -o -z "$MINIMAL_ONLY" ]; then
echo
fi
echo " Fuzzers alive : $ALIVE_CNT"
echo " Fuzzers alive : $ALIVE_CNT"
if [ ! "$START_CNT" = "0" ]; then
echo " Starting up : $START_CNT ($TXT)"
echo " Starting up : $START_CNT ($TXT)"
fi
if [ ! "$DEAD_CNT" = "0" ]; then
echo " Dead or remote : $DEAD_CNT ($TXT)"
echo " Dead or remote : $DEAD_CNT ($TXT)"
fi
echo " Total run time : $FMT_TIME"
echo " Total run time : $FMT_TIME"
if [ -z "$MINIMAL_ONLY" ]; then
echo " Total execs : $FMT_EXECS"
echo " Cumulative speed : $TOTAL_EPS execs/sec"
echo " Total execs : $FMT_EXECS"
echo " Cumulative speed : $TOTAL_EPS execs/sec"
if [ "$ALIVE_CNT" -gt "0" ]; then
echo " Total average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
fi
fi
if [ "$ALIVE_CNT" -gt "0" ]; then
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
echo "Current average speed : $TOTAL_EPLM execs/sec"
fi
if [ -z "$MINIMAL_ONLY" ]; then
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
fi
if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then
if [ "$ALIVE_CNT" -gt "0" ]; then
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
fi
fi
echo " Coverage reached : ${TOTAL_COVERAGE}%"
echo " Crashes saved : $TOTAL_CRASHES"
echo " Coverage reached : ${TOTAL_COVERAGE}%"
echo " Crashes saved : $TOTAL_CRASHES"
if [ -z "$MINIMAL_ONLY" ]; then
echo " Hangs saved : $TOTAL_HANGS"
echo "Cycles without finds : $TOTAL_WCOP"
echo " Hangs saved : $TOTAL_HANGS"
echo " Cycles without finds : $TOTAL_WCOP"
fi
echo " Time without finds : $TOTAL_LAST_FIND"
echo " Time without finds : $TOTAL_LAST_FIND"
echo
exit 0

View File

@ -1,13 +1,13 @@
CPU | MHz | threads | singlecore | multicore | afl-*-config |
====================================================|=======|=========|============|===========|==============|
Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|CPU | MHz | threads | singlecore | multicore | afl-*-config |
|----------------------------------------------------|-------|---------|------------|-----------|--------------|
|Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |

View File

@ -205,7 +205,7 @@ async def save_benchmark_results() -> None:
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
cores = str(args.fuzzers).ljust(7)
comparisonfile.write(f"{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
comparisonfile.write(f"|{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
with open("COMPARISON.md", "r") as comparisonfile:
print(comparisonfile.read())

View File

@ -1,3 +1,4 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
typedef struct my_mutator {

View File

@ -1,9 +1,6 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
typedef struct my_mutator {
afl_state_t *afl;
@ -155,7 +152,7 @@ int main(int argc, char *argv[]) {
return -1;
}
if (verbose) fprintf(stderr, "Mutation output length: %zu\n", outlen);
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n");

View File

@ -1 +1 @@
5ed4f8d
95a6857

View File

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

View File

@ -3,12 +3,52 @@
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.20a (dev)
### Version ++4.21c (release)
* afl-fuzz
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
do a switch from gettimeofday() to clock_gettime() which should be rather
three times faster. The reason for this is unknown.
- new queue selection algorithm based on 2 core years of queue data
analysis. gives a noticable improvement on coverage although the results
seem counterintuitive :-)
- added AFL_DISABLE_REDUNDANT for huge queues
- added `AFL_NO_SYNC` environment variable that does what you think it does
- fix AFL_PERSISTENT_RECORD
- run custom_post_process after standard trimming
- prevent filenames in the queue that have spaces
- minor fix for FAST schedules
- more frequent stats update when syncing (todo: check performance impact)
- now timing of calibration, trimming and syncing is measured seperately,
thanks to @eqv!
- -V timing is now accurately the fuzz time (without syncing), before
long calibration times and syncing could result in now fuzzing being
made when the time was already run out until then, thanks to @eqv!
- fix -n uninstrumented mode when ending fuzzing
- enhanced the ASAN configuration
- make afl-fuzz use less memory with cmplog and fix a memleak
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode for i386
- fix COMPCOV split compare for old LLVMs
- disable xml/curl/g_ string transform functions because we do not check
for null pointers ... TODO
- ensure shared memory variables are visible in weird build setups
- compatability to new LLVM 19 changes
* afl-cmin
- work with input files that have a space
* afl-showmap
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
- minor fix to collect coverage -C (thanks to @bet4it)
* Fixed a shmem mmap bug (that rarely came up on MacOS)
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built
for CMPLOG/Redqueen, but new compiled targets will not work with
old afl-fuzz versions!
! Recompiled all targets that are instrumented for CMPLOG/Redqueen!
! Recompile all targets that are instrumented for CMPLOG/Redqueen!
- AFL++ now supports up to 4 billion coverage edges, up from 6 million.
- New compile option: `make PERFORMANCE=1` - this will enable special
CPU dependent optimizations that make everything more performant - but
@ -22,15 +62,27 @@
- small improvements to CMPLOG/redqueen
- workround for a bug with MOpt -L when used with -M - in the future
we will either remove or rewrite MOpt.
- fix for `-t xxx+` feature
- -e extension option now saves the queue items, crashes, etc. with the
extension too
- fixes for trimmming, correct -V time and reading stats on resume by eqv
thanks a lot!
- afl-cc:
- added collision free caller instrumentation to LTO mode. activate with
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
- fixes for COMPCOV/LAF and most other modules
- fix for GCC_PLUGIN cmplog that broke on std::strings
- afl-whatsup:
- now also displays current average speed
- small bugfixes
- custom mutators:
- fixes for aflpp custom mutator and standalone tool
- important fix to the symcc custom mutator
- Minor edits to afl-persistent-config
- Prevent temporary files being left behind on aborted afl-whatsup
- More CPU benchmarks added to benchmark/
### Version ++4.10c (release)
- afl-fuzz:
- default power schedule is now EXPLORE, due a fix in fast schedules

View File

@ -21,7 +21,7 @@ If you want to build AFL++ yourself, you have many options. The easiest choice
is to build and install everything:
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
whatever llvm version is available. We recommend llvm 13, 14, 15 or 16.
whatever llvm version is available. We recommend llvm 13 or newer.
```shell
sudo apt-get update
@ -67,7 +67,7 @@ These build targets exist:
* unit: perform unit tests (based on cmocka)
* help: shows these build options
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
[Unless you are on macOS](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
you can also build statically linked versions of the AFL++ binaries by passing
the `PERFORMANCE=1` argument to make:
@ -77,10 +77,10 @@ make PERFORMANCE=1
These build options exist:
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended!
* STATIC - compile AFL++ static
* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended (except on macOS)!
* STATIC - compile AFL++ static (does not work on macOS)
* CODE_COVERAGE - compile the target for code coverage (see [README.llvm.md](../instrumentation/README.llvm.md))
* ASAN_BUILD - compiles AFL++ with address sanitizer for debug purposes
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
* LLVM_DEBUG - shows llvm deprecation warnings
@ -92,7 +92,7 @@ These build options exist:
* NO_NYX - disable building nyx mode dependencies
* NO_CORESIGHT - disable building coresight (arm64 only)
* NO_UNICORN_ARM64 - disable building unicorn on arm64
* AFL_NO_X86 - if compiling on non-intel/amd platforms
* AFL_NO_X86 - if compiling on non-Intel/AMD platforms
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
e.g.: `make LLVM_CONFIG=llvm-config-14`
@ -101,8 +101,19 @@ e.g.: `make LLVM_CONFIG=llvm-config-14`
macOS has some gotchas due to the idiosyncrasies of the platform.
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
instructions for Linux. If possible, avoid Xcode at all cost.
macOS supports SYSV shared memory used by AFL++'s instrumentation, but the
default settings aren't sufficient. Before even building, increase
them by running the provided script:
```shell
sudo afl-system-config
```
See
[https://www.spy-hill.com/help/apple/SharedMemory.html](https://www.spy-hill.com/help/apple/SharedMemory.html)
for documentation for the shared memory settings and how to make them permanent.
Next, to build AFL++, install the following packages from brew:
```shell
brew install wget git make cmake llvm gdb coreutils
@ -113,38 +124,37 @@ You can check with `brew info llvm` to know where, then create a variable for it
```shell
export HOMEBREW_BASE="/opt/homebrew/opt"
# or
```
or
```shell
export HOMEBREW_BASE="/usr/local/opt"
```
Be sure to setup `PATH` to point to the correct clang binaries and use the
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
Set `PATH` to point to the brew clang, clang++, llvm-config, gmake and coreutils.
Also use the brew clang compiler; the Xcode clang compiler must not be used.
```shell
export PATH="$HOMEBREW_BASE/coreutils/libexec/gnubin:/usr/local/bin:$HOMEBREW_BASE/llvm/bin:$PATH"
export CC=clang
export CXX=clang++
gmake
cd frida_mode
gmake
cd ..
sudo gmake install
```
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
Then build following the general Linux instructions.
If everything worked, you should then have `afl-clang-fast` installed, which you can check with:
```shell
which afl-clang-fast
```
Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
The crash reporting daemon that comes by default with macOS will cause
problems with fuzzing. You need to turn it off:
problems with fuzzing. You need to turn it off, which you can do with `afl-system-config`.
```
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
```
The `fork()` semantics on OS X are a bit unusual compared to other unix systems
The `fork()` semantics on macOS are a bit unusual compared to other unix systems
and definitely don't look POSIX-compliant. This means two things:
- Fuzzing will be probably slower than on Linux. In fact, some folks report
@ -157,39 +167,3 @@ 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.
macOS supports SYSV shared memory used by AFL's instrumentation, but the
default settings aren't usable with AFL++. The default settings on 10.14 seem to
be:
```bash
$ ipcs -M
IPC status from <running system> as of XXX
shminfo:
shmmax: 4194304 (max shared memory segment size)
shmmin: 1 (min shared memory segment size)
shmmni: 32 (max number of shared memory identifiers)
shmseg: 8 (max shared memory segments per process)
shmall: 1024 (max amount of shared memory in pages)
```
To temporarily change your settings to something minimally usable with AFL++,
run these commands as root:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmall=4096
```
If you're running more than one instance of AFL, you likely want to make
`shmall` bigger and increase `shmseg` as well:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmseg=48
sysctl kern.sysv.shmall=98304
```
See
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
for documentation for these settings and how to make them permanent.

View File

@ -266,6 +266,11 @@ trimmed input. Here's a quick API description:
Omitting any of three trimming methods will cause the trimming to be disabled
and trigger a fallback to the built-in default trimming routine.
**IMPORTANT** If you have a custom post process mutator that needs to be run
after trimming, you must call it yourself at the end of your successful
trimming!
### Environment Variables
Optionally, the following environment variables are supported:

View File

@ -381,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
usually a bad idea!
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
This can be useful with huge queues.
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
new coverage
@ -547,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool:
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
arguments.
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
of their contents, rather than use the standard `id:000000,...` names.
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
by some users for unorthodox parallelized fuzzing setups, but not advisable
otherwise.
@ -582,6 +588,9 @@ checks or alter some of the more exotic semantics of the tool:
between fuzzing instances synchronization. Default sync time is 30 minutes,
note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
other syncing parameters.
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would

View File

@ -958,7 +958,7 @@ too long for your overall available fuzz run time.
campaign but not good for short CI runs.
How this can look like can, e.g., be seen at AFL++'s setup in Google's
[oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
[previous oss-fuzz version](https://github.com/google/oss-fuzz/blob/3e2c5312417d1a6f9564472f3df1fd27759b289d/infra/base-images/base-builder/compile_afl)
and
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).

View File

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

View File

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

View File

@ -2,7 +2,7 @@
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep -E 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep 'Frida\ [0-9.]*'|head -n 1|sed 's/.*Frida\ //'| sed 's/<\/h2>//')
echo Current set version: $OLD
echo Newest available version: $NEW

View File

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

View File

@ -5,9 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
Dominik Maier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -139,6 +139,10 @@
#define AFL_RAND_RETURN u32
#endif
#ifndef INTERESTING_32_LEN
#error INTERESTING_32_LEN not defined - BUG!
#endif
extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32
@ -452,7 +456,8 @@ typedef struct afl_env_vars {
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems;
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames, afl_no_sync;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -648,7 +653,11 @@ typedef struct afl_state {
longest_find_time, /* Longest time taken for a find */
exit_on_time, /* Delay to exit if no new paths */
sync_time, /* Sync time (ms) */
switch_fuzz_mode; /* auto or fixed fuzz mode */
switch_fuzz_mode, /* auto or fixed fuzz mode */
calibration_time_us, /* Time spend on calibration */
sync_time_us, /* Time spend on sync */
cmplog_time_us, /* Time spend on cmplog */
trim_time_us; /* Time spend on trimming */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
subseq_tmouts; /* Number of timeouts in a row */
@ -1215,6 +1224,11 @@ void show_stats_normal(afl_state_t *);
void show_stats_pizza(afl_state_t *);
void show_init_stats(afl_state_t *);
void update_calibration_time(afl_state_t *afl, u64 *time);
void update_trim_time(afl_state_t *afl, u64 *time);
void update_sync_time(afl_state_t *afl, u64 *time);
void update_cmplog_time(afl_state_t *afl, u64 *time);
/* StatsD */
void statsd_setup_format(afl_state_t *afl);
@ -1264,6 +1278,7 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *);
u64 get_binary_hash(u8 *fn);
void check_if_tty(afl_state_t *);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);
@ -1397,6 +1412,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
char *sha1_hex(const u8 *data, size_t len);
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
char *sha1_hex_for_file(const char *fname, u32 len);
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
* enabled. */
static inline int permissive_create(afl_state_t *afl, const char *fn) {
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) {
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
PFATAL("Unable to create '%s'", fn);
}
}
return fd;
}
#if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1
#endif

View File

@ -30,10 +30,17 @@
#include <stdbool.h>
#include <inttypes.h>
#include "afl-fuzz.h"
#define MUT_STRATEGY_ARRAY_SIZE 256
#ifndef INTERESTING_32
#error INTERESTING_32 is not defined - BUG!
#endif
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
enum {
/* 00 */ MUT_FLIPBIT,

View File

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

View File

@ -28,7 +28,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
static unsigned short int inited = 0;
char tcase[PATH_MAX];
if (is_replay_record) {
if (is_replay_record && cycle_cnt) {
if (!inited) {
@ -59,7 +59,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
}
return --cycle_cnt;
return cycle_cnt--;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,17 +21,18 @@ static char *afl_environment_variables[] = {
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
"AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
"AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
@ -80,14 +81,13 @@ static char *afl_environment_variables[] = {
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
"AFL_LLVM_LTO_SKIPINIT"
"AFL_LLVM_LTO_STARTID",
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
#if defined USE_COLOR && !defined ALWAYS_COLORED
"AFL_NO_COLOR", "AFL_NO_COLOUR",
#endif
"AFL_NO_CPU_RED",
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
@ -95,27 +95,27 @@ static char *afl_environment_variables[] = {
"AFL_MAX_DET_EXTRAS",
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
"AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH",
"AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD",
"AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV",
"AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV",
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
"AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR",
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR",
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM",
"AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
"AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES",
"AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE",
"AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH",
"AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
"AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST",
"AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME",
"AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT",
"AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_USE_ASAN",
"AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN",
"AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
"AFL_NYX_HANDLE_INVALID_WRITE", "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT",
"AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE",
"AFL_PERSISTENT_RECORD", "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD",
"AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN",
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS",
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL",
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
"AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET",
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
};

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>>
@ -188,6 +188,8 @@ typedef struct afl_forkserver {
u8 persistent_mode;
u32 max_length;
#ifdef __linux__
nyx_plugin_handler_t *nyx_handlers;
char *out_dir_path; /* path to the output directory */

View File

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

View File

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

View File

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

View File

@ -207,7 +207,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_first(
return (unsigned)__builtin_e2k_addcd_c(base, addend, 0);
}
\
#define add64carry_first(base, addend, sum) \
e2k_add64carry_first(base, addend, sum)
@ -218,7 +218,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_next(
return (unsigned)__builtin_e2k_addcd_c(base, addend, carry);
}
\
#define add64carry_next(carry, base, addend, sum) \
e2k_add64carry_next(carry, base, addend, sum)
@ -230,7 +230,7 @@ static __maybe_unused __always_inline void e2k_add64carry_last(unsigned carry,
*sum = __builtin_e2k_addcd(base, addend, carry);
}
\
#define add64carry_last(carry, base, addend, sum) \
e2k_add64carry_last(carry, base, addend, sum)
#endif /* __iset__ >= 5 */
@ -311,7 +311,7 @@ static __forceinline char msvc32_add64carry_first(uint64_t base,
base_32h, addend_32h, sum32 + 1);
}
\
#define add64carry_first(base, addend, sum) \
msvc32_add64carry_first(base, addend, sum)
@ -328,7 +328,7 @@ static __forceinline char msvc32_add64carry_next(char carry, uint64_t base,
base_32h, addend_32h, sum32 + 1);
}
\
#define add64carry_next(carry, base, addend, sum) \
msvc32_add64carry_next(carry, base, addend, sum)
@ -345,7 +345,7 @@ static __forceinline void msvc32_add64carry_last(char carry, uint64_t base,
addend_32h, sum32 + 1);
}
\
#define add64carry_last(carry, base, addend, sum) \
msvc32_add64carry_last(carry, base, addend, sum)
#endif /* _MSC_FULL_VER >= 190024231 */
@ -454,7 +454,7 @@ typedef struct {
uint64_t unaligned_64;
} __attribute__((__packed__)) t1ha_unaligned_proxy;
\
#define read_unaligned(ptr, bits) \
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
t1ha_unaligned_proxy, unaligned_##bits))) \
@ -539,6 +539,7 @@ static __always_inline const uint64_t *__attribute__((
(void)(ptr); \
\
} while (0)
#endif
#endif /* prefetch */

View File

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

View File

@ -1734,7 +1734,7 @@ XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t *src);
* These declarations should only be used with static linking.
* Never use them in association with dynamic linking!
*****************************************************************************
*/
*/
/*
* These definitions are only present to allow static allocation
@ -2399,9 +2399,9 @@ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(
#define XXH_NO_STREAM
#undef XXH_NO_STREAM /* don't actually */
#endif /* XXH_DOXYGEN */
/*!
* @}
*/
/*!
* @}
*/
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command \
line for example */
@ -2614,6 +2614,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
_Static_assert((c), m); \
\
} while (0)
#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */
#define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \
do { \
@ -2621,6 +2622,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
static_assert((c), m); \
\
} while (0)
#else
#define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \
do { \
@ -2632,6 +2634,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
}; \
\
} while (0)
#endif
#define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c), #c)
#endif
@ -2850,7 +2853,7 @@ static int XXH_isLittleEndian(void) {
return one.c[0];
}
\
#define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
#endif
#endif
@ -4679,6 +4682,7 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) {
acc = svadd_u64_x(mask, acc, mul); \
\
} while (0)
#endif /* XXH_VECTOR == XXH_SVE */
/* prefetch
@ -4737,12 +4741,14 @@ static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {
};
static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!<
0b0001011001010110011001111001000110011110001101110111100111111001
*/
static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!<
0b1001111110110010000111000110010100011110100110001101111100100101
*/
static const xxh_u64 PRIME_MX1 =
0x165667919E3779F9ULL; /*!<
0b0001011001010110011001111001000110011110001101110111100111111001
*/
static const xxh_u64 PRIME_MX2 =
0x9FB21C651E98DF25ULL; /*!<
0b1001111110110010000111000110010100011110100110001101111100100101
*/
#ifdef XXH_OLD_NAMES
#define kSecret XXH3_kSecret
@ -7854,7 +7860,7 @@ XXH3_128bits_digest(XXH_NOESCAPE const XXH3_state_t *state) {
}
#endif /* !XXH_NO_STREAM */
/* 128-bit utility functions */
/* 128-bit utility functions */
#include <string.h> /* memcmp, memcpy */

View File

@ -486,7 +486,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
}
@ -1304,7 +1304,12 @@ u32 countCallers(Function *F) {
for (auto *U : F->users()) {
if (auto *CI = dyn_cast<CallInst>(U)) { ++callers; }
if (auto *CI = dyn_cast<CallInst>(U)) {
++callers;
(void)(CI);
}
}

View File

@ -195,7 +195,7 @@ class ModuleSanitizerCoverageAFL
SanitizerCoverageOptions Options;
uint32_t instr = 0, selects = 0, unhandled = 0;
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
GlobalVariable *AFLMapPtr = NULL;
ConstantInt *One = NULL;
ConstantInt *Zero = NULL;
@ -330,6 +330,8 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
if (getenv("AFL_DEBUG")) { debug = 1; }
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
@ -638,6 +640,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
// InjectTraceForCmp(F, CmpTraceTargets);
// InjectTraceForSwitch(F, SwitchTraceTargets);
if (dump_cc) { calcCyclomaticComplexity(&F); }
}
GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(

View File

@ -1617,7 +1617,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
if (pc_filter) {
if (pc_filter && !mod_info->next) {
char PcDescr[1024];
// This function is a part of the sanitizer run-time.
@ -1644,7 +1644,8 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
if (__afl_filter_pcs && strstr(mod_info->name, __afl_filter_pcs_module)) {
if (__afl_filter_pcs && !mod_info->next &&
strstr(mod_info->name, __afl_filter_pcs_module)) {
u32 result_index;
if (locate_in_pcs(PC, &result_index)) {
@ -1669,7 +1670,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
mod_info->mapped = 1;
if (__afl_pcmap_ptr) { mod_info->mapped = 1; }
if (__afl_debug) {
@ -1848,7 +1849,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
to avoid duplicate calls (which can happen as an artifact of the underlying
implementation in LLVM). */
if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries
if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries
*(start++) = ++__afl_final_loc;

View File

@ -180,19 +180,19 @@ struct afl_cmptrs_pass : afl_base_pass {
c = DECL_CONTEXT(c);
if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
/* Check that the first nonstatic data member of the record type
/* Check that the first nonstatic named data member of the record type
is named _M_dataplus. */
for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
if (TREE_CODE(c) == FIELD_DECL) break;
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
return false;
/* Check that the second nonstatic data member of the record type
/* Check that the second nonstatic named data member of the record type
is named _M_string_length. */
tree f2;
for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
if (TREE_CODE(f2) == FIELD_DECL) break;
if (TREE_CODE(f2) == FIELD_DECL && DECL_NAME(f2)) break;
if (!f2 /* No need to check this field's offset. */
|| strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
return false;
@ -208,9 +208,12 @@ struct afl_cmptrs_pass : afl_base_pass {
strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
return false;
/* And its first data member is named _M_p. */
/* And its first nonstatic named data member should be named _M_p.
There may be (unnamed) subobjects from empty base classes. We
skip the subobjects, then check the offset of the first data
member. */
for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
if (TREE_CODE(c) == FIELD_DECL) break;
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
return false;

View File

@ -26,6 +26,51 @@ static std::list<std::string> allowListFunctions;
static std::list<std::string> denyListFiles;
static std::list<std::string> denyListFunctions;
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
unsigned int numBlocks = 0;
unsigned int numEdges = 0;
unsigned int numCalls = 0;
// Iterate through each basic block in the function
for (BasicBlock &BB : *F) {
// count all nodes == basic blocks
numBlocks++;
// Count the number of successors (outgoing edges)
for (BasicBlock *Succ : successors(&BB)) {
// count edges for CC
numEdges++;
(void)(Succ);
}
for (Instruction &I : BB) {
// every call is also an edge, so we need to count the calls too
if (isa<CallInst>(&I) || isa<InvokeInst>(&I)) { numCalls++; }
}
}
// Cyclomatic Complexity V(G) = E - N + 2P
// For a single function, P (number of connected components) is 1
// Calls are considered to be an edge
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
// if (debug) {
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
F->getName().str().c_str(), CC);
//}
return CC;
}
char *getBBName(const llvm::BasicBlock *BB) {
static char *name;
@ -91,7 +136,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
for (auto const &ignoreListFunc : ignoreList) {
#if LLVM_VERSION_MAJOR >= 19
if (F->getName().starts_with(ignoreListFunc)) { return true; }
#else
if (F->getName().startswith(ignoreListFunc)) { return true; }
#endif
}

View File

@ -55,6 +55,7 @@ void initInstrumentList();
bool isInInstrumentList(llvm::Function *F, std::string Filename);
unsigned long long int calculateCollisions(uint32_t edges);
void scanForDangerousFunctions(llvm::Module *M);
unsigned int calcCyclomaticComplexity(llvm::Function *F);
#ifndef IS_EXTERN
#define IS_EXTERN

View File

@ -746,7 +746,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
auto PA = PreservedAnalyses::all();
return PA;
#else
return true;
return false;
#endif
}

View File

@ -128,7 +128,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(AFLCoverage());
@ -212,10 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) {
u32 rand_seed;
unsigned int cur_loc = 0;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@ -1081,7 +1081,7 @@ bool AFLCoverage::runOnModule(Module &M) {
}
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
return PreservedAnalyses();
#else
return true;
#endif

View File

@ -680,13 +680,16 @@ bool CmpLogInstructions::runOnModule(Module &M) {
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookInstrs(M);
bool ret = hookInstrs(M);
verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */
return PreservedAnalyses::all();
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -758,16 +758,16 @@ bool CmpLogRoutines::runOnModule(Module &M) {
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookRtns(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookRtns(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -442,16 +442,16 @@ bool CmplogSwitches::runOnModule(Module &M) {
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookInstrs(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookInstrs(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -54,6 +54,12 @@
#define nullptr 0
#endif
#if LLVM_MAJOR >= 19
#define STARTSWITH starts_with
#else
#define STARTSWITH startswith
#endif
#include <set>
#include "afl-llvm-common.h"
@ -89,7 +95,7 @@ class CompareTransform : public ModulePass {
#endif
return "cmplog transform";
return "compcov transform";
}
@ -123,7 +129,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(CompareTransform());
@ -226,38 +236,38 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
isStrcmp &=
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
(!FuncName.compare("strcmp") /*|| !FuncName.compare("xmlStrcmp") ||
!FuncName.compare("xmlStrEqual") ||
!FuncName.compare("curl_strequal") ||
!FuncName.compare("strcsequal") ||
!FuncName.compare("g_strcmp0"));
!FuncName.compare("g_strcmp0")*/);
isMemcmp &=
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
!FuncName.compare("CRYPTO_memcmp") ||
!FuncName.compare("OPENSSL_memcmp") ||
!FuncName.compare("memcmp_const_time") ||
!FuncName.compare("memcmpct"));
isStrncmp &= (!FuncName.compare("strncmp") ||
isStrncmp &= (!FuncName.compare("strncmp")/* ||
!FuncName.compare("curl_strnequal") ||
!FuncName.compare("xmlStrncmp"));
!FuncName.compare("xmlStrncmp")*/);
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
!FuncName.compare("stricmp") ||
!FuncName.compare("ap_cstr_casecmp") ||
!FuncName.compare("OPENSSL_strcasecmp") ||
!FuncName.compare("xmlStrcasecmp") ||
/*!FuncName.compare("xmlStrcasecmp") ||
!FuncName.compare("g_strcasecmp") ||
!FuncName.compare("g_ascii_strcasecmp") ||
!FuncName.compare("Curl_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||*/
!FuncName.compare("cmsstrcasecmp"));
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
!FuncName.compare("strnicmp") ||
!FuncName.compare("ap_cstr_casecmpn") ||
!FuncName.compare("OPENSSL_strncasecmp") ||
!FuncName.compare("OPENSSL_strncasecmp") /*||
!FuncName.compare("xmlStrncasecmp") ||
!FuncName.compare("g_ascii_strncasecmp") ||
!FuncName.compare("Curl_strncasecompare") ||
!FuncName.compare("g_strncasecmp"));
!FuncName.compare("g_strncasecmp")*/);
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
@ -461,8 +471,20 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool isCaseInsensitive = false;
bool needs_null = false;
bool success_is_one = false;
bool nullCheck = false;
Function *Callee = callInst->getCalledFunction();
/*
fprintf(stderr, "%s - %s - %s\n",
callInst->getParent()
->getParent()
->getParent()
->getName()
.str()
.c_str(),
callInst->getParent()->getParent()->getName().str().c_str(),
Callee ? Callee->getName().str().c_str() : "NULL");*/
if (Callee) {
if (!Callee->getName().compare("memcmp") ||
@ -516,6 +538,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
}
if (!isSizedcmp) needs_null = true;
if (Callee->getName().STARTSWITH("g_") ||
Callee->getName().STARTSWITH("curl_") ||
Callee->getName().STARTSWITH("Curl_") ||
Callee->getName().STARTSWITH("xml"))
nullCheck = true;
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
@ -600,8 +627,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
/* split before the call instruction */
BasicBlock *bb = callInst->getParent();
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
BasicBlock *next_lenchk_bb = NULL;
if (nullCheck) { fprintf(stderr, "TODO: null check\n"); }
if (isSizedcmp && !isConstSized) {
next_lenchk_bb =
@ -746,6 +775,8 @@ bool CompareTransform::runOnModule(Module &M) {
#endif
bool ret = false;
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
printf(
"Running compare-transform-pass by laf.intel@gmail.com, extended by "
@ -753,11 +784,7 @@ bool CompareTransform::runOnModule(Module &M) {
else
be_quiet = 1;
#if LLVM_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
transformCmps(M, true, true, true, true, true);
if (transformCmps(M, true, true, true, true, true) == true) ret = true;
verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */
@ -767,9 +794,18 @@ bool CompareTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == true) {
return PreservedAnalyses();
} else {
return PreservedAnalyses::all();
}
#else
return true;
return ret;
#endif
}

View File

@ -204,6 +204,8 @@ bool InjectionRoutines::hookRtns(Module &M) {
Function *FuncPtr;
#endif
bool ret = false;
/* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) {
@ -281,6 +283,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
ret = true;
Value *parameter = callInst->getArgOperand(param);
@ -299,7 +302,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
}
return true;
return ret;
}
@ -328,16 +331,16 @@ bool InjectionRoutines::runOnModule(Module &M) {
if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; }
if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; }
hookRtns(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookRtns(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -1,7 +1,7 @@
/*
* Copyright 2016 laf-intel
* extended for floating point by Heiko Eißfeldt
* adapted to new pass manager by Heiko Eißfeldt
* extended for floating point by Heiko Eissfeldt
* adapted to new pass manager by Heiko Eissfeldt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -189,7 +189,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitComparesTransform());
@ -262,8 +266,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
/* this is probably not needed but we do it anyway */
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
int constants = 0;
if (llvm::isa<llvm::Constant>(op0)) { ++constants; }
if (llvm::isa<llvm::Constant>(op1)) { ++constants; }
if (constants != 1) { continue; }
fcomps.push_back(selectcmpInst);
@ -935,7 +942,7 @@ size_t SplitComparesTransform::nextPowerOfTwo(size_t in) {
/* splits fcmps into two nested fcmps with sign compare and the rest */
size_t SplitComparesTransform::splitFPCompares(Module &M) {
size_t count = 0;
size_t counts = 0;
LLVMContext &C = M.getContext();
@ -951,7 +958,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
} else {
return count;
return counts;
}
@ -1004,7 +1011,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
}
if (!fcomps.size()) { return count; }
if (!fcomps.size()) { return counts; }
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
@ -1690,11 +1697,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
#else
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
#endif
++count;
++counts;
}
return count;
return counts;
}
@ -1743,10 +1750,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}
#if LLVM_MAJOR >= 11
auto PA = PreservedAnalyses::all();
#endif
if (enableFPSplit) {
simplifyFPCompares(M);
@ -1778,15 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
auto op0 = CI->getOperand(0);
auto op1 = CI->getOperand(1);
if (!op0 || !op1) {
#if LLVM_MAJOR >= 11
return PA;
#else
return false;
#endif
}
// has to valid operands
if (!op0 || !op1) { continue; }
// has exactly one constant and one variable
int constants = 0;
if (dyn_cast<ConstantInt>(op0)) { ++constants; }
if (dyn_cast<ConstantInt>(op1)) { ++constants; }
if (constants != 1) { continue; }
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
if (iTy1 && isa<IntegerType>(op1->getType())) {
@ -1814,6 +1815,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}
bool ret = count == 0 ? false : true;
bool brokenDebug = false;
if (verifyModule(M, &errs()
#if LLVM_VERSION_MAJOR >= 4 || \
@ -1852,9 +1855,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -137,7 +137,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitSwitchesTransform());
@ -516,11 +520,7 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
else
be_quiet = 1;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
splitSwitches(M);
bool ret = splitSwitches(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
@ -530,9 +530,12 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -1 +1 @@
40033af00c
a6f0632a65

View File

@ -202,6 +202,8 @@ QEMU_CONF_FLAGS=" \
--disable-xfsctl \
--target-list="${CPU_TARGET}-linux-user" \
--without-default-devices \
--extra-cflags=-Wno-int-conversion \
--disable-werror \
"
if [ -n "${CROSS_PREFIX}" ]; then
@ -215,8 +217,10 @@ if [ "$STATIC" = "1" ]; then
echo Building STATIC binary
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
# plugin support requires dynamic linking
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
--static --disable-pie \
--disable-plugins \
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
"
@ -241,7 +245,6 @@ if [ "$DEBUG" = "1" ]; then
--enable-debug-stack-usage \
--enable-debug-tcg \
--enable-qom-cast-debug \
--enable-werror \
"
else
@ -252,7 +255,6 @@ else
--disable-debug-tcg \
--disable-qom-cast-debug \
--disable-stack-protector \
--disable-werror \
--disable-docs \
"

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -17,6 +17,10 @@
#define AFL_MAIN
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include "common.h"
#include "config.h"
#include "types.h"
@ -32,7 +36,9 @@
#include <limits.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@ -464,6 +470,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) {
*slash = 0;
tmp = alloc_printf("%s/%s", exepath, obj);
if (aflcc->debug) DEBUGF("Trying %s\n", tmp);
if (!access(tmp, R_OK)) { return tmp; }
ck_free(tmp);
@ -517,8 +525,8 @@ void find_built_deps(aflcc_state_t *aflcc) {
char *ptr = NULL;
#if defined(__x86_64__)
if ((ptr = find_object(aflcc, "as")) != NULL) {
#if defined(__x86_64__) || defined(__i386__)
if ((ptr = find_object(aflcc, "afl-as")) != NULL) {
#ifndef __APPLE__
// on OSX clang masquerades as GCC
@ -828,7 +836,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) {
}
if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX;
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX"))
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") ||
getenv("AFL_LLVM_LTO_CTX"))
aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
if (getenv("AFL_LLVM_NGRAM_SIZE")) {
@ -1260,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
aflcc->lto_mode = 1;
// force CFG
// if (!aflcc->instrument_mode) {
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
// }
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
aflcc->lto_mode = 1;
@ -1368,6 +1372,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
}
if (getenv("AFL_LLVM_DICT2FILE") &&
(getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")))
FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*");
aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") ||
getenv("AFL_GCC_CMPLOG");
@ -1575,8 +1586,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) {
insert_param(aflcc,
"-D__AFL_FUZZ_INIT()="
"int __afl_sharedmem_fuzzing = 1;"
"extern unsigned int *__afl_fuzz_len;"
"extern unsigned char *__afl_fuzz_ptr;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned int *__afl_fuzz_len;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned char *__afl_fuzz_ptr;"
"unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
@ -1898,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
}
add_defs_fortify(aflcc, 0);
if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); }
if (!aflcc->have_asan) {
insert_param(aflcc, "-fsanitize=address");
insert_param(aflcc, "-fno-common");
}
aflcc->have_asan = 1;
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
@ -2347,8 +2366,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined");
insert_param(aflcc, "dynamic_lookup");
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
@ -2379,7 +2397,11 @@ void add_runtime(aflcc_state_t *aflcc) {
if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
strncmp(libdir, "/lib", 4)) {
#ifdef __APPLE__
u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR);
#else
u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR);
#endif
insert_param(aflcc, libdir_opt);
}
@ -2461,13 +2483,60 @@ void add_runtime(aflcc_state_t *aflcc) {
*/
void add_assembler(aflcc_state_t *aflcc) {
u8 *afl_as = find_object(aflcc, "as");
u8 *afl_as = find_object(aflcc, "afl-as");
if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as').");
if (!afl_as) FATAL("Cannot find 'afl-as'.");
u8 *slash = strrchr(afl_as, '/');
if (slash) *slash = 0;
// Search for 'as' may be unreliable in some cases (see #2058)
// so use 'afl-as' instead, because 'as' is usually a symbolic link,
// or can be a renamed copy of 'afl-as' created in the same dir.
// Now we should verify if the compiler can find the 'as' we need.
#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')"
u8 *afl_as_dup = alloc_printf("%s/as", afl_as);
int fd = open(afl_as_dup, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); }
struct stat st;
if (fstat(fd, &st) < 0) {
PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup);
}
u32 f_len = st.st_size;
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) {
PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup);
}
close(fd);
// "AFL_AS" is a const str passed to getenv in afl-as.c
if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) {
FATAL(
"Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. "
"It is a prerequisite to override system-wide 'as' for "
"instrumentation.",
afl_as_dup, afl_as);
}
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
ck_free(afl_as_dup);
#undef AFL_AS_ERR
insert_param(aflcc, "-B");
insert_param(aflcc, afl_as);
@ -2724,11 +2793,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
"MODES: NCC PERSIST DICT LAF "
"CMPLOG SELECT\n"
" [LLVM] LLVM: %s%s\n"
" PCGUARD %s yes yes module yes yes "
" PCGUARD %s yes yes module yes yes "
"yes\n"
" NATIVE AVAILABLE no yes no no "
"part. yes\n"
" CLASSIC %s no yes module yes yes "
" CLASSIC %s no yes module yes yes "
"yes\n"
" - NORMAL\n"
" - CALLER\n"
@ -2745,10 +2814,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" [GCC/CLANG] simple gcc/clang: %s%s\n"
" CLASSIC DEFAULT no no no no no "
"no\n\n",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->compiler_mode == LLVM ? " [SELECTED]" : "",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_lto ? "AVAILABLE" : "unavailable!",
aflcc->compiler_mode == LTO ? " [SELECTED]" : "",
aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!",
@ -2774,7 +2843,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -34,6 +34,7 @@
#endif
#include <string.h>
#include <strings.h>
#include <time.h>
#include <math.h>
#include <sys/mman.h>
@ -86,9 +87,10 @@ void set_sanitizer_defaults() {
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
u8 have_san_options = 0;
u8 default_options[1024] =
"detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
"return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
"sigfpe=0:handle_sigill=0:";
"detect_odr_violation=0:abort_on_error=1:symbolize=0:"
"allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:"
"detect_stack_use_after_return=0:check_initialization_order=0:";
if (have_asan_options || have_ubsan_options || have_msan_options ||
have_lsan_options) {
@ -985,7 +987,7 @@ inline u64 get_cur_time(void) {
/* Get unix time in microseconds */
u64 get_cur_time_us(void) {
inline u64 get_cur_time_us(void) {
struct timeval tv;
struct timezone tz;

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -27,6 +27,9 @@
*/
#include "config.h"
#ifdef AFL_PERSISTENT_RECORD
#include "afl-fuzz.h"
#endif
#include "types.h"
#include "debug.h"
#include "common.h"
@ -575,7 +578,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
fsrv->max_length);
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
true);
@ -724,7 +728,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
/* autodict in Nyx mode */
if (!ignore_autodict) {
if (!ignore_autodict && fsrv->add_extra_func) {
char *x =
alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
@ -1111,7 +1115,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) {
if (status & FS_NEW_OPT_SHDMEM_FUZZ) {
if (fsrv->support_shmem_fuzz) {
@ -1128,7 +1132,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
if ((status & FS_NEW_OPT_AUTODICT)) {
if (status & FS_NEW_OPT_AUTODICT) {
// even if we do not need the dictionary we have to read it
u32 dict_size;
if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
@ -1152,12 +1158,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
while (dict_size != 0) {
while (offset < dict_size) {
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size);
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size - offset);
if (rlen > 0) {
dict_size -= rlen;
offset += rlen;
} else {
@ -1165,7 +1170,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
FATAL(
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, dict_size);
offset, dict_size - offset);
}
@ -1174,14 +1179,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
offset = 0;
while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
(u8)dict[offset]);
if (!ignore_autodict && fsrv->add_extra_func) {
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
(u8)dict[offset]);
count++;
}
offset += (1 + dict[offset]);
count++;
}
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
if (!be_quiet && count) {
ACTF("Loaded %u autodictionary entries", count);
}
ck_free(dict);
}
@ -1640,7 +1655,8 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
if (fsrv->fsrv_pid > 0) {
kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal);
waitpid(fsrv->fsrv_pid, NULL, 0);
usleep(25);
waitpid(fsrv->fsrv_pid, NULL, WNOHANG);
}
@ -1828,6 +1844,8 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
case Timeout:
return FSRV_RUN_TMOUT;
case InvalidWriteToPayload:
if (!!getenv("AFL_NYX_HANDLE_INVALID_WRITE")) { return FSRV_RUN_CRASH; }
/* ??? */
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
break;
@ -1861,7 +1879,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
territory. */
#ifdef __linux__
if (!fsrv->nyx_mode) {
if (likely(!fsrv->nyx_mode)) {
memset(fsrv->trace_bits, 0, fsrv->map_size);
MEM_BARRIER();
@ -1931,7 +1949,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (exec_ms > timeout) {
/* If there was no response from forkserver after timeout seconds,
/* If there was no response from forkserver after timeout milliseconds,
we kill the child. The forkserver should inform us afterwards */
s32 tmp_pid = fsrv->child_pid;
@ -2003,7 +2021,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (unlikely(fsrv->persistent_record)) {
retval = FSRV_RUN_TMOUT;
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u";
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u%s%s";
goto store_persistent_record;
}
@ -2039,7 +2057,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (unlikely(fsrv->persistent_record)) {
retval = FSRV_RUN_CRASH;
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u";
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u%s%s";
goto store_persistent_record;
}
@ -2065,8 +2083,13 @@ store_persistent_record: {
u32 len = fsrv->persistent_record_len[entry];
if (likely(len && data)) {
snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
fsrv->persistent_record_cnt, writecnt++);
snprintf(
fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
fsrv->persistent_record_cnt, writecnt++,
((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "",
((afl_state_t *)(fsrv->afl_ptr))->file_extension
? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension
: "");
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (fd >= 0) {

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -527,21 +527,41 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
queue_fn =
alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_items,
describe_op(afl, new_bits + is_timeout,
NAME_MAX - strlen("id:000000,")));
if (!afl->afl_env.afl_sha1_filenames) {
queue_fn = alloc_printf(
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
describe_op(afl, new_bits + is_timeout,
NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
queue_fn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
queue_fn =
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items);
queue_fn = alloc_printf(
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn);
close(fd);
fd = permissive_create(afl, queue_fn);
if (likely(fd >= 0)) {
ck_write(fd, mem, len, queue_fn);
close(fd);
}
add_to_queue(afl, queue_fn, len, 0);
if (unlikely(afl->fuzz_mode) &&
@ -739,14 +759,29 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
afl->saved_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
afl->saved_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
afl->saved_hangs);
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir,
afl->saved_hangs, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -792,14 +827,30 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal);
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -862,10 +913,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* If we're here, we apparently want to save the crash or hang
test case, too. */
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
ck_write(fd, mem, len, fn);
close(fd);
fd = permissive_create(afl, fn);
if (fd >= 0) {
ck_write(fd, mem, len, fn);
close(fd);
}
#ifdef __linux__
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -742,8 +742,11 @@ 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", afl->out_dir, 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 : "");
s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -459,6 +459,24 @@ void bind_to_free_cpu(afl_state_t *afl) {
#endif /* HAVE_AFFINITY */
/* transforms spaces in a string to underscores (inplace) */
static void no_spaces(u8 *string) {
if (string) {
u8 *ptr = string;
while (*ptr != 0) {
if (*ptr == ' ') { *ptr = '_'; }
++ptr;
}
}
}
/* Shuffle an array of pointers. Might be slightly biased. */
static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
@ -559,6 +577,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
afl->stage_cur = 0;
afl->stage_max = 0;
show_stats(afl);
for (i = 0; i < (u32)nl_cnt; ++i) {
struct stat st;
@ -637,7 +657,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
munmap(mem, st.st_size);
close(fd);
if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
if (st.st_mtime > mtime_max) {
mtime_max = st.st_mtime;
show_stats(afl);
}
}
@ -914,6 +939,14 @@ void perform_dry_run(afl_state_t *afl) {
res = calibrate_case(afl, q, use_mem, 0, 1);
/* For AFLFast schedules we update the queue entry */
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) &&
likely(q->exec_cksum)) {
q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE;
}
if (afl->stop_soon) { return; }
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
@ -1157,18 +1190,35 @@ void perform_dry_run(afl_state_t *afl) {
#ifndef SIMPLE_FILES
snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0,
NAME_MAX - strlen("id:000000,sig:00,") -
strlen(use_name)),
use_name);
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(
afl, 0,
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
use_name, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(use_mem, read_len);
snprintf(
crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
afl->out_dir, afl->saved_crashes,
afl->fsrv.last_kill_signal);
snprintf(
crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif
@ -1372,11 +1422,11 @@ void perform_dry_run(afl_state_t *afl) {
static void link_or_copy(u8 *old_path, u8 *new_path) {
s32 i = link(old_path, new_path);
if (!i) { return; }
s32 sfd, dfd;
u8 *tmp;
if (!i) { return; }
sfd = open(old_path, O_RDONLY);
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
@ -1439,7 +1489,9 @@ void pivot_inputs(afl_state_t *afl) {
u32 src_id;
afl->resuming_fuzz = 1;
nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
nfn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, rsl, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
/* Since we're at it, let's also get the parent and figure out the
appropriate depth for this entry. */
@ -1479,12 +1531,33 @@ void pivot_inputs(afl_state_t *afl) {
}
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
afl->out_dir, id, afl->fsrv.total_execs, use_name);
if (!afl->afl_env.afl_sha1_filenames) {
nfn = alloc_printf(
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex_for_file(q->fname, q->len);
nfn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
u8 *pos = strrchr(nfn, '/');
no_spaces(pos + 30);
#else
nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
nfn = alloc_printf(
"%s/queue/id_%06u%s%s", afl->out_dir, id,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -1691,10 +1764,11 @@ double get_runnable_processes(void) {
void nuke_resume_dir(afl_state_t *afl) {
u8 *fn;
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
u8 *fn;
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
@ -1702,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
@ -1714,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/_resume", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
return;
@ -1731,8 +1805,9 @@ dir_cleanup_failed:
static void handle_existing_out_dir(afl_state_t *afl) {
FILE *f;
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
FILE *f;
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
/* See if the output directory is locked. If yes, bail out. If not,
create a lock that will persist for the lifetime of the process
@ -1854,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
@ -1862,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* Then, get rid of the .state subdirectory itself (should be empty by now)
@ -1877,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/queue", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* All right, let's do <afl->out_dir>/crashes/id:* and
@ -1924,7 +1999,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
#ifdef AFL_PERSISTENT_RECORD
delete_files(fn, RECORD_PREFIX);
#endif
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/hangs", afl->out_dir);
@ -1959,7 +2034,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
#ifdef AFL_PERSISTENT_RECORD
delete_files(fn, RECORD_PREFIX);
#endif
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* And now, for some finishing touches. */

View File

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

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -60,32 +60,6 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
double compute_weight(afl_state_t *afl, struct queue_entry *q,
double avg_exec_us, double avg_bitmap_size,
double avg_top_size) {
double weight = 1.0;
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
}
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
weight *= (log(q->bitmap_size) / avg_bitmap_size);
weight *= (1 + (q->tc_ref / avg_top_size));
if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
if (unlikely(q->fs_redundant)) { weight *= 0.8; }
return weight;
}
/* create the alias table that allows weighted random selection - expensive */
void create_alias_table(afl_state_t *afl) {
@ -117,7 +91,7 @@ void create_alias_table(afl_state_t *afl) {
double avg_exec_us = 0.0;
double avg_bitmap_size = 0.0;
double avg_top_size = 0.0;
double avg_len = 0.0;
u32 active = 0;
for (i = 0; i < n; i++) {
@ -129,7 +103,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us += q->exec_us;
avg_bitmap_size += log(q->bitmap_size);
avg_top_size += q->tc_ref;
avg_len += q->len;
++active;
}
@ -138,7 +112,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us /= active;
avg_bitmap_size /= active;
avg_top_size /= active;
avg_len /= active;
for (i = 0; i < n; i++) {
@ -146,8 +120,59 @@ void create_alias_table(afl_state_t *afl) {
if (likely(!q->disabled)) {
q->weight =
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
double weight = 1.0;
{ // inline does result in a compile error with LTO, weird
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
}
if (likely(afl->schedule < RARE)) {
double t = q->exec_us / avg_exec_us;
if (likely(t < 0.1)) {
// nothing
} else if (likely(t <= 0.25))
weight *= 0.9;
else if (likely(t <= 0.5)) {
// nothing
} else if (likely(t < 1.0))
weight *= 1.15;
else if (unlikely(t > 2.5 && t < 5.0))
weight *= 1.1;
// else nothing
}
double l = q->len / avg_len;
if (likely(l < 0.1))
weight *= 0.75;
else if (likely(l < 0.25))
weight *= 1.1;
else if (unlikely(l >= 10))
weight *= 1.1;
double bms = q->bitmap_size / avg_bitmap_size;
if (likely(bms < 0.5))
weight *= (1.0 + ((bms - 0.5) / 2));
else if (unlikely(bms > 1.33))
weight *= 1.1;
if (unlikely(!q->was_fuzzed)) { weight *= 2.5; }
if (unlikely(q->fs_redundant)) { weight *= 0.75; }
}
q->weight = weight;
q->perf_score = calculate_score(afl, q);
sum += q->weight;
@ -370,9 +395,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd);
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
fd = permissive_create(afl, fn);
if (fd >= 0) { close(fd); }
} else {
@ -596,6 +621,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
q->trace_mini = NULL;
q->testcase_buf = NULL;
q->mother = afl->queue_cur;
q->weight = 1.0;
q->perf_score = 100;
#ifdef INTROSPECTION
q->bitsmap_size = afl->bitsmap_size;
@ -1201,9 +1228,11 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
u32 len = q->len;
if (len != old_len) {
// only realloc if necessary or useful
// (a custom trim can make the testcase larger)
if (unlikely(len > old_len || len < old_len + 1024)) {
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
afl->q_testcase_cache_size += len - old_len;
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
if (unlikely(!q->testcase_buf)) {
@ -1232,41 +1261,48 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
if (likely(q->testcase_buf)) {
u32 is_same = in == q->testcase_buf;
if (likely(in != q->testcase_buf)) {
if (likely(len != old_len)) {
// only realloc if we save memory
if (unlikely(len < old_len + 1024)) {
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
if (likely(ptr)) {
if (likely(ptr)) {
q->testcase_buf = ptr;
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
q->testcase_buf = ptr;
afl->q_testcase_cache_size += len - old_len;
}
}
}
memcpy(q->testcase_buf, in, len);
if (unlikely(!is_same)) { memcpy(q->testcase_buf, in, len); }
}
}
}
/* Returns the testcase buf from the file behind this queue entry.
Increases the refcount. */
Increases the refcount. */
inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
u32 len = q->len;
if (likely(q->testcase_buf)) { return q->testcase_buf; }
/* first handle if no testcase cache is configured */
u32 len = q->len;
double weight = q->weight;
if (unlikely(!afl->q_testcase_max_cache_size)) {
// first handle if no testcase cache is configured, or if the
// weighting of the testcase is below average.
if (unlikely(weight < 1.0 || !afl->q_testcase_max_cache_size)) {
u8 *buf;
if (unlikely(q == afl->queue_cur)) {
if (likely(q == afl->queue_cur)) {
buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len);
@ -1292,117 +1328,113 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
}
/* now handle the testcase cache */
/* now handle the testcase cache and we know it is an interesting one */
if (unlikely(!q->testcase_buf)) {
/* Buf not cached, let's load it */
u32 tid = afl->q_testcase_max_cache_count;
static u32 do_once = 0; // because even threaded we would want this. WIP
/* Buf not cached, let's load it */
u32 tid = afl->q_testcase_max_cache_count;
static u32 do_once = 0; // because even threaded we would want this. WIP
while (unlikely(
(afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size &&
afl->q_testcase_cache_count > 1) ||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
while (unlikely(
afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size ||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
/* We want a max number of entries to the cache that we learn.
Very simple: once the cache is filled by size - that is the max. */
/* We want a max number of entries to the cache that we learn.
Very simple: once the cache is filled by size - that is the max. */
if (unlikely(
afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size &&
(afl->q_testcase_cache_count < afl->q_testcase_max_cache_entries &&
afl->q_testcase_max_cache_count <
afl->q_testcase_max_cache_entries) &&
!do_once)) {
if (unlikely(afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size &&
(afl->q_testcase_cache_count <
afl->q_testcase_max_cache_entries &&
afl->q_testcase_max_cache_count <
afl->q_testcase_max_cache_entries) &&
!do_once)) {
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_count + 1;
afl->q_testcase_max_cache_entries =
afl->q_testcase_max_cache_count + 1;
} else {
} else {
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
}
do_once = 1;
// release unneeded memory
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
}
/* Cache full. We neet to evict one or more to map one.
Get a random one which is not in use */
do {
// if the cache (MB) is not enough for the queue then this gets
// undesirable because q_testcase_max_cache_count grows sometimes
// although the number of items in the cache will not change hence
// more and more loops
tid = rand_below(afl, afl->q_testcase_max_cache_count);
} while (afl->q_testcase_cache[tid] == NULL ||
afl->q_testcase_cache[tid] == afl->queue_cur);
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
free(old_cached->testcase_buf);
old_cached->testcase_buf = NULL;
afl->q_testcase_cache_size -= old_cached->len;
afl->q_testcase_cache[tid] = NULL;
--afl->q_testcase_cache_count;
++afl->q_testcase_evictions;
if (tid < afl->q_testcase_smallest_free)
afl->q_testcase_smallest_free = tid;
do_once = 1;
// release unneeded memory
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
}
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
/* Cache full. We neet to evict one or more to map one.
Get a random one which is not in use */
// uh we were full, so now we have to search from start
tid = afl->q_testcase_smallest_free;
do {
}
// if the cache (MB) is not enough for the queue then this gets
// undesirable because q_testcase_max_cache_count grows sometimes
// although the number of items in the cache will not change hence
// more and more loops
tid = rand_below(afl, afl->q_testcase_max_cache_count);
// we need this while loop in case there were ever previous evictions but
// not in this call.
while (unlikely(afl->q_testcase_cache[tid] != NULL))
++tid;
} while (afl->q_testcase_cache[tid] == NULL ||
/* Map the test case into memory. */
afl->q_testcase_cache[tid] == afl->queue_cur);
int fd = open((char *)q->fname, O_RDONLY);
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
free(old_cached->testcase_buf);
old_cached->testcase_buf = NULL;
afl->q_testcase_cache_size -= old_cached->len;
afl->q_testcase_cache[tid] = NULL;
--afl->q_testcase_cache_count;
++afl->q_testcase_evictions;
if (tid < afl->q_testcase_smallest_free)
afl->q_testcase_smallest_free = tid;
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
}
q->testcase_buf = (u8 *)malloc(len);
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
if (unlikely(!q->testcase_buf)) {
// uh we were full, so now we have to search from start
tid = afl->q_testcase_smallest_free;
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
}
// we need this while loop in case there were ever previous evictions but
// not in this call.
while (unlikely(afl->q_testcase_cache[tid] != NULL))
++tid;
ck_read(fd, q->testcase_buf, len, q->fname);
close(fd);
/* Map the test case into memory. */
/* Register testcase as cached */
afl->q_testcase_cache[tid] = q;
afl->q_testcase_cache_size += len;
++afl->q_testcase_cache_count;
if (likely(tid >= afl->q_testcase_max_cache_count)) {
int fd = open((char *)q->fname, O_RDONLY);
afl->q_testcase_max_cache_count = tid + 1;
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
q->testcase_buf = (u8 *)malloc(len);
afl->q_testcase_smallest_free = tid + 1;
if (unlikely(!q->testcase_buf)) {
}
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
ck_read(fd, q->testcase_buf, len, q->fname);
close(fd);
/* Register testcase as cached */
afl->q_testcase_cache[tid] = q;
afl->q_testcase_cache_size += len;
++afl->q_testcase_cache_count;
if (likely(tid >= afl->q_testcase_max_cache_count)) {
afl->q_testcase_max_cache_count = tid + 1;
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
afl->q_testcase_smallest_free = tid + 1;
}
@ -1417,12 +1449,13 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q,
u32 len = q->len;
if (unlikely(afl->q_testcase_cache_size + len >=
if (unlikely(q->weight < 1.0 ||
afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size ||
afl->q_testcase_cache_count >=
afl->q_testcase_max_cache_entries - 1)) {
// no space? will be loaded regularly later.
// no space or uninteresting? will be loaded regularly later.
return;
}

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -322,7 +322,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
memcpy(backup, buf, len);
memcpy(changed, buf, len);
if (afl->cmplog_random_colorization) {
if (likely(afl->cmplog_random_colorization)) {
random_replace(afl, changed, len);
@ -402,6 +402,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u32 i = 1;
u32 positions = 0;
while (i) {
restart:
@ -2764,15 +2765,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG
u32 j;
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
hshape, h->attribute);
fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape,
h->attribute);
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", o->v0[j]);
fprintf(stderr, " v1=");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", o->v1[j]);
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
hh->id, hshape, hh->attribute);
fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape,
hh->attribute);
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
@ -2937,7 +2938,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
// afl->queue_cur->exec_cksum
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u8 r = 1;
u64 cmplog_start_us = get_cur_time_us();
u8 r = 1;
if (unlikely(!afl->pass_stats)) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
@ -2965,7 +2967,12 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
if (unlikely(colorization(afl, buf, len, &taint))) { return 1; }
if (unlikely(colorization(afl, buf, len, &taint))) {
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
// no taint? still try, create a dummy to prevent again colorization
if (!taint) {
@ -2974,6 +2981,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
fprintf(stderr, "TAINT FAILED\n");
#endif
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
update_cmplog_time(afl, &cmplog_start_us);
return 0;
}
@ -2994,17 +3002,20 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
struct tainted *t = taint;
#ifdef _DEBUG
while (t) {
#ifdef _DEBUG
fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len);
#endif
t = t->next;
}
#endif
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
u64 start_time = get_cur_time();
u32 cmp_locations = 0;
@ -3025,6 +3036,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
@ -3048,6 +3060,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
@ -3066,6 +3079,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
update_cmplog_time(afl, &cmplog_start_us);
afl->stage_name = "input-to-state";
afl->stage_short = "its";
@ -3142,33 +3156,35 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
}
r = 0;
exit_its:
if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
// if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
if (afl->queue_cur->cmplog_colorinput) {
if (afl->queue_cur->cmplog_colorinput) {
ck_free(afl->queue_cur->cmplog_colorinput);
ck_free(afl->queue_cur->cmplog_colorinput);
}
}
while (taint) {
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
t = taint->next;
ck_free(taint);
taint = t;
}
}
afl->queue_cur->taint = NULL;
afl->queue_cur->taint = NULL;
} else {
/*} else {
afl->queue_cur->colorized = LVL2;
@ -3182,7 +3198,7 @@ exit_its:
}
}
}*/
#ifdef CMPLOG_COMBINE
if (afl->queued_items + afl->saved_crashes > orig_hit_cnt + 1) {
@ -3270,6 +3286,7 @@ exit_its:
#endif
update_cmplog_time(afl, &cmplog_start_us);
return r;
}

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name;
u64 calibration_start_us = get_cur_time_us();
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
/* Be a bit more generous about timeouts when resuming sessions, or when
@ -504,6 +505,10 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
// update the time spend in calibration after each execution, as those may
// be slow
update_calibration_time(afl, &calibration_start_us);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */
@ -601,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
q->exec_us = diff_us / afl->stage_max;
if (unlikely(!q->exec_us)) { q->exec_us = 1; }
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
q->handicap = handicap;
q->cal_failed = 0;
@ -650,6 +657,7 @@ abort_calibration:
if (!first_run) { show_stats(afl); }
update_calibration_time(afl, &calibration_start_us);
return fault;
}
@ -658,6 +666,8 @@ abort_calibration:
void sync_fuzzers(afl_state_t *afl) {
if (unlikely(afl->afl_env.afl_no_sync)) { return; }
DIR *sd;
struct dirent *sd_ent;
u32 sync_cnt = 0, synced = 0, entries = 0;
@ -669,11 +679,16 @@ void sync_fuzzers(afl_state_t *afl) {
afl->stage_max = afl->stage_cur = 0;
afl->cur_depth = 0;
u64 sync_start_us = get_cur_time_us();
/* Look at the entries created for every other fuzzer in the sync directory.
*/
while ((sd_ent = readdir(sd))) {
// since sync can take substantial amounts of time, update time spend every
// iteration
update_sync_time(afl, &sync_start_us);
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
u32 min_accept = 0, next_min_accept = 0;
@ -760,6 +775,8 @@ void sync_fuzzers(afl_state_t *afl) {
afl->stage_cur = 0;
afl->stage_max = 0;
show_stats(afl);
/* For every file queued by this fuzzer, parse ID and see if we have
looked at it before; exec a test case if not. */
@ -811,15 +828,15 @@ void sync_fuzzers(afl_state_t *afl) {
/* See what happens. We rely on save_if_interesting() to catch major
errors and save the test case. */
(void)write_to_testcase(afl, (void **)&mem, st.st_size, 1);
u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) { goto close_sync; }
afl->syncing_party = sd_ent->d_name;
afl->queued_imported +=
save_if_interesting(afl, mem, st.st_size, fault);
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
show_stats(afl);
afl->syncing_party = 0;
munmap(mem, st.st_size);
@ -861,6 +878,9 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
// add time in sync one last time
update_sync_time(afl, &sync_start_us);
afl->last_sync_time = get_cur_time();
afl->last_sync_cycle = afl->queue_cycle;
@ -872,8 +892,9 @@ void sync_fuzzers(afl_state_t *afl) {
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
u8 needs_write = 0, fault = 0;
u32 orig_len = q->len;
u64 trim_start_us = get_cur_time_us();
/* Custom mutator trimmer */
if (afl->custom_mutators_count) {
@ -897,11 +918,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
if (custom_trimmed) return trimmed_case;
if (custom_trimmed) {
fault = trimmed_case;
goto abort_trimming;
}
}
u8 needs_write = 0, fault = 0;
u32 trim_exec = 0;
u32 remove_len;
u32 len_p2;
@ -912,7 +937,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
detected, it will still work to some extent, so we don't check for
this. */
if (unlikely(q->len < 5)) { return 0; }
if (unlikely(q->len < 5)) {
fault = 0;
goto abort_trimming;
}
afl->stage_name = afl->stage_name_buf;
afl->bytes_trim_in += q->len;
@ -946,6 +976,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
update_trim_time(afl, &trim_start_us);
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
@ -972,7 +1004,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
/* Let's save a clean trace, which will be needed by
update_bitmap_score once we're done with the trimming stuff. */
if (!needs_write) {
needs_write = 1;
@ -987,7 +1018,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
/* Since this can be slow, update the screen every now and then. */
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
++afl->stage_cur;
@ -1002,6 +1032,68 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (needs_write) {
// run afl_custom_post_process
if (unlikely(afl->custom_mutators_count) &&
likely(!afl->afl_env.afl_post_process_keep_original)) {
ssize_t new_size = q->len;
u8 *new_mem = in_buf;
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 (unlikely(!new_buf || new_size <= 0)) {
new_size = 0;
new_buf = new_mem;
} else {
new_mem = new_buf;
}
}
});
if (unlikely(!new_size)) {
new_size = q->len;
new_mem = in_buf;
}
if (unlikely(new_size < afl->min_length)) {
new_size = afl->min_length;
} else if (unlikely(new_size > afl->max_length)) {
new_size = afl->max_length;
}
q->len = new_size;
if (new_mem != in_buf && new_mem != NULL) {
new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
memcpy(new_buf, new_mem, new_size);
in_buf = new_buf;
}
}
s32 fd;
if (unlikely(afl->no_unlink)) {
@ -1039,8 +1131,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
abort_trimming:
afl->bytes_trim_out += q->len;
update_trim_time(afl, &trim_start_us);
return fault;
}

View File

@ -33,15 +33,15 @@ u8 is_det_timeout(u64 cur_ms, u8 is_flip) {
u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) {
if (!afl->skipdet_g->virgin_det_bits) {
if (unlikely(!afl->skipdet_g->virgin_det_bits)) {
afl->skipdet_g->virgin_det_bits =
(u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size);
}
if (!q->favored || q->passed_det) return 0;
if (!q->trace_mini) return 0;
if (likely(!q->favored || q->passed_det)) return 0;
if (unlikely(!q->trace_mini)) return 0;
if (!afl->skipdet_g->last_cov_undet)
afl->skipdet_g->last_cov_undet = get_cur_time();
@ -122,7 +122,8 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
afl->stage_cur = 0;
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len);
static u8 *inf_eff_map;
inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len);
memset(inf_eff_map, 1, sizeof(u8) * len);
if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; }

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -28,10 +28,6 @@
#include "afl-fuzz.h"
#include "envs.h"
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit",
"fast", "coe", "lin",
"quad", "rare", "seek"};
@ -283,6 +279,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_final_sync =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_NO_SYNC",
afl_environment_variable_len)) {
afl->afl_env.afl_no_sync =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY",
afl_environment_variable_len)) {
@ -297,6 +300,16 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_cmplog_only_new =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_DISABLE_REDUNDANT",
afl_environment_variable_len) ||
!strncmp(env, "AFL_NO_REDUNDANT",
afl_environment_variable_len)) {
afl->afl_env.afl_disable_redundant =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
afl_environment_variable_len)) {
@ -623,6 +636,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
} else if (!strncmp(env, "AFL_SHA1_FILENAMES",
afl_environment_variable_len)) {
afl->afl_env.afl_sha1_filenames =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
}
} else {
@ -749,8 +769,9 @@ void afl_states_stop(void) {
if (el->fsrv.fsrv_pid > 0) {
kill(el->fsrv.fsrv_pid, el->fsrv.fsrv_kill_signal);
usleep(100);
/* Make sure the forkserver does not end up as zombie. */
waitpid(el->fsrv.fsrv_pid, NULL, 0);
waitpid(el->fsrv.fsrv_pid, NULL, WNOHANG);
}

View File

@ -5,8 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Meier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -133,6 +134,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
}
static bool starts_with(char *key, char *line) {
return strncmp(key, line, strlen(key)) == 0;
}
/* load some of the existing stats file when resuming.*/
void load_stats_file(afl_state_t *afl) {
@ -175,58 +182,90 @@ void load_stats_file(afl_state_t *afl) {
strcpy(keystring, lstartptr);
lptr++;
char *nptr;
switch (lineno) {
if (starts_with("run_time", keystring)) {
case 3:
if (!strcmp(keystring, "run_time "))
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
break;
case 5:
if (!strcmp(keystring, "cycles_done "))
afl->queue_cycle =
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
break;
case 7:
if (!strcmp(keystring, "execs_done "))
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
break;
case 10:
if (!strcmp(keystring, "corpus_count ")) {
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
u32 corpus_count = strtoul(lptr, &nptr, 10);
if (corpus_count != afl->queued_items) {
}
WARNF(
"queue/ has been modified -- things might not work, you're "
"on your own!");
if (starts_with("cycles_done", keystring)) {
}
afl->queue_cycle =
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
}
}
break;
case 12:
if (!strcmp(keystring, "corpus_found "))
afl->queued_discovered = strtoul(lptr, &nptr, 10);
break;
case 13:
if (!strcmp(keystring, "corpus_imported "))
afl->queued_imported = strtoul(lptr, &nptr, 10);
break;
case 14:
if (!strcmp(keystring, "max_depth "))
afl->max_depth = strtoul(lptr, &nptr, 10);
break;
case 21:
if (!strcmp(keystring, "saved_crashes "))
afl->saved_crashes = strtoull(lptr, &nptr, 10);
break;
case 22:
if (!strcmp(keystring, "saved_hangs "))
afl->saved_hangs = strtoull(lptr, &nptr, 10);
break;
default:
break;
if (starts_with("calibration_time", keystring)) {
afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("sync_time", keystring)) {
afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("cmplog_time", keystring)) {
afl->cmplog_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("trim_time", keystring)) {
afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("execs_done", keystring)) {
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
}
if (starts_with("corpus_count", keystring)) {
u32 corpus_count = strtoul(lptr, &nptr, 10);
if (corpus_count != afl->queued_items) {
WARNF(
"queue/ has been modified -- things might not work, you're "
"on your own!");
sleep(3);
}
}
if (starts_with("corpus_found", keystring)) {
afl->queued_discovered = strtoul(lptr, &nptr, 10);
}
if (starts_with("corpus_imported", keystring)) {
afl->queued_imported = strtoul(lptr, &nptr, 10);
}
if (starts_with("max_depth", keystring)) {
afl->max_depth = strtoul(lptr, &nptr, 10);
}
if (starts_with("saved_crashes", keystring)) {
afl->saved_crashes = strtoull(lptr, &nptr, 10);
}
if (starts_with("saved_hangs", keystring)) {
afl->saved_hangs = strtoull(lptr, &nptr, 10);
}
@ -288,8 +327,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
#ifndef __HAIKU__
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
#endif
u64 runtime = afl->prev_run_time + cur_time - afl->start_time;
if (!runtime) { runtime = 1; }
u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time;
u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us +
afl->trim_time_us + afl->cmplog_time_us) /
1000;
if (!runtime_ms) { runtime_ms = 1; }
fprintf(
f,
@ -300,6 +342,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"cycles_done : %llu\n"
"cycles_wo_finds : %llu\n"
"time_wo_finds : %llu\n"
"fuzz_time : %llu\n"
"calibration_time : %llu\n"
"cmplog_time : %llu\n"
"sync_time : %llu\n"
"trim_time : %llu\n"
"execs_done : %llu\n"
"execs_per_sec : %0.02f\n"
"execs_ps_last_min : %0.02f\n"
@ -337,15 +384,19 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"\n"
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
"command_line : %s\n",
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
runtime / 1000, (u32)getpid(),
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
runtime_ms / 1000, (u32)getpid(),
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
afl->longest_find_time > cur_time - afl->last_find_time
? afl->longest_find_time / 1000
: ((afl->start_time == 0 || afl->last_find_time == 0)
? 0
: (cur_time - afl->last_find_time) / 1000),
afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000),
(runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000,
afl->calibration_time_us / 1000000, afl->cmplog_time_us / 1000000,
afl->sync_time_us / 1000000, afl->trim_time_us / 1000000,
afl->fsrv.total_execs,
afl->fsrv.total_execs / ((double)(runtime_ms) / 1000),
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
afl->max_depth, afl->current_entry, afl->pending_favored,
@ -589,9 +640,10 @@ void show_stats_normal(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -600,7 +652,7 @@ void show_stats_normal(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -876,6 +928,10 @@ void show_stats_normal(afl_state_t *afl) {
#endif
if (banner_pad)
for (u32 i = 0; i < banner_pad; ++i)
strcat(banner, " ");
}
SAYF("\n%s\n", banner);
@ -1284,7 +1340,9 @@ void show_stats_normal(afl_state_t *afl) {
sprintf(tmp, "disabled, ");
} else if (unlikely(!afl->bytes_trim_out)) {
} else if (unlikely(!afl->bytes_trim_out ||
afl->bytes_trim_in <= afl->bytes_trim_out)) {
sprintf(tmp, "n/a, ");
@ -1301,7 +1359,9 @@ void show_stats_normal(afl_state_t *afl) {
strcat(tmp, "disabled");
} else if (unlikely(!afl->blocks_eff_total)) {
} else if (unlikely(!afl->blocks_eff_total ||
afl->blocks_eff_select >= afl->blocks_eff_total)) {
strcat(tmp, "n/a");
@ -1415,9 +1475,10 @@ void show_stats_pizza(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -1426,7 +1487,7 @@ void show_stats_pizza(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -2435,3 +2496,35 @@ void show_init_stats(afl_state_t *afl) {
}
inline void update_calibration_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->calibration_time_us += cur - *time;
*time = cur;
}
inline void update_trim_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->trim_time_us += cur - *time;
*time = cur;
}
inline void update_sync_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->sync_time_us += cur - *time;
*time = cur;
}
inline void update_cmplog_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->cmplog_time_us += cur - *time;
*time = cur;
}

View File

@ -5,8 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Meier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -199,7 +200,8 @@ static void usage(u8 *argv0, int more_help) {
"Test settings:\n"
" -s seed - use a fixed seed for the RNG\n"
" -V seconds - fuzz for a specified time then terminate\n"
" -V seconds - fuzz for a specified time then terminate (fuzz time "
"only!)\n"
" -E execs - fuzz for an approx. no. of total executions then "
"terminate\n"
" Note: not precise and can have several more "
@ -262,6 +264,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
"AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
@ -332,6 +335,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
"AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
" suported formats: dogstatsd, librato, signalfx, influxdb\n"
"AFL_NO_SYNC: disables all syncing\n"
"AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
"AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
"AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
@ -911,8 +915,15 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M';
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1;
if (mem_limit_given) {
WARNF("Overriding previous -m option.");
} else {
mem_limit_given = 1;
}
if (!optarg) { FATAL("Wrong usage of -m"); }
@ -1458,15 +1469,16 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
afl->afl_env.afl_fsrv_kill_signal,
(afl->fsrv.qemu_mode || afl->unicorn_mode
configure_afl_kill_signals(
&afl->fsrv, afl->afl_env.afl_child_kill_signal,
afl->afl_env.afl_fsrv_kill_signal,
(afl->fsrv.qemu_mode || afl->unicorn_mode || afl->fsrv.use_fauxsrv
#ifdef __linux__
|| afl->fsrv.nyx_mode
|| afl->fsrv.nyx_mode
#endif
)
? SIGKILL
: SIGTERM);
)
? SIGKILL
: SIGTERM);
setup_signal_handlers();
check_asan_opts(afl);
@ -1562,7 +1574,11 @@ int main(int argc, char **argv_orig, char **envp) {
setenv("__AFL_OUT_DIR", afl->out_dir, 1);
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
if (get_afl_env("AFL_DISABLE_TRIM") || get_afl_env("AFL_NO_TRIM")) {
afl->disable_trim = 1;
}
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
@ -1798,6 +1814,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
afl->fsrv.max_length = afl->max_length;
#ifdef __linux__
if (!afl->fsrv.nyx_mode) {
@ -2073,6 +2090,17 @@ int main(int argc, char **argv_orig, char **envp) {
}
/* Simply code if AFL_TMPDIR is used or not */
if (!afl->afl_env.afl_tmpdir) {
afl->tmp_dir = afl->out_dir;
} else {
afl->tmp_dir = afl->afl_env.afl_tmpdir;
}
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind);
@ -2085,8 +2113,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
!afl->in_place_resume) {
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
char tmpfile[PATH_MAX];
@ -2111,10 +2138,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
} else {
afl->tmp_dir = afl->out_dir;
}
/* If we don't have a file name chosen yet, use a safe default. */
@ -2493,8 +2516,15 @@ int main(int argc, char **argv_orig, char **envp) {
for (entry = 0; entry < afl->queued_items; ++entry)
if (!afl->queue_buf[entry]->disabled)
if (afl->queue_buf[entry]->exec_us > max_ms)
max_ms = afl->queue_buf[entry]->exec_us;
if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms)
max_ms = afl->queue_buf[entry]->exec_us / 1000;
// Add 20% as a safety margin, capped to exec_tmout given in -t option
max_ms *= 1.2;
if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout;
// Ensure that there is a sensible timeout even for very fast binaries
if (max_ms < 5) max_ms = 5;
afl->fsrv.exec_tmout = max_ms;
afl->timeout_given = 1;
@ -2530,8 +2560,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
// (void)nice(-20); // does not improve the speed
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
#ifdef INTROSPECTION
u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
@ -2552,6 +2580,9 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Writing mutation introspection to '%s'", ifn);
#endif
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
while (likely(!afl->stop_soon)) {
cull_queue(afl);
@ -2564,7 +2595,7 @@ int main(int argc, char **argv_orig, char **envp) {
(!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
afl->sync_id)) {
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
if (unlikely(!afl->queue_cycle && afl->afl_env.afl_import_first)) {
OKF("Syncing queues from other fuzzer instances first ...");
@ -2575,6 +2606,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
++afl->queue_cycle;
if (afl->afl_env.afl_no_ui) {
ACTF("Entering queue cycle %llu\n", afl->queue_cycle);
}
runs_in_current_cycle = (u32)-1;
afl->cur_skipped_items = 0;
@ -2583,7 +2620,7 @@ int main(int argc, char **argv_orig, char **envp) {
// queue is fully cycled.
time_t cursec = time(NULL);
struct tm *curdate = localtime(&cursec);
if (likely(!afl->afl_env.afl_pizza_mode)) {
if (unlikely(!afl->afl_env.afl_pizza_mode)) {
if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) {
@ -2628,13 +2665,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (unlikely(afl->not_on_tty)) {
ACTF("Entering queue cycle %llu.", afl->queue_cycle);
fflush(stdout);
}
/* If we had a full queue cycle with no new finds, try
recombination strategies next. */
@ -2920,26 +2950,13 @@ int main(int argc, char **argv_orig, char **envp) {
if (likely(!afl->stop_soon && afl->sync_id)) {
if (likely(afl->skip_deterministic)) {
if (unlikely(afl->is_main_node)) {
if (unlikely(afl->is_main_node)) {
if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) {
if (unlikely(cur_time >
(afl->sync_time >> 1) + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
sync_fuzzers(afl);
}
}
} else {
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
sync_fuzzers(afl);
}
@ -2947,7 +2964,11 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
sync_fuzzers(afl);
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
}
}
@ -3061,7 +3082,7 @@ stop_fuzzing:
afl_fsrv_deinit(&afl->fsrv);
/* remove tmpfile */
if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
if (!afl->in_place_resume && afl->fsrv.out_file) {
(void)unlink(afl->fsrv.out_file);

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Written by Marc Heuse <mh@mh-sec.de> for AFL++
Maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Maier <domenukk@gmail.com>

View File

@ -95,3 +95,331 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
}
/* Hash a file */
u64 get_binary_hash(u8 *fn) {
int fd = open(fn, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
struct stat st;
if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
u32 f_len = st.st_size;
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
close(fd);
u64 hash = hash64(f_data, f_len, 0);
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
return hash;
}
// Public domain SHA1 implementation copied from:
// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c
/* This code is public-domain - it is based on libcrypt
* placed in the public domain by Wei Dai and other contributors.
*/
// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test
#include <stdint.h>
#include <string.h>
#ifdef __BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#elif defined __LITTLE_ENDIAN__
/* override */
#elif defined __BYTE_ORDER
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#endif
#else // ! defined __LITTLE_ENDIAN__
#include <endian.h> // machine/endian.h
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#endif
#endif
/* header */
#define HASH_LENGTH 20
#define BLOCK_LENGTH 64
typedef struct sha1nfo {
uint32_t buffer[BLOCK_LENGTH / 4];
uint32_t state[HASH_LENGTH / 4];
uint32_t byteCount;
uint8_t bufferOffset;
uint8_t keyBuffer[BLOCK_LENGTH];
uint8_t innerHash[HASH_LENGTH];
} sha1nfo;
/* public API - prototypes - TODO: doxygen*/
/**
*/
void sha1_init(sha1nfo *s);
/**
*/
void sha1_writebyte(sha1nfo *s, uint8_t data);
/**
*/
void sha1_write(sha1nfo *s, const char *data, size_t len);
/**
*/
uint8_t *sha1_result(sha1nfo *s);
/**
*/
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength);
/**
*/
uint8_t *sha1_resultHmac(sha1nfo *s);
/* code */
#define SHA1_K0 0x5a827999
#define SHA1_K20 0x6ed9eba1
#define SHA1_K40 0x8f1bbcdc
#define SHA1_K60 0xca62c1d6
void sha1_init(sha1nfo *s) {
s->state[0] = 0x67452301;
s->state[1] = 0xefcdab89;
s->state[2] = 0x98badcfe;
s->state[3] = 0x10325476;
s->state[4] = 0xc3d2e1f0;
s->byteCount = 0;
s->bufferOffset = 0;
}
uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
return ((number << bits) | (number >> (32 - bits)));
}
void sha1_hashBlock(sha1nfo *s) {
uint8_t i;
uint32_t a, b, c, d, e, t;
a = s->state[0];
b = s->state[1];
c = s->state[2];
d = s->state[3];
e = s->state[4];
for (i = 0; i < 80; i++) {
if (i >= 16) {
t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^
s->buffer[(i + 2) & 15] ^ s->buffer[i & 15];
s->buffer[i & 15] = sha1_rol32(t, 1);
}
if (i < 20) {
t = (d ^ (b & (c ^ d))) + SHA1_K0;
} else if (i < 40) {
t = (b ^ c ^ d) + SHA1_K20;
} else if (i < 60) {
t = ((b & c) | (d & (b | c))) + SHA1_K40;
} else {
t = (b ^ c ^ d) + SHA1_K60;
}
t += sha1_rol32(a, 5) + e + s->buffer[i & 15];
e = d;
d = c;
c = sha1_rol32(b, 30);
b = a;
a = t;
}
s->state[0] += a;
s->state[1] += b;
s->state[2] += c;
s->state[3] += d;
s->state[4] += e;
}
void sha1_addUncounted(sha1nfo *s, uint8_t data) {
uint8_t *const b = (uint8_t *)s->buffer;
#ifdef SHA_BIG_ENDIAN
b[s->bufferOffset] = data;
#else
b[s->bufferOffset ^ 3] = data;
#endif
s->bufferOffset++;
if (s->bufferOffset == BLOCK_LENGTH) {
sha1_hashBlock(s);
s->bufferOffset = 0;
}
}
void sha1_writebyte(sha1nfo *s, uint8_t data) {
++s->byteCount;
sha1_addUncounted(s, data);
}
void sha1_write(sha1nfo *s, const char *data, size_t len) {
for (; len--;)
sha1_writebyte(s, (uint8_t)*data++);
}
void sha1_pad(sha1nfo *s) {
// Implement SHA-1 padding (fips180-2 §5.1.1)
// Pad with 0x80 followed by 0x00 until the end of the block
sha1_addUncounted(s, 0x80);
while (s->bufferOffset != 56)
sha1_addUncounted(s, 0x00);
// Append length in the last 8 bytes
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
sha1_addUncounted(s, 0); // So zero pad the top bits
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
sha1_addUncounted(
s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, s->byteCount >> 13); // byte.
sha1_addUncounted(s, s->byteCount >> 5);
sha1_addUncounted(s, s->byteCount << 3);
}
uint8_t *sha1_result(sha1nfo *s) {
// Pad to complete the last block
sha1_pad(s);
#ifndef SHA_BIG_ENDIAN
// Swap byte order back
int i;
for (i = 0; i < 5; i++) {
s->state[i] = (((s->state[i]) << 24) & 0xff000000) |
(((s->state[i]) << 8) & 0x00ff0000) |
(((s->state[i]) >> 8) & 0x0000ff00) |
(((s->state[i]) >> 24) & 0x000000ff);
}
#endif
// Return pointer to hash (20 characters)
return (uint8_t *)s->state;
}
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) {
uint8_t i;
memset(s->keyBuffer, 0, BLOCK_LENGTH);
if (keyLength > BLOCK_LENGTH) {
// Hash long keys
sha1_init(s);
for (; keyLength--;)
sha1_writebyte(s, *key++);
memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
} else {
// Block length keys are used as is
memcpy(s->keyBuffer, key, keyLength);
}
// Start inner hash
sha1_init(s);
for (i = 0; i < BLOCK_LENGTH; i++) {
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
}
}
uint8_t *sha1_resultHmac(sha1nfo *s) {
uint8_t i;
// Complete inner hash
memcpy(s->innerHash, sha1_result(s), HASH_LENGTH);
// Calculate outer hash
sha1_init(s);
for (i = 0; i < BLOCK_LENGTH; i++)
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
for (i = 0; i < HASH_LENGTH; i++)
sha1_writebyte(s, s->innerHash[i]);
return sha1_result(s);
}
// End public domain SHA1 implementation
void sha1(const u8 *data, size_t len, u8 *out) {
sha1nfo s;
sha1_init(&s);
sha1_write(&s, (const char *)data, len);
memcpy(out, sha1_result(&s), HASH_LENGTH);
}
char *sha1_hex(const u8 *data, size_t len) {
u8 digest[HASH_LENGTH];
sha1(data, len, digest);
u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1);
for (size_t i = 0; i < HASH_LENGTH; ++i) {
sprintf((char *)(hex + i * 2), "%02x", digest[i]);
}
return hex;
}
char *sha1_hex_for_file(const char *fname, u32 len) {
int fd = open(fname, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
u32 read_len = MIN(len, (u32)MAX_FILE);
u8 *tmp = ck_alloc(read_len);
ck_read(fd, tmp, read_len, fname);
close(fd);
char *hex = sha1_hex(tmp, read_len);
ck_free(tmp);
return hex;
}

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -239,15 +239,15 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* configure the size of the shared memory segment */
if (ftruncate(shm->cmplog_g_shm_fd, map_size)) {
if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) {
PFATAL("setup_shm(): cmplog ftruncate() failed");
}
/* map the shared memory segment to the address space of the process */
shm->cmp_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
shm->cmplog_g_shm_fd, 0);
shm->cmp_map = mmap(0, sizeof(struct cmp_map), PROT_READ | PROT_WRITE,
MAP_SHARED, shm->cmplog_g_shm_fd, 0);
if (shm->cmp_map == MAP_FAILED) {
close(shm->cmplog_g_shm_fd);

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -178,7 +178,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human;
const u8 *map = (binary_mode || collect_coverage) ? count_class_binary
: count_class_human;
u32 i = map_size;
@ -224,8 +225,13 @@ static void at_exit_handler(void) {
if (remove_shm) {
remove_shm = false;
if (shm.map) afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) deinit_shmem(fsrv, shm_fuzz);
if ((shm_fuzz && shm_fuzz->shmemfuzz_mode) || fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
}
@ -240,14 +246,7 @@ static void analyze_results(afl_forkserver_t *fsrv) {
u32 i;
for (i = 0; i < map_size; i++) {
if (fsrv->trace_bits[i]) {
total += fsrv->trace_bits[i];
if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
// if (!coverage_map[i]) { coverage_map[i] = 1; }
coverage_map[i] |= fsrv->trace_bits[i];
}
if (fsrv->trace_bits[i]) { coverage_map[i] |= fsrv->trace_bits[i]; }
}
@ -1339,6 +1338,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (collect_coverage) { binary_mode = false; } // ensure this
if (optind == argc || !out_file) { usage(argv[0]); }
if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
@ -1531,6 +1532,8 @@ int main(int argc, char **argv_orig, char **envp) {
/* initialize cmplog_mode */
shm_fuzz->cmplog_mode = 0;
atexit(at_exit_handler);
u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
shm_fuzz->shmemfuzz_mode = true;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
@ -1677,12 +1680,9 @@ int main(int argc, char **argv_orig, char **envp) {
if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
FATAL("coult not grab memory");
edges_only = false;
raw_instr_output = true;
}
atexit(at_exit_handler);
if (get_afl_env("AFL_DEBUG")) {
int j = optind;
@ -1699,9 +1699,12 @@ int main(int argc, char **argv_orig, char **envp) {
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
if (in_dir) {
if (execute_testcases(in_dir) == 0) {
@ -1733,9 +1736,12 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
#ifdef __linux__
if (!fsrv->nyx_mode) {
@ -1782,9 +1788,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
remove_shm = 0;
remove_shm = false;
afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
if (fsrv->use_shmem_fuzz) { shm_fuzz = deinit_shmem(fsrv, shm_fuzz); }
u32 ret;

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -82,6 +82,8 @@ static u8 crash_mode, /* Crash-centric mode? */
remove_shm = 1, /* remove shmem on exit? */
debug; /* debug mode */
static u32 del_len_limit = 1; /* Minimum block deletion length */
static volatile u8 stop_soon; /* Ctrl-C pressed? */
static afl_forkserver_t *fsrv;
@ -480,7 +482,7 @@ next_del_blksize:
}
if (del_len > 1 && in_len >= 1) {
if (del_len > del_len_limit && in_len >= 1) {
del_len /= 2;
goto next_del_blksize;
@ -796,8 +798,9 @@ static void usage(u8 *argv0) {
"Minimization settings:\n"
" -e - solve for edge coverage only, ignore hit counts\n"
" -x - treat non-zero exit codes as crashes\n\n"
" -H - minimize a hang (hang mode)\n"
" -l bytes - set minimum block deletion length to speed up minimization\n"
" -x - treat non-zero exit codes as crashes\n"
" -H - minimize a hang (hang mode)\n\n"
"For additional tips, please consult %s/README.md.\n\n"
@ -829,8 +832,9 @@ static void usage(u8 *argv0) {
int main(int argc, char **argv_orig, char **envp) {
s32 opt;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
s32 opt;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
del_limit_given = 0;
char **use_argv;
char **argv = argv_cpy_dup(argc, argv_orig);
@ -846,7 +850,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
switch (opt) {
@ -1055,6 +1059,24 @@ int main(int argc, char **argv_orig, char **envp) {
read_bitmap(optarg, mask_bitmap, map_size);
break;
case 'l':
if (del_limit_given) { FATAL("Multiple -l options not supported"); }
del_limit_given = 1;
if (!optarg) { FATAL("Wrong usage of -l"); }
if (optarg[0] == '-') { FATAL("Dangerously low value of -l"); }
del_len_limit = atoi(optarg);
if (del_len_limit < 1 || del_len_limit > TMIN_MAX_FILE) {
FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE");
}
break;
case 'h':
usage(argv[0]);
return -1;

View File

@ -10,12 +10,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) {
if (i < 15) return -1;
if (buf[0] != 'A') return 0;
if (buf[1] != 'B') return 0;
if (buf[2] != 'C') return 0;
if (buf[3] != 'D') return 0;
int *icmp = (int *)(buf + 4);
int *icmp = (int *)(buf + 1);
if (*icmp != 0x69694141) return 0;
if (memcmp(buf + 8, "1234EF", 6) == 0) abort();
if (memcmp(buf + 5, "1234EF", 6) == 0) abort();
return 0;
}

View File

@ -197,7 +197,8 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
for I in char short int long "long long"; do
for BITS in 8 16 32 64; do
bin="$testcase-split-$I-$BITS.compcov"
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
#AFL_LLVM_INSTRUMENT=AFL
AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
if ! test -e "$bin"; then
cat test.out
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
@ -263,13 +264,12 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
}
rm -f test-compcov test.out instrumentlist.txt
AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
../afl-clang-fast -O0 -o test-c test-cmplog.c > /dev/null 2>&1
test -e test-cmplog && {
$ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
{
mkdir -p in
echo 00000000000000000000000000000000 > in/in
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -l 3 -m none -V30 -i in -o out -c ./test-cmplog -- ./test-c >>errors 2>&1
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1
} >>errors 2>&1
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
@ -284,7 +284,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
$ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
INCOMPLETE=1
}
rm -rf errors test-cmplog test-c in core.*
rm -rf errors test-cmplog in core.*
../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
test -e test-persistent && {
echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {

View File

@ -1 +1 @@
63aab0f
4b4fdab1

View File

@ -89,8 +89,8 @@ def dump_arch_info():
def dump_regs():
reg_state = {}
for reg in current_arch.all_registers:
reg_val = get_register(reg)
for reg in gef.arch.registers:
reg_val = gef.arch.register(reg)
reg_state[reg.strip().strip("$")] = reg_val
return reg_state
@ -101,7 +101,9 @@ def dump_process_memory(output_dir):
final_segment_list = []
# GEF:
vmmap = get_process_maps()
vmmap = gef.memory.maps
memory = GefMemoryManager()
if not vmmap:
print("No address mapping information found")
return final_segment_list
@ -126,7 +128,7 @@ def dump_process_memory(output_dir):
if entry.is_readable() and not "(deleted)" in entry.path:
try:
# Compress and dump the content to a file
seg_content = read_memory(entry.page_start, entry.size)
seg_content = memory.read(entry.page_start, entry.size)
if seg_content == None:
print(
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(

View File

@ -136,7 +136,7 @@ def overlap_alignments(segments, memory):
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/Triple.h
def get_arch():
arch, arch_vendor, arch_os = lldb.target.GetTriple().split("-")
arch, arch_vendor, arch_os, *arch_remains = lldb.debugger.GetSelectedTarget().GetTriple().split("-")
if arch == "x86_64":
return "x64"
elif arch == "x86" or arch == "i386":
@ -165,7 +165,7 @@ def dump_arch_info():
def dump_regs():
reg_state = {}
for reg_list in lldb.frame.GetRegisters():
for reg_list in lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetRegisters():
if "general purpose registers" in reg_list.GetName().lower():
for reg in reg_list:
reg_state[reg.GetName()] = int(reg.GetValue(), 16)
@ -180,8 +180,9 @@ def get_section_info(sec):
module_name = sec.addr.module.file.GetFilename()
module_name = module_name if module_name is not None else ""
long_name = module_name + "." + name
load_addr = sec.addr.GetLoadAddress(lldb.debugger.GetSelectedTarget())
return sec.addr.load_addr, (sec.addr.load_addr + sec.size), sec.size, long_name
return load_addr, (load_addr + sec.size), sec.size, long_name
def dump_process_memory(output_dir):
@ -191,7 +192,7 @@ def dump_process_memory(output_dir):
# 1st pass:
# Loop over the segments, fill in the segment info dictionary
for module in lldb.target.module_iter():
for module in lldb.debugger.GetSelectedTarget().module_iter():
for seg_ea in module.section_iter():
seg_info = {"module": module.file.GetFilename()}
(
@ -201,8 +202,8 @@ def dump_process_memory(output_dir):
seg_info["name"],
) = get_section_info(seg_ea)
# TODO: Ugly hack for -1 LONG address on 32-bit
if seg_info["start"] >= sys.maxint or seg_size <= 0:
print "Throwing away page: {}".format(seg_info["name"])
if seg_info["start"] >= sys.maxsize or seg_size <= 0:
print ("Throwing away page: {}".format(seg_info["name"]))
continue
# Page-align segment
@ -212,7 +213,7 @@ def dump_process_memory(output_dir):
raw_segment_list.append(seg_info)
# Add the stack memory region (just hardcode 0x1000 around the current SP)
sp = lldb.frame.GetSP()
sp = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetSP()
start_sp = ALIGN_PAGE_DOWN(sp)
raw_segment_list.append(
{"start": start_sp, "end": start_sp + 0x1000, "name": "STACK"}
@ -228,7 +229,7 @@ def dump_process_memory(output_dir):
start_addr = -1
next_region_addr = 0
while next_region_addr > start_addr:
err = lldb.process.GetMemoryRegionInfo(next_region_addr, mem_info)
err = lldb.debugger.GetSelectedTarget().GetProcess().GetMemoryRegionInfo(next_region_addr, mem_info)
# TODO: Should check err.success. If False, what do we do?
if not err.success:
break
@ -267,7 +268,7 @@ def dump_process_memory(output_dir):
region_name = seg_info["name"]
# Compress and dump the content to a file
err = lldb.SBError()
seg_content = lldb.process.ReadMemory(
seg_content = lldb.debugger.GetSelectedTarget().GetProcess().ReadMemory(
start_addr, end_addr - start_addr, err
)
if seg_content == None:
@ -340,11 +341,12 @@ def main():
index_file.close()
print ("Done.")
except Exception, e:
except Exception as e:
print ("!!! ERROR:\n\t{}".format(repr(e)))
if __name__ == "__main__":
lldb.debugger = lldb.SBDebugger.Create()
main()
elif lldb.debugger:
main()

View File

@ -111,12 +111,14 @@ def dump_regs():
reg_state = {}
for reg in pwndbg.gdblib.regs.all:
reg_val = pwndbg.gdblib.regs[reg]
if reg_val is None:
continue
# current dumper script looks for register values to be hex strings
# reg_str = "0x{:08x}".format(reg_val)
# if "64" in get_arch():
# reg_str = "0x{:016x}".format(reg_val)
# reg_state[reg.strip().strip('$')] = reg_str
reg_state[reg.strip().strip("$")] = reg_val
reg_state[reg.strip().strip("$")] = int(reg_val)
return reg_state

View File

@ -21,10 +21,10 @@ import zlib
# Unicorn imports
from unicornafl import *
from unicornafl.arm_const import *
from unicornafl.arm64_const import *
from unicornafl.x86_const import *
from unicornafl.mips_const import *
from unicorn.arm_const import *
from unicorn.arm64_const import *
from unicorn.x86_const import *
from unicorn.mips_const import *
# If Capstone libraries are availible (only check once)
try:
@ -87,9 +87,10 @@ class UnicornSimpleHeap(object):
_uc = None # Unicorn engine instance to interact with
_chunks = [] # List of all known chunks
_chunks_freed = [] # List of all freed chunks
_debug_print = False # True to print debug information
def __init__(self, uc, debug_print=False):
def __init__(self, uc, debug_print=False uaf_check=False):
self._uc = uc
self._debug_print = debug_print
@ -101,12 +102,23 @@ class UnicornSimpleHeap(object):
# - Allocate at least 1 4k page of memory to make Unicorn happy
# - Add guard pages at the start and end of the region
total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
if size == 0:
return 0
# Gross but efficient way to find space for the chunk:
chunk = None
for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
try:
self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
chunk = self.HeapChunk(addr, total_chunk_size, size)
if self.uaf_check:
for chunk_freed in self._chunks_freed:
if chunk_freed.is_buffer_in_chunk(chunk.data_addr, 1):
self._chunks_freed.remove(chunk_freed)
break
if self._debug_print:
print(
"Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
@ -148,6 +160,9 @@ class UnicornSimpleHeap(object):
return new_chunk_addr
def free(self, addr):
if addr == 0:
return False
for chunk in self._chunks:
if chunk.is_buffer_in_chunk(addr, 1):
if self._debug_print:
@ -157,9 +172,14 @@ class UnicornSimpleHeap(object):
)
)
self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
if self.uaf_check:
self._chunks_freed.append(chunk)
self._chunks.remove(chunk)
return True
return False
# Freed an object that doesn't exist. Maybe 'dobule-free' or 'invalid free' vulnerability here.
self._uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
# Implements basic guard-page functionality
def __check_mem_access(self, uc, access, address, size, value, user_data):
@ -179,6 +199,15 @@ class UnicornSimpleHeap(object):
# Force a memory-based crash
uc.force_crash(UcError(UC_ERR_READ_PROT))
if self.uaf_check:
for chunk in self._chunks_freed:
if address >= chunk.actual_addr and (
(address + size) <= (chunk.actual_addr + chunk.total_size)
):
if chunk.is_buffer_in_chunk(address, size):
print("Use-after-free @ 0x{0:016x}".format(address))
uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
# ---------------------------
# ---- Loading function

View File

@ -119,7 +119,7 @@ def main():
binary_code = binary_file.read()
binary_file.close()
# Apply constraints to the mutated input
# Assert that the binary size is within limits
if len(binary_code) > CODE_SIZE_MAX:
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
return

View File

@ -10,6 +10,7 @@ PROGRAMS = afl-network-client afl-network-server
HASH=\#
CFLAGS += -Wno-pointer-sign
LDFLAGS += -ldl
ifdef STATIC
CFLAGS += -static

View File

@ -69,3 +69,21 @@ need to be changed for other OSes.
Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen)
Also, the following example (generate_libtoken_dict.sh) shows how to use a script to capture tokens from the
files in the target output directory,
and then generate a dictionary file from those tokens.
#### usage:
```bash
./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 -- [-program_args]
```
#### description opts:
- ```-o``` : Path to target output directory ;
- ```-b``` : Path to target program binary ;
- ```-p``` : Path to LD_PRELOAD library ;
- ```-t``` : Timeout in seconds ;
- ```-- [-program_args]```: Any additional arguments required by the target binary can be specified after ```--```.
#### output:
A sorted and unique token dictionary file with the extension ``*.dict``
is created in the same directory as the target output containing tokens captured during the execution of the target binary.

View File

@ -0,0 +1,55 @@
#help
usage() {
echo "Usage: $0 -o <target_output> -b <target_bin> -p <LD_PRELOAD_PATH> [-t <timeout_sec>] -- [target_args]"
echo "Options:"
echo " -o Path to target output directory"
echo " -b Path to target program binary"
echo " -p Path to LD_PRELOAD library"
echo " -t Timeout in seconds"
exit 1
}
#parse cli options
while getopts ":o:b:p:t:" opt; do
case $opt in
o) target_output="$OPTARG" ;;
b) target_bin="$OPTARG" ;;
p) LD_PRELOAD_PATH="$OPTARG" ;;
t) timeout_sec="$OPTARG" ;;
\?) echo "Invalid option: -$OPTARG" >&2; usage ;;
:) echo "Option -$OPTARG requires an argument." >&2; usage ;;
esac
done
#shift away the parsed opts
shift $((OPTIND - 1))
#check options
if [ -z "$target_output" ] || [ -z "$target_bin" ] || [ -z "$LD_PRELOAD_PATH" ]; then
echo "Error: Missing mandatory opts" >&2
usage
fi
# initialize vars
AFL_TOKEN_FILE="${PWD}/temp_output.txt"
AFL_DICT_FILE="${PWD}/$(basename "$target_bin")_tokens.dict"
#generate token-file
{
touch "$AFL_TOKEN_FILE"
for i in $(find "$target_output" -type f -name "id*"); do
LD_PRELOAD="$LD_PRELOAD_PATH" \
timeout -s SIGKILL "$timeout_sec" \
"$target_bin" "$@" "$i"
done
} >"$AFL_TOKEN_FILE"
# sort & remove duplicates
sort -u "$AFL_TOKEN_FILE" >"$AFL_DICT_FILE"
# delete temp-file
rm "$AFL_TOKEN_FILE"
# print done-message
echo "Token dictionary created: $AFL_DICT_FILE"
echo "Script completed successfully"