mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 02:58:08 +00:00
more api
This commit is contained in:
committed by
van Hauser
parent
fc4b03ee74
commit
d6a7630fe2
@ -27,7 +27,7 @@ performed with the custom mutator.
|
|||||||
|
|
||||||
C/C++:
|
C/C++:
|
||||||
```c
|
```c
|
||||||
void afl_custom_init(unsigned int seed);
|
void afl_custom_init(void *afl, unsigned int seed);
|
||||||
size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf,
|
size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf,
|
||||||
size_t add_buf_size, size_t max_size);
|
size_t add_buf_size, size_t max_size);
|
||||||
size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, uint8_t** out_buf);
|
size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, uint8_t** out_buf);
|
||||||
@ -39,6 +39,7 @@ uint8_t afl_custom_havoc_mutation_probability(void);
|
|||||||
uint8_t afl_custom_queue_get(const uint8_t* filename);
|
uint8_t afl_custom_queue_get(const uint8_t* filename);
|
||||||
void afl_custom_queue_new_entry(const uint8_t* filename_new_queue,
|
void afl_custom_queue_new_entry(const uint8_t* filename_new_queue,
|
||||||
const uint8_t* filename_orig_queue);
|
const uint8_t* filename_orig_queue);
|
||||||
|
void afl_custom_deinit(void *data);
|
||||||
```
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define DATA_SIZE (100)
|
#define DATA_SIZE (100)
|
||||||
|
#define INITIAL_BUF_SIZE (16384)
|
||||||
|
|
||||||
static const char *commands[] = {
|
static const char *commands[] = {
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ typedef struct my_mutator {
|
|||||||
|
|
||||||
afl_t *afl;
|
afl_t *afl;
|
||||||
// any additional data here!
|
// any additional data here!
|
||||||
|
size_t pre_save_size;
|
||||||
|
u8 * pre_save_buf;
|
||||||
|
|
||||||
} my_mutator_t;
|
} my_mutator_t;
|
||||||
|
|
||||||
@ -56,6 +59,16 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
|
|||||||
|
|
||||||
data->afl = afl;
|
data->afl = afl;
|
||||||
|
|
||||||
|
data->pre_save_buf = malloc(INITIAL_BUF_SIZE);
|
||||||
|
if (!data->pre_save_buf) {
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data->pre_save_size = INITIAL_BUF_SIZE;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -125,12 +138,23 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
|||||||
size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||||
uint8_t *out_buf, size_t out_buf_size) {
|
uint8_t *out_buf, size_t out_buf_size) {
|
||||||
|
|
||||||
// In case we need more than out_buf_size, we return that amount and get
|
if (data->pre_save_size < buf_size + 5) {
|
||||||
// called again.
|
|
||||||
if (out_buf_size < 32000) return 32000;
|
|
||||||
|
|
||||||
memcpy(out_buf, buf, buf_size);
|
data->pre_save_buf = realloc(data->pre_save_buf, buf_size + 5);
|
||||||
out_buf_size = buf_size;
|
if (!data->pre_save_buf) {
|
||||||
|
|
||||||
|
perror("custom mutator realloc");
|
||||||
|
free(data);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data->pre_save_size = buf_size + 5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out_buf + 5, buf, buf_size);
|
||||||
|
out_buf_size = buf_size + 5;
|
||||||
out_buf[0] = 'A';
|
out_buf[0] = 'A';
|
||||||
out_buf[1] = 'F';
|
out_buf[1] = 'F';
|
||||||
out_buf[2] = 'L';
|
out_buf[2] = 'L';
|
||||||
@ -322,6 +346,7 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
|
|||||||
*/
|
*/
|
||||||
void afl_custom_deinit(my_mutator_t *data) {
|
void afl_custom_deinit(my_mutator_t *data) {
|
||||||
|
|
||||||
|
free(data->pre_save_buf);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,6 @@
|
|||||||
#define AFL_MAIN
|
#define AFL_MAIN
|
||||||
#define MESSAGES_TO_STDOUT
|
#define MESSAGES_TO_STDOUT
|
||||||
|
|
||||||
/* We preallocate a buffer of this size for afl_custom_pre_save */
|
|
||||||
#define PRE_SAVE_BUF_INIT_SIZE (16384)
|
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE 1
|
#define _GNU_SOURCE 1
|
||||||
#endif
|
#endif
|
||||||
@ -296,8 +293,8 @@ typedef struct py_mutator {
|
|||||||
void * afl_state;
|
void * afl_state;
|
||||||
void * py_data;
|
void * py_data;
|
||||||
|
|
||||||
PyObject *scratch_buf;
|
u8 * pre_save_buf;
|
||||||
size_t scratch_size;
|
size_t pre_save_size;
|
||||||
|
|
||||||
} py_mutator_t;
|
} py_mutator_t;
|
||||||
|
|
||||||
@ -641,13 +638,13 @@ struct custom_mutator {
|
|||||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||||
* @param[in] buf Buffer containing the test case to be executed
|
* @param[in] buf Buffer containing the test case to be executed
|
||||||
* @param[in] buf_size Size of the test case
|
* @param[in] buf_size Size of the test case
|
||||||
* @param[out] out_buf Pointer to the buffer of storing the test case after
|
* @param[out] out_buf Pointer to the buffer storing the test case after
|
||||||
* processing. External library should allocate memory for out_buf. AFL++
|
* processing. External library should allocate memory for out_buf.
|
||||||
* will release the memory after saving the test case.
|
* It can chose to alter buf in-place, if the space is large enough.
|
||||||
* @return Size of the output buffer after processing
|
* @return Size of the output buffer.
|
||||||
*/
|
*/
|
||||||
size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
|
size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
|
||||||
u8 *out_buf, size_t out_buf_size);
|
u8 **out_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called at the start of each trimming operation and receives
|
* This method is called at the start of each trimming operation and receives
|
||||||
@ -783,7 +780,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
|
|||||||
|
|
||||||
void finalize_py_module(void *);
|
void finalize_py_module(void *);
|
||||||
|
|
||||||
size_t pre_save_py(void *, u8 *, size_t, u8 *, size_t);
|
size_t pre_save_py(void *, u8 *, size_t, u8 **);
|
||||||
u32 init_trim_py(void *, u8 *, size_t);
|
u32 init_trim_py(void *, u8 *, size_t);
|
||||||
u32 post_trim_py(void *, u8);
|
u32 post_trim_py(void *, u8);
|
||||||
void trim_py(void *, u8 **, size_t *);
|
void trim_py(void *, u8 **, size_t *);
|
||||||
|
@ -135,18 +135,9 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
|||||||
|
|
||||||
/* "afl_custom_pre_save", optional */
|
/* "afl_custom_pre_save", optional */
|
||||||
afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
|
afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
|
||||||
if (!afl->mutator->afl_custom_pre_save) {
|
if (!afl->mutator->afl_custom_pre_save)
|
||||||
|
|
||||||
WARNF("Symbol 'afl_custom_pre_save' not found.");
|
WARNF("Symbol 'afl_custom_pre_save' not found.");
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* if we have a pre_save hook, prealloc some memory. */
|
|
||||||
afl->mutator->pre_save_buf = ck_alloc(PRE_SAVE_BUF_INIT_SIZE * sizeof(u8));
|
|
||||||
afl->mutator->pre_save_size = PRE_SAVE_BUF_INIT_SIZE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 notrim = 0;
|
u8 notrim = 0;
|
||||||
/* "afl_custom_init_trim", optional */
|
/* "afl_custom_init_trim", optional */
|
||||||
afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
||||||
|
@ -307,14 +307,8 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
|
|||||||
is quite different from the custom mutator. */
|
is quite different from the custom mutator. */
|
||||||
afl->mutator->afl_custom_fuzz = fuzz_py;
|
afl->mutator->afl_custom_fuzz = fuzz_py;
|
||||||
|
|
||||||
if (py_functions[PY_FUNC_PRE_SAVE]) {
|
if (py_functions[PY_FUNC_PRE_SAVE])
|
||||||
|
|
||||||
afl->mutator->afl_custom_pre_save = pre_save_py;
|
afl->mutator->afl_custom_pre_save = pre_save_py;
|
||||||
/* if we have a pre_save hook, prealloc some memory. */
|
|
||||||
afl->mutator->pre_save_buf = ck_alloc(PRE_SAVE_BUF_INIT_SIZE * sizeof(u8));
|
|
||||||
afl->mutator->pre_save_size = PRE_SAVE_BUF_INIT_SIZE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (py_functions[PY_FUNC_INIT_TRIM])
|
if (py_functions[PY_FUNC_INIT_TRIM])
|
||||||
afl->mutator->afl_custom_init_trim = init_trim_py;
|
afl->mutator->afl_custom_init_trim = init_trim_py;
|
||||||
@ -344,39 +338,18 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 *out_buf,
|
size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
|
||||||
size_t out_buf_size) {
|
|
||||||
|
|
||||||
size_t py_out_buf_size;
|
size_t py_out_buf_size;
|
||||||
PyObject *py_args, *py_value;
|
PyObject * py_args, *py_value;
|
||||||
|
py_mutator_t *py = (py_mutator_t *)py_mutator;
|
||||||
if (((py_mutator_t *)py_mutator)->scratch_buf) {
|
|
||||||
|
|
||||||
/* We are being recalled from an earlier run
|
|
||||||
where we didn't have enough mem. */
|
|
||||||
if (((py_mutator_t *)py_mutator)->scratch_size < out_buf_size) {
|
|
||||||
|
|
||||||
FATAL("out_buf is still too small after resizing in custom mutator.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
py_value = ((py_mutator_t *)py_mutator)->scratch_buf;
|
|
||||||
py_out_buf_size = ((py_mutator_t *)py_mutator)->scratch_size;
|
|
||||||
((py_mutator_t *)py_mutator)->scratch_buf = NULL;
|
|
||||||
py_out_buf_size = 0;
|
|
||||||
|
|
||||||
memcpy(out_buf, PyByteArray_AsString(py_value), py_out_buf_size);
|
|
||||||
Py_DECREF(py_value);
|
|
||||||
return py_out_buf_size;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
py_args = PyTuple_New(1);
|
py_args = PyTuple_New(1);
|
||||||
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
||||||
if (!py_value) {
|
if (!py_value) {
|
||||||
|
|
||||||
Py_DECREF(py_args);
|
Py_DECREF(py_args);
|
||||||
FATAL("Failed to convert arguments");
|
FATAL("Failed to convert arguments in custom pre_save");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,25 +363,26 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 *out_buf,
|
|||||||
if (py_value != NULL) {
|
if (py_value != NULL) {
|
||||||
|
|
||||||
py_out_buf_size = PyByteArray_Size(py_value);
|
py_out_buf_size = PyByteArray_Size(py_value);
|
||||||
if (py_out_buf_size > out_buf_size) {
|
|
||||||
|
if (py_out_buf_size > py->pre_save_size) {
|
||||||
|
|
||||||
/* Not enough space!
|
/* Not enough space!
|
||||||
We will get called again right after resizing the buf.
|
Let's resize our buf */
|
||||||
Keep the references to our data for now. */
|
py->pre_save_buf = ck_realloc(py->pre_save_buf, py_out_buf_size);
|
||||||
((py_mutator_t *)py_mutator)->scratch_buf = py_value;
|
py->pre_save_size = py_out_buf_size;
|
||||||
((py_mutator_t *)py_mutator)->scratch_size = py_out_buf_size;
|
|
||||||
return py_out_buf_size;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(out_buf, PyByteArray_AsString(py_value), py_out_buf_size);
|
memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size);
|
||||||
Py_DECREF(py_value);
|
Py_DECREF(py_value);
|
||||||
|
|
||||||
|
*out_buf = py->pre_save_buf;
|
||||||
return py_out_buf_size;
|
return py_out_buf_size;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
FATAL("Call failed");
|
FATAL("Python custom mutator: pre_save call failed.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,47 +214,18 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
|
|||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
if (afl->mutator && afl->mutator->afl_custom_pre_save) {
|
if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
|
||||||
|
|
||||||
if (unlikely(afl->mutator->pre_save_size < len)) {
|
u8 *new_buf = NULL;
|
||||||
|
|
||||||
afl->mutator->pre_save_buf =
|
size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
|
||||||
ck_realloc(afl->mutator->pre_save_buf, len * sizeof(u8));
|
len, &new_buf);
|
||||||
afl->mutator->pre_save_size = len;
|
|
||||||
|
|
||||||
}
|
if (unlikely(new_size <= 0 || !new_buf))
|
||||||
|
FATAL("Custom_pre_save failed (ret: %ld)", new_size);
|
||||||
|
|
||||||
u8 buf_written = 0;
|
/* everything as planned. use the new data. */
|
||||||
while (!buf_written) {
|
ck_write(fd, new_buf, new_size, afl->fsrv.out_file);
|
||||||
|
|
||||||
buf_written = 1;
|
|
||||||
size_t new_size = afl->mutator->afl_custom_pre_save(
|
|
||||||
afl->mutator->data, mem, len, afl->mutator->pre_save_buf,
|
|
||||||
afl->mutator->pre_save_size);
|
|
||||||
|
|
||||||
if (unlikely(new_size) == 0) {
|
|
||||||
|
|
||||||
/* custom_pre_save wants us to use the old buf */
|
|
||||||
ck_write(fd, mem, len, afl->fsrv.out_file);
|
|
||||||
|
|
||||||
} else if (unlikely(new_size) > afl->mutator->pre_save_size) {
|
|
||||||
|
|
||||||
/* The custom func needs more space.
|
|
||||||
Realloc and call again. */
|
|
||||||
afl->mutator->pre_save_buf =
|
|
||||||
ck_realloc(afl->mutator->pre_save_buf, new_size * sizeof(u8));
|
|
||||||
afl->mutator->pre_save_size = new_size;
|
|
||||||
buf_written = 0;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* everything as planned. use the new data. */
|
|
||||||
ck_write(fd, afl->mutator->pre_save_buf, new_size, afl->fsrv.out_file);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -361,9 +361,9 @@ void show_stats(afl_state_t *afl) {
|
|||||||
|
|
||||||
/* Lord, forgive me this. */
|
/* Lord, forgive me this. */
|
||||||
|
|
||||||
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
|
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
|
||||||
" process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
|
" process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
|
||||||
" overall results " bSTG bH2 bH2 bRT "\n");
|
" overall results " bSTG bH2 bH2 bRT "\n");
|
||||||
|
|
||||||
if (afl->dumb_mode) {
|
if (afl->dumb_mode) {
|
||||||
|
|
||||||
@ -445,9 +445,9 @@ void show_stats(afl_state_t *afl) {
|
|||||||
" uniq hangs : " cRST "%-6s" bSTG bV "\n",
|
" uniq hangs : " cRST "%-6s" bSTG bV "\n",
|
||||||
time_tmp, tmp);
|
time_tmp, tmp);
|
||||||
|
|
||||||
SAYF(bVR bH bSTOP cCYA
|
SAYF(bVR bH bSTOP cCYA
|
||||||
" cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
|
" cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
|
||||||
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
|
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
|
||||||
|
|
||||||
/* This gets funny because we want to print several variable-length variables
|
/* This gets funny because we want to print several variable-length variables
|
||||||
together, but then cram them into a fixed-width field - so we need to
|
together, but then cram them into a fixed-width field - so we need to
|
||||||
@ -476,9 +476,9 @@ void show_stats(afl_state_t *afl) {
|
|||||||
|
|
||||||
SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
|
SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
|
||||||
|
|
||||||
SAYF(bVR bH bSTOP cCYA
|
SAYF(bVR bH bSTOP cCYA
|
||||||
" stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
|
" stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
|
||||||
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
|
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
|
||||||
|
|
||||||
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
|
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
|
||||||
((double)afl->queued_favored) * 100 / afl->queued_paths);
|
((double)afl->queued_favored) * 100 / afl->queued_paths);
|
||||||
@ -552,7 +552,7 @@ void show_stats(afl_state_t *afl) {
|
|||||||
|
|
||||||
/* Aaaalmost there... hold on! */
|
/* Aaaalmost there... hold on! */
|
||||||
|
|
||||||
SAYF(bVR bH cCYA bSTOP
|
SAYF(bVR bH cCYA bSTOP
|
||||||
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
|
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
|
||||||
" path geometry " bSTG bH5 bH2 bVL "\n");
|
" path geometry " bSTG bH5 bH2 bVL "\n");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user