mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-10 01:01:33 +00:00
fastresume implementation
This commit is contained in:
parent
6ed0a2b4aa
commit
dd762726dc
@ -236,7 +236,6 @@ struct queue_entry {
|
||||
custom, /* Marker for custom mutators */
|
||||
stats_mutated; /* stats: # of mutations performed */
|
||||
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u32 tc_ref; /* Trace bytes ref count */
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
@ -246,13 +245,11 @@ struct queue_entry {
|
||||
double perf_score, /* performance score */
|
||||
weight;
|
||||
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
struct skipdet_entry *skipdet_e;
|
||||
|
||||
};
|
||||
|
@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
if (!q->was_fuzzed) {
|
||||
if (unlikely(!q->was_fuzzed)) {
|
||||
|
||||
q->was_fuzzed = 1;
|
||||
afl->reinit_table = 1;
|
||||
|
@ -401,7 +401,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
} else {
|
||||
|
||||
if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); }
|
||||
if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ }
|
||||
|
||||
}
|
||||
|
||||
@ -699,12 +699,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
|
||||
void destroy_queue(afl_state_t *afl) {
|
||||
|
||||
u32 i;
|
||||
u32 i;
|
||||
struct queue_entry *q;
|
||||
|
||||
for (i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
struct queue_entry *q;
|
||||
|
||||
q = afl->queue_buf[i];
|
||||
ck_free(q->fname);
|
||||
ck_free(q->trace_mini);
|
||||
|
224
src/afl-fuzz.c
224
src/afl-fuzz.c
@ -181,7 +181,7 @@ static void usage(u8 *argv0, int more_help) {
|
||||
"it.\n"
|
||||
" if using QEMU/FRIDA or the fuzzing target is "
|
||||
"compiled\n"
|
||||
" for CmpLog then use '-c 0'. To disable Cmplog use '-c "
|
||||
" for CmpLog then use '-c 0'. To disable CMPLOG use '-c "
|
||||
"-'.\n"
|
||||
" -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
|
||||
" 1=small files, 2=larger files (default), 3=all "
|
||||
@ -2116,7 +2116,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (read(fr_fd, buf, 32) >= 16) {
|
||||
|
||||
sscanf(buf, "%p", (void**)&prev_target_hash);
|
||||
sscanf(buf, "%p", (void **)&prev_target_hash);
|
||||
|
||||
}
|
||||
|
||||
@ -2126,7 +2126,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
write_setup_file(afl, argc, argv);
|
||||
|
||||
if (afl->in_place_resume) {
|
||||
@ -2143,8 +2142,23 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
|
||||
if ((fr_fd = open(fn, O_RDONLY)) >= 0) {
|
||||
|
||||
OKF("Performing FAST RESUME");
|
||||
// fast_resume = 1;
|
||||
u8 ver_string[8];
|
||||
u64 *ver = (u64 *)ver_string;
|
||||
u64 expect_ver =
|
||||
afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
|
||||
|
||||
if (read(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string))
|
||||
WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME");
|
||||
else if (expect_ver != *ver)
|
||||
WARNF(
|
||||
"Different AFL++ version or feature usage, cannot perform FAST "
|
||||
"RESUME");
|
||||
else {
|
||||
|
||||
OKF("Will perform FAST RESUME");
|
||||
fast_resume = 1;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@ -2156,42 +2170,34 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (fast_resume) {
|
||||
read_testcases(afl, NULL);
|
||||
|
||||
// XXX
|
||||
pivot_inputs(afl);
|
||||
|
||||
} else {
|
||||
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
|
||||
|
||||
read_testcases(afl, NULL);
|
||||
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
|
||||
|
||||
pivot_inputs(afl);
|
||||
char tmpfile[PATH_MAX];
|
||||
|
||||
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
|
||||
if (afl->file_extension) {
|
||||
|
||||
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
|
||||
snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
|
||||
afl->file_extension);
|
||||
|
||||
char tmpfile[PATH_MAX];
|
||||
} else {
|
||||
|
||||
if (afl->file_extension) {
|
||||
snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
|
||||
|
||||
snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
|
||||
afl->file_extension);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* there is still a race condition here, but well ... */
|
||||
if (access(tmpfile, F_OK) != -1) {
|
||||
|
||||
snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
|
||||
|
||||
}
|
||||
|
||||
/* there is still a race condition here, but well ... */
|
||||
if (access(tmpfile, F_OK) != -1) {
|
||||
|
||||
FATAL(
|
||||
"AFL_TMPDIR already has an existing temporary input file: %s - if "
|
||||
"this is not from another instance, then just remove the file.",
|
||||
tmpfile);
|
||||
|
||||
}
|
||||
FATAL(
|
||||
"AFL_TMPDIR already has an existing temporary input file: %s - if "
|
||||
"this is not from another instance, then just remove the file.",
|
||||
tmpfile);
|
||||
|
||||
}
|
||||
|
||||
@ -2474,7 +2480,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
OKF("Cmplog forkserver successfully started");
|
||||
OKF("CMPLOG forkserver successfully started");
|
||||
|
||||
}
|
||||
|
||||
@ -2512,29 +2518,102 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
dedup_extras(afl);
|
||||
if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
|
||||
|
||||
// after we have the correct bitmap size we can read the bitmap -B option
|
||||
// and set the virgin maps
|
||||
if (afl->in_bitmap) {
|
||||
if (unlikely(fast_resume)) {
|
||||
|
||||
read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
|
||||
u64 resume_start = get_cur_time_us();
|
||||
// if we get here then we should abort on errors
|
||||
ck_read(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
|
||||
ck_read(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout");
|
||||
ck_read(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash");
|
||||
ck_read(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes");
|
||||
|
||||
u8 res[1] = {0};
|
||||
u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
|
||||
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
|
||||
u32 r = 8 + afl->fsrv.map_size * 4;
|
||||
u32 q_len = o_end - o_start;
|
||||
u32 m_len = (afl->fsrv.map_size >> 3);
|
||||
struct queue_entry *q;
|
||||
|
||||
for (u32 i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
q = afl->queue_buf[i];
|
||||
ck_read(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
|
||||
ck_read(fr_fd, res, 1, "check map");
|
||||
if (res[0]) {
|
||||
|
||||
q->trace_mini = ck_alloc(m_len);
|
||||
ck_read(fr_fd, q->trace_mini, m_len, "trace_mini");
|
||||
r += q_len + m_len + 1;
|
||||
|
||||
} else {
|
||||
|
||||
r += q_len + 1;
|
||||
|
||||
}
|
||||
|
||||
afl->total_bitmap_size += q->bitmap_size;
|
||||
++afl->total_bitmap_entries;
|
||||
update_bitmap_score(afl, q);
|
||||
|
||||
if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
|
||||
|
||||
if (q->disabled) {
|
||||
|
||||
if (!q->was_fuzzed) { --afl->pending_not_fuzzed; }
|
||||
--afl->active_items;
|
||||
|
||||
}
|
||||
|
||||
if (q->var_behavior) { ++afl->queued_variable; }
|
||||
if (q->favored) {
|
||||
|
||||
++afl->queued_favored;
|
||||
if (!q->was_fuzzed) { ++afl->pending_favored; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u8 buf[4];
|
||||
if (read(fr_fd, buf, 3) > 0) {
|
||||
|
||||
FATAL("invalid trailing data in fastresume.bin");
|
||||
|
||||
}
|
||||
|
||||
OKF("Successfully loaded fastresume.bin (%u bytes)!", r);
|
||||
close(fr_fd);
|
||||
afl->reinit_table = 1;
|
||||
update_calibration_time(afl, &resume_start);
|
||||
|
||||
} else {
|
||||
|
||||
memset(afl->virgin_bits, 255, map_size);
|
||||
// after we have the correct bitmap size we can read the bitmap -B option
|
||||
// and set the virgin maps
|
||||
if (afl->in_bitmap) {
|
||||
|
||||
}
|
||||
read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
|
||||
|
||||
memset(afl->virgin_tmout, 255, map_size);
|
||||
memset(afl->virgin_crash, 255, map_size);
|
||||
} else {
|
||||
|
||||
if (likely(!afl->afl_env.afl_no_startup_calibration)) {
|
||||
memset(afl->virgin_bits, 255, map_size);
|
||||
|
||||
perform_dry_run(afl);
|
||||
}
|
||||
|
||||
} else {
|
||||
memset(afl->virgin_tmout, 255, map_size);
|
||||
memset(afl->virgin_crash, 255, map_size);
|
||||
|
||||
ACTF("skipping initial seed calibration due option override!");
|
||||
usleep(1000);
|
||||
if (likely(!afl->afl_env.afl_no_startup_calibration)) {
|
||||
|
||||
perform_dry_run(afl);
|
||||
|
||||
} else {
|
||||
|
||||
ACTF("Skipping initial seed calibration due option override!");
|
||||
usleep(1000);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3125,6 +3204,63 @@ stop_fuzzing:
|
||||
fclose(afl->fsrv.det_plot_file);
|
||||
#endif
|
||||
|
||||
/* create fastresume.bin */
|
||||
u8 fr[PATH_MAX];
|
||||
snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
|
||||
if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >=
|
||||
0) {
|
||||
|
||||
u8 ver_string[8];
|
||||
u32 w = 0;
|
||||
u64 *ver = (u64 *)ver_string;
|
||||
*ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
|
||||
|
||||
w += write(fr_fd, ver_string, sizeof(ver_string));
|
||||
|
||||
w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size);
|
||||
w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size);
|
||||
w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size);
|
||||
w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size);
|
||||
|
||||
u8 on[1] = {1}, off[1] = {0};
|
||||
u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
|
||||
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
|
||||
u32 q_len = o_end - o_start;
|
||||
u32 m_len = (afl->fsrv.map_size >> 3);
|
||||
struct queue_entry *q;
|
||||
|
||||
afl->pending_not_fuzzed = afl->queued_items;
|
||||
afl->active_items = afl->queued_items;
|
||||
|
||||
for (u32 i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
q = afl->queue_buf[i];
|
||||
ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
|
||||
if (!q->trace_mini) {
|
||||
|
||||
ck_write(fr_fd, off, 1, "no_mini");
|
||||
w += q_len + 1;
|
||||
|
||||
} else {
|
||||
|
||||
ck_write(fr_fd, on, 1, "yes_mini");
|
||||
ck_write(fr_fd, q->trace_mini, m_len, "trace_mini");
|
||||
w += q_len + m_len + 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
close(fr_fd);
|
||||
afl->var_byte_count = count_bytes(afl, afl->var_bytes);
|
||||
OKF("Written fastresume.bin with %u bytes!", w);
|
||||
|
||||
} else {
|
||||
|
||||
WARNF("Could not create fastresume.bin");
|
||||
|
||||
}
|
||||
|
||||
destroy_queue(afl);
|
||||
destroy_extras(afl);
|
||||
destroy_custom_mutators(afl);
|
||||
|
Loading…
x
Reference in New Issue
Block a user