diff options
author | van Hauser <vh@thc.org> | 2020-06-12 08:27:03 +0200 |
---|---|---|
committer | van Hauser <vh@thc.org> | 2020-06-12 08:27:03 +0200 |
commit | 818afe6232a6ee7dd83bb0fffb739a05acf46301 (patch) | |
tree | c5071d277eee2a44244632803807a5d135de178e | |
parent | e8da5f9e2894a89e36f899719e442a897a189f1f (diff) | |
download | afl++-818afe6232a6ee7dd83bb0fffb739a05acf46301.tar.gz |
added MOpt dictionary support from repo
-rw-r--r-- | docs/Changelog.md | 1 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 185 |
2 files changed, 186 insertions, 0 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md index eaaeb529..1fdc4677 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -17,6 +17,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - If no main node is present at a sync one secondary node automatically becomes a temporary main node until a real main nodes shows up - fix/update to MOpt (thanks to arnow117) + - added MOpt dictionary support from repo - llvm_mode: - the default instrumentation is now PCGUARD, as it is faster and provides better coverage. The original afl instrumentation can be set via diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 578ac584..bea7e76e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3806,6 +3806,191 @@ skip_extras: havoc_stage: pacemaker_fuzzing: + if (afl->key_puppet == 1) { + + double select_bool = ((double)(random() % 10000) * 0.0001); + if (select_bool < 0.001) { + + /******************** + * DICTIONARY STUFF * + ********************/ + + if (!afl->extras_cnt) goto skip_puppet_extras; + + /* Overwrite with user-supplied extras. */ + + afl->stage_name = "user extras (over)"; + afl->stage_short = "ext_UO"; + afl->stage_cur = 0; + afl->stage_max = afl->extras_cnt * len; + + afl->stage_val_type = STAGE_VAL_NONE; + + orig_hit_cnt = new_hit_cnt; + + for (i = 0; i < len; i++) { + + u32 last_len = 0; + + afl->stage_cur_byte = i; + + /* Extras are sorted by size, from smallest to largest. This means + that we don't have to worry about restoring the buffer in + between writes at a particular offset determined by the outer + loop. */ + + for (j = 0; j < afl->extras_cnt; j++) { + + /* Skip extras probabilistically if extras_cnt > MAX_DET_EXTRAS. Also + skip them if there's no room to insert the payload, if the token + is redundant, or if its entire span has no bytes set in the + effector map. */ + + if ((afl->extras_cnt > MAX_DET_EXTRAS && + rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) || + afl->extras[j].len > len - i || + !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) || + !memchr(eff_map + EFF_APOS(i), 1, + EFF_SPAN_ALEN(i, afl->extras[j].len))) { + + afl->stage_max--; + continue; + + } + + last_len = afl->extras[j].len; + memcpy(out_buf + i, afl->extras[j].data, last_len); + + if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + + afl->stage_cur++; + + } + + /* Restore all the clobbered memory. */ + memcpy(out_buf + i, in_buf + i, last_len); + + } + + new_hit_cnt = afl->queued_paths + afl->unique_crashes; + + afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max; + + /* Insertion of user-supplied extras. */ + + afl->stage_name = "user extras (insert)"; + afl->stage_short = "ext_UI"; + afl->stage_cur = 0; + afl->stage_max = afl->extras_cnt * len; + + orig_hit_cnt = new_hit_cnt; + + ex_tmp = ck_alloc(len + MAX_DICT_FILE); + + for (i = 0; i <= len; i++) { + + afl->stage_cur_byte = i; + + for (j = 0; j < afl->extras_cnt; j++) { + + if (len + afl->extras[j].len > MAX_FILE) { + + afl->stage_max--; + continue; + + } + + /* Insert token */ + memcpy(ex_tmp + i, afl->extras[j].data, afl->extras[j].len); + + /* Copy tail */ + memcpy(ex_tmp + i + afl->extras[j].len, out_buf + i, len - i); + + if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) { + + ck_free(ex_tmp); + goto abandon_entry; + + } + + afl->stage_cur++; + + } + + /* Copy head */ + ex_tmp[i] = out_buf[i]; + + } + + ck_free(ex_tmp); + + new_hit_cnt = afl->queued_paths + afl->unique_crashes; + + afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max; + + skip_puppet_extras: + + if (!afl->a_extras_cnt) goto skip_extras_v2; + + afl->stage_name = "auto afl->extras (over)"; + afl->stage_short = "ext_AO"; + afl->stage_cur = 0; + afl->stage_max = MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS) * len; + + afl->stage_val_type = STAGE_VAL_NONE; + + orig_hit_cnt = new_hit_cnt; + + for (i = 0; i < len; i++) { + + u32 last_len = 0; + + afl->stage_cur_byte = i; + + for (j = 0; j < MIN(afl->a_extras_cnt, USE_AUTO_EXTRAS); j++) { + + /* See the comment in the earlier code; afl->extras are sorted by + * size. */ + + if (afl->a_extras[j].len > len - i || + !memcmp(afl->a_extras[j].data, out_buf + i, + afl->a_extras[j].len) || + !memchr(eff_map + EFF_APOS(i), 1, + EFF_SPAN_ALEN(i, afl->a_extras[j].len))) { + + afl->stage_max--; + continue; + + } + + last_len = afl->a_extras[j].len; + memcpy(out_buf + i, afl->a_extras[j].data, last_len); + + if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + + afl->stage_cur++; + + } + + /* Restore all the clobbered memory. */ + memcpy(out_buf + i, in_buf + i, last_len); + + } + + new_hit_cnt = afl->queued_paths + afl->unique_crashes; + + afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; + afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max; + + skip_extras_v2: + new_hit_cnt = afl->queued_paths + afl->unique_crashes; + + } + + } + afl->stage_cur_byte = -1; /* The havoc stage mutation code is also invoked when splicing files; if the |