diff --git a/examples/libaflfuzzer.c b/examples/libaflfuzzer.c index 6e78240..7db673c 100644 --- a/examples/libaflfuzzer.c +++ b/examples/libaflfuzzer.c @@ -34,6 +34,7 @@ static llmp_message_t *current_fuzz_input_msg = NULL; static afl_input_t * current_input = NULL; static int debug = 0; static char * queue_dirpath; +static ssize_t calibration_idx = -1; typedef struct cur_state { @@ -105,13 +106,34 @@ afl_exit_t debug_harness_func(afl_executor_t *executor, u8 *input, size_t len) { } -/* Initializer: LLVMFuzzerInitialize */ +/* Initializer: run initial seeds and run LLVMFuzzerInitialize */ static afl_ret_t in_memory_fuzzer_initialize(afl_executor_t *executor) { in_memory_executor_t *in_memory_fuzzer = (in_memory_executor_t *)executor; if (LLVMFuzzerInitialize) { LLVMFuzzerInitialize(&in_memory_fuzzer->argc, &in_memory_fuzzer->argv); } + /* TODO + while(calibration_idx > 0) { + + --calibration_idx; + afl_entry_t *queue_entry = global_queue->base.funcs.get_queue_entry((afl_queue_t *)global_queue, calibration_idx); + if (queue_entry && queue_entry->skip_entry == false) { + + if (afl_stage_run(stage, queue_entry->input) != AFL_RET_SUCCESS) { + + WARNF("Queue entry %d misbehaved, disabling...", calibration_idx); + queue_entry->skip_entry = true; + + } + + } + + } + + calibration_idx = -1; // we are done + */ + return AFL_RET_SUCCESS; } @@ -129,6 +151,7 @@ void write_cur_state(llmp_message_t *out_msg) { state->map_size = __afl_map_size; memcpy(state->payload, virgin_bits, state->map_size); state->current_input_len = current_input->len; + state->calibration_idx = calibration_idx; memcpy(state->payload + state->map_size, current_input->bytes, current_input->len); } @@ -322,8 +345,7 @@ u8 execute(afl_engine_t *engine, afl_input_t *input) { default: { /* TODO: We'll never reach this, actually... */ - if (afl_input_dump_to_crashfile(executor->current_input, queue_dirpath) == AFL_RET_SUCCESS) - engine->crashes++; + if (afl_input_dump_to_crashfile(executor->current_input, queue_dirpath) == AFL_RET_SUCCESS) engine->crashes++; return AFL_RET_WRITE_TO_CRASH; } @@ -332,7 +354,7 @@ u8 execute(afl_engine_t *engine, afl_input_t *input) { } -/* This initializeds the fuzzer */ +/* This initializes the fuzzer */ afl_engine_t *initialize_fuzzer(char *in_dir, char *queue_dir, int argc, char *argv[]) { /* Let's create an in-memory executor */ @@ -440,7 +462,8 @@ afl_engine_t *initialize_fuzzer(char *in_dir, char *queue_dir, int argc, char *a } - OKF("Starting seed count: %llu", ((afl_queue_t *)engine->global_queue)->entries_count); + calibration_idx = (ssize_t)((afl_queue_t *)engine->global_queue)->entries_count; + OKF("Starting seed count: %llu", calibration_idx); return engine; @@ -478,13 +501,18 @@ void fuzzer_process_main(llmp_client_t *llmp_client, void *data) { afl_stage_t * stage = engine->fuzz_one->stages[0]; afl_mutator_scheduled_t *mutators_havoc = (afl_mutator_scheduled_t *)stage->mutators[0]; - afl_feedback_cov_t *coverage_feedback = NULL; + afl_feedback_cov_t * coverage_feedback = NULL; for (i = 0; i < engine->feedbacks_count; i++) { + if (engine->feedbacks[i]->tag == AFL_FEEDBACK_TAG_COV) { + coverage_feedback = (afl_feedback_cov_t *)(engine->feedbacks[i]); break; + } + } + if (!coverage_feedback) { FATAL("No coverage feedback added to engine"); } /* The actual fuzzing */ @@ -605,6 +633,22 @@ bool broker_message_hook(llmp_broker_t *broker, llmp_broker_clientdata_t *client DBG("We found a timeout..."); /* write timeout output */ state = LLMP_MSG_BUF_AS(msg, cur_state_t); + if (state->calibration_idx < calibration_idx) calibration_idx = state->calibration_idx; + /* + if (state->calibration_idx >= 0) { + + afl_entry_t *queue_entry = global_queue->base.funcs.get_queue_entry((afl_queue_t *)global_queue, + calibration_idx); if (queue_entry && queue_entry->skip_entry == false) { if (afl_stage_run(stage, + queue_entry->input) != AFL_RET_SUCCESS) { WARNF("Queue entry %d misbehaved, disabling...", calibration_idx); + queue_entry->skip_entry = true; + + } + + } + + } + + */ afl_input_t timeout_input = {0}; AFL_TRY(afl_input_init(&timeout_input), { FATAL("Error initializing input for crash: %s", afl_ret_stringify(err)); }); @@ -613,10 +657,13 @@ bool broker_message_hook(llmp_broker_t *broker, llmp_broker_clientdata_t *client timeout_input.len = state->current_input_len; if (timeout_input.len) { - if (afl_input_dump_to_timeoutfile(&timeout_input, queue_dirpath) == AFL_RET_SUCCESS) - fuzzer_stats->timeouts++; + + if (afl_input_dump_to_timeoutfile(&timeout_input, queue_dirpath) == AFL_RET_SUCCESS) fuzzer_stats->timeouts++; + } else { + WARNF("Crash input has zero length, this cannot happen."); + } broker_handle_client_restart(broker, clientdata, state); @@ -632,6 +679,7 @@ bool broker_message_hook(llmp_broker_t *broker, llmp_broker_clientdata_t *client DBG("We found a crash!"); /* write crash output */ state = LLMP_MSG_BUF_AS(msg, cur_state_t); + if (state->calibration_idx < calibration_idx) calibration_idx = state->calibration_idx; afl_input_t crashing_input = {0}; AFL_TRY(afl_input_init(&crashing_input), { FATAL("Error initializing input for crash: %s", afl_ret_stringify(err)); }); @@ -640,10 +688,13 @@ bool broker_message_hook(llmp_broker_t *broker, llmp_broker_clientdata_t *client crashing_input.len = state->current_input_len; if (crashing_input.len) { - if (afl_input_dump_to_crashfile(&crashing_input, queue_dirpath) == AFL_RET_SUCCESS) - fuzzer_stats->crashes++; + + if (afl_input_dump_to_crashfile(&crashing_input, queue_dirpath) == AFL_RET_SUCCESS) fuzzer_stats->crashes++; + } else { + WARNF("Crash input has zero length, this cannot happen."); + } broker_handle_client_restart(broker, clientdata, state); diff --git a/include/queue.h b/include/queue.h index 78550f7..ced29c0 100644 --- a/include/queue.h +++ b/include/queue.h @@ -90,6 +90,7 @@ struct afl_queue_funcs { afl_entry_t *(*get)(afl_queue_t *); afl_entry_t *(*get_next_in_queue)(afl_queue_t *, int); + afl_entry_t *(*get_queue_entry)(afl_queue_t *, u32); afl_entry_t *(*get_queue_base)(afl_queue_t *); size_t (*get_size)(afl_queue_t *); char *(*get_dirpath)(afl_queue_t *); @@ -114,6 +115,7 @@ struct afl_queue { size_t names_id; bool save_to_files; bool fuzz_started; + bool skip_entry; struct afl_queue_funcs funcs; }; @@ -132,6 +134,7 @@ void afl_queue_set_dirpath(afl_queue_t *, char *); void afl_queue_set_engine(afl_queue_t *queue, afl_engine_t *engine); void afl_queue_global_set_engine(afl_queue_t *, afl_engine_t *); afl_entry_t *afl_queue_next_base_queue(afl_queue_t *queue, int engine_id); +afl_entry_t *afl_queue_get_entry(afl_queue_t *queue, u32 entry); AFL_NEW_AND_DELETE_FOR(afl_queue) diff --git a/include/stage.h b/include/stage.h index dab77d7..e6e6b4e 100644 --- a/include/stage.h +++ b/include/stage.h @@ -46,6 +46,7 @@ struct afl_stage { }; +afl_ret_t afl_stage_run(afl_stage_t *, afl_input_t *, bool); afl_ret_t afl_stage_perform(afl_stage_t *, afl_input_t *); size_t afl_stage_get_iters(afl_stage_t *); afl_ret_t afl_stage_init(afl_stage_t *, afl_engine_t *); diff --git a/src/input.c b/src/input.c index 9ebef7e..02ed3f4 100644 --- a/src/input.c +++ b/src/input.c @@ -151,7 +151,7 @@ afl_ret_t afl_input_write_to_file(afl_input_t *input, char *fname) { // if it already exists we will not overwrite it if (access(fname, W_OK) == 0) return AFL_RET_FILE_DUPLICATE; - + s32 fd = open(fname, O_RDWR | O_CREAT | O_EXCL, 0600); if (fd < 0) { return AFL_RET_FILE_OPEN_ERROR; } diff --git a/src/queue.c b/src/queue.c index ecd7ba2..31004e6 100644 --- a/src/queue.c +++ b/src/queue.c @@ -113,6 +113,7 @@ afl_ret_t afl_queue_init(afl_queue_t *queue) { queue->funcs.set_dirpath = afl_queue_set_dirpath; queue->funcs.set_engine = afl_queue_set_engine; queue->funcs.get_next_in_queue = afl_queue_next_base_queue; + queue->funcs.get_queue_entry = afl_queue_get_entry; return AFL_RET_SUCCESS; @@ -266,20 +267,23 @@ void afl_queue_set_engine(afl_queue_t *queue, afl_engine_t *engine) { } +afl_entry_t *afl_queue_get_entry(afl_queue_t *queue, u32 entry) { + + if (queue->entries_count <= entry) { return NULL; } + return queue->entries[entry]; + +} + afl_entry_t *afl_queue_next_base_queue(afl_queue_t *queue, int engine_id) { if (queue->entries_count) { afl_entry_t *current = queue->entries[queue->current]; - if (engine_id != queue->engine_id) { - - return current; - - } // If some other engine grabs from the queue, don't update the queue's + if (engine_id != queue->engine_id) { return current; } + // If some other engine grabs from the queue, don't update the queue's // current entry - // If we reach the end of queue, start from beginning queue->current = (queue->current + 1) % queue->entries_count; diff --git a/src/stage.c b/src/stage.c index 51e068e..8629d09 100644 --- a/src/stage.c +++ b/src/stage.c @@ -75,6 +75,32 @@ size_t afl_stage_get_iters(afl_stage_t *stage) { } +afl_ret_t afl_stage_run(afl_stage_t *stage, afl_input_t *input, bool overwrite) { + + afl_input_t *copy; + if (!overwrite) + copy = input->funcs.copy(input); + else + copy = input; + + /* Let's post process the mutated data now. */ + size_t j; + for (j = 0; j < stage->mutators_count; ++j) { + + afl_mutator_t *mutator = stage->mutators[j]; + + if (mutator->funcs.post_process) { mutator->funcs.post_process(mutator, copy); } + + } + + afl_ret_t ret = stage->engine->funcs.execute(stage->engine, copy); + + if (!overwrite) afl_input_delete(copy); + + return ret; + +} + /* Perform default for fuzzing stage */ afl_ret_t afl_stage_perform(afl_stage_t *stage, afl_input_t *input) { @@ -116,18 +142,9 @@ afl_ret_t afl_stage_perform(afl_stage_t *stage, afl_input_t *input) { } - /* Let's post process the mutated data now. */ - for (j = 0; j < stage->mutators_count; ++j) { - - afl_mutator_t *mutator = stage->mutators[j]; + afl_ret_t ret = afl_stage_run(stage, copy, true); - if (mutator->funcs.post_process) { mutator->funcs.post_process(mutator, copy); } - - } - - afl_ret_t ret = stage->engine->funcs.execute(stage->engine, copy); /* Let's collect some feedback on the input now */ - bool interestingness = 0.0f; afl_feedback_t **feedbacks = stage->engine->feedbacks;