integration in fuzz_one

This commit is contained in:
van Hauser
2020-08-09 20:24:56 +02:00
parent b60663c031
commit e99d7e9730
4 changed files with 147 additions and 21 deletions

View File

@ -430,7 +430,9 @@ typedef struct afl_state {
*in_bitmap, /* Input bitmap */ *in_bitmap, /* Input bitmap */
*file_extension, /* File extension */ *file_extension, /* File extension */
*orig_cmdline, /* Original command line */ *orig_cmdline, /* Original command line */
*infoexec; /* Command to execute on a new crash */ *infoexec, /* Command to execute on a new crash */
*taint_input_file, /* fuzz_input_one input file */
*taint_src, *taint_map;
u32 hang_tmout; /* Timeout used for hang det (ms) */ u32 hang_tmout; /* Timeout used for hang det (ms) */
@ -441,7 +443,8 @@ typedef struct afl_state {
custom_only, /* Custom mutator only mode */ custom_only, /* Custom mutator only mode */
python_only, /* Python-only mode */ python_only, /* Python-only mode */
is_main_node, /* if this is the main node */ is_main_node, /* if this is the main node */
is_secondary_node; /* if this is a secondary instance */ is_secondary_node, /* if this is a secondary instance */
taint_needs_splode; /* explode fuzz input */
u32 stats_update_freq; /* Stats update frequency (execs) */ u32 stats_update_freq; /* Stats update frequency (execs) */
@ -502,7 +505,8 @@ typedef struct afl_state {
useless_at_start, /* Number of useless starting paths */ useless_at_start, /* Number of useless starting paths */
var_byte_count, /* Bitmap bytes with var behavior */ var_byte_count, /* Bitmap bytes with var behavior */
current_entry, /* Current queue entry ID */ current_entry, /* Current queue entry ID */
havoc_div; /* Cycle count divisor for havoc */ havoc_div, /* Cycle count divisor for havoc */
taint_len;
u64 total_crashes, /* Total number of crashes */ u64 total_crashes, /* Total number of crashes */
unique_crashes, /* Crashes with unique signatures */ unique_crashes, /* Crashes with unique signatures */

View File

@ -458,7 +458,80 @@ u8 fuzz_one_original(afl_state_t *afl) {
} }
if (unlikely(afl->fsrv.taint_mode && (afl->queue_cycle % 3))) {
if (unlikely(afl->queue_cur->cal_failed)) goto abandon_entry;
u32 dst = 0, i;
fd = open(afl->queue_cur->fname, O_RDONLY);
afl->taint_src = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)afl->taint_src == -1)
FATAL("unable to open '%s'", afl->queue_cur->fname);
close(fd);
switch (afl->queue_cycle % 3) {
case 0: // do nothing, but cannot happen -> else
break;
case 1: // fuzz only tainted bytes
if (!afl->queue_cur->taint_bytes_all) goto abandon_entry;
afl->taint_needs_splode = 1;
fd = open(afl->taint_input_file, O_RDONLY);
len = afl->taint_len = afl->queue_cur->taint_bytes_all;
orig_in = in_buf =
mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1)
FATAL("unable to open '%s'", afl->taint_input_file);
close(fd);
fd = open(afl->queue_cur->fname_taint, O_RDWR);
afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1)
FATAL("unable to open '%s'", afl->queue_cur->fname_taint);
close(fd);
for (i = 0; i < afl->queue_cur->len && dst < len; i++)
if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
break;
case 2: // fuzz only newly tainted bytes
if (!afl->queue_cur->taint_bytes_new) goto abandon_entry;
afl->taint_needs_splode = 1;
fd = open(afl->taint_input_file, O_RDONLY);
len = afl->taint_len = afl->queue_cur->taint_bytes_new;
orig_in = in_buf =
mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1)
FATAL("unable to open '%s'", afl->taint_input_file);
close(fd);
u8 *fn = alloc_printf("%s.new", afl->queue_cur->fname_taint);
fd = open(fn, O_RDWR);
afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1) FATAL("unable to open '%s'", fn);
close(fd);
ck_free(fn);
for (i = 0; i < afl->queue_cur->len && dst < len; i++)
if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
break;
}
goto havoc_stage; // we let the normal cycles do deterministic mode - if
} else {
/* Map the test case into memory. */ /* Map the test case into memory. */
afl->taint_needs_splode = 0;
fd = open(afl->queue_cur->fname, O_RDONLY); fd = open(afl->queue_cur->fname, O_RDONLY);
@ -480,6 +553,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
close(fd); close(fd);
}
/* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every
single byte anyway, so it wouldn't give us any performance or memory usage single byte anyway, so it wouldn't give us any performance or memory usage
benefits. */ benefits. */
@ -527,7 +602,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
************/ ************/
if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
!afl->disable_trim) { !afl->disable_trim && !afl->taint_needs_splode) {
u8 res = trim_case(afl, afl->queue_cur, in_buf); u8 res = trim_case(afl, afl->queue_cur, in_buf);
@ -2568,8 +2643,18 @@ abandon_entry:
++afl->queue_cur->fuzz_level; ++afl->queue_cur->fuzz_level;
if (afl->taint_needs_splode) {
munmap(afl->taint_src, afl->queue_cur->len);
munmap(orig_in, afl->taint_len);
munmap(afl->taint_map, afl->queue_cur->len);
} else {
munmap(orig_in, afl->queue_cur->len); munmap(orig_in, afl->queue_cur->len);
}
return ret_val; return ret_val;
#undef FLIP_BIT #undef FLIP_BIT

View File

@ -863,6 +863,8 @@ abort_trimming:
} }
#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
/* Write a modified test case, run program, process results. Handle /* Write a modified test case, run program, process results. Handle
error conditions, returning 1 if it's time to bail out. This is error conditions, returning 1 if it's time to bail out. This is
a helper function for fuzz_one(). */ a helper function for fuzz_one(). */
@ -871,6 +873,27 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault; u8 fault;
if (unlikely(afl->taint_needs_splode)) {
s32 new_len = afl->queue_cur->len + len - afl->taint_len;
if (new_len < 4) new_len = 4;
u8 *new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len);
u32 i, taint = 0;
for (i = 0; i < new_len; i++) {
if (afl->taint_map[i] || i > afl->queue_cur->len)
new_buf[i] = out_buf[taint++];
else
new_buf[i] = afl->taint_src[i];
}
out_buf = new_buf;
len = new_len;
}
write_to_testcase(afl, out_buf, len); write_to_testcase(afl, out_buf, len);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@ -918,3 +941,5 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
} }
#undef BUF_PARAMS

View File

@ -1260,12 +1260,15 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.taint_mode) { if (afl->fsrv.taint_mode) {
ACTF("Spawning qemu_taint forkserver"); ACTF("Spawning qemu_taint forkserver");
u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0);
afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv); afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv);
afl->taint_fsrv.qemu_mode = 2; afl->taint_fsrv.qemu_mode = 2;
afl->taint_fsrv.taint_mode = 1; afl->taint_fsrv.taint_mode = 1;
afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits; afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits;
ck_free(afl->taint_fsrv.target_path); ck_free(afl->taint_fsrv.target_path);
afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind)); afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind));
afl->taint_fsrv.target_path = afl->taint_fsrv.target_path =
@ -1290,7 +1293,16 @@ int main(int argc, char **argv_orig, char **envp) {
setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1); setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1);
afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon, afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon,
afl->afl_env.afl_debug_child_output); afl->afl_env.afl_debug_child_output);
afl->taint_input_file = alloc_printf("%s/taint/.input", afl->out_dir);
int fd = open(afl->taint_input_file, O_CREAT | O_TRUNC | O_RDWR, 0644);
if (fd < 0)
FATAL("Cannot create taint inpu file '%s'", afl->taint_input_file);
lseek(fd, MAX_FILE, SEEK_SET);
ck_write(fd, "\0", 1, afl->taint_input_file);
if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION"); if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
OKF("Taint forkserver successfully started"); OKF("Taint forkserver successfully started");
} }