Compare commits

...

63 Commits

Author SHA1 Message Date
91320d95ae showmap 2024-06-02 16:56:46 +02:00
c00d01bc7b score values 2024-06-02 16:37:53 +02:00
ce6ff9ff27 fixes 2024-05-27 14:43:15 +02:00
3d15e1efb4 add cmplog stats to experiment 2024-05-27 13:13:51 +02:00
59d546f39a minor enhancement 2024-05-23 21:42:17 +02:00
35156eb917 update 2024-05-17 19:04:25 +02:00
4265d70d70 fix 2024-05-17 18:40:14 +02:00
e36185cbd5 debug 2024-05-16 14:46:24 +02:00
2dc967fee3 debug 2024-05-16 14:43:35 +02:00
d4071b0fe4 debug 2024-05-16 14:40:53 +02:00
5a0a33e52a debug 2024-05-16 13:30:25 +02:00
c510ba6863 fixes and debug 2024-05-16 12:30:53 +02:00
bd4c9a5eab use score for weighting in exploit mode 2024-05-16 11:43:17 +02:00
f9e85817ad write score to map 2024-05-16 11:24:15 +02:00
8758be3630 add vuln complexity score 2024-05-15 18:03:07 +02:00
31a7ff2ba2 add loop analysis to CC 2024-05-15 15:28:03 +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
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
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
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
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
61 changed files with 1475 additions and 202 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

@ -46,7 +46,7 @@ LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^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

@ -4,7 +4,7 @@
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.20c
GitHub version: 4.21a
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -11,6 +11,7 @@
- afl-showmap -f support
- afl-fuzz multicore wrapper script
- when trimming then perform crash detection
- cyclomatic complexity: 2 + calls + edges - blocks
## Should

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)
@ -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

@ -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

View File

@ -3,6 +3,26 @@
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.21a (dev)
* afl-fuzz
- added AFL_DISABLE_REDUNDANT for huge queues
- 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)
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode
- 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
* afl-cmin
- work with input files that have a space
* enhanced the ASAN configuration
### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built

View File

@ -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.

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

@ -200,6 +200,8 @@ struct queue_entry {
u8 *fname; /* File name for the test case */
u32 len; /* Input length */
u32 id; /* entry number in queue_buf */
u32 found;
s32 cmp, fcmp, rtn;
u8 colorized, /* Do not run redqueen stage again */
cal_failed; /* Calibration failed? */
@ -251,6 +253,9 @@ struct queue_entry {
struct skipdet_entry *skipdet_e;
u32 score; /* complexity/vulnerability score */
u64 total_execs; /* total executes of this item */
};
struct extra_data {
@ -452,7 +457,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;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -831,6 +837,9 @@ typedef struct afl_state {
/* How often did we evict from the cache (for statistics only) */
u32 q_testcase_evictions;
/* current complexity/vulnerability score received */
u32 current_score;
/* Refs to each queue entry with cached testcase (for eviction, if cache_count
* is too large) */
struct queue_entry **q_testcase_cache;
@ -1404,6 +1413,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

@ -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,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.20c"
#define VERSION "++4.21a"
/******************************************************
* *
@ -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,13 +21,16 @@ 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_DUMP_QUEUE_ON_EXIT", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
"AFL_DUMP_VULNERABILITY_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_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"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",
@ -107,15 +110,15 @@ static char *afl_environment_variables[] = {
"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_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

@ -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

@ -60,6 +60,8 @@
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "config.h"
#include "debug.h"
@ -172,6 +174,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
}
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
using PostDomTreeCallback =
function_ref<const PostDominatorTree *(Function &F)>;
@ -187,13 +190,15 @@ class ModuleSanitizerCoverageLTO
}
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback);
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
private:
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback);
/* void InjectCoverageForIndirectCalls(Function &F,
ArrayRef<Instruction *>
IndirCalls);*/
@ -250,6 +255,7 @@ class ModuleSanitizerCoverageLTO
uint32_t afl_global_id = 0;
uint32_t unhandled = 0;
uint32_t select_cnt = 0;
uint32_t dump_cc = 0, dump_vc = 0;
uint32_t instrument_ctx = 0;
uint32_t instrument_ctx_max_depth = 0;
uint32_t extra_ctx_inst = 0;
@ -291,6 +297,7 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<PostDominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
}
@ -319,7 +326,15 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
};
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
auto LoopCallback = [this](Function &F) -> const LoopInfo * {
return &this->getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
};
ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback);
return 1;
}
@ -341,7 +356,7 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 15
PB.registerFullLinkTimeOptimizationEarlyEPCallback(
PB.registerFullLinkTimeOptimizationLastEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
@ -372,15 +387,21 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
};
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
return PreservedAnalyses::all();
return &FAM.getResult<LoopAnalysis>(F);
};
ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback);
return PreservedAnalyses::none();
}
bool ModuleSanitizerCoverageLTO::instrumentModule(
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false;
/*
@ -474,6 +495,10 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
if (getenv("AFL_DUMP_VULNERABILITY_COMPLEXITY")) { dump_vc = 1; }
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
@ -486,7 +511,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);
}
@ -1057,7 +1082,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
// M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
for (auto &F : M)
instrumentFunction(F, DTCallback, PDTCallback);
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
// AFL++ START
if (dFile.is_open()) dFile.close();
@ -1347,7 +1372,8 @@ Function *returnOnlyCaller(Function *F) {
}
void ModuleSanitizerCoverageLTO::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback) {
if (F.empty()) return;
if (F.getName().find(".module_ctor") != std::string::npos)
@ -1421,6 +1447,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
const DominatorTree *DT = DTCallback(F);
const PostDominatorTree *PDT = PDTCallback(F);
const LoopInfo *LI = LCallback(F);
bool IsLeafFunc = true;
uint32_t skip_next = 0;
uint32_t call_counter = 0, call_depth = 0;
@ -1955,6 +1982,51 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
}
unsigned int score = 0;
if (dump_cc) { score += calcCyclomaticComplexity(&F, LI); }
if (dump_vc) { score += calcVulnerabilityScore(&F, LI, DT, PDT); }
if (score) {
BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
IRBuilder<> builder(&*IP);
// Access the int32 value at u8 offset 1 (unaligned access)
LoadInst *MapPtr =
builder.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
llvm::Value *CastToInt8Ptr =
builder.CreateBitCast(MapPtr, llvm::PointerType::get(Int8Ty, 0));
llvm::Value *Int32Ptr = builder.CreateGEP(
Int8Ty, CastToInt8Ptr, llvm::ConstantInt::get(Int32Ty, 1));
llvm::Value *CastToInt32Ptr =
builder.CreateBitCast(Int32Ptr, llvm::PointerType::get(Int32Ty, 0));
// Load the unaligned int32 value
llvm::LoadInst *Load = builder.CreateLoad(Int32Ty, CastToInt32Ptr);
Load->setAlignment(llvm::Align(1));
// Value to add
llvm::Value *ValueToAdd = llvm::ConstantInt::get(Int32Ty, score);
// Perform addition and check for wrap around
llvm::Value *Add =
builder.CreateAdd(Load, ValueToAdd, "addValue", true, true);
// Check if addition wrapped (unsigned)
llvm::Value *DidWrap = builder.CreateICmpULT(Add, Load, "didWrap");
// Select the maximum value if there was a wrap, otherwise use the result
llvm::Value *MaxInt32 = llvm::ConstantInt::get(Int32Ty, UINT32_MAX);
llvm::Value *Result =
builder.CreateSelect(DidWrap, MaxInt32, Add, "selectMaxOrResult");
// Store the result back at the same unaligned offset
llvm::StoreInst *Store = builder.CreateStore(Result, CastToInt32Ptr);
Store->setAlignment(llvm::Align(1));
}
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
// InjectCoverageForIndirectCalls(F, IndirCalls);

View File

@ -70,6 +70,8 @@
#endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "config.h"
#include "debug.h"
@ -119,6 +121,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
}
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
using PostDomTreeCallback =
function_ref<const PostDominatorTree *(Function &F)>;
@ -135,11 +138,13 @@ class ModuleSanitizerCoverageAFL
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback);
private:
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback);
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
void InjectTraceForSwitch(Function &F,
ArrayRef<Instruction *> SwitchTraceTargets);
@ -195,7 +200,7 @@ class ModuleSanitizerCoverageAFL
SanitizerCoverageOptions Options;
uint32_t instr = 0, selects = 0, unhandled = 0;
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0, dump_vc = 0;
GlobalVariable *AFLMapPtr = NULL;
ConstantInt *One = NULL;
ConstantInt *Zero = NULL;
@ -233,8 +238,10 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
ModuleAnalysisManager &MAM) {
ModuleSanitizerCoverageAFL ModuleSancov(Options);
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
return &FAM.getResult<DominatorTreeAnalysis>(F);
@ -246,9 +253,21 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
};
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
return &FAM.getResult<LoopAnalysis>(F);
};
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback)) {
return PreservedAnalyses::none();
return PreservedAnalyses::all();
} else {
return PreservedAnalyses::all();
}
}
@ -324,12 +343,17 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
}
bool ModuleSanitizerCoverageAFL::instrumentModule(
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback) {
setvbuf(stdout, NULL, _IONBF, 0);
if (getenv("AFL_DEBUG")) { debug = 1; }
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
if (getenv("AFL_DUMP_VULNERABILITY_COMPLEXITY")) { dump_vc = 1; }
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
@ -427,7 +451,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
for (auto &F : M)
instrumentFunction(F, DTCallback, PDTCallback);
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
Function *Ctor = nullptr;
@ -566,7 +590,8 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
#endif
void ModuleSanitizerCoverageAFL::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
LoopInfoCallback LCallback) {
if (F.empty()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
@ -602,6 +627,7 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
const DominatorTree *DT = DTCallback(F);
const PostDominatorTree *PDT = PDTCallback(F);
const LoopInfo *LI = LCallback(F);
bool IsLeafFunc = true;
for (auto &BB : F) {
@ -634,6 +660,51 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
}
unsigned int score = 0;
if (dump_cc) { score += calcCyclomaticComplexity(&F, LI); }
if (dump_vc) { score += calcVulnerabilityScore(&F, LI, DT, PDT); }
if (score) {
BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
IRBuilder<> builder(&*IP);
// Access the int32 value at u8 offset 1 (unaligned access)
LoadInst *MapPtr =
builder.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
llvm::Value *CastToInt8Ptr =
builder.CreateBitCast(MapPtr, llvm::PointerType::get(Int8Ty, 0));
llvm::Value *Int32Ptr = builder.CreateGEP(
Int8Ty, CastToInt8Ptr, llvm::ConstantInt::get(Int32Ty, 1));
llvm::Value *CastToInt32Ptr =
builder.CreateBitCast(Int32Ptr, llvm::PointerType::get(Int32Ty, 0));
// Load the unaligned int32 value
llvm::LoadInst *Load = builder.CreateLoad(Int32Ty, CastToInt32Ptr);
Load->setAlignment(llvm::Align(1));
// Value to add
llvm::Value *ValueToAdd = llvm::ConstantInt::get(Int32Ty, score);
// Perform addition and check for wrap around
llvm::Value *Add =
builder.CreateAdd(Load, ValueToAdd, "addValue", true, true);
// Check if addition wrapped (unsigned)
llvm::Value *DidWrap = builder.CreateICmpULT(Add, Load, "didWrap");
// Select the maximum value if there was a wrap, otherwise use the result
llvm::Value *MaxInt32 = llvm::ConstantInt::get(Int32Ty, UINT32_MAX);
llvm::Value *Result =
builder.CreateSelect(DidWrap, MaxInt32, Add, "selectMaxOrResult");
// Store the result back at the same unaligned offset
llvm::StoreInst *Store = builder.CreateStore(Result, CastToInt32Ptr);
Store->setAlignment(llvm::Align(1));
}
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
// InjectTraceForCmp(F, CmpTraceTargets);
// InjectTraceForSwitch(F, SwitchTraceTargets);

View File

@ -1849,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

@ -14,7 +14,21 @@
#include <fstream>
#include <cmath>
#include <llvm/Support/raw_ostream.h>
#if LLVM_VERSION_MAJOR >= 13
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Analysis/PostDominators.h"
#endif
// #define LEOPARD_USE_WEIGHTS 1
#define IS_EXTERN extern
#include "afl-llvm-common.h"
@ -26,6 +40,294 @@ static std::list<std::string> allowListFunctions;
static std::list<std::string> denyListFiles;
static std::list<std::string> denyListFunctions;
#if LLVM_VERSION_MAJOR >= 13
// Leopard complexity calculations
#ifndef LEOPARD_USE_WEIGHTS
#define C1_WEIGHT 1.0
#define C2_WEIGHT 1.0
#define C3_WEIGHT 1.0
#define C4_WEIGHT 1.0
#define V1_WEIGHT 1.0
#define V2_WEIGHT 1.0
#define V3_WEIGHT 1.0
#define V4_WEIGHT 1.0
#define V5_WEIGHT 1.0
#define V6_WEIGHT 1.0
#define V7_WEIGHT 1.0
#define V8_WEIGHT 1.0
#define V9_WEIGHT 1.0
#define V10_WEIGHT 1.0
#define V11_WEIGHT 1.0
#else
// Cyclomatic weights
#define C1_WEIGHT 1.0
#define C2_WEIGHT 1.0
#define C3_WEIGHT 1.0
#define C4_WEIGHT 1.0
// Vulnerability weights
#define V1_WEIGHT 1.5
#define V2_WEIGHT 3.25
#define V3_WEIGHT 4.25
#define V4_WEIGHT 3.0
#define V5_WEIGHT 4.25
#define V6_WEIGHT 7.75
#define V7_WEIGHT 2.5
#define V8_WEIGHT 2.5
#define V9_WEIGHT 4.0
#define V10_WEIGHT 5.25
#define V11_WEIGHT 3.5
#endif
static void countNestedLoops(Loop *L, int depth, unsigned int &loopCount,
unsigned int &nestedLoopCount,
unsigned int &maxNestingLevel) {
loopCount++;
if (!L->getSubLoops().empty()) {
// Increment nested loop count by the number of sub-loops
nestedLoopCount += L->getSubLoops().size();
// Update maximum nesting level
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
// Recursively count sub-loops
for (Loop *SubLoop : L->getSubLoops()) {
countNestedLoops(SubLoop, depth + 1, loopCount, nestedLoopCount,
maxNestingLevel);
}
}
}
unsigned int calcCyclomaticComplexity(llvm::Function *F,
const llvm::LoopInfo *LI) {
unsigned int numBlocks = 0;
unsigned int numEdges = 0;
unsigned int numCalls = 0;
unsigned int numLoops = 0;
unsigned int numNestedLoops = 0;
unsigned int maxLoopNesting = 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++; }
}
}
for (Loop *L : *LI) {
countNestedLoops(L, 1, numLoops, numNestedLoops, maxLoopNesting);
}
// 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 =
(unsigned int)(C1_WEIGHT * (double)(2 + numCalls + numEdges - numBlocks) +
C2_WEIGHT * (double)numLoops +
C3_WEIGHT * (double)numNestedLoops +
C4_WEIGHT * (double)maxLoopNesting);
// if (debug) {
fprintf(stderr,
"CyclomaticComplexity for %s: %u (calls=%u edges=%u blocks=%u "
"loops=%u nested_loops=%u max_loop_nesting_level=%u)\n",
F->getName().str().c_str(), cc, numCalls, numEdges, numBlocks,
numLoops, numNestedLoops, maxLoopNesting);
//}
return cc;
}
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
const llvm::DominatorTree *DT,
const llvm::PostDominatorTree *PDT) {
unsigned int score = 0;
// V1 and V2
unsigned paramCount = F->arg_size();
unsigned calledParamCount = 0;
// V3, V4 and V5
unsigned pointerArithCount = 0;
unsigned totalPointerArithParams = 0;
unsigned maxPointerArithVars = 0;
// V6 to V11
unsigned nestedControlStructCount = 0;
unsigned maxNestingLevel = 0;
unsigned maxControlDependentControls = 0;
unsigned maxDataDependentControls = 0;
unsigned ifWithoutElseCount = 0;
unsigned controlPredicateVarCount = 0;
std::function<void(Loop *, unsigned)> countNestedLoops = [&](Loop *L,
unsigned depth) {
nestedControlStructCount++;
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
for (Loop *SubLoop : L->getSubLoops()) {
countNestedLoops(SubLoop, depth + 1);
}
};
for (Loop *TopLoop : *LI) {
countNestedLoops(TopLoop, 1);
}
for (inst_iterator I = inst_begin(*F), E = inst_end(*F); I != E; ++I) {
if (CallInst *CI = dyn_cast<CallInst>(&*I)) {
if (Function *CalledF = CI->getCalledFunction()) {
calledParamCount += CalledF->arg_size();
}
}
if (auto *GEP = dyn_cast<GetElementPtrInst>(&*I)) {
pointerArithCount++;
unsigned numPointerArithVars = GEP->getNumOperands();
totalPointerArithParams += numPointerArithVars;
if (numPointerArithVars > maxPointerArithVars) {
maxPointerArithVars = numPointerArithVars;
}
}
if (BranchInst *BI = dyn_cast<BranchInst>(&*I)) {
if (BI->isConditional()) {
unsigned controlDependentCount = 0;
unsigned dataDependentCount = 0;
for (Use &U : BI->operands()) {
if (Instruction *Op = dyn_cast<Instruction>(U.get())) {
if (DT->dominates(Op, &*I)) { controlDependentCount++; }
if (PDT->dominates(Op, &*I)) { dataDependentCount++; }
}
}
if (controlDependentCount > maxControlDependentControls) {
maxControlDependentControls = controlDependentCount;
}
if (dataDependentCount > maxDataDependentControls) {
maxDataDependentControls = dataDependentCount;
}
// Check for if() without else
BasicBlock *TrueBB = BI->getSuccessor(0);
BasicBlock *FalseBB = BI->getSuccessor(1);
if (TrueBB && FalseBB) {
if (TrueBB->getSinglePredecessor() == &*I->getParent() &&
FalseBB->empty()) {
ifWithoutElseCount++;
}
}
// Count variables involved in control predicates
if (ICmpInst *ICmp = dyn_cast<ICmpInst>(BI->getCondition())) {
controlPredicateVarCount += ICmp->getNumOperands();
} else if (BinaryOperator *BinOp =
dyn_cast<BinaryOperator>(BI->getCondition())) {
controlPredicateVarCount += BinOp->getNumOperands();
} else if (SelectInst *Select =
dyn_cast<SelectInst>(BI->getCondition())) {
controlPredicateVarCount += Select->getNumOperands();
}
}
}
}
score = (unsigned int)(V1_WEIGHT * (double)paramCount +
V2_WEIGHT * (double)calledParamCount +
V3_WEIGHT * (double)pointerArithCount +
V4_WEIGHT * (double)totalPointerArithParams +
V5_WEIGHT * (double)maxPointerArithVars +
V6_WEIGHT * (double)nestedControlStructCount +
V7_WEIGHT * (double)maxNestingLevel +
V8_WEIGHT * (double)maxControlDependentControls +
V9_WEIGHT * (double)maxDataDependentControls +
V10_WEIGHT * (double)ifWithoutElseCount +
V11_WEIGHT * (double)controlPredicateVarCount);
fprintf(stderr,
"VulnerabilityScore for %s: %u (paramCount=%u "
"calledParamCount=%u|pointerArithCount=%u totalPointerArithParams=%u "
"maxPointerArithVars=%u|maxNestingLevel=%u "
"maxControlDependentControls=%u maxDataDependentControls=%u "
"ifWithoutElseCount=%u controlPredicateVarCount=%u)\n",
F->getName().str().c_str(), score, paramCount, calledParamCount,
pointerArithCount, totalPointerArithParams, maxPointerArithVars,
maxNestingLevel, maxControlDependentControls,
maxDataDependentControls, ifWithoutElseCount,
controlPredicateVarCount);
return score;
}
#endif
char *getBBName(const llvm::BasicBlock *BB) {
static char *name;
@ -91,7 +393,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

@ -12,6 +12,7 @@
#include <sys/time.h>
#include "llvm/Config/llvm-config.h"
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
typedef long double max_align_t;
#endif
@ -26,6 +27,19 @@ typedef long double max_align_t;
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
#if LLVM_VERSION_MAJOR > 12
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Analysis/PostDominators.h"
#endif
#if LLVM_VERSION_MAJOR > 3 || \
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
#include "llvm/IR/DebugInfo.h"
@ -55,6 +69,11 @@ 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,
const llvm::LoopInfo *LI);
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
const llvm::DominatorTree *DT,
const llvm::PostDominatorTree *PDT);
#ifndef IS_EXTERN
#define IS_EXTERN

View File

@ -57,6 +57,12 @@
#include <set>
#include "afl-llvm-common.h"
#if LLVM_MAJOR >= 19
#define STARTSWITH starts_with
#else
#define STARTSWITH startswith
#endif
using namespace llvm;
namespace {
@ -230,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 &&
@ -465,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") ||
@ -520,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);
@ -604,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 =

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.
@ -266,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);
@ -1778,7 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
auto op0 = CI->getOperand(0);
auto op1 = CI->getOperand(1);
// 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())) {

View File

@ -1 +1 @@
40033af00c
a6f0632a65

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
@ -1261,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;
@ -1583,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;");
@ -1906,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) {
@ -2473,13 +2484,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);

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.
@ -108,9 +108,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) {

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);
@ -2078,10 +2082,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++,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
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.
@ -481,6 +481,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
s32 fd;
u64 cksum = 0;
// will be classified away otherwise
if (unlikely((afl->current_score = *(u32 *)((u8 *)afl->fsrv.trace_bits + 1)) >
0)) {
memset(afl->fsrv.trace_bits + 1, 0, 4);
}
/* Update path frequency. */
/* Generating a hash on every input is super expensive. Bad idea and should
@ -527,12 +535,24 @@ 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%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 : "");
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
@ -542,10 +562,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
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) &&
@ -743,11 +767,23 @@ 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%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 : "");
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
@ -799,11 +835,23 @@ 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%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 : "");
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
@ -873,10 +921,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.

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,14 +1190,27 @@ void perform_dry_run(afl_state_t *afl) {
#ifndef SIMPLE_FILES
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 : "");
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
@ -1376,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); }
@ -1485,10 +1531,26 @@ void pivot_inputs(afl_state_t *afl) {
}
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 : "");
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
@ -1702,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);
@ -1713,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);
@ -1725,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;
@ -1742,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
@ -1865,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);
@ -1873,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)
@ -1888,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
@ -1935,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);
@ -1970,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,27 +60,61 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
// #define DEBUG_QUEUE 1
double compute_weight(afl_state_t *afl, struct queue_entry *q,
double avg_exec_us, double avg_bitmap_size,
double avg_top_size) {
double avg_top_size, double avg_score) {
double weight = 1.0;
/*
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
}
}
#ifdef DEBUG_QUEUE
fprintf(stderr, "WEIGHT id=%u fname=%s start_weight=1.0\n", q->id,
q->fname); fprintf(stderr, " after step 1: %.2f (log10(hits))\n", weight);
#endif
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 2: %.2f (exec_us)\n", weight);
#endif
weight *= (log(q->bitmap_size) / avg_bitmap_size);
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 3: %.2f (log(bitmap_size))\n", weight);
#endif
weight *= (1 + (q->tc_ref / avg_top_size));
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 4: %.2f (top_size)\n", weight);
#endif
if (unlikely(avg_score != 0.0)) { weight *= (q->score / avg_score); }
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 5: %.2f (score)\n", weight);
#endif
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)) {
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; }
weight += 1;
weight *= 5;
}
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 6: %.2f (favored)\n", weight);
#endif
*/
if (unlikely(!q->was_fuzzed)) { weight *= 5; }
#ifdef DEBUG_QUEUE
fprintf(stderr, " after step 7: %.2f (was_fuzzed)\n", weight);
#endif
if (unlikely(q->fs_redundant)) { weight = 0.0; }
#ifdef DEBUG_QUEUE
fprintf(stderr, " after final step: %.2f (fs_redundant)\n", weight);
#endif
return weight;
@ -90,7 +124,8 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
void create_alias_table(afl_state_t *afl) {
u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1;
u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1,
exploit = afl->fuzz_mode;
double sum = 0;
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
@ -118,6 +153,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_score = 0.0;
u32 active = 0;
for (i = 0; i < n; i++) {
@ -130,6 +166,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;
if (exploit) { avg_score += /*log(*/ q->score /*)*/; }
++active;
}
@ -140,14 +177,16 @@ void create_alias_table(afl_state_t *afl) {
avg_bitmap_size /= active;
avg_top_size /= active;
if (exploit) { avg_score /= active; }
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
if (likely(!q->disabled)) {
q->weight =
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size,
avg_top_size, avg_score);
q->perf_score = calculate_score(afl, q);
sum += q->weight;
@ -370,9 +409,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 +635,13 @@ 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->cmp = q->fcmp = q->rtn = -1;
if (afl->queue_cur) {
afl->queue_cur->found++;
}
q->score = afl->current_score;
if (unlikely(!q->score)) { q->score = 1; }
#ifdef INTROSPECTION
q->bitsmap_size = afl->bitsmap_size;
@ -914,6 +960,8 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
u32 avg_bitmap_size = afl->total_bitmap_size / bitmap_entries;
u32 perf_score = 100;
return perf_score;
/* Adjust score based on execution speed of this path, compared to the
global average. Multiplier ranges from 0.1x to 3x. Fast inputs are
less expensive to fuzz, so we're giving them more air time. */

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.
@ -2764,15 +2764,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=");
@ -3072,6 +3072,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
afl->stage_max = 0;
afl->stage_cur = 0;
afl->queue_cur->cmp = afl->queue_cur->fcmp = afl->queue_cur->rtn = 0;
u32 lvl = (afl->queue_cur->colorized ? 0 : LVL1) +
(afl->cmplog_lvl == CMPLOG_LVL_MAX ? LVL3 : 0);
@ -3089,6 +3091,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
if (!afl->shm.cmp_map->headers[k].hits) { continue; }
if (afl->shm.cmp_map->headers[k].type != CMP_TYPE_INS)
afl->queue_cur->rtn++;
else if (unlikely((afl->shm.cmp_map->headers[k].attribute & 8) == 8))
afl->queue_cur->fcmp++;
else
afl->queue_cur->cmp++;
if (afl->pass_stats[k].faileds >= CMPLOG_FAIL_MAX ||
afl->pass_stats[k].total >= CMPLOG_FAIL_MAX) {

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>
@ -606,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;
@ -771,6 +773,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. */
@ -829,8 +833,8 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->stop_soon) { goto close_sync; }
afl->syncing_party = sd_ent->d_name;
afl->queued_imported +=
save_if_interesting(afl, mem, new_len, fault);
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
show_stats(afl);
afl->syncing_party = 0;
munmap(mem, st.st_size);
@ -1026,6 +1030,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)) {

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.
@ -293,6 +293,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)) {
@ -619,6 +629,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 {

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.
@ -382,8 +383,8 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
? 0
: (cur_time - afl->last_find_time) / 1000),
(runtime -
(afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) /
1000) /
((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) /
1000)) /
1000,
afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000,
afl->trim_time_us / 1000000, afl->fsrv.total_execs,

View File

@ -264,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"
@ -1564,7 +1565,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")) {
@ -1800,6 +1805,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) {
@ -2862,7 +2868,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
u64 execs_before = afl->fsrv.total_execs;
skipped_fuzz = fuzz_one(afl);
afl->queue_cur->total_execs += afl->fsrv.total_execs - execs_before;
#ifdef INTROSPECTION
++afl->queue_cur->stats_selected;
@ -3061,6 +3069,39 @@ stop_fuzzing:
}
if (getenv("AFL_DUMP_QUEUE_ON_EXIT")) {
for (u32 mode = 0; mode < 1; mode++) {
afl->fuzz_mode = mode;
create_alias_table(afl);
fprintf(stderr, "\nQUEUE DUMP MODE: %u\n", mode);
for (u32 k = 0; k < afl->queued_items; ++k) {
struct queue_entry *q = afl->queue_buf[k];
fprintf(stderr,
"item=%u fname=%s len=%u exec_us=%llu total_execs=%llu "
"has_new_cov=%u "
"var_behavior=%u favored=%u fs_redundant=%u disabled=%u "
"bitmap_size=%u tc_ref=%u fuzz_level=%u was_fuzzed=%u "
"cmp=%d fcmp=%d rtn=%d "
"mother=%d found=%u perf_score=%.2f weight=%.2f score=%u\n",
k, q->fname, q->len, q->exec_us, q->total_execs, q->has_new_cov,
q->var_behavior, q->favored, q->fs_redundant, q->disabled,
q->bitmap_size, q->tc_ref, q->fuzz_level, q->was_fuzzed,
q->cmp, q->fcmp, q->rtn,
q->mother == NULL ? -1 : (int)q->mother->id, q->found,
q->perf_score, q->weight, q->score);
}
fprintf(stderr, "\n");
}
}
if (frida_afl_preload) { ck_free(frida_afl_preload); }
fclose(afl->fsrv.plot_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,313 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
}
// 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.

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>
@ -83,6 +83,8 @@ static u32 tcnt, highest; /* tuple content information */
static u32 in_len; /* Input data length */
static u32 score;
static u32 map_size = MAP_SIZE, timed_out = 0;
static bool quiet_mode, /* Hide non-essential messages? */
@ -238,6 +240,13 @@ static void at_exit_handler(void) {
static void analyze_results(afl_forkserver_t *fsrv) {
u32 i;
if (unlikely((score = *(u32 *)((u8 *)fsrv->trace_bits + 1)) > 0)) {
memset(fsrv->trace_bits + 1, 0, 4);
}
for (i = 0; i < map_size; i++) {
if (fsrv->trace_bits[i]) {
@ -269,6 +278,12 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
}
if (unlikely((score = *(u32 *)((u8 *)fsrv->trace_bits + 1)) > 0)) {
memset(fsrv->trace_bits + 1, 0, 4);
}
if (cmin_mode &&
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
@ -1766,12 +1781,20 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Captured %u tuples (map size %u, highest value %u, total values %llu) "
"in '%s'." cRST,
tcnt, fsrv->real_map_size, highest, total, out_file);
if (collect_coverage)
if (collect_coverage) {
OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
"with %llu input files.",
tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
fsrv->total_execs);
} else if (score > 0) {
OKF("Path score is %u (cyclomatic and/or vulnerability scoring).\n",
score);
}
}
if (stdin_file) {

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>

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
764b66b2