From be96253f5293a0446aae8b2f1795119456c0d5d5 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 31 Mar 2023 11:02:27 +0200
Subject: nits
---
src/afl-fuzz-bitmap.c | 10 +++++++---
src/afl-fuzz-one.c | 6 +++---
2 files changed, 10 insertions(+), 6 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index d9c792d1..556bb5d1 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -465,7 +465,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
u8 fn[PATH_MAX];
u8 *queue_fn = "";
- u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0;
+ u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0,
+ need_hash = 1;
s32 fd;
u64 cksum = 0;
@@ -477,6 +478,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
classify_counts(&afl->fsrv);
classified = 1;
+ need_hash = 0;
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@@ -499,6 +501,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
+ if (unlikely(new_bits)) { classified = 1; }
+
}
if (likely(!new_bits)) {
@@ -565,12 +569,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- if (unlikely(!classified && new_bits)) {
+ if (unlikely(need_hash && new_bits)) {
/* due to classify counts we have to recalculate the checksum */
afl->queue_top->exec_cksum =
hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
- classified = 1;
+ need_hash = 0;
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 070669c5..eec5e4b5 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -2071,7 +2071,7 @@ havoc_stage:
afl->stage_short = "havoc";
afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
perf_score / afl->havoc_div) >>
- 7;
+ 8;
} else {
@@ -2080,7 +2080,7 @@ havoc_stage:
snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = "splice";
- afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
@@ -4640,7 +4640,7 @@ pacemaker_fuzzing:
MOpt_globals.splice_stageformat, splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = MOpt_globals.splice_stagenameshort;
- afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 7;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
--
cgit 1.4.1
From 4d02d8e43dd9b413ed819e27bb012e16022d85f6 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 2 Apr 2023 11:52:36 +0200
Subject: fix buffer overflow in pizza mode :(
---
src/afl-fuzz-stats.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 25ebe987..88844322 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -753,20 +753,20 @@ void show_stats_normal(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
@@ -1557,20 +1557,22 @@ void show_stats_pizza(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
--
cgit 1.4.1
From e46e0bce44f0799731f5e7724ba3dfacafd4c41a Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 2 Apr 2023 12:03:45 +0200
Subject: allow pizza mode to be disabled
---
docs/Changelog.md | 3 +++
docs/env_variables.md | 2 +-
include/afl-fuzz.h | 6 ++++--
src/afl-fuzz-state.c | 10 +++++++++-
4 files changed, 17 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 3c06a785..fbf50137 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -9,6 +9,9 @@
- added `AFL_NO_WARN_INSTABILITY`
- added `AFL_FRIDA_STATS_INTERVAL`
- added time_wo_finds to fuzzer_stats
+ - fixed a crash in pizza (1st april easter egg) mode. Sorry for
+ everyone who was affected!
+ - allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
- afl-cc:
- add CFI sanitizer variant to gcc targets
- llvm 16 support (thanks to @devnexen!)
diff --git a/docs/env_variables.md b/docs/env_variables.md
index c9dc1bbd..a6a0ae44 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -581,7 +581,7 @@ checks or alter some of the more exotic semantics of the tool:
constructors in your target, you can set `AFL_EARLY_FORKSERVER`.
Note that this is not a compile time option but a runtime option :-)
- - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to 0
+ - Set `AFL_PIZZA_MODE` to 1 to enable the April 1st stats menu, set to -1
to disable although it is 1st of April.
- If you need a specific interval to update fuzzer_stats file, you can
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 58d02af5..5fd393dd 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -398,8 +398,8 @@ typedef struct afl_env_vars {
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
- afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme,
- afl_ignore_timeouts, afl_no_startup_calibration, afl_no_warn_instability;
+ afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
+ afl_no_startup_calibration, afl_no_warn_instability;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@@ -408,6 +408,8 @@ typedef struct afl_env_vars {
*afl_testcache_entries, *afl_child_kill_signal, *afl_fsrv_kill_signal,
*afl_target_env, *afl_persistent_record, *afl_exit_on_time;
+ s32 afl_pizza_mode;
+
} afl_env_vars_t;
struct afl_pass_stat {
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index f9aa5cfe..46b67def 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -648,7 +648,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
- if (afl->afl_env.afl_pizza_mode) { afl->pizza_is_served = 1; }
+ if (afl->afl_env.afl_pizza_mode > 0) {
+
+ afl->pizza_is_served = 1;
+
+ } else if (afl->afl_env.afl_pizza_mode < 0) {
+
+ OKF("Pizza easter egg mode is now disabled.");
+
+ }
if (issue_detected) { sleep(2); }
--
cgit 1.4.1
From 319b2e8e6f64bd35c5395c8a9e5053f25875a86d Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 2 Apr 2023 12:08:54 +0200
Subject: fix ui layout with slow targets in pizza mode
---
src/afl-fuzz-stats.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 88844322..07157bf7 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -1803,10 +1803,10 @@ void show_stats_pizza(afl_state_t *afl) {
/* Show a warning about slow execution. */
- if (afl->stats_avg_exec < 100) {
+ if (afl->stats_avg_exec < 20) {
sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
- afl->stats_avg_exec < 20 ? "zzzz..." : "Gennarino is at it again!");
+ "zzzz...");
SAYF(bV bSTOP " pizza making speed : " cLRD
"%-22s ",
--
cgit 1.4.1
From 36127fb1970746f53fec44f9394061f57a4e94c3 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Wed, 5 Apr 2023 12:59:20 +0200
Subject: add -z switch
---
docs/Changelog.md | 1 +
include/afl-fuzz.h | 3 ++-
src/afl-fuzz-queue.c | 7 ++++++-
src/afl-fuzz.c | 5 +++++
4 files changed, 14 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index fbf50137..8127e594 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -12,6 +12,7 @@
- fixed a crash in pizza (1st april easter egg) mode. Sorry for
everyone who was affected!
- allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
+ - add -z switch to prefer new coverage findings in seed selection
- afl-cc:
- add CFI sanitizer variant to gcc targets
- llvm 16 support (thanks to @devnexen!)
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 5fd393dd..7ff3315b 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -501,7 +501,8 @@ typedef struct afl_state {
custom_splice_optout, /* Custom mutator no splice buffer */
is_main_node, /* if this is the main node */
is_secondary_node, /* if this is a secondary instance */
- pizza_is_served; /* pizza mode */
+ pizza_is_served, /* pizza mode */
+ prefer_new; /* prefer new queue entries */
u32 stats_update_freq; /* Stats update frequency (execs) */
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 40184645..1cdc8b54 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -74,9 +74,14 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
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 < 1.0)) { weight = 1.0; }
+ if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
+ if (unlikely(afl->prefer_new)) {
+
+ weight *= (2.0 * (q->id / (afl->queued_items - 1)));
+
+ }
return weight;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 3380fd90..0f01360e 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -132,6 +132,7 @@ static void usage(u8 *argv0, int more_help) {
" fast(default), explore, exploit, seek, rare, mmopt, "
"coe, lin\n"
" quad -- see docs/FAQ.md for more information\n"
+ " -z - prefer new coverage findings when fuzzing\n"
" -f file - location read by the fuzzed program (default: stdin "
"or @@)\n"
" -t msec - timeout for each run (auto-scaled, default %u ms). "
@@ -569,6 +570,10 @@ int main(int argc, char **argv_orig, char **envp) {
afl->max_length = atoi(optarg);
break;
+ case 'z':
+ afl->prefer_new = 1;
+ break;
+
case 'Z':
afl->old_seed_selection = 1;
break;
--
cgit 1.4.1
From dba93705a79fb859ce0ede606f79dd4ed203725b Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Wed, 5 Apr 2023 13:07:22 +0200
Subject: better new weighting
---
src/afl-fuzz-queue.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 1cdc8b54..3335e869 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -74,15 +74,17 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
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(afl->prefer_new)) {
- weight *= (2.0 * (q->id / (afl->queued_items - 1)));
+ weight *= (2.0 * ((1 + q->id) / afl->queued_items));
}
+ if (unlikely(weight < 0.1)) { weight = 0.1; }
+ if (unlikely(q->favored)) { weight *= 5; }
+ if (unlikely(!q->was_fuzzed)) { weight *= 2; }
+
return weight;
}
--
cgit 1.4.1
From d67ee1777859b55b1660cef15fc09219fb165140 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Wed, 5 Apr 2023 13:30:06 +0200
Subject: fix
---
src/afl-fuzz.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 0f01360e..c7eb985c 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -557,7 +557,7 @@ int main(int argc, char **argv_orig, char **envp) {
while (
(opt = getopt(
argc, argv,
- "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) >
+ "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YzZ")) >
0) {
switch (opt) {
--
cgit 1.4.1
From f9851dbfbbfbc013172f500099b5f4dc572c508b Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sat, 8 Apr 2023 13:00:57 +0200
Subject: hopefully better -z algorithm
---
src/afl-fuzz-queue.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 3335e869..6fc3c743 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -75,12 +75,6 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
weight *= (log(q->bitmap_size) / avg_bitmap_size);
weight *= (1 + (q->tc_ref / avg_top_size));
- if (unlikely(afl->prefer_new)) {
-
- weight *= (2.0 * ((1 + q->id) / afl->queued_items));
-
- }
-
if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
@@ -155,6 +149,26 @@ void create_alias_table(afl_state_t *afl) {
}
+ if (unlikely(afl->prefer_new) && afl->queued_discovered) {
+
+ double avg_weight = sum / active;
+
+ for (i = n - afl->queued_discovered; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+
+ if (likely(!q->disabled) && q->weight > avg_weight) {
+
+ double prev_weight = q->weight;
+ q->weight *= (2.0 * (i / n));
+ sum += (q->weight - prev_weight);
+
+ }
+
+ }
+
+ }
+
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
--
cgit 1.4.1
From 75d7a094691550afe86519a1d669def0d698b5ce Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sat, 8 Apr 2023 13:48:07 +0200
Subject: show custom mutator name in UI
---
docs/Changelog.md | 1 +
src/afl-fuzz-mutators.c | 16 ++++++++++++----
src/afl-fuzz-one.c | 1 +
src/afl-fuzz-python.c | 13 ++++++++++++-
4 files changed, 26 insertions(+), 5 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 8127e594..40c328ec 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -13,6 +13,7 @@
everyone who was affected!
- allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
- add -z switch to prefer new coverage findings in seed selection
+ - print name of custom mutator in UI
- afl-cc:
- add CFI sanitizer variant to gcc targets
- llvm 16 support (thanks to @devnexen!)
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 9ea46e7a..64dbe7c6 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -179,11 +179,19 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
void *dh;
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
- mutator->name = fn;
- if (memchr(fn, '/', strlen(fn)))
- mutator->name_short = strrchr(fn, '/') + 1;
- else
+ if (memchr(fn, '/', strlen(fn))) {
+
+ mutator->name_short = strdup(strrchr(fn, '/') + 1);
+
+ } else {
+
mutator->name_short = strdup(fn);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
+ mutator->name = fn;
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index eec5e4b5..ee562f96 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1931,6 +1931,7 @@ custom_mutator_stage:
if (el->afl_custom_fuzz) {
afl->current_custom_fuzz = el;
+ afl->stage_name = el->name_short;
if (el->afl_custom_fuzz_count) {
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 2799268b..673e5a6c 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -414,10 +414,21 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
struct custom_mutator *mutator;
mutator = ck_alloc(sizeof(struct custom_mutator));
-
mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
+ if (memchr(module_name, '/', strlen(module_name))) {
+
+ mutator->name_short = strdup(strrchr(module_name, '/') + 1);
+
+ } else {
+
+ mutator->name_short = strdup(module_name);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
py_mutator_t *py_mutator;
py_mutator = init_py_module(afl, module_name);
mutator->data = py_mutator;
--
cgit 1.4.1
From 0eace0212e35e9ed6ba5d084f787402406fa440c Mon Sep 17 00:00:00 2001
From: Jonathan Neuschäfer
Date: Sat, 8 Apr 2023 17:19:09 +0200
Subject: afl-cc: Avoid casts of string literals to char*, in definition of
__AFL_INIT() etc.
With the right -W options, compilers may complain about the cast of
string literals (for PERSIST_SIG and DEFER_SIG) to (char*), and they're
right to do so, because string literals are constant. Since some
projects enable -Werror, this can lead to a broken build with afl-cc.
Let's simply cast to (const char *), which preserves the constness of
the string literal.
---
src/afl-cc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 7b059d40..35b90a5c 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -1171,8 +1171,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] =
"-D__AFL_LOOP(_A)="
- "({ static volatile char *_B __attribute__((used,unused)); "
- " _B = (char*)\"" PERSIST_SIG
+ "({ static volatile const char *_B __attribute__((used,unused)); "
+ " _B = (const char*)\"" PERSIST_SIG
"\"; "
"extern int __afl_connected;"
#ifdef __APPLE__
@@ -1187,8 +1187,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] =
"-D__AFL_INIT()="
- "do { static volatile char *_A __attribute__((used,unused)); "
- " _A = (char*)\"" DEFER_SIG
+ "do { static volatile const char *_A __attribute__((used,unused)); "
+ " _A = (const char*)\"" DEFER_SIG
"\"; "
#ifdef __APPLE__
"__attribute__((visibility(\"default\"))) "
--
cgit 1.4.1
From 0782ed38414bed37168feafc971fd102b8294510 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 9 Apr 2023 10:33:39 +0200
Subject: remove pointer to removed doc
---
src/afl-fuzz.c | 1 -
1 file changed, 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index c7eb985c..a0c322da 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -166,7 +166,6 @@ static void usage(u8 *argv0, int more_help) {
" pacemaker mode (minutes of no new finds). 0 = "
"immediately,\n"
" -1 = immediately and together with normal mutation.\n"
- " See docs/README.MOpt.md\n"
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
" if using QEMU/FRIDA or the fuzzing target is "
--
cgit 1.4.1
From 9e3e1a5512acd44020430f24c9ec1260aeeda285 Mon Sep 17 00:00:00 2001
From: Jonathan Neuschäfer
Date: Mon, 10 Apr 2023 12:22:42 +0200
Subject: afl-cc: Don't offer __AFL_INIT() etc. in GCC/CLANG modes
instrumentation/README.persistent_mode.md documents in the section about
deferred forkserver initialization:
> With the location selected, add this code in the appropriate spot:
>
> ```c
> #ifdef __AFL_HAVE_MANUAL_CONTROL
> __AFL_INIT();
> #endif
> ```
>
> You don't need the #ifdef guards, but including them ensures that the program
> will keep working normally when compiled with a tool other than afl-clang-fast/
> afl-clang-lto/afl-gcc-fast.
>
> Finally, recompile the program with afl-clang-fast/afl-clang-lto/afl-gcc-fast
> (afl-gcc or afl-clang will *not* generate a deferred-initialization binary) -
> and you should be all set!
This strongly implies that you can compile a program that uses __AFL_INIT()
under an `#ifdef __AFL_HAVE_MANUAL_CONTROL` guard with afl-gcc/-clang.
However, this currently fails:
$ cat example.c
#include
int main(void) {
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif
puts("Hello");
}
$ afl-gcc example.c -o example
afl-cc++4.06a by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: GCC-GCC
[!] WARNING: You are using outdated instrumentation, install LLVM and/or gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast instead!
afl-as++4.06a by Michal Zalewski
[+] Instrumented 1 locations (64-bit, non-hardened mode, ratio 100%).
/usr/bin/ld: /tmp/ccuJHcpt.o: in function `main':
/home/jn/dev/fuzz/AFLplusplus/example.c:5: undefined reference to `__afl_manual_init'
collect2: error: ld returned 1 exit status
The issue here is an inconsistency in afl-gcc (i.e. afl-cc operating in GCC mode):
- afl-cc defines __AFL_HAVE_MANUAL_CONTROL and __AFL_INIT unconditionally
- __AFL_INIT relies on __afl_manual_init, which is defined in afl-compiler-rt.o
- afl-cc doesn't link afl-compiler-rt in GCC or CLANG mode
Since afl-gcc/-clang is documented as not supporting deferred forkserver
initialization, this patch omits the definitions of __AFL_HAVE_MANUAL_CONTROL
and related macros in GCC/CLANG mode.
This restores the ability to compile a deferred-forkserver program under
afl-gcc, if it can also be compiled under gcc.
[ In case someone reads this an feels adventurous enough (as I did) to
think about enabling deferred forkserver under afl-gcc: Whether the
deferred forkserver actually works can be verified by placing a
usleep(100000) or similar at the start of main (before __AFL_INIT()),
and watching the execution speed. It doesn't work. ]
---
src/afl-cc.c | 102 +++++++++++++++++++++++++++++++++--------------------------
1 file changed, 57 insertions(+), 45 deletions(-)
(limited to 'src')
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 35b90a5c..7f15ad76 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -1101,37 +1101,45 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!have_c) cc_params[cc_par_cnt++] = "-lrt";
#endif
- cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
- /* When the user tries to use persistent or deferred forkserver modes by
- appending a single line to the program, we want to reliably inject a
- signature into the binary (to be picked up by afl-fuzz) and we want
- to call a function from the runtime .o file. This is unnecessarily
- painful for three reasons:
+ /* As documented in instrumentation/README.persistent_mode.md, deferred
+ forkserver initialization and persistent mode are not available in afl-gcc
+ and afl-clang. */
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
- 1) We need to convince the compiler not to optimize out the signature.
- This is done with __attribute__((used)).
+ cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
- 2) We need to convince the linker, when called with -Wl,--gc-sections,
- not to do the same. This is done by forcing an assignment to a
- 'volatile' pointer.
+ /* When the user tries to use persistent or deferred forkserver modes by
+ appending a single line to the program, we want to reliably inject a
+ signature into the binary (to be picked up by afl-fuzz) and we want
+ to call a function from the runtime .o file. This is unnecessarily
+ painful for three reasons:
- 3) We need to declare __afl_persistent_loop() in the global namespace,
- but doing this within a method in a class is hard - :: and extern "C"
- are forbidden and __attribute__((alias(...))) doesn't work. Hence the
- __asm__ aliasing trick.
+ 1) We need to convince the compiler not to optimize out the signature.
+ This is done with __attribute__((used)).
- */
+ 2) We need to convince the linker, when called with -Wl,--gc-sections,
+ not to do the same. This is done by forcing an assignment to a
+ 'volatile' pointer.
- cc_params[cc_par_cnt++] =
- "-D__AFL_FUZZ_INIT()="
- "int __afl_sharedmem_fuzzing = 1;"
- "extern unsigned int *__afl_fuzz_len;"
- "extern unsigned char *__afl_fuzz_ptr;"
- "unsigned char __afl_fuzz_alt[1048576];"
- "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+ 3) We need to declare __afl_persistent_loop() in the global namespace,
+ but doing this within a method in a class is hard - :: and extern "C"
+ are forbidden and __attribute__((alias(...))) doesn't work. Hence the
+ __asm__ aliasing trick.
+
+ */
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_FUZZ_INIT()="
+ "int __afl_sharedmem_fuzzing = 1;"
+ "extern unsigned int *__afl_fuzz_len;"
+ "extern unsigned char *__afl_fuzz_ptr;"
+ "unsigned char __afl_fuzz_alt[1048576];"
+ "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+
+ }
if (plusplus_mode) {
@@ -1169,35 +1177,39 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff "
"? 0 : *__afl_fuzz_len)";
- cc_params[cc_par_cnt++] =
- "-D__AFL_LOOP(_A)="
- "({ static volatile const char *_B __attribute__((used,unused)); "
- " _B = (const char*)\"" PERSIST_SIG
- "\"; "
- "extern int __afl_connected;"
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_LOOP(_A)="
+ "({ static volatile const char *_B __attribute__((used,unused)); "
+ " _B = (const char*)\"" PERSIST_SIG
+ "\"; "
+ "extern int __afl_connected;"
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
- // if afl is connected, we run _A times, else once.
- "_L(__afl_connected ? _A : 1); })";
+ // if afl is connected, we run _A times, else once.
+ "_L(__afl_connected ? _A : 1); })";
- cc_params[cc_par_cnt++] =
- "-D__AFL_INIT()="
- "do { static volatile const char *_A __attribute__((used,unused)); "
- " _A = (const char*)\"" DEFER_SIG
- "\"; "
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_INIT()="
+ "do { static volatile const char *_A __attribute__((used,unused)); "
+ " _A = (const char*)\"" DEFER_SIG
+ "\"; "
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"___afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"___afl_manual_init\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"__afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
- "_I(); } while (0)";
+ "_I(); } while (0)";
+
+ }
if (x_set) {
--
cgit 1.4.1
From 6cc8d607fb24e060591ece4b42d83fc06de68fc6 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 13 Apr 2023 11:44:39 +0200
Subject: remove -z option, use -p mmopt instead
---
GNUmakefile | 2 +-
docs/Changelog.md | 2 +-
include/afl-fuzz.h | 3 +--
instrumentation/SanitizerCoverageLTO.so.cc | 2 +-
instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +-
src/afl-fuzz-queue.c | 14 ++++----------
src/afl-fuzz.c | 7 +------
7 files changed, 10 insertions(+), 22 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile b/GNUmakefile
index 208e965b..85f164f5 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -546,7 +546,7 @@ ifndef AFL_NO_X86
test_build: afl-cc afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
@unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c $(LDFLAGS) -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
- - ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -o .test-instr0 ./test-instr < /dev/null
+ -ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -q -m none -o .test-instr0 ./test-instr < /dev/null
-echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation of afl-cc does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 736deb30..501300b1 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -12,7 +12,7 @@
- fixed a crash in pizza (1st april easter egg) mode. Sorry for
everyone who was affected!
- allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
- - add -z switch to prefer new coverage findings in seed selection
+ - option `-p mmopt` now also selects new queue items more often
- print name of custom mutator in UI
- afl-cc:
- add CFI sanitizer variant to gcc targets
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 7ff3315b..5fd393dd 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -501,8 +501,7 @@ typedef struct afl_state {
custom_splice_optout, /* Custom mutator no splice buffer */
is_main_node, /* if this is the main node */
is_secondary_node, /* if this is a secondary instance */
- pizza_is_served, /* pizza mode */
- prefer_new; /* prefer new queue entries */
+ pizza_is_served; /* pizza mode */
u32 stats_update_freq; /* Stats update frequency (execs) */
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 5603c455..e41f19b6 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -18,7 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#if LLVM_VERSION_MAJOR < 17
-#include "llvm/ADT/Triple.h"
+ #include "llvm/ADT/Triple.h"
#endif
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/PostDominators.h"
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 5f23698b..85b1ddd5 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -14,7 +14,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#if LLVM_VERSION_MAJOR < 17
-#include "llvm/ADT/Triple.h"
+ #include "llvm/ADT/Triple.h"
#endif
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/PostDominators.h"
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 6fc3c743..8ad7cd97 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -149,21 +149,15 @@ void create_alias_table(afl_state_t *afl) {
}
- if (unlikely(afl->prefer_new) && afl->queued_discovered) {
+ if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) {
- double avg_weight = sum / active;
+ u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered;
- for (i = n - afl->queued_discovered; i < n; i++) {
+ for (i = n - cnt; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
- if (likely(!q->disabled) && q->weight > avg_weight) {
-
- double prev_weight = q->weight;
- q->weight *= (2.0 * (i / n));
- sum += (q->weight - prev_weight);
-
- }
+ if (likely(!q->disabled)) { q->weight *= 2.0; }
}
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index a0c322da..5ba54d0b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -132,7 +132,6 @@ static void usage(u8 *argv0, int more_help) {
" fast(default), explore, exploit, seek, rare, mmopt, "
"coe, lin\n"
" quad -- see docs/FAQ.md for more information\n"
- " -z - prefer new coverage findings when fuzzing\n"
" -f file - location read by the fuzzed program (default: stdin "
"or @@)\n"
" -t msec - timeout for each run (auto-scaled, default %u ms). "
@@ -556,7 +555,7 @@ int main(int argc, char **argv_orig, char **envp) {
while (
(opt = getopt(
argc, argv,
- "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YzZ")) >
+ "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) >
0) {
switch (opt) {
@@ -569,10 +568,6 @@ int main(int argc, char **argv_orig, char **envp) {
afl->max_length = atoi(optarg);
break;
- case 'z':
- afl->prefer_new = 1;
- break;
-
case 'Z':
afl->old_seed_selection = 1;
break;
--
cgit 1.4.1
From f756734ad2782c3ed56feadb4b7b23fc82a7a968 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 13 Apr 2023 12:07:27 +0200
Subject: fix attempt at post_process implementation
---
docs/Changelog.md | 1 +
docs/custom_mutators.md | 9 +++++++--
include/afl-fuzz.h | 9 +++++++--
src/afl-fuzz-python.c | 49 +++++++++----------------------------------------
src/afl-fuzz-run.c | 7 ++++++-
5 files changed, 30 insertions(+), 45 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 501300b1..9436fc9f 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -13,6 +13,7 @@
everyone who was affected!
- allow pizza mode to be disabled when AFL_PIZZA_MODE is set to -1
- option `-p mmopt` now also selects new queue items more often
+ - fix bug in post_process custom mutator implementation
- print name of custom mutator in UI
- afl-cc:
- add CFI sanitizer variant to gcc targets
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 82131c92..a1de479e 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -118,7 +118,7 @@ def deinit(): # optional for Python
### Custom Mutation
-- `init`:
+- `init` (optional in Python):
This method is called when AFL++ starts up and is used to seed RNG and set
up buffers and state.
@@ -184,6 +184,11 @@ def deinit(): # optional for Python
to the target, e.g. if it is too short, too corrupted, etc. If so,
return a NULL buffer and zero length (or a 0 length string in Python).
+ NOTE: Do not make any random changes to the data in this function!
+
+ PERFORMANCE for C/C++: If possible make the changes in-place (so modify
+ the `*data` directly, and return it as `*outbuf = data`.
+
- `fuzz_send` (optional):
This method can be used if you want to send data to the target yourself,
@@ -202,7 +207,7 @@ def deinit(): # optional for Python
discovered if compiled with INTROSPECTION. The custom mutator can then
return a string (const char *) that reports the exact mutations used.
-- `deinit`:
+- `deinit` (optional in Python):
The last method to be called, deinitializing the state.
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 5fd393dd..8b6502b4 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -885,14 +885,19 @@ struct custom_mutator {
* A post-processing function to use right before AFL writes the test case to
* disk in order to execute the target.
*
- * (Optional) If this functionality is not needed, simply don't define this
+ * NOTE: Do not do any random changes to the data in this function!
+ *
+ * PERFORMANCE: If you can modify the data in-place you will have a better
+ * performance. Modify *data and set `*out_buf = data`.
+ *
+ * (Optional) If this functionality is not needed, simply do not define this
* function.
*
* @param[in] data pointer returned in afl_custom_init by this custom mutator
* @param[in] buf Buffer containing the test case to be executed
* @param[in] buf_size Size of the test case
* @param[out] out_buf Pointer to the buffer storing the test case after
- * processing. External library should allocate memory for out_buf.
+ * processing. The external library should allocate memory for out_buf.
* It can chose to alter buf in-place, if the space is large enough.
* @return Size of the output buffer.
*/
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 673e5a6c..7dad0770 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -219,11 +219,14 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (py_module != NULL) {
- u8 py_notrim = 0, py_idx;
- /* init, required */
+ u8 py_notrim = 0;
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
- if (!py_functions[PY_FUNC_INIT])
- FATAL("init function not found in python module");
+ if (!py_functions[PY_FUNC_INIT]) {
+
+ WARNF("init function not found in python module");
+
+ }
+
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
@@ -231,12 +234,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
- if (!py_functions[PY_FUNC_FUZZ]) {
-
- WARNF("fuzz function not found in python module");
-
- }
-
py_functions[PY_FUNC_POST_PROCESS] =
PyObject_GetAttrString(py_module, "post_process");
py_functions[PY_FUNC_INIT_TRIM] =
@@ -263,36 +260,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (!py_functions[PY_FUNC_DEINIT])
WARNF("deinit function not found in python module");
- for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
-
- if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
-
- if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
-
- // Implementing the trim API is optional for now
- if (PyErr_Occurred()) { PyErr_Print(); }
- py_notrim = 1;
-
- } else if (py_idx >= PY_OPTIONAL) {
-
- // Only _init and _deinit are not optional currently
-
- if (PyErr_Occurred()) { PyErr_Print(); }
-
- } else {
-
- fprintf(stderr,
- "Cannot find/call function with index %d in external "
- "Python module.\n",
- py_idx);
- return NULL;
-
- }
-
- }
-
- }
-
if (py_notrim) {
py_functions[PY_FUNC_INIT_TRIM] = NULL;
@@ -345,6 +312,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
(void)afl;
+ if (py_mutator->py_functions[PY_FUNC_INIT] == NULL) { return; }
+
PyObject *py_args, *py_value;
/* Provide the init function a seed for the Python RNG */
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index f5425011..26e8549d 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -133,7 +133,12 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
}
- if (new_mem != *mem) { *mem = new_mem; }
+ if (new_mem != *mem && new_mem != NULL && new_size > 0) {
+
+ *mem = afl_realloc((void **)mem, new_size);
+ memmove(*mem, new_mem, new_size);
+
+ }
if (unlikely(afl->custom_mutators_count)) {
--
cgit 1.4.1
From eefd98f3741b5feca32c75b34a8d7b33e34044d0 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Fri, 14 Apr 2023 02:25:33 +0200
Subject: add Nyx support in various tools (like afl-cmin)
---
afl-cmin | 14 ++++++--
include/common.h | 6 ++++
include/forkserver.h | 3 ++
src/afl-analyze.c | 64 ++++++++++++++++++++++++++++++---
src/afl-common.c | 31 ++++++++++++++++
src/afl-forkserver.c | 65 ++++++++++++++++++++++++++++++++++
src/afl-fuzz.c | 63 ---------------------------------
src/afl-showmap.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++--
src/afl-tmin.c | 59 ++++++++++++++++++++++++++++++-
9 files changed, 330 insertions(+), 74 deletions(-)
(limited to 'src')
diff --git a/afl-cmin b/afl-cmin
index 15b61f89..12791584 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -109,6 +109,7 @@ function usage() {
" -O - use binary-only instrumentation (FRIDA mode)\n" \
" -Q - use binary-only instrumentation (QEMU mode)\n" \
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
+" -X - use Nyx mode\n" \
"\n" \
"Minimization settings:\n" \
" -A - allow crashes and timeouts (not recommended)\n" \
@@ -156,7 +157,7 @@ BEGIN {
# process options
Opterr = 1 # default is to diagnose
Optind = 1 # skip ARGV[0]
- while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQU?")) != -1) {
+ while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUX?")) != -1) {
if (_go_c == "i") {
if (!Optarg) usage()
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -217,6 +218,12 @@ BEGIN {
extra_par = extra_par " -U"
unicorn_mode = 1
continue
+ } else
+ if (_go_c == "X") {
+ if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
+ extra_par = extra_par " -X"
+ nyx_mode = 1
+ continue
} else
if (_go_c == "?") {
exit 1
@@ -291,7 +298,8 @@ BEGIN {
exit 1
}
- if (target_bin && !exists_and_is_executable(target_bin)) {
+
+ if (!nyx_mode && target_bin && !exists_and_is_executable(target_bin)) {
"command -v "target_bin" 2>/dev/null" | getline tnew
if (!tnew || !exists_and_is_executable(tnew)) {
@@ -311,7 +319,7 @@ BEGIN {
}
}
- if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
+ if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode && !nyx_mode) {
if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
exit 1
diff --git a/include/common.h b/include/common.h
index 0958b035..279a5f47 100644
--- a/include/common.h
+++ b/include/common.h
@@ -147,5 +147,11 @@ s32 create_file(u8 *fn);
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
size_t needlelen);
+#ifdef __linux__
+/* Nyx helper functions to create and remove tmp workdirs */
+char* create_nyx_tmp_workdir(void);
+void remove_nyx_tmp_workdir(char* nyx_out_dir_path);
+#endif
+
#endif
diff --git a/include/forkserver.h b/include/forkserver.h
index 50898a08..273a9255 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -75,6 +75,9 @@ typedef struct {
} nyx_plugin_handler_t;
+/* Imports helper functions to enable Nyx mode (Linux only )*/
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
+
#endif
typedef struct afl_forkserver {
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 548956d8..0bdadfdc 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -121,9 +121,9 @@ static void kill_child() {
}
-static void classify_counts(u8 *mem) {
+static void classify_counts(u8 *mem, u32 mem_size) {
- u32 i = map_size;
+ u32 i = mem_size;
if (edges_only) {
@@ -222,7 +222,7 @@ static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
}
- classify_counts(fsrv.trace_bits);
+ classify_counts(fsrv.trace_bits, fsrv.map_size);
total_execs++;
if (stop_soon) {
@@ -768,6 +768,7 @@ static void usage(u8 *argv0) {
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
"mode)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -814,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init(&fsrv);
- while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXh")) > 0) {
switch (opt) {
@@ -965,6 +966,22 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv.mem_limit = mem_limit;
break;
+
+ #ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv.nyx_mode = 1;
+ fsrv.nyx_parent = true;
+ fsrv.nyx_standalone = true;
+
+ break;
+ #else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+ #endif
case 'h':
usage(argv[0]);
@@ -997,7 +1014,17 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(argv);
+#ifdef __linux__
+ if(!fsrv.nyx_mode){
+ fsrv.target_path = find_binary(argv[optind]);
+ }
+ else{
+ fsrv.target_path = ck_strdup(argv[optind]);
+ }
+#else
fsrv.target_path = find_binary(argv[optind]);
+#endif
+
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
signal(SIGALRM, kill_child);
@@ -1020,6 +1047,23 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
+#ifdef __linux__
+ } else if (fsrv.nyx_mode) {
+
+ fsrv.nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv.nyx_handlers == NULL) {
+ FATAL("failed to initialize libnyx.so...");
+ }
+
+ fsrv.out_dir_path = create_nyx_tmp_workdir();
+ fsrv.nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1045,7 +1089,13 @@ int main(int argc, char **argv_orig, char **envp) {
&fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
read_initial_file();
+#ifdef __linux__
+ if(!fsrv.nyx_mode){
+ (void)check_binary_signatures(fsrv.target_path);
+ }
+#else
(void)check_binary_signatures(fsrv.target_path);
+#endif
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
mem_limit, exec_tmout, edges_only ? ", edges only" : "");
@@ -1069,6 +1119,12 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
+#ifdef __linux__
+ if (fsrv.nyx_mode) {
+ remove_nyx_tmp_workdir(fsrv.out_dir_path);
+ }
+#endif
+
afl_shm_deinit(&shm);
afl_fsrv_deinit(&fsrv);
if (fsrv.target_path) { ck_free(fsrv.target_path); }
diff --git a/src/afl-common.c b/src/afl-common.c
index 86226c9f..7dbf7129 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -1359,3 +1359,34 @@ s32 create_file(u8 *fn) {
}
+#ifdef __linux__
+
+/* Nyx requires a tmp workdir to access specific files (such as mmapped files,
+ * etc.). This helper function basically creates both a path to a tmp workdir
+ * and the workdir itself. If the environment variable TMPDIR is set, we use
+ * that as the base directory, otherwise we use /tmp. */
+char* create_nyx_tmp_workdir(void) {
+
+ char *tmpdir = getenv("TMPDIR");
+
+ if (!tmpdir) { tmpdir = "/tmp"; }
+
+ char* nyx_out_dir_path = alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
+
+ if (mkdir(nyx_out_dir_path, 0700)) {
+ PFATAL("Unable to create nyx workdir");
+ }
+
+ return nyx_out_dir_path;
+}
+
+/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
+void remove_nyx_tmp_workdir(char* nyx_out_dir_path) {
+ /* Fix me: This is not recursive, so it will always fail. Use a libnyx helper function instead
+ * to remove the workdir safely (and not risking to wipe the whole filesystem accidentally). */
+ //if (rmdir(nyx_out_dir_path)) {
+ // PFATAL("Unable to remove nyx workdir");
+ //}
+ free(nyx_out_dir_path);
+}
+#endif
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 5aa4c2ff..95328aa2 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -49,6 +49,71 @@
#include
#include
+#ifdef __linux__
+#include
+
+/* function to load nyx_helper function from libnyx.so */
+
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
+
+ void *handle;
+ nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
+
+ ACTF("Trying to load libnyx.so plugin...");
+ handle = dlopen((char *)libnyx_binary, RTLD_NOW);
+ if (!handle) { goto fail; }
+
+ plugin->nyx_new = dlsym(handle, "nyx_new");
+ if (plugin->nyx_new == NULL) { goto fail; }
+
+ plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
+ if (plugin->nyx_new_parent == NULL) { goto fail; }
+
+ plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
+ if (plugin->nyx_new_child == NULL) { goto fail; }
+
+ plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
+ if (plugin->nyx_shutdown == NULL) { goto fail; }
+
+ plugin->nyx_option_set_reload_mode =
+ dlsym(handle, "nyx_option_set_reload_mode");
+ if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
+
+ plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
+ if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
+
+ plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
+ if (plugin->nyx_option_apply == NULL) { goto fail; }
+
+ plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
+ if (plugin->nyx_set_afl_input == NULL) { goto fail; }
+
+ plugin->nyx_exec = dlsym(handle, "nyx_exec");
+ if (plugin->nyx_exec == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
+ if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer_size =
+ dlsym(handle, "nyx_get_bitmap_buffer_size");
+ if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
+ if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+
+ OKF("libnyx plugin is ready!");
+ return plugin;
+
+fail:
+
+ FATAL("failed to load libnyx: %s\n", dlerror());
+ free(plugin);
+ return NULL;
+
+}
+
+#endif
+
/**
* The correct fds for reading and writing pipes
*/
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index a0c322da..8b4fe1e5 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -436,69 +436,6 @@ static void fasan_check_afl_preload(char *afl_preload) {
}
- #ifdef __linux__
- #include
-
-nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
-
- void *handle;
- nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
-
- ACTF("Trying to load libnyx.so plugin...");
- handle = dlopen((char *)libnyx_binary, RTLD_NOW);
- if (!handle) { goto fail; }
-
- plugin->nyx_new = dlsym(handle, "nyx_new");
- if (plugin->nyx_new == NULL) { goto fail; }
-
- plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
- if (plugin->nyx_new_parent == NULL) { goto fail; }
-
- plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
- if (plugin->nyx_new_child == NULL) { goto fail; }
-
- plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
- if (plugin->nyx_shutdown == NULL) { goto fail; }
-
- plugin->nyx_option_set_reload_mode =
- dlsym(handle, "nyx_option_set_reload_mode");
- if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
-
- plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
- if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
-
- plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
- if (plugin->nyx_option_apply == NULL) { goto fail; }
-
- plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
- if (plugin->nyx_set_afl_input == NULL) { goto fail; }
-
- plugin->nyx_exec = dlsym(handle, "nyx_exec");
- if (plugin->nyx_exec == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
- if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer_size =
- dlsym(handle, "nyx_get_bitmap_buffer_size");
- if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
-
- plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
- if (plugin->nyx_get_aux_string == NULL) { goto fail; }
-
- OKF("libnyx plugin is ready!");
- return plugin;
-
-fail:
-
- FATAL("failed to load libnyx: %s\n", dlerror());
- free(plugin);
- return NULL;
-
-}
-
- #endif
-
/* Main entry point */
int main(int argc, char **argv_orig, char **envp) {
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 29abeb13..3ddebaad 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -434,6 +434,20 @@ static u32 read_file(u8 *in_file) {
}
+#ifdef __linux__
+/* Execute the target application with an empty input (in Nyx mode). */
+static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
+
+ afl_fsrv_write_to_testcase(fsrv, NULL, 0);
+
+ if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
+ FSRV_RUN_ERROR) {
+
+ FATAL("Error running target in Nyx mode");
+ }
+}
+#endif
+
/* Execute target application. */
static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
@@ -797,6 +811,7 @@ static void usage(u8 *argv0) {
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
"Other settings:\n"
@@ -875,7 +890,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshX")) > 0) {
switch (opt) {
@@ -1063,6 +1078,22 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ #ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+ #else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+ #endif
+
case 'b':
/* Secret undocumented mode. Writes output in raw binary format
@@ -1134,7 +1165,17 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if(!fsrv->nyx_mode){
+ fsrv->target_path = find_binary(argv[optind]);
+ }
+ else{
+ fsrv->target_path = ck_strdup(argv[optind]);
+ }
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
if (!quiet_mode) {
@@ -1190,6 +1231,26 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+ } else if (fsrv->nyx_mode) {
+
+ use_argv = ck_alloc(sizeof(char *) * (1));
+ use_argv[0] = argv[0];
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv->out_dir_path = create_nyx_tmp_workdir();
+ fsrv->nyx_bind_cpu_id = 0;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1226,7 +1287,13 @@ int main(int argc, char **argv_orig, char **envp) {
}
+#ifdef __linux__
+ if(!fsrv->nyx_mode && in_dir){
+ (void)check_binary_signatures(fsrv->target_path);
+ }
+#else
if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+#endif
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
@@ -1247,7 +1314,13 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz = map + sizeof(u32);
configure_afl_kill_signals(
- fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
+ fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode
+ #ifdef __linux__
+ || fsrv->nyx_mode
+ #endif
+ )
+ ? SIGKILL
+ : SIGTERM);
if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
@@ -1370,6 +1443,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (execute_testcases(in_dir) == 0) {
+#ifdef __linux__
+ if (fsrv->nyx_mode) {
+ remove_nyx_tmp_workdir(fsrv->out_dir_path);
+ fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+ }
+#endif
FATAL("could not read input testcases from %s", in_dir);
}
@@ -1390,7 +1469,15 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
- showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+ if(!fsrv->nyx_mode){
+#endif
+ showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+ } else {
+ showmap_run_target_nyx_mode(fsrv);
+ }
+#endif
tcnt = write_results_to_file(fsrv, out_file);
if (!quiet_mode) {
@@ -1441,6 +1528,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->target_path) { ck_free(fsrv->target_path); }
+#ifdef __linux__
+ if (fsrv->nyx_mode) {
+ remove_nyx_tmp_workdir(fsrv->out_dir_path);
+ }
+#endif
+
afl_fsrv_deinit(fsrv);
if (stdin_file) { ck_free(stdin_file); }
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index c0087f5f..942525d4 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -789,6 +789,7 @@ static void usage(u8 *argv0) {
"mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -845,7 +846,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:xeAOQUWHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXHh")) > 0) {
switch (opt) {
@@ -1003,6 +1004,22 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ #ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+ #else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+ #endif
+
case 'H': /* Hang Mode */
/* Minimizes a testcase to the minimum that still times out */
@@ -1068,7 +1085,17 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if(!fsrv->nyx_mode){
+ fsrv->target_path = find_binary(argv[optind]);
+ }
+ else{
+ fsrv->target_path = ck_strdup(argv[optind]);
+ }
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
signal(SIGALRM, kill_child);
@@ -1092,6 +1119,23 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+ } else if (fsrv->nyx_mode) {
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+ FATAL("failed to initialize libnyx.so...");
+ }
+
+ fsrv->out_dir_path = create_nyx_tmp_workdir();
+ fsrv->nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1161,7 +1205,14 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz = map + sizeof(u32);
read_initial_file();
+
+#ifdef __linux__
+ if(!fsrv->nyx_mode){
+ (void)check_binary_signatures(fsrv->target_path);
+ }
+#else
(void)check_binary_signatures(fsrv->target_path);
+#endif
if (!fsrv->qemu_mode && !unicorn_mode) {
@@ -1265,6 +1316,12 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
+#ifdef __linux__
+ if (fsrv->nyx_mode) {
+ remove_nyx_tmp_workdir(fsrv->out_dir_path);
+ }
+#endif
+
remove_shm = 0;
afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
--
cgit 1.4.1
From a96cdc649fbdf2ae6f40d4e966812c46083032a2 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Fri, 14 Apr 2023 05:59:12 +0200
Subject: switch to latest libnyx API
---
include/forkserver.h | 25 ++++++++++++++++--------
src/afl-forkserver.c | 54 ++++++++++++++++++++++++++++++++++------------------
2 files changed, 52 insertions(+), 27 deletions(-)
(limited to 'src')
diff --git a/include/forkserver.h b/include/forkserver.h
index 273a9255..7cbad8c8 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -51,16 +51,23 @@ typedef enum NyxReturnValue {
} NyxReturnValue;
+typedef enum NyxProcessRole {
+ StandAlone,
+ Parent,
+ Child,
+} NyxProcessRole;
+
typedef struct {
- void *(*nyx_new)(const char *sharedir, const char *workdir, uint32_t cpu_id,
- uint32_t input_buffer_size,
- bool input_buffer_write_protection);
- void *(*nyx_new_parent)(const char *sharedir, const char *workdir,
- uint32_t cpu_id, uint32_t input_buffer_size,
- bool input_buffer_write_protection);
- void *(*nyx_new_child)(const char *sharedir, const char *workdir,
- uint32_t cpu_id, uint32_t worker_id);
+ void *(*nyx_config_load)(const char *sharedir);
+ void (*nyx_config_set_workdir_path)(void *config, const char *workdir);
+ void (*nyx_config_set_input_buffer_size)(void *config, uint32_t input_buffer_size);
+ void (*nyx_config_set_input_buffer_write_protection)(void *config, bool input_buffer_write_protection);
+ void (*nyx_config_set_hprintf_fd)(void *config, int32_t hprintf_fd);
+ void (*nyx_config_set_process_role)(void *config, enum NyxProcessRole role);
+ void (*nyx_config_set_reuse_snapshot_path)(void *config, const char *reuse_snapshot_path);
+
+ void *(*nyx_new)(void *config, uint32_t worker_id);
void (*nyx_shutdown)(void *qemu_process);
void (*nyx_option_set_reload_mode)(void *qemu_process, bool enable);
void (*nyx_option_set_timeout)(void *qemu_process, uint8_t timeout_sec,
@@ -73,6 +80,8 @@ typedef struct {
uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer,
uint32_t size);
+ bool (*nyx_remove_work_dir)(const char *workdir);
+
} nyx_plugin_handler_t;
/* Imports helper functions to enable Nyx mode (Linux only )*/
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 95328aa2..33c46b8c 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -63,14 +63,29 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
handle = dlopen((char *)libnyx_binary, RTLD_NOW);
if (!handle) { goto fail; }
- plugin->nyx_new = dlsym(handle, "nyx_new");
- if (plugin->nyx_new == NULL) { goto fail; }
+ plugin->nyx_config_load = dlsym(handle, "nyx_config_load");
+ if (plugin->nyx_config_load == NULL) { goto fail; }
+
+ plugin->nyx_config_set_workdir_path = dlsym(handle, "nyx_config_set_workdir_path");
+ if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_size = dlsym(handle, "nyx_config_set_input_buffer_size");
+ if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_write_protection = dlsym(handle, "nyx_config_set_input_buffer_write_protection");
+ if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { goto fail; }
- plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
- if (plugin->nyx_new_parent == NULL) { goto fail; }
+ plugin->nyx_config_set_hprintf_fd = dlsym(handle, "nyx_config_set_hprintf_fd");
+ if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; }
- plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
- if (plugin->nyx_new_child == NULL) { goto fail; }
+ plugin->nyx_config_set_process_role = dlsym(handle, "nyx_config_set_process_role");
+ if (plugin->nyx_config_set_process_role == NULL) { goto fail; }
+
+ plugin->nyx_config_set_reuse_snapshot_path = dlsym(handle, "nyx_config_set_reuse_snapshot_path");
+ if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; }
+
+ plugin->nyx_new = dlsym(handle, "nyx_new");
+ if (plugin->nyx_new == NULL) { goto fail; }
plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
if (plugin->nyx_shutdown == NULL) { goto fail; }
@@ -101,6 +116,10 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+ plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
+ if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
+
+
OKF("libnyx plugin is ready!");
return plugin;
@@ -474,27 +493,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
- if (fsrv->nyx_standalone) {
+ void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+ fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, x);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config, true);
+ if (fsrv->nyx_standalone) {
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
} else {
-
if (fsrv->nyx_parent) {
-
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_parent(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
-
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent);
} else {
-
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_child(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, fsrv->nyx_id);
-
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child);
}
-
}
+ fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
+
ck_free(x);
if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
--
cgit 1.4.1
From 4f6ec6cb081bfee7a6e1d6ac211b33a820ec2f71 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Fri, 14 Apr 2023 06:21:43 +0200
Subject: add NYX_REUSE_SNAPSHOT env-var option
---
src/afl-forkserver.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
(limited to 'src')
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 33c46b8c..7eb2155e 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -509,6 +509,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
}
+ if (getenv("NYX_REUSE_SNAPSHOT") != NULL){
+
+ if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+ FATAL("NYX_REUSE_SNAPSHOT path does not exist");
+ }
+
+ /* stupid sanity check to avoid passing an empty or invalid snapshot directory */
+ char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+ if (access(snapshot_file_path, R_OK) == -1) {
+ FATAL("NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+ }
+ free(snapshot_file_path);
+
+ fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+ }
+
fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
ck_free(x);
--
cgit 1.4.1
From c34c3e2f5f70d9a445bdbbb2e2f0937e98358607 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Fri, 14 Apr 2023 06:24:46 +0200
Subject: add some sanity checks and remove duplicate nyx_shutdown calls
---
src/afl-forkserver.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
(limited to 'src')
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 7eb2155e..ae2adc3d 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -555,14 +555,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
FATAL("Error: Nyx abort occured...");
break;
case IoError:
FATAL("Error: QEMU-Nyx has died...");
break;
case Error:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
FATAL("Error: Nyx runtime error has occured...");
break;
default:
@@ -1293,8 +1291,14 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
#ifdef __linux__
if (fsrv->nyx_mode) {
- free(fsrv->nyx_aux_string);
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+ if (fsrv->nyx_aux_string){
+ free(fsrv->nyx_aux_string);
+ }
+
+ /* check if we actually got a valid nyx runner */
+ if (fsrv->nyx_runner) {
+ fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+ }
}
@@ -1474,7 +1478,6 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
break;
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
FATAL("Error: Nyx abort occured...");
case IoError:
if (*stop_soon_p) {
--
cgit 1.4.1
From 8f6d9d66ef96286661dab876d9b57a36982b2a4d Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sat, 15 Apr 2023 08:33:50 +0200
Subject: fix post_process
---
src/afl-fuzz-run.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 26e8549d..4d56f3a7 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -135,8 +135,11 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
if (new_mem != *mem && new_mem != NULL && new_size > 0) {
- *mem = afl_realloc((void **)mem, new_size);
- memmove(*mem, new_mem, new_size);
+ u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+ *mem = new_buf;
+ memcpy(*mem, new_mem, new_size);
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
}
--
cgit 1.4.1
From 47833bcf9e4b642e090f7cc0da25d1ed99688e5e Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Sun, 16 Apr 2023 04:28:19 +0200
Subject: fix remove_nyx_tmp_workdir function
---
include/common.h | 2 +-
src/afl-common.c | 24 +++++++++++++++++-------
2 files changed, 18 insertions(+), 8 deletions(-)
(limited to 'src')
diff --git a/include/common.h b/include/common.h
index 279a5f47..e03566de 100644
--- a/include/common.h
+++ b/include/common.h
@@ -150,7 +150,7 @@ void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
#ifdef __linux__
/* Nyx helper functions to create and remove tmp workdirs */
char* create_nyx_tmp_workdir(void);
-void remove_nyx_tmp_workdir(char* nyx_out_dir_path);
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path);
#endif
#endif
diff --git a/src/afl-common.c b/src/afl-common.c
index 7dbf7129..fe0db94d 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -1381,12 +1381,22 @@ char* create_nyx_tmp_workdir(void) {
}
/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
-void remove_nyx_tmp_workdir(char* nyx_out_dir_path) {
- /* Fix me: This is not recursive, so it will always fail. Use a libnyx helper function instead
- * to remove the workdir safely (and not risking to wipe the whole filesystem accidentally). */
- //if (rmdir(nyx_out_dir_path)) {
- // PFATAL("Unable to remove nyx workdir");
- //}
- free(nyx_out_dir_path);
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) {
+ char* workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
+
+ if (access(workdir_path, R_OK) == 0) {
+ if(fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+ WARNF("Unable to remove nyx workdir (%s)", workdir_path);
+ }
+ }
+
+ if (access(nyx_out_dir_path, R_OK) == 0) {
+ if (rmdir(nyx_out_dir_path)) {
+ WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
+ }
+ }
+
+ ck_free(workdir_path);
+ ck_free(nyx_out_dir_path);
}
#endif
--
cgit 1.4.1
From 059d470e8dd0a5339daefe0842f4ad5014717838 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Sun, 16 Apr 2023 04:42:09 +0200
Subject: improved Nyx tmp dir handling (additional sanity checks)
---
include/forkserver.h | 2 ++
src/afl-analyze.c | 7 +---
src/afl-forkserver.c | 97 +++++++++++++++++++++++++++++++++++-----------------
src/afl-fuzz.c | 8 -----
src/afl-showmap.c | 13 +------
src/afl-tmin.c | 7 +---
6 files changed, 71 insertions(+), 63 deletions(-)
(limited to 'src')
diff --git a/include/forkserver.h b/include/forkserver.h
index 7cbad8c8..ba280d38 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -190,6 +190,8 @@ typedef struct afl_forkserver {
u32 nyx_id; /* nyx runner id (0 -> master) */
u32 nyx_bind_cpu_id; /* nyx runner cpu id */
char *nyx_aux_string;
+ bool nyx_use_tmp_workdir;
+ char *nyx_tmp_workdir_path;
#endif
} afl_forkserver_t;
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 0bdadfdc..0a4e7fb5 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -1058,7 +1058,7 @@ int main(int argc, char **argv_orig, char **envp) {
FATAL("failed to initialize libnyx.so...");
}
- fsrv.out_dir_path = create_nyx_tmp_workdir();
+ fsrv.nyx_use_tmp_workdir = true;
fsrv.nyx_bind_cpu_id = 0;
use_argv = argv + optind;
@@ -1119,11 +1119,6 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
-#ifdef __linux__
- if (fsrv.nyx_mode) {
- remove_nyx_tmp_workdir(fsrv.out_dir_path);
- }
-#endif
afl_shm_deinit(&shm);
afl_fsrv_deinit(&fsrv);
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index ae2adc3d..0e705c63 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -126,11 +126,39 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
fail:
FATAL("failed to load libnyx: %s\n", dlerror());
- free(plugin);
+ ck_free(plugin);
return NULL;
}
+void afl_nyx_runner_kill(afl_forkserver_t *fsrv){
+ if (fsrv->nyx_mode) {
+
+ if (fsrv->nyx_aux_string){
+ ck_free(fsrv->nyx_aux_string);
+ }
+
+ /* check if we actually got a valid nyx runner */
+ if (fsrv->nyx_runner) {
+ fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+ }
+
+ /* if we have use a tmp work dir we need to remove it */
+ if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) {
+ remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path);
+ }
+ }
+}
+
+/* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
+ * files) before exiting. Used before "afl_fsrv_killall()" is registered as
+ * an atexit() handler. */
+#define NYX_PRE_FATAL(fsrv, x...) \
+ do { \
+ afl_nyx_runner_kill(fsrv); \
+ FATAL(x); \
+ } while (0)
+
#endif
/**
@@ -168,6 +196,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->nyx_runner = NULL;
fsrv->nyx_id = 0xFFFFFFFF;
fsrv->nyx_bind_cpu_id = 0xFFFFFFFF;
+ fsrv->nyx_use_tmp_workdir = false;
+ fsrv->nyx_tmp_workdir_path = NULL;
#endif
// this structure needs default so we initialize it if this was not done
@@ -481,21 +511,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Spinning up the NYX backend..."); }
- if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); }
+ if (fsrv->nyx_use_tmp_workdir){
+ fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir();
+ fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path;
+ } else {
+ if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); }
+ }
- char *x = alloc_printf("%s/workdir", fsrv->out_dir_path);
+ char *workdir_path = alloc_printf("%s/workdir", fsrv->out_dir_path);
- if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); }
+ if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); }
if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
-
- FATAL("Nyx CPU ID is not set...");
-
+ NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set...");
}
void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
- fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, x);
+ 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_write_protection(nyx_config, true);
@@ -512,22 +545,36 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (getenv("NYX_REUSE_SNAPSHOT") != NULL){
if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
- FATAL("NYX_REUSE_SNAPSHOT path does not exist");
+ NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
}
/* stupid sanity check to avoid passing an empty or invalid snapshot directory */
char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
if (access(snapshot_file_path, R_OK) == -1) {
- FATAL("NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+ NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
}
- free(snapshot_file_path);
+ ck_free(snapshot_file_path);
+
+ /* another sanity check to avoid passing a snapshot directory that is
+ * located in the current workdir (the workdir will be wiped by libnyx on startup) */
+ char* outdir_path_real = realpath(fsrv->out_dir_path, NULL);
+ char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_real);
+ char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+
+ if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){
+ NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path is located in current workdir (use another output directory)");
+ }
+
+ ck_free(reuse_snapshot_path_real);
+ ck_free(workdir_snapshot_path);
+ ck_free(outdir_path_real);
fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
}
fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
- ck_free(x);
+ ck_free(workdir_path);
if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
@@ -555,13 +602,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
case Abort:
- FATAL("Error: Nyx abort occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured...");
break;
case IoError:
- FATAL("Error: QEMU-Nyx has died...");
+ NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died...");
break;
case Error:
- FATAL("Error: Nyx runtime error has occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured...");
break;
default:
break;
@@ -571,7 +618,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* autodict in Nyx mode */
if (!ignore_autodict) {
- x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
+ char* x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
int nyx_autodict_fd = open(x, O_RDONLY);
ck_free(x);
@@ -584,7 +631,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u8 *dict = ck_alloc(f_len);
if (dict == NULL) {
- FATAL("Could not allocate %u bytes of autodictionary memory",
+ NYX_PRE_FATAL(fsrv, "Could not allocate %u bytes of autodictionary memory",
f_len);
}
@@ -602,7 +649,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} else {
- FATAL(
+ NYX_PRE_FATAL(fsrv,
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
@@ -1289,19 +1336,7 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
fsrv->child_pid = -1;
#ifdef __linux__
- if (fsrv->nyx_mode) {
-
- if (fsrv->nyx_aux_string){
- free(fsrv->nyx_aux_string);
- }
-
- /* check if we actually got a valid nyx runner */
- if (fsrv->nyx_runner) {
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- }
-
- }
-
+ afl_nyx_runner_kill(fsrv);
#endif
}
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8b4fe1e5..0e380f73 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -2191,14 +2191,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->pending_not_fuzzed || !valid_seeds) {
- #ifdef __linux__
- if (afl->fsrv.nyx_mode) {
-
- afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
-
- }
-
- #endif
FATAL("We need at least one valid input seed that does not crash!");
}
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 3ddebaad..832730fd 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1247,7 +1247,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- fsrv->out_dir_path = create_nyx_tmp_workdir();
+ fsrv->nyx_use_tmp_workdir = true;
fsrv->nyx_bind_cpu_id = 0;
#endif
@@ -1443,12 +1443,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (execute_testcases(in_dir) == 0) {
-#ifdef __linux__
- if (fsrv->nyx_mode) {
- remove_nyx_tmp_workdir(fsrv->out_dir_path);
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- }
-#endif
FATAL("could not read input testcases from %s", in_dir);
}
@@ -1528,11 +1522,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->target_path) { ck_free(fsrv->target_path); }
-#ifdef __linux__
- if (fsrv->nyx_mode) {
- remove_nyx_tmp_workdir(fsrv->out_dir_path);
- }
-#endif
afl_fsrv_deinit(fsrv);
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 942525d4..98403049 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -1130,7 +1130,7 @@ int main(int argc, char **argv_orig, char **envp) {
FATAL("failed to initialize libnyx.so...");
}
- fsrv->out_dir_path = create_nyx_tmp_workdir();
+ fsrv->nyx_use_tmp_workdir = true;
fsrv->nyx_bind_cpu_id = 0;
use_argv = argv + optind;
@@ -1316,11 +1316,6 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
-#ifdef __linux__
- if (fsrv->nyx_mode) {
- remove_nyx_tmp_workdir(fsrv->out_dir_path);
- }
-#endif
remove_shm = 0;
afl_shm_deinit(&shm);
--
cgit 1.4.1
From 61aeb4486310b4aab66558bd21ead8b6e35501e2 Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Sun, 16 Apr 2023 05:19:09 +0200
Subject: remove redundant access() call
---
src/afl-common.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/src/afl-common.c b/src/afl-common.c
index fe0db94d..5692e277 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -1390,10 +1390,8 @@ void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) {
}
}
- if (access(nyx_out_dir_path, R_OK) == 0) {
- if (rmdir(nyx_out_dir_path)) {
- WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
- }
+ if (rmdir(nyx_out_dir_path)) {
+ WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
}
ck_free(workdir_path);
--
cgit 1.4.1
From d0b86bf05563dea686d27f14972f448b6f33023b Mon Sep 17 00:00:00 2001
From: Sergej Schumilo
Date: Sun, 16 Apr 2023 06:23:38 +0200
Subject: pass absolute paths to libnyx
---
src/afl-forkserver.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 0e705c63..fd4e213d 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -518,7 +518,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); }
}
- char *workdir_path = alloc_printf("%s/workdir", fsrv->out_dir_path);
+ /* libnyx expects an absolute path */
+ char* outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
+ if (outdir_path_absolute == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); }
+
+ char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute);
if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); }
@@ -557,8 +561,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* another sanity check to avoid passing a snapshot directory that is
* located in the current workdir (the workdir will be wiped by libnyx on startup) */
- char* outdir_path_real = realpath(fsrv->out_dir_path, NULL);
- char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_real);
+ char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){
@@ -567,7 +570,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
ck_free(reuse_snapshot_path_real);
ck_free(workdir_snapshot_path);
- ck_free(outdir_path_real);
fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
}
@@ -575,6 +577,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
ck_free(workdir_path);
+ ck_free(outdir_path_absolute);
if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
--
cgit 1.4.1
From 56f7e3aa088e715b054f10c01b6b5a7e5acf8931 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 16 Apr 2023 12:42:32 +0200
Subject: hidden -Y option for nyx, code format
---
afl-cmin | 10 +--
afl-cmin.bash | 30 +++++---
include/common.h | 4 +-
include/forkserver.h | 13 +++-
src/afl-analyze.c | 29 +++++---
src/afl-common.c | 26 +++++--
src/afl-forkserver.c | 151 +++++++++++++++++++++++++++-----------
src/afl-showmap.c | 54 +++++++++-----
src/afl-tmin.c | 27 ++++---
utils/aflpp_driver/aflpp_driver.c | 23 +++---
10 files changed, 243 insertions(+), 124 deletions(-)
(limited to 'src')
diff --git a/afl-cmin b/afl-cmin
index 12791584..c5e64410 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -124,9 +124,9 @@ function usage() {
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
"AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \
"AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \
-"AFL_FORK_SERVER_KILL_SIGNAL: Signal delivered to fork server processes on termination\n" \
-" (default: SIGTERM). If this is not set and AFL_KILL_SIGNAL is set,\n" \
-" this will be set to the same value as AFL_KILL_SIGNAL.\n" \
+"AFL_FORK_SERVER_KILL_SIGNAL: Signal delivered to fork server processes on\n" \
+" termination (default: SIGTERM). If this is not set and AFL_KILL_SIGNAL is\n" \
+" set, this will be set to the same value as AFL_KILL_SIGNAL.\n" \
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" \
"AFL_CMIN_ALLOW_ANY: write tuples for crashing inputs also\n" \
"AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \
@@ -157,7 +157,7 @@ BEGIN {
# process options
Opterr = 1 # default is to diagnose
Optind = 1 # skip ARGV[0]
- while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUX?")) != -1) {
+ while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXY?")) != -1) {
if (_go_c == "i") {
if (!Optarg) usage()
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -219,7 +219,7 @@ BEGIN {
unicorn_mode = 1
continue
} else
- if (_go_c == "X") {
+ if (_go_c == "X" || _go_c == "Y") {
if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
extra_par = extra_par " -X"
nyx_mode = 1
diff --git a/afl-cmin.bash b/afl-cmin.bash
index 10c9477a..bcf62eba 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
export AFL_QUIET=1
-while getopts "+i:o:f:m:t:eOQUACh" opt; do
+while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
case "$opt" in
@@ -94,6 +94,14 @@ while getopts "+i:o:f:m:t:eOQUACh" opt; do
EXTRA_PAR="$EXTRA_PAR -Q"
QEMU_MODE=1
;;
+ "Y")
+ EXTRA_PAR="$EXTRA_PAR -X"
+ NYX_MODE=1
+ ;;
+ "X")
+ EXTRA_PAR="$EXTRA_PAR -X"
+ NYX_MODE=1
+ ;;
"U")
EXTRA_PAR="$EXTRA_PAR -U"
UNICORN_MODE=1
@@ -128,6 +136,7 @@ Execution control settings:
-O - use binary-only instrumentation (FRIDA mode)
-Q - use binary-only instrumentation (QEMU mode)
-U - use unicorn-based instrumentation (Unicorn mode)
+ -X - use Nyx mode
Minimization settings:
@@ -206,16 +215,19 @@ if [ ! "$TIMEOUT" = "none" ]; then
fi
-if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
+if [ "$NYX_MODE" = "" ]; then
+ if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
- TNEW="`which "$TARGET_BIN" 2>/dev/null`"
+ TNEW="`which "$TARGET_BIN" 2>/dev/null`"
- if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then
- echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2
- exit 1
- fi
+ if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then
+ echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2
+ exit 1
+ fi
+
+ TARGET_BIN="$TNEW"
- TARGET_BIN="$TNEW"
+ fi
fi
@@ -228,7 +240,7 @@ grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && {
}
}
-if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
+if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" -a "$NYX_MODE" = "" ]; then
if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then
echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2
diff --git a/include/common.h b/include/common.h
index e03566de..8d85d201 100644
--- a/include/common.h
+++ b/include/common.h
@@ -149,8 +149,8 @@ void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
#ifdef __linux__
/* Nyx helper functions to create and remove tmp workdirs */
-char* create_nyx_tmp_workdir(void);
-void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path);
+char *create_nyx_tmp_workdir(void);
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path);
#endif
#endif
diff --git a/include/forkserver.h b/include/forkserver.h
index ba280d38..f5069ce2 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -52,20 +52,25 @@ typedef enum NyxReturnValue {
} NyxReturnValue;
typedef enum NyxProcessRole {
+
StandAlone,
Parent,
Child,
+
} NyxProcessRole;
typedef struct {
void *(*nyx_config_load)(const char *sharedir);
void (*nyx_config_set_workdir_path)(void *config, const char *workdir);
- void (*nyx_config_set_input_buffer_size)(void *config, uint32_t input_buffer_size);
- void (*nyx_config_set_input_buffer_write_protection)(void *config, bool input_buffer_write_protection);
+ void (*nyx_config_set_input_buffer_size)(void *config,
+ uint32_t input_buffer_size);
+ void (*nyx_config_set_input_buffer_write_protection)(
+ void *config, bool input_buffer_write_protection);
void (*nyx_config_set_hprintf_fd)(void *config, int32_t hprintf_fd);
void (*nyx_config_set_process_role)(void *config, enum NyxProcessRole role);
- void (*nyx_config_set_reuse_snapshot_path)(void *config, const char *reuse_snapshot_path);
+ void (*nyx_config_set_reuse_snapshot_path)(void *config,
+ const char *reuse_snapshot_path);
void *(*nyx_new)(void *config, uint32_t worker_id);
void (*nyx_shutdown)(void *qemu_process);
@@ -191,7 +196,7 @@ typedef struct afl_forkserver {
u32 nyx_bind_cpu_id; /* nyx runner cpu id */
char *nyx_aux_string;
bool nyx_use_tmp_workdir;
- char *nyx_tmp_workdir_path;
+ char *nyx_tmp_workdir_path;
#endif
} afl_forkserver_t;
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 0a4e7fb5..5b122741 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -815,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init(&fsrv);
- while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXYh")) > 0) {
switch (opt) {
@@ -966,8 +966,9 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv.mem_limit = mem_limit;
break;
-
- #ifdef __linux__
+
+ case 'Y': // fallthough
+#ifdef __linux__
case 'X': /* NYX mode */
if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
@@ -977,11 +978,11 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv.nyx_standalone = true;
break;
- #else
+#else
case 'X':
FATAL("Nyx mode is only availabe on linux...");
break;
- #endif
+#endif
case 'h':
usage(argv[0]);
@@ -1015,12 +1016,16 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(argv);
#ifdef __linux__
- if(!fsrv.nyx_mode){
+ if (!fsrv.nyx_mode) {
+
fsrv.target_path = find_binary(argv[optind]);
- }
- else{
+
+ } else {
+
fsrv.target_path = ck_strdup(argv[optind]);
+
}
+
#else
fsrv.target_path = find_binary(argv[optind]);
#endif
@@ -1048,6 +1053,7 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
#ifdef __linux__
+
} else if (fsrv.nyx_mode) {
fsrv.nyx_id = 0;
@@ -1055,7 +1061,9 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
if (fsrv.nyx_handlers == NULL) {
+
FATAL("failed to initialize libnyx.so...");
+
}
fsrv.nyx_use_tmp_workdir = true;
@@ -1090,9 +1098,7 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
#ifdef __linux__
- if(!fsrv.nyx_mode){
- (void)check_binary_signatures(fsrv.target_path);
- }
+ if (!fsrv.nyx_mode) { (void)check_binary_signatures(fsrv.target_path); }
#else
(void)check_binary_signatures(fsrv.target_path);
#endif
@@ -1119,7 +1125,6 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
-
afl_shm_deinit(&shm);
afl_fsrv_deinit(&fsrv);
if (fsrv.target_path) { ck_free(fsrv.target_path); }
diff --git a/src/afl-common.c b/src/afl-common.c
index 5692e277..a5c48e80 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -1365,36 +1365,46 @@ s32 create_file(u8 *fn) {
* etc.). This helper function basically creates both a path to a tmp workdir
* and the workdir itself. If the environment variable TMPDIR is set, we use
* that as the base directory, otherwise we use /tmp. */
-char* create_nyx_tmp_workdir(void) {
+char *create_nyx_tmp_workdir(void) {
char *tmpdir = getenv("TMPDIR");
if (!tmpdir) { tmpdir = "/tmp"; }
- char* nyx_out_dir_path = alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
+ char *nyx_out_dir_path =
+ alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
- if (mkdir(nyx_out_dir_path, 0700)) {
- PFATAL("Unable to create nyx workdir");
- }
+ if (mkdir(nyx_out_dir_path, 0700)) { PFATAL("Unable to create nyx workdir"); }
return nyx_out_dir_path;
+
}
/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
-void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char* nyx_out_dir_path) {
- char* workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path) {
+
+ char *workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
if (access(workdir_path, R_OK) == 0) {
- if(fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+
+ if (fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+
WARNF("Unable to remove nyx workdir (%s)", workdir_path);
+
}
+
}
if (rmdir(nyx_out_dir_path)) {
+
WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
+
}
ck_free(workdir_path);
ck_free(nyx_out_dir_path);
+
}
+
#endif
+
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index fd4e213d..aa8c8622 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -50,7 +50,7 @@
#include
#ifdef __linux__
-#include
+ #include
/* function to load nyx_helper function from libnyx.so */
@@ -66,22 +66,32 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
plugin->nyx_config_load = dlsym(handle, "nyx_config_load");
if (plugin->nyx_config_load == NULL) { goto fail; }
- plugin->nyx_config_set_workdir_path = dlsym(handle, "nyx_config_set_workdir_path");
+ plugin->nyx_config_set_workdir_path =
+ dlsym(handle, "nyx_config_set_workdir_path");
if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; }
- plugin->nyx_config_set_input_buffer_size = dlsym(handle, "nyx_config_set_input_buffer_size");
+ plugin->nyx_config_set_input_buffer_size =
+ dlsym(handle, "nyx_config_set_input_buffer_size");
if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; }
- plugin->nyx_config_set_input_buffer_write_protection = dlsym(handle, "nyx_config_set_input_buffer_write_protection");
- if (plugin->nyx_config_set_input_buffer_write_protection == NULL) { goto fail; }
+ plugin->nyx_config_set_input_buffer_write_protection =
+ dlsym(handle, "nyx_config_set_input_buffer_write_protection");
+ if (plugin->nyx_config_set_input_buffer_write_protection == NULL) {
- plugin->nyx_config_set_hprintf_fd = dlsym(handle, "nyx_config_set_hprintf_fd");
+ goto fail;
+
+ }
+
+ plugin->nyx_config_set_hprintf_fd =
+ dlsym(handle, "nyx_config_set_hprintf_fd");
if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; }
- plugin->nyx_config_set_process_role = dlsym(handle, "nyx_config_set_process_role");
+ plugin->nyx_config_set_process_role =
+ dlsym(handle, "nyx_config_set_process_role");
if (plugin->nyx_config_set_process_role == NULL) { goto fail; }
- plugin->nyx_config_set_reuse_snapshot_path = dlsym(handle, "nyx_config_set_reuse_snapshot_path");
+ plugin->nyx_config_set_reuse_snapshot_path =
+ dlsym(handle, "nyx_config_set_reuse_snapshot_path");
if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; }
plugin->nyx_new = dlsym(handle, "nyx_new");
@@ -119,7 +129,6 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
-
OKF("libnyx plugin is ready!");
return plugin;
@@ -131,33 +140,40 @@ fail:
}
-void afl_nyx_runner_kill(afl_forkserver_t *fsrv){
+void afl_nyx_runner_kill(afl_forkserver_t *fsrv) {
+
if (fsrv->nyx_mode) {
- if (fsrv->nyx_aux_string){
- ck_free(fsrv->nyx_aux_string);
- }
+ if (fsrv->nyx_aux_string) { ck_free(fsrv->nyx_aux_string); }
/* check if we actually got a valid nyx runner */
if (fsrv->nyx_runner) {
+
fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+
}
/* if we have use a tmp work dir we need to remove it */
if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) {
+
remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path);
+
}
+
}
+
}
-/* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
- * files) before exiting. Used before "afl_fsrv_killall()" is registered as
- * an atexit() handler. */
-#define NYX_PRE_FATAL(fsrv, x...) \
- do { \
- afl_nyx_runner_kill(fsrv); \
- FATAL(x); \
- } while (0)
+ /* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
+ * files) before exiting. Used before "afl_fsrv_killall()" is registered as
+ * an atexit() handler. */
+ #define NYX_PRE_FATAL(fsrv, x...) \
+ do { \
+ \
+ afl_nyx_runner_kill(fsrv); \
+ FATAL(x); \
+ \
+ } while (0)
#endif
@@ -511,70 +527,116 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Spinning up the NYX backend..."); }
- if (fsrv->nyx_use_tmp_workdir){
+ if (fsrv->nyx_use_tmp_workdir) {
+
fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir();
fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path;
+
} else {
- if (fsrv->out_dir_path == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path not found..."); }
+
+ if (fsrv->out_dir_path == NULL) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path not found...");
+
+ }
+
}
/* libnyx expects an absolute path */
- char* outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
- if (outdir_path_absolute == NULL) { NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ..."); }
+ char *outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
+ if (outdir_path_absolute == NULL) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ...");
+
+ }
char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute);
- if (fsrv->nyx_id == 0xFFFFFFFF) {NYX_PRE_FATAL(fsrv, "Nyx ID is not set..."); }
+ if (fsrv->nyx_id == 0xFFFFFFFF) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx ID is not set...");
+
+ }
if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
+
NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set...");
+
}
- void* nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
+ 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_write_protection(nyx_config, true);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
+ true);
if (fsrv->nyx_standalone) {
+
fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
+
} else {
+
if (fsrv->nyx_parent) {
+
fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent);
+
} else {
+
fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child);
+
}
+
}
- if (getenv("NYX_REUSE_SNAPSHOT") != NULL){
+ if (getenv("NYX_REUSE_SNAPSHOT") != NULL) {
if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+
NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
+
}
- /* stupid sanity check to avoid passing an empty or invalid snapshot directory */
- char* snapshot_file_path = alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+ /* stupid sanity check to avoid passing an empty or invalid snapshot
+ * directory */
+ char *snapshot_file_path =
+ alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
if (access(snapshot_file_path, R_OK) == -1) {
- NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+
+ NYX_PRE_FATAL(
+ fsrv,
+ "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+
}
+
ck_free(snapshot_file_path);
/* another sanity check to avoid passing a snapshot directory that is
- * located in the current workdir (the workdir will be wiped by libnyx on startup) */
- char* workdir_snapshot_path = alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
- char* reuse_snapshot_path_real = realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+ * located in the current workdir (the workdir will be wiped by libnyx on
+ * startup) */
+ char *workdir_snapshot_path =
+ alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
+ char *reuse_snapshot_path_real =
+ realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+
+ if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) {
+
+ NYX_PRE_FATAL(fsrv,
+ "NYX_REUSE_SNAPSHOT path is located in current workdir "
+ "(use another output directory)");
- if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0){
- NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path is located in current workdir (use another output directory)");
}
ck_free(reuse_snapshot_path_real);
ck_free(workdir_snapshot_path);
- fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+ fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(
+ nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+
}
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
+ fsrv->nyx_runner =
+ fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
ck_free(workdir_path);
ck_free(outdir_path_absolute);
@@ -621,7 +683,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* autodict in Nyx mode */
if (!ignore_autodict) {
- char* x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
+ char *x =
+ alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
int nyx_autodict_fd = open(x, O_RDONLY);
ck_free(x);
@@ -634,8 +697,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u8 *dict = ck_alloc(f_len);
if (dict == NULL) {
- NYX_PRE_FATAL(fsrv, "Could not allocate %u bytes of autodictionary memory",
- f_len);
+ NYX_PRE_FATAL(
+ fsrv, "Could not allocate %u bytes of autodictionary memory",
+ f_len);
}
@@ -652,7 +716,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} else {
- NYX_PRE_FATAL(fsrv,
+ NYX_PRE_FATAL(
+ fsrv,
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 832730fd..df030672 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -444,8 +444,11 @@ static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
FSRV_RUN_ERROR) {
FATAL("Error running target in Nyx mode");
+
}
+
}
+
#endif
/* Execute target application. */
@@ -890,7 +893,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshX")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
switch (opt) {
@@ -1078,7 +1081,8 @@ int main(int argc, char **argv_orig, char **envp) {
break;
- #ifdef __linux__
+ case 'Y': // fallthough
+#ifdef __linux__
case 'X': /* NYX mode */
if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
@@ -1088,11 +1092,11 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->nyx_standalone = true;
break;
- #else
+#else
case 'X':
FATAL("Nyx mode is only availabe on linux...");
break;
- #endif
+#endif
case 'b':
@@ -1166,12 +1170,16 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
#ifdef __linux__
- if(!fsrv->nyx_mode){
+ if (!fsrv->nyx_mode) {
+
fsrv->target_path = find_binary(argv[optind]);
- }
- else{
+
+ } else {
+
fsrv->target_path = ck_strdup(argv[optind]);
+
}
+
#else
fsrv->target_path = find_binary(argv[optind]);
#endif
@@ -1232,11 +1240,12 @@ int main(int argc, char **argv_orig, char **envp) {
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
#ifdef __linux__
+
} else if (fsrv->nyx_mode) {
use_argv = ck_alloc(sizeof(char *) * (1));
use_argv[0] = argv[0];
-
+
fsrv->nyx_id = 0;
u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
@@ -1288,9 +1297,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
#ifdef __linux__
- if(!fsrv->nyx_mode && in_dir){
+ if (!fsrv->nyx_mode && in_dir) {
+
(void)check_binary_signatures(fsrv->target_path);
+
}
+
#else
if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
#endif
@@ -1313,14 +1325,14 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32);
- configure_afl_kill_signals(
- fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode
- #ifdef __linux__
- || fsrv->nyx_mode
- #endif
- )
- ? SIGKILL
- : SIGTERM);
+ configure_afl_kill_signals(fsrv, NULL, NULL,
+ (fsrv->qemu_mode || unicorn_mode
+#ifdef __linux__
+ || fsrv->nyx_mode
+#endif
+ )
+ ? SIGKILL
+ : SIGTERM);
if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
@@ -1464,13 +1476,18 @@ int main(int argc, char **argv_orig, char **envp) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
#ifdef __linux__
- if(!fsrv->nyx_mode){
+ if (!fsrv->nyx_mode) {
+
#endif
showmap_run_target(fsrv, use_argv);
#ifdef __linux__
+
} else {
+
showmap_run_target_nyx_mode(fsrv);
+
}
+
#endif
tcnt = write_results_to_file(fsrv, out_file);
if (!quiet_mode) {
@@ -1522,7 +1539,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->target_path) { ck_free(fsrv->target_path); }
-
afl_fsrv_deinit(fsrv);
if (stdin_file) { ck_free(stdin_file); }
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 98403049..e7442d1d 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -846,7 +846,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:xeAOQUWXHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
switch (opt) {
@@ -1004,7 +1004,8 @@ int main(int argc, char **argv_orig, char **envp) {
break;
- #ifdef __linux__
+ case 'Y': // fallthough
+#ifdef __linux__
case 'X': /* NYX mode */
if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
@@ -1014,11 +1015,11 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->nyx_standalone = true;
break;
- #else
+#else
case 'X':
FATAL("Nyx mode is only availabe on linux...");
break;
- #endif
+#endif
case 'H': /* Hang Mode */
@@ -1086,12 +1087,16 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
#ifdef __linux__
- if(!fsrv->nyx_mode){
+ if (!fsrv->nyx_mode) {
+
fsrv->target_path = find_binary(argv[optind]);
- }
- else{
+
+ } else {
+
fsrv->target_path = ck_strdup(argv[optind]);
+
}
+
#else
fsrv->target_path = find_binary(argv[optind]);
#endif
@@ -1120,6 +1125,7 @@ int main(int argc, char **argv_orig, char **envp) {
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
#ifdef __linux__
+
} else if (fsrv->nyx_mode) {
fsrv->nyx_id = 0;
@@ -1127,7 +1133,9 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
if (fsrv->nyx_handlers == NULL) {
+
FATAL("failed to initialize libnyx.so...");
+
}
fsrv->nyx_use_tmp_workdir = true;
@@ -1207,9 +1215,7 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
#ifdef __linux__
- if(!fsrv->nyx_mode){
- (void)check_binary_signatures(fsrv->target_path);
- }
+ if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
#else
(void)check_binary_signatures(fsrv->target_path);
#endif
@@ -1316,7 +1322,6 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("We're done here. Have a nice day!\n");
-
remove_shm = 0;
afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index 34294809..4e8f466d 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -78,10 +78,10 @@ extern unsigned int __afl_map_size;
on the other hand this is what Google needs to make LLVMFuzzerRunDriver()
work. Choose your poison Google! */
/*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data,
- size_t Size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
-__attribute__((weak)) int LLVMFuzzerRunDriver(
- int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size));
+ size_t Size);
+__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+__attribute__((weak)) int LLVMFuzzerRunDriver(
+ int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size));
// Default nop ASan hooks for manual poisoning when not linking the ASan
// runtime
@@ -268,15 +268,16 @@ static int ExecuteFilesOnyByOne(int argc, char **argv,
__attribute__((weak)) int main(int argc, char **argv) {
-// Enable if LLVMFuzzerTestOneInput() has the weak attribute
-/*
- if (!LLVMFuzzerTestOneInput) {
+ // Enable if LLVMFuzzerTestOneInput() has the weak attribute
+ /*
+ if (!LLVMFuzzerTestOneInput) {
- fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n");
- abort();
+ fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n");
+ abort();
- }
-*/
+ }
+
+ */
if (argc < 2 || strncmp(argv[1], "-h", 2) == 0)
printf(
--
cgit 1.4.1
From 450dbae8cd2ae278e0b381d172cb7694f40278cb Mon Sep 17 00:00:00 2001
From: Maik Betka <9078425+voidptr127@users.noreply.github.com>
Date: Mon, 17 Apr 2023 17:09:48 +0200
Subject: first version with unix domain sockets is ready for testing
---
custom_mutators/atnwalk/atnwalk.c | 254 +++++++++++++++++++++++++++++++++-----
src/afl-fuzz-run.c | 11 +-
2 files changed, 232 insertions(+), 33 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c
index cc9f9618..584add61 100644
--- a/custom_mutators/atnwalk/atnwalk.c
+++ b/custom_mutators/atnwalk/atnwalk.c
@@ -1,5 +1,4 @@
-#include "../../include/afl-fuzz.h"
-
+#include
#include
#include
#include
@@ -7,10 +6,10 @@
#include
#include
-
#define INIT_BUF_SIZE 4096
#define SOCKET_NAME "/tmp/atnwalk.socket"
+
// handshake constants
const uint8_t SERVER_ARE_YOU_ALIVE = 42;
const uint8_t SERVER_YES_I_AM_ALIVE = 213;
@@ -23,8 +22,10 @@ const uint8_t SERVER_ENCODE_BIT = 0b00001000;
typedef struct atnwalk_mutator {
- uint8_t *decoded_buf;
- size_t decoded_size;
+ uint8_t *fuzz_buf;
+ size_t fuzz_size;
+ uint8_t *post_process_buf;
+ size_t post_process_size;
} atnwalk_mutator_t;
@@ -55,6 +56,32 @@ int write_all(int fd, uint8_t *buf, size_t buf_size) {
return 1;
}
+void put_uint32(uint8_t *buf, uint32_t val) {
+ buf[0] = (uint8_t) (val >> 24);
+ buf[1] = (uint8_t) ((val & 0x00ff0000) >> 16);
+ buf[2] = (uint8_t) ((val & 0x0000ff00) >> 8);
+ buf[3] = (uint8_t) (val & 0x000000ff);
+}
+
+uint32_t to_uint32(uint8_t *buf) {
+ uint32_t val = 0;
+ val |= (((uint32_t) buf[0]) << 24);
+ val |= (((uint32_t) buf[1]) << 16);
+ val |= (((uint32_t) buf[2]) << 8);
+ val |= ((uint32_t) buf[3]);
+ return val;
+}
+
+void put_uint64(uint8_t *buf, uint64_t val) {
+ buf[0] = (uint8_t) (val >> 56);
+ buf[1] = (uint8_t) ((val & 0x00ff000000000000) >> 48);
+ buf[2] = (uint8_t) ((val & 0x0000ff0000000000) >> 40);
+ buf[3] = (uint8_t) ((val & 0x000000ff00000000) >> 32);
+ buf[4] = (uint8_t) ((val & 0x00000000ff000000) >> 24);
+ buf[5] = (uint8_t) ((val & 0x0000000000ff0000) >> 16);
+ buf[6] = (uint8_t) ((val & 0x000000000000ff00) >> 8);
+ buf[7] = (uint8_t) (val & 0x00000000000000ff);
+}
/**
* Initialize this custom mutator
@@ -67,19 +94,21 @@ int write_all(int fd, uint8_t *buf, size_t buf_size) {
* There may be multiple instances of this mutator in one afl-fuzz run!
* Return NULL on error.
*/
-atnwalk_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
+atnwalk_mutator_t *afl_custom_init(void *afl, unsigned int seed) {
srand(seed);
atnwalk_mutator_t *data = (atnwalk_mutator_t *) malloc(sizeof(atnwalk_mutator_t));
if (!data) {
perror("afl_custom_init alloc");
return NULL;
}
- data->decoded_buf = (uint8_t *) malloc(INIT_BUF_SIZE);
- data->decoded_size = INIT_BUF_SIZE;
+ data->fuzz_buf = (uint8_t *) malloc(INIT_BUF_SIZE);
+ data->fuzz_size = INIT_BUF_SIZE;
+ data->post_process_buf = (uint8_t *) malloc(INIT_BUF_SIZE);
+ data->post_process_size = INIT_BUF_SIZE;
return data;
}
-// TODO: implement
+
/**
* Perform custom mutations on a given input
*
@@ -100,13 +129,12 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
uint8_t *add_buf, size_t add_buf_size, size_t max_size) {
struct sockaddr_un addr;
int fd_socket;
- ssize_t n;
- uint8_t buffer[5];
+ uint8_t ctrl_buf[8];
+ uint8_t wanted;
// initialize the socket
fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd_socket == -1) {
- perror("socket");
*out_buf = NULL;
return 0;
}
@@ -114,26 +142,127 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
- perror("atnwalk server is down");
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // TODO: how to set connection deadline? maybe not required if server already closes the connection?
+
+ // TODO: there should be some kind of loop retrying with different seeds and ultimately giving up on that input?
+ // maybe this is not necessary, because we may also just return a single byte in case of failure?
+
+ // ask whether the server is alive
+ ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
+ if (!write_all(fd_socket, ctrl_buf, 1)) {
+ close(fd_socket);
*out_buf = NULL;
return 0;
}
- if (!write_all(fd_socket, buffer, 5)) {
- perror("write to atnwalk server failed");
+ // see whether the server replies as expected
+ if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // tell the server what we want to do
+ wanted = SERVER_MUTATE_BIT | SERVER_ENCODE_BIT;
+
+ // 50% chance to perform a crossover if there is an additional buffer available
+ if ((add_buf_size > 0) && (rand() % 2)) {
+ wanted |= SERVER_CROSSOVER_BIT;
+ }
+
+ // tell the server what we want and how much data will be sent
+ ctrl_buf[0] = wanted;
+ put_uint32(ctrl_buf + 1, (uint32_t) buf_size);
+ if (!write_all(fd_socket, ctrl_buf, 5)) {
+ close(fd_socket);
*out_buf = NULL;
return 0;
}
- if (read_all(fd_socket, buffer, 5)) {
- perror("read to atnwalk server failed");
- exit(EXIT_FAILURE);
+ // send the data to mutate and encode
+ if (!write_all(fd_socket, buf, buf_size)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ if (wanted & SERVER_CROSSOVER_BIT) {
+ // since we requested crossover, we will first tell how much additional data is to be expected
+ put_uint32(ctrl_buf, (uint32_t) add_buf_size);
+ if (!write_all(fd_socket, ctrl_buf, 4)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ // send the additional data for crossover
+ if (!write_all(fd_socket, add_buf, add_buf_size)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ // lastly, a seed is required for crossover so send one
+ put_uint64(ctrl_buf, (uint64_t) rand());
+ if (!write_all(fd_socket, ctrl_buf, 8)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+ }
+
+ // since we requested mutation, we need to provide a seed for that
+ put_uint64(ctrl_buf, (uint64_t) rand());
+ if (!write_all(fd_socket, ctrl_buf, 8)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ // obtain the required buffer size for the data that will be returned
+ if (!read_all(fd_socket, ctrl_buf, 4)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+ size_t new_size = (size_t) to_uint32(ctrl_buf);
+
+ // if the data is too large then we ignore this round
+ if (new_size > max_size) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ if (new_size > buf_size) {
+ // buf is too small, need to use data->fuzz_buf, let's see whether we need to reallocate
+ if (new_size > data->fuzz_size) {
+ data->fuzz_size = new_size << 1;
+ data->fuzz_buf = (uint8_t *) realloc(data->fuzz_buf, data->fuzz_size);
+ }
+ *out_buf = data->fuzz_buf;
+ } else {
+ // new_size fits into buf, so re-use it
+ *out_buf = buf;
+ }
+
+ // obtain the encoded data
+ if (!read_all(fd_socket, *out_buf, new_size)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
}
close(fd_socket);
+ return new_size;
}
-// TODO: implement
+
/**
* A post-processing function to use right before AFL writes the test case to
* disk in order to execute the target.
@@ -151,23 +280,90 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
* A return of 0 indicates an error.
*/
size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) {
- data->decoded_buf[0] = 'p';
- data->decoded_buf[1] = 'u';
- data->decoded_buf[2] = 't';
- data->decoded_buf[3] = 's';
- data->decoded_buf[4] = ' ';
- data->decoded_buf[5] = ';';
- data->decoded_buf[6] = '\n';
- return 7;
+ struct sockaddr_un addr;
+ int fd_socket;
+ uint8_t ctrl_buf[8];
+
+ // initialize the socket
+ fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd_socket == -1) {
+ *out_buf = NULL;
+ return 0;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
+ if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // ask whether the server is alive
+ ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
+ if (!write_all(fd_socket, ctrl_buf, 1)) {
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // see whether the server replies as expected
+ if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // tell the server what we want and how much data will be sent
+ ctrl_buf[0] = SERVER_DECODE_BIT;
+ put_uint32(ctrl_buf + 1, (uint32_t) buf_size);
+ if (!write_all(fd_socket, ctrl_buf, 5)) {
+ close(fd_socket);
+ *out_buf = NULL;
+ return 0;
+ }
+
+ // send the data to decode
+ if (!write_all(fd_socket, buf, buf_size)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ // obtain the required buffer size for the data that will be returned
+ if (!read_all(fd_socket, ctrl_buf, 4)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+ size_t new_size = (size_t) to_uint32(ctrl_buf);
+
+ // need to use data->post_process_buf, let's see whether we need to reallocate
+ if (new_size > data->post_process_size) {
+ data->post_process_size = new_size << 1;
+ data->post_process_buf = (uint8_t *) realloc(data->post_process_buf, data->post_process_size);
+ }
+ *out_buf = data->post_process_buf;
+
+ // obtain the decoded data
+ if (!read_all(fd_socket, *out_buf, new_size)) {
+ close(fd_socket);
+ *out_buf = buf;
+ return buf_size;
+ }
+
+ close(fd_socket);
+ return new_size;
}
-// TODO: implement
+
/**
* Deinitialize everything
*
* @param data The data ptr from afl_custom_init
*/
void afl_custom_deinit(atnwalk_mutator_t *data) {
- free(data->decoded_buf);
+ free(data->fuzz_buf);
+ free(data->post_process_buf);
free(data);
}
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index ee4a3298..26a1ea36 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -130,12 +130,15 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
new_size = afl->max_length;
}
-
- if (new_mem != *mem) { *mem = new_mem; }
+ // TODO: think about how to enable the change without breaking other implementations
+ // if (new_mem != *mem) { *mem = new_mem; }
/* everything as planned. use the potentially new data. */
- afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
- len = new_size;
+ // TODO: think about how to enable the change without breaking other implementations
+ afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
+
+ // TODO: think about how to enable the change without breaking other implementations
+ // len = new_size;
} else {
--
cgit 1.4.1
From 9ab902402cd33156257fc0355c0105e7e03f5ba3 Mon Sep 17 00:00:00 2001
From: Maik Betka <9078425+voidptr127@users.noreply.github.com>
Date: Mon, 17 Apr 2023 17:09:48 +0200
Subject: fixed code clones in atnwalk.c, introduced new environment variable
AFL_POST_PROCESS_KEEP_ORIGINAL in AFL++ to integrate atnwalk without
re-compiling afl-fuzz
---
custom_mutators/atnwalk/atnwalk.c | 144 +++++++++++++-------------------------
include/afl-fuzz.h | 4 +-
include/envs.h | 1 +
src/afl-fuzz-run.c | 11 +--
src/afl-fuzz-state.c | 7 ++
src/afl-fuzz.c | 2 +
6 files changed, 66 insertions(+), 103 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c
index 0194ff18..901b8a9e 100644
--- a/custom_mutators/atnwalk/atnwalk.c
+++ b/custom_mutators/atnwalk/atnwalk.c
@@ -1,4 +1,4 @@
-#include "../../include/afl-fuzz.h"
+#include "afl-fuzz.h"
#include
#include
@@ -9,7 +9,7 @@
#include
#define BUF_SIZE_INIT 4096
-#define SOCKET_NAME "/tmp/atnwalk.socket"
+#define SOCKET_NAME "./atnwalk.socket"
// how many errors (e.g. timeouts) to tolerate until moving on to the next queue entry
#define ATNWALK_ERRORS_MAX 1
@@ -155,6 +155,29 @@ unsigned int afl_custom_fuzz_count(atnwalk_mutator_t *data, const unsigned char
return data->stage_havoc_max + data->stage_splice_max;
}
+
+size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
+ if (fd_socket != -1) {
+ close(fd_socket);
+ }
+ *out_buf = NULL;
+ return 0;
+}
+
+
+size_t fail_gracefully(int fd_socket, atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) {
+ if (fd_socket != -1) {
+ close(fd_socket);
+ }
+ data->atnwalk_error_count++;
+ if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
+ data->afl->stage_max = data->afl->stage_cur;
+ }
+ *out_buf = buf;
+ return buf_size;
+}
+
+
/**
* Perform custom mutations on a given input
*
@@ -202,7 +225,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
}
}
- // keep track of found new corpus seeds per stage and run the stage twice as long as initially planned
+ // keep track of found new corpus seeds per stage
if (data->afl->queued_items + data->afl->saved_crashes > data->prev_hits) {
if (data->stage_splice_cur <= 1) {
data->afl->stage_finds[STAGE_HAVOC] += data->afl->queued_items + data->afl->saved_crashes - data->prev_hits;
@@ -216,38 +239,28 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
// check whether this input produces a lot of timeouts, if it does then abandon this queue entry
if (data->afl->total_tmouts - data->prev_timeouts >= EXEC_TIMEOUT_MAX) {
data->afl->stage_max = data->afl->stage_cur;
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(-1, data, buf, buf_size, out_buf);
}
// initialize the socket
fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd_socket == -1) {
- *out_buf = NULL;
- return 0;
- }
+ if (fd_socket == -1) { return fail_fatal(fd_socket, out_buf); }
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// ask whether the server is alive
ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
if (!write_all(fd_socket, ctrl_buf, 1)) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// see whether the server replies as expected
if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// tell the server what we want to do
@@ -262,88 +275,48 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
ctrl_buf[0] = wanted;
put_uint32(ctrl_buf + 1, (uint32_t) buf_size);
if (!write_all(fd_socket, ctrl_buf, 5)) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// send the data to mutate and encode
if (!write_all(fd_socket, buf, buf_size)) {
- close(fd_socket);
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
if (wanted & SERVER_CROSSOVER_BIT) {
// since we requested crossover, we will first tell how much additional data is to be expected
put_uint32(ctrl_buf, (uint32_t) add_buf_size);
if (!write_all(fd_socket, ctrl_buf, 4)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
// send the additional data for crossover
if (!write_all(fd_socket, add_buf, add_buf_size)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
// lastly, a seed is required for crossover so send one
put_uint64(ctrl_buf, (uint64_t) rand());
if (!write_all(fd_socket, ctrl_buf, 8)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
}
// since we requested mutation, we need to provide a seed for that
put_uint64(ctrl_buf, (uint64_t) rand());
if (!write_all(fd_socket, ctrl_buf, 8)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
// obtain the required buffer size for the data that will be returned
if (!read_all(fd_socket, ctrl_buf, 4)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
size_t new_size = (size_t) to_uint32(ctrl_buf);
// if the data is too large then we ignore this round
if (new_size > max_size) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
if (new_size > buf_size) {
@@ -360,13 +333,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size, u
// obtain the encoded data
if (!read_all(fd_socket, *out_buf, new_size)) {
- close(fd_socket);
- data->atnwalk_error_count++;
- if (data->atnwalk_error_count > ATNWALK_ERRORS_MAX) {
- data->afl->stage_max = data->afl->stage_cur;
- }
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
close(fd_socket);
@@ -398,54 +365,41 @@ size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf
// initialize the socket
fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd_socket == -1) {
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
if (connect(fd_socket, (const struct sockaddr *) &addr, sizeof(addr)) == -1) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// ask whether the server is alive
ctrl_buf[0] = SERVER_ARE_YOU_ALIVE;
if (!write_all(fd_socket, ctrl_buf, 1)) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// see whether the server replies as expected
if (!read_all(fd_socket, ctrl_buf, 1) || ctrl_buf[0] != SERVER_YES_I_AM_ALIVE) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_fatal(fd_socket, out_buf);
}
// tell the server what we want and how much data will be sent
ctrl_buf[0] = SERVER_DECODE_BIT;
put_uint32(ctrl_buf + 1, (uint32_t) buf_size);
if (!write_all(fd_socket, ctrl_buf, 5)) {
- close(fd_socket);
- *out_buf = NULL;
- return 0;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
// send the data to decode
if (!write_all(fd_socket, buf, buf_size)) {
- close(fd_socket);
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
// obtain the required buffer size for the data that will be returned
if (!read_all(fd_socket, ctrl_buf, 4)) {
- close(fd_socket);
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
size_t new_size = (size_t) to_uint32(ctrl_buf);
@@ -458,9 +412,7 @@ size_t afl_custom_post_process(atnwalk_mutator_t *data, uint8_t *buf, size_t buf
// obtain the decoded data
if (!read_all(fd_socket, *out_buf, new_size)) {
- close(fd_socket);
- *out_buf = buf;
- return buf_size;
+ return fail_gracefully(fd_socket, data, buf, buf_size, out_buf);
}
close(fd_socket);
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 23c20cc4..5d9b17e7 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -386,8 +386,8 @@ typedef struct afl_env_vars {
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
- afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme,
- afl_no_startup_calibration;
+ afl_keep_timeouts, afl_pizza_mode, afl_post_process_keep_original,
+ afl_no_crash_readme, afl_no_startup_calibration;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
diff --git a/include/envs.h b/include/envs.h
index 2204a100..1527dfcb 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -177,6 +177,7 @@ static char *afl_environment_variables[] = {
"AFL_PATH",
"AFL_PERFORMANCE_FILE",
"AFL_PERSISTENT_RECORD",
+ "AFL_POST_PROCESS_KEEP_ORIGINAL",
"AFL_PRELOAD",
"AFL_TARGET_ENV",
"AFL_PYTHON_MODULE",
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 26a1ea36..3c3d4817 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -130,15 +130,16 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
new_size = afl->max_length;
}
- // TODO: think about how to enable the change without breaking other implementations
- // if (new_mem != *mem) { *mem = new_mem; }
/* everything as planned. use the potentially new data. */
- // TODO: think about how to enable the change without breaking other implementations
afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
- // TODO: think about how to enable the change without breaking other implementations
- // len = new_size;
+ if (likely(!afl->afl_env.afl_post_process_keep_original)) {
+
+ if (new_mem != *mem) { *mem = new_mem; }
+ len = new_size;
+
+ }
} else {
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 0576f84f..10bc2768 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -377,6 +377,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_statsd =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_POST_PROCESS_KEEP_ORIGINAL",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_post_process_keep_original =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_TMPDIR",
afl_environment_variable_len)) {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 1f0fcab1..b83af257 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -284,6 +284,8 @@ static void usage(u8 *argv0, int more_help) {
PERSISTENT_MSG
+ "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to the queue,\n"
+ " but execute the post-processed one\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TARGET_ENV: pass extra environment variables to target\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
--
cgit 1.4.1
From 4e5f42cab6b8c501eeaf76ec7ca920089f6e0f3a Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 20 Apr 2023 10:39:23 +0200
Subject: afl-showmap custom mutator support
---
GNUmakefile | 2 +-
TODO.md | 4 +--
afl-cmin | 2 ++
afl-cmin.bash | 2 ++
docs/Changelog.md | 3 +-
include/afl-fuzz.h | 8 +++--
src/afl-showmap.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
7 files changed, 107 insertions(+), 7 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile b/GNUmakefile
index 5bc3f9d5..0f890308 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -453,7 +453,7 @@ afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
- $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
+ $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
diff --git a/TODO.md b/TODO.md
index e7789cf6..dba75070 100644
--- a/TODO.md
+++ b/TODO.md
@@ -3,14 +3,14 @@
## Should
- splicing selection weighted?
- - support afl_custom_{send,post_process}, persistent and deferred fork
- server in afl-showmap
+ - support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
- Update afl->pending_not_fuzzed for MOpt
- afl-plot to support multiple plot_data
- parallel builds for source-only targets
- get rid of check_binary, replace with more forkserver communication
- first fuzzer should be a main automatically? not sure.
+ - reload fuzz binary on signal
## Maybe
diff --git a/afl-cmin b/afl-cmin
index c5e64410..e2c26d91 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -133,6 +133,8 @@ function usage() {
"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
"printed to stdout\n" \
"AFL_SKIP_BIN_CHECK: skip afl instrumentation checks for target binary\n"
+"AFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send)\n"
+"AFL_PYTHON_MODULE: custom mutator library (post_process and send)\n"
exit 1
}
diff --git a/afl-cmin.bash b/afl-cmin.bash
index bcf62eba..5258758e 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -151,6 +151,8 @@ AFL_KEEP_TRACES: leave the temporary \.traces directory
AFL_NO_FORKSRV: run target via execve instead of using the forkserver
AFL_PATH: last resort location to find the afl-showmap binary
AFL_SKIP_BIN_CHECK: skip check for target binary
+AFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send)
+AFL_PYTHON_MODULE: custom mutator library (post_process and send)
_EOF_
exit 1
fi
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 30e76f2c..5ed5ef2b 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -4,7 +4,8 @@
release of the tool. See README.md for the general instruction manual.
### Version ++4.07a (dev)
- - soon :)
+ - afl-showmap:
+ - added custom mutator post_process and send support
### Version ++4.06c (release)
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 8b6502b4..ec69ba17 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -1103,7 +1103,6 @@ u32 count_bits(afl_state_t *, u8 *);
u32 count_bytes(afl_state_t *, u8 *);
u32 count_non_255_bytes(afl_state_t *, u8 *);
void simplify_trace(afl_state_t *, u8 *);
-void classify_counts(afl_forkserver_t *);
#ifdef WORD_SIZE_64
void discover_word(u8 *ret, u64 *current, u64 *virgin);
#else
@@ -1117,6 +1116,9 @@ u8 *describe_op(afl_state_t *, u8, size_t);
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
u8 has_new_bits(afl_state_t *, u8 *);
u8 has_new_bits_unclassified(afl_state_t *, u8 *);
+#ifndef AFL_SHOWMAP
+void classify_counts(afl_forkserver_t *);
+#endif
/* Extras */
@@ -1192,11 +1194,13 @@ void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *);
void check_if_tty(afl_state_t *);
-void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);
void write_crash_readme(afl_state_t *afl);
u8 check_if_text_buf(u8 *buf, u32 len);
+#ifndef AFL_SHOWMAP
+void setup_signal_handlers(void);
+#endif
/* CmpLog */
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index df030672..b5a61de5 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -30,8 +30,10 @@
*/
#define AFL_MAIN
+#define AFL_SHOWMAP
#include "config.h"
+#include "afl-fuzz.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"
@@ -62,6 +64,8 @@
#include
#include
+static afl_state_t *afl;
+
static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
@@ -308,12 +312,73 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
}
+void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) {
+
+ static u8 buf[MAX_FILE];
+ u32 sent = 0;
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ ssize_t new_size = len;
+ u8 *new_mem = mem;
+ u8 *new_buf = NULL;
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_post_process) {
+
+ new_size =
+ el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
+
+ if (unlikely(!new_buf || new_size <= 0)) {
+
+ return;
+
+ } else {
+
+ new_mem = new_buf;
+ len = new_size;
+
+ }
+
+ }
+
+ });
+
+ if (new_mem != mem && new_mem != NULL) {
+
+ mem = buf;
+ memcpy(mem, new_mem, new_size);
+
+ }
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ el->afl_custom_fuzz_send(el->data, mem, len);
+ sent = 1;
+
+ }
+
+ });
+
+ }
+
+ }
+
+ if (likely(!sent)) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
+
+}
+
/* Execute target application. */
static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
- afl_fsrv_write_to_testcase(fsrv, mem, len);
+ pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
@@ -835,6 +900,10 @@ static void usage(u8 *argv0) {
"This tool displays raw tuple data captured by AFL instrumentation.\n"
"For additional help, consult %s/README.md.\n\n"
+ "If you use -i mode, then custom mutator post_process send send "
+ "functionality\n"
+ "is supported.\n\n"
+
"Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
@@ -1266,6 +1335,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ afl = calloc(1, sizeof(afl_state_t));
+
if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
@@ -1380,6 +1451,26 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (in_dir) {
+
+ afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+ afl->afl_env.afl_custom_mutator_library =
+ getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
+ afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
+ setup_custom_mutators(afl);
+
+ } else {
+
+ if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
+
+ WARNF(
+ "Custom mutator environment detected, this is only supported in -i "
+ "mode!\n");
+
+ }
+
+ }
+
if (in_dir) {
DIR *dir_in, *dir_out = NULL;
--
cgit 1.4.1
From 0a297ed9ef48c1eaf69fdc13bd1016f8f29124be Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 21 Apr 2023 15:09:35 +0200
Subject: dummy function for afl-showmap
---
src/afl-showmap.c | 9 +++++++++
1 file changed, 9 insertions(+)
(limited to 'src')
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index b5a61de5..affad7d6 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -140,6 +140,15 @@ static void kill_child() {
}
+/* dummy function */
+u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
+
+ (void)afl;
+ (void)mem;
+ return a + b;
+
+}
+
static void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
--
cgit 1.4.1
From 7a8d0a10ce25d20bdd2021920b0b5ebbc0d3f3a6 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 21 Apr 2023 15:21:11 +0200
Subject: add dummy functions to afl-showmap for old gcc compilers
---
src/afl-showmap.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index affad7d6..0b9fc211 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -140,7 +140,7 @@ static void kill_child() {
}
-/* dummy function */
+/* dummy functions */
u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
(void)afl;
@@ -149,7 +149,30 @@ u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
}
-static void classify_counts(afl_forkserver_t *fsrv) {
+void show_stats(afl_state_t *afl) {
+
+ (void)afl;
+
+}
+
+void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
+
+ (void)afl;
+ (void)q;
+
+}
+
+fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
+ u32 i) {
+
+ (void)afl;
+ (void)fsrv;
+ (void)i;
+ return 0;
+
+}
+
+void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human;
--
cgit 1.4.1
From 779a72ef8c2457430b824f7830eba731745fb6ee Mon Sep 17 00:00:00 2001
From: Maik Betka <9078425+voidptr127@users.noreply.github.com>
Date: Fri, 21 Apr 2023 16:46:15 +0200
Subject: fixed AFL_POST_PROCESS_KEEP_ORIGINAL for version 4.07a
---
src/afl-fuzz-run.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 2d53de93..ac4fb4a9 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -133,14 +133,22 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
}
- if (new_mem != *mem && new_mem != NULL && new_size > 0
- && !afl->afl_env.afl_post_process_keep_original) {
+ if (new_mem != *mem && new_mem != NULL && new_size > 0) {
- u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
- if (unlikely(!new_buf)) { PFATAL("alloc"); }
- *mem = new_buf;
- memcpy(*mem, new_mem, new_size);
- afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+ memcpy(new_buf, new_mem, new_size);
+
+ /* if AFL_POST_PROCESS_KEEP_ORIGINAL is set then save the original memory
+ prior post-processing in new_mem to restore it later */
+ if (unlikely(afl->afl_env.afl_post_process_keep_original)) {
+
+ new_mem = *mem;
+
+ }
+
+ *mem = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
}
@@ -162,17 +170,19 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
if (likely(!sent)) {
/* everything as planned. use the potentially new data. */
+ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
if (likely(!afl->afl_env.afl_post_process_keep_original)) {
- afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
+ len = new_size;
} else {
- afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
+ /* restore the original memory which was saved in new_mem */
+ *mem = new_mem;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
}
- len = new_size;
}
--
cgit 1.4.1
From 228e9527cb0c00644e9601afc0449c586b468576 Mon Sep 17 00:00:00 2001
From: Maik Betka <9078425+voidptr127@users.noreply.github.com>
Date: Fri, 21 Apr 2023 17:19:37 +0200
Subject: fixed formatting with make code-format
---
src/afl-fuzz-state.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index cccebeb9..5e736029 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -396,10 +396,10 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
} else if (!strncmp(env, "AFL_POST_PROCESS_KEEP_ORIGINAL",
- afl_environment_variable_len)) {
+ afl_environment_variable_len)) {
- afl->afl_env.afl_post_process_keep_original =
- get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ afl->afl_env.afl_post_process_keep_original =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_TMPDIR",
--
cgit 1.4.1
From 599b4631a3a40930e54e103f8ad1a69499fd1c8b Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sat, 22 Apr 2023 11:31:21 +0200
Subject: typo
---
src/afl-fuzz.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index f6628851..394f33f9 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -326,7 +326,7 @@ static void usage(u8 *argv0, int more_help) {
}
#ifdef USE_PYTHON
- SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
+ SAYF("Compiled with %s module support, see docs/custom_mutators.md\n",
(char *)PYTHON_VERSION);
#else
SAYF("Compiled without Python module support.\n");
--
cgit 1.4.1
From 8c228b0d23e303499dccf3df77c5d0b3a8b59b7b Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Mon, 24 Apr 2023 18:08:27 +0200
Subject: afl-showmap -I option
---
afl-cmin | 2 +-
docs/Changelog.md | 1 +
src/afl-showmap.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 156 insertions(+), 22 deletions(-)
(limited to 'src')
diff --git a/afl-cmin b/afl-cmin
index e2c26d91..6b36c261 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -234,7 +234,7 @@ BEGIN {
} # while options
if (!mem_limit) mem_limit = "none"
- if (!timeout) timeout = "none"
+ if (!timeout) timeout = "5000"
# get program args
i = 0
diff --git a/docs/Changelog.md b/docs/Changelog.md
index f33acff9..d4e68036 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -9,6 +9,7 @@
data before post process on finds
- afl-showmap:
- added custom mutator post_process and send support
+ - add `-I filelist` option, an alternative to `-i in_dir`
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 0b9fc211..09a1d2dc 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -69,7 +69,9 @@ static afl_state_t *afl;
static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
- *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
+ *out_file = NULL, /* output file or directory */
+ *at_file = NULL, /* Substitution string for @@ */
+ *in_filelist = NULL; /* input file list */
static u8 outfile[PATH_MAX];
@@ -878,6 +880,104 @@ u32 execute_testcases(u8 *dir) {
}
+u32 execute_testcases_filelist(u8 *fn) {
+
+ u32 done = 0;
+ u8 buf[4096];
+ u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
+ FILE *f;
+
+ if (!be_quiet) { ACTF("Reading from '%s'...", fn); }
+
+ if ((f = fopen(fn, "r")) == NULL) { FATAL("could not open '%s'", fn); }
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+
+ struct stat st;
+
+ u8 *fn2 = buf, *fn3;
+ ;
+
+ while (*fn2 == ' ') {
+
+ ++fn2;
+
+ }
+
+ if (*fn2) {
+
+ while (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
+ fn2[strlen(fn2) - 1] == ' ') {
+
+ fn2[strlen(fn2) - 1] = 0;
+
+ }
+
+ }
+
+ if (debug) { printf("Getting coverage for '%s'\n", fn2); }
+
+ if (!*fn2) { continue; }
+
+ if (lstat(fn2, &st) || access(fn2, R_OK)) {
+
+ WARNF("Unable to access '%s'", fn2);
+ continue;
+
+ }
+
+ if (!S_ISREG(st.st_mode) || !st.st_size) { continue; }
+
+ if ((fn3 = strrchr(fn2, '/'))) {
+
+ ++fn3;
+
+ } else {
+
+ fn3 = fn2;
+
+ }
+
+ if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) {
+
+ WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
+ stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
+ stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
+
+ }
+
+ if (!collect_coverage)
+ snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3);
+
+ if (read_file(fn2)) {
+
+ if (wait_for_gdb) {
+
+ fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
+ fprintf(stderr, "exec: kill -CONT %d\n", getpid());
+ kill(0, SIGSTOP);
+
+ }
+
+ showmap_run_target_forkserver(fsrv, in_data, in_len);
+ ck_free(in_data);
+ ++done;
+
+ if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
+
+ if (collect_coverage)
+ analyze_results(fsrv);
+ else
+ tcnt = write_results_to_file(fsrv, outfile);
+
+ }
+
+ }
+
+ return done;
+
+}
+
/* Show banner. */
static void show_banner(void) {
@@ -920,6 +1020,7 @@ static void usage(u8 *argv0) {
" With -C, -o is a file, without -C it must be a "
"directory\n"
" and each bitmap will be written there individually.\n"
+ " -I filelist - alternatively to -i, -I is a list of files\n"
" -C - collect coverage, writes all edges to -o and gives a "
"summary\n"
" Must be combined with -i.\n"
@@ -932,7 +1033,7 @@ static void usage(u8 *argv0) {
"This tool displays raw tuple data captured by AFL instrumentation.\n"
"For additional help, consult %s/README.md.\n\n"
- "If you use -i mode, then custom mutator post_process send send "
+ "If you use -i/-I mode, then custom mutator post_process send send "
"functionality\n"
"is supported.\n\n"
@@ -994,7 +1095,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:I:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
switch (opt) {
@@ -1012,6 +1113,11 @@ int main(int argc, char **argv_orig, char **envp) {
in_dir = optarg;
break;
+ case 'I':
+ if (in_filelist) { FATAL("Multiple -I options not supported"); }
+ in_filelist = optarg;
+ break;
+
case 'o':
if (out_file) { FATAL("Multiple -o options not supported"); }
@@ -1234,10 +1340,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !out_file) { usage(argv[0]); }
- if (in_dir) {
+ if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
+
+ if (in_dir || in_filelist) {
if (!out_file && !collect_coverage)
- FATAL("for -i you need to specify either -C and/or -o");
+ FATAL("for -i/-I you need to specify either -C and/or -o");
}
@@ -1294,7 +1402,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (in_dir) {
+ if (in_dir || in_filelist) {
/* If we don't have a file name chosen yet, use a safe default. */
u8 *use_dir = ".";
@@ -1400,7 +1508,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
#ifdef __linux__
- if (!fsrv->nyx_mode && in_dir) {
+ if (!fsrv->nyx_mode && (in_dir || in_filelist)) {
(void)check_binary_signatures(fsrv->target_path);
@@ -1483,7 +1591,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (in_dir) {
+ if (in_dir || in_filelist) {
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
afl->afl_env.afl_custom_mutator_library =
@@ -1496,33 +1604,46 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
WARNF(
- "Custom mutator environment detected, this is only supported in -i "
- "mode!\n");
+ "Custom mutator environment detected, this is only supported in "
+ "-i/-I mode!\n");
}
}
- if (in_dir) {
+ if (in_dir || in_filelist) {
DIR *dir_in, *dir_out = NULL;
+ u8 *dn = NULL;
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
- // if a queue subdirectory exists switch to that
- u8 *dn = alloc_printf("%s/queue", in_dir);
- if ((dir_in = opendir(dn)) != NULL) {
+ if (in_filelist) {
+
+ if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
+
+ } else {
+
+ // if a queue subdirectory exists switch to that
+ dn = alloc_printf("%s/queue", in_dir);
+
+ if ((dir_in = opendir(dn)) != NULL) {
+
+ closedir(dir_in);
+ in_dir = dn;
+
+ } else {
+
+ ck_free(dn);
- closedir(dir_in);
- in_dir = dn;
+ }
- } else
+ if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
- ck_free(dn);
- if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
+ }
if (!collect_coverage) {
@@ -1576,9 +1697,21 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
- if (execute_testcases(in_dir) == 0) {
+ if (in_dir) {
+
+ if (execute_testcases(in_dir) == 0) {
+
+ FATAL("could not read input testcases from %s", in_dir);
+
+ }
+
+ } else {
- FATAL("could not read input testcases from %s", in_dir);
+ if (execute_testcases_filelist(in_filelist) == 0) {
+
+ FATAL("could not read input testcases from %s", in_filelist);
+
+ }
}
--
cgit 1.4.1
From 7c3c0b26d1ae477fbae6944c0de18256621e1993 Mon Sep 17 00:00:00 2001
From: Keno Hassler <40292329+kenohassler@users.noreply.github.com>
Date: Mon, 24 Apr 2023 20:21:54 +0200
Subject: document new env var
---
docs/env_variables.md | 6 ++++--
src/afl-cc.c | 2 ++
2 files changed, 6 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/docs/env_variables.md b/docs/env_variables.md
index c5995d13..087ccdb7 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -156,7 +156,7 @@ Available options:
- LTO - LTO instrumentation
- NATIVE - clang's original pcguard based instrumentation
- NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
- - PCGUARD - our own pcgard based instrumentation (default)
+ - PCGUARD - our own pcguard based instrumentation (default)
#### CMPLOG
@@ -240,7 +240,9 @@ combined.
the default `0x10000`. A value of 0 or empty sets the map address to be
dynamic (the original AFL way, which is slower).
- `AFL_LLVM_MAP_DYNAMIC` sets the shared memory address to be dynamic.
-
+ - `AFL_LLVM_LTO_SKIPINIT` skips adding initialization code. Some global vars
+ (e.g. the highest location ID) are not injected. Needed to instrument with
+ [WAFL](https://github.com/fgsect/WAFL.git).
For more information, see
[instrumentation/README.lto.md](../instrumentation/README.lto.md).
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 7f15ad76..d1001187 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -2099,6 +2099,8 @@ int main(int argc, char **argv, char **envp) {
"bb\n"
" AFL_REAL_LD: use this lld linker instead of the compiled in "
"path\n"
+ " AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
+ "(used in WAFL mode)\n"
"If anything fails - be sure to read README.lto.md!\n");
#endif
--
cgit 1.4.1
From c0ecf7cf61fdca901b041d57e7e2bb78bc8fcf80 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 25 Apr 2023 08:33:51 +0200
Subject: only reverse reading the queue on restart
---
docs/Changelog.md | 4 ++++
src/afl-fuzz-init.c | 30 ++++++++++++++++++++----------
2 files changed, 24 insertions(+), 10 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index d4e68036..14323ae0 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -7,6 +7,10 @@
- afl-fuzz:
- new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal
data before post process on finds
+ - reverse reading the seeds only on restarts
+ - afl-cc:
+ - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
+ (https://github.com/fgsect/WAFL) project
- afl-showmap:
- added custom mutator post_process and send support
- add `-I filelist` option, an alternative to `-i in_dir`
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 01d1e82e..002a26f8 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -718,10 +718,21 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
if (nl_cnt) {
- i = nl_cnt;
+ u32 done = 0;
+
+ if (unlikely(afl->in_place_resume)) {
+
+ i = nl_cnt;
+
+ } else {
+
+ i = 0;
+
+ }
+
do {
- --i;
+ if (unlikely(afl->in_place_resume)) { --i; }
struct stat st;
u8 dfn[PATH_MAX];
@@ -801,18 +812,17 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
- /*
- if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ if (unlikely(afl->in_place_resume)) {
- u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
- HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
- afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
+ if (unlikely(i == 0)) { done = 1; }
- }
+ } else {
+
+ if (unlikely(++i == (u32)nl_cnt)) { done = 1; }
- */
+ }
- } while (i > 0);
+ } while (!done);
}
--
cgit 1.4.1
From bc969f78f634035abf88bc73a5076848660901e7 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 25 Apr 2023 11:56:50 +0200
Subject: fixes
---
afl-cmin.bash | 9 +++++++--
src/afl-fuzz-init.c | 7 ++++---
2 files changed, 11 insertions(+), 5 deletions(-)
(limited to 'src')
diff --git a/afl-cmin.bash b/afl-cmin.bash
index ba7083fa..0e2d973d 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -316,12 +316,16 @@ if [ ! "$T_ARG" = "" ]; then
if [ "$T_ARG" = "all" ]; then
THREADS=$(nproc)
else
- if [ "$T_ARG" -gt 0 -a "$T_ARG" -le "$(nproc)" ]; then
+ if [ "$T_ARG" -gt 1 -a "$T_ARG" -le "$(nproc)" ]; then
THREADS=$T_ARG
else
- echo "[-] Error: -T parameter must between 1 and $(nproc) or \"all\"." 1>&2
+ echo "[-] Error: -T parameter must between 2 and $(nproc) or \"all\"." 1>&2
fi
fi
+else
+ if [ "$F_ARG" = ""]; then
+ echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?"
+ fi
fi
IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`))
@@ -332,6 +336,7 @@ if [ "$IN_COUNT" = "0" ]; then
exit 1
fi
+echo "[*] Are you aware that afl-cmin is faster than this afl-cmin.bash script?"
echo "[+] Found $IN_COUNT files for minimizing."
FIRST_FILE=`ls "$IN_DIR" | head -1`
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 002a26f8..bd591c8f 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -756,7 +756,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
free(nl[i]); /* not tracked */
read_testcases(afl, fn2);
ck_free(fn2);
- continue;
+ goto next_entry;
}
@@ -765,7 +765,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
ck_free(fn2);
- continue;
+ goto next_entry;
}
@@ -812,13 +812,14 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
+ next_entry:
if (unlikely(afl->in_place_resume)) {
if (unlikely(i == 0)) { done = 1; }
} else {
- if (unlikely(++i == (u32)nl_cnt)) { done = 1; }
+ if (unlikely(++i >= (u32)nl_cnt)) { done = 1; }
}
--
cgit 1.4.1
From d822181467ec41f1ee2d840c3c5b1918c72ffc86 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 25 Apr 2023 13:13:43 +0200
Subject: afl-cmin -T support
---
afl-cmin | 143 ++++++++++++++++++++++++++++++++++++++++++------------
docs/Changelog.md | 2 +-
src/afl-showmap.c | 23 +++++----
3 files changed, 124 insertions(+), 44 deletions(-)
(limited to 'src')
diff --git a/afl-cmin b/afl-cmin
index 6b36c261..c8bbd8d7 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -103,9 +103,10 @@ function usage() {
" -o dir - output directory for minimized files\n" \
"\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" \
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
-" -t msec - run time limit for child process (default: none)\n" \
+" -t msec - run time limit for child process (default: 5000)\n" \
" -O - use binary-only instrumentation (FRIDA mode)\n" \
" -Q - use binary-only instrumentation (QEMU mode)\n" \
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
@@ -119,7 +120,6 @@ function usage() {
"For additional tips, please consult README.md\n" \
"\n" \
"Environment variables used:\n" \
-"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
"AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \
@@ -159,13 +159,19 @@ BEGIN {
# process options
Opterr = 1 # default is to diagnose
Optind = 1 # skip ARGV[0]
- while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXY?")) != -1) {
+ while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXYT:?")) != -1) {
if (_go_c == "i") {
if (!Optarg) usage()
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
in_dir = Optarg
continue
} else
+ if (_go_c == "T") {
+ if (!Optarg) usage()
+ if (threads) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
+ threads = Optarg
+ continue
+ } else
if (_go_c == "o") {
if (!Optarg) usage()
if (out_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -253,21 +259,30 @@ BEGIN {
# Do a sanity check to discourage the use of /tmp, since we can't really
# handle this safely from an awk script.
- if (!ENVIRON["AFL_ALLOW_TMP"]) {
- dirlist[0] = in_dir
- dirlist[1] = target_bin
- dirlist[2] = out_dir
- dirlist[3] = stdin_file
- "pwd" | getline dirlist[4] # current directory
- for (dirind in dirlist) {
- dir = dirlist[dirind]
-
- if (dir ~ /^(\/var)?\/tmp/) {
- print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr"
- exit 1
- }
- }
- delete dirlist
+ #if (!ENVIRON["AFL_ALLOW_TMP"]) {
+ # dirlist[0] = in_dir
+ # dirlist[1] = target_bin
+ # dirlist[2] = out_dir
+ # dirlist[3] = stdin_file
+ # "pwd" | getline dirlist[4] # current directory
+ # for (dirind in dirlist) {
+ # dir = dirlist[dirind]
+ #
+ # if (dir ~ /^(\/var)?\/tmp/) {
+ # print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr"
+ # exit 1
+ # }
+ # }
+ # delete dirlist
+ #}
+
+ if (threads && stdin_file) {
+ print "[-] Error: -T and -f cannot be used together." > "/dev/stderr"
+ exit 1
+ }
+
+ if (!threads && !stdin_file) {
+ print "[*] Are you aware of the '-T all' parallelize option that massively improves the speed for large corpuses?"
}
# If @@ is specified, but there's no -f, let's come up with a temporary input
@@ -350,6 +365,18 @@ BEGIN {
exit 1
}
+ if (threads) {
+ "nproc" | getline nproc
+ if (threads == "all") {
+ threads = nproc
+ } else {
+ if (!(threads > 1 && threads <= nproc)) {
+ print "[-] Error: -T option must be between 1 and "nproc" or \"all\"." > "/dev/stderr"
+ exit 1
+ }
+ }
+ }
+
# Check for the more efficient way to copy files...
if (0 != system("mkdir -p -m 0700 "trace_dir)) {
print "[-] Error: Cannot create directory "trace_dir > "/dev/stderr"
@@ -459,27 +486,81 @@ BEGIN {
# STEP 1: Collecting traces #
#############################
+ if (threads) {
+
+ inputsperfile = in_count / threads
+ if (in_count % threads) {
+ inputsperfile++;
+ }
+
+ cnt = 0;
+ tmpfile=out_dir "/.filelist"
+ for (instance = 1; instance < threads; instance++) {
+ for (i = 0; i < inputsperfile; i++) {
+ print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."instance
+ cnt++
+ }
+ }
+ for (; cnt < in_count; cnt++) {
+ print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."threads
+ }
+
+ print "ls -l "tmpfile"*"
+
+ }
+
print "[*] Obtaining traces for "in_count" input files in '"in_dir"'."
cur = 0;
- if (!stdin_file) {
- print " Processing "in_count" files (forkserver mode)..."
-# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
- retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
+
+ if (threads > 1) {
+
+ print "[*] Creating " threads " parallel tasks with about " inputsperfile " each."
+ for (i = 1; i <= threads; i++) {
+
+ if (!stdin_file) {
+# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &"
+ retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &")
+ } else {
+ stdin_file=tmpfile"."i".stdin"
+# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" "tmpfile"."i".done ; } &"
+ retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" "tmpfile"."i".done ; } &")
+ }
+ }
+ print "[*] Waiting for parallel tasks to complete ..."
+ # wait for all processes to finish
+ ok=0
+ while (ok < threads) {
+ ok=0
+ for (i = 1; i <= threads; i++) {
+ if (system("test -f "tmpfile"."i".done") == 0) {
+ ok++
+ }
+ }
+ }
+ print "[*] Done!"
+ system("rm -f "tmpfile"*")
} else {
- print " Processing "in_count" files (forkserver mode)..."
+ if (!stdin_file) {
+ print " Processing "in_count" files (forkserver mode)..."
+# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
+ retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
+ } else {
+ print " Processing "in_count" files (forkserver mode)..."
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" /dev/null")
- system("rmdir "out_dir)
+ if (!ENVIRON["AFL_KEEP_TRACES"]) {
+ system("rm -rf "trace_dir" 2>/dev/null")
+ system("rmdir "out_dir)
+ }
+ exit retval
}
- exit retval
+
}
#######################################################
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 816a864d..667fd634 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -14,7 +14,7 @@
- afl-showmap:
- added custom mutator post_process and send support
- add `-I filelist` option, an alternative to `-i in_dir`
- - afl-cmin.bash:
+ - afl-cmin + afl-cmin.bash:
- `-T threads` parallel task support, huge speedup!
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 09a1d2dc..d0e01cb1 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -894,9 +894,7 @@ u32 execute_testcases_filelist(u8 *fn) {
while (fgets(buf, sizeof(buf), f) != NULL) {
struct stat st;
-
- u8 *fn2 = buf, *fn3;
- ;
+ u8 *fn2 = buf, *fn3;
while (*fn2 == ' ') {
@@ -904,14 +902,11 @@ u32 execute_testcases_filelist(u8 *fn) {
}
- if (*fn2) {
-
- while (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
- fn2[strlen(fn2) - 1] == ' ') {
-
- fn2[strlen(fn2) - 1] = 0;
+ while (*fn2 &&
+ (fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
+ fn2[strlen(fn2) - 1] == ' ')) {
- }
+ fn2[strlen(fn2) - 1] = 0;
}
@@ -926,6 +921,8 @@ u32 execute_testcases_filelist(u8 *fn) {
}
+ ++done;
+
if (!S_ISREG(st.st_mode) || !st.st_size) { continue; }
if ((fn3 = strrchr(fn2, '/'))) {
@@ -946,9 +943,12 @@ u32 execute_testcases_filelist(u8 *fn) {
}
- if (!collect_coverage)
+ if (!collect_coverage) {
+
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3);
+ }
+
if (read_file(fn2)) {
if (wait_for_gdb) {
@@ -961,7 +961,6 @@ u32 execute_testcases_filelist(u8 *fn) {
showmap_run_target_forkserver(fsrv, in_data, in_len);
ck_free(in_data);
- ++done;
if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
--
cgit 1.4.1
From 21865c622483d2e2285de3dfad4626c28ca27843 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 25 Apr 2023 16:47:37 +0200
Subject: rename env to AFL_IGNORE_PROBLEMS_COVERAGE
---
docs/FAQ.md | 3 ++-
docs/env_variables.md | 3 ++-
include/envs.h | 1 +
instrumentation/afl-compiler-rt.o.c | 4 ++--
src/afl-fuzz.c | 2 ++
5 files changed, 9 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/docs/FAQ.md b/docs/FAQ.md
index 4a9080f8..76350c79 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -229,7 +229,8 @@ If you find an interesting or important question missing, submit it via
If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then
the existing map will be used also for the newly loaded libraries, which
allows it to work, however, the efficiency of the fuzzing will be partially
- degraded.
+ degraded. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to
+ additionally tell AFL++ to ignore any coverage from the late loaded libaries.
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 087ccdb7..b1f23159 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -406,7 +406,8 @@ checks or alter some of the more exotic semantics of the tool:
- If afl-fuzz encounters an incorrect fuzzing setup during a fuzzing session
(not at startup), it will terminate. If you do not want this, then you can
- set `AFL_IGNORE_PROBLEMS`.
+ set `AFL_IGNORE_PROBLEMS`. If you additionally want to also ignore coverage
+ from late loaded libraries, you can set `AFL_IGNORE_PROBLEMS_COVERAGE`.
- When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the
fuzzer to import test cases from other instances before doing anything else.
diff --git a/include/envs.h b/include/envs.h
index 5e68c80b..fe5ee0e3 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -106,6 +106,7 @@ static char *afl_environment_variables[] = {
"AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
"AFL_IGNORE_PROBLEMS",
+ "AFL_IGNORE_PROBLEMS_COVERAGE",
"AFL_IGNORE_TIMEOUTS",
"AFL_IGNORE_UNKNOWN_ENVS",
"AFL_IMPORT_FIRST",
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 74506e4c..0912e52b 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -1565,13 +1565,13 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
"be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n"
"To ignore this set AFL_IGNORE_PROBLEMS=1 but this will lead to "
"ambiguous coverage data.\n"
- "In addition, you can set AFL_LLVM_IGNORE_PROBLEMS_COVERAGE=1 to "
+ "In addition, you can set AFL_IGNORE_PROBLEMS_COVERAGE=1 to "
"ignore the additional coverage instead (use with caution!).\n");
abort();
} else {
- u8 ignore_dso_after_fs = !!getenv("AFL_LLVM_IGNORE_PROBLEMS_COVERAGE");
+ u8 ignore_dso_after_fs = !!getenv("AFL_IGNORE_PROBLEMS_COVERAGE");
if (__afl_debug && ignore_dso_after_fs) {
fprintf(stderr, "Ignoring coverage from dynamically loaded code\n");
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index ebdbb3fa..c44144f5 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -259,6 +259,8 @@ static void usage(u8 *argv0, int more_help) {
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
+ "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n
+ " ignore those libs for coverage\n"
"AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
--
cgit 1.4.1
From 96848398d45e08eaa69be245c986375808d2b3a7 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 25 Apr 2023 17:56:36 +0200
Subject: fix
---
src/afl-fuzz.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index c44144f5..71d2afd8 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -259,7 +259,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
- "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n
+ "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n"
" ignore those libs for coverage\n"
"AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
--
cgit 1.4.1
From 3e84d6a2ae7df5f6b9073a91ccc6acef50b45aab Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 27 Apr 2023 11:49:00 +0200
Subject: afl++ -> AFL++
---
Dockerfile | 4 ++--
GNUmakefile | 12 ++++++------
GNUmakefile.gcc_plugin | 6 +++---
GNUmakefile.llvm | 6 +++---
afl-cmin | 2 +-
docs/Changelog.md | 2 +-
docs/INSTALL.md | 2 +-
include/alloc-inl.h | 2 +-
instrumentation/SanitizerCoverageLTO.so.cc | 30 +++++++++++++++---------------
instrumentation/afl-llvm-common.cc | 2 +-
instrumentation/afl-llvm-dict2file.so.cc | 2 +-
qemu_mode/build_qemu_support.sh | 4 ++--
src/afl-cc.c | 2 +-
src/afl-forkserver.c | 6 +++---
src/afl-fuzz.c | 10 +++++-----
src/afl-ld-lto.c | 4 ++--
test/test-dlopen.c | 2 +-
test/test-gcc-plugin.sh | 2 +-
test/test-performance.sh | 4 ++--
test/test-pre.sh | 2 +-
unicorn_mode/build_unicorn_support.sh | 2 +-
21 files changed, 54 insertions(+), 54 deletions(-)
(limited to 'src')
diff --git a/Dockerfile b/Dockerfile
index 4e53de40..1b5ffd28 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,7 +6,7 @@
#
FROM ubuntu:22.04 AS aflplusplus
-LABEL "maintainer"="afl++ team "
+LABEL "maintainer"="AFL++ team "
LABEL "about"="AFLplusplus container image"
### Comment out to enable these features
@@ -94,4 +94,4 @@ RUN sed -i.bak 's/^ -/ /g' GNUmakefile && \
RUN echo "set encoding=utf-8" > /root/.vimrc && \
echo ". /etc/bash_completion" >> ~/.bashrc && \
echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc && \
- echo "export PS1='"'[afl++ \h] \w \$ '"'" >> ~/.bashrc
+ echo "export PS1='"'[AFL++ \h] \w \$ '"'" >> ~/.bashrc
diff --git a/GNUmakefile b/GNUmakefile
index 23cae65d..5900ad61 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -39,7 +39,7 @@ ASAN_OPTIONS=detect_leaks=0
SYS = $(shell uname -s)
ARCH = $(shell uname -m)
-$(info [*] Compiling afl++ for OS $(SYS) on ARCH $(ARCH))
+$(info [*] Compiling AFL++ for OS $(SYS) on ARCH $(ARCH))
ifdef NO_SPLICING
override CFLAGS_OPT += -DNO_SPLICING
@@ -359,7 +359,7 @@ performance-test: source-only
help:
@echo "HELP --- the following make targets exist:"
@echo "=========================================="
- @echo "all: the main afl++ binaries and llvm/gcc instrumentation"
+ @echo "all: the main AFL++ binaries and llvm/gcc instrumentation"
@echo "binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
@echo "source-only: everything for source code fuzzing: nyx_mode, libdislocator, libtokencap"
@echo "distrib: everything (for both binary-only and source code fuzzing)"
@@ -367,7 +367,7 @@ help:
@echo "install: installs everything you have compiled with the build option above"
@echo "clean: cleans everything compiled (not downloads when on a checkout)"
@echo "deepclean: cleans everything including downloads"
- @echo "uninstall: uninstall afl++ from the system"
+ @echo "uninstall: uninstall AFL++ from the system"
@echo "code-format: format the code, do this before you commit and send a PR please!"
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
@echo "unit: perform unit tests (based on cmocka and GNU linker)"
@@ -749,7 +749,7 @@ endif
@echo
%.8: %
- @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
+ @echo .TH $* 8 $(BUILD_DATE) "AFL++" > $@
@echo .SH NAME >> $@
@echo .B $* >> $@
@echo >> $@
@@ -761,8 +761,8 @@ endif
@./$* -hh 2>&1 | tail -n +4 >> $@
@echo >> $@
@echo .SH AUTHOR >> $@
- @echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Heiko \"hexcoder-\" Eissfeldt , Andrea Fioraldi and Dominik Maier " >> $@
- @echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
+ @echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Dominik Maier , Andrea Fioraldi and Heiko \"hexcoder-\" Eissfeldt " >> $@
+ @echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
@echo >> $@
@echo .SH LICENSE >> $@
@echo Apache License Version 2.0, January 2004 >> $@
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index 4c4e10c4..41face4c 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -175,7 +175,7 @@ all_done: test_build
.NOTPARALLEL: clean
%.8: %
- @echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ./$@
+ @echo .TH $* 8 `date "+%Y-%m-%d"` "AFL++" > ./$@
@echo .SH NAME >> ./$@
@echo .B $* >> ./$@
@echo >> ./$@
@@ -187,8 +187,8 @@ all_done: test_build
@./$* -h 2>&1 | tail -n +4 >> ./$@
@echo >> ./$@
@echo .SH AUTHOR >> ./$@
- @echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Heiko \"hexcoder-\" Eissfeldt , Andrea Fioraldi and Dominik Maier " >> ./$@
- @echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
+ @echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Dominik Maier , Andrea Fioraldi and Heiko \"hexcoder-\" Eissfeldt " >> ./$@
+ @echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo >> ./$@
@echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index a053403b..c1b006ba 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -510,7 +510,7 @@ install: all
install -m 644 instrumentation/README.*.md $${DESTDIR}$(DOC_PATH)/
%.8: %
- @echo .TH $* 8 $(BUILD_DATE) "afl++" > ./$@
+ @echo .TH $* 8 $(BUILD_DATE) "AFL++" > ./$@
@echo .SH NAME >> ./$@
@printf "%s" ".B $* \- " >> ./$@
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ./$@
@@ -524,8 +524,8 @@ install: all
@./$* -h 2>&1 | tail -n +4 >> ./$@
@echo >> ./$@
@echo .SH AUTHOR >> ./$@
- @echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Heiko \"hexcoder-\" Eissfeldt , Andrea Fioraldi and Dominik Maier " >> ./$@
- @echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
+ @echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Dominik Maier , Andrea Fioraldi and Heiko \"hexcoder-\" Eissfeldt " >> ./$@
+ @echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo >> ./$@
@echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@
diff --git a/afl-cmin b/afl-cmin
index 63cfdd7e..ae723c1b 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -149,7 +149,7 @@ BEGIN {
redirected = 0
}
- print "corpus minimization tool for afl++ (awk version)\n"
+ print "corpus minimization tool for AFL++ (awk version)\n"
# defaults
extra_par = ""
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 20b915fa..cd5ed9fc 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -229,7 +229,7 @@
afl-showmap and other tools.
- afl-cc:
- detect overflow reads on initial input buffer for asan
- - new cmplog mode (incompatible with older afl++ versions)
+ - new cmplog mode (incompatible with older AFL++ versions)
- support llvm IR select instrumentation for default PCGUARD and LTO
- fix for shared linking on MacOS
- better selective instrumentation AFL_LLVM_{ALLOW|DENY}LIST
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 591b7ded..c54cb9ad 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -51,7 +51,7 @@ make source-only
These build targets exist:
-* all: the main afl++ binaries and llvm/gcc instrumentation
+* all: the main AFL++ binaries and llvm/gcc instrumentation
* binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode,
qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator,
libtokencap
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index ae37028e..bbb42e88 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -42,7 +42,7 @@
// Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators
#ifndef _WANT_ORIGINAL_AFL_ALLOC
- // afl++ stuff without memory corruption checks - for speed
+ // AFL++ stuff without memory corruption checks - for speed
/* User-facing macro to sprintf() to a dynamically allocated buffer. */
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 42583f9e..6a719737 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -1,4 +1,4 @@
-/* SanitizeCoverage.cpp ported to afl++ LTO :-) */
+/* SanitizeCoverage.cpp ported to AFL++ LTO :-) */
#define AFL_LLVM_PASS
@@ -234,7 +234,7 @@ class ModuleSanitizerCoverageLTO
SanitizerCoverageOptions Options;
- // afl++ START
+ // AFL++ START
// const SpecialCaseList * Allowlist;
// const SpecialCaseList * Blocklist;
uint32_t autodictionary = 1;
@@ -260,7 +260,7 @@ class ModuleSanitizerCoverageLTO
Value *MapPtrFixed = NULL;
std::ofstream dFile;
size_t found = 0;
- // afl++ END
+ // AFL++ END
};
@@ -404,7 +404,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
- /* afl++ START */
+ /* AFL++ START */
char *ptr;
LLVMContext &Ctx = M.getContext();
Ct = &Ctx;
@@ -978,7 +978,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
- // afl++ END
+ // AFL++ END
SanCovTracePCIndir =
M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy);
@@ -1002,7 +1002,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
for (auto &F : M)
instrumentFunction(F, DTCallback, PDTCallback);
- // afl++ START
+ // AFL++ START
if (dFile.is_open()) dFile.close();
if (!getenv("AFL_LLVM_LTO_SKIPINIT") &&
@@ -1156,7 +1156,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
- // afl++ END
+ // AFL++ END
// We don't reference these arrays directly in any of our runtime functions,
// so we need to prevent them from being dead stripped.
@@ -1213,10 +1213,10 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
// (catchswitch blocks).
if (BB->getFirstInsertionPt() == BB->end()) return false;
- // afl++ START
+ // AFL++ START
if (!Options.NoPrune && &F.getEntryBlock() == BB && F.size() > 1)
return false;
- // afl++ END
+ // AFL++ END
if (Options.NoPrune || &F.getEntryBlock() == BB) return true;
@@ -1258,10 +1258,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
// if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
// return;
- // afl++ START
+ // AFL++ START
if (!F.size()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
- // afl++ END
+ // AFL++ END
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(
@@ -1559,7 +1559,7 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
- // afl++ START
+ // AFL++ START
if (BlockList.size()) {
int skip = 0;
@@ -1581,7 +1581,7 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
}
- // afl++ END
+ // AFL++ END
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
@@ -1647,7 +1647,7 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
if (Options.TracePCGuard) {
- // afl++ START
+ // AFL++ START
++afl_global_id;
if (dFile.is_open()) {
@@ -1711,7 +1711,7 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
// done :)
inst++;
- // afl++ END
+ // AFL++ END
/*
XXXXXXXXXXXXXXXXXXX
diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc
index 5d82aa25..7f17b02d 100644
--- a/instrumentation/afl-llvm-common.cc
+++ b/instrumentation/afl-llvm-common.cc
@@ -584,7 +584,7 @@ bool isInInstrumentList(llvm::Function *F, std::string Filename) {
}
// Calculate the number of average collisions that would occur if all
-// location IDs would be assigned randomly (like normal afl/afl++).
+// location IDs would be assigned randomly (like normal afl/AFL++).
// This uses the "balls in bins" algorithm.
unsigned long long int calculateCollisions(uint32_t edges) {
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index 97f1d47f..cf368e35 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -744,7 +744,7 @@ static void registerAFLdict2filePass(const PassManagerBuilder &,
}
static RegisterPass X("afl-dict2file",
- "afl++ dict2file instrumentation pass",
+ "AFL++ dict2file instrumentation pass",
false, false);
static RegisterStandardPasses RegisterAFLdict2filePass(
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index a064fe58..f59cba78 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -356,7 +356,7 @@ fi
if ! command -v "$CROSS" > /dev/null ; then
if [ "$CPU_TARGET" = "$(uname -m)" ] ; then
- echo "[+] Building afl++ qemu support libraries with CC=$CC"
+ echo "[+] Building AFL++ qemu support libraries with CC=$CC"
echo "[+] Building libcompcov ..."
make -C libcompcov && echo "[+] libcompcov ready"
echo "[+] Building unsigaction ..."
@@ -371,7 +371,7 @@ if ! command -v "$CROSS" > /dev/null ; then
echo "[!] Cross compiler $CROSS could not be found, cannot compile libcompcov libqasan and unsigaction"
fi
else
- echo "[+] Building afl++ qemu support libraries with CC=\"$CROSS $CROSS_FLAGS\""
+ echo "[+] Building AFL++ qemu support libraries with CC=\"$CROSS $CROSS_FLAGS\""
echo "[+] Building libcompcov ..."
make -C libcompcov CC="$CROSS $CROSS_FLAGS" && echo "[+] libcompcov ready"
echo "[+] Building unsigaction ..."
diff --git a/src/afl-cc.c b/src/afl-cc.c
index d1001187..99ce39d4 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -642,7 +642,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
//#if LLVM_MAJOR >= 13
- // // Use the old pass manager in LLVM 14 which the afl++ passes still
+ // // Use the old pass manager in LLVM 14 which the AFL++ passes still
// use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
//#endif
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index aa8c8622..30c8901c 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -489,7 +489,7 @@ static void report_error_and_exit(int error) {
break;
case FS_ERROR_OLD_CMPLOG:
FATAL(
- "the -c cmplog target was instrumented with an too old afl++ "
+ "the -c cmplog target was instrumented with an too old AFL++ "
"version, you need to recompile it.");
break;
case FS_ERROR_OLD_CMPLOG_QEMU:
@@ -987,7 +987,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
- // workaround for recent afl++ versions
+ // workaround for recent AFL++ versions
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff);
@@ -1059,7 +1059,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
FATAL(
"Target's coverage map size of %u is larger than the one this "
- "afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
+ "AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
"afl-fuzz",
tmp_map_size, fsrv->map_size, tmp_map_size);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 71d2afd8..646dc50b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1280,16 +1280,16 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
- OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
- "Eißfeldt, Andrea Fioraldi and Dominik Maier");
- OKF("afl++ is open source, get it at "
+ OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
+ "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
+ OKF("AFL++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
- OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md");
+ OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
+ OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
}
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 5438bd9f..420dd817 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -2,7 +2,7 @@
american fuzzy lop++ - wrapper for llvm 11+ lld
-----------------------------------------------
- Written by Marc Heuse for afl++
+ Written by Marc Heuse for AFL++
Maintained by Marc Heuse ,
Heiko Eißfeldt
@@ -210,7 +210,7 @@ static void edit_params(int argc, char **argv) {
if (strcmp(argv[i], "--afl") == 0) {
- if (!be_quiet) OKF("afl++ test command line flag detected, exiting.");
+ if (!be_quiet) OKF("AFL++ test command line flag detected, exiting.");
exit(0);
}
diff --git a/test/test-dlopen.c b/test/test-dlopen.c
index b81bab13..39442f93 100644
--- a/test/test-dlopen.c
+++ b/test/test-dlopen.c
@@ -28,7 +28,7 @@ int main(int argc, char **argv) {
}
- // must use deferred forkserver as otherwise afl++ instrumentation aborts
+ // must use deferred forkserver as otherwise AFL++ instrumentation aborts
// because all dlopen() of instrumented libs must be before the forkserver
__AFL_INIT();
diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh
index 54e6987f..3690a80a 100755
--- a/test/test-gcc-plugin.sh
+++ b/test/test-gcc-plugin.sh
@@ -23,7 +23,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
$ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
} || {
$ECHO "$RED[!] gcc_plugin instrumentation produces a weird numbers: $TUPLES"
- $ECHO "$YELLOW[-] this is a known issue in gcc, not afl++. It is not flagged as an error because travis builds would all fail otherwise :-("
+ $ECHO "$YELLOW[-] this is a known issue in gcc, not AFL++. It is not flagged as an error because travis builds would all fail otherwise :-("
#CODE=1
}
test "$TUPLES" -lt 2 && SKIP=1
diff --git a/test/test-performance.sh b/test/test-performance.sh
index d61e2f2a..50957141 100755
--- a/test/test-performance.sh
+++ b/test/test-performance.sh
@@ -7,7 +7,7 @@ FILE=$AFL_PERFORMANCE_FILE
test -z "$FILE" && FILE=.afl_performance
test -e $FILE || {
- echo Warning: This script measure the performance of afl++ and saves the result for future comparisons into $FILE
+ echo Warning: This script measure the performance of AFL++ and saves the result for future comparisons into $FILE
echo Press ENTER to continue or CONTROL-C to abort
read IN
}
@@ -74,7 +74,7 @@ afl-system-config > /dev/null 2>&1
echo Performance settings applied.
echo
-$ECHO "${RESET}${GREY}[*] starting afl++ performance test framework ..."
+$ECHO "${RESET}${GREY}[*] starting AFL++ performance test framework ..."
$ECHO "$BLUE[*] Testing: ${AFL_GCC}"
GCC=x
diff --git a/test/test-pre.sh b/test/test-pre.sh
index b8b286e5..1ca9dfb5 100755
--- a/test/test-pre.sh
+++ b/test/test-pre.sh
@@ -133,7 +133,7 @@ MEM_LIMIT=none
export PATH="${PATH}:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
-$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
+$ECHO "${RESET}${GREY}[*] starting AFL++ test framework ..."
test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index 53ec2481..d3d16ad5 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -182,7 +182,7 @@ git pull
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
git checkout "$UNICORNAFL_VERSION" || exit 1
-echo "[*] making sure afl++ header files match"
+echo "[*] making sure AFL++ header files match"
cp "../../include/config.h" "./include" || exit 1
echo "[*] Configuring Unicorn build..."
--
cgit 1.4.1
From e983e2e9cfb9e4c8489dc35f28bca502ec241c27 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 27 Apr 2023 16:24:43 +0200
Subject: more debug
---
src/afl-fuzz-init.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index bd591c8f..baf56a5f 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -716,6 +716,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
+ // if (getenv("MYTEST")) afl->in_place_resume = 1;
+
if (nl_cnt) {
u32 done = 0;
@@ -827,6 +829,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
+ // if (getenv("MYTEST")) afl->in_place_resume = 0;
+
free(nl); /* not tracked */
if (!afl->queued_items && directory == NULL) {
@@ -908,8 +912,10 @@ void perform_dry_run(afl_state_t *afl) {
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
- SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST,
- q->len, q->bitmap_size, q->exec_us);
+ SAYF(cGRA
+ " len = %u, map size = %u, exec speed = %llu us, hash = "
+ "%016llx\n" cRST,
+ q->len, q->bitmap_size, q->exec_us, q->exec_cksum);
}
@@ -1164,14 +1170,14 @@ void perform_dry_run(afl_state_t *afl) {
u32 duplicates = 0, i;
- for (idx = 0; idx < afl->queued_items; idx++) {
+ for (idx = 0; idx < afl->queued_items - 1; idx++) {
q = afl->queue_buf[idx];
if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
-
u32 done = 0;
+
for (i = idx + 1;
- i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) {
+ likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) {
struct queue_entry *p = afl->queue_buf[i];
if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
@@ -1194,6 +1200,13 @@ void perform_dry_run(afl_state_t *afl) {
p->disabled = 1;
p->perf_score = 0;
+ if (afl->debug) {
+
+ WARNF("Same coverage - %s is kept active, %s is disabled.",
+ q->fname, p->fname);
+
+ }
+
} else {
if (!q->was_fuzzed) {
@@ -1207,7 +1220,14 @@ void perform_dry_run(afl_state_t *afl) {
q->disabled = 1;
q->perf_score = 0;
- done = 1;
+ if (afl->debug) {
+
+ WARNF("Same coverage - %s is kept active, %s is disabled.",
+ p->fname, q->fname);
+
+ }
+
+ done = 1; // end inner loop because outer loop entry is disabled now
}
--
cgit 1.4.1
From a2daef29f9c323c0a6a7a64013aadb79ffd3e534 Mon Sep 17 00:00:00 2001
From: van Hauser
Date: Thu, 27 Apr 2023 17:57:22 +0200
Subject: slightly different weighting algo (#1719)
* better seed selection
* slightly different weighting calculation
* remove unnecessary memset
---
include/afl-fuzz.h | 4 +--
src/afl-fuzz-queue.c | 92 +++++++++++++++++++++++++++++++++++-----------------
2 files changed, 65 insertions(+), 31 deletions(-)
(limited to 'src')
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 831a0dbc..8fb7ecb1 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -1223,7 +1223,7 @@ double rand_next_percent(afl_state_t *afl);
static inline u32 rand_below(afl_state_t *afl, u32 limit) {
- if (limit <= 1) return 0;
+ if (unlikely(limit <= 1)) return 0;
/* The boundary not being necessarily a power of 2,
we need to ensure the result uniformity. */
@@ -1256,7 +1256,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
expand havoc mode */
static inline u32 rand_below_datalen(afl_state_t *afl, u32 limit) {
- if (limit <= 1) return 0;
+ if (unlikely(limit <= 1)) return 0;
switch (rand_below(afl, 3)) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 8ad7cd97..b10bf749 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
u32 s = rand_below(afl, afl->queued_items);
double p = rand_next_percent(afl);
+
/*
fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u"
" ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p <
afl->alias_probability[s] ? s : afl->alias_table[s]);
*/
+
return (p < afl->alias_probability[s] ? s : afl->alias_table[s]);
}
@@ -87,25 +89,28 @@ 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, a, g;
+ u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1;
double sum = 0;
+ double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
+ u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
+ u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
+
afl->alias_table =
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
afl->alias_probability = (double *)afl_realloc(
(void **)&afl->alias_probability, n * sizeof(double));
- double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
- int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
- int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
- if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
+ if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) {
FATAL("could not acquire memory for alias table");
}
- memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
+ memset((void *)afl->alias_table, 0, n * sizeof(u32));
+ memset((void *)Small, 0, n * sizeof(u32));
+ memset((void *)Large, 0, n * sizeof(u32));
if (likely(afl->schedule < RARE)) {
@@ -166,7 +171,15 @@ void create_alias_table(afl_state_t *afl) {
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
- P[i] = (afl->queue_buf[i]->weight * n) / sum;
+ if (unlikely(afl->queue_buf[i]->disabled)) {
+
+ P[i] = 0;
+
+ } else {
+
+ P[i] = (afl->queue_buf[i]->weight * n) / sum;
+
+ }
}
@@ -176,60 +189,81 @@ void create_alias_table(afl_state_t *afl) {
struct queue_entry *q = afl->queue_buf[i];
- if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); }
+ if (likely(!q->disabled)) {
+
+ q->perf_score = calculate_score(afl, q);
+ sum += q->perf_score;
- sum += q->perf_score;
+ }
}
for (i = 0; i < n; i++) {
// perf_score is always 0 for disabled entries
- P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+ if (unlikely(afl->queue_buf[i]->disabled)) {
+
+ P[i] = 0;
+
+ } else {
+
+ P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
+
+ }
}
}
- int nS = 0, nL = 0, s;
- for (s = (s32)n - 1; s >= 0; --s) {
+ // Done collecting weightings in P, now create the arrays.
+
+ for (s32 j = (s32)(n - 1); j >= 0; j--) {
- if (P[s] < 1) {
+ if (P[j] < 1) {
- S[nS++] = s;
+ Small[nSmall++] = (u32)j;
} else {
- L[nL++] = s;
+ Large[nLarge--] = (u32)j;
}
}
- while (nS && nL) {
+ while (nSmall && nLarge != n - 1) {
+
+ u32 small = Small[--nSmall];
+ u32 large = Large[++nLarge];
+
+ afl->alias_probability[small] = P[small];
+ afl->alias_table[small] = large;
- a = S[--nS];
- g = L[--nL];
- afl->alias_probability[a] = P[a];
- afl->alias_table[a] = g;
- P[g] = P[g] + P[a] - 1;
- if (P[g] < 1) {
+ P[large] = P[large] - (1 - P[small]);
- S[nS++] = g;
+ if (P[large] < 1) {
+
+ Small[nSmall++] = large;
} else {
- L[nL++] = g;
+ Large[nLarge--] = large;
}
}
- while (nL)
- afl->alias_probability[L[--nL]] = 1;
+ while (nSmall) {
+
+ afl->alias_probability[Small[--nSmall]] = 1;
+
+ }
- while (nS)
- afl->alias_probability[S[--nS]] = 1;
+ while (nLarge != n - 1) {
+
+ afl->alias_probability[Large[++nLarge]] = 1;
+
+ }
afl->reinit_table = 0;
@@ -264,7 +298,7 @@ void create_alias_table(afl_state_t *afl) {
*/
/*
fprintf(stderr, " entry alias probability perf_score weight
- filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
+ filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
%0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i],
afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight,
afl->queue_buf[i]->fname);
--
cgit 1.4.1
From 6cad585bdc5c335cc2894c97e9aaf6d5fff88e1f Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 27 Apr 2023 18:57:28 +0200
Subject: nits
---
src/afl-showmap.c | 2 +-
test/test-llvm.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index d0e01cb1..f60acb2d 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1287,7 +1287,7 @@ int main(int argc, char **argv_orig, char **envp) {
break;
- case 'Y': // fallthough
+ case 'Y': // fallthrough
#ifdef __linux__
case 'X': /* NYX mode */
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
index 0e66cc97..714bda93 100755
--- a/test/test-llvm.sh
+++ b/test/test-llvm.sh
@@ -263,7 +263,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
{
mkdir -p in
echo 00000000000000000000000000000000 > in/in
- AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V15 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1
+ AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V30 -i in -o out -c./test-cmplog -- ./test-c >>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"
--
cgit 1.4.1
From 41b0fe7280372031753fc5f11b9a03b214189155 Mon Sep 17 00:00:00 2001
From: Nick Potenski
Date: Thu, 27 Apr 2023 11:57:55 -0500
Subject: afl-showmap: Start a only a single fork server (#1718)
A forkserver is started by afl_fsrv_get_mapsize() when dynamically
finding the map size. When an input directory option is specified a
second fork server was also started. This commit re-arranges the inits
for several forkserver struct members so that we can re-use the server
started by the get_mapsize() call when not in coresight/qemu/unicorn
modes and just start the server otherwise.
---
src/afl-showmap.c | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
(limited to 'src')
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index f60acb2d..9c029035 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1421,6 +1421,14 @@ int main(int argc, char **argv_orig, char **envp) {
// If @@ are in the target args, replace them and also set use_stdin=false.
detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
+ fsrv->dev_null_fd = open("/dev/null", O_RDWR);
+ if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
+
+ fsrv->out_file = stdin_file;
+ fsrv->out_fd =
+ open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+ if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); }
+
} else {
// If @@ are in the target args, replace them and also set use_stdin=false.
@@ -1588,6 +1596,14 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->map_size = map_size;
+ } else {
+
+ afl_fsrv_start(fsrv, use_argv, &stop_soon,
+ (get_afl_env("AFL_DEBUG_CHILD") ||
+ get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+ ? 1
+ : 0);
+
}
if (in_dir || in_filelist) {
@@ -1617,9 +1633,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
- fsrv->dev_null_fd = open("/dev/null", O_RDWR);
- if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
-
if (in_filelist) {
if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
@@ -1666,10 +1679,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
atexit(at_exit_handler);
- fsrv->out_file = stdin_file;
- fsrv->out_fd =
- open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
- if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
if (get_afl_env("AFL_DEBUG")) {
@@ -1685,12 +1694,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- afl_fsrv_start(fsrv, use_argv, &stop_soon,
- (get_afl_env("AFL_DEBUG_CHILD") ||
- get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
- ? 1
- : 0);
-
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
--
cgit 1.4.1
From e956f23a77b776a5c11344889503c833adbf1052 Mon Sep 17 00:00:00 2001
From: "Christian Holler (:decoder)"
Date: Fri, 28 Apr 2023 11:35:22 +0200
Subject: Source Code Coverage support for Nyx (Part 1) (#1720)
* Additional source code reformatting in afl-compiler-rt
* Add source code coverage support to afl-compiler-rt (for use with Nyx)
---
GNUmakefile.llvm | 5 +
instrumentation/README.llvm.md | 24 ++++
instrumentation/afl-compiler-rt.o.c | 261 +++++++++++++++++++++++++++++++++++-
src/afl-cc.c | 26 +++-
4 files changed, 308 insertions(+), 8 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index c1b006ba..2bb4e7f8 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -274,6 +274,11 @@ ifndef LLVM_DEBUG
CFLAGS_SAFE += -Wno-deprecated
endif
+ifdef CODE_COVERAGE
+ override CFLAGS_SAFE += -D__AFL_CODE_COVERAGE=1
+ override LDFLAGS += -ldl
+endif
+
override CFLAGS += $(CFLAGS_SAFE)
ifdef AFL_TRACE_PC
diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md
index c0677474..126cf1a2 100644
--- a/instrumentation/README.llvm.md
+++ b/instrumentation/README.llvm.md
@@ -280,3 +280,27 @@ Please note that the default counter implementations are not thread safe!
Support for thread safe counters in mode LLVM CLASSIC can be activated with
setting `AFL_LLVM_THREADSAFE_INST=1`.
+
+## 8) Source code coverage through instrumentation
+
+Measuring source code coverage is a common task in fuzzing, but it is very
+difficut to do in some situations (e.g. when using snapshot fuzzing).
+
+When using the `AFL_LLVM_INSTRUMENT=llvm-codecov` option, afl-cc will use
+native trace-pc-guard instrumentation but additionally select options that
+are required to utilize the instrumentation for source code coverage.
+
+In particular, it will switch the instrumentation to be per basic block
+instead of instrumenting edges, disable all guard pruning and enable the
+experimental pc-table support that allows the runtime to gather 100% of
+instrumented basic blocks at start, including their locations.
+
+Note: You must compile AFL with the `CODE_COVERAGE=1` option to enable the
+respective parts in the AFL compiler runtime. Support is currently only
+implemented for Nyx, but can in theory also work without Nyx.
+
+Note: You might have to adjust `MAP_SIZE_POW2` in include/config.h to ensure
+that your coverage map is large enough to hold all basic blocks of your
+target program without any collisions.
+
+More documentation on how to utilize this with Nyx will follow.
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 0912e52b..3f8b519b 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -14,6 +14,16 @@
*/
+#ifdef __AFL_CODE_COVERAGE
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE
+ #endif
+ #ifndef __USE_GNU
+ #define __USE_GNU
+ #endif
+ #include
+#endif
+
#ifdef __ANDROID__
#include "android-ashmem.h"
#endif
@@ -105,6 +115,44 @@ u32 __afl_dictionary_len;
u64 __afl_map_addr;
u32 __afl_first_final_loc;
+#ifdef __AFL_CODE_COVERAGE
+typedef struct afl_module_info_t afl_module_info_t;
+
+struct afl_module_info_t {
+
+ // A unique id starting with 0
+ u32 id;
+
+ // Name and base address of the module
+ char *name;
+ uintptr_t base_address;
+
+ // PC Guard start/stop
+ u32 start;
+ u32 stop;
+
+ // PC Table begin/end
+ const uintptr_t *pcs_beg;
+ const uintptr_t *pcs_end;
+
+ u8 mapped;
+
+ afl_module_info_t *next;
+
+};
+
+typedef struct {
+
+ uintptr_t PC, PCFlags;
+
+} PCTableEntry;
+
+afl_module_info_t *__afl_module_info = NULL;
+
+u32 __afl_pcmap_size = 0;
+uintptr_t *__afl_pcmap_ptr = NULL;
+#endif // __AFL_CODE_COVERAGE
+
/* 1 if we are running in afl, and the forkserver was started, else 0 */
u32 __afl_connected = 0;
@@ -496,11 +544,12 @@ static void __afl_map_shm(void) {
if (__afl_map_size && __afl_map_size > MAP_SIZE) {
- u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
- if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
+ u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
+ if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
- send_forkserver_error(FS_ERROR_MAP_SIZE);
- _exit(1);
+ fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
+ send_forkserver_error(FS_ERROR_MAP_SIZE);
+ _exit(1);
}
@@ -512,13 +561,13 @@ static void __afl_map_shm(void) {
if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) {
- if (__afl_map_addr)
+ if (__afl_map_addr)
send_forkserver_error(FS_ERROR_MAP_ADDR);
else
send_forkserver_error(FS_ERROR_SHMAT);
perror("shmat for map");
- _exit(1);
+ _exit(1);
}
@@ -678,6 +727,27 @@ static void __afl_map_shm(void) {
}
+#ifdef __AFL_CODE_COVERAGE
+ char *pcmap_id_str = getenv("__AFL_PCMAP_SHM_ID");
+
+ if (pcmap_id_str) {
+
+ __afl_pcmap_size = __afl_map_size * sizeof(void *);
+ u32 shm_id = atoi(pcmap_id_str);
+
+ __afl_pcmap_ptr = (uintptr_t *)shmat(shm_id, NULL, 0);
+
+ if (__afl_debug) {
+
+ fprintf(stderr, "DEBUG: Received %p via shmat for pcmap\n",
+ __afl_pcmap_ptr);
+
+ }
+
+ }
+
+#endif // __AFL_CODE_COVERAGE
+
}
/* unmap SHM. */
@@ -686,6 +756,17 @@ static void __afl_unmap_shm(void) {
if (!__afl_already_initialized_shm) return;
+#ifdef __AFL_CODE_COVERAGE
+ if (__afl_pcmap_size) {
+
+ shmdt((void *)__afl_pcmap_ptr);
+ __afl_pcmap_ptr = NULL;
+ __afl_pcmap_size = 0;
+
+ }
+
+#endif // __AFL_CODE_COVERAGE
+
char *id_str = getenv(SHM_ENV_VAR);
if (id_str) {
@@ -1507,6 +1588,102 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
}
+#ifdef __AFL_CODE_COVERAGE
+void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
+ const uintptr_t *pcs_end) {
+
+ if (__afl_debug) {
+
+ fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init called\n");
+
+ }
+
+ // If for whatever reason, we cannot get dlinfo here, then pc_guard_init also
+ // couldn't get it and we'd end up attributing to the wrong module.
+ Dl_info dlinfo;
+ if (!dladdr(__builtin_return_address(0), &dlinfo)) {
+
+ fprintf(stderr,
+ "WARNING: Ignoring __sanitizer_cov_pcs_init callback due to "
+ "missing module info\n");
+ return;
+
+ }
+
+ afl_module_info_t *last_module_info = __afl_module_info;
+ while (last_module_info && last_module_info->next) {
+
+ last_module_info = last_module_info->next;
+
+ }
+
+ if (!last_module_info) {
+
+ fprintf(stderr,
+ "ERROR: __sanitizer_cov_pcs_init called with no module info?!\n");
+ abort();
+
+ }
+
+ last_module_info->pcs_beg = pcs_beg;
+ last_module_info->pcs_end = pcs_end;
+
+ // Now update the pcmap. If this is the last module coming in, after all
+ // pre-loaded code, then this will also map all of our delayed previous
+ // modules.
+
+ if (!__afl_pcmap_ptr) { return; }
+
+ for (afl_module_info_t *mod_info = __afl_module_info; mod_info;
+ mod_info = mod_info->next) {
+
+ if (mod_info->mapped) { continue; }
+
+ PCTableEntry *start = (PCTableEntry *)(mod_info->pcs_beg);
+ PCTableEntry *end = (PCTableEntry *)(mod_info->pcs_end);
+
+ u32 in_module_index = 0;
+
+ while (start < end) {
+
+ if (mod_info->start + in_module_index >= __afl_map_size) {
+
+ fprintf(stderr, "ERROR: __sanitizer_cov_pcs_init out of bounds?!\n");
+ abort();
+
+ }
+
+ uintptr_t PC = start->PC;
+
+ // This is what `GetPreviousInstructionPc` in sanitizer runtime does
+ // for x86/x86-64. Needs more work for ARM and other archs.
+ PC = PC - 1;
+
+ // Calculate relative offset in module
+ PC = PC - mod_info->base_address;
+
+ __afl_pcmap_ptr[mod_info->start + in_module_index] = PC;
+
+ start++;
+ in_module_index++;
+
+ }
+
+ mod_info->mapped = 1;
+
+ if (__afl_debug) {
+
+ fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init initialized %u PCs\n",
+ in_module_index);
+
+ }
+
+ }
+
+}
+
+#endif // __AFL_CODE_COVERAGE
+
/* Init callback. Populates instrumentation IDs. Note that we're using
ID of 0 as a special value to indicate non-instrumented bits. That may
still touch the bitmap, but in a fairly harmless way. */
@@ -1538,6 +1715,62 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
if (start == stop || *start) { return; }
+#ifdef __AFL_CODE_COVERAGE
+ u32 *orig_start = start;
+ afl_module_info_t *mod_info = NULL;
+
+ Dl_info dlinfo;
+ if (dladdr(__builtin_return_address(0), &dlinfo)) {
+
+ if (__afl_already_initialized_forkserver) {
+
+ fprintf(stderr, "[pcmap] Error: Module was not preloaded: %s\n",
+ dlinfo.dli_fname);
+
+ } else {
+
+ afl_module_info_t *last_module_info = __afl_module_info;
+ while (last_module_info && last_module_info->next) {
+
+ last_module_info = last_module_info->next;
+
+ }
+
+ mod_info = malloc(sizeof(afl_module_info_t));
+
+ mod_info->id = last_module_info ? last_module_info->id + 1 : 0;
+ mod_info->name = strdup(dlinfo.dli_fname);
+ mod_info->base_address = (uintptr_t)dlinfo.dli_fbase;
+ mod_info->start = 0;
+ mod_info->stop = 0;
+ mod_info->pcs_beg = NULL;
+ mod_info->pcs_end = NULL;
+ mod_info->mapped = 0;
+ mod_info->next = NULL;
+
+ if (last_module_info) {
+
+ last_module_info->next = mod_info;
+
+ } else {
+
+ __afl_module_info = mod_info;
+
+ }
+
+ fprintf(stderr, "[pcmap] Module: %s Base Address: %p\n", dlinfo.dli_fname,
+ dlinfo.dli_fbase);
+
+ }
+
+ } else {
+
+ fprintf(stderr, "[pcmap] dladdr call failed\n");
+
+ }
+
+#endif // __AFL_CODE_COVERAGE
+
x = getenv("AFL_INST_RATIO");
if (x) {
@@ -1625,6 +1858,22 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
}
+#ifdef __AFL_CODE_COVERAGE
+ if (mod_info) {
+
+ mod_info->start = *orig_start;
+ mod_info->stop = *(stop - 1);
+ if (__afl_debug) {
+
+ fprintf(stderr, "DEBUG: [pcmap] Start Index: %u Stop Index: %u\n",
+ mod_info->start, mod_info->stop);
+
+ }
+
+ }
+
+#endif // __AFL_CODE_COVERAGE
+
if (__afl_debug) {
fprintf(stderr,
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 99ce39d4..b11a041d 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -76,6 +76,7 @@ enum {
INSTRUMENT_OPT_NGRAM = 16,
INSTRUMENT_OPT_CALLER = 32,
INSTRUMENT_OPT_CTX_K = 64,
+ INSTRUMENT_OPT_CODECOV = 128,
};
@@ -751,7 +752,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
#if LLVM_MAJOR >= 4
- cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+ if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
+ #if LLVM_MAJOR >= 6
+ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
+ #else
+ FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+");
+ #endif
+ } else {
+ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+ }
#else
FATAL("pcguard instrumentation requires llvm 4.0.1+");
#endif
@@ -1682,6 +1691,18 @@ int main(int argc, char **argv, char **envp) {
}
+ if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 ||
+ strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) {
+
+ if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) {
+ instrument_mode = INSTRUMENT_LLVMNATIVE;
+ instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
+ } else
+ FATAL("main instrumentation mode already set with %s",
+ instrument_mode_string[instrument_mode]);
+
+ }
+
if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
@@ -2241,7 +2262,8 @@ int main(int argc, char **argv, char **envp) {
"(requires LLVM 11 or higher)");
#endif
- if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
+ if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
+ instrument_mode != INSTRUMENT_CLASSIC)
FATAL(
"CALLER, CTX and NGRAM instrumentation options can only be used with "
"the LLVM CLASSIC instrumentation mode.");
--
cgit 1.4.1
From 5813a4319c88848b2a1c47c12fe27f5e14dcad44 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 28 Apr 2023 11:42:21 +0200
Subject: doc, code format
---
GNUmakefile | 3 ++-
docs/INSTALL.md | 10 ++++------
instrumentation/afl-compiler-rt.o.c | 14 +++++++-------
src/afl-cc.c | 31 +++++++++++++++++++++++--------
4 files changed, 36 insertions(+), 22 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile b/GNUmakefile
index 5900ad61..56b8bb42 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -379,6 +379,7 @@ help:
@echo Known build environment options:
@echo "=========================================="
@echo STATIC - compile AFL++ static
+ @echo CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
@echo UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
@@ -394,7 +395,7 @@ help:
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
@echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)"
@echo "=========================================="
- @echo e.g.: make ASAN_BUILD=1
+ @echo e.g.: make LLVM_CONFIG=llvm-config-16
.PHONY: test_x86
ifndef AFL_NO_X86
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index c54cb9ad..637e8658 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -79,22 +79,20 @@ make STATIC=1
These build options exist:
* 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
-* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour 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
* PROFILING - compile afl-fuzz with profiling information
* INTROSPECTION - compile afl-fuzz with mutation introspection
* NO_PYTHON - disable python support
-* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for
- normal fuzzing
+* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
* 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
-* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config
- (e.g., Debian)
+* 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`
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 3f8b519b..5372fae0 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -544,12 +544,12 @@ static void __afl_map_shm(void) {
if (__afl_map_size && __afl_map_size > MAP_SIZE) {
- u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
- if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
+ u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
+ if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
- fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
- send_forkserver_error(FS_ERROR_MAP_SIZE);
- _exit(1);
+ fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
+ send_forkserver_error(FS_ERROR_MAP_SIZE);
+ _exit(1);
}
@@ -561,13 +561,13 @@ static void __afl_map_shm(void) {
if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) {
- if (__afl_map_addr)
+ if (__afl_map_addr)
send_forkserver_error(FS_ERROR_MAP_ADDR);
else
send_forkserver_error(FS_ERROR_SHMAT);
perror("shmat for map");
- _exit(1);
+ _exit(1);
}
diff --git a/src/afl-cc.c b/src/afl-cc.c
index b11a041d..19314555 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -752,15 +752,21 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
#if LLVM_MAJOR >= 4
- if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
+ if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
+
#if LLVM_MAJOR >= 6
- cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
+ cc_params[cc_par_cnt++] =
+ "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
#else
FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+");
#endif
- } else {
+
+ } else {
+
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
- }
+
+ }
+
#else
FATAL("pcguard instrumentation requires llvm 4.0.1+");
#endif
@@ -1660,13 +1666,17 @@ int main(int argc, char **argv, char **envp) {
instrument_mode = INSTRUMENT_CLASSIC;
lto_mode = 1;
- } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
+ } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) {
instrument_mode = INSTRUMENT_AFL;
- else
+
+ } else {
+
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
+ }
+
}
if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
@@ -1695,12 +1705,17 @@ int main(int argc, char **argv, char **envp) {
strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) {
+
instrument_mode = INSTRUMENT_LLVMNATIVE;
- instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
- } else
+ instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
+
+ } else {
+
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
+ }
+
}
if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
--
cgit 1.4.1
From 9065d4ba86ecdafeade50e5235ee1e99f4179692 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Mon, 1 May 2023 08:38:13 +0200
Subject: fix effector map
---
src/afl-fuzz-one.c | 2 ++
1 file changed, 2 insertions(+)
(limited to 'src')
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index ee562f96..442240a9 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -842,6 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ memset(eff_map, 0, sizeof(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
@@ -3570,6 +3571,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ memset(eff_map, 0, sizeof(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
--
cgit 1.4.1
From 2cd07abca9c7b843bbd2085e0e4d852d41169092 Mon Sep 17 00:00:00 2001
From: lazymio
Date: Mon, 1 May 2023 13:12:05 +0200
Subject: Should memset EFF_ALEN(len) of eff_map (#1722)
---
src/afl-fuzz-one.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 442240a9..a9902087 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -842,7 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
- memset(eff_map, 0, sizeof(len));
+ memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
@@ -3571,7 +3571,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
- memset(eff_map, 0, sizeof(len));
+ memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
--
cgit 1.4.1
From 22db79aefafb48fed48199a86a39babdee795870 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Mon, 1 May 2023 15:07:49 +0200
Subject: fix reallocs
---
include/alloc-inl.h | 7 +++----
src/afl-fuzz.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 4 deletions(-)
(limited to 'src')
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index bbb42e88..1e9a192b 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -704,12 +704,11 @@ static inline void *afl_realloc(void **buf, size_t size_needed) {
*buf = NULL;
return NULL;
- } else {
-
- new_buf = newer_buf;
-
}
+ new_buf = newer_buf;
+ memset(((u8 *)new_buf) + current_size, 0, next_size - current_size);
+
new_buf->complete_size = next_size;
*buf = (void *)(new_buf->buf);
return *buf;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 646dc50b..c02479cf 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1979,6 +1979,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
+ u32 old_map_size = map_size;
map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
@@ -1990,6 +1991,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
+ if (old_map_size < map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
+
+ }
+
}
afl->argv = use_argv;
@@ -2017,6 +2030,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes", new_map_size);
+ u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2029,6 +2043,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
+ if (old_map_size < new_map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ new_map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+ }
+
afl_fsrv_kill(&afl->fsrv);
afl_shm_deinit(&afl->shm);
afl->fsrv.map_size = new_map_size;
@@ -2079,6 +2105,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
+ u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@@ -2091,6 +2118,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
+ if (old_map_size < new_map_size) {
+
+ memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->clean_trace_custom + old_map_size, 0,
+ new_map_size - old_map_size);
+ memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
+ memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
+
+ }
+
afl_fsrv_kill(&afl->fsrv);
afl_fsrv_kill(&afl->cmplog_fsrv);
afl_shm_deinit(&afl->shm);
--
cgit 1.4.1
From f516926f006545d45162eaef723d786a427721f8 Mon Sep 17 00:00:00 2001
From: Moshe Kaplan
Date: Thu, 4 May 2023 11:23:30 -0400
Subject: afl-fuzz.c: Document -i - in --help (#1725)
afl-fuzz.c: Document `-i -` in `--help`, to write that `-i` can be passed '-' to resume the prior fuzzing job. Also reference AFL_AUTORESUME so users know they can set that parameter to sidestep the issue entirely.
---
src/afl-fuzz.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index c02479cf..c5206282 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -124,7 +124,7 @@ static void usage(u8 *argv0, int more_help) {
"\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
"Required parameters:\n"
- " -i dir - input directory with test cases\n"
+ " -i dir - input directory with test cases (or '-' to resume, also see AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
--
cgit 1.4.1
From 396157dedae2049f830c49eb81ef9617275333ee Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 5 May 2023 13:52:54 +0200
Subject: tritondse custom mutator attempt
---
custom_mutators/aflpp_tritondse/README.md | 17 ++++
custom_mutators/aflpp_tritondse/aflpp_tritondse.py | 106 +++++++++++++++++++++
src/afl-fuzz-one.c | 16 ++--
3 files changed, 132 insertions(+), 7 deletions(-)
create mode 100644 custom_mutators/aflpp_tritondse/README.md
create mode 100644 custom_mutators/aflpp_tritondse/aflpp_tritondse.py
(limited to 'src')
diff --git a/custom_mutators/aflpp_tritondse/README.md b/custom_mutators/aflpp_tritondse/README.md
new file mode 100644
index 00000000..8a5dd02b
--- /dev/null
+++ b/custom_mutators/aflpp_tritondse/README.md
@@ -0,0 +1,17 @@
+# An AFL++ custom mutator using TritonDSE
+
+## Installing the requirements
+
+`pip3 install tritondse`
+
+## How to run with an example
+
+```
+../../afl-cc -o ../../test-instr ../../test-instr.c
+mkdir -p in
+echo aaaa > in/in
+TRITON_DSE_TARGET=../../test-instr AFL_CUSTOM_MUTATOR_ONLY=1 AFL_SYNC_TIME=1 AFL_PYTHON_MODULE=aflpp_tritondse PYTHONPATH=. ../../afl-fuzz -i in -o out -- ../../test-instr
+```
+
+Note that this custom mutator works differently, new finds are synced
+after 10-60 seconds to the fuzzing instance.
diff --git a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
new file mode 100644
index 00000000..33bf8a9f
--- /dev/null
+++ b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
@@ -0,0 +1,106 @@
+import sys
+import os
+import logging
+
+from tritondse import Config
+from tritondse import CoverageStrategy
+from tritondse import ProcessState
+from tritondse import Program
+from tritondse import Seed
+from tritondse import SeedFormat
+from tritondse import SymbolicExecutor
+from tritondse import SymbolicExplorator
+
+
+#logging.basicConfig(level=logging.INFO)
+
+is_debug = False
+out_path = "out/tritondse/queue"
+input_file = None
+prog = None
+config = None
+dse = None
+cycle = 0
+count = 0
+hashes = set()
+
+def pre_exec_hook(se: SymbolicExecutor, state: ProcessState):
+ #logging.info(f"[PRE-EXEC] Processing seed: {se.seed.hash}, \
+ # ({repr(se.seed.content)})")
+ global count
+ global hasshes
+ if se.seed.hash not in hashes:
+ hashes.add(se.seed.hash)
+ filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
+ if not os.path.exists(filename):
+ with open(filename, 'wb') as file:
+ file.write(se.seed.content)
+ count += 1
+ if input_file:
+ with open(input_file, 'wb') as file:
+ file.write(se.seed.content)
+
+
+def init(seed):
+ global prog
+ global config
+ global dse
+ global input_file
+ global is_debug
+ # Load the program (LIEF-based program loader).
+ prog = Program(os.environ['TRITON_DSE_TARGET'])
+ # Set the configuration.
+ argv = None
+ try:
+ foo = os.environ['AFL_DEBUG']
+ is_debug = True
+ except KeyError:
+ pass
+ try:
+ argv_list = os.environ['TRITON_DSE_TARGET_ARGV']
+ argv = argv_list.split()
+ except KeyError:
+ pass
+ try:
+ foo = os.environ['TRITON_DSE_TARGET_INPUT']
+ input_file = foo
+ except KeyError:
+ pass
+ config = Config(coverage_strategy = CoverageStrategy.PATH,
+ debug = is_debug,
+ pipe_stdout = is_debug,
+ pipe_stderr = is_debug,
+ execution_timeout = 1,
+ program_argv = argv,
+ smt_timeout= 50,
+ seed_format = SeedFormat.RAW)
+ # Create an instance of the Symbolic Explorator
+ dse = SymbolicExplorator(config, prog)
+ # Add callbacks.
+ dse.callback_manager.register_pre_execution_callback(pre_exec_hook)
+ # Create the output directory
+ os.makedirs(out_path, exist_ok=True)
+
+
+#def fuzz(buf, add_buf, max_size):
+# return b""
+
+
+def queue_new_entry(filename_new_queue, filename_orig_queue):
+ global dse
+ global cycle
+ # Add seed to the worklist.
+ with open(filename_new_queue, "rb") as file:
+ seed = file.read()
+ seed = Seed(seed)
+ dse.add_input_seed(seed)
+ if is_debug:
+ print("NEW FILE " + filename_new_queue + " count " + str(cycle))
+ cycle += 1
+ # Start exploration!
+ #dse.step()
+ dse.explore()
+ pass
+
+def splice_optout():
+ pass
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index a9902087..c6e9a295 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -2048,20 +2048,22 @@ custom_mutator_stage:
afl->queue_cur->stats_mutated += afl->stage_max;
#endif
- if (likely(afl->custom_only)) {
+ /****************
+ * RANDOM HAVOC *
+ ****************/
+
+havoc_stage:
+
+ if (unlikely(afl->custom_only)) {
+ /* Force UI update */
+ show_stats(afl);
/* Skip other stages */
ret_val = 0;
goto abandon_entry;
}
- /****************
- * RANDOM HAVOC *
- ****************/
-
-havoc_stage:
-
afl->stage_cur_byte = -1;
/* The havoc stage mutation code is also invoked when splicing files; if the
--
cgit 1.4.1
From c97caa6e1095a4bce8f0c32108e6e33f7ac240e4 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 9 May 2023 14:17:09 +0200
Subject: fix makefile
---
GNUmakefile | 2 +-
src/afl-fuzz.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile b/GNUmakefile
index 794ebeab..31374c10 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -379,7 +379,7 @@ help:
@echo Known build environment options:
@echo "=========================================="
@echo STATIC - compile AFL++ static
- @echo CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
+ @echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
@echo UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index c5206282..f982258f 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -124,7 +124,8 @@ static void usage(u8 *argv0, int more_help) {
"\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
"Required parameters:\n"
- " -i dir - input directory with test cases (or '-' to resume, also see AFL_AUTORESUME)\n"
+ " -i dir - input directory with test cases (or '-' to resume, "
+ "also see AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
--
cgit 1.4.1
From 70da0c2e405102dc044cb4bed0f4f1e847c90d0b Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Wed, 10 May 2023 16:09:18 +0200
Subject: better tritondse support
---
custom_mutators/aflpp_tritondse/aflpp_tritondse.py | 54 ++++++++++---
docs/custom_mutators.md | 28 +++++++
include/envs.h | 4 +
src/afl-fuzz.c | 91 ++++++++++++++++------
4 files changed, 145 insertions(+), 32 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
index 49f67d75..9584b368 100644
--- a/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
+++ b/custom_mutators/aflpp_tritondse/aflpp_tritondse.py
@@ -7,6 +7,7 @@ from tritondse import Config
from tritondse import CoverageStrategy
from tritondse import ProcessState
from tritondse import Program
+from tritondse import CleLoader
from tritondse import Seed
from tritondse import SeedFormat
from tritondse import SymbolicExecutor
@@ -16,7 +17,7 @@ from tritondse import SymbolicExplorator
#logging.basicConfig(level=logging.INFO)
is_debug = False
-out_path = "out/tritondse/queue"
+out_path = ""
input_file = None
prog = None
config = None
@@ -29,28 +30,38 @@ def pre_exec_hook(se: SymbolicExecutor, state: ProcessState):
#logging.info(f"[PRE-EXEC] Processing seed: {se.seed.hash}, \
# ({repr(se.seed.content)})")
global count
- global hasshes
+ global hashes
+ print('DEBUG - prehook')
if se.seed.hash not in hashes:
hashes.add(se.seed.hash)
filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
if not os.path.exists(filename):
+ if is_debug:
+ print('Creating queue input ' + filename)
with open(filename, 'wb') as file:
file.write(se.seed.content)
count += 1
+ else:
+ print('has hash: ' + se.seed.hash)
if input_file:
+ if is_debug:
+ print('Writing to ' + input_file + ' the content: ' + str(se.seed.content))
with open(input_file, 'wb') as file:
file.write(se.seed.content)
+ else:
+ print('no input!')
def init(seed):
global prog
global config
global dse
+ global out_path
global input_file
global is_debug
# Load the program (LIEF-based program loader).
- prog = Program(os.environ['TRITON_DSE_TARGET'])
- # Set the configuration.
+ prog = CleLoader(os.environ['AFL_CUSTOM_INFO_PROGRAM'])
+ # Process other configuration environment variables.
argv = None
try:
foo = os.environ['AFL_DEBUG']
@@ -58,15 +69,42 @@ def init(seed):
except KeyError:
pass
try:
- argv_list = os.environ['TRITON_DSE_TARGET_ARGV']
- argv = argv_list.split()
+ foo = os.environ['AFL_CUSTOM_INFO_OUT']
+ out_path = foo + '/../tritondse/queue'
except KeyError:
pass
try:
- foo = os.environ['TRITON_DSE_TARGET_INPUT']
+ foo = os.environ['AFL_CUSTOM_INFO_PROGRAM_INPUT']
input_file = foo
except KeyError:
pass
+ try:
+ argv_list = os.environ['AFL_CUSTOM_INFO_PROGRAM_ARGV']
+ argv_tmp = [ os.environ['AFL_CUSTOM_INFO_PROGRAM'] ]
+ argv_tmp += argv_list.split()
+ argv = []
+ # now check for @@
+ for item in argv_tmp:
+ if "@@" in item:
+ input_file = out_path + '/../.input'
+ argv.append(input_file)
+ else:
+ argv.append(item)
+ except KeyError:
+ pass
+ # Create the output directory
+ os.makedirs(out_path, exist_ok=True)
+ # Debug
+ if is_debug:
+ print('DEBUG target: ' + os.environ['AFL_CUSTOM_INFO_PROGRAM'])
+ if argv:
+ print('DEBUG argv: ')
+ print(argv)
+ if input_file:
+ print('DEBUG input_file: ' + input_file)
+ print('DEBUG out_path: ' + out_path)
+ print('')
+ # Now set up TritonDSE
config = Config(coverage_strategy = CoverageStrategy.PATH,
debug = is_debug,
pipe_stdout = is_debug,
@@ -79,8 +117,6 @@ def init(seed):
dse = SymbolicExplorator(config, prog)
# Add callbacks.
dse.callback_manager.register_pre_execution_callback(pre_exec_hook)
- # Create the output directory
- os.makedirs(out_path, exist_ok=True)
#def fuzz(buf, add_buf, max_size):
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index a1de479e..3f7e9e6e 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -304,6 +304,34 @@ Note: for some distributions, you might also need the package `python[3]-apt`.
In case your setup is different, set the necessary variables like this:
`PYTHON_INCLUDE=/path/to/python/include LDFLAGS=-L/path/to/python/lib make`.
+### Helpers
+
+For C/C++ custom mutators you get a pointer to `afl_state_t *afl` in the
+`afl_custom_init()` which contains all information that you need.
+Note that if you access it, you need to recompile your custom mutator if
+you update AFL++ because the structure might have changed!
+
+For mutators written in Python, Rust, GO, etc. there are a few environment
+variables set to help you to get started:
+
+`AFL_CUSTOM_INFO_PROGRAM` - the program name of the target that is executed.
+If your custom mutator is used with modes like Qemu (`-Q`), this will still
+contain the target program, not afl-qemu-trace.
+
+`AFL_CUSTOM_INFO_PROGRAM_INPUT` - if the `-f` parameter is used with afl-fuzz
+then this value is found in this environment variable.
+
+`AFL_CUSTOM_INFO_PROGRAM_ARGV` - this contains the parameters given to the
+target program and still has the `@@` identifier in there.
+
+Note: If `AFL_CUSTOM_INFO_PROGRAM_INPUT` is empty and `AFL_CUSTOM_INFO_PROGRAM_ARGV`
+is either empty or does not contain `@@` then the target gets the input via
+`stdin`.
+
+`AFL_CUSTOM_INFO_OUT` - This is the output directory for this fuzzer instance,
+so if `afl-fuzz` was called with `-o out -S foobar`, then this will be set to
+`out/foobar`.
+
### Custom Mutator Preparation
For C/C++ mutators, the source code must be compiled as a shared object:
diff --git a/include/envs.h b/include/envs.h
index fe5ee0e3..edfd06e4 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -37,6 +37,10 @@ static char *afl_environment_variables[] = {
"AFL_CRASH_EXITCODE",
"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",
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index f982258f..4339ddd2 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1530,29 +1530,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
-
- if (afl->custom_only) {
-
- FATAL("Custom mutators are incompatible with MOpt (-L)");
-
- }
-
- u32 custom_fuzz = 0;
- LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
-
- if (el->afl_custom_fuzz) { custom_fuzz = 1; }
-
- });
-
- if (custom_fuzz) {
-
- WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
-
- }
-
- }
-
if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@@ -1827,8 +1804,76 @@ int main(int argc, char **argv_orig, char **envp) {
printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
#endif
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
+
+ }
+
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
+
+ }
+
+ {
+
+ u8 envbuf[8096] = "", tmpbuf[8096] = "";
+ for (s32 i = optind + 1; i < argc; ++i) {
+
+ strcpy(tmpbuf, envbuf);
+ if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
+ !strchr(argv[i], '\'')) {
+
+ if (!strchr(argv[i], '\'')) {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
+
+ } else {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
+
+ }
+
+ } else {
+
+ snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
+
+ }
+
+ }
+
+ setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
+
+ }
+
+ setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
+
setup_custom_mutators(afl);
+ if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
+
+ if (afl->custom_only) {
+
+ FATAL("Custom mutators are incompatible with MOpt (-L)");
+
+ }
+
+ u32 custom_fuzz = 0;
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz) { custom_fuzz = 1; }
+
+ });
+
+ if (custom_fuzz) {
+
+ WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
+
+ }
+
+ }
+
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind);
--
cgit 1.4.1
From 93c821aaa3df0cf20f892ce72447ff022161c8ab Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 12 May 2023 08:39:11 +0200
Subject: afl-clang-lto incomptable with -flto=thin
---
docs/Changelog.md | 1 +
src/afl-cc.c | 9 +++++++++
2 files changed, 10 insertions(+)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index e85de763..799c13af 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -13,6 +13,7 @@
- afl-cc:
- new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
(https://github.com/fgsect/WAFL) project
+ - error and print help if afl-clan-lto is used with lto=thin
- afl-showmap:
- added custom mutator post_process and send support
- add `-I filelist` option, an alternative to `-i in_dir`
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 19314555..13ca751e 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -853,6 +853,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (cur[0] != '-') { non_dash = 1; }
if (!strncmp(cur, "--afl", 5)) continue;
+
+ if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
+
+ FATAL(
+ "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
+ "use afl-clang-fast!");
+
+ }
+
if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
if (!strncmp(cur, "-fno-unroll", 11)) continue;
--
cgit 1.4.1
From 7f636dbfc247fbe75910fa8fb681ea55d230ba79 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Fri, 12 May 2023 15:58:20 +0200
Subject: add @responsefile support for afl-cc
---
docs/Changelog.md | 1 +
src/afl-cc.c | 460 +++++++++++++++++++++++++++++++++++-------------------
2 files changed, 300 insertions(+), 161 deletions(-)
(limited to 'src')
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 799c13af..3602af50 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -11,6 +11,7 @@
- new env `AFL_IGNORE_PROBLEMS_COVERAGE` to ignore coverage from
loaded libs after forkserver initialization (required by Mozilla)
- afl-cc:
+ - added @responsefile support
- new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
(https://github.com/fgsect/WAFL) project
- error and print help if afl-clan-lto is used with lto=thin
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 13ca751e..972ac8cd 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -31,6 +31,8 @@
#include
#include
#include
+#include
+#include
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@@ -376,15 +378,304 @@ void parse_fsanitize(char *string) {
}
+static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0,
+ shared_linking = 0, preprocessor_only = 0, have_unroll = 0,
+ have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0,
+ non_dash = 0;
+
+static void process_params(u32 argc, char **argv) {
+
+ if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); }
+
+ if (lto_mode && argc > 1) {
+
+ u32 idx;
+ for (idx = 1; idx < argc; idx++) {
+
+ if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
+
+ }
+
+ }
+
+ // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
+
+ /* Process the argument list. */
+
+ u8 skip_next = 0;
+ while (--argc) {
+
+ u8 *cur = *(++argv);
+
+ if (skip_next) {
+
+ skip_next = 0;
+ continue;
+
+ }
+
+ if (cur[0] != '-') { non_dash = 1; }
+ if (!strncmp(cur, "--afl", 5)) continue;
+
+ if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
+
+ FATAL(
+ "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
+ "use afl-clang-fast!");
+
+ }
+
+ if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
+ if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
+ if (!strncmp(cur, "-fno-unroll", 11)) continue;
+ if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
+ if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
+ !strcmp(cur, "--no-undefined")) {
+
+ continue;
+
+ }
+
+ if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
+
+ if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
+
+ u8 *param = *(argv + 1);
+ if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
+
+ skip_next = 1;
+ continue;
+
+ }
+
+ }
+
+ if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
+ !strncmp(cur, "-stdlib=", 8)) {
+
+ if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+ continue;
+
+ }
+
+ if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
+
+ have_instr_list = 1;
+
+ }
+
+ if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
+ strchr(cur, ',')) {
+
+ parse_fsanitize(cur);
+ if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
+
+ } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
+
+ strlen("-fsanitize=fuzzer-")) ||
+ !strncmp(cur, "-fsanitize-coverage",
+ strlen("-fsanitize-coverage"))) &&
+ (strncmp(cur, "sanitize-coverage-allow",
+ strlen("sanitize-coverage-allow")) &&
+ strncmp(cur, "sanitize-coverage-deny",
+ strlen("sanitize-coverage-deny")) &&
+ instrument_mode != INSTRUMENT_LLVMNATIVE)) {
+
+ if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
+ continue;
+
+ }
+
+ if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
+
+ u8 *afllib = find_object("libAFLDriver.a", argv[0]);
+
+ if (!be_quiet) {
+
+ OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
+
+ }
+
+ if (!afllib) {
+
+ if (!be_quiet) {
+
+ WARNF(
+ "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
+ "the flags - this will fail!");
+
+ }
+
+ } else {
+
+ cc_params[cc_par_cnt++] = afllib;
+
+#ifdef __APPLE__
+ cc_params[cc_par_cnt++] = "-undefined";
+ cc_params[cc_par_cnt++] = "dynamic_lookup";
+#endif
+
+ }
+
+ if (need_aflpplib) {
+
+ need_aflpplib = 0;
+
+ } else {
+
+ continue;
+
+ }
+
+ }
+
+ if (!strcmp(cur, "-m32")) bit_mode = 32;
+ if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
+ if (!strcmp(cur, "-m64")) bit_mode = 64;
+
+ if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
+ asan_set = 1;
+
+ if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
+
+ if (!strcmp(cur, "-x")) x_set = 1;
+ if (!strcmp(cur, "-E")) preprocessor_only = 1;
+ if (!strcmp(cur, "-shared")) shared_linking = 1;
+ if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
+ if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
+ if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
+ if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
+ if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
+ if (!strcmp(cur, "-r")) partial_linking = 1;
+ if (!strcmp(cur, "--relocatable")) partial_linking = 1;
+ if (!strcmp(cur, "-c")) have_c = 1;
+
+ if (!strncmp(cur, "-O", 2)) have_o = 1;
+ if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
+
+ if (*cur == '@') {
+
+ // response file support.
+ // we have two choices - move everything to the command line or
+ // rewrite the response files to temporary files and delete them
+ // afterwards. We choose the first for easiness.
+ // We do *not* support quotes in the rsp files to cope with spaces in
+ // filenames etc! If you need that then send a patch!
+ u8 *filename = cur + 1;
+ if (debug) { DEBUGF("response file=%s\n", filename); }
+ FILE *f = fopen(filename, "r");
+ struct stat st;
+
+ // Check not found or empty? let the compiler complain if so.
+ if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) {
+
+ cc_params[cc_par_cnt++] = cur;
+ continue;
+
+ }
+
+ u8 *tmpbuf = malloc(st.st_size + 1), *ptr;
+ char **args = malloc(sizeof(char *) * (st.st_size >> 1));
+ int count = 1, cont = 0, cont_act = 0;
+
+ while (fgets(tmpbuf, st.st_size, f)) {
+
+ ptr = tmpbuf;
+ // no leading whitespace
+ while (isspace(*ptr)) {
+
+ ++ptr;
+ cont_act = 0;
+
+ }
+
+ // no comments, no empty lines
+ if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; }
+ // remove LF
+ if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; }
+ // remove CR
+ if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; }
+ // handle \ at end of line
+ if (*ptr && ptr[strlen(ptr) - 1] == '\\') {
+
+ cont = 1;
+ ptr[strlen(ptr) - 1] = 0;
+
+ }
+
+ // remove whitespace at end
+ while (*ptr && isspace(ptr[strlen(ptr) - 1])) {
+
+ ptr[strlen(ptr) - 1] = 0;
+ cont = 0;
+
+ }
+
+ if (*ptr) {
+
+ do {
+
+ u8 *value = ptr;
+ while (*ptr && !isspace(*ptr)) {
+
+ ++ptr;
+
+ }
+
+ while (*ptr && isspace(*ptr)) {
+
+ *ptr++ = 0;
+
+ }
+
+ if (cont_act) {
+
+ u32 len = strlen(args[count - 1]) + strlen(value) + 1;
+ u8 *tmp = malloc(len);
+ snprintf(tmp, len, "%s%s", args[count - 1], value);
+ free(args[count - 1]);
+ args[count - 1] = tmp;
+ cont_act = 0;
+
+ } else {
+
+ args[count++] = strdup(value);
+
+ }
+
+ } while (*ptr);
+
+ }
+
+ if (cont) {
+
+ cont_act = 1;
+ cont = 0;
+
+ }
+
+ }
+
+ if (count) { process_params(count, args); }
+
+ // we cannot free args[]
+ free(tmpbuf);
+
+ continue;
+
+ }
+
+ cc_params[cc_par_cnt++] = cur;
+
+ }
+
+}
+
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char **argv, char **envp) {
- u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
- preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0,
- have_c = 0, partial_linking = 0;
-
- cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
+ cc_params = ck_alloc(1024 * sizeof(u8 *));
if (lto_mode) {
@@ -831,168 +1122,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC";
-
}
}
- /* Detect stray -v calls from ./configure scripts. */
-
- u8 skip_next = 0, non_dash = 0;
- while (--argc) {
-
- u8 *cur = *(++argv);
-
- if (skip_next) {
-
- skip_next = 0;
- continue;
-
- }
-
- if (cur[0] != '-') { non_dash = 1; }
- if (!strncmp(cur, "--afl", 5)) continue;
-
- if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
-
- FATAL(
- "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
- "use afl-clang-fast!");
-
- }
-
- if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
- if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
- if (!strncmp(cur, "-fno-unroll", 11)) continue;
- if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
- if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
- !strcmp(cur, "--no-undefined")) {
-
- continue;
-
- }
+ /* Inspect the command line parameters. */
- if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
-
- if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
+ process_params(argc, argv);
- u8 *param = *(argv + 1);
- if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
-
- skip_next = 1;
- continue;
-
- }
-
- }
-
- if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
- !strncmp(cur, "-stdlib=", 8)) {
-
- if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
- continue;
-
- }
-
- if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
-
- have_instr_list = 1;
-
- }
-
- if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
- strchr(cur, ',')) {
-
- parse_fsanitize(cur);
- if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
-
- } else if ((!strncmp(cur, "-fsanitize=fuzzer-",
-
- strlen("-fsanitize=fuzzer-")) ||
- !strncmp(cur, "-fsanitize-coverage",
- strlen("-fsanitize-coverage"))) &&
- (strncmp(cur, "sanitize-coverage-allow",
- strlen("sanitize-coverage-allow")) &&
- strncmp(cur, "sanitize-coverage-deny",
- strlen("sanitize-coverage-deny")) &&
- instrument_mode != INSTRUMENT_LLVMNATIVE)) {
-
- if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
- continue;
-
- }
-
- if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
-
- u8 *afllib = find_object("libAFLDriver.a", argv[0]);
-
- if (!be_quiet) {
-
- OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
-
- }
-
- if (!afllib) {
-
- if (!be_quiet) {
-
- WARNF(
- "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
- "the flags - this will fail!");
-
- }
-
- } else {
-
- cc_params[cc_par_cnt++] = afllib;
-
-#ifdef __APPLE__
- cc_params[cc_par_cnt++] = "-undefined";
- cc_params[cc_par_cnt++] = "dynamic_lookup";
-#endif
-
- }
-
- if (need_aflpplib) {
-
- need_aflpplib = 0;
-
- } else {
-
- continue;
-
- }
-
- }
-
- if (!strcmp(cur, "-m32")) bit_mode = 32;
- if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
- if (!strcmp(cur, "-m64")) bit_mode = 64;
-
- if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
- asan_set = 1;
-
- if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
-
- if (!strcmp(cur, "-x")) x_set = 1;
- if (!strcmp(cur, "-E")) preprocessor_only = 1;
- if (!strcmp(cur, "-shared")) shared_linking = 1;
- if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
- if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
- if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
- if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
- if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
- if (!strcmp(cur, "-r")) partial_linking = 1;
- if (!strcmp(cur, "--relocatable")) partial_linking = 1;
- if (!strcmp(cur, "-c")) have_c = 1;
-
- if (!strncmp(cur, "-O", 2)) have_o = 1;
- if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
-
- cc_params[cc_par_cnt++] = cur;
-
- }
+ if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; }
// in case LLVM is installed not via a package manager or "make install"
// e.g. compiled download or compiled from github then its ./lib directory
--
cgit 1.4.1
From abd6eace9d767e4db6019e8eb69080d2352015c9 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 18 May 2023 10:32:15 +0200
Subject: improved symqemu custom mutator
---
custom_mutators/symqemu/README.md | 2 +-
custom_mutators/symqemu/symqemu.c | 239 +++++++++++++++-----------------------
include/afl-fuzz.h | 1 +
src/afl-fuzz-one.c | 1 +
4 files changed, 98 insertions(+), 145 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/symqemu/README.md b/custom_mutators/symqemu/README.md
index 55ce05c5..b7702c06 100644
--- a/custom_mutators/symqemu/README.md
+++ b/custom_mutators/symqemu/README.md
@@ -8,4 +8,4 @@ on how to build symqemu-x86_x64 and put it in your `PATH`.
just type `make` to build this custom mutator.
-```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_SYNC_TIME=1 AFL_DISABLE_TRIM=1 afl-fuzz ...```
+```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_DISABLE_TRIM=1 afl-fuzz ...```
diff --git a/custom_mutators/symqemu/symqemu.c b/custom_mutators/symqemu/symqemu.c
index 9030397b..163ae240 100644
--- a/custom_mutators/symqemu/symqemu.c
+++ b/custom_mutators/symqemu/symqemu.c
@@ -13,6 +13,9 @@
afl_state_t *afl_struct;
static u32 debug = 0;
+static u32 found_items = 0;
+
+#define SYMQEMU_LOCATION "symqemu"
#define DBG(x...) \
if (debug) { fprintf(stderr, x); }
@@ -22,7 +25,6 @@ typedef struct my_mutator {
afl_state_t *afl;
u8 *mutator_buf;
u8 *out_dir;
- u8 *queue_dir;
u8 *target;
u8 *symqemu;
u8 *input_file;
@@ -67,8 +69,13 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if (!data->symqemu) FATAL("symqemu binary %s not found", exec_name);
DBG("Found %s\n", data->symqemu);
- if (getenv("AFL_CUSTOM_MUTATOR_ONLY"))
- FATAL("the symqemu module cannot be used with AFL_CUSTOM_MUTATOR_ONLY.");
+ if (getenv("AFL_CUSTOM_MUTATOR_ONLY")) {
+
+ WARNF(
+ "the symqemu module is not very effective with "
+ "AFL_CUSTOM_MUTATOR_ONLY.");
+
+ }
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
@@ -84,14 +91,11 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
u32 len = strlen(path_tmp) + 32;
u8 *symqemu_path = malloc(len);
data->out_dir = malloc(len);
- data->queue_dir = malloc(len);
- snprintf(symqemu_path, len, "%s/../symqemu", path_tmp);
- snprintf(data->out_dir, len, "%s/../symqemu/out", path_tmp);
- snprintf(data->queue_dir, len, "%s/../symqemu/queue", path_tmp);
+ snprintf(symqemu_path, len, "%s/%s", path_tmp, SYMQEMU_LOCATION);
+ snprintf(data->out_dir, len, "%s/out", symqemu_path, path_tmp);
- mkdir(symqemu_path, 0755);
- mkdir(data->out_dir, 0755);
- mkdir(data->queue_dir, 0755);
+ (void)mkdir(symqemu_path, 0755);
+ (void)mkdir(data->out_dir, 0755);
setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1);
@@ -153,8 +157,8 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
data->argv[0] = data->symqemu;
data->argv[1] = data->target;
- DBG("out_dir=%s, queue_dir=%s, target=%s, input_file=%s, argc=%u\n",
- data->out_dir, data->queue_dir, data->target,
+ DBG("out_dir=%s, target=%s, input_file=%s, argc=%u\n", data->out_dir,
+ data->target,
data->input_file ? (char *)data->input_file : (char *)"",
data->argc);
@@ -174,29 +178,39 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
}
- OKF("Custom mutator symqemu loaded - note that the initial startup of "
- "afl-fuzz will be delayed the more starting seeds are present. This is "
- "fine, do not worry!");
-
return data;
}
-/* When a new queue entry is added we run this input with the symqemu
- instrumented binary */
-uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
- const uint8_t *filename_new_queue,
- const uint8_t *filename_orig_queue) {
+/* No need to receive a splicing item */
+void afl_custom_splice_optout(void *data) {
+
+ (void)(data);
+
+}
+
+u32 afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, size_t buf_size) {
+
+ if (likely(!afl_struct->queue_cur->favored ||
+ afl_struct->queue_cur->was_fuzzed)) {
+
+ return 0;
+
+ }
int pipefd[2];
struct stat st;
- if (data->afl->afl_env.afl_no_ui)
- ACTF("Sending to symqemu: %s", filename_new_queue);
- u8 *fn = alloc_printf("%s", filename_new_queue);
- if (!(stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size)) {
- ck_free(fn);
- PFATAL("Couldn't find enqueued file: %s", fn);
+ if (afl_struct->afl_env.afl_no_ui) {
+
+ ACTF("Sending to symqemu: %s", afl_struct->queue_cur->fname);
+
+ }
+
+ if (!(stat(afl_struct->queue_cur->fname, &st) == 0 && S_ISREG(st.st_mode) &&
+ st.st_size)) {
+
+ PFATAL("Couldn't find enqueued file: %s", afl_struct->queue_cur->fname);
}
@@ -204,7 +218,6 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
if (pipe(pipefd) == -1) {
- ck_free(fn);
PFATAL(
"Couldn't create a pipe for interacting with symqemu child process");
@@ -212,19 +225,12 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
}
- int fd = open(fn, O_RDONLY);
- if (fd < 0) return 0;
- ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
- DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r);
- ck_free(fn);
- close(fd);
-
if (data->input_file) {
- fd = open(data->input_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- ssize_t s = write(fd, data->mutator_buf, r);
+ int fd = open(data->input_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ ssize_t s = write(fd, buf, buf_size);
close(fd);
- DBG("wrote %zd/%zd to %s\n", s, r, data->input_file);
+ DBG("wrote %zd/%zd to %s\n", s, buf_size, data->input_file);
}
@@ -232,35 +238,20 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
if (pid == -1) return 0;
- if (pid) {
+ if (likely(pid)) {
if (!data->input_file || afl_struct->fsrv.use_stdin) {
close(pipefd[0]);
- if (fd >= 0) {
-
- if (r <= 0) {
-
- close(pipefd[1]);
- return 0;
-
- }
+ if (fcntl(pipefd[1], F_GETPIPE_SZ)) {
- if (r > fcntl(pipefd[1], F_GETPIPE_SZ))
- fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
- ck_write(pipefd[1], data->mutator_buf, r, filename_new_queue);
-
- } else {
-
- ck_free(fn);
- close(pipefd[1]);
- PFATAL(
- "Something happened to the enqueued file before sending its "
- "contents to symqemu binary");
+ fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
}
+ ck_write(pipefd[1], buf, buf_size, data->input_file);
+
close(pipefd[1]);
}
@@ -268,46 +259,6 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
pid = waitpid(pid, NULL, 0);
DBG("symqemu finished executing!\n");
- // At this point we need to transfer files to output dir, since their names
- // collide and symqemu will just overwrite them
-
- struct dirent **nl;
- int32_t items = scandir(data->out_dir, &nl, NULL, NULL);
- u8 *origin_name = basename(filename_new_queue);
- u8 source_name[4096], destination_name[4096];
- int32_t i;
-
- if (items > 0) {
-
- for (i = 0; i < (u32)items; ++i) {
-
- // symqemu output files start with a digit
- if (!isdigit(nl[i]->d_name[0])) continue;
-
- struct stat st;
- snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir,
- nl[i]->d_name);
- DBG("file=%s\n", source_name);
-
- if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
-
- snprintf(destination_name, sizeof(destination_name), "%s/id:%06u,%s",
- data->queue_dir, data->counter++, nl[i]->d_name);
- DBG("src=%s dst=%s\n", source_name, destination_name);
- rename(source_name, destination_name);
-
- }
-
- free(nl[i]);
-
- }
-
- free(nl);
-
- }
-
- DBG("Done!\n");
-
} else /* (pid == 0) */ { // child
if (afl_struct->fsrv.use_stdin) {
@@ -338,33 +289,31 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
}
- return 0;
-
-}
-
-/*
-uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
- size_t buf_size) {
+ /* back in mother process */
- uint32_t count = 0, i;
struct dirent **nl;
- int32_t items = scandir(data->out_dir, &nl, NULL, NULL);
+ s32 i, items = scandir(data->out_dir, &nl, NULL, NULL);
+ found_items = 0;
+ char source_name[4096];
if (items > 0) {
for (i = 0; i < (u32)items; ++i) {
+ // symqemu output files start with a digit
+ if (!isdigit(nl[i]->d_name[0])) continue;
+
struct stat st;
- 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) {
+ snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir,
+ nl[i]->d_name);
+ DBG("file=%s\n", source_name);
+
+ if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
- DBG("found=%s\n", fn);
- count++;
+ ++found_items;
}
- ck_free(fn);
free(nl[i]);
}
@@ -373,65 +322,67 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
}
- DBG("dir=%s, count=%u\n", data->out_dir, count);
- return count;
+ DBG("Done, found %u items!\n", found_items);
-}
+ return found_items;
-*/
+}
-// here we actually just read the files generated from symqemu
-/*
-size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
- u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
+size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
+ u8 **out_buf, u8 *add_buf, size_t add_buf_size,
size_t max_size) {
struct dirent **nl;
- int32_t i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL);
- ssize_t size = 0;
+ s32 done = 0, i, items = scandir(data->out_dir, &nl, NULL, NULL);
+ char source_name[4096];
- if (items <= 0) return 0;
+ if (items > 0) {
- for (i = 0; i < (u32)items; ++i) {
+ for (i = 0; i < (u32)items; ++i) {
- struct stat st;
- u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
+ // symqemu output files start with a digit
+ if (!isdigit(nl[i]->d_name[0])) continue;
- if (done == 0) {
+ struct stat st;
+ snprintf(source_name, sizeof(source_name), "%s/%s", data->out_dir,
+ nl[i]->d_name);
+ DBG("file=%s\n", source_name);
- if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
+ if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
- int fd = open(fn, O_RDONLY);
+ int fd = open(source_name, O_RDONLY);
+ if (fd < 0) { goto got_an_issue; }
- if (fd >= 0) {
+ ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
+ close(fd);
- size = read(fd, data->mutator_buf, max_size);
- *out_buf = data->mutator_buf;
+ DBG("fn=%s, fd=%d, size=%ld\n", source_name, fd, r);
- close(fd);
- done = 1;
+ if (r < 1) { goto got_an_issue; }
- }
+ done = 1;
+ --found_items;
+ unlink(source_name);
+
+ *out_buf = data->mutator_buf;
+ return (u32)r;
}
- unlink(fn);
+ free(nl[i]);
}
- ck_free(fn);
- free(nl[i]);
+ free(nl);
}
- free(nl);
- DBG("FUZZ size=%lu\n", size);
- return (uint32_t)size;
+got_an_issue:
+ *out_buf = NULL;
+ return 0;
}
-*/
-
/**
* Deinitialize everything
*
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 8fb7ecb1..beb2de2a 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -184,6 +184,7 @@ struct queue_entry {
handicap, /* Number of queue cycles behind */
depth, /* Path depth */
exec_cksum, /* Checksum of the execution trace */
+ custom, /* Marker for custom mutators */
stats_mutated; /* stats: # of mutations performed */
u8 *trace_mini; /* Trace bytes, if kept */
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index c6e9a295..5c71fc59 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1912,6 +1912,7 @@ custom_mutator_stage:
afl->stage_name = "custom mutator";
afl->stage_short = "custom";
+ afl->stage_cur = 0;
afl->stage_val_type = STAGE_VAL_NONE;
bool has_custom_fuzz = false;
u32 shift = unlikely(afl->custom_only) ? 7 : 8;
--
cgit 1.4.1
From 401d7617efbd2f38d9132eabfd1b1152abceda52 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 18 May 2023 10:50:10 +0200
Subject: symqemu mutator options
---
custom_mutators/aflpp_tritondse/README.md | 7 +++--
custom_mutators/symqemu/README.md | 10 ++++++-
custom_mutators/symqemu/symqemu.c | 44 +++++++++++++++++++++++++------
src/afl-common.c | 2 +-
4 files changed, 51 insertions(+), 12 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/aflpp_tritondse/README.md b/custom_mutators/aflpp_tritondse/README.md
index 8a5dd02b..608c2624 100644
--- a/custom_mutators/aflpp_tritondse/README.md
+++ b/custom_mutators/aflpp_tritondse/README.md
@@ -10,8 +10,11 @@
../../afl-cc -o ../../test-instr ../../test-instr.c
mkdir -p in
echo aaaa > in/in
-TRITON_DSE_TARGET=../../test-instr AFL_CUSTOM_MUTATOR_ONLY=1 AFL_SYNC_TIME=1 AFL_PYTHON_MODULE=aflpp_tritondse PYTHONPATH=. ../../afl-fuzz -i in -o out -- ../../test-instr
+AFL_DISABLE_TRIM=1 AFL_CUSTOM_MUTATOR_ONLY=1 AFL_SYNC_TIME=1 AFL_PYTHON_MODULE=aflpp_tritondse PYTHONPATH=. ../../afl-fuzz -i in -o out -- ../../test-instr
```
Note that this custom mutator works differently, new finds are synced
-after 10-60 seconds to the fuzzing instance.
+after 10-60 seconds to the fuzzing instance. This is necessary because only
+C/C++ mutators have access to the internal AFL++ state.
+
+Hence the symqemu customer mutator is more effective.
diff --git a/custom_mutators/symqemu/README.md b/custom_mutators/symqemu/README.md
index b7702c06..c3071afc 100644
--- a/custom_mutators/symqemu/README.md
+++ b/custom_mutators/symqemu/README.md
@@ -2,10 +2,18 @@
This uses the symcc to find new paths into the target.
+## How to build and use
+
To use this custom mutator follow the steps in the symqemu repository
[https://github.com/eurecom-s3/symqemu/](https://github.com/eurecom-s3/symqemu/)
on how to build symqemu-x86_x64 and put it in your `PATH`.
-just type `make` to build this custom mutator.
+Just type `make` to build this custom mutator.
```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/symqemu/symqemu-mutator.so AFL_DISABLE_TRIM=1 afl-fuzz ...```
+
+## Options
+
+`SYMQEMU_ALL=1` - use concolic solving on **all** queue items, not only interesting/favorite ones.
+
+`SYMQEMU_LATE=1` - use concolic solving only after there have been no finds for 5 minutes.
diff --git a/custom_mutators/symqemu/symqemu.c b/custom_mutators/symqemu/symqemu.c
index 163ae240..e2b07af6 100644
--- a/custom_mutators/symqemu/symqemu.c
+++ b/custom_mutators/symqemu/symqemu.c
@@ -23,6 +23,8 @@ static u32 found_items = 0;
typedef struct my_mutator {
afl_state_t *afl;
+ u32 all;
+ u32 late;
u8 *mutator_buf;
u8 *out_dir;
u8 *target;
@@ -156,18 +158,19 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
data->argv[0] = data->symqemu;
data->argv[1] = data->target;
+ data->afl = afl;
+ data->seed = seed;
+ afl_struct = afl;
+
+ if (getenv("SYMQEMU_ALL")) { data->all = 1; }
+ if (getenv("SYMQEMU_LATE")) { data->late = 1; }
+ if (data->input_file) { setenv("SYMCC_INPUT_FILE", data->input_file, 1); }
DBG("out_dir=%s, target=%s, input_file=%s, argc=%u\n", data->out_dir,
data->target,
data->input_file ? (char *)data->input_file : (char *)"",
data->argc);
- if (data->input_file) { setenv("SYMCC_INPUT_FILE", data->input_file, 1); }
-
- data->afl = afl;
- data->seed = seed;
- afl_struct = afl;
-
if (debug) {
fprintf(stderr, "[");
@@ -189,15 +192,40 @@ void afl_custom_splice_optout(void *data) {
}
+/* Get unix time in milliseconds */
+
+inline u64 get_cur_time(void) {
+
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+
+ return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+
+}
+
u32 afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf, size_t buf_size) {
- if (likely(!afl_struct->queue_cur->favored ||
- afl_struct->queue_cur->was_fuzzed)) {
+ if (likely((!afl_struct->queue_cur->favored ||
+ afl_struct->queue_cur->was_fuzzed) &&
+ !data->all)) {
return 0;
}
+ if (likely(data->late)) {
+
+ if (unlikely(get_cur_time() - afl_struct->last_find_time <=
+ 10 * 60 * 1000)) {
+
+ return 0;
+
+ }
+
+ }
+
int pipefd[2];
struct stat st;
diff --git a/src/afl-common.c b/src/afl-common.c
index a5c48e80..84ddefd8 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -949,7 +949,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
/* Get unix time in milliseconds */
-u64 get_cur_time(void) {
+inline u64 get_cur_time(void) {
struct timeval tv;
struct timezone tz;
--
cgit 1.4.1
From 53a869b757287e8bebdfcbc96b8abe1729955171 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 18 May 2023 14:45:45 +0200
Subject: act on invalid AFL_CUSTOM_MUTATOR_ONLY usage
---
src/afl-fuzz.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 4339ddd2..e2d8dea5 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1748,6 +1748,23 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->afl_env.afl_custom_mutator_only) {
+ if (!afl->custom_mutators_count) {
+
+ if (afl->shm.cmplog_mode) {
+
+ WARNF(
+ "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
+ "pointless and only allowed now to allow experiments with CMPLOG.");
+
+ } else {
+
+ FATAL(
+ "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
+
+ }
+
+ }
+
/* This ensures we don't proceed to havoc/splice */
afl->custom_only = 1;
--
cgit 1.4.1
From 9a6c0ec0c0af42d33e4350ee2958b58fef1c39dd Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 21 May 2023 13:04:17 +0200
Subject: make AFL_CUSTOM_INFO overridable
---
custom_mutators/symqemu/Makefile | 2 +-
src/afl-fuzz.c | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
(limited to 'src')
diff --git a/custom_mutators/symqemu/Makefile b/custom_mutators/symqemu/Makefile
index 3361ab0f..958aec19 100644
--- a/custom_mutators/symqemu/Makefile
+++ b/custom_mutators/symqemu/Makefile
@@ -8,7 +8,7 @@ all: symqemu-mutator.so
CFLAGS += -O3 -funroll-loops
symqemu-mutator.so: symqemu.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -g -I../../include -shared -fPIC -o symqemu-mutator.so symqemu.c
+ $(CC) -g $(CFLAGS) $(CPPFLAGS) -g -I../../include -shared -fPIC -o symqemu-mutator.so symqemu.c
clean:
rm -f symqemu-mutator.so *.o *~ core
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index e2d8dea5..a61718a7 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1833,7 +1833,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- {
+ if (!getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) {
u8 envbuf[8096] = "", tmpbuf[8096] = "";
for (s32 i = optind + 1; i < argc; ++i) {
@@ -1864,7 +1864,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
- setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
+ if (!getenv("AFL_CUSTOM_INFO_OUT") {
+
+ setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
+
+ }
setup_custom_mutators(afl);
--
cgit 1.4.1
From d4085314c1c1d4e8bbe4159216f8cb83e0804ea7 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 21 May 2023 13:44:07 +0200
Subject: fix
---
src/afl-fuzz.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index a61718a7..559a7326 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1864,7 +1864,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!getenv("AFL_CUSTOM_INFO_OUT") {
+ if (!getenv("AFL_CUSTOM_INFO_OUT")) {
setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
--
cgit 1.4.1
From 029e039cbcbf9e30f35eb255162679b8d609d25d Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Sun, 21 May 2023 17:49:14 +0200
Subject: code format
---
.custom-format.py | 2 +-
frida_mode/src/lib/lib_apple.c | 4 +--
include/config.h | 2 +-
instrumentation/SanitizerCoverageLTO.so.cc | 4 +--
instrumentation/SanitizerCoveragePCGUARD.so.cc | 4 +--
instrumentation/afl-compiler-rt.o.c | 14 +++++-----
instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +-
instrumentation/cmplog-routines-pass.cc | 4 +--
instrumentation/compare-transform-pass.so.cc | 2 +-
instrumentation/split-compares-pass.so.cc | 2 +-
qemu_mode/libcompcov/libcompcov.so.c | 6 ++++-
src/afl-cc.c | 8 +++---
src/afl-fuzz-redqueen.c | 32 +++++++++++------------
utils/afl_untracer/afl-untracer.c | 2 +-
utils/libtokencap/libtokencap.so.c | 6 ++++-
utils/socket_fuzzing/socketfuzz.c | 3 ++-
16 files changed, 53 insertions(+), 44 deletions(-)
(limited to 'src')
diff --git a/.custom-format.py b/.custom-format.py
index 1295ce55..1d5c8839 100755
--- a/.custom-format.py
+++ b/.custom-format.py
@@ -24,7 +24,7 @@ import importlib.metadata
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
-CURRENT_LLVM = os.getenv('LLVM_VERSION', 14)
+CURRENT_LLVM = os.getenv('LLVM_VERSION', 15)
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c
index 634e0e30..d29d0303 100644
--- a/frida_mode/src/lib/lib_apple.c
+++ b/frida_mode/src/lib/lib_apple.c
@@ -17,8 +17,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
GumDarwinModule **ret = (GumDarwinModule **)user_data;
GumDarwinModule *module = gum_darwin_module_new_from_memory(
- details->path, mach_task_self(), details->range->base_address,
- GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
+ details->path, mach_task_self(), details->range->base_address,
+ GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
FVERBOSE("Found main module: %s", module->name);
diff --git a/include/config.h b/include/config.h
index 764c29dc..194786f7 100644
--- a/include/config.h
+++ b/include/config.h
@@ -81,7 +81,7 @@
will be kept and written to the crash/ directory as RECORD:... files.
Note that every crash will be written, not only unique ones! */
-//#define AFL_PERSISTENT_RECORD
+// #define AFL_PERSISTENT_RECORD
/* console output colors: There are three ways to configure its behavior
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index b3b0d2cd..d7b03634 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -1478,8 +1478,8 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreateFunctionLocalArrayInSection(
ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
auto Array = new GlobalVariable(
- *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
- Constant::getNullValue(ArrayTy), "__sancov_gen_");
+ *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
+ Constant::getNullValue(ArrayTy), "__sancov_gen_");
#if LLVM_VERSION_MAJOR >= 13
if (TargetTriple.supportsCOMDAT() &&
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 41c38283..8fed2042 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -714,8 +714,8 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
auto Array = new GlobalVariable(
- *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
- Constant::getNullValue(ArrayTy), "__sancov_gen_");
+ *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
+ Constant::getNullValue(ArrayTy), "__sancov_gen_");
#if LLVM_VERSION_MAJOR >= 13
if (TargetTriple.supportsCOMDAT() &&
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 5372fae0..3f8b519b 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -544,12 +544,12 @@ static void __afl_map_shm(void) {
if (__afl_map_size && __afl_map_size > MAP_SIZE) {
- u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
- if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
+ u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
+ if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
- fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
- send_forkserver_error(FS_ERROR_MAP_SIZE);
- _exit(1);
+ fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
+ send_forkserver_error(FS_ERROR_MAP_SIZE);
+ _exit(1);
}
@@ -561,13 +561,13 @@ static void __afl_map_shm(void) {
if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) {
- if (__afl_map_addr)
+ if (__afl_map_addr)
send_forkserver_error(FS_ERROR_MAP_ADDR);
else
send_forkserver_error(FS_ERROR_SHMAT);
perror("shmat for map");
- _exit(1);
+ _exit(1);
}
diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
index db5bd55e..61f97d77 100644
--- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc
@@ -45,7 +45,7 @@
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
-//#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+// #include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc
index 39db5aa4..c3fbed8d 100644
--- a/instrumentation/cmplog-routines-pass.cc
+++ b/instrumentation/cmplog-routines-pass.cc
@@ -542,7 +542,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
Value *v3Pbitcast = IRB.CreateBitCast(
- v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
+ v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
Value *v3Pcasted =
IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false);
args.push_back(v1Pcasted);
@@ -608,7 +608,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
Value *v3Pbitcast = IRB.CreateBitCast(
- v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
+ v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits()));
Value *v3Pcasted =
IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false);
args.push_back(v1Pcasted);
diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc
index efc99d20..5dd705cf 100644
--- a/instrumentation/compare-transform-pass.so.cc
+++ b/instrumentation/compare-transform-pass.so.cc
@@ -623,7 +623,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
IRBuilder<> cur_lenchk_IRB(&*(cur_lenchk_bb->getFirstInsertionPt()));
Value *icmp = cur_lenchk_IRB.CreateICmpEQ(
- sizedValue, ConstantInt::get(sizedValue->getType(), i));
+ sizedValue, ConstantInt::get(sizedValue->getType(), i));
cur_lenchk_IRB.CreateCondBr(icmp, end_bb, cur_cmp_bb);
cur_lenchk_bb->getTerminator()->eraseFromParent();
diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc
index 8a07610c..aec6758e 100644
--- a/instrumentation/split-compares-pass.so.cc
+++ b/instrumentation/split-compares-pass.so.cc
@@ -60,7 +60,7 @@ using namespace llvm;
// uncomment this toggle function verification at each step. horribly slow, but
// helps to pinpoint a potential problem in the splitting code.
-//#define VERIFY_TOO_MUCH 1
+// #define VERIFY_TOO_MUCH 1
namespace {
diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c
index b6ee0019..b57e9701 100644
--- a/qemu_mode/libcompcov/libcompcov.so.c
+++ b/qemu_mode/libcompcov/libcompcov.so.c
@@ -68,7 +68,11 @@ static int debug_fd = -1;
#define MAX_MAPPINGS 1024
-static struct mapping { void *st, *en; } __compcov_ro[MAX_MAPPINGS];
+static struct mapping {
+
+ void *st, *en;
+
+} __compcov_ro[MAX_MAPPINGS];
static u32 __compcov_ro_cnt;
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 972ac8cd..e3cc04dd 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -933,10 +933,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- //#if LLVM_MAJOR >= 13
- // // Use the old pass manager in LLVM 14 which the AFL++ passes still
- // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
- //#endif
+ // #if LLVM_MAJOR >= 13
+ // // Use the old pass manager in LLVM 14 which the AFL++ passes still
+ // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
+ // #endif
if (lto_mode && !have_c) {
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 6e4a655b..d9dc50df 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -28,8 +28,8 @@
#include "afl-fuzz.h"
#include "cmplog.h"
-//#define _DEBUG
-//#define CMPLOG_INTROSPECTION
+// #define _DEBUG
+// #define CMPLOG_INTROSPECTION
// CMP attribute enum
enum {
@@ -571,7 +571,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
}
-//#ifdef CMPLOG_SOLVE_TRANSFORM
+// #ifdef CMPLOG_SOLVE_TRANSFORM
static int strntoll(const char *str, size_t sz, char **end, int base,
long long *out) {
@@ -771,7 +771,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
#endif
-//#endif
+// #endif
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern,
@@ -803,8 +803,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// o_pattern, pattern, repl, changed_val, idx, taint_len,
// hshape, attr);
- //#ifdef CMPLOG_SOLVE_TRANSFORM
- // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
+ // #ifdef CMPLOG_SOLVE_TRANSFORM
+ // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u8 *endptr;
@@ -1120,7 +1120,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- //#endif
+ // #endif
// we only allow this for ascii2integer (above) so leave if this is the case
if (unlikely(pattern == o_pattern)) { return 0; }
@@ -1275,7 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// 16 = modified float, 32 = modified integer (modified = wont match
// in original buffer)
- //#ifdef CMPLOG_SOLVE_ARITHMETIC
+ // #ifdef CMPLOG_SOLVE_ARITHMETIC
if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
return 0;
@@ -1440,8 +1440,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- //#endif /*
- // CMPLOG_SOLVE_ARITHMETIC
+ // #endif /*
+ // CMPLOG_SOLVE_ARITHMETIC
return 0;
@@ -1948,9 +1948,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
#ifndef CMPLOG_COMBINE
(void)(cbuf);
#endif
- //#ifndef CMPLOG_SOLVE_TRANSFORM
- // (void)(changed_val);
- //#endif
+ // #ifndef CMPLOG_SOLVE_TRANSFORM
+ // (void)(changed_val);
+ // #endif
if (afl->fsrv.total_execs - last_update > screen_update) {
@@ -2418,7 +2418,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
- //#endif
+ // #endif
return 0;
@@ -2818,9 +2818,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} else if ((lvl & LVL1)
- //#ifdef CMPLOG_SOLVE_TRANSFORM
+ // #ifdef CMPLOG_SOLVE_TRANSFORM
|| ((lvl & LVL3) && afl->cmplog_enable_transform)
- //#endif
+ // #endif
) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c
index a18e314e..e1038212 100644
--- a/utils/afl_untracer/afl-untracer.c
+++ b/utils/afl_untracer/afl-untracer.c
@@ -288,7 +288,7 @@ library_list_t *find_library(char *name) {
#pragma GCC optimize("O0")
void breakpoint(void) {
- if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n");
+ if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n");
}
diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c
index 299056ab..b21f3068 100644
--- a/utils/libtokencap/libtokencap.so.c
+++ b/utils/libtokencap/libtokencap.so.c
@@ -81,7 +81,11 @@ void *(*__libc_memmem)(const void *haystack, size_t haystack_len,
#define MAX_MAPPINGS 1024
-static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS];
+static struct mapping {
+
+ void *st, *en;
+
+} __tokencap_ro[MAX_MAPPINGS];
static u32 __tokencap_ro_cnt;
static u8 __tokencap_ro_loaded;
diff --git a/utils/socket_fuzzing/socketfuzz.c b/utils/socket_fuzzing/socketfuzz.c
index 3ec8383b..7497519e 100644
--- a/utils/socket_fuzzing/socketfuzz.c
+++ b/utils/socket_fuzzing/socketfuzz.c
@@ -23,7 +23,8 @@
#include
#include
#include
-//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: "
+// #include "logging.h" // switched from preeny_info() to fprintf(stderr, "Info:
+// "
//
// originals
--
cgit 1.4.1
From d5e3223f0340181e74d352db3def2c98cf14d628 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 23 May 2023 09:01:49 +0200
Subject: fix custom mutator only check
---
src/afl-fuzz.c | 54 +++++++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 27 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 559a7326..4134b99e 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1746,33 +1746,6 @@ int main(int argc, char **argv_orig, char **envp) {
check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
- if (afl->afl_env.afl_custom_mutator_only) {
-
- if (!afl->custom_mutators_count) {
-
- if (afl->shm.cmplog_mode) {
-
- WARNF(
- "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
- "pointless and only allowed now to allow experiments with CMPLOG.");
-
- } else {
-
- FATAL(
- "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
-
- }
-
- }
-
- /* This ensures we don't proceed to havoc/splice */
- afl->custom_only = 1;
-
- /* Ensure we also skip all deterministic steps */
- afl->skip_deterministic = 1;
-
- }
-
get_core_count(afl);
atexit(at_exit);
@@ -1872,6 +1845,33 @@ int main(int argc, char **argv_orig, char **envp) {
setup_custom_mutators(afl);
+ if (afl->afl_env.afl_custom_mutator_only) {
+
+ if (!afl->custom_mutators_count) {
+
+ if (afl->shm.cmplog_mode) {
+
+ WARNF(
+ "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
+ "pointless and only allowed now to allow experiments with CMPLOG.");
+
+ } else {
+
+ FATAL(
+ "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
+
+ }
+
+ }
+
+ /* This ensures we don't proceed to havoc/splice */
+ afl->custom_only = 1;
+
+ /* Ensure we also skip all deterministic steps */
+ afl->skip_deterministic = 1;
+
+ }
+
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
--
cgit 1.4.1
From dd736126dc9da78d6828cdf76f7eb8b389af7ed3 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 23 May 2023 09:06:29 +0200
Subject: allow llvm_instrument native
---
src/afl-cc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/afl-cc.c b/src/afl-cc.c
index e3cc04dd..64c0ce66 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -1838,7 +1838,8 @@ int main(int argc, char **argv, char **envp) {
}
if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 ||
- strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) {
+ strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 ||
+ strncasecmp(ptr2, "native", strlen("native")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE)
instrument_mode = INSTRUMENT_LLVMNATIVE;
--
cgit 1.4.1
From 22837b5ad2d1cc6313c706ac9cb7fcd005cd3c2c Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 23 May 2023 12:14:58 +0200
Subject: response file fix
---
src/afl-cc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
(limited to 'src')
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 64c0ce66..84fe70ec 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -574,14 +574,15 @@ static void process_params(u32 argc, char **argv) {
}
- u8 *tmpbuf = malloc(st.st_size + 1), *ptr;
+ u8 *tmpbuf = malloc(st.st_size + 2), *ptr;
char **args = malloc(sizeof(char *) * (st.st_size >> 1));
int count = 1, cont = 0, cont_act = 0;
- while (fgets(tmpbuf, st.st_size, f)) {
+ while (fgets(tmpbuf, st.st_size + 1, f)) {
ptr = tmpbuf;
- // no leading whitespace
+ // fprintf(stderr, "1: %s\n", ptr);
+ // no leading whitespace
while (isspace(*ptr)) {
++ptr;
@@ -603,6 +604,8 @@ static void process_params(u32 argc, char **argv) {
}
+ // fprintf(stderr, "2: %s\n", ptr);
+
// remove whitespace at end
while (*ptr && isspace(ptr[strlen(ptr) - 1])) {
@@ -611,6 +614,7 @@ static void process_params(u32 argc, char **argv) {
}
+ // fprintf(stderr, "3: %s\n", ptr);
if (*ptr) {
do {
--
cgit 1.4.1
From eeed38c5f8335b5a2b69d85b950aa33682a2c079 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 23 May 2023 18:31:34 +0200
Subject: fix gnumakefile for non-gcc
---
GNUmakefile | 11 ++++++++---
src/afl-fuzz-redqueen.c | 12 ++++++------
2 files changed, 14 insertions(+), 9 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile b/GNUmakefile
index 4ecdae52..6962d28a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -100,8 +100,13 @@ else
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
+endif
+
ifeq "$(SYS)" "SunOS"
- CFLAGS_OPT += -Wno-format-truncation
LDFLAGS = -lkstat -lrt -lsocket -lnsl
endif
@@ -139,13 +144,13 @@ endif
ifdef DEBUG
$(info Compiling DEBUG version of binaries)
- override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror -Wno-error=format-truncation= $(CFLAGS_OPT)
+ override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
else
CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
endif
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wno-pointer-arith \
- -fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" -Wno-format-truncation \
+ -fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
# -fstack-protector
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index d9dc50df..7f42db3f 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -379,7 +379,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
}
- if (++afl->stage_cur % screen_update == 0) { show_stats(afl); };
+ if (unlikely(++afl->stage_cur % screen_update == 0)) { show_stats(afl); };
}
@@ -790,7 +790,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 its_len = MIN(len - idx, taint_len);
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -1455,7 +1455,7 @@ static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 do_reverse, u8 lvl, u8 *status) {
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -1952,7 +1952,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
// (void)(changed_val);
// #endif
- if (afl->fsrv.total_execs - last_update > screen_update) {
+ if (unlikely(afl->fsrv.total_execs - last_update > screen_update)) {
show_stats(afl);
last_update = afl->fsrv.total_execs;
@@ -2002,10 +2002,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
- u8 lmax = MAX(l0, ol0);
+ u8 lmin = MIN(l0, ol0);
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
- u32 its_len = MIN(MIN(lmax, hshape), len - idx);
+ u32 its_len = MIN(MIN(lmin, hshape), len - idx);
its_len = MIN(its_len, taint_len);
u32 saved_its_len = its_len;
--
cgit 1.4.1
From c323e0dc63e97299da4a2f775f6f1639d5e13bf0 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Tue, 23 May 2023 19:46:35 +0200
Subject: revert fix
---
src/afl-fuzz-redqueen.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'src')
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 7f42db3f..41644cb9 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -2002,10 +2002,10 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
- u8 lmin = MIN(l0, ol0);
+ u8 lmax = MAX(l0, ol0);
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
- u32 its_len = MIN(MIN(lmin, hshape), len - idx);
+ u32 its_len = MIN(MIN(lmax, hshape), len - idx);
its_len = MIN(its_len, taint_len);
u32 saved_its_len = its_len;
--
cgit 1.4.1
From ad8f7d6eb3be245202ace23d4d1dd9152647a775 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Wed, 31 May 2023 11:40:48 +0200
Subject: switch user mailinglist reference to discord
---
TODO.md | 1 +
src/afl-forkserver.c | 8 ++++----
src/afl-fuzz-init.c | 4 ++--
3 files changed, 7 insertions(+), 6 deletions(-)
(limited to 'src')
diff --git a/TODO.md b/TODO.md
index d6a2e6fd..dc02a914 100644
--- a/TODO.md
+++ b/TODO.md
@@ -3,6 +3,7 @@
## Should
- redo PCGUARD + LTO for llvm 15+
+ - test cmplog for less than 16bit
- splicing selection weighted?
- support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 30c8901c..7322f1ad 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -1226,7 +1226,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n");
} else {
@@ -1271,7 +1271,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n",
stringify_mem_size(val_buf, sizeof(val_buf), fsrv->mem_limit << 20),
fsrv->mem_limit - 1);
@@ -1321,7 +1321,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" Retry with setting AFL_MAP_SIZE=10000000.\n\n"
"Otherwise there is a horrible bug in the fuzzer.\n"
- "Poke for troubleshooting tips.\n");
+ "Poke the Awesome Fuzzing Discord for troubleshooting tips.\n");
} else {
@@ -1370,7 +1370,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
- " fail, poke for troubleshooting "
+ " fail, poke the Awesome Fuzzing Discord for troubleshooting "
"tips.\n",
getenv(DEFER_ENV_VAR)
? " - You are using deferred forkserver, but __AFL_INIT() is "
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index baf56a5f..13802f40 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -1012,7 +1012,7 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n"
- " fail, poke for "
+ " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n",
stringify_mem_size(val_buf, sizeof(val_buf),
afl->fsrv.mem_limit << 20),
@@ -1041,7 +1041,7 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n"
- " fail, poke for "
+ " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n");
}
--
cgit 1.4.1
From 9324f3f6289c62451e2add1f7553a7eda0d7d642 Mon Sep 17 00:00:00 2001
From: vanhauser-thc
Date: Thu, 1 Jun 2023 12:19:45 +0200
Subject: rewrote PCGUARD
---
GNUmakefile.llvm | 4 +-
TODO.md | 2 -
afl-cmin.bash | 4 +-
docs/Changelog.md | 5 +-
instrumentation/SanitizerCoveragePCGUARD.so.cc | 603 +++++++++----------------
src/afl-cc.c | 31 +-
6 files changed, 249 insertions(+), 400 deletions(-)
(limited to 'src')
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index 2bb4e7f8..6c68f1f3 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -49,7 +49,7 @@ LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && 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 )
-LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
+LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 )
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 )
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
@@ -422,7 +422,7 @@ endif
$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
-ifeq "$(LLVM_10_OK)" "1"
+ifeq "$(LLVM_13_OK)" "1"
-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
endif
diff --git a/TODO.md b/TODO.md
index dc02a914..2b7e8fcf 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,9 +2,7 @@
## Should
- - redo PCGUARD + LTO for llvm 15+
- test cmplog for less than 16bit
- - splicing selection weighted?
- support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
- Update afl->pending_not_fuzzed for MOpt
diff --git a/afl-cmin.bash b/afl-cmin.bash
index d390ff65..dc6d5342 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -206,7 +206,7 @@ fi
# Check for obvious errors.
-if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" -a ! "$NYX_MODE" == 1 ]; then
+if [ ! "$T_ARG" = "" -a -n "$F_ARG" -a ! "$NYX_MODE" == 1 ]; then
echo "[-] Error: -T and -f can not be used together." 1>&2
exit 1
fi
@@ -323,7 +323,7 @@ if [ ! "$T_ARG" = "" ]; then
fi
fi
else
- if [ "$F_ARG" = ""]; then
+ if [ -z "$F_ARG" ]; then
echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?"
fi
fi
diff --git a/docs/Changelog.md b/docs/Changelog.md
index e99747f6..facf2196 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -15,13 +15,16 @@
- new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
(https://github.com/fgsect/WAFL) project
- error and print help if afl-clan-lto is used with lto=thin
+ - rewrote our PCGUARD pass to be compatible with LLVM 15+ shenanigans,
+ requires LLVM 13+ now instead of 10.0.1+
+ - fallback to native LLVM PCGUARD if our PCGUARD is unavailable
- afl-showmap:
- added custom mutator post_process and send support
- add `-I filelist` option, an alternative to `-i in_dir`
- afl-cmin + afl-cmin.bash:
- `-T threads` parallel task support, can be a huge speedup!
- qemu_mode:
- - Persistent mode +QASAN support for ppc32 tragets by @worksbutnottested
+ - Persistent mode + QASAN support for ppc32 targets by @worksbutnottested
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
- two new custom mutators are now available:
- TritonDSE in custom_mutators/aflpp_tritondse
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 8fed2042..2abc58ec 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -13,42 +13,64 @@
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#if LLVM_VERSION_MAJOR >= 15
+ #if LLVM_VERSION_MAJOR < 17
+ #include "llvm/ADT/Triple.h"
+ #endif
+#endif
#if LLVM_VERSION_MAJOR < 17
- #include "llvm/ADT/Triple.h"
#include "llvm/Analysis/EHPersonalities.h"
-#else
- #include "llvm/IR/EHPersonalities.h"
#endif
#include "llvm/Analysis/PostDominators.h"
-#include "llvm/IR/CFG.h"
+#if LLVM_VERSION_MAJOR < 15
+ #include "llvm/IR/CFG.h"
+#endif
#include "llvm/IR/Constant.h"
#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DebugInfo.h"
+#if LLVM_VERSION_MAJOR < 15
+ #include "llvm/IR/DebugInfo.h"
+#endif
#include "llvm/IR/Dominators.h"
+#if LLVM_VERSION_MAJOR >= 17
+ #include "llvm/Analysis/EHPersonalities.h"
+#endif
#include "llvm/IR/Function.h"
-#include "llvm/IR/GlobalVariable.h"
+#if LLVM_VERSION_MAJOR >= 16
+ #include "llvm/IR/GlobalVariable.h"
+#endif
#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/InlineAsm.h"
+#if LLVM_VERSION_MAJOR < 15
+ #include "llvm/IR/InlineAsm.h"
+#endif
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/MDBuilder.h"
-#include "llvm/IR/Mangler.h"
+#if LLVM_VERSION_MAJOR < 15
+ #include "llvm/IR/MDBuilder.h"
+ #include "llvm/IR/Mangler.h"
+#endif
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
#include "llvm/IR/Type.h"
-#include "llvm/InitializePasses.h"
+#if LLVM_VERSION_MAJOR < 17
+ #include "llvm/InitializePasses.h"
+#endif
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/Instrumentation.h"
+#if LLVM_VERSION_MAJOR < 15
+ #include "llvm/Support/raw_ostream.h"
+#endif
+#if LLVM_VERSION_MAJOR < 17
+ #include "llvm/Transforms/Instrumentation.h"
+#else
+ #include "llvm/TargetParser/Triple.h"
+#endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
-#include "llvm/Passes/PassPlugin.h"
-#include "llvm/Passes/PassBuilder.h"
-#include "llvm/IR/PassManager.h"
#include "config.h"
#include "debug.h"
@@ -58,7 +80,8 @@ using namespace llvm;
#define DEBUG_TYPE "sancov"
-const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir";
+static const uint64_t SanCtorAndDtorPriority = 2;
+
const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc";
const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1";
const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2";
@@ -68,22 +91,13 @@ const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1";
const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2";
const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4";
const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8";
-const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4";
-const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8";
-const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep";
const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch";
+
const char SanCovModuleCtorTracePcGuardName[] =
"sancov.module_ctor_trace_pc_guard";
-const char SanCovModuleCtor8bitCountersName[] =
- "sancov.module_ctor_8bit_counters";
-const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag";
-static const uint64_t SanCtorAndDtorPriority = 2;
+const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init";
const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard";
-const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init";
-const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init";
-const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init";
-const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init";
const char SanCovGuardsSectionName[] = "sancov_guards";
const char SanCovCountersSectionName[] = "sancov_cntrs";
@@ -99,27 +113,9 @@ namespace {
SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
- // Sets CoverageType and IndirectCalls.
- // SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel);
- Options.CoverageType =
- SanitizerCoverageOptions::SCK_Edge; // std::max(Options.CoverageType,
- // CLOpts.CoverageType);
- Options.IndirectCalls = false; // CLOpts.IndirectCalls;
- Options.TraceCmp = false; //|= ClCMPTracing;
- Options.TraceDiv = false; //|= ClDIVTracing;
- Options.TraceGep = false; //|= ClGEPTracing;
- Options.TracePC = false; //|= ClTracePC;
- Options.TracePCGuard = true; // |= ClTracePCGuard;
- Options.Inline8bitCounters = 0; //|= ClInline8bitCounters;
- // Options.InlineBoolFlag = 0; //|= ClInlineBoolFlag;
- Options.PCTable = false; //|= ClCreatePCTable;
- Options.NoPrune = false; //|= !ClPruneBlocks;
- Options.StackDepth = false; //|= ClStackDepth;
- if (!Options.TracePCGuard && !Options.TracePC &&
- !Options.Inline8bitCounters && !Options.StackDepth /*&&
- !Options.InlineBoolFlag*/)
- Options.TracePCGuard = true; // TracePCGuard is default.
-
+ Options.CoverageType = SanitizerCoverageOptions::SCK_Edge;
+ // Options.NoPrune = true;
+ Options.TracePCGuard = true; // TracePCGuard is default.
return Options;
}
@@ -139,20 +135,13 @@ class ModuleSanitizerCoverageAFL
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
-
- bool instrumentModule(Module &M, DomTreeCallback DTCallback,
- PostDomTreeCallback PDTCallback);
+ bool instrumentModule(Module &M, DomTreeCallback DTCallback,
+ PostDomTreeCallback PDTCallback);
private:
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
- void InjectCoverageForIndirectCalls(Function &F,
- ArrayRef IndirCalls);
void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets);
- void InjectTraceForDiv(Function &F,
- ArrayRef DivTraceTargets);
- void InjectTraceForGep(Function &F,
- ArrayRef GepTraceTargets);
void InjectTraceForSwitch(Function &F,
ArrayRef SwitchTraceTargets);
bool InjectCoverage(Function &F, ArrayRef AllBlocks,
@@ -173,20 +162,23 @@ class ModuleSanitizerCoverageAFL
void SetNoSanitizeMetadata(Instruction *I) {
+#if LLVM_VERSION_MAJOR == 15
+ I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, None));
+#elif LLVM_VERSION_MAJOR >= 16
+ I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
+#else
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
MDNode::get(*C, None));
+#endif
}
std::string getSectionName(const std::string &Section) const;
std::string getSectionStart(const std::string &Section) const;
std::string getSectionEnd(const std::string &Section) const;
- FunctionCallee SanCovTracePCIndir;
FunctionCallee SanCovTracePC, SanCovTracePCGuard;
FunctionCallee SanCovTraceCmpFunction[4];
FunctionCallee SanCovTraceConstCmpFunction[4];
- FunctionCallee SanCovTraceDivFunction[2];
- FunctionCallee SanCovTraceGepFunction;
FunctionCallee SanCovTraceSwitchFunction;
GlobalVariable *SanCovLowestStack;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
@@ -215,18 +207,16 @@ class ModuleSanitizerCoverageAFL
} // namespace
-#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
-
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
- return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1",
+ return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.2",
/* lambda to insert our pass into the pass pipeline. */
[](PassBuilder &PB) {
- #if LLVM_VERSION_MAJOR <= 13
+#if LLVM_VERSION_MAJOR == 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
- #endif
+#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
@@ -238,8 +228,7 @@ llvmGetPassPluginInfo() {
}
-#endif
-
+#if LLVM_VERSION_MAJOR == 1
PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
ModuleAnalysisManager &MAM) {
@@ -257,34 +246,65 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
};
+ if (!ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon();
+ return PA;
+
+}
+
+#else
+ #if LLVM_VERSION_MAJOR >= 16
+PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+
+ #else
+PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+
+ #endif
+ ModuleSanitizerCoverageAFL ModuleSancov(Options);
+ auto &FAM = MAM.getResult(M).getManager();
+ auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
+
+ return &FAM.getResult(F);
+
+ };
+
+ auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * {
+
+ return &FAM.getResult(F);
+
+ };
+
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
+#endif
+
std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd(
Module &M, const char *Section, Type *Ty) {
- GlobalVariable *SecStart =
- new GlobalVariable(M,
-#if LLVM_VERSION_MAJOR >= 15
- Ty,
-#else
- Ty->getPointerElementType(),
-#endif
- false, GlobalVariable::ExternalWeakLinkage, nullptr,
- getSectionStart(Section));
+ // Use ExternalWeak so that if all sections are discarded due to section
+ // garbage collection, the linker will not report undefined symbol errors.
+ // Windows defines the start/stop symbols in compiler-rt so no need for
+ // ExternalWeak.
+ GlobalValue::LinkageTypes Linkage = TargetTriple.isOSBinFormatCOFF()
+ ? GlobalVariable::ExternalLinkage
+ : GlobalVariable::ExternalWeakLinkage;
+ GlobalVariable *SecStart = new GlobalVariable(M, Ty, false, Linkage, nullptr,
+ getSectionStart(Section));
SecStart->setVisibility(GlobalValue::HiddenVisibility);
- GlobalVariable *SecEnd =
- new GlobalVariable(M,
-#if LLVM_VERSION_MAJOR >= 15
- Ty,
-#else
- Ty->getPointerElementType(),
-#endif
- false, GlobalVariable::ExternalWeakLinkage, nullptr,
- getSectionEnd(Section));
+ GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr,
+ getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility);
IRBuilder<> IRB(M.getContext());
if (!TargetTriple.isOSBinFormatCOFF())
@@ -295,7 +315,8 @@ std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd(
auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
ConstantInt::get(IntptrTy, sizeof(uint64_t)));
- return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEnd);
+ return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)),
+ SecEnd);
}
@@ -307,8 +328,9 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
auto SecStart = SecStartEnd.first;
auto SecEnd = SecStartEnd.second;
Function *CtorFunc;
+ Type *PtrTy = PointerType::getUnqual(Ty);
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
- M, CtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd});
+ M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd});
assert(CtorFunc->getName() == CtorName);
if (TargetTriple.supportsCOMDAT()) {
@@ -332,7 +354,6 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
// to include the sancov constructor. This way the linker can deduplicate
// the constructors but always leave one copy.
CtorFunc->setLinkage(GlobalValue::WeakODRLinkage);
- appendToUsed(M, CtorFunc);
}
@@ -344,37 +365,25 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
setvbuf(stdout, NULL, _IONBF, 0);
- if (getenv("AFL_DEBUG")) debug = 1;
+
+ if (getenv("AFL_DEBUG")) { debug = 1; }
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
- } else
+ } else {
be_quiet = 1;
+ }
+
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
initInstrumentList();
scanForDangerousFunctions(&M);
- if (debug) {
-
- fprintf(stderr,
- "SANCOV: covtype:%u indirect:%d stack:%d noprune:%d "
- "createtable:%d tracepcguard:%d tracepc:%d\n",
- Options.CoverageType, Options.IndirectCalls == true ? 1 : 0,
- Options.StackDepth == true ? 1 : 0, Options.NoPrune == true ? 1 : 0,
- // Options.InlineBoolFlag == true ? 1 : 0,
- Options.PCTable == true ? 1 : 0,
- Options.TracePCGuard == true ? 1 : 0,
- Options.TracePC == true ? 1 : 0);
-
- }
-
- if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false;
C = &(M.getContext());
DL = &M.getDataLayout();
CurModule = &M;
@@ -397,16 +406,14 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
- LLVMContext &Ctx = M.getContext();
+ LLVMContext &Ctx = M.getContext();
AFLMapPtr =
new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
One = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 1);
Zero = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 0);
- SanCovTracePCIndir =
- M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy);
// Make sure smaller parameters are zero-extended to i64 if required by the
// target ABI.
AttributeList SanCovTraceCmpZeroExtAL;
@@ -436,26 +443,13 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
SanCovTraceConstCmpFunction[3] =
M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty);
- {
-
- AttributeList AL;
- AL = AL.addParamAttribute(*C, 0, Attribute::ZExt);
- SanCovTraceDivFunction[0] =
- M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty());
-
- }
-
- SanCovTraceDivFunction[1] =
- M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty);
- SanCovTraceGepFunction =
- M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy);
SanCovTraceSwitchFunction =
M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy);
Constant *SanCovLowestStackConstant =
M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
SanCovLowestStack = dyn_cast(SanCovLowestStackConstant);
- if (!SanCovLowestStack) {
+ if (!SanCovLowestStack || SanCovLowestStack->getValueType() != IntptrTy) {
C->emitError(StringRef("'") + SanCovLowestStackName +
"' should not be declared by the user");
@@ -465,8 +459,6 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
SanCovLowestStack->setThreadLocalMode(
GlobalValue::ThreadLocalMode::InitialExecTLSModel);
- if (Options.StackDepth && !SanCovLowestStack->isDeclaration())
- SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy));
SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy);
SanCovTracePCGuard =
@@ -481,40 +473,25 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,
SanCovTracePCGuardInitName, Int32PtrTy,
SanCovGuardsSectionName);
- if (Function8bitCounterArray)
- Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
- SanCov8bitCountersInitName, Int8PtrTy,
- SanCovCountersSectionName);
- if (FunctionBoolArray) {
-
- Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName,
- SanCovBoolFlagInitName, Int1PtrTy,
- SanCovBoolFlagSectionName);
- }
-
- if (Ctor && Options.PCTable) {
+ if (Ctor && debug) {
- auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
- FunctionCallee InitFunction = declareSanitizerInitFunction(
- M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
- IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
- IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
+ fprintf(stderr, "SANCOV: installed pcguard_init in ctor\n");
}
- // We don't reference these arrays directly in any of our runtime functions,
- // so we need to prevent them from being dead stripped.
- if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed);
+ appendToUsed(M, GlobalsToAppendToUsed);
appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed);
if (!be_quiet) {
- if (!instr)
+ if (!instr) {
+
WARNF("No instrumentation targets found.");
- else {
- char modeline[100];
+ } else {
+
+ char modeline[128];
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s",
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
@@ -535,39 +512,36 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
}
// True if block has successors and it dominates all of them.
-bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) {
+static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) {
- if (succ_begin(BB) == succ_end(BB)) return false;
+ if (succ_empty(BB)) return false;
- for (const BasicBlock *SUCC : make_range(succ_begin(BB), succ_end(BB))) {
+ return llvm::all_of(successors(BB), [&](const BasicBlock *SUCC) {
- if (!DT->dominates(BB, SUCC)) return false;
+ return DT->dominates(BB, SUCC);
- }
-
- return true;
+ });
}
// True if block has predecessors and it postdominates all of them.
-bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT) {
+static bool isFullPostDominator(const BasicBlock *BB,
+ const PostDominatorTree *PDT) {
- if (pred_begin(BB) == pred_end(BB)) return false;
+ if (pred_empty(BB)) return false;
- for (const BasicBlock *PRED : make_range(pred_begin(BB), pred_end(BB))) {
+ return llvm::all_of(predecessors(BB), [&](const BasicBlock *PRED) {
- if (!PDT->dominates(BB, PRED)) return false;
+ return PDT->dominates(BB, PRED);
- }
-
- return true;
+ });
}
-bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
- const DominatorTree *DT,
- const PostDominatorTree *PDT,
- const SanitizerCoverageOptions &Options) {
+static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
+ const DominatorTree *DT,
+ const PostDominatorTree *PDT,
+ const SanitizerCoverageOptions &Options) {
// Don't insert coverage for blocks containing nothing but unreachable: we
// will never call __sanitizer_cov() for them, so counting them in
@@ -582,10 +556,6 @@ bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
if (Options.NoPrune || &F.getEntryBlock() == BB) return true;
- if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function &&
- &F.getEntryBlock() != BB)
- return false;
-
// Do not instrument full dominators, or full post-dominators with multiple
// predecessors.
return !isFullDominator(BB, DT) &&
@@ -597,38 +567,47 @@ bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
// A twist here is that we treat From->To as a backedge if
// * To dominates From or
// * To->UniqueSuccessor dominates From
-bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) {
+#if 0
+static bool IsBackEdge(BasicBlock *From, BasicBlock *To,
+ const DominatorTree *DT) {
- if (DT->dominates(To, From)) return true;
+ if (DT->dominates(To, From))
+ return true;
if (auto Next = To->getUniqueSuccessor())
- if (DT->dominates(Next, From)) return true;
+ if (DT->dominates(Next, From))
+ return true;
return false;
}
+#endif
+
// Prunes uninteresting Cmp instrumentation:
// * CMP instructions that feed into loop backedge branch.
//
// Note that Cmp pruning is controlled by the same flag as the
// BB pruning.
-bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
- const SanitizerCoverageOptions &Options) {
+#if 0
+static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
+ const SanitizerCoverageOptions &Options) {
if (!Options.NoPrune)
if (CMP->hasOneUse())
if (auto BR = dyn_cast(CMP->user_back()))
for (BasicBlock *B : BR->successors())
- if (IsBackEdge(BR->getParent(), B, DT)) return false;
+ if (IsBackEdge(BR->getParent(), B, DT))
+ return false;
return true;
}
+#endif
+
void ModuleSanitizerCoverageAFL::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
if (F.empty()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
-
if (F.getName().find(".module_ctor") != std::string::npos)
return; // Should not instrument sanitizer init functions.
if (F.getName().startswith("__sanitizer_"))
@@ -647,15 +626,13 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return;
+ if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
- SmallVector IndirCalls;
- SmallVector BlocksToInstrument;
- SmallVector CmpTraceTargets;
- SmallVector SwitchTraceTargets;
- SmallVector DivTraceTargets;
- SmallVector GepTraceTargets;
+ SmallVector BlocksToInstrument;
+ SmallVector CmpTraceTargets;
+ SmallVector SwitchTraceTargets;
const DominatorTree *DT = DTCallback(F);
const PostDominatorTree *PDT = PDTCallback(F);
@@ -665,47 +642,28 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
if (shouldInstrumentBlock(F, &BB, DT, PDT, Options))
BlocksToInstrument.push_back(&BB);
- for (auto &Inst : BB) {
-
- if (Options.IndirectCalls) {
-
- CallBase *CB = dyn_cast(&Inst);
- if (CB && !CB->getCalledFunction()) IndirCalls.push_back(&Inst);
-
- }
+ /*
+ for (auto &Inst : BB) {
- if (Options.TraceCmp) {
+ if (Options.TraceCmp) {
- if (ICmpInst *CMP = dyn_cast(&Inst))
- if (IsInterestingCmp(CMP, DT, Options))
- CmpTraceTargets.push_back(&Inst);
- if (isa(&Inst)) SwitchTraceTargets.push_back(&Inst);
+ if (ICmpInst *CMP = dyn_cast(&Inst))
+ if (IsInterestingCmp(CMP, DT, Options))
+ CmpTraceTargets.push_back(&Inst);
+ if (isa(&Inst))
+ SwitchTraceTargets.push_back(&Inst);
- }
+ }
- if (Options.TraceDiv)
- if (BinaryOperator *BO = dyn_cast(&Inst))
- if (BO->getOpcode() == Instruction::SDiv ||
- BO->getOpcode() == Instruction::UDiv)
- DivTraceTargets.push_back(BO);
- if (Options.TraceGep)
- if (GetElementPtrInst *GEP = dyn_cast(&Inst))
- GepTraceTargets.push_back(GEP);
- if (Options.StackDepth)
- if (isa(Inst) ||
- (isa(Inst) && !isa(Inst)))
- IsLeafFunc = false;
+ }
- }
+ */
}
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
- InjectCoverageForIndirectCalls(F, IndirCalls);
- InjectTraceForCmp(F, CmpTraceTargets);
- InjectTraceForSwitch(F, SwitchTraceTargets);
- InjectTraceForDiv(F, DivTraceTargets);
- InjectTraceForGep(F, GepTraceTargets);
+ // InjectTraceForCmp(F, CmpTraceTargets);
+ // InjectTraceForSwitch(F, SwitchTraceTargets);
}
@@ -717,33 +675,30 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,
Constant::getNullValue(ArrayTy), "__sancov_gen_");
-#if LLVM_VERSION_MAJOR >= 13
if (TargetTriple.supportsCOMDAT() &&
(TargetTriple.isOSBinFormatELF() || !F.isInterposable()))
if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple))
Array->setComdat(Comdat);
-#else
- if (TargetTriple.supportsCOMDAT() && !F.isInterposable())
- if (auto Comdat =
- GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
- Array->setComdat(Comdat);
-#endif
-
Array->setSection(getSectionName(Section));
-#if (LLVM_VERSION_MAJOR >= 11) || \
- (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1)
- #if LLVM_VERSION_MAJOR >= 16
+#if LLVM_VERSION_MAJOR >= 16
Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue()));
- #else
- Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
- #endif
#else
- Array->setAlignment(Align(4)); // cheating
+ Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize()));
#endif
- GlobalsToAppendToUsed.push_back(Array);
- GlobalsToAppendToCompilerUsed.push_back(Array);
- MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F));
- Array->addMetadata(LLVMContext::MD_associated, *MD);
+
+ // sancov_pcs parallels the other metadata section(s). Optimizers (e.g.
+ // GlobalOpt/ConstantMerge) may not discard sancov_pcs and the other
+ // section(s) as a unit, so we conservatively retain all unconditionally in
+ // the compiler.
+ //
+ // With comdat (COFF/ELF), the linker can guarantee the associated sections
+ // will be retained or discarded as a unit, so llvm.compiler.used is
+ // sufficient. Otherwise, conservatively make all of them retained by the
+ // linker.
+ if (Array->hasComdat())
+ GlobalsToAppendToCompilerUsed.push_back(Array);
+ else
+ GlobalsToAppendToUsed.push_back(Array);
return Array;
@@ -768,8 +723,12 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
PCs.push_back((Constant *)IRB.CreatePointerCast(
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
+#if LLVM_VERSION_MAJOR >= 16
+ PCs.push_back(Constant::getNullValue(IntptrPtrTy));
+#else
PCs.push_back((Constant *)IRB.CreateIntToPtr(
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
+#endif
}
@@ -792,21 +751,13 @@ void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays(
FunctionGuardArray = CreateFunctionLocalArrayInSection(
AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName);
- if (Options.Inline8bitCounters)
- Function8bitCounterArray = CreateFunctionLocalArrayInSection(
- AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName);
- /*
- if (Options.InlineBoolFlag)
- FunctionBoolArray = CreateFunctionLocalArrayInSection(
- AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName);
- */
- if (Options.PCTable) FunctionPCsArray = CreatePCArray(F, AllBlocks);
-
}
bool ModuleSanitizerCoverageAFL::InjectCoverage(
Function &F, ArrayRef AllBlocks, bool IsLeafFunc) {
+ if (AllBlocks.empty()) return false;
+
uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0;
static uint32_t first = 1;
@@ -855,7 +806,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
}
-#if (LLVM_VERSION_MAJOR >= 12)
else if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
FixedVectorType *tt = dyn_cast(t);
@@ -868,16 +818,14 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
}
-#endif
-
}
}
}
- /* Create PCGUARD array */
CreateFunctionLocalArrays(F, AllBlocks, first + cnt_cov + cnt_sel_inc);
+
if (first) { first = 0; }
selects += cnt_sel;
@@ -889,12 +837,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
CallInst *callInst = nullptr;
- /*
- std::string errMsg;
- raw_string_ostream os(errMsg);
- IN.print(os);
- fprintf(stderr, "X: %s\n", os.str().c_str());
- */
if ((callInst = dyn_cast(&IN))) {
Function *Callee = callInst->getCalledFunction();
@@ -1033,12 +975,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
}
- /*
- std::string errMsg;
- raw_string_ostream os(errMsg);
- x->print(os);
- fprintf(stderr, "X: %s\n", os.str().c_str());
- */
result = IRB.CreateSelect(condition, x, y);
}
@@ -1063,13 +999,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr);
- /*
- std::string errMsg;
- raw_string_ostream os(errMsg);
- result->print(os);
- fprintf(stderr, "X: %s\n", os.str().c_str());
- */
-
while (1) {
/* Get CurLoc */
@@ -1159,29 +1088,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
}
-// On every indirect call we call a run-time function
-// __sanitizer_cov_indir_call* with two parameters:
-// - callee address,
-// - global cache array that contains CacheSize pointers (zero-initialized).
-// The cache is used to speed up recording the caller-callee pairs.
-// The address of the caller is passed implicitly via caller PC.
-// CacheSize is encoded in the name of the run-time function.
-void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls(
- Function &F, ArrayRef IndirCalls) {
-
- if (IndirCalls.empty()) return;
- for (auto I : IndirCalls) {
-
- IRBuilder<> IRB(I);
- CallBase &CB = cast(*I);
- Value *Callee = CB.getCalledOperand();
- if (isa(Callee)) continue;
- IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy));
-
- }
-
-}
-
// For every switch statement we insert a call:
// __sanitizer_cov_trace_switch(CondValue,
// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
@@ -1237,41 +1143,6 @@ void ModuleSanitizerCoverageAFL::InjectTraceForSwitch(
}
-void ModuleSanitizerCoverageAFL::InjectTraceForDiv(
- Function &, ArrayRef DivTraceTargets) {
-
- for (auto BO : DivTraceTargets) {
-
- IRBuilder<> IRB(BO);
- Value *A1 = BO->getOperand(1);
- if (isa(A1)) continue;
- if (!A1->getType()->isIntegerTy()) continue;
- uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType());
- int CallbackIdx = TypeSize == 32 ? 0 : TypeSize == 64 ? 1 : -1;
- if (CallbackIdx < 0) continue;
- auto Ty = Type::getIntNTy(*C, TypeSize);
- IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx],
- {IRB.CreateIntCast(A1, Ty, true)});
-
- }
-
-}
-
-void ModuleSanitizerCoverageAFL::InjectTraceForGep(
- Function &, ArrayRef GepTraceTargets) {
-
- for (auto GEP : GepTraceTargets) {
-
- IRBuilder<> IRB(GEP);
- for (Use &Idx : GEP->indices())
- if (!isa(Idx) && Idx->getType()->isIntegerTy())
- IRB.CreateCall(SanCovTraceGepFunction,
- {IRB.CreateIntCast(Idx, IntptrTy, true)});
-
- }
-
-}
-
void ModuleSanitizerCoverageAFL::InjectTraceForCmp(
Function &, ArrayRef CmpTraceTargets) {
@@ -1321,27 +1192,44 @@ void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function &F,
BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock();
+ DebugLoc EntryLoc;
if (IsEntryBB) {
- // Keep allocas and llvm.localescape calls in the entry block. Even
+ if (auto SP = F.getSubprogram())
+ EntryLoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
+ // Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before
// calls.
IP = PrepareToSplitEntryBlock(BB, IP);
+#if LLVM_VERSION_MAJOR < 15
- }
-
- IRBuilder<> IRB(&*IP);
-
- if (Options.TracePC) {
+ } else {
- IRB.CreateCall(SanCovTracePC);
- // ->setCannotMerge(); // gets the PC using GET_CALLER_PC.
+ EntryLoc = IP->getDebugLoc();
+ if (!EntryLoc)
+ if (auto *SP = F.getSubprogram())
+ EntryLoc = DILocation::get(SP->getContext(), 0, 0, SP);
+#endif
}
+#if LLVM_VERSION_MAJOR >= 15
+ InstrumentationIRBuilder IRB(&*IP);
+#else
+ IRBuilder<> IRB(&*IP);
+#endif
+ if (EntryLoc) IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePCGuard) {
+ /*
+ auto GuardPtr = IRB.CreateIntToPtr(
+ IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
+ ConstantInt::get(IntptrTy, Idx * 4)),
+ Int32PtrTy);
+ IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge();
+ */
+
/* Get CurLoc */
Value *GuardPtr = IRB.CreateIntToPtr(
@@ -1399,57 +1287,6 @@ void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function &F,
}
- if (Options.Inline8bitCounters) {
-
- auto CounterPtr = IRB.CreateGEP(
- Function8bitCounterArray->getValueType(), Function8bitCounterArray,
- {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
- auto Load = IRB.CreateLoad(Int8Ty, CounterPtr);
- auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1));
- auto Store = IRB.CreateStore(Inc, CounterPtr);
- SetNoSanitizeMetadata(Load);
- SetNoSanitizeMetadata(Store);
-
- }
-
- /*
- if (Options.InlineBoolFlag) {
-
- auto FlagPtr = IRB.CreateGEP(
- FunctionBoolArray->getValueType(), FunctionBoolArray,
- {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
- auto Load = IRB.CreateLoad(Int1Ty, FlagPtr);
- auto ThenTerm =
- SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false);
- IRBuilder<> ThenIRB(ThenTerm);
- auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
- SetNoSanitizeMetadata(Load);
- SetNoSanitizeMetadata(Store);
-
- }
-
- */
-
- if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
-
- // Check stack depth. If it's the deepest so far, record it.
- Module *M = F.getParent();
- Function *GetFrameAddr = Intrinsic::getDeclaration(
- M, Intrinsic::frameaddress,
- IRB.getInt8PtrTy(M->getDataLayout().getAllocaAddrSpace()));
- auto FrameAddrPtr =
- IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)});
- auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy);
- auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack);
- auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack);
- auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false);
- IRBuilder<> ThenIRB(ThenTerm);
- auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
- SetNoSanitizeMetadata(LowestStack);
- SetNoSanitizeMetadata(Store);
-
- }
-
}
std::string ModuleSanitizerCoverageAFL::getSectionName(
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 84fe70ec..9e56828c 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -997,7 +997,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
-#if LLVM_MAJOR >= 11
+#if LLVM_MAJOR >= 13
#if defined __ANDROID__ || ANDROID
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -1014,7 +1014,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else {
- #if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR >= 13 /* use new pass manager */
#if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
#endif
@@ -1035,12 +1035,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
#if LLVM_MAJOR >= 4
if (!be_quiet)
SAYF(
- "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for "
+ "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for "
"enhanced version.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
instrument_mode = INSTRUMENT_LLVMNATIVE;
#else
- FATAL("pcguard instrumentation requires llvm 4.0.1+");
+ FATAL("pcguard instrumentation requires LLVM 4.0.1+");
#endif
#endif
@@ -1053,7 +1053,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] =
"-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
#else
- FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+");
+ FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+");
#endif
} else {
@@ -1063,7 +1063,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
#else
- FATAL("pcguard instrumentation requires llvm 4.0.1+");
+ FATAL("pcguard instrumentation requires LLVM 4.0.1+");
#endif
} else {
@@ -2031,7 +2031,7 @@ int main(int argc, char **argv, char **envp) {
if (!compiler_mode) {
// lto is not a default because outside of afl-cc RANLIB and AR have to
- // be set to llvm versions so this would work
+ // be set to LLVM versions so this would work
if (have_llvm)
compiler_mode = LLVM;
else if (have_gcc_plugin)
@@ -2050,6 +2050,17 @@ int main(int argc, char **argv, char **envp) {
}
+ /* if our PCGUARD implementation is not available then silently switch to
+ native LLVM PCGUARD */
+ if (compiler_mode == CLANG &&
+ (instrument_mode == INSTRUMENT_DEFAULT ||
+ instrument_mode == INSTRUMENT_PCGUARD) &&
+ find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) {
+
+ instrument_mode = INSTRUMENT_LLVMNATIVE;
+
+ }
+
if (compiler_mode == GCC) {
if (clang_mode) {
@@ -2096,12 +2107,12 @@ int main(int argc, char **argv, char **envp) {
"-------------|\n"
"MODES: NCC PERSIST DICT LAF "
"CMPLOG SELECT\n"
- " [LTO] llvm LTO: %s%s\n"
+ " [LTO] LLVM LTO: %s%s\n"
" PCGUARD DEFAULT yes yes yes yes yes "
" yes\n"
" CLASSIC yes yes yes yes yes "
" yes\n"
- " [LLVM] llvm: %s%s\n"
+ " [LLVM] LLVM: %s%s\n"
" PCGUARD %s yes yes module yes yes "
"yes\n"
" CLASSIC %s no yes module yes yes "
@@ -2171,7 +2182,7 @@ int main(int argc, char **argv, char **envp) {
" (instrumentation/README.lto.md)\n"
" PERSIST: persistent mode support [code] (huge speed increase!)\n"
" (instrumentation/README.persistent_mode.md)\n"
- " DICT: dictionary in the target [yes=automatic or llvm module "
+ " DICT: dictionary in the target [yes=automatic or LLVM module "
"pass]\n"
" (instrumentation/README.lto.md + "
"instrumentation/README.llvm.md)\n"
--
cgit 1.4.1