update mutation strategy

This commit is contained in:
vanhauser-thc
2023-06-29 16:57:20 +02:00
parent 15fc47a62c
commit 3e1d794107
5 changed files with 95 additions and 66 deletions

View File

@ -8,7 +8,8 @@
- new mutation engine: mutations that favor discovery more paths are
prefered until no new finds for 10 minutes then switching to mutations
that favor triggering crashes. Modes and switch time can be configured
with `-P`.
with `-P`. Also input mode for the target can be defined with `-a` to
be `text` or `binary` (defaults to `generic`)
- new custom mutator that has the new afl++ engine (so it can easily
incorporated into new custom mutators), and also comes with a standalone
command line tool! See custom_mutators/aflpp/standalone/
@ -23,6 +24,7 @@
Thanks to @amykweon for spotting and fixing!
- @toka fixed a bug in laf-intel signed integer comparison splitting,
thanks a lot!!
- more LLVM compatability
- frida_mode:
- support for long form instrumentation on x86_x64 and arm64

View File

@ -505,36 +505,37 @@ typedef struct afl_state {
is_main_node, /* if this is the main node */
is_secondary_node, /* if this is a secondary instance */
pizza_is_served, /* pizza mode */
text_input, /* target wants text inputs */
fuzz_mode, /* current mode: coverage/exploration or crash/exploitation */
input_mode, /* target wants text inputs */
fuzz_mode, /* coverage/exploration or crash/exploitation mode */
schedule, /* Power schedule (default: EXPLORE)*/
havoc_max_mult, skip_deterministic, /* Skip deterministic stages? */
use_splicing, /* Recombine input files? */
non_instrumented_mode, /* Run in non-instrumented mode? */
score_changed, /* Scoring for favorites changed? */
resuming_fuzz, /* Resuming an older fuzzing job? */
timeout_given, /* Specific timeout given? */
not_on_tty, /* stdout is not a tty */
term_too_small, /* terminal dimensions too small */
no_forkserver, /* Disable forkserver? */
crash_mode, /* Crash mode! Yeah! */
in_place_resume, /* Attempt in-place resume? */
autoresume, /* Resume if afl->out_dir exists? */
auto_changed, /* Auto-generated tokens changed? */
no_cpu_meter_red, /* Feng shui on the status screen */
no_arith, /* Skip most arithmetic ops */
shuffle_queue, /* Shuffle input queue? */
bitmap_changed, /* Time to update bitmap? */
unicorn_mode, /* Running in Unicorn mode? */
use_wine, /* Use WINE with QEMU mode */
skip_requested, /* Skip request, via SIGUSR1 */
run_over10m, /* Run time over 10 minutes? */
persistent_mode, /* Running in persistent mode? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal, /* Try to calibrate faster? */
disable_trim, /* Never trim in fuzz_one */
shmem_testcase_mode, /* If sharedmem testcases are used */
havoc_max_mult, /* havoc multiplier */
skip_deterministic, /* Skip deterministic stages? */
use_splicing, /* Recombine input files? */
non_instrumented_mode, /* Run in non-instrumented mode? */
score_changed, /* Scoring for favorites changed? */
resuming_fuzz, /* Resuming an older fuzzing job? */
timeout_given, /* Specific timeout given? */
not_on_tty, /* stdout is not a tty */
term_too_small, /* terminal dimensions too small */
no_forkserver, /* Disable forkserver? */
crash_mode, /* Crash mode! Yeah! */
in_place_resume, /* Attempt in-place resume? */
autoresume, /* Resume if afl->out_dir exists? */
auto_changed, /* Auto-generated tokens changed? */
no_cpu_meter_red, /* Feng shui on the status screen */
no_arith, /* Skip most arithmetic ops */
shuffle_queue, /* Shuffle input queue? */
bitmap_changed, /* Time to update bitmap? */
unicorn_mode, /* Running in Unicorn mode? */
use_wine, /* Use WINE with QEMU mode */
skip_requested, /* Skip request, via SIGUSR1 */
run_over10m, /* Run time over 10 minutes? */
persistent_mode, /* Running in persistent mode? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal, /* Try to calibrate faster? */
disable_trim, /* Never trim in fuzz_one */
shmem_testcase_mode, /* If sharedmem testcases are used */
expand_havoc, /* perform expensive havoc after no find */
cycle_schedules, /* cycle power schedules? */
old_seed_selection, /* use vanilla afl seed selection */

View File

@ -14,14 +14,14 @@
Parameters:
afl_state_t *afl - the *afl state pointer
u8 *buf - the input buffer to mutate which will be mutated into.
NOTE: must be able to contain a size of at least max_len (see below)!
NOTE: must be able to contain a size of at least max_len!! (see below)
u32 len - the length of the input
u32 steps - how many mutations to perform on the input
bool is_text - is the target expecting text inputs
bool is_exploration - mutate for exploration mode (instead of exploitation)
splice_buf - a buffer from another corpus item to splice with.
If NULL then no splicing
splice_len - the length of the splice buffer. If 0 then no splicing
If NULL then no splicing is done (obviously).
splice_len - the length of the splice buffer. If 0 then no splicing.
u32 max_len - the maximum size the mutated buffer may grow to
*/

View File

@ -2085,47 +2085,57 @@ havoc_stage:
u32 *mutation_array;
u32 stack_max, rand_max; // stack_max_pow = afl->havoc_stack_pow2;
/*
switch (afl->input_mode) {
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
case 1: { // TEXT
mutation_array = full_splice_array;
rand_max = MUT_SPLICE_ARRAY_SIZE;
if (likely(afl->fuzz_mode == 0)) { // is exploration?
mutation_array = (unsigned int *)&binary_array;
rand_max = MUT_BIN_ARRAY_SIZE;
} else {
} else { // exploitation mode
mutation_array = normal_splice_array;
rand_max = MUT_NORMAL_ARRAY_SIZE;
mutation_array = (unsigned int *)&mutation_strategy_exploitation_text;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
}
}
*/
if (unlikely(afl->text_input)) { // is text?
if (likely(afl->fuzz_mode == 0)) { // is exploration?
mutation_array = (unsigned int *)&text_array;
rand_max = MUT_TXT_ARRAY_SIZE;
} else { // is exploitation!
mutation_array = (unsigned int *)&mutation_strategy_exploitation_text;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
break;
}
} else { // is binary!
case 2: { // BINARY
if (likely(afl->fuzz_mode == 0)) { // is exploration?
if (likely(afl->fuzz_mode == 0)) { // is exploration?
mutation_array = (unsigned int *)&mutation_strategy_exploration_binary;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
mutation_array = (unsigned int *)&binary_array;
rand_max = MUT_BIN_ARRAY_SIZE;
} else { // exploitation mode
} else { // is exploitation!
mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
}
break;
}
default: { // DEFAULT/GENERIC
if (likely(afl->fuzz_mode == 0)) { // is exploration?
mutation_array = (unsigned int *)&binary_array;
rand_max = MUT_BIN_ARRAY_SIZE;
} else { // exploitation mode
// this will need to be changed I guess
mutation_array = (unsigned int *)&mutation_strategy_exploration_text;
rand_max = MUT_STRATEGY_ARRAY_SIZE;
}
break;
}

View File

@ -125,7 +125,8 @@ static void usage(u8 *argv0, int more_help) {
"Required parameters:\n"
" -i dir - input directory with test cases (or '-' to resume, "
"also see AFL_AUTORESUME)\n"
"also see \n"
" AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
@ -164,8 +165,8 @@ static void usage(u8 *argv0, int more_help) {
"\n"
"Mutator settings:\n"
" -a - target expects ascii text input (prefer text "
"mutators)\n"
" -a - target input format, \"text\" or \"binary\" (default: "
"generic)\n"
" -g minlength - set min length of generated fuzz input (default: 1)\n"
" -G maxlength - set max length of generated fuzz input (default: "
"%lu)\n"
@ -506,13 +507,28 @@ int main(int argc, char **argv_orig, char **envp) {
// still available: HjJkKqruvwz
while ((opt = getopt(argc, argv,
"+aAb:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
"T:UV:WXx:YZ")) > 0) {
switch (opt) {
case 'a':
afl->text_input = 1;
if (!stricmp(optarg, "text") || !stricmp(optarg, "ascii") ||
!stricmp(optarg, "txt") || !stricmp(optarg, "asc")) {
afl->input_mode = 1;
} else if (!stricmp(optarg, "bin") || !stricmp(optarg, "binary")) {
afl->input_mode = 2;
} else {
FATAL("-a input mode needs to be \"text\" or \"binary\".");
}
break;
case 'P':