diff options
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | afl-fuzz.c | 188 | ||||
-rw-r--r-- | afl-showmap.c | 25 | ||||
-rw-r--r-- | docs/ChangeLog | 6 | ||||
-rw-r--r-- | docs/PATCHES | 1 | ||||
-rw-r--r-- | docs/unicorn_mode.txt | 2 | ||||
-rw-r--r-- | llvm_mode/LLVMInsTrim.so.cc | 8 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-inl.h | 2 | ||||
-rw-r--r-- | unicorn_mode/README.md | 2 |
9 files changed, 172 insertions, 72 deletions
diff --git a/README.md b/README.md index 953c1afb..2124b862 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # american fuzzy lop plus plus (afl++) + Release Version: 2.53c + Github Version: 2.53d + + Originally developed by Michal "lcamtuf" Zalewski. Repository: [https://github.com/vanhauser-thc/AFLplusplus](https://github.com/vanhauser-thc/AFLplusplus) - afl++ is maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eissfeldt + afl++ is maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>. ## The enhancements compared to the original stock afl @@ -18,7 +22,7 @@ Additionally the following patches have been integrated: - * AFLfast's power schedules by Marcel Boehme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast) + * AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast) * C. Hollers afl-fuzz Python mutator module and llvm_mode whitelist support: [https://github.com/choller/afl](https://github.com/choller/afl) @@ -28,6 +32,8 @@ * unicorn_mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk) + * Custom mutator by a library (instead of Python) by kyakdan + A more thorough list is available in the PATCHES file. So all in all this is the best-of AFL that is currently out there :-) diff --git a/afl-fuzz.c b/afl-fuzz.c index 6c003ae6..a1388a55 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -126,7 +126,7 @@ double x_now[swarm_num][operator_num], core_operator_finds_puppet[operator_num], core_operator_finds_puppet_v2[operator_num], core_operator_cycles_puppet[operator_num], - core_operator_cycles_puppet_v2[operator_num], + core_operator_cycles_puppet_v2[operator_num], core_operator_cycles_puppet_v3[operator_num]; /* Execs per fuzz stage */ #define RAND_C (rand()%1000*0.001) @@ -368,6 +368,11 @@ static u32 a_extras_cnt; /* Total number of tokens available */ static u8* (*post_handler)(u8* buf, u32* len); +/* hooks for the custom mutator function */ +static size_t (*custom_mutator)(u8 *data, size_t size, u8* mutated_out, size_t max_size, unsigned int seed); +static size_t (*pre_save_handler)(u8 *data, size_t size, u8 **new_data); + + /* Interesting values, as per config.h */ static s8 interesting_8[] = { INTERESTING_8 }; @@ -394,7 +399,8 @@ enum { /* 14 */ STAGE_EXTRAS_AO, /* 15 */ STAGE_HAVOC, /* 16 */ STAGE_SPLICE, - /* 17 */ STAGE_PYTHON + /* 17 */ STAGE_PYTHON, + /* 18 */ STAGE_CUSTOM_MUTATOR }; /* Stage value types */ @@ -1560,7 +1566,7 @@ static u64 next_p2(u64 val) { while (val > ret) ret <<= 1; return ret; -} +} /* When we bump into a new path, we call this to see if the path appears @@ -1714,6 +1720,26 @@ static void setup_post(void) { } +static void setup_custom_mutator(void) { + void* dh; + u8* fn = getenv("AFL_CUSTOM_MUTATOR_LIBRARY"); + + if (!fn) return; + + ACTF("Loading custom mutator library from '%s'...", fn); + + dh = dlopen(fn, RTLD_NOW); + if (!dh) FATAL("%s", dlerror()); + + custom_mutator = dlsym(dh, "afl_custom_mutator"); + if (!custom_mutator) FATAL("Symbol 'afl_custom_mutator' not found."); + + pre_save_handler = dlsym(dh, "afl_pre_save_handler"); +// if (!pre_save_handler) WARNF("Symbol 'afl_pre_save_handler' not found."); + + OKF("Custom mutator installed successfully."); +} + /* Read all testcases from the input directory, then queue them for testing. Called at startup. */ @@ -2801,7 +2827,13 @@ static void write_to_testcase(void* mem, u32 len) { } else lseek(fd, 0, SEEK_SET); - ck_write(fd, mem, len, out_file); + if (pre_save_handler) { + u8* new_data; + size_t new_size = pre_save_handler(mem, len, &new_data); + ck_write(fd, new_data, new_size, out_file); + } else { + ck_write(fd, mem, len, out_file); + } if (!out_file) { @@ -4178,7 +4210,7 @@ static void maybe_delete_out_dir(void) { fn = alloc_printf("%s/plot_data", out_dir); if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; ck_free(fn); - + fn = alloc_printf("%s/cmdline", out_dir); if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; ck_free(fn); @@ -4236,7 +4268,7 @@ static void show_stats(void) { /* Calculate smoothed exec speed stats. */ if (!last_execs) { - + avg_exec = ((double)total_execs) * 1000 / (cur_ms - start_time); } else { @@ -4268,7 +4300,7 @@ static void show_stats(void) { t_bytes = count_non_255_bytes(virgin_bits); t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; - if (t_bytes) + if (t_bytes) stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes; else stab_ratio = 100; @@ -4290,7 +4322,7 @@ static void show_stats(void) { last_plot_ms = cur_ms; maybe_update_plot_file(t_byte_ratio, avg_exec); - + } /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ @@ -4338,11 +4370,11 @@ static void show_stats(void) { #ifdef HAVE_AFFINITY sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN - " (%s) " cPIN "[%s]" cBLU " {%d}", crash_mode ? cPIN "peruvian were-rabbit" : + " (%s) " cPIN "[%s]" cBLU " {%d}", crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", use_banner, power_name, cpu_aff); #else sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN - " (%s) " cPIN "[%s]", crash_mode ? cPIN "peruvian were-rabbit" : + " (%s) " cPIN "[%s]", crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", use_banner, power_name); #endif /* HAVE_AFFINITY */ @@ -4405,7 +4437,7 @@ static void show_stats(void) { if (dumb_mode) - SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST + SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST " (non-instrumented mode) "); else @@ -4432,7 +4464,7 @@ static void show_stats(void) { sprintf(tmp, "%s%s", DI(unique_hangs), (unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); - SAYF(bV bSTOP " last uniq hang : " cRST "%-33s " bSTG bV bSTOP + SAYF(bV bSTOP " last uniq hang : " cRST "%-33s " bSTG bV bSTOP " uniq hangs : " cRST "%-6s" bSTG bV "\n", DTD(cur_ms, last_hang_time), tmp); @@ -4449,10 +4481,10 @@ static void show_stats(void) { SAYF(bV bSTOP " now processing : " cRST "%-16s " bSTG bV bSTOP, tmp); - sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * + sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * 100 / MAP_SIZE, t_byte_ratio); - SAYF(" map density : %s%-21s" bSTG bV "\n", t_byte_ratio > 70 ? cLRD : + SAYF(" map density : %s%-21s" bSTG bV "\n", t_byte_ratio > 70 ? cLRD : ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp); sprintf(tmp, "%s (%0.02f%%)", DI(cur_skipped_paths), @@ -4473,7 +4505,7 @@ static void show_stats(void) { /* Yeah... it's still going on... halp? */ - SAYF(bV bSTOP " now trying : " cRST "%-20s " bSTG bV bSTOP + SAYF(bV bSTOP " now trying : " cRST "%-20s " bSTG bV bSTOP " favored paths : " cRST "%-22s" bSTG bV "\n", stage_name, tmp); if (!stage_max) { @@ -4600,7 +4632,7 @@ static void show_stats(void) { if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio); else strcpy(tmp, "n/a"); - SAYF(" stability : %s%-10s" bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) + SAYF(" stability : %s%-10s" bSTG bV "\n", (stab_ratio < 85 && var_byte_count > 40) ? cLRD : ((queued_variable && (!persistent_mode || var_byte_count > 20)) ? cMGN : cRST), tmp); @@ -4634,9 +4666,14 @@ static void show_stats(void) { strcat(tmp, tmp2); } - - SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n" + if (custom_mutator) { + sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]), DI(stage_cycles[STAGE_CUSTOM_MUTATOR])); + SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n" + bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1, tmp); + } else { + SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n" bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1, tmp); + } /* Provide some CPU utilization stats. */ @@ -4717,7 +4754,7 @@ static void show_init_stats(void) { SAYF("\n"); - if (avg_us > ((qemu_mode || unicorn_mode) ? 50000 : 10000)) + if (avg_us > ((qemu_mode || unicorn_mode) ? 50000 : 10000)) WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.txt.", doc_path); @@ -5198,7 +5235,7 @@ static u32 calculate_score(struct queue_entry* q) { switch (schedule) { - case EXPLORE: + case EXPLORE: break; case EXPLOIT: @@ -5209,7 +5246,7 @@ static u32 calculate_score(struct queue_entry* q) { fuzz_total = 0; n_paths = 0; - struct queue_entry *queue_it = queue; + struct queue_entry *queue_it = queue; while (queue_it) { fuzz_total += queue_it->n_fuzz; n_paths ++; @@ -5220,22 +5257,22 @@ static u32 calculate_score(struct queue_entry* q) { if (fuzz <= fuzz_mu) { if (q->fuzz_level < 16) factor = ((u32) (1 << q->fuzz_level)); - else + else factor = MAX_FACTOR; } else { factor = 0; } break; - + case FAST: if (q->fuzz_level < 16) { - factor = ((u32) (1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); + factor = ((u32) (1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); } else factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2 (fuzz)); break; case LIN: - factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); + factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break; case QUAD: @@ -5245,7 +5282,7 @@ static u32 calculate_score(struct queue_entry* q) { default: PFATAL ("Unknown Power Schedule"); } - if (factor > MAX_FACTOR) + if (factor > MAX_FACTOR) factor = MAX_FACTOR; perf_score *= factor / POWER_BETA; @@ -5561,7 +5598,7 @@ static u8 fuzz_one_original(char** argv) { * TRIMMING * ************/ - if (!dumb_mode && !queue_cur->trim_done) { + if (!dumb_mode && !queue_cur->trim_done && !custom_mutator) { u8 res = trim_case(argv, queue_cur, in_buf); @@ -5591,16 +5628,48 @@ static u8 fuzz_one_original(char** argv) { if (perf_score == 0) goto abandon_entry; + if (custom_mutator) { + stage_short = "custom"; + stage_name = "custom mutator"; + stage_max = len << 3; + stage_val_type = STAGE_VAL_NONE; + + const u32 max_seed_size = 4096*4096; + u8* mutated_buf = ck_alloc(max_seed_size); + + orig_hit_cnt = queued_paths + unique_crashes; + + for (stage_cur = 0 ; stage_cur < stage_max ; stage_cur++) { + size_t orig_size = (size_t) len; + size_t mutated_size = custom_mutator(out_buf, orig_size, mutated_buf, max_seed_size, UR(UINT32_MAX)); + if (mutated_size > 0) { + out_buf = ck_realloc(out_buf, mutated_size); + memcpy(out_buf, mutated_buf, mutated_size); + if (common_fuzz_stuff(argv, out_buf, (u32) mutated_size)) { + goto abandon_entry; + } + } + } + + ck_free(mutated_buf); + new_hit_cnt = queued_paths + unique_crashes; + + stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt; + stage_cycles[STAGE_CUSTOM_MUTATOR] += stage_max; + goto abandon_entry; + } + + /* Skip right away if -d is given, if it has not been chosen sufficiently often to warrant the expensive deterministic stage (fuzz_level), or if it has gone through deterministic testing in earlier, resumed runs (passed_det). */ - if (skip_deterministic - || ((!queue_cur->passed_det) + if (skip_deterministic + || ((!queue_cur->passed_det) && perf_score < ( queue_cur->depth * 30 <= havoc_max_mult * 100 - ? queue_cur->depth * 30 + ? queue_cur->depth * 30 : havoc_max_mult * 100)) || queue_cur->passed_det) #ifdef USE_PYTHON @@ -7259,7 +7328,7 @@ static u8 pilot_fuzzing(char** argv) { u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; u64 havoc_queued, orig_hit_cnt, new_hit_cnt, cur_ms_lv; u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; - + u8 ret_val = 1, doing_det = 0; u8 a_collect[MAX_AUTO_EXTRA]; @@ -7412,7 +7481,7 @@ static u8 pilot_fuzzing(char** argv) { key_puppet = 1; goto pacemaker_fuzzing; } - + doing_det = 1; /********************************************* @@ -7591,7 +7660,7 @@ static u8 pilot_fuzzing(char** argv) { - + /* Effector map setup. These macros calculate: EFF_APOS - position of a particular file offset in the map. @@ -7773,7 +7842,7 @@ static u8 pilot_fuzzing(char** argv) { - + skip_bitflip: @@ -8197,7 +8266,7 @@ static u8 pilot_fuzzing(char** argv) { stage_cur = 0; stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2); - + orig_hit_cnt = new_hit_cnt; for (i = 0; i < len - 3; i++) { @@ -8446,7 +8515,7 @@ static u8 pilot_fuzzing(char** argv) { /**************** * RANDOM HAVOC * ****************/ - + havoc_stage: pacemaker_fuzzing: @@ -8481,7 +8550,7 @@ static u8 pilot_fuzzing(char** argv) { cur_ms_lv = get_cur_time(); { - + if (key_puppet == 1) { @@ -8492,7 +8561,7 @@ static u8 pilot_fuzzing(char** argv) { SPLICE_CYCLES_puppet = (UR(SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) + SPLICE_CYCLES_puppet_low); } } - + { havoc_stage_puppet: @@ -8776,7 +8845,7 @@ static u8 pilot_fuzzing(char** argv) { ck_free(out_buf); out_buf = new_buf; temp_len += clone_len; - stage_cycles_puppet_v2[swarm_now][STAGE_Clone75] += 1; + stage_cycles_puppet_v2[swarm_now][STAGE_Clone75] += 1; } break; @@ -8803,7 +8872,7 @@ static u8 pilot_fuzzing(char** argv) { } else memset(out_buf + copy_to, UR(2) ? UR(256) : out_buf[UR(temp_len)], copy_len); - stage_cycles_puppet_v2[swarm_now][STAGE_OverWrite75] += 1; + stage_cycles_puppet_v2[swarm_now][STAGE_OverWrite75] += 1; break; } @@ -8815,7 +8884,7 @@ static u8 pilot_fuzzing(char** argv) { tmp_pilot_time += 1; - + @@ -8861,7 +8930,7 @@ static u8 pilot_fuzzing(char** argv) { } new_hit_cnt = queued_paths + unique_crashes; - + if (!splice_cycle) { stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; stage_cycles[STAGE_HAVOC] += stage_max; @@ -8992,7 +9061,7 @@ static u8 pilot_fuzzing(char** argv) { last_limit_time_start = 0; } } - + if (unlikely(tmp_pilot_time > period_pilot)) { total_pacemaker_time += tmp_pilot_time; @@ -9064,7 +9133,7 @@ static u8 core_fuzzing(char** argv) { u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; u64 havoc_queued, orig_hit_cnt, new_hit_cnt, cur_ms_lv; u32 splice_cycle = 0, perf_score = 100, orig_perf, prev_cksum, eff_cnt = 1; - + u8 ret_val = 1, doing_det = 0; u8 a_collect[MAX_AUTO_EXTRA]; @@ -9325,7 +9394,7 @@ static u8 core_fuzzing(char** argv) { stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt; stage_cycles[STAGE_FLIP1] += stage_max; - + /* Two walking bits. */ @@ -9533,7 +9602,7 @@ static u8 core_fuzzing(char** argv) { stage_cur = 0; stage_max = len - 3; - + orig_hit_cnt = new_hit_cnt; for (i = 0; i < len - 3; i++) { @@ -10218,7 +10287,7 @@ static u8 core_fuzzing(char** argv) { /**************** * RANDOM HAVOC * ****************/ - + havoc_stage: pacemaker_fuzzing: @@ -10519,7 +10588,7 @@ static u8 core_fuzzing(char** argv) { ck_free(out_buf); out_buf = new_buf; temp_len += clone_len; - core_operator_cycles_puppet_v2[STAGE_Clone75] += 1; + core_operator_cycles_puppet_v2[STAGE_Clone75] += 1; } break; @@ -10546,7 +10615,7 @@ static u8 core_fuzzing(char** argv) { } else memset(out_buf + copy_to, UR(2) ? UR(256) : out_buf[UR(temp_len)], copy_len); - core_operator_cycles_puppet_v2[STAGE_OverWrite75] += 1; + core_operator_cycles_puppet_v2[STAGE_OverWrite75] += 1; break; } @@ -10598,7 +10667,7 @@ static u8 core_fuzzing(char** argv) { } new_hit_cnt = queued_paths + unique_crashes; - + #ifndef IGNORE_FINDS @@ -10754,13 +10823,13 @@ void pso_updating(void) { g_now += 1; if (g_now > g_max) g_now = 0; - w_now = (w_init - w_end)*(g_max - g_now) / (g_max)+w_end; + w_now = (w_init - w_end)*(g_max - g_now) / (g_max)+w_end; int tmp_swarm, i, j; u64 temp_operator_finds_puppet = 0; for (i = 0; i < operator_num; i++) { operator_finds_puppet[i] = core_operator_finds_puppet[i]; - + for (j = 0; j < swarm_num; j++) { operator_finds_puppet[i] = operator_finds_puppet[i] + stage_finds_puppet[j][i]; @@ -10771,7 +10840,7 @@ void pso_updating(void) { for (i = 0; i < operator_num; i++) { if (operator_finds_puppet[i]) - G_best[i] = (double)((double)(operator_finds_puppet[i]) / (double)(temp_operator_finds_puppet)); + G_best[i] = (double)((double)(operator_finds_puppet[i]) / (double)(temp_operator_finds_puppet)); } for (tmp_swarm = 0; tmp_swarm < swarm_num; tmp_swarm++) @@ -10800,7 +10869,7 @@ void pso_updating(void) { if (probability_now[tmp_swarm][operator_num - 1] < 0.99 || probability_now[tmp_swarm][operator_num - 1] > 1.01) FATAL("ERROR probability"); } swarm_now = 0; - key_module = 0; + key_module = 0; } @@ -10820,7 +10889,7 @@ static u8 fuzz_one(char** argv) { pso_updating(); } - return key_val_lv; + return key_val_lv; } @@ -12236,10 +12305,10 @@ int main(int argc, char** argv) { else probability_now[tmp_swarm][i] = x_now[tmp_swarm][i]; } - if (probability_now[tmp_swarm][operator_num - 1] < 0.99 || probability_now[tmp_swarm][operator_num - 1] > 1.01) + if (probability_now[tmp_swarm][operator_num - 1] < 0.99 || probability_now[tmp_swarm][operator_num - 1] > 1.01) FATAL("ERROR probability"); } - + for (i = 0; i < operator_num; i++) { core_operator_finds_puppet[i] = 0; core_operator_finds_puppet_v2[i] = 0; @@ -12287,7 +12356,7 @@ int main(int argc, char** argv) { if (unicorn_mode) FATAL("-U and -n are mutually exclusive"); } - + if (index(argv[optind], '/') == NULL) WARNF(cLRD "Target binary called without a prefixed path, make sure you are fuzzing the right binary: " cRST "%s", argv[optind]); OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" Eissfeldt and Andrea Fioraldi"); @@ -12363,6 +12432,7 @@ int main(int argc, char** argv) { check_cpu_governor(); setup_post(); + setup_custom_mutator(); setup_shm(dumb_mode); if (!in_bitmap) memset(virgin_bits, 255, MAP_SIZE); @@ -12540,7 +12610,7 @@ stop_fuzzing: SAYF(cYEL "[!] " cRST "Time limit was reached\n"); if (most_execs_key == 2) SAYF(cYEL "[!] " cRST "Execution limit was reached\n"); - + /* Running for more than 30 minutes but still doing first cycle? */ if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) { diff --git a/afl-showmap.c b/afl-showmap.c index baf8352e..bce7cb4e 100644 --- a/afl-showmap.c +++ b/afl-showmap.c @@ -59,10 +59,13 @@ static u8 *out_file, /* Trace output file */ static u32 exec_tmout; /* Exec timeout (ms) */ +static u32 total, highest; /* tuple content information */ + static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ static u8 quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ + raw_instr_output, /* Do not apply AFL filters */ cmin_mode, /* Generate output in afl-cmin mode? */ binary_mode, /* Write output as a binary map */ keep_cores; /* Allow coredumps? */ @@ -114,7 +117,7 @@ static void classify_counts(u8* mem, const u8* map) { mem++; } - } else { + } else if (!raw_instr_output) { while (i--) { *mem = map[*mem]; @@ -154,7 +157,6 @@ static u32 write_results(void) { } - if (binary_mode) { for (i = 0; i < MAP_SIZE; i++) @@ -173,6 +175,10 @@ static u32 write_results(void) { if (!trace_bits[i]) continue; ret++; + + total += trace_bits[i]; + if (highest < trace_bits[i]) + highest = trace_bits[i]; if (cmin_mode) { @@ -412,6 +418,7 @@ static void usage(u8* argv0) { " -q - sink program's output and don't show messages\n" " -e - show edge coverage only, ignore hit counts\n" + " -r - show real tuple values instead of AFL filter values\n" " -c - allow core dumps\n\n" "This tool displays raw tuple data captured by AFL instrumentation.\n" @@ -541,12 +548,12 @@ int main(int argc, char** argv) { s32 opt; u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0; - u32 tcnt; + u32 tcnt = 0; char** use_argv; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQUbc")) > 0) + while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQUbcr")) > 0) switch (opt) { @@ -611,6 +618,7 @@ int main(int argc, char** argv) { case 'e': if (edges_only) FATAL("Multiple -e options not supported"); + if (raw_instr_output) FATAL("-e and -r are mutually exclusive"); edges_only = 1; break; @@ -664,6 +672,13 @@ int main(int argc, char** argv) { if (keep_cores) FATAL("Multiple -c options not supported"); keep_cores = 1; break; + + case 'r': + + if (raw_instr_output) FATAL("Multiple -r options not supported"); + if (edges_only) FATAL("-e and -r are mutually exclusive"); + raw_instr_output = 1; + break; default: @@ -699,7 +714,7 @@ int main(int argc, char** argv) { if (!quiet_mode) { if (!tcnt) FATAL("No instrumentation detected" cRST); - OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file); + OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST, tcnt, highest, total, out_file); } diff --git a/docs/ChangeLog b/docs/ChangeLog index dfb2e4e7..5e78610e 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,6 +17,12 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. Version ++2.53d (dev): ---------------------- + - custom mutator by a loaded library is now supported (thanks to kyakdan!) + - fix for a few features to support different map sized than 2^16 + - afl-showmap: new option -r now shows the real values in the buckets (stock + afl never did), plus shows tuple content summary information now + - fix building on *BSD (thanks to tobias.kortkamp for the patch) + - small docu updates - ... your patch? :) diff --git a/docs/PATCHES b/docs/PATCHES index 8b188814..50bcb32f 100644 --- a/docs/PATCHES +++ b/docs/PATCHES @@ -17,6 +17,7 @@ afl-qemu-optimize-entrypoint.diff by mh(at)mh-sec(dot)de afl-qemu-speed.diff by abiondo on github afl-qemu-optimize-map.diff by mh(at)mh-sec(dot)de ++ Custom mutator (native library) (by kyakdan) + unicorn_mode (modernized and updated by domenukk) + instrim (https://github.com/csienslab/instrim) was integrated + MOpt (github.com/puppet-meteor/MOpt-AFL) was imported diff --git a/docs/unicorn_mode.txt b/docs/unicorn_mode.txt index ae6a2bde..b691fff8 100644 --- a/docs/unicorn_mode.txt +++ b/docs/unicorn_mode.txt @@ -20,6 +20,8 @@ The idea and much of the implementation comes from Nathan Voss <njvoss299@gmail. 2) How to use ------------- +Requirements: you need an installed python2 environment. + *** Building AFL's Unicorn Mode *** First, make afl as usual. diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 81cf98c4..fad6dd4f 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -46,15 +46,13 @@ namespace { std::mt19937 generator; int total_instr = 0; - unsigned genLabel() { - return generator() % 65536; + unsigned int genLabel() { + return generator() & (MAP_SIZE - 1); } public: static char ID; - InsTrim() : ModulePass(ID), generator(0) {//} - -// AFLCoverage() : ModulePass(ID) { + InsTrim() : ModulePass(ID), generator(0) { char* instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); if (instWhiteListFilename) { std::string line; diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index 03951fea..86203a5b 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -57,7 +57,7 @@ /* This is equivalent to afl-as.h: */ -static unsigned char dummy[65536]; /* costs 64kb but saves a few instructions */ +static unsigned char dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */ unsigned char *afl_area_ptr = dummy; /* Exported for afl_gen_trace */ /* Exported variables populated by the code patched into elfload.c: */ diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md index f12ed8bc..9ee975ef 100644 --- a/unicorn_mode/README.md +++ b/unicorn_mode/README.md @@ -10,6 +10,8 @@ afl-unicorn lets you fuzz any piece of binary that can be emulated by [Unicorn Engine](http://www.unicorn-engine.org/). +Requirements: Python2 + For the full readme please see docs/unicorn_mode.txt For an in-depth description of what this is, how to install it, and how to use |