From de2c565953228a52b2ac75b778b27aab983151c6 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 19 Jun 2020 18:05:04 +0200 Subject: first commit, looks good --- GNUmakefile | 2 +- include/afl-fuzz.h | 7 +- include/config.h | 25 ++- src/afl-fuzz-one.c | 566 +++++++++++++++++++++++++++++++++++++++++++++----- src/afl-fuzz-queue.c | 114 ++++++++++ src/afl-performance.c | 10 +- 6 files changed, 660 insertions(+), 64 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index f1c5f99b..6a881675 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -398,7 +398,7 @@ afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86 # document all mutations and only do one run (use with only one input file!) document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86 - $(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS) + $(CC) -g -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS) test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES) @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e7b52d56..8d8db100 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -138,7 +138,8 @@ struct queue_entry { var_behavior, /* Variable behavior? */ favored, /* Currently favored? */ fs_redundant, /* Marked as redundant in the fs? */ - fully_colorized; /* Do not run redqueen stage again */ + fully_colorized, /* Do not run redqueen stage again */ + is_ascii; /* Is the input just ascii text? */ u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level; /* Number of fuzzing iterations */ @@ -947,7 +948,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, u64 exec_cksum); /* xoshiro256** */ -uint64_t rand_next(afl_state_t *afl); +uint32_t rand_next(afl_state_t *afl); /**** Inline routines ****/ @@ -967,7 +968,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { } - return rand_next(afl) % limit; + return (rand_next(afl) % limit); } diff --git a/include/config.h b/include/config.h index 711d0b77..d4dd70ff 100644 --- a/include/config.h +++ b/include/config.h @@ -293,7 +293,7 @@ /* Call count interval between reseeding the libc PRNG from /dev/urandom: */ -#define RESEED_RNG 100000 +#define RESEED_RNG 256000 /* Maximum line length passed from GCC to 'as' and used for parsing configuration files: */ @@ -397,6 +397,29 @@ // #define IGNORE_FINDS +/* Text mutations */ + +/* What is the minimum length of a queue input to be evaluated for "is_ascii"? + */ + +#define AFL_TXT_MIN_LEN 8 + +/* What is the minimum percentage of ascii characters present to be classifed + as "is_ascii"? */ + +#define AFL_TXT_MIN_PERCENT 80 + +/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ + +#define AFL_TXT_BIAS 6 + +/* Maximum length of a string to tamper with */ + +#define AFL_TXT_STRING_MAX_LEN 1024 + +/* Maximum mutations on a string */ + +#define AFL_TXT_STRING_MAX_MUTATIONS 16 #endif /* ! _HAVE_CONFIG_H */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e42a323d..e097f6ef 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -24,6 +24,11 @@ */ #include "afl-fuzz.h" +#include + +static u8 *strnstr(const u8 *s, const u8 *find, size_t slen); +static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, + u8 *to); /* MOpt */ @@ -362,6 +367,446 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { #endif /* !IGNORE_FINDS */ +/* Not pretty, but saves a lot of writing */ +#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + +static u8 *strnstr(const u8 *s, const u8 *find, size_t slen) { + + char c, sc; + size_t len; + + if ((c = *find++) != '\0') { + + len = strlen(find); + do { + + do { + + if (slen-- < 1 || (sc = *s++) == '\0') return (NULL); + + } while (sc != c); + + if (len > slen) return (NULL); + + } while (strncmp(s, find, len) != 0); + + s--; + + } + + return ((u8 *)s); + +} + +/* replace between deliminators, if rep == NULL, then we will duplicate the + * target */ + +static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos, + const u8 *ldelim, const u8 *rdelim, u8 *rep) { + + u8 *end_buf = *out_buf + *temp_len; + u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos); + + if (ldelim_start != NULL) { + + u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN : end_buf - ldelim_start - 1); + + if (max > 0) { + + u8 *rdelim_end = + strnstr(ldelim_start + 1, rdelim, max); + + if (rdelim_end != NULL) { + + u32 rep_len, delim_space_len = rdelim_end - ldelim_start - 1, xtra = 0; + + if (rep != NULL) { + + rep_len = (u32)strlen(rep); + + } else { // NULL? then we copy the value in between the delimiters + + rep_len = delim_space_len; + delim_space_len = 0; + rep = ldelim_start + 1; + xtra = rep_len; + + } + + if (rep_len != delim_space_len) { + + memmove(ldelim_start + rep_len + xtra + 1, rdelim_end, + *temp_len - (rdelim_end - *out_buf)); + + } + + memcpy(ldelim_start + 1, rep, rep_len); + *temp_len = (*temp_len - delim_space_len + rep_len); + + return 1; + + } + + } + + } + + return 0; + +} + +static u32 delim_swap(u8 **out_buf, s32 *temp_len, size_t pos, const u8 *ldelim, + const u8 *mdelim, const u8 *rdelim) { + + u8 *out_buf_end = *out_buf + *temp_len; + u32 max = (*temp_len - pos > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN + : *temp_len - pos); + u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, max); + + if (ldelim_start != NULL) { + + max = (out_buf_end - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : out_buf_end - ldelim_start - 1); + if (max > 1) { + + u8 *mdelim_pos = strnstr(ldelim_start + 1, mdelim, max); + + if (mdelim_pos != NULL) { + + max = (out_buf_end - mdelim_pos - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : out_buf_end - mdelim_pos - 1); + if (max > 0) { + + u8 *rdelim_end = strnstr(mdelim + 1, rdelim, max); + + if (rdelim_end != NULL) { + + u32 first_len = mdelim_pos - ldelim_start - 1; + u32 second_len = rdelim_end - mdelim_pos - 1; + u8 scratch[AFL_TXT_STRING_MAX_LEN]; + + memcpy(scratch, ldelim_start + 1, first_len); + + if (first_len != second_len) { + + memmove(ldelim_start + second_len + 1, mdelim_pos, + out_buf_end - mdelim_pos); + + } + + memcpy(ldelim_start + 1, mdelim_pos + 1, second_len); + + if (first_len != second_len) { + + memmove(mdelim_pos + first_len + 1, rdelim_end, + out_buf_end - rdelim_end); + + } + + memcpy(mdelim_pos + 1, scratch, first_len); + + return 1; + + } + + } + + } + + } + + } + + return 0; + +} + +static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, + u8 *to) { + + u8 *start = strnstr(*out_buf + pos, from, *temp_len - pos); + + if (start) { + + u32 from_len = strlen(from); + u32 to_len = strlen(to); + + if (from_len != to_len) { + + memmove(start + to_len, start + from_len, + *temp_len - from_len - (start - *out_buf)); + + } + + memcpy(start, to, to_len); + *temp_len = (*temp_len - from_len + to_len); + + return 1; + + } + + return 0; + +} + +/* Returns 1 if a mutant was generated and placed in out_buf, 0 if none + * generated. */ + +static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { + + s32 temp_len; + u32 pos, yes = 0, + mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 1; + u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS); + temp_len = *orig_temp_len; + memcpy(new_buf, *out_buf, temp_len); + + for (u32 i = 0; i < mutations; i++) { + + if (temp_len < AFL_TXT_MIN_LEN) { return 0; } + + pos = rand_below(afl, temp_len - 1); + int choice = rand_below(afl, 72); + switch (choice) { + + case 0: /* Semantic statement deletion */ + yes += string_replace(out_buf, &temp_len, pos, "\n", "\nif (0==1)\n"); + break; + case 1: + yes += string_replace(out_buf, &temp_len, pos, "(", "(!"); + break; + case 2: + yes += string_replace(out_buf, &temp_len, pos, "==", "!="); + break; + case 3: + yes += string_replace(out_buf, &temp_len, pos, "!=", "=="); + break; + case 4: + yes += string_replace(out_buf, &temp_len, pos, "==", "<"); + break; + case 5: + yes += string_replace(out_buf, &temp_len, pos, "<", "=="); + break; + case 6: + yes += string_replace(out_buf, &temp_len, pos, "==", ">"); + break; + case 7: + yes += string_replace(out_buf, &temp_len, pos, ">", "=="); + break; + case 8: + yes += string_replace(out_buf, &temp_len, pos, "=", "<"); + break; + case 9: + yes += string_replace(out_buf, &temp_len, pos, "=", ">"); + break; + case 10: + yes += string_replace(out_buf, &temp_len, pos, "<", ">"); + break; + case 11: + yes += string_replace(out_buf, &temp_len, pos, ">", "<"); + break; + case 12: + yes += string_replace(out_buf, &temp_len, pos, "++", "--"); + break; + case 13: + yes += string_replace(out_buf, &temp_len, pos, "--", "++"); + break; + case 14: + yes += string_replace(out_buf, &temp_len, pos, "+", "-"); + break; + case 15: + yes += string_replace(out_buf, &temp_len, pos, "+", "*"); + break; + case 16: + yes += string_replace(out_buf, &temp_len, pos, "+", "/"); + break; + case 17: + yes += string_replace(out_buf, &temp_len, pos, "+", "%"); + break; + case 18: + yes += string_replace(out_buf, &temp_len, pos, "*", "-"); + break; + case 19: + yes += string_replace(out_buf, &temp_len, pos, "*", "+"); + break; + case 20: + yes += string_replace(out_buf, &temp_len, pos, "*", "/"); + break; + case 21: + yes += string_replace(out_buf, &temp_len, pos, "*", "%"); + break; + case 22: + yes += string_replace(out_buf, &temp_len, pos, "-", "+"); + break; + case 23: + yes += string_replace(out_buf, &temp_len, pos, "-", "*"); + break; + case 24: + yes += string_replace(out_buf, &temp_len, pos, "-", "/"); + break; + case 25: + yes += string_replace(out_buf, &temp_len, pos, "-", "%"); + break; + case 26: + yes += string_replace(out_buf, &temp_len, pos, "/", "-"); + break; + case 27: + yes += string_replace(out_buf, &temp_len, pos, "/", "*"); + break; + case 28: + yes += string_replace(out_buf, &temp_len, pos, "/", "+"); + break; + case 29: + yes += string_replace(out_buf, &temp_len, pos, "/", "%"); + break; + case 30: + yes += string_replace(out_buf, &temp_len, pos, "%", "-"); + break; + case 31: + yes += string_replace(out_buf, &temp_len, pos, "%", "*"); + break; + case 32: + yes += string_replace(out_buf, &temp_len, pos, "%", "/"); + break; + case 33: + yes += string_replace(out_buf, &temp_len, pos, "%", "+"); + break; + case 34: + yes += string_replace(out_buf, &temp_len, pos, "\n", "\nbreak;\n"); + break; + case 35: + yes += string_replace(out_buf, &temp_len, pos, "\n", "\ncontinue;\n"); + break; + case 36: + yes += string_replace(out_buf, &temp_len, pos, "0", "1"); + break; + case 37: + yes += string_replace(out_buf, &temp_len, pos, "1", "0"); + break; + case 38: + yes += string_replace(out_buf, &temp_len, pos, "if", "while"); + break; + case 39: + yes += string_replace(out_buf, &temp_len, pos, "while", "if"); + break; + case 40: + yes += string_replace(out_buf, &temp_len, pos, "\n", "\nwhile(1==1)\n"); + break; + case 41: + yes += string_replace(out_buf, &temp_len, pos, "&&", "||"); + break; + case 42: + yes += string_replace(out_buf, &temp_len, pos, "||", "&&"); + break; + case 43: + yes += string_replace(out_buf, &temp_len, pos, "!", ""); + break; + case 44: + yes += string_replace(out_buf, &temp_len, pos, "==", "="); + break; + case 45: + yes += string_replace(out_buf, &temp_len, pos, "--", ""); + break; + case 46: + yes += string_replace(out_buf, &temp_len, pos, "<<", "<"); + break; + case 47: + yes += string_replace(out_buf, &temp_len, pos, ">>", ">"); + break; + case 48: + yes += string_replace(out_buf, &temp_len, pos, "<", "<<"); + break; + case 49: + yes += string_replace(out_buf, &temp_len, pos, ">", ">>"); + break; + case 50: + yes += string_replace(out_buf, &temp_len, pos, "\"", "'"); + break; + case 51: + yes += string_replace(out_buf, &temp_len, pos, "'", "\""); + break; + case 52: + yes += string_replace(out_buf, &temp_len, pos, "(", "\""); + break; + case 53: /* Remove a semicolon delimited statement after a semicolon */ + yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";"); + break; + case 54: /* Remove a semicolon delimited statement after a left curly + brace */ + yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}"); + break; + case 55: /* Remove a curly brace construct */ + yes += delim_replace(out_buf, &temp_len, pos, "{", "}", ""); + break; + case 56: /* Replace a curly brace construct with an empty one */ + yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}"); + break; + case 57: + yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";"); + break; + case 58: + yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";"); + break; + case 59: /* Swap comma delimited things case 1 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")"); + break; + case 60: /* Swap comma delimited things case 2 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ","); + break; + case 61: /* Swap comma delimited things case 3 */ + yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ","); + break; + case 62: /* Swap comma delimited things case 4 */ + yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")"); + break; + case 63: /* Just delete a line */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", ""); + break; + case 64: /* Delete something like "const" case 1 */ + yes += delim_replace(out_buf, &temp_len, pos, " ", " ", ""); + break; + case 65: /* Delete something like "const" case 2 */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", ""); + break; + case 66: /* Delete something like "const" case 3 */ + yes += delim_replace(out_buf, &temp_len, pos, "(", " ", ""); + break; + case 67: /* Swap space delimited things case 1 */ + yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " "); + break; + case 68: /* Swap space delimited things case 2 */ + yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")"); + break; + case 69: /* Swap space delimited things case 3 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " "); + break; + case 70: /* Swap space delimited things case 4 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")"); + break; + case 71: /* Duplicate a single line of code */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL); + break; + case 72: /* Duplicate a construct (most often, a non-nested for loop */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL); + break; + + } + + } + + if (yes == 0 || temp_len <= 0) { return 0; } + + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); + *out_buf = new_buf; + *orig_temp_len = temp_len; + + return 1; + +} + /* Take the current entry from the queue, fuzz it for a while. This function is a tad too long... returns 0 if fuzzed successfully, 1 if skipped or bailed out. */ @@ -378,9 +823,6 @@ u8 fuzz_one_original(afl_state_t *afl) { u8 a_collect[MAX_AUTO_EXTRA]; u32 a_len = 0; -/* Not pretty, but saves a lot of writing */ -#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size - #ifdef IGNORE_FINDS /* In IGNORE_FINDS mode, skip any entries that weren't in the @@ -1853,9 +2295,12 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ + u32 r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0) + + (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0); + for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2)); + u32 r, use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2)); afl->stage_cur_val = use_stacking; @@ -1895,8 +2340,9 @@ havoc_stage: } - switch (rand_below( - afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) { + retry_havoc: + + switch ((r = rand_below(afl, r_max))) { case 0: @@ -2191,85 +2637,95 @@ havoc_stage: } - /* Values 15 and 16 can be selected only if there are any extras - present in the dictionaries. */ + // TODO: add splicing mutation here. + // 15: + // break; - case 15: { + default: + if (r == 15 && (afl->extras_cnt || afl->a_extras_cnt)) { - /* Overwrite bytes with an extra. */ + /* Values 15 and 16 can be selected only if there are any extras + present in the dictionaries. */ - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + /* Overwrite bytes with an extra. */ - /* No user-specified extras or odds in our favor. Let's use an - auto-detected one. */ + if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { - u32 use_extra = rand_below(afl, afl->a_extras_cnt); - u32 extra_len = afl->a_extras[use_extra].len; - u32 insert_at; + /* No user-specified extras or odds in our favor. Let's use an + auto-detected one. */ - if (extra_len > temp_len) { break; } + u32 use_extra = rand_below(afl, afl->a_extras_cnt); + u32 extra_len = afl->a_extras[use_extra].len; + u32 insert_at; - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, - extra_len); + if (extra_len > temp_len) { break; } - } else { + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, + extra_len); - /* No auto extras or odds in our favor. Use the dictionary. */ + } else { - u32 use_extra = rand_below(afl, afl->extras_cnt); - u32 extra_len = afl->extras[use_extra].len; - u32 insert_at; + /* No auto extras or odds in our favor. Use the dictionary. */ - if (extra_len > temp_len) { break; } + u32 use_extra = rand_below(afl, afl->extras_cnt); + u32 extra_len = afl->extras[use_extra].len; + u32 insert_at; - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len); + if (extra_len > temp_len) { break; } - } + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->extras[use_extra].data, + extra_len); - break; + } - } + } else if (r == 16 && (afl->extras_cnt || afl->a_extras_cnt)) { - case 16: { + u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1); + u8 *ptr; - u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1); - u8 *ptr; + /* Insert an extra. Do the same dice-rolling stuff as for the + previous case. */ - /* Insert an extra. Do the same dice-rolling stuff as for the - previous case. */ + if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + use_extra = rand_below(afl, afl->a_extras_cnt); + extra_len = afl->a_extras[use_extra].len; + ptr = afl->a_extras[use_extra].data; - use_extra = rand_below(afl, afl->a_extras_cnt); - extra_len = afl->a_extras[use_extra].len; - ptr = afl->a_extras[use_extra].data; + } else { - } else { + use_extra = rand_below(afl, afl->extras_cnt); + extra_len = afl->extras[use_extra].len; + ptr = afl->extras[use_extra].data; - use_extra = rand_below(afl, afl->extras_cnt); - extra_len = afl->extras[use_extra].len; - ptr = afl->extras[use_extra].data; + } - } + if (temp_len + extra_len >= MAX_FILE) { break; } - if (temp_len + extra_len >= MAX_FILE) { break; } + out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); - out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); + /* Tail */ + memmove(out_buf + insert_at + extra_len, out_buf + insert_at, + temp_len - insert_at); - /* Tail */ - memmove(out_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); + /* Inserted part */ + memcpy(out_buf + insert_at, ptr, extra_len); - /* Inserted part */ - memcpy(out_buf + insert_at, ptr, extra_len); + temp_len += extra_len; - temp_len += extra_len; + } else { - break; + // ascii mutations + if (text_mutation(afl, &out_buf, &temp_len) == 0) goto retry_havoc; - } +//#ifdef _AFL_DOCUMENT_MUTATIONS +// fprintf(stderr, "MUTATED: %s/mutations/%09u:*\n", afl->out_dir, +// afl->document_counter); +//#endif + + } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 0e8c8e47..f6c0e830 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -24,6 +24,7 @@ #include "afl-fuzz.h" #include +#include /* Mark deterministic checks as done for a particular queue entry. We use the .state file to avoid repeating deterministic fuzzing when resuming aborted @@ -100,6 +101,117 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } +/* check if ascii or UTF-8 */ + +static u8 check_if_text(struct queue_entry *q) { + + if (q->len < AFL_TXT_MIN_LEN) return 0; + + u8 buf[MAX_FILE]; + s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, percent, type, comp; + + if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; + if ((comp = read(fd, buf, len)) != len) return 0; + close(fd); + + while (offset < len) { + + // ASCII: <= 0x7F to allow ASCII control characters + if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A || + buf[offset + 0] == 0x0D || + (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) { + + offset++; + utf8++; + ascii++; + continue; + + } + + if (isascii((int)buf[offset]) || isprint((int)buf[offset])) { + + ascii++; + // we continue though as it can also be a valid utf8 + + } + + // non-overlong 2-byte + if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) { + + offset += 2; + utf8++; + comp--; + continue; + + } + + // excluding overlongs + if ((buf[offset + 0] == 0xE0 && + (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // straight 3-byte + (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) || + buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // excluding surrogates + (buf[offset + 0] == 0xED && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) { + + offset += 3; + utf8++; + comp -= 2; + continue; + + } + + // planes 1-3 + if ((buf[offset + 0] == 0xF0 && + (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && + buf[offset + 3] <= 0xBF)) || // planes 4-15 + ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16 + (buf[offset + 0] == 0xF4 && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) { + + offset += 4; + utf8++; + comp -= 3; + continue; + + } + + offset++; + + } + + if (utf8 >= ascii) { + + type = 2; + percent = (utf8 * 100) / comp; + + } else { + + type = 1; + percent = (ascii * 100) / comp; + + } + + if (percent >= AFL_TXT_MIN_PERCENT) + return type; + else + return 0; + +} + /* Append new test case to the queue. */ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { @@ -159,6 +271,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } + q->is_ascii = check_if_text(q); + } /* Destroy the entire queue. */ diff --git a/src/afl-performance.c b/src/afl-performance.c index 8efefcd8..07069108 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -33,10 +33,12 @@ static inline uint64_t rotl(const uint64_t x, int k) { } -uint64_t rand_next(afl_state_t *afl) { +uint32_t rand_next(afl_state_t *afl) { - const uint64_t result = - rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) + afl->rand_seed[0]; + const uint32_t result = + (uint32_t)rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) + + afl->rand_seed[0]; + // const uint32_t result = (uint32_t) rotl(afl->rand_seed[1] * 5, 7) * 9; const uint64_t t = afl->rand_seed[1] << 17; @@ -49,7 +51,7 @@ uint64_t rand_next(afl_state_t *afl) { afl->rand_seed[3] = rotl(afl->rand_seed[3], 45); - return result; + return (uint32_t)result; } -- cgit 1.4.1 From 5ca303393f0c3646c1ad032787f85c340c3aebbc Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 20 Jun 2020 09:21:02 +0200 Subject: fix ascii percentage calc --- src/afl-fuzz-queue.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f6c0e830..8f2d5a24 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -108,7 +108,7 @@ static u8 check_if_text(struct queue_entry *q) { if (q->len < AFL_TXT_MIN_LEN) return 0; u8 buf[MAX_FILE]; - s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, percent, type, comp; + s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, type, comp; if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; if ((comp = read(fd, buf, len)) != len) return 0; @@ -193,22 +193,14 @@ static u8 check_if_text(struct queue_entry *q) { } - if (utf8 >= ascii) { - - type = 2; - percent = (utf8 * 100) / comp; - - } else { - - type = 1; - percent = (ascii * 100) / comp; - - } - - if (percent >= AFL_TXT_MIN_PERCENT) - return type; - else - return 0; + u32 percent_utf8 = (utf8 * 100) / comp; + u32 percent_ascii = (ascii * 100) / len; + + if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT) + return 2; + if (percent_utf8 >= AFL_TXT_MIN_PERCENT) + return 1; + return 0; } -- cgit 1.4.1 From 1381e96d8ce09c6c09704764da189609fbe841cf Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 20 Jun 2020 09:22:14 +0200 Subject: fix ascii percentage calc --- src/afl-fuzz-queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 8f2d5a24..9988f335 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -108,7 +108,7 @@ static u8 check_if_text(struct queue_entry *q) { if (q->len < AFL_TXT_MIN_LEN) return 0; u8 buf[MAX_FILE]; - s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, type, comp; + s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp; if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; if ((comp = read(fd, buf, len)) != len) return 0; @@ -198,7 +198,7 @@ static u8 check_if_text(struct queue_entry *q) { if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT) return 2; - if (percent_utf8 >= AFL_TXT_MIN_PERCENT) + if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1; return 0; -- cgit 1.4.1 From 07a4e6370af5e1ad046c063b5b904176c7e978df Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 20 Jun 2020 10:55:02 +0200 Subject: modify txt configs for test --- include/config.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/config.h b/include/config.h index d4dd70ff..0ee149e7 100644 --- a/include/config.h +++ b/include/config.h @@ -402,16 +402,16 @@ /* What is the minimum length of a queue input to be evaluated for "is_ascii"? */ -#define AFL_TXT_MIN_LEN 8 +#define AFL_TXT_MIN_LEN 12 /* What is the minimum percentage of ascii characters present to be classifed as "is_ascii"? */ -#define AFL_TXT_MIN_PERCENT 80 +#define AFL_TXT_MIN_PERCENT 95 /* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ -#define AFL_TXT_BIAS 6 +#define AFL_TXT_BIAS 8 /* Maximum length of a string to tamper with */ @@ -419,7 +419,7 @@ /* Maximum mutations on a string */ -#define AFL_TXT_STRING_MAX_MUTATIONS 16 +#define AFL_TXT_STRING_MAX_MUTATIONS 8 #endif /* ! _HAVE_CONFIG_H */ -- cgit 1.4.1 From 76a2d9b59b23873c8a6d174a2f3c48eba60712fb Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 22 Jun 2020 13:48:59 +0200 Subject: further refinement --- include/config.h | 2 +- llvm_mode/afl-clang-fast.c | 8 ++--- src/afl-fuzz-one.c | 88 ++++++++++++++++++++++++++++------------------ src/afl-fuzz-queue.c | 18 +++++++--- 4 files changed, 72 insertions(+), 44 deletions(-) diff --git a/include/config.h b/include/config.h index 0ee149e7..09405a22 100644 --- a/include/config.h +++ b/include/config.h @@ -419,7 +419,7 @@ /* Maximum mutations on a string */ -#define AFL_TXT_STRING_MAX_MUTATIONS 8 +#define AFL_TXT_STRING_MAX_MUTATIONS 6 #endif /* ! _HAVE_CONFIG_H */ diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 6604b57c..65f9bb80 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -760,10 +760,10 @@ int main(int argc, char **argv, char **envp) { #if LLVM_VERSION_MAJOR <= 6 instrument_mode = INSTRUMENT_AFL; #else - if (getenv("AFL_LLVM_WHITELIST")) - instrument_mode = INSTRUMENT_AFL; - else - instrument_mode = INSTRUMENT_PCGUARD; + if (getenv("AFL_LLVM_WHITELIST")) + instrument_mode = INSTRUMENT_AFL; + else + instrument_mode = INSTRUMENT_PCGUARD; #endif } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index e097f6ef..ae53feb8 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -408,13 +408,14 @@ static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos, u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos); if (ldelim_start != NULL) { - - u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN : end_buf - ldelim_start - 1); + + u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : end_buf - ldelim_start - 1); if (max > 0) { - u8 *rdelim_end = - strnstr(ldelim_start + 1, rdelim, max); + u8 *rdelim_end = strnstr(ldelim_start + 1, rdelim, max); if (rdelim_end != NULL) { @@ -566,14 +567,21 @@ static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { for (u32 i = 0; i < mutations; i++) { - if (temp_len < AFL_TXT_MIN_LEN) { return 0; } + if (temp_len < AFL_TXT_MIN_LEN) { + + if (yes) + return 1; + else + return 0; + + } pos = rand_below(afl, temp_len - 1); - int choice = rand_below(afl, 72); + int choice = rand_below(afl, 76); switch (choice) { - case 0: /* Semantic statement deletion */ - yes += string_replace(out_buf, &temp_len, pos, "\n", "\nif (0==1)\n"); + case 0: + yes += string_replace(out_buf, &temp_len, pos, "*", " "); break; case 1: yes += string_replace(out_buf, &temp_len, pos, "(", "(!"); @@ -675,10 +683,10 @@ static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { yes += string_replace(out_buf, &temp_len, pos, "%", "+"); break; case 34: - yes += string_replace(out_buf, &temp_len, pos, "\n", "\nbreak;\n"); + yes += string_replace(out_buf, &temp_len, pos, "->", "."); break; case 35: - yes += string_replace(out_buf, &temp_len, pos, "\n", "\ncontinue;\n"); + yes += string_replace(out_buf, &temp_len, pos, ".", "->"); break; case 36: yes += string_replace(out_buf, &temp_len, pos, "0", "1"); @@ -693,7 +701,7 @@ static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { yes += string_replace(out_buf, &temp_len, pos, "while", "if"); break; case 40: - yes += string_replace(out_buf, &temp_len, pos, "\n", "\nwhile(1==1)\n"); + yes += string_replace(out_buf, &temp_len, pos, "!", " "); break; case 41: yes += string_replace(out_buf, &temp_len, pos, "&&", "||"); @@ -731,65 +739,74 @@ static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { case 52: yes += string_replace(out_buf, &temp_len, pos, "(", "\""); break; - case 53: /* Remove a semicolon delimited statement after a semicolon */ + case 53: + yes += string_replace(out_buf, &temp_len, pos, "\n", " "); + break; + case 54: + yes += string_replace(out_buf, &temp_len, pos, "\n", ";"); + break; + case 55: + yes += string_replace(out_buf, &temp_len, pos, "\n", "<"); + break; + case 56: /* Remove a semicolon delimited statement after a semicolon */ yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";"); break; - case 54: /* Remove a semicolon delimited statement after a left curly + case 57: /* Remove a semicolon delimited statement after a left curly brace */ yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}"); break; - case 55: /* Remove a curly brace construct */ + case 58: /* Remove a curly brace construct */ yes += delim_replace(out_buf, &temp_len, pos, "{", "}", ""); break; - case 56: /* Replace a curly brace construct with an empty one */ + case 59: /* Replace a curly brace construct with an empty one */ yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}"); break; - case 57: + case 60: yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";"); break; - case 58: + case 61: yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";"); break; - case 59: /* Swap comma delimited things case 1 */ + case 62: /* Swap comma delimited things case 1 */ yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")"); break; - case 60: /* Swap comma delimited things case 2 */ + case 63: /* Swap comma delimited things case 2 */ yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ","); break; - case 61: /* Swap comma delimited things case 3 */ + case 64: /* Swap comma delimited things case 3 */ yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ","); break; - case 62: /* Swap comma delimited things case 4 */ + case 65: /* Swap comma delimited things case 4 */ yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")"); break; - case 63: /* Just delete a line */ + case 66: /* Just delete a line */ yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", ""); break; - case 64: /* Delete something like "const" case 1 */ + case 67: /* Delete something like "const" case 1 */ yes += delim_replace(out_buf, &temp_len, pos, " ", " ", ""); break; - case 65: /* Delete something like "const" case 2 */ + case 68: /* Delete something like "const" case 2 */ yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", ""); break; - case 66: /* Delete something like "const" case 3 */ + case 69: /* Delete something like "const" case 3 */ yes += delim_replace(out_buf, &temp_len, pos, "(", " ", ""); break; - case 67: /* Swap space delimited things case 1 */ + case 70: /* Swap space delimited things case 1 */ yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " "); break; - case 68: /* Swap space delimited things case 2 */ + case 71: /* Swap space delimited things case 2 */ yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")"); break; - case 69: /* Swap space delimited things case 3 */ + case 72: /* Swap space delimited things case 3 */ yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " "); break; - case 70: /* Swap space delimited things case 4 */ + case 73: /* Swap space delimited things case 4 */ yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")"); break; - case 71: /* Duplicate a single line of code */ + case 74: /* Duplicate a single line of code */ yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL); break; - case 72: /* Duplicate a construct (most often, a non-nested for loop */ + case 75: /* Duplicate a construct (most often, a non-nested for loop */ yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL); break; @@ -2720,10 +2737,11 @@ havoc_stage: // ascii mutations if (text_mutation(afl, &out_buf, &temp_len) == 0) goto retry_havoc; -//#ifdef _AFL_DOCUMENT_MUTATIONS -// fprintf(stderr, "MUTATED: %s/mutations/%09u:*\n", afl->out_dir, -// afl->document_counter); -//#endif + //#ifdef _AFL_DOCUMENT_MUTATIONS + // fprintf(stderr, "MUTATED: %s/mutations/%09u:*\n", + // afl->out_dir, + // afl->document_counter); + //#endif } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 9988f335..39087878 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -107,7 +107,7 @@ static u8 check_if_text(struct queue_entry *q) { if (q->len < AFL_TXT_MIN_LEN) return 0; - u8 buf[MAX_FILE]; + u8 buf[MAX_FILE], bom[3] = {0xef, 0xbb, 0xbf}; s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp; if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; @@ -189,17 +189,27 @@ static u8 check_if_text(struct queue_entry *q) { } + // handle utf8 bom + if (buf[offset + 0] == bom[0] && buf[offset + 1] == bom[1] && + buf[offset + 2] == bom[2]) { + + offset += 3; + utf8++; + comp -= 2; + continue; + + } + offset++; } u32 percent_utf8 = (utf8 * 100) / comp; u32 percent_ascii = (ascii * 100) / len; - + if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT) return 2; - if (percent_ascii >= AFL_TXT_MIN_PERCENT) - return 1; + if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1; return 0; } -- cgit 1.4.1 From 4b99ebbf22fa7a9d4fe43056c641e71af04133be Mon Sep 17 00:00:00 2001 From: root Date: Mon, 29 Jun 2020 18:48:17 +0200 Subject: Revert "Merge branch 'text_inputs' into dev" This reverts commit 6d9b29daca46c8912aa9ddf6c053bc8554e9e9f7, reversing changes made to 07648f75ea5ef8f03a92db0c7566da8c229dc27b. --- include/afl-fuzz.h | 7 +- include/config.h | 26 +-- src/afl-fuzz-one.c | 584 +++++--------------------------------------------- src/afl-fuzz-queue.c | 116 ---------- src/afl-performance.c | 10 +- 5 files changed, 63 insertions(+), 680 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index ca785e47..c9f84c61 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -139,8 +139,7 @@ struct queue_entry { var_behavior, /* Variable behavior? */ favored, /* Currently favored? */ fs_redundant, /* Marked as redundant in the fs? */ - fully_colorized, /* Do not run redqueen stage again */ - is_ascii; /* Is the input just ascii text? */ + fully_colorized; /* Do not run redqueen stage again */ u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level; /* Number of fuzzing iterations */ @@ -948,7 +947,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, u64 exec_cksum); /* xoshiro256** */ -uint32_t rand_next(afl_state_t *afl); +uint64_t rand_next(afl_state_t *afl); /**** Inline routines ****/ @@ -968,7 +967,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { } - return (rand_next(afl) % limit); + return rand_next(afl) % limit; } diff --git a/include/config.h b/include/config.h index 09405a22..087e0a76 100644 --- a/include/config.h +++ b/include/config.h @@ -293,7 +293,7 @@ /* Call count interval between reseeding the libc PRNG from /dev/urandom: */ -#define RESEED_RNG 256000 +#define RESEED_RNG 100000 /* Maximum line length passed from GCC to 'as' and used for parsing configuration files: */ @@ -397,29 +397,5 @@ // #define IGNORE_FINDS -/* Text mutations */ - -/* What is the minimum length of a queue input to be evaluated for "is_ascii"? - */ - -#define AFL_TXT_MIN_LEN 12 - -/* What is the minimum percentage of ascii characters present to be classifed - as "is_ascii"? */ - -#define AFL_TXT_MIN_PERCENT 95 - -/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ - -#define AFL_TXT_BIAS 8 - -/* Maximum length of a string to tamper with */ - -#define AFL_TXT_STRING_MAX_LEN 1024 - -/* Maximum mutations on a string */ - -#define AFL_TXT_STRING_MAX_MUTATIONS 6 - #endif /* ! _HAVE_CONFIG_H */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 9e54815c..72383727 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -24,11 +24,6 @@ */ #include "afl-fuzz.h" -#include - -static u8 *strnstr(const u8 *s, const u8 *find, size_t slen); -static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, - u8 *to); /* MOpt */ @@ -367,463 +362,6 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { #endif /* !IGNORE_FINDS */ -/* Not pretty, but saves a lot of writing */ -#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size - -static u8 *strnstr(const u8 *s, const u8 *find, size_t slen) { - - char c, sc; - size_t len; - - if ((c = *find++) != '\0') { - - len = strlen(find); - do { - - do { - - if (slen-- < 1 || (sc = *s++) == '\0') return (NULL); - - } while (sc != c); - - if (len > slen) return (NULL); - - } while (strncmp(s, find, len) != 0); - - s--; - - } - - return ((u8 *)s); - -} - -/* replace between deliminators, if rep == NULL, then we will duplicate the - * target */ - -static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos, - const u8 *ldelim, const u8 *rdelim, u8 *rep) { - - u8 *end_buf = *out_buf + *temp_len; - u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos); - - if (ldelim_start != NULL) { - - u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN - ? AFL_TXT_STRING_MAX_LEN - : end_buf - ldelim_start - 1); - - if (max > 0) { - - u8 *rdelim_end = strnstr(ldelim_start + 1, rdelim, max); - - if (rdelim_end != NULL) { - - u32 rep_len, delim_space_len = rdelim_end - ldelim_start - 1, xtra = 0; - - if (rep != NULL) { - - rep_len = (u32)strlen(rep); - - } else { // NULL? then we copy the value in between the delimiters - - rep_len = delim_space_len; - delim_space_len = 0; - rep = ldelim_start + 1; - xtra = rep_len; - - } - - if (rep_len != delim_space_len) { - - memmove(ldelim_start + rep_len + xtra + 1, rdelim_end, - *temp_len - (rdelim_end - *out_buf)); - - } - - memcpy(ldelim_start + 1, rep, rep_len); - *temp_len = (*temp_len - delim_space_len + rep_len); - - return 1; - - } - - } - - } - - return 0; - -} - -static u32 delim_swap(u8 **out_buf, s32 *temp_len, size_t pos, const u8 *ldelim, - const u8 *mdelim, const u8 *rdelim) { - - u8 *out_buf_end = *out_buf + *temp_len; - u32 max = (*temp_len - pos > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN - : *temp_len - pos); - u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, max); - - if (ldelim_start != NULL) { - - max = (out_buf_end - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN - ? AFL_TXT_STRING_MAX_LEN - : out_buf_end - ldelim_start - 1); - if (max > 1) { - - u8 *mdelim_pos = strnstr(ldelim_start + 1, mdelim, max); - - if (mdelim_pos != NULL) { - - max = (out_buf_end - mdelim_pos - 1 > AFL_TXT_STRING_MAX_LEN - ? AFL_TXT_STRING_MAX_LEN - : out_buf_end - mdelim_pos - 1); - if (max > 0) { - - u8 *rdelim_end = strnstr(mdelim + 1, rdelim, max); - - if (rdelim_end != NULL) { - - u32 first_len = mdelim_pos - ldelim_start - 1; - u32 second_len = rdelim_end - mdelim_pos - 1; - u8 scratch[AFL_TXT_STRING_MAX_LEN]; - - memcpy(scratch, ldelim_start + 1, first_len); - - if (first_len != second_len) { - - memmove(ldelim_start + second_len + 1, mdelim_pos, - out_buf_end - mdelim_pos); - - } - - memcpy(ldelim_start + 1, mdelim_pos + 1, second_len); - - if (first_len != second_len) { - - memmove(mdelim_pos + first_len + 1, rdelim_end, - out_buf_end - rdelim_end); - - } - - memcpy(mdelim_pos + 1, scratch, first_len); - - return 1; - - } - - } - - } - - } - - } - - return 0; - -} - -static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, - u8 *to) { - - u8 *start = strnstr(*out_buf + pos, from, *temp_len - pos); - - if (start) { - - u32 from_len = strlen(from); - u32 to_len = strlen(to); - - if (from_len != to_len) { - - memmove(start + to_len, start + from_len, - *temp_len - from_len - (start - *out_buf)); - - } - - memcpy(start, to, to_len); - *temp_len = (*temp_len - from_len + to_len); - - return 1; - - } - - return 0; - -} - -/* Returns 1 if a mutant was generated and placed in out_buf, 0 if none - * generated. */ - -static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { - - s32 temp_len; - u32 pos, yes = 0, - mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 1; - u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), - *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS); - temp_len = *orig_temp_len; - memcpy(new_buf, *out_buf, temp_len); - - for (u32 i = 0; i < mutations; i++) { - - if (temp_len < AFL_TXT_MIN_LEN) { - - if (yes) - return 1; - else - return 0; - - } - - pos = rand_below(afl, temp_len - 1); - int choice = rand_below(afl, 76); - switch (choice) { - - case 0: - yes += string_replace(out_buf, &temp_len, pos, "*", " "); - break; - case 1: - yes += string_replace(out_buf, &temp_len, pos, "(", "(!"); - break; - case 2: - yes += string_replace(out_buf, &temp_len, pos, "==", "!="); - break; - case 3: - yes += string_replace(out_buf, &temp_len, pos, "!=", "=="); - break; - case 4: - yes += string_replace(out_buf, &temp_len, pos, "==", "<"); - break; - case 5: - yes += string_replace(out_buf, &temp_len, pos, "<", "=="); - break; - case 6: - yes += string_replace(out_buf, &temp_len, pos, "==", ">"); - break; - case 7: - yes += string_replace(out_buf, &temp_len, pos, ">", "=="); - break; - case 8: - yes += string_replace(out_buf, &temp_len, pos, "=", "<"); - break; - case 9: - yes += string_replace(out_buf, &temp_len, pos, "=", ">"); - break; - case 10: - yes += string_replace(out_buf, &temp_len, pos, "<", ">"); - break; - case 11: - yes += string_replace(out_buf, &temp_len, pos, ">", "<"); - break; - case 12: - yes += string_replace(out_buf, &temp_len, pos, "++", "--"); - break; - case 13: - yes += string_replace(out_buf, &temp_len, pos, "--", "++"); - break; - case 14: - yes += string_replace(out_buf, &temp_len, pos, "+", "-"); - break; - case 15: - yes += string_replace(out_buf, &temp_len, pos, "+", "*"); - break; - case 16: - yes += string_replace(out_buf, &temp_len, pos, "+", "/"); - break; - case 17: - yes += string_replace(out_buf, &temp_len, pos, "+", "%"); - break; - case 18: - yes += string_replace(out_buf, &temp_len, pos, "*", "-"); - break; - case 19: - yes += string_replace(out_buf, &temp_len, pos, "*", "+"); - break; - case 20: - yes += string_replace(out_buf, &temp_len, pos, "*", "/"); - break; - case 21: - yes += string_replace(out_buf, &temp_len, pos, "*", "%"); - break; - case 22: - yes += string_replace(out_buf, &temp_len, pos, "-", "+"); - break; - case 23: - yes += string_replace(out_buf, &temp_len, pos, "-", "*"); - break; - case 24: - yes += string_replace(out_buf, &temp_len, pos, "-", "/"); - break; - case 25: - yes += string_replace(out_buf, &temp_len, pos, "-", "%"); - break; - case 26: - yes += string_replace(out_buf, &temp_len, pos, "/", "-"); - break; - case 27: - yes += string_replace(out_buf, &temp_len, pos, "/", "*"); - break; - case 28: - yes += string_replace(out_buf, &temp_len, pos, "/", "+"); - break; - case 29: - yes += string_replace(out_buf, &temp_len, pos, "/", "%"); - break; - case 30: - yes += string_replace(out_buf, &temp_len, pos, "%", "-"); - break; - case 31: - yes += string_replace(out_buf, &temp_len, pos, "%", "*"); - break; - case 32: - yes += string_replace(out_buf, &temp_len, pos, "%", "/"); - break; - case 33: - yes += string_replace(out_buf, &temp_len, pos, "%", "+"); - break; - case 34: - yes += string_replace(out_buf, &temp_len, pos, "->", "."); - break; - case 35: - yes += string_replace(out_buf, &temp_len, pos, ".", "->"); - break; - case 36: - yes += string_replace(out_buf, &temp_len, pos, "0", "1"); - break; - case 37: - yes += string_replace(out_buf, &temp_len, pos, "1", "0"); - break; - case 38: - yes += string_replace(out_buf, &temp_len, pos, "if", "while"); - break; - case 39: - yes += string_replace(out_buf, &temp_len, pos, "while", "if"); - break; - case 40: - yes += string_replace(out_buf, &temp_len, pos, "!", " "); - break; - case 41: - yes += string_replace(out_buf, &temp_len, pos, "&&", "||"); - break; - case 42: - yes += string_replace(out_buf, &temp_len, pos, "||", "&&"); - break; - case 43: - yes += string_replace(out_buf, &temp_len, pos, "!", ""); - break; - case 44: - yes += string_replace(out_buf, &temp_len, pos, "==", "="); - break; - case 45: - yes += string_replace(out_buf, &temp_len, pos, "--", ""); - break; - case 46: - yes += string_replace(out_buf, &temp_len, pos, "<<", "<"); - break; - case 47: - yes += string_replace(out_buf, &temp_len, pos, ">>", ">"); - break; - case 48: - yes += string_replace(out_buf, &temp_len, pos, "<", "<<"); - break; - case 49: - yes += string_replace(out_buf, &temp_len, pos, ">", ">>"); - break; - case 50: - yes += string_replace(out_buf, &temp_len, pos, "\"", "'"); - break; - case 51: - yes += string_replace(out_buf, &temp_len, pos, "'", "\""); - break; - case 52: - yes += string_replace(out_buf, &temp_len, pos, "(", "\""); - break; - case 53: - yes += string_replace(out_buf, &temp_len, pos, "\n", " "); - break; - case 54: - yes += string_replace(out_buf, &temp_len, pos, "\n", ";"); - break; - case 55: - yes += string_replace(out_buf, &temp_len, pos, "\n", "<"); - break; - case 56: /* Remove a semicolon delimited statement after a semicolon */ - yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";"); - break; - case 57: /* Remove a semicolon delimited statement after a left curly - brace */ - yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}"); - break; - case 58: /* Remove a curly brace construct */ - yes += delim_replace(out_buf, &temp_len, pos, "{", "}", ""); - break; - case 59: /* Replace a curly brace construct with an empty one */ - yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}"); - break; - case 60: - yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";"); - break; - case 61: - yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";"); - break; - case 62: /* Swap comma delimited things case 1 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")"); - break; - case 63: /* Swap comma delimited things case 2 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ","); - break; - case 64: /* Swap comma delimited things case 3 */ - yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ","); - break; - case 65: /* Swap comma delimited things case 4 */ - yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")"); - break; - case 66: /* Just delete a line */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", ""); - break; - case 67: /* Delete something like "const" case 1 */ - yes += delim_replace(out_buf, &temp_len, pos, " ", " ", ""); - break; - case 68: /* Delete something like "const" case 2 */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", ""); - break; - case 69: /* Delete something like "const" case 3 */ - yes += delim_replace(out_buf, &temp_len, pos, "(", " ", ""); - break; - case 70: /* Swap space delimited things case 1 */ - yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " "); - break; - case 71: /* Swap space delimited things case 2 */ - yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")"); - break; - case 72: /* Swap space delimited things case 3 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " "); - break; - case 73: /* Swap space delimited things case 4 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")"); - break; - case 74: /* Duplicate a single line of code */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL); - break; - case 75: /* Duplicate a construct (most often, a non-nested for loop */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL); - break; - - } - - } - - if (yes == 0 || temp_len <= 0) { return 0; } - - swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); - *out_buf = new_buf; - *orig_temp_len = temp_len; - - return 1; - -} - /* Take the current entry from the queue, fuzz it for a while. This function is a tad too long... returns 0 if fuzzed successfully, 1 if skipped or bailed out. */ @@ -840,6 +378,9 @@ u8 fuzz_one_original(afl_state_t *afl) { u8 a_collect[MAX_AUTO_EXTRA]; u32 a_len = 0; +/* Not pretty, but saves a lot of writing */ +#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + #ifdef IGNORE_FINDS /* In IGNORE_FINDS mode, skip any entries that weren't in the @@ -2313,12 +1854,9 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ - u32 r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0) + - (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0); - for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { - u32 r, use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2)); + u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2)); afl->stage_cur_val = use_stacking; @@ -2358,9 +1896,8 @@ havoc_stage: } - retry_havoc: - - switch ((r = rand_below(afl, r_max))) { + switch (rand_below( + afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) { case 0: @@ -2655,96 +2192,85 @@ havoc_stage: } - // TODO: add splicing mutation here. - // 15: - // break; - - default: - if (r == 15 && (afl->extras_cnt || afl->a_extras_cnt)) { + /* Values 15 and 16 can be selected only if there are any extras + present in the dictionaries. */ - /* Values 15 and 16 can be selected only if there are any extras - present in the dictionaries. */ + case 15: { - /* Overwrite bytes with an extra. */ + /* Overwrite bytes with an extra. */ - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { - /* No user-specified extras or odds in our favor. Let's use an - auto-detected one. */ + /* No user-specified extras or odds in our favor. Let's use an + auto-detected one. */ - u32 use_extra = rand_below(afl, afl->a_extras_cnt); - u32 extra_len = afl->a_extras[use_extra].len; - u32 insert_at; + u32 use_extra = rand_below(afl, afl->a_extras_cnt); + u32 extra_len = afl->a_extras[use_extra].len; + u32 insert_at; - if (extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, - extra_len); + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, + extra_len); - } else { + } else { - /* No auto extras or odds in our favor. Use the dictionary. */ + /* No auto extras or odds in our favor. Use the dictionary. */ - u32 use_extra = rand_below(afl, afl->extras_cnt); - u32 extra_len = afl->extras[use_extra].len; - u32 insert_at; + u32 use_extra = rand_below(afl, afl->extras_cnt); + u32 extra_len = afl->extras[use_extra].len; + u32 insert_at; - if (extra_len > temp_len) { break; } + if (extra_len > temp_len) { break; } - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->extras[use_extra].data, - extra_len); + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len); - } + } - } else if (r == 16 && (afl->extras_cnt || afl->a_extras_cnt)) { + break; - u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1); - u8 *ptr; + } - /* Insert an extra. Do the same dice-rolling stuff as for the - previous case. */ + case 16: { - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1); + u8 *ptr; - use_extra = rand_below(afl, afl->a_extras_cnt); - extra_len = afl->a_extras[use_extra].len; - ptr = afl->a_extras[use_extra].data; + /* Insert an extra. Do the same dice-rolling stuff as for the + previous case. */ - } else { + if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { - use_extra = rand_below(afl, afl->extras_cnt); - extra_len = afl->extras[use_extra].len; - ptr = afl->extras[use_extra].data; + use_extra = rand_below(afl, afl->a_extras_cnt); + extra_len = afl->a_extras[use_extra].len; + ptr = afl->a_extras[use_extra].data; - } + } else { - if (temp_len + extra_len >= MAX_FILE) { break; } + use_extra = rand_below(afl, afl->extras_cnt); + extra_len = afl->extras[use_extra].len; + ptr = afl->extras[use_extra].data; - out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); + } - /* Tail */ - memmove(out_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); + if (temp_len + extra_len >= MAX_FILE) { break; } - /* Inserted part */ - memcpy(out_buf + insert_at, ptr, extra_len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); - temp_len += extra_len; + /* Tail */ + memmove(out_buf + insert_at + extra_len, out_buf + insert_at, + temp_len - insert_at); - } else { + /* Inserted part */ + memcpy(out_buf + insert_at, ptr, extra_len); - // ascii mutations - if (text_mutation(afl, &out_buf, &temp_len) == 0) goto retry_havoc; + temp_len += extra_len; - //#ifdef _AFL_DOCUMENT_MUTATIONS - // fprintf(stderr, "MUTATED: %s/mutations/%09u:*\n", - // afl->out_dir, - // afl->document_counter); - //#endif + break; - } + } } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index da6b1eee..7afdd9f1 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -24,7 +24,6 @@ #include "afl-fuzz.h" #include -#include /* Mark deterministic checks as done for a particular queue entry. We use the .state file to avoid repeating deterministic fuzzing when resuming aborted @@ -101,119 +100,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } -/* check if ascii or UTF-8 */ - -static u8 check_if_text(struct queue_entry *q) { - - if (q->len < AFL_TXT_MIN_LEN) return 0; - - u8 buf[MAX_FILE], bom[3] = {0xef, 0xbb, 0xbf}; - s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp; - - if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; - if ((comp = read(fd, buf, len)) != len) return 0; - close(fd); - - while (offset < len) { - - // ASCII: <= 0x7F to allow ASCII control characters - if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A || - buf[offset + 0] == 0x0D || - (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) { - - offset++; - utf8++; - ascii++; - continue; - - } - - if (isascii((int)buf[offset]) || isprint((int)buf[offset])) { - - ascii++; - // we continue though as it can also be a valid utf8 - - } - - // non-overlong 2-byte - if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) { - - offset += 2; - utf8++; - comp--; - continue; - - } - - // excluding overlongs - if ((buf[offset + 0] == 0xE0 && - (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && - buf[offset + 2] <= 0xBF)) || // straight 3-byte - (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) || - buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && - buf[offset + 2] <= 0xBF)) || // excluding surrogates - (buf[offset + 0] == 0xED && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) { - - offset += 3; - utf8++; - comp -= 2; - continue; - - } - - // planes 1-3 - if ((buf[offset + 0] == 0xF0 && - (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && - buf[offset + 3] <= 0xBF)) || // planes 4-15 - ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16 - (buf[offset + 0] == 0xF4 && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) { - - offset += 4; - utf8++; - comp -= 3; - continue; - - } - - // handle utf8 bom - if (buf[offset + 0] == bom[0] && buf[offset + 1] == bom[1] && - buf[offset + 2] == bom[2]) { - - offset += 3; - utf8++; - comp -= 2; - continue; - - } - - offset++; - - } - - u32 percent_utf8 = (utf8 * 100) / comp; - u32 percent_ascii = (ascii * 100) / len; - - if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT) - return 2; - if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1; - return 0; - -} - /* Append new test case to the queue. */ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { @@ -273,8 +159,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } - q->is_ascii = check_if_text(q); - } /* Destroy the entire queue. */ diff --git a/src/afl-performance.c b/src/afl-performance.c index 6631f148..0c1697a8 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -44,12 +44,10 @@ void rand_set_seed(afl_state_t *afl, s64 init_seed) { } -uint32_t rand_next(afl_state_t *afl) { +uint64_t rand_next(afl_state_t *afl) { - const uint32_t result = - (uint32_t)rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) + - afl->rand_seed[0]; - // const uint32_t result = (uint32_t) rotl(afl->rand_seed[1] * 5, 7) * 9; + const uint64_t result = + rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) + afl->rand_seed[0]; const uint64_t t = afl->rand_seed[1] << 17; @@ -62,7 +60,7 @@ uint32_t rand_next(afl_state_t *afl) { afl->rand_seed[3] = rotl(afl->rand_seed[3], 45); - return (uint32_t)result; + return result; } -- cgit 1.4.1 From 878b27af762b9d79d46c3de59ced749bb0e93d35 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 30 Jun 2020 16:52:48 +0200 Subject: blacklist -> ignore renaming --- llvm_mode/afl-llvm-common.cc | 14 +++++++------- llvm_mode/afl-llvm-common.h | 2 +- llvm_mode/afl-llvm-lto-instrim.so.cc | 2 +- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 2 +- llvm_mode/afl-llvm-lto-whitelist.so.cc | 2 +- src/afl-fuzz-redqueen.c | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 6c7222cd..5a75c4dd 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -44,13 +44,13 @@ char *getBBName(const llvm::BasicBlock *BB) { } /* Function that we never instrument or analyze */ -/* Note: this blacklist check is also called in isInWhitelist() */ -bool isBlacklisted(const llvm::Function *F) { +/* Note: this ignore check is also called in isInWhitelist() */ +bool isIgnoreFunction(const llvm::Function *F) { // Starting from "LLVMFuzzer" these are functions used in libfuzzer based // fuzzing campaign installations, e.g. oss-fuzz - static const char *Blacklist[] = { + static const char *ignoreList[] = { "asan.", "llvm.", @@ -73,9 +73,9 @@ bool isBlacklisted(const llvm::Function *F) { }; - for (auto const &BlacklistFunc : Blacklist) { + for (auto const &ignoreListFunc : ignoreList) { - if (F->getName().startswith(BlacklistFunc)) { return true; } + if (F->getName().startswith(ignoreListFunc)) { return true; } } @@ -107,8 +107,8 @@ void initWhitelist() { bool isInWhitelist(llvm::Function *F) { // is this a function with code? If it is external we dont instrument it - // anyway and cant be in the whitelist. Or if it is blacklisted. - if (!F->size() || isBlacklisted(F)) return false; + // anyway and cant be in the whitelist. Or if it is ignored. + if (!F->size() || isIgnoreFunction(F)) return false; // if we do not have a whitelist return true if (myWhitelist.empty()) return true; diff --git a/llvm_mode/afl-llvm-common.h b/llvm_mode/afl-llvm-common.h index 50ad3abc..db009f8f 100644 --- a/llvm_mode/afl-llvm-common.h +++ b/llvm_mode/afl-llvm-common.h @@ -33,7 +33,7 @@ typedef long double max_align_t; #endif char * getBBName(const llvm::BasicBlock *BB); -bool isBlacklisted(const llvm::Function *F); +bool isIgnoreFunction(const llvm::Function *F); void initWhitelist(); bool isInWhitelist(llvm::Function *F); unsigned long long int calculateCollisions(uint32_t edges); diff --git a/llvm_mode/afl-llvm-lto-instrim.so.cc b/llvm_mode/afl-llvm-lto-instrim.so.cc index 4b89c9d0..b62912a6 100644 --- a/llvm_mode/afl-llvm-lto-instrim.so.cc +++ b/llvm_mode/afl-llvm-lto-instrim.so.cc @@ -562,7 +562,7 @@ struct InsTrimLTO : public ModulePass { // if the function below our minimum size skip it (1 or 2) if (F.size() < function_minimum_size) continue; - if (isBlacklisted(&F)) continue; + if (isIgnoreFunction(&F)) continue; functions++; diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 0d3015d7..82af890c 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -196,7 +196,7 @@ bool AFLLTOPass::runOnModule(Module &M) { // fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str()); if (F.size() < function_minimum_size) continue; - if (isBlacklisted(&F)) continue; + if (isIgnoreFunction(&F)) continue; // whitelist check AttributeList Attrs = F.getAttributes(); diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc index b1f791f4..52c7cf0d 100644 --- a/llvm_mode/afl-llvm-lto-whitelist.so.cc +++ b/llvm_mode/afl-llvm-lto-whitelist.so.cc @@ -126,7 +126,7 @@ bool AFLwhitelist::runOnModule(Module &M) { if (F.size() < 1) continue; // fprintf(stderr, "F:%s\n", F.getName().str().c_str()); - if (isBlacklisted(&F)) continue; + if (isIgnoreFunction(&F)) continue; BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 43850eb5..44953a52 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -435,7 +435,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { u32 fails; u8 found_one = 0; - /* loop cmps are useless, detect and blacklist them */ + /* loop cmps are useless, detect and ignores them */ u64 s_v0, s_v1; u8 s_v0_fixed = 1, s_v1_fixed = 1; u8 s_v0_inc = 1, s_v1_inc = 1; @@ -743,7 +743,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, afl->pass_stats[k].faileds || afl->pass_stats[k].total == 0xff)) { - afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp + afl->shm.cmp_map->headers[k].hits = 0; // ignores this cmp } -- cgit 1.4.1 From 06264df16891070a09a31cd981a9dcaaf01de7c7 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 30 Jun 2020 17:28:21 +0200 Subject: rename whitelist -> instrumentlist --- README.md | 8 +- docs/Changelog.md | 14 +- docs/PATCHES.md | 2 +- docs/env_variables.md | 12 +- docs/perf_tips.md | 4 +- gcc_plugin/GNUmakefile | 2 +- gcc_plugin/Makefile | 2 +- gcc_plugin/README.instrument_file.md | 73 ++++++++ gcc_plugin/README.whitelist.md | 73 -------- gcc_plugin/afl-gcc-fast.c | 95 +++++----- gcc_plugin/afl-gcc-pass.so.cc | 37 ++-- llvm_mode/GNUmakefile | 6 +- llvm_mode/LLVMInsTrim.so.cc | 4 +- llvm_mode/README.instrument_file.md | 79 +++++++++ llvm_mode/README.lto.md | 4 +- llvm_mode/README.md | 4 +- llvm_mode/README.whitelist.md | 79 --------- llvm_mode/TODO | 10 -- llvm_mode/afl-clang-fast.c | 17 +- llvm_mode/afl-llvm-common.cc | 37 ++-- llvm_mode/afl-llvm-common.h | 4 +- llvm_mode/afl-llvm-lto-instrim.so.cc | 5 +- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 5 +- llvm_mode/afl-llvm-lto-instrumentlist.so.cc | 253 +++++++++++++++++++++++++++ llvm_mode/afl-llvm-lto-whitelist.so.cc | 244 -------------------------- llvm_mode/afl-llvm-pass.so.cc | 4 +- llvm_mode/cmplog-instructions-pass.cc | 4 +- llvm_mode/cmplog-routines-pass.cc | 4 +- llvm_mode/compare-transform-pass.so.cc | 4 +- llvm_mode/split-compares-pass.so.cc | 4 +- llvm_mode/split-switches-pass.so.cc | 4 +- src/afl-common.c | 4 +- src/afl-fuzz.c | 4 +- test/test-performance.sh | 4 +- test/test.sh | 40 ++--- 35 files changed, 586 insertions(+), 563 deletions(-) create mode 100644 gcc_plugin/README.instrument_file.md delete mode 100644 gcc_plugin/README.whitelist.md create mode 100644 llvm_mode/README.instrument_file.md delete mode 100644 llvm_mode/README.whitelist.md delete mode 100644 llvm_mode/TODO create mode 100644 llvm_mode/afl-llvm-lto-instrumentlist.so.cc delete mode 100644 llvm_mode/afl-llvm-lto-whitelist.so.cc diff --git a/README.md b/README.md index 104f56ea..dd32e28e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ AFL++ Logo - ![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=master) + ![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=stable) Release Version: [2.65c](https://github.com/AFLplusplus/AFLplusplus/releases) @@ -40,7 +40,7 @@ * InsTrim, a very effective CFG llvm_mode instrumentation implementation for large targets: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim) - * C. Holler's afl-fuzz Python mutator module and llvm_mode whitelist support: [https://github.com/choller/afl](https://github.com/choller/afl) + * C. Holler's afl-fuzz Python mutator module and llvm_mode instrument file support: [https://github.com/choller/afl](https://github.com/choller/afl) * Custom mutator by a library (instead of Python) by kyakdan @@ -70,7 +70,7 @@ | Persistent mode | | x | x | x86[_64]/arm[64] | x | | LAF-Intel / CompCov | | x | | x86[_64]/arm[64] | x86[_64]/arm | | CmpLog | | x | | x86[_64]/arm[64] | | - | Whitelist | | x | x | (x)(3) | | + | Instrument file list | | x | x | (x)(3) | | | Non-colliding coverage | | x(4) | | (x)(5) | | | InsTrim | | x | | | | | Ngram prev_loc coverage | | x(6) | | | | @@ -297,7 +297,7 @@ Using the LAF Intel performance enhancements are also recommended, see [llvm_mode/README.laf-intel.md](llvm_mode/README.laf-intel.md) Using partial instrumentation is also recommended, see -[llvm_mode/README.whitelist.md](llvm_mode/README.whitelist.md) +[llvm_mode/README.instrument_file.md](llvm_mode/README.instrument_file.md) When testing libraries, you need to find or write a simple program that reads data from stdin or from a file and passes it to the tested library. In such a diff --git a/docs/Changelog.md b/docs/Changelog.md index 1ecea274..6718ecde 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,10 @@ sending a mail to . ### Version ++2.65d (dev) + - renamed the main branch on Github to "stable" + - renamed master/slave to main/secondary + - renamed blacklist/whitelist to ignorelist/instrumentlist -> + AFL_LLVM_INSTRUMENT_FILE and AFL_GCC_INSTRUMENT_FILE - afl-fuzz: - -S secondary nodes now only sync from the main node to increase performance, the -M main node still syncs from everyone. Added checks @@ -40,8 +44,8 @@ sending a mail to . - WHITELIST feature now supports wildcards (thanks to sirmc) - small change to cmplog to make it work with current llvm 11-dev - added AFL_LLVM_LAF_ALL, sets all laf-intel settings - - LTO whitelist functionality rewritten, now main, _init etc functions - need not to be whitelisted anymore + - LTO instrument_files functionality rewritten, now main, _init etc functions + need not to be instrument_filesed anymore - fixed crash in compare-transform-pass when strcasecmp/strncasecmp was tried to be instrumented with LTO - fixed crash in cmplog with LTO @@ -249,7 +253,7 @@ sending a mail to . the original script is still present as afl-cmin.bash - afl-showmap: -i dir option now allows processing multiple inputs using the forkserver. This is for enhanced speed in afl-cmin. - - added blacklist and whitelisting function check in all modules of llvm_mode + - added blacklist and instrument_filesing function check in all modules of llvm_mode - added fix from Debian project to compile libdislocator and libtokencap - libdislocator: AFL_ALIGNED_ALLOC to force size alignment to max_align_t @@ -304,7 +308,7 @@ sending a mail to . performance loss of ~10% - added test/test-performance.sh script - (re)added gcc_plugin, fast inline instrumentation is not yet finished, - however it includes the whitelisting and persistance feature! by hexcoder- + however it includes the instrument_filesing and persistance feature! by hexcoder- - gcc_plugin tests added to testing framework @@ -392,7 +396,7 @@ sending a mail to . - more cpu power for afl-system-config - added forkserver patch to afl-tmin, makes it much faster (originally from github.com/nccgroup/TriforceAFL) - - added whitelist support for llvm_mode via AFL_LLVM_WHITELIST to allow + - added instrument_files support for llvm_mode via AFL_LLVM_WHITELIST to allow only to instrument what is actually interesting. Gives more speed and less map pollution (originally by choller@mozilla) - added Python Module mutator support, python2.7-dev is autodetected. diff --git a/docs/PATCHES.md b/docs/PATCHES.md index a6783523..b2cff43a 100644 --- a/docs/PATCHES.md +++ b/docs/PATCHES.md @@ -28,7 +28,7 @@ afl-qemu-optimize-map.diff by mh(at)mh-sec(dot)de + AFLfast additions (github.com/mboehme/aflfast) were incorporated. + Qemu 3.1 upgrade with enhancement patches (github.com/andreafioraldi/afl) + Python mutator modules support (github.com/choller/afl) -+ Whitelisting in LLVM mode (github.com/choller/afl) ++ Instrument file list in LLVM mode (github.com/choller/afl) + forkserver patch for afl-tmin (github.com/nccgroup/TriforceAFL) diff --git a/docs/env_variables.md b/docs/env_variables.md index 867e937e..87344331 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -204,14 +204,14 @@ Then there are a few specific features that are only available in llvm_mode: See llvm_mode/README.laf-intel.md for more information. -### WHITELIST +### INSTRUMENT_FILE This feature allows selectively instrumentation of the source - - Setting AFL_LLVM_WHITELIST with a filename will only instrument those + - Setting AFL_LLVM_INSTRUMENT_FILE with a filename will only instrument those files that match the names listed in this file. - See llvm_mode/README.whitelist.md for more information. + See llvm_mode/README.instrument_file.md for more information. ### NOT_ZERO @@ -236,14 +236,14 @@ Then there are a few specific features that are only available in llvm_mode: Then there are a few specific features that are only available in the gcc_plugin: -### WHITELIST +### INSTRUMENT_FILE This feature allows selective instrumentation of the source - - Setting AFL_GCC_WHITELIST with a filename will only instrument those + - Setting AFL_GCC_INSTRUMENT_FILE with a filename will only instrument those files that match the names listed in this file (one filename per line). - See gcc_plugin/README.whitelist.md for more information. + See gcc_plugin/README.instrument_file.md for more information. ## 3) Settings for afl-fuzz diff --git a/docs/perf_tips.md b/docs/perf_tips.md index fcd03db7..7a690b77 100644 --- a/docs/perf_tips.md +++ b/docs/perf_tips.md @@ -66,8 +66,8 @@ then using laf-intel (see llvm_mode/README.laf-intel.md) will help `afl-fuzz` a to get to the important parts in the code. If you are only interested in specific parts of the code being fuzzed, you can -whitelist the files that are actually relevant. This improves the speed and -accuracy of afl. See llvm_mode/README.whitelist.md +instrument_files the files that are actually relevant. This improves the speed and +accuracy of afl. See llvm_mode/README.instrument_file.md Also use the InsTrim mode on larger binaries, this improves performance and coverage a lot. diff --git a/gcc_plugin/GNUmakefile b/gcc_plugin/GNUmakefile index 60f04bb7..bf5c53e0 100644 --- a/gcc_plugin/GNUmakefile +++ b/gcc_plugin/GNUmakefile @@ -156,7 +156,7 @@ install: all install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH) install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH) install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md - install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md + install -m 644 -T README.instrument_file.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md clean: rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2 diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index 7eff326a..f720112f 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -152,7 +152,7 @@ install: all install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH) install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH) install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md - install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md + install -m 644 -T README.instrument_file.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.instrument_file.md clean: rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2 diff --git a/gcc_plugin/README.instrument_file.md b/gcc_plugin/README.instrument_file.md new file mode 100644 index 00000000..d0eaf6ff --- /dev/null +++ b/gcc_plugin/README.instrument_file.md @@ -0,0 +1,73 @@ +======================================== +Using afl++ with partial instrumentation +======================================== + + This file describes how you can selectively instrument only the source files + that are interesting to you using the gcc instrumentation provided by + afl++. + + Plugin by hexcoder-. + + +## 1) Description and purpose + +When building and testing complex programs where only a part of the program is +the fuzzing target, it often helps to only instrument the necessary parts of +the program, leaving the rest uninstrumented. This helps to focus the fuzzer +on the important parts of the program, avoiding undesired noise and +disturbance by uninteresting code being exercised. + +For this purpose, I have added a "partial instrumentation" support to the gcc +plugin of AFLFuzz that allows you to specify on a source file level which files +should be compiled with or without instrumentation. + + +## 2) Building the gcc plugin + +The new code is part of the existing afl++ gcc plugin in the gcc_plugin/ +subdirectory. There is nothing specifically to do :) + + +## 3) How to use the partial instrumentation mode + +In order to build with partial instrumentation, you need to build with +afl-gcc-fast and afl-g++-fast respectively. The only required change is +that you need to set the environment variable AFL_GCC_INSTRUMENT_FILE when calling +the compiler. + +The environment variable must point to a file containing all the filenames +that should be instrumented. For matching, the filename that is being compiled +must end in the filename entry contained in this instrument list (to avoid breaking +the matching when absolute paths are used during compilation). + +For example if your source tree looks like this: + +``` +project/ +project/feature_a/a1.cpp +project/feature_a/a2.cpp +project/feature_b/b1.cpp +project/feature_b/b2.cpp +``` + +and you only want to test feature_a, then create a instrument list file containing: + +``` +feature_a/a1.cpp +feature_a/a2.cpp +``` + +However if the instrument list file contains only this, it works as well: + +``` +a1.cpp +a2.cpp +``` + +but it might lead to files being unwantedly instrumented if the same filename +exists somewhere else in the project directories. + +The created instrument list file is then set to AFL_GCC_INSTRUMENT_FILE when you compile +your program. For each file that didn't match the instrument list, the compiler will +issue a warning at the end stating that no blocks were instrumented. If you +didn't intend to instrument that file, then you can safely ignore that warning. diff --git a/gcc_plugin/README.whitelist.md b/gcc_plugin/README.whitelist.md deleted file mode 100644 index 8ad2068d..00000000 --- a/gcc_plugin/README.whitelist.md +++ /dev/null @@ -1,73 +0,0 @@ -======================================== -Using afl++ with partial instrumentation -======================================== - - This file describes how you can selectively instrument only the source files - that are interesting to you using the gcc instrumentation provided by - afl++. - - Plugin by hexcoder-. - - -## 1) Description and purpose - -When building and testing complex programs where only a part of the program is -the fuzzing target, it often helps to only instrument the necessary parts of -the program, leaving the rest uninstrumented. This helps to focus the fuzzer -on the important parts of the program, avoiding undesired noise and -disturbance by uninteresting code being exercised. - -For this purpose, I have added a "partial instrumentation" support to the gcc -plugin of AFLFuzz that allows you to specify on a source file level which files -should be compiled with or without instrumentation. - - -## 2) Building the gcc plugin - -The new code is part of the existing afl++ gcc plugin in the gcc_plugin/ -subdirectory. There is nothing specifically to do :) - - -## 3) How to use the partial instrumentation mode - -In order to build with partial instrumentation, you need to build with -afl-gcc-fast and afl-g++-fast respectively. The only required change is -that you need to set the environment variable AFL_GCC_WHITELIST when calling -the compiler. - -The environment variable must point to a file containing all the filenames -that should be instrumented. For matching, the filename that is being compiled -must end in the filename entry contained in this whitelist (to avoid breaking -the matching when absolute paths are used during compilation). - -For example if your source tree looks like this: - -``` -project/ -project/feature_a/a1.cpp -project/feature_a/a2.cpp -project/feature_b/b1.cpp -project/feature_b/b2.cpp -``` - -and you only want to test feature_a, then create a whitelist file containing: - -``` -feature_a/a1.cpp -feature_a/a2.cpp -``` - -However if the whitelist file contains only this, it works as well: - -``` -a1.cpp -a2.cpp -``` - -but it might lead to files being unwantedly instrumented if the same filename -exists somewhere else in the project directories. - -The created whitelist file is then set to AFL_GCC_WHITELIST when you compile -your program. For each file that didn't match the whitelist, the compiler will -issue a warning at the end stating that no blocks were instrumented. If you -didn't intend to instrument that file, then you can safely ignore that warning. diff --git a/gcc_plugin/afl-gcc-fast.c b/gcc_plugin/afl-gcc-fast.c index bd780b40..af0beca7 100644 --- a/gcc_plugin/afl-gcc-fast.c +++ b/gcc_plugin/afl-gcc-fast.c @@ -306,47 +306,47 @@ int main(int argc, char **argv, char **envp) { if (argc < 2 || strcmp(argv[1], "-h") == 0) { - printf( - cCYA - "afl-gcc-fast" VERSION cRST - " initially by , maintainer: hexcoder-\n" - "\n" - "afl-gcc-fast [options]\n" - "\n" - "This is a helper application for afl-fuzz. It serves as a drop-in " - "replacement\n" - "for gcc, letting you recompile third-party code with the required " - "runtime\n" - "instrumentation. A common use pattern would be one of the " - "following:\n\n" - - " CC=%s/afl-gcc-fast ./configure\n" - " CXX=%s/afl-g++-fast ./configure\n\n" - - "In contrast to the traditional afl-gcc tool, this version is " - "implemented as\n" - "a GCC plugin and tends to offer improved performance with slow " - "programs\n" - "(similarly to the LLVM plugin used by afl-clang-fast).\n\n" - - "Environment variables used:\n" - "AFL_CC: path to the C compiler to use\n" - "AFL_CXX: path to the C++ compiler to use\n" - "AFL_PATH: path to instrumenting pass and runtime (afl-gcc-rt.*o)\n" - "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" - "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" - "AFL_INST_RATIO: percentage of branches to instrument\n" - "AFL_QUIET: suppress verbose output\n" - "AFL_DEBUG: enable developer debugging output\n" - "AFL_HARDEN: adds code hardening to catch memory bugs\n" - "AFL_USE_ASAN: activate address sanitizer\n" - "AFL_USE_MSAN: activate memory sanitizer\n" - "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" - "AFL_GCC_WHITELIST: enable whitelisting (selective instrumentation)\n" - - "\nafl-gcc-fast was built for gcc %s with the gcc binary path of " - "\"%s\".\n\n", - BIN_PATH, BIN_PATH, GCC_VERSION, GCC_BINDIR); + printf(cCYA + "afl-gcc-fast" VERSION cRST + " initially by , maintainer: hexcoder-\n" + "\n" + "afl-gcc-fast [options]\n" + "\n" + "This is a helper application for afl-fuzz. It serves as a drop-in " + "replacement\n" + "for gcc, letting you recompile third-party code with the required " + "runtime\n" + "instrumentation. A common use pattern would be one of the " + "following:\n\n" + + " CC=%s/afl-gcc-fast ./configure\n" + " CXX=%s/afl-g++-fast ./configure\n\n" + + "In contrast to the traditional afl-gcc tool, this version is " + "implemented as\n" + "a GCC plugin and tends to offer improved performance with slow " + "programs\n" + "(similarly to the LLVM plugin used by afl-clang-fast).\n\n" + + "Environment variables used:\n" + "AFL_CC: path to the C compiler to use\n" + "AFL_CXX: path to the C++ compiler to use\n" + "AFL_PATH: path to instrumenting pass and runtime (afl-gcc-rt.*o)\n" + "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" + "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" + "AFL_INST_RATIO: percentage of branches to instrument\n" + "AFL_QUIET: suppress verbose output\n" + "AFL_DEBUG: enable developer debugging output\n" + "AFL_HARDEN: adds code hardening to catch memory bugs\n" + "AFL_USE_ASAN: activate address sanitizer\n" + "AFL_USE_MSAN: activate memory sanitizer\n" + "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" + "AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by " + "filename\n" + + "\nafl-gcc-fast was built for gcc %s with the gcc binary path of " + "\"%s\".\n\n", + BIN_PATH, BIN_PATH, GCC_VERSION, GCC_BINDIR); exit(1); @@ -357,12 +357,15 @@ int main(int argc, char **argv, char **envp) { SAYF(cCYA "afl-gcc-fast" VERSION cRST " initially by , maintainer: hexcoder-\n"); - if (getenv("AFL_GCC_WHITELIST") == NULL) { + if (getenv("AFL_GCC_INSTRUMENT_FILE") == NULL && + getenv("AFL_GCC_WHITELIST") == NULL) { - SAYF(cYEL "Warning:" cRST - " using afl-gcc-fast without using AFL_GCC_WHITELIST currently " - "produces worse results than afl-gcc. Even better, use " - "llvm_mode for now.\n"); + SAYF( + cYEL + "Warning:" cRST + " using afl-gcc-fast without using AFL_GCC_INSTRUMENT_FILE currently " + "produces worse results than afl-gcc. Even better, use " + "llvm_mode for now.\n"); } diff --git a/gcc_plugin/afl-gcc-pass.so.cc b/gcc_plugin/afl-gcc-pass.so.cc index 08f7d748..c5614aca 100644 --- a/gcc_plugin/afl-gcc-pass.so.cc +++ b/gcc_plugin/afl-gcc-pass.so.cc @@ -2,7 +2,7 @@ // There are some TODOs in this file: // - fix instrumentation via external call // - fix inline instrumentation -// - implement whitelist feature +// - implement instrument list feature // - dont instrument blocks that are uninteresting // - implement neverZero // @@ -95,7 +95,7 @@ static int be_quiet = 0; static unsigned int inst_ratio = 100; static bool inst_ext = true; -static std::list myWhitelist; +static std::list myInstrumentList; static unsigned int ext_call_instrument(function *fun) { @@ -414,7 +414,7 @@ class afl_pass : public gimple_opt_pass { unsigned int execute(function *fun) override { - if (!myWhitelist.empty()) { + if (!myInstrumentList.empty()) { bool instrumentBlock = false; std::string instFilename; @@ -436,8 +436,8 @@ class afl_pass : public gimple_opt_pass { /* Continue only if we know where we actually are */ if (!instFilename.empty()) { - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { + for (std::list::iterator it = myInstrumentList.begin(); + it != myInstrumentList.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we @@ -462,13 +462,14 @@ class afl_pass : public gimple_opt_pass { } /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ + * not in the instrument list, so we skip instrumentation. */ if (!instrumentBlock) { if (!be_quiet) { if (!instFilename.empty()) - SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s line %u...\n", + SAYF(cYEL "[!] " cBRI + "Not in instrument list, skipping %s line %u...\n", instFilename.c_str(), instLine); else SAYF(cYEL "[!] " cBRI "No filename information found, skipping it"); @@ -562,26 +563,32 @@ int plugin_init(struct plugin_name_args * plugin_info, } - char *instWhiteListFilename = getenv("AFL_GCC_WHITELIST"); - if (instWhiteListFilename) { + char *instInstrumentListFilename = getenv("AFL_GCC_INSTRUMENT_FILE"); + if (!instInstrumentListFilename) + instInstrumentListFilename = getenv("AFL_GCC_WHITELIST"); + if (instInstrumentListFilename) { std::string line; std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) PFATAL("Unable to open AFL_GCC_WHITELIST"); + fileStream.open(instInstrumentListFilename); + if (!fileStream) PFATAL("Unable to open AFL_GCC_INSTRUMENT_FILE"); getline(fileStream, line); while (fileStream) { - myWhitelist.push_back(line); + myInstrumentList.push_back(line); getline(fileStream, line); } - } else if (!be_quiet && getenv("AFL_LLVM_WHITELIST")) + } else if (!be_quiet && (getenv("AFL_LLVM_WHITELIST") || + + getenv("AFL_LLVM_INSTRUMENT_FILE"))) { SAYF(cYEL "[-] " cRST - "AFL_LLVM_WHITELIST environment variable detected - did you mean " - "AFL_GCC_WHITELIST?\n"); + "AFL_LLVM_INSTRUMENT_FILE environment variable detected - did " + "you mean AFL_GCC_INSTRUMENT_FILE?\n"); + + } /* Go go gadget */ register_callback(plugin_info->base_name, PLUGIN_INFO, NULL, diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 4cc55d92..b5d026ef 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -253,7 +253,7 @@ ifeq "$(TEST_MMAP)" "1" LDFLAGS += -Wno-deprecated-declarations endif - PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so + PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-instrumentlist.so ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so # If prerequisites are not given, warn, do not build anything, and exit with code 0 ifeq "$(LLVMVER)" "" @@ -332,7 +332,7 @@ ifeq "$(LLVM_MIN_4_0_1)" "0" endif $(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o -../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc afl-llvm-common.o +../afl-llvm-lto-instrumentlist.so: afl-llvm-lto-instrumentlist.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o endif @@ -403,7 +403,7 @@ all_done: test_build install: all install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi - if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-ld-lto ]; then set -e; install -m 755 ../afl-ld-lto $${DESTDIR}$(BIN_PATH); fi if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 991127a7..75548266 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -74,7 +74,7 @@ struct InsTrim : public ModulePass { InsTrim() : ModulePass(ID), generator(0) { - initWhitelist(); + initInstrumentList(); } @@ -271,7 +271,7 @@ struct InsTrim : public ModulePass { } - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; // if the function below our minimum size skip it (1 or 2) if (F.size() < function_minimum_size) { continue; } diff --git a/llvm_mode/README.instrument_file.md b/llvm_mode/README.instrument_file.md new file mode 100644 index 00000000..347bd3c6 --- /dev/null +++ b/llvm_mode/README.instrument_file.md @@ -0,0 +1,79 @@ +# Using afl++ with partial instrumentation + + This file describes how you can selectively instrument only the source files + that are interesting to you using the LLVM instrumentation provided by + afl++ + + Originally developed by Christian Holler (:decoder) . + +## 1) Description and purpose + +When building and testing complex programs where only a part of the program is +the fuzzing target, it often helps to only instrument the necessary parts of +the program, leaving the rest uninstrumented. This helps to focus the fuzzer +on the important parts of the program, avoiding undesired noise and +disturbance by uninteresting code being exercised. + +For this purpose, I have added a "partial instrumentation" support to the LLVM +mode of AFLFuzz that allows you to specify on a source file level which files +should be compiled with or without instrumentation. + + +## 2) Building the LLVM module + +The new code is part of the existing afl++ LLVM module in the llvm_mode/ +subdirectory. There is nothing specifically to do :) + + +## 3) How to use the partial instrumentation mode + +In order to build with partial instrumentation, you need to build with +afl-clang-fast and afl-clang-fast++ respectively. The only required change is +that you need to set the environment variable AFL_LLVM_INSTRUMENT_FILE when calling +the compiler. + +The environment variable must point to a file containing all the filenames +that should be instrumented. For matching, the filename that is being compiled +must end in the filename entry contained in this the instrument file list (to avoid breaking +the matching when absolute paths are used during compilation). + +For example if your source tree looks like this: + +``` +project/ +project/feature_a/a1.cpp +project/feature_a/a2.cpp +project/feature_b/b1.cpp +project/feature_b/b2.cpp +``` + +and you only want to test feature_a, then create a the instrument file list file containing: + +``` +feature_a/a1.cpp +feature_a/a2.cpp +``` + +However if the the instrument file list file contains only this, it works as well: + +``` +a1.cpp +a2.cpp +``` + +but it might lead to files being unwantedly instrumented if the same filename +exists somewhere else in the project directories. + +The created the instrument file list file is then set to AFL_LLVM_INSTRUMENT_FILE when you compile +your program. For each file that didn't match the the instrument file list, the compiler will +issue a warning at the end stating that no blocks were instrumented. If you +didn't intend to instrument that file, then you can safely ignore that warning. + +For old LLVM versions this feature might require to be compiled with debug +information (-g), however at least from llvm version 6.0 onwards this is not +required anymore (and might hurt performance and crash detection, so better not +use -g). + +## 4) UNIX-style filename pattern matching +You can add UNIX-style pattern matching in the the instrument file list entries. See `man +fnmatch` for the syntax. We do not set any of the `fnmatch` flags. diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 517cb62a..4641fa89 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -7,7 +7,7 @@ This version requires a current llvm 11 compiled from the github master. 1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better coverage than anything else that is out there in the AFL world -2. You can use it together with llvm_mode: laf-intel and whitelisting +2. You can use it together with llvm_mode: laf-intel and the instrument file listing features and can be combined with cmplog/Redqueen 3. It only works with llvm 11 (current github master state) @@ -108,7 +108,7 @@ make install Just use afl-clang-lto like you did with afl-clang-fast or afl-gcc. -Also whitelisting (AFL_LLVM_WHITELIST -> [README.whitelist.md](README.whitelist.md)) and +Also the instrument file listing (AFL_LLVM_INSTRUMENT_FILE -> [README.instrument_file.md](README.instrument_file.md)) and laf-intel/compcov (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work. InsTrim (control flow graph instrumentation) is supported and recommended! (set `AFL_LLVM_INSTRUMENT=CFG`) diff --git a/llvm_mode/README.md b/llvm_mode/README.md index c24aef49..e2e22751 100644 --- a/llvm_mode/README.md +++ b/llvm_mode/README.md @@ -108,8 +108,8 @@ directory. Several options are present to make llvm_mode faster or help it rearrange the code to make afl-fuzz path discovery easier. -If you need just to instrument specific parts of the code, you can whitelist -which C/C++ files to actually instrument. See [README.whitelist](README.whitelist.md) +If you need just to instrument specific parts of the code, you can the instrument file list +which C/C++ files to actually instrument. See [README.instrument_file](README.instrument_file.md) For splitting memcmp, strncmp, etc. please see [README.laf-intel](README.laf-intel.md) diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md deleted file mode 100644 index 6393fae8..00000000 --- a/llvm_mode/README.whitelist.md +++ /dev/null @@ -1,79 +0,0 @@ -# Using afl++ with partial instrumentation - - This file describes how you can selectively instrument only the source files - that are interesting to you using the LLVM instrumentation provided by - afl++ - - Originally developed by Christian Holler (:decoder) . - -## 1) Description and purpose - -When building and testing complex programs where only a part of the program is -the fuzzing target, it often helps to only instrument the necessary parts of -the program, leaving the rest uninstrumented. This helps to focus the fuzzer -on the important parts of the program, avoiding undesired noise and -disturbance by uninteresting code being exercised. - -For this purpose, I have added a "partial instrumentation" support to the LLVM -mode of AFLFuzz that allows you to specify on a source file level which files -should be compiled with or without instrumentation. - - -## 2) Building the LLVM module - -The new code is part of the existing afl++ LLVM module in the llvm_mode/ -subdirectory. There is nothing specifically to do :) - - -## 3) How to use the partial instrumentation mode - -In order to build with partial instrumentation, you need to build with -afl-clang-fast and afl-clang-fast++ respectively. The only required change is -that you need to set the environment variable AFL_LLVM_WHITELIST when calling -the compiler. - -The environment variable must point to a file containing all the filenames -that should be instrumented. For matching, the filename that is being compiled -must end in the filename entry contained in this whitelist (to avoid breaking -the matching when absolute paths are used during compilation). - -For example if your source tree looks like this: - -``` -project/ -project/feature_a/a1.cpp -project/feature_a/a2.cpp -project/feature_b/b1.cpp -project/feature_b/b2.cpp -``` - -and you only want to test feature_a, then create a whitelist file containing: - -``` -feature_a/a1.cpp -feature_a/a2.cpp -``` - -However if the whitelist file contains only this, it works as well: - -``` -a1.cpp -a2.cpp -``` - -but it might lead to files being unwantedly instrumented if the same filename -exists somewhere else in the project directories. - -The created whitelist file is then set to AFL_LLVM_WHITELIST when you compile -your program. For each file that didn't match the whitelist, the compiler will -issue a warning at the end stating that no blocks were instrumented. If you -didn't intend to instrument that file, then you can safely ignore that warning. - -For old LLVM versions this feature might require to be compiled with debug -information (-g), however at least from llvm version 6.0 onwards this is not -required anymore (and might hurt performance and crash detection, so better not -use -g). - -## 4) UNIX-style filename pattern matching -You can add UNIX-style pattern matching in the whitelist entries. See `man -fnmatch` for the syntax. We do not set any of the `fnmatch` flags. diff --git a/llvm_mode/TODO b/llvm_mode/TODO deleted file mode 100644 index 2729d688..00000000 --- a/llvm_mode/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO for afl-ld: -* handle libfoo.a object archives - -TODO for afl-llvm-lto-instrumentation: -* better algo for putting stuff in the map? -* try to predict how long the instrumentation process will take - -TODO for afl-llvm-lto-whitelist -* different solution then renaming? - diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 3b0225c2..f1b03682 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -227,13 +227,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode) { - if (getenv("AFL_LLVM_WHITELIST") != NULL) { + if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL || + getenv("AFL_LLVM_WHITELIST")) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-lto-whitelist.so", obj_path); + alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path); } @@ -762,7 +763,7 @@ int main(int argc, char **argv, char **envp) { #if LLVM_VERSION_MAJOR <= 6 instrument_mode = INSTRUMENT_AFL; #else - if (getenv("AFL_LLVM_WHITELIST")) + if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) instrument_mode = INSTRUMENT_AFL; else instrument_mode = INSTRUMENT_PCGUARD; @@ -810,8 +811,11 @@ int main(int argc, char **argv, char **envp) { "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " "together"); - if (instrument_mode == INSTRUMENT_PCGUARD && getenv("AFL_LLVM_WHITELIST")) - WARNF("Instrumentation type PCGUARD does not support AFL_LLVM_WHITELIST!"); + if (instrument_mode == INSTRUMENT_PCGUARD && + (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST"))) + WARNF( + "Instrumentation type PCGUARD does not support " + "AFL_LLVM_INSTRUMENT_FILE!"); if (argc < 2 || strcmp(argv[1], "-h") == 0) { @@ -861,7 +865,8 @@ int main(int argc, char **argv, char **envp) { "AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison " "function calls\n" "AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" - "AFL_LLVM_WHITELIST: enable whitelisting (selective " + "AFL_LLVM_INSTRUMENT_FILE: enable the instrument file listing " + "(selective " "instrumentation)\n" "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" "AFL_PATH: path to instrumenting pass and runtime " diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 5a75c4dd..47b49358 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -18,7 +18,7 @@ using namespace llvm; -static std::list myWhitelist; +static std::list myInstrumentList; char *getBBName(const llvm::BasicBlock *BB) { @@ -44,7 +44,7 @@ char *getBBName(const llvm::BasicBlock *BB) { } /* Function that we never instrument or analyze */ -/* Note: this ignore check is also called in isInWhitelist() */ +/* Note: this ignore check is also called in isInInstrumentList() */ bool isIgnoreFunction(const llvm::Function *F) { // Starting from "LLVMFuzzer" these are functions used in libfuzzer based @@ -83,19 +83,22 @@ bool isIgnoreFunction(const llvm::Function *F) { } -void initWhitelist() { +void initInstrumentList() { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { + char *instrumentListFilename = getenv("AFL_LLVM_INSTRUMENT_FILE"); + if (!instrumentListFilename) + instrumentListFilename = getenv("AFL_LLVM_WHITELIST"); + if (instrumentListFilename) { std::string line; std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); + fileStream.open(instrumentListFilename); + if (!fileStream) + report_fatal_error("Unable to open AFL_LLVM_INSTRUMENT_FILE"); getline(fileStream, line); while (fileStream) { - myWhitelist.push_back(line); + myInstrumentList.push_back(line); getline(fileStream, line); } @@ -104,14 +107,14 @@ void initWhitelist() { } -bool isInWhitelist(llvm::Function *F) { +bool isInInstrumentList(llvm::Function *F) { // is this a function with code? If it is external we dont instrument it - // anyway and cant be in the whitelist. Or if it is ignored. + // anyway and cant be in the the instrument file list. Or if it is ignored. if (!F->size() || isIgnoreFunction(F)) return false; - // if we do not have a whitelist return true - if (myWhitelist.empty()) return true; + // if we do not have a the instrument file list return true + if (myInstrumentList.empty()) return true; // let's try to get the filename for the function auto bb = &F->getEntryBlock(); @@ -147,8 +150,8 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { + for (std::list::iterator it = myInstrumentList.begin(); + it != myInstrumentList.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we @@ -185,8 +188,8 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { + for (std::list::iterator it = myInstrumentList.begin(); + it != myInstrumentList.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we @@ -215,7 +218,7 @@ bool isInWhitelist(llvm::Function *F) { else { // we could not find out the location. in this case we say it is not - // in the whitelist + // in the the instrument file list return false; diff --git a/llvm_mode/afl-llvm-common.h b/llvm_mode/afl-llvm-common.h index db009f8f..38e0c830 100644 --- a/llvm_mode/afl-llvm-common.h +++ b/llvm_mode/afl-llvm-common.h @@ -34,8 +34,8 @@ typedef long double max_align_t; char * getBBName(const llvm::BasicBlock *BB); bool isIgnoreFunction(const llvm::Function *F); -void initWhitelist(); -bool isInWhitelist(llvm::Function *F); +void initInstrumentList(); +bool isInInstrumentList(llvm::Function *F); unsigned long long int calculateCollisions(uint32_t edges); #endif diff --git a/llvm_mode/afl-llvm-lto-instrim.so.cc b/llvm_mode/afl-llvm-lto-instrim.so.cc index b62912a6..ca2b5886 100644 --- a/llvm_mode/afl-llvm-lto-instrim.so.cc +++ b/llvm_mode/afl-llvm-lto-instrim.so.cc @@ -566,12 +566,13 @@ struct InsTrimLTO : public ModulePass { functions++; - // whitelist check + // the instrument file list check AttributeList Attrs = F.getAttributes(); if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) { if (debug) - fprintf(stderr, "DEBUG: Function %s is not whitelisted\n", + fprintf(stderr, + "DEBUG: Function %s is not the instrument file listed\n", F.getName().str().c_str()); continue; diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 82af890c..af2db3ff 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -198,12 +198,13 @@ bool AFLLTOPass::runOnModule(Module &M) { if (F.size() < function_minimum_size) continue; if (isIgnoreFunction(&F)) continue; - // whitelist check + // the instrument file list check AttributeList Attrs = F.getAttributes(); if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) { if (debug) - fprintf(stderr, "DEBUG: Function %s is not whitelisted\n", + fprintf(stderr, + "DEBUG: Function %s is not the instrument file listed\n", F.getName().str().c_str()); continue; diff --git a/llvm_mode/afl-llvm-lto-instrumentlist.so.cc b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc new file mode 100644 index 00000000..6e6199e9 --- /dev/null +++ b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc @@ -0,0 +1,253 @@ +/* + american fuzzy lop++ - LLVM-mode instrumentation pass + --------------------------------------------------- + + Written by Laszlo Szekeres and + Michal Zalewski + + LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted + from afl-as.c are Michal's fault. + + Copyright 2015, 2016 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This library is plugged into LLVM when invoking clang through afl-clang-fast. + It tells the compiler to add code roughly equivalent to the bits discussed + in ../afl-as.h. + + */ + +#define AFL_LLVM_PASS + +#include "config.h" +#include "debug.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/IR/CFG.h" + +#include "afl-llvm-common.h" + +using namespace llvm; + +namespace { + +class AFLcheckIfInstrument : public ModulePass { + + public: + static char ID; + AFLcheckIfInstrument() : ModulePass(ID) { + + int entries = 0; + + if (getenv("AFL_DEBUG")) debug = 1; + + char *instrumentListFilename = getenv("AFL_LLVM_INSTRUMENT_FILE"); + if (!instrumentListFilename) + instrumentListFilename = getenv("AFL_LLVM_WHITELIST"); + if (instrumentListFilename) { + + std::string line; + std::ifstream fileStream; + fileStream.open(instrumentListFilename); + if (!fileStream) + report_fatal_error("Unable to open AFL_LLVM_INSTRUMENT_FILE"); + getline(fileStream, line); + while (fileStream) { + + myInstrumentList.push_back(line); + getline(fileStream, line); + entries++; + + } + + } else + + PFATAL( + "afl-llvm-lto-instrumentlist.so loaded without " + "AFL_LLVM_INSTRUMENT_FILE?!"); + + if (debug) + SAYF(cMGN "[D] " cRST + "loaded the instrument file list %s with %d entries\n", + instrumentListFilename, entries); + + } + + bool runOnModule(Module &M) override; + + // StringRef getPassName() const override { + + // return "American Fuzzy Lop Instrumentation"; + // } + + protected: + std::list myInstrumentList; + int debug = 0; + +}; + +} // namespace + +char AFLcheckIfInstrument::ID = 0; + +bool AFLcheckIfInstrument::runOnModule(Module &M) { + + /* Show a banner */ + + char be_quiet = 0; + setvbuf(stdout, NULL, _IONBF, 0); + + if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { + + SAYF(cCYA "afl-llvm-lto-instrumentlist" VERSION cRST + " by Marc \"vanHauser\" Heuse \n"); + + } else if (getenv("AFL_QUIET")) + + be_quiet = 1; + + for (auto &F : M) { + + if (F.size() < 1) continue; + // fprintf(stderr, "F:%s\n", F.getName().str().c_str()); + if (isIgnoreFunction(&F)) continue; + + BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); + + if (!myInstrumentList.empty()) { + + bool instrumentFunction = false; + + /* Get the current location using debug information. + * For now, just instrument the block if we are not able + * to determine our location. */ + DebugLoc Loc = IP->getDebugLoc(); + if (Loc) { + + DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); + + unsigned int instLine = cDILoc->getLine(); + StringRef instFilename = cDILoc->getFilename(); + + if (instFilename.str().empty()) { + + /* If the original location is empty, try using the inlined location + */ + DILocation *oDILoc = cDILoc->getInlinedAt(); + if (oDILoc) { + + instFilename = oDILoc->getFilename(); + instLine = oDILoc->getLine(); + + } + + } + + (void)instLine; + + if (debug) + SAYF(cMGN "[D] " cRST "function %s is in file %s\n", + F.getName().str().c_str(), instFilename.str().c_str()); + /* Continue only if we know where we actually are */ + if (!instFilename.str().empty()) { + + for (std::list::iterator it = myInstrumentList.begin(); + it != myInstrumentList.end(); ++it) { + + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. */ + if (instFilename.str().length() >= it->length()) { + + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { + + instrumentFunction = true; + break; + + } + + } + + } + + } + + } + + /* Either we couldn't figure out our location or the location is + * not the instrument file listed, so we skip instrumentation. + * We do this by renaming the function. */ + if (instrumentFunction == true) { + + if (debug) + SAYF(cMGN "[D] " cRST "function %s is in the instrument file list\n", + F.getName().str().c_str()); + + } else { + + if (debug) + SAYF(cMGN "[D] " cRST + "function %s is NOT in the instrument file list\n", + F.getName().str().c_str()); + + auto & Ctx = F.getContext(); + AttributeList Attrs = F.getAttributes(); + AttrBuilder NewAttrs; + NewAttrs.addAttribute("skipinstrument"); + F.setAttributes( + Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); + + } + + } else { + + PFATAL("InstrumentList is empty"); + + } + + } + + return true; + +} + +static void registerAFLcheckIfInstrumentpass(const PassManagerBuilder &, + legacy::PassManagerBase &PM) { + + PM.add(new AFLcheckIfInstrument()); + +} + +static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass( + PassManagerBuilder::EP_ModuleOptimizerEarly, + registerAFLcheckIfInstrumentpass); + +static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass0( + PassManagerBuilder::EP_EnabledOnOptLevel0, + registerAFLcheckIfInstrumentpass); + diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc deleted file mode 100644 index 52c7cf0d..00000000 --- a/llvm_mode/afl-llvm-lto-whitelist.so.cc +++ /dev/null @@ -1,244 +0,0 @@ -/* - american fuzzy lop++ - LLVM-mode instrumentation pass - --------------------------------------------------- - - Written by Laszlo Szekeres and - Michal Zalewski - - LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted - from afl-as.c are Michal's fault. - - Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This library is plugged into LLVM when invoking clang through afl-clang-fast. - It tells the compiler to add code roughly equivalent to the bits discussed - in ../afl-as.h. - - */ - -#define AFL_LLVM_PASS - -#include "config.h" -#include "debug.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Debug.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" -#include "llvm/IR/CFG.h" - -#include "afl-llvm-common.h" - -using namespace llvm; - -namespace { - -class AFLwhitelist : public ModulePass { - - public: - static char ID; - AFLwhitelist() : ModulePass(ID) { - - int entries = 0; - - if (getenv("AFL_DEBUG")) debug = 1; - - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - entries++; - - } - - } else - - PFATAL("afl-llvm-lto-whitelist.so loaded without AFL_LLVM_WHITELIST?!"); - - if (debug) - SAYF(cMGN "[D] " cRST "loaded whitelist %s with %d entries\n", - instWhiteListFilename, entries); - - } - - bool runOnModule(Module &M) override; - - // StringRef getPassName() const override { - - // return "American Fuzzy Lop Instrumentation"; - // } - - protected: - std::list myWhitelist; - int debug = 0; - -}; - -} // namespace - -char AFLwhitelist::ID = 0; - -bool AFLwhitelist::runOnModule(Module &M) { - - /* Show a banner */ - - char be_quiet = 0; - setvbuf(stdout, NULL, _IONBF, 0); - - if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) { - - SAYF(cCYA "afl-llvm-lto-whitelist" VERSION cRST - " by Marc \"vanHauser\" Heuse \n"); - - } else if (getenv("AFL_QUIET")) - - be_quiet = 1; - - for (auto &F : M) { - - if (F.size() < 1) continue; - // fprintf(stderr, "F:%s\n", F.getName().str().c_str()); - if (isIgnoreFunction(&F)) continue; - - BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - - if (!myWhitelist.empty()) { - - bool instrumentFunction = false; - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - if (debug) - SAYF(cMGN "[D] " cRST "function %s is in file %s\n", - F.getName().str().c_str(), instFilename.str().c_str()); - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == - 0) { - - instrumentFunction = true; - break; - - } - - } - - } - - } - - } - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. - * We do this by renaming the function. */ - if (instrumentFunction == true) { - - if (debug) - SAYF(cMGN "[D] " cRST "function %s is in whitelist\n", - F.getName().str().c_str()); - - } else { - - if (debug) - SAYF(cMGN "[D] " cRST "function %s is NOT in whitelist\n", - F.getName().str().c_str()); - - auto & Ctx = F.getContext(); - AttributeList Attrs = F.getAttributes(); - AttrBuilder NewAttrs; - NewAttrs.addAttribute("skipinstrument"); - F.setAttributes( - Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); - - } - - } else { - - PFATAL("Whitelist is empty"); - - } - - } - - return true; - -} - -static void registerAFLwhitelistpass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { - - PM.add(new AFLwhitelist()); - -} - -static RegisterStandardPasses RegisterAFLwhitelistpass( - PassManagerBuilder::EP_ModuleOptimizerEarly, registerAFLwhitelistpass); - -static RegisterStandardPasses RegisterAFLwhitelistpass0( - PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLwhitelistpass); - diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 7997df51..90cf3eb4 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -74,7 +74,7 @@ class AFLCoverage : public ModulePass { static char ID; AFLCoverage() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -307,7 +307,7 @@ bool AFLCoverage::runOnModule(Module &M) { fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), F.size()); - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; if (F.size() < function_minimum_size) continue; diff --git a/llvm_mode/cmplog-instructions-pass.cc b/llvm_mode/cmplog-instructions-pass.cc index c5a6ff8b..f929361a 100644 --- a/llvm_mode/cmplog-instructions-pass.cc +++ b/llvm_mode/cmplog-instructions-pass.cc @@ -59,7 +59,7 @@ class CmpLogInstructions : public ModulePass { static char ID; CmpLogInstructions() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -170,7 +170,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; for (auto &BB : F) { diff --git a/llvm_mode/cmplog-routines-pass.cc b/llvm_mode/cmplog-routines-pass.cc index 792a45b9..318193a4 100644 --- a/llvm_mode/cmplog-routines-pass.cc +++ b/llvm_mode/cmplog-routines-pass.cc @@ -59,7 +59,7 @@ class CmpLogRoutines : public ModulePass { static char ID; CmpLogRoutines() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -118,7 +118,7 @@ bool CmpLogRoutines::hookRtns(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; for (auto &BB : F) { diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index 96abeebb..2d1ab1cc 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -58,7 +58,7 @@ class CompareTransform : public ModulePass { static char ID; CompareTransform() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -124,7 +124,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, * strcmp/memcmp/strncmp/strcasecmp/strncasecmp */ for (auto &F : M) { - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; for (auto &BB : F) { diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index 2c4ed71c..651fa5b4 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -55,7 +55,7 @@ class SplitComparesTransform : public ModulePass { static char ID; SplitComparesTransform() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -102,7 +102,7 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { * all integer comparisons with >= and <= predicates to the icomps vector */ for (auto &F : M) { - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; for (auto &BB : F) { diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc index 4a6ca3d9..44075c94 100644 --- a/llvm_mode/split-switches-pass.so.cc +++ b/llvm_mode/split-switches-pass.so.cc @@ -60,7 +60,7 @@ class SplitSwitchesTransform : public ModulePass { static char ID; SplitSwitchesTransform() : ModulePass(ID) { - initWhitelist(); + initInstrumentList(); } @@ -312,7 +312,7 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { * all switches to switches vector for later processing */ for (auto &F : M) { - if (!isInWhitelist(&F)) continue; + if (!isInInstrumentList(&F)) continue; for (auto &BB : F) { diff --git a/src/afl-common.c b/src/afl-common.c index 79d419cd..8995b57e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -58,7 +58,7 @@ char *afl_environment_variables[] = { //"AFL_DEFER_FORKSRV", // not implemented anymore, so warn additionally "AFL_DISABLE_TRIM", "AFL_DONT_OPTIMIZE", "AFL_DUMB_FORKSRV", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", "AFL_FAST_CAL", "AFL_FORCE_UI", - "AFL_GCC_WHITELIST", "AFL_GCJ", "AFL_HANG_TMOUT", "AFL_HARDEN", + "AFL_GCC_INSTRUMENT_FILE", "AFL_GCJ", "AFL_HANG_TMOUT", "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", "AFL_KEEP_TRACES", "AFL_KEEP_ASSEMBLY", "AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", @@ -71,7 +71,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f25f8bb6..7580caad 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -790,8 +790,8 @@ int main(int argc, char **argv_orig, char **envp) { OKF("afl++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); OKF("Power schedules from github.com/mboehme/aflfast"); - OKF("Python Mutator and llvm_mode whitelisting from github.com/choller/afl"); - OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL"); + OKF("Python Mutator and llvm_mode instrument file list from " + "github.com/choller/afl"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->is_main_node && diff --git a/test/test-performance.sh b/test/test-performance.sh index 87eea665..cee46060 100755 --- a/test/test-performance.sh +++ b/test/test-performance.sh @@ -21,8 +21,8 @@ unset AFL_USE_ASAN unset AFL_USE_MSAN unset AFL_CC unset AFL_PRELOAD -unset AFL_GCC_WHITELIST -unset AFL_LLVM_WHITELIST +unset AFL_GCC_INSTRUMENT_FILE +unset AFL_LLVM_INSTRUMENT_FILE unset AFL_LLVM_INSTRIM unset AFL_LLVM_LAF_SPLIT_SWITCHES unset AFL_LLVM_LAF_TRANSFORM_COMPARES diff --git a/test/test.sh b/test/test.sh index a7d9fc49..90920215 100755 --- a/test/test.sh +++ b/test/test.sh @@ -62,8 +62,8 @@ unset AFL_USE_UBSAN unset AFL_TMPDIR unset AFL_CC unset AFL_PRELOAD -unset AFL_GCC_WHITELIST -unset AFL_LLVM_WHITELIST +unset AFL_GCC_INSTRUMENT_FILE +unset AFL_LLVM_INSTRUMENT_FILE unset AFL_LLVM_INSTRIM unset AFL_LLVM_LAF_SPLIT_SWITCHES unset AFL_LLVM_LAF_TRANSFORM_COMPARES @@ -386,20 +386,20 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 } rm -f test-compcov.compcov test.out - echo foobar.c > whitelist.txt - AFL_DEBUG=1 AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1 + echo foobar.c > instrumentlist.txt + AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1 test -e test-compcov && test_compcov_binary_functionality ./test-compcov && { grep -q "No instrumentation targets found" test.out && { - $ECHO "$GREEN[+] llvm_mode whitelist feature works correctly" + $ECHO "$GREEN[+] llvm_mode instrumentlist feature works correctly" } || { - $ECHO "$RED[!] llvm_mode whitelist feature failed" + $ECHO "$RED[!] llvm_mode instrumentlist feature failed" CODE=1 } } || { - $ECHO "$RED[!] llvm_mode whitelist feature compilation failed" + $ECHO "$RED[!] llvm_mode instrumentlist feature compilation failed" CODE=1 } - rm -f test-compcov test.out whitelist.txt + rm -f test-compcov test.out instrumentlist.txt ../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { @@ -459,20 +459,20 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { } rm -f test-instr.plain - echo foobar.c > whitelist.txt - AFL_DEBUG=1 AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-lto -o test-compcov test-compcov.c > test.out 2>&1 + echo foobar.c > instrumentlist.txt + AFL_DEBUG=1 AFL_LLVM_INSTRUMENT_FILE=instrumentlist.txt ../afl-clang-lto -o test-compcov test-compcov.c > test.out 2>&1 test -e test-compcov && { grep -q "No instrumentation targets found" test.out && { - $ECHO "$GREEN[+] llvm_mode LTO whitelist feature works correctly" + $ECHO "$GREEN[+] llvm_mode LTO instrumentlist feature works correctly" } || { - $ECHO "$RED[!] llvm_mode LTO whitelist feature failed" + $ECHO "$RED[!] llvm_mode LTO instrumentlist feature failed" CODE=1 } } || { - $ECHO "$RED[!] llvm_mode LTO whitelist feature compilation failed" + $ECHO "$RED[!] llvm_mode LTO instrumentlist feature compilation failed" CODE=1 } - rm -f test-compcov test.out whitelist.txt + rm -f test-compcov test.out instrumentlist.txt ../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && { @@ -569,20 +569,20 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { rm -f test-instr.plain.gccpi # now for the special gcc_plugin things - echo foobar.c > whitelist.txt - AFL_GCC_WHITELIST=whitelist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1 + echo foobar.c > instrumentlist.txt + AFL_GCC_INSTRUMENT_FILE=instrumentlist.txt ../afl-gcc-fast -o test-compcov test-compcov.c > /dev/null 2>&1 test -e test-compcov && test_compcov_binary_functionality ./test-compcov && { echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && { - $ECHO "$GREEN[+] gcc_plugin whitelist feature works correctly" + $ECHO "$GREEN[+] gcc_plugin instrumentlist feature works correctly" } || { - $ECHO "$RED[!] gcc_plugin whitelist feature failed" + $ECHO "$RED[!] gcc_plugin instrumentlist feature failed" CODE=1 } } || { - $ECHO "$RED[!] gcc_plugin whitelist feature compilation failed" + $ECHO "$RED[!] gcc_plugin instrumentlist feature compilation failed" CODE=1 } - rm -f test-compcov test.out whitelist.txt + rm -f test-compcov test.out instrumentlist.txt ../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 test -e test-persistent && { echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && { -- cgit 1.4.1 From 7527c76c7446f8197b9f7acb8ca0ccd44fe7bd39 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 30 Jun 2020 17:33:47 +0200 Subject: reduce the time interval in which the secondaries sync --- include/config.h | 2 +- src/afl-fuzz.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index 087e0a76..5ee93389 100644 --- a/include/config.h +++ b/include/config.h @@ -234,7 +234,7 @@ /* Sync interval (every n havoc cycles): */ -#define SYNC_INTERVAL 5 +#define SYNC_INTERVAL 8 /* Output directory reuse grace period (minutes): */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7580caad..e4e2669c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1280,7 +1280,7 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->is_main_node)) { - if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 2))) { sync_fuzzers(afl); } + if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { sync_fuzzers(afl); } } else { -- cgit 1.4.1 From be83f06b2f3e575716974c4bd4b0d79a68ab6441 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:25:33 +0200 Subject: renaming remains fixed --- docs/Changelog.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 6718ecde..eede6751 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -34,18 +34,18 @@ sending a mail to . - the default instrumentation is now PCGUARD if the llvm version is >= 7, as it is faster and provides better coverage. The original afl instrumentation can be set via AFL_LLVM_INSTRUMENT=AFL. This is - automatically done when the WHITELIST feature is used. + automatically done when the instrument_file list feature is used. - PCGUARD mode is now even better because we made it collision free - plus it has a fixed map size, so it is also faster! :) - some targets want a ld variant for LD that is not gcc/clang but ld, added afl-ld-lto to solve this - lowered minimum required llvm version to 3.4 (except LLVMInsTrim, which needs 3.8.0) - - WHITELIST feature now supports wildcards (thanks to sirmc) + - instrument_file list feature now supports wildcards (thanks to sirmc) - small change to cmplog to make it work with current llvm 11-dev - added AFL_LLVM_LAF_ALL, sets all laf-intel settings - LTO instrument_files functionality rewritten, now main, _init etc functions - need not to be instrument_filesed anymore + need not to be listed anymore - fixed crash in compare-transform-pass when strcasecmp/strncasecmp was tried to be instrumented with LTO - fixed crash in cmplog with LTO @@ -253,7 +253,7 @@ sending a mail to . the original script is still present as afl-cmin.bash - afl-showmap: -i dir option now allows processing multiple inputs using the forkserver. This is for enhanced speed in afl-cmin. - - added blacklist and instrument_filesing function check in all modules of llvm_mode + - added ignore and instrument_file list function check in all modules of llvm_mode - added fix from Debian project to compile libdislocator and libtokencap - libdislocator: AFL_ALIGNED_ALLOC to force size alignment to max_align_t @@ -308,7 +308,7 @@ sending a mail to . performance loss of ~10% - added test/test-performance.sh script - (re)added gcc_plugin, fast inline instrumentation is not yet finished, - however it includes the instrument_filesing and persistance feature! by hexcoder- + however it includes the instrument_files listing and persistance feature! by hexcoder- - gcc_plugin tests added to testing framework @@ -396,7 +396,7 @@ sending a mail to . - more cpu power for afl-system-config - added forkserver patch to afl-tmin, makes it much faster (originally from github.com/nccgroup/TriforceAFL) - - added instrument_files support for llvm_mode via AFL_LLVM_WHITELIST to allow + - added instrument_files support for llvm_mode via AFL_LLVM_INSTRUMENT_FILE to allow only to instrument what is actually interesting. Gives more speed and less map pollution (originally by choller@mozilla) - added Python Module mutator support, python2.7-dev is autodetected. -- cgit 1.4.1 From b201279ae5e4066ffa7f11d58f0efd73938aa8dd Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:27:53 +0200 Subject: text fix --- docs/perf_tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/perf_tips.md b/docs/perf_tips.md index 7a690b77..46a45001 100644 --- a/docs/perf_tips.md +++ b/docs/perf_tips.md @@ -66,7 +66,7 @@ then using laf-intel (see llvm_mode/README.laf-intel.md) will help `afl-fuzz` a to get to the important parts in the code. If you are only interested in specific parts of the code being fuzzed, you can -instrument_files the files that are actually relevant. This improves the speed and +list the files that are actually relevant. This improves the speed and accuracy of afl. See llvm_mode/README.instrument_file.md Also use the InsTrim mode on larger binaries, this improves performance and -- cgit 1.4.1 From e9dce3149606877883df01cc66f99da0addf79ee Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:35:42 +0200 Subject: comments fixed --- llvm_mode/afl-llvm-common.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 47b49358..d70ccaeb 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -110,10 +110,10 @@ void initInstrumentList() { bool isInInstrumentList(llvm::Function *F) { // is this a function with code? If it is external we dont instrument it - // anyway and cant be in the the instrument file list. Or if it is ignored. + // anyway and cant be in the instrument file list. Or if it is ignored. if (!F->size() || isIgnoreFunction(F)) return false; - // if we do not have a the instrument file list return true + // if we do not have any instrument file list entries return true if (myInstrumentList.empty()) return true; // let's try to get the filename for the function @@ -218,7 +218,7 @@ bool isInInstrumentList(llvm::Function *F) { else { // we could not find out the location. in this case we say it is not - // in the the instrument file list + // in the instrument file list return false; -- cgit 1.4.1 From 2aaa60e4fc45bac022f7170ccfb57d63bf23569d Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:39:55 +0200 Subject: comments fix --- llvm_mode/afl-llvm-lto-instrumentlist.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_mode/afl-llvm-lto-instrumentlist.so.cc b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc index 6e6199e9..96c30fcb 100644 --- a/llvm_mode/afl-llvm-lto-instrumentlist.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentlist.so.cc @@ -200,7 +200,7 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) { } /* Either we couldn't figure out our location or the location is - * not the instrument file listed, so we skip instrumentation. + * not listed in the instrument file list, so we skip instrumentation. * We do this by renaming the function. */ if (instrumentFunction == true) { -- cgit 1.4.1 From d8984180377fb244d43990feb7cda2d212924ab3 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:43:14 +0200 Subject: restore credit for afl-tmin fork server patch --- src/afl-fuzz.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e4e2669c..15a68096 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -792,6 +792,7 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Power schedules from github.com/mboehme/aflfast"); OKF("Python Mutator and llvm_mode instrument file list from " "github.com/choller/afl"); + OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->is_main_node && -- cgit 1.4.1 From 52a0410d926bff61e2c4a854713c2cd29d3b67b1 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:49:07 +0200 Subject: fix text --- llvm_mode/README.instrument_file.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm_mode/README.instrument_file.md b/llvm_mode/README.instrument_file.md index 347bd3c6..a27eacc6 100644 --- a/llvm_mode/README.instrument_file.md +++ b/llvm_mode/README.instrument_file.md @@ -47,14 +47,14 @@ project/feature_b/b1.cpp project/feature_b/b2.cpp ``` -and you only want to test feature_a, then create a the instrument file list file containing: +and you only want to test feature_a, then create a instrument file list file containing: ``` feature_a/a1.cpp feature_a/a2.cpp ``` -However if the the instrument file list file contains only this, it works as well: +However if the instrument file list file contains only this, it works as well: ``` a1.cpp @@ -64,8 +64,8 @@ a2.cpp but it might lead to files being unwantedly instrumented if the same filename exists somewhere else in the project directories. -The created the instrument file list file is then set to AFL_LLVM_INSTRUMENT_FILE when you compile -your program. For each file that didn't match the the instrument file list, the compiler will +The created instrument file list file is then set to AFL_LLVM_INSTRUMENT_FILE when you compile +your program. For each file that didn't match the instrument file list, the compiler will issue a warning at the end stating that no blocks were instrumented. If you didn't intend to instrument that file, then you can safely ignore that warning. @@ -75,5 +75,5 @@ required anymore (and might hurt performance and crash detection, so better not use -g). ## 4) UNIX-style filename pattern matching -You can add UNIX-style pattern matching in the the instrument file list entries. See `man +You can add UNIX-style pattern matching in the instrument file list entries. See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags. -- cgit 1.4.1 From 4d2ccd18f6434a06b80857c4ee5fa6c6e1ae502c Mon Sep 17 00:00:00 2001 From: hexcoder Date: Wed, 1 Jul 2020 07:55:58 +0200 Subject: comments fix --- src/afl-fuzz-redqueen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 44953a52..724da407 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -435,7 +435,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { u32 fails; u8 found_one = 0; - /* loop cmps are useless, detect and ignores them */ + /* loop cmps are useless, detect and ignore them */ u64 s_v0, s_v1; u8 s_v0_fixed = 1, s_v1_fixed = 1; u8 s_v0_inc = 1, s_v1_inc = 1; @@ -743,7 +743,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, afl->pass_stats[k].faileds || afl->pass_stats[k].total == 0xff)) { - afl->shm.cmp_map->headers[k].hits = 0; // ignores this cmp + afl->shm.cmp_map->headers[k].hits = 0; // ignore this cmp } -- cgit 1.4.1 From 6b98157c1a235c10ed5f9fc3220aa1869ea8f3e4 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 1 Jul 2020 09:15:47 +0200 Subject: v2.66c release preparation --- README.md | 4 ++-- TODO.md | 2 +- docs/Changelog.md | 2 +- include/config.h | 2 +- src/afl-fuzz.c | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index dd32e28e..14a42b7e 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ ![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=stable) - Release Version: [2.65c](https://github.com/AFLplusplus/AFLplusplus/releases) + Release Version: [2.66c](https://github.com/AFLplusplus/AFLplusplus/releases) - Github Version: 2.65d + Github Version: 2.66d includes all necessary/interesting changes from Google's afl 2.56b diff --git a/TODO.md b/TODO.md index 55b886e4..8085bc07 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ # TODO list for AFL++ -## Roadmap 2.65+ +## Roadmap 2.66+ - AFL_MAP_SIZE for qemu_mode and unicorn_mode - namespace for targets? e.g. network diff --git a/docs/Changelog.md b/docs/Changelog.md index eede6751..1bf77839 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++2.65d (dev) +### Version ++2.66c (release) - renamed the main branch on Github to "stable" - renamed master/slave to main/secondary - renamed blacklist/whitelist to ignorelist/instrumentlist -> diff --git a/include/config.h b/include/config.h index 5ee93389..e8f52f45 100644 --- a/include/config.h +++ b/include/config.h @@ -28,7 +28,7 @@ /* Version string: */ // c = release, d = volatile github dev, e = experimental branch -#define VERSION "++2.65d" +#define VERSION "++2.66c" /****************************************************** * * diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 15a68096..e4e2669c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -792,7 +792,6 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Power schedules from github.com/mboehme/aflfast"); OKF("Python Mutator and llvm_mode instrument file list from " "github.com/choller/afl"); - OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->is_main_node && -- cgit 1.4.1