diff options
Diffstat (limited to 'custom_mutators/gramatron/gramfuzz.c')
-rw-r--r-- | custom_mutators/gramatron/gramfuzz.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/custom_mutators/gramatron/gramfuzz.c b/custom_mutators/gramatron/gramfuzz.c new file mode 100644 index 00000000..fd126ec0 --- /dev/null +++ b/custom_mutators/gramatron/gramfuzz.c @@ -0,0 +1,429 @@ +// This simple example just creates random buffer <= 100 filled with 'A' +// needs -I /path/to/AFLplusplus/include +//#include "custom_mutator_helpers.h" + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "afl-fuzz.h" +#include "gramfuzz.h" + +#define MUTATORS 4 // Specify the total number of mutators + +typedef struct my_mutator { + + afl_state_t *afl; + + u8 * mutator_buf; + u8 * unparsed_input; + Array *mutated_walk; + Array *orig_walk; + + IdxMap_new *statemap; // Keeps track of the statemap + UT_array ** recurIdx; + // Get_Dupes_Ret* getdupesret; // Recursive feature map + int recurlen; + + int mut_alloced; + int orig_alloced; + int mut_idx; // Signals the current mutator being used, used to cycle through + // each mutator + + unsigned int seed; + +} my_mutator_t; + +state *create_pda(u8 *automaton_file) { + + struct json_object *parsed_json; + state * pda; + json_object * source_obj, *attr; + int arraylen, ii, ii2, trigger_len, error; + + printf("\n[GF] Automaton file passed:%s", automaton_file); + // parsed_json = + // json_object_from_file("./gramfuzz/php_gnf_processed_full.json"); + parsed_json = json_object_from_file(automaton_file); + + // Getting final state + source_obj = json_object_object_get(parsed_json, "final_state"); + printf("\t\nFinal=%s\n", json_object_get_string(source_obj)); + final_state = atoi(json_object_get_string(source_obj)); + + // Getting initial state + source_obj = json_object_object_get(parsed_json, "init_state"); + init_state = atoi(json_object_get_string(source_obj)); + printf("\tInit=%s\n", json_object_get_string(source_obj)); + + // Getting number of states + source_obj = json_object_object_get(parsed_json, "numstates"); + numstates = atoi(json_object_get_string(source_obj)) + 1; + printf("\tNumStates=%d\n", numstates); + + // Allocate state space for each pda state + pda = (state *)calloc(atoi(json_object_get_string(source_obj)) + 1, + sizeof(state)); + + // Getting PDA representation + source_obj = json_object_object_get(parsed_json, "pda"); + enum json_type type; + json_object_object_foreach(source_obj, key, val) { + + state * state_ptr; + trigger *trigger_ptr; + int offset; + + // Get the correct offset into the pda to store state information + state_ptr = pda; + offset = atoi(key); + state_ptr += offset; + // Store state string + state_ptr->state_name = offset; + + // Create trigger array of structs + trigger_len = json_object_array_length(val); + state_ptr->trigger_len = trigger_len; + trigger_ptr = (trigger *)calloc(trigger_len, sizeof(trigger)); + state_ptr->ptr = trigger_ptr; + + for (ii = 0; ii < trigger_len; ii++) { + + json_object *obj = json_object_array_get_idx(val, ii); + // Get all the trigger trigger attributes + attr = json_object_array_get_idx(obj, 0); + (trigger_ptr)->id = strdup(json_object_get_string(attr)); + + attr = json_object_array_get_idx(obj, 1); + trigger_ptr->dest = atoi(json_object_get_string(attr)); + + attr = json_object_array_get_idx(obj, 2); + if (!strcmp("\\n", json_object_get_string(attr))) { + + trigger_ptr->term = strdup("\n"); + + } else { + + trigger_ptr->term = strdup(json_object_get_string(attr)); + + } + + trigger_ptr->term_len = strlen(trigger_ptr->term); + trigger_ptr++; + + } + + } + + // Delete the JSON object + json_object_put(parsed_json); + + return pda; + +} + +my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { + + srand(seed); + my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); + if (!data) { + + perror("afl_custom_init alloc"); + return NULL; + + } + + if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) { + + perror("mutator_buf alloc"); + return NULL; + + } + + data->afl = afl; + data->seed = seed; + + data->mut_alloced = 0; + data->orig_alloced = 0; + data->mut_idx = 0; + data->recurlen = 0; + + // data->mutator_buf = NULL; + // data->unparsed_input = NULL; + // data->mutated_walk = NULL; + // data->orig_walk = NULL; + // + // data->statemap = NULL; // Keeps track of the statemap + // data->recur_idx = NULL; // Will keep track of recursive feature indices + // u32 recur_len = 0; // The number of recursive features + // data->mutator_buf = NULL; + + char *automaton_file = getenv("GRAMATRON_AUTOMATION"); + if (automaton_file) { + + pda = create_pda(automaton_file); + + } else { + + fprintf(stderr, + "\nError: GrammaTron needs an automation json file set in " + "AFL_GRAMATRON_AUTOMATON\n"); + exit(-1); + + } + + return data; + +} + +size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, + u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, + size_t max_size) { + + u8 *unparsed_input; + + // Pick a mutator + // int choice = rand() % MUTATORS; + // data->mut_idx = 1; + // GC old mutant + if (data->mut_alloced) { + + free(data->mutated_walk->start); + free(data->mutated_walk); + data->mut_alloced = 0; + + }; + + // printf("\nChoice:%d", choice); + + if (data->mut_idx == 0) { // Perform random mutation + data->mutated_walk = performRandomMutation(pda, data->orig_walk); + data->mut_alloced = 1; + + } else if (data->mut_idx == 1 && + + data->recurlen) { // Perform recursive mutation + data->mutated_walk = + doMult(data->orig_walk, data->recurIdx, data->recurlen); + data->mut_alloced = 1; + + } else if (data->mut_idx == 2) { // Perform splice mutation + + // we cannot use the supplied splice data so choose a new random file + u32 tid = rand() % data->afl->queued_paths; + struct queue_entry *q = data->afl->queue_buf[tid]; + + // Read the input representation for the splice candidate + u8 * automaton_fn = alloc_printf("%s.aut", q->fname); + Array *spliceCandidate = read_input(pda, automaton_fn); + + if (spliceCandidate) { + + data->mutated_walk = + performSpliceOne(data->orig_walk, data->statemap, spliceCandidate); + data->mut_alloced = 1; + free(spliceCandidate->start); + free(spliceCandidate); + + } else { + + data->mutated_walk = gen_input(pda, NULL); + data->mut_alloced = 1; + + } + + ck_free(automaton_fn); + + } else { // Generate an input from scratch + + data->mutated_walk = gen_input(pda, NULL); + data->mut_alloced = 1; + + } + + // Cycle to the next mutator + if (data->mut_idx == MUTATORS - 1) + data->mut_idx = + 0; // Wrap around if we have reached end of the mutator list + else + data->mut_idx += 1; + + // Unparse the mutated automaton walk + if (data->unparsed_input) { free(data->unparsed_input); } + data->unparsed_input = unparse_walk(data->mutated_walk); + *out_buf = data->unparsed_input; + + return data->mutated_walk->inputlen; + +} + +/** + * Create the automaton-based representation for the corresponding input + * + * @param data pointer returned in afl_custom_init for this fuzz case + * @param filename_new_queue File name of the new queue entry + * @param filename_orig_queue File name of the original queue entry + */ +u8 afl_custom_queue_new_entry(my_mutator_t * data, + const uint8_t *filename_new_queue, + const uint8_t *filename_orig_queue) { + + // get the filename + u8 * automaton_fn, *unparsed_input; + Array *new_input; + s32 fd; + + automaton_fn = alloc_printf("%s.aut", filename_new_queue); + // Check if this method is being called during initialization + + // fprintf(stderr, "new: %s, old: %s, auto: %s\n", + // filename_new_queue,filename_orig_queue,automaton_fn); + + if (filename_orig_queue) { + + write_input(data->mutated_walk, automaton_fn); + + } else { + + new_input = gen_input(pda, NULL); + write_input(new_input, automaton_fn); + + // Update the placeholder file + if (unlink(filename_new_queue)) { + + PFATAL("Unable to delete '%s'", filename_new_queue); + + } + + unparsed_input = unparse_walk(new_input); + fd = open(filename_new_queue, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR); + if (fd < 0) { PFATAL("Failed to update file '%s'", filename_new_queue); } + int written = write(fd, unparsed_input, new_input->inputlen + 1); + close(fd); + + free(new_input->start); + free(new_input); + free(unparsed_input); + + } + + ck_free(automaton_fn); + + return 1; + +} + +/** + * Get the corresponding tree representation for the candidate that is to be + * mutated + * + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param filename File name of the test case in the queue entry + * @return Return True(1) if the fuzzer will fuzz the queue entry, and + * False(0) otherwise. + */ +uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) { + + // get the filename + u8 * automaton_fn = alloc_printf("%s.aut", filename); + IdxMap_new *statemap_ptr; + terminal * term_ptr; + int state; + + // TODO: I don't think we need to update pointers when reading back + // Probably build two different versions of read_input one for flushing + // inputs to disk and the other that + if (data->orig_alloced) { + + free(data->orig_walk->start); + free(data->orig_walk); + data->orig_alloced = 0; + + } + + if (data->statemap) { + + for (int x = 0; x < numstates; x++) { + + utarray_free(data->statemap[x].nums); + + } + + free(data->statemap); + + } + + if (data->recurIdx) { + + data->recurlen = 0; + free(data->recurIdx); + + } + + data->orig_walk = read_input(pda, automaton_fn); + data->orig_alloced = 1; + + // Create statemap for the fuzz candidate + IdxMap_new *statemap_start = + (IdxMap_new *)malloc(sizeof(IdxMap_new) * numstates); + for (int x = 0; x < numstates; x++) { + + statemap_ptr = &statemap_start[x]; + utarray_new(statemap_ptr->nums, &ut_int_icd); + + } + + int offset = 0; + while (offset < data->orig_walk->used) { + + term_ptr = &data->orig_walk->start[offset]; + state = term_ptr->state; + statemap_ptr = &statemap_start[state]; + utarray_push_back(statemap_ptr->nums, &offset); + offset += 1; + + } + + data->statemap = statemap_start; + + // Create recursive feature map (if it exists) + data->recurIdx = malloc(sizeof(UT_array *) * numstates); + // Retrieve the duplicated states + offset = 0; + while (offset < numstates) { + + statemap_ptr = &data->statemap[offset]; + int length = utarray_len(statemap_ptr->nums); + if (length >= 2) { + + data->recurIdx[data->recurlen] = statemap_ptr->nums; + data->recurlen += 1; + + } + + offset += 1; + + } + + // data->getdupesret = get_dupes(data->orig_walk, &data->recurlen); + + ck_free(automaton_fn); + return 1; + +} + +/** + * Deinitialize everything + * + * @param data The data ptr from afl_custom_init + */ + +void afl_custom_deinit(my_mutator_t *data) { + + free(data->mutator_buf); + free(data); + +} + |