mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 02:58:08 +00:00
Add new APIs for the custom mutator
This commit is contained in:
@ -458,29 +458,83 @@ u8* (*post_handler)(u8* buf, u32* len);
|
|||||||
extern u8* cmplog_binary;
|
extern u8* cmplog_binary;
|
||||||
extern s32 cmplog_child_pid, cmplog_forksrv_pid;
|
extern s32 cmplog_child_pid, cmplog_forksrv_pid;
|
||||||
|
|
||||||
/* hooks for the custom mutator function */
|
/* Custom mutators */
|
||||||
/**
|
|
||||||
* Perform custom mutations on a given input
|
struct custom_mutator {
|
||||||
* @param data Input data to be mutated
|
const char* name;
|
||||||
* @param size Size of input data
|
void* dh;
|
||||||
* @param mutated_out Buffer to store the mutated input
|
|
||||||
* @param max_size Maximum size of the mutated output. The mutation must not
|
/* hooks for the custom mutator function */
|
||||||
* produce data larger than max_size.
|
|
||||||
* @param seed Seed used for the mutation. The mutation should produce the same
|
/**
|
||||||
* output given the same seed.
|
* Initialize the custom mutator.
|
||||||
* @return Size of the mutated output.
|
*
|
||||||
*/
|
* (Optional)
|
||||||
|
*/
|
||||||
|
u32 (*afl_custom_init)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform custom mutations on a given input
|
||||||
|
*
|
||||||
|
* (Required)
|
||||||
|
*
|
||||||
|
* @param[in] data Input data to be mutated
|
||||||
|
* @param[in] size Size of input data
|
||||||
|
* @param[out] mutated_out Buffer to store the mutated input
|
||||||
|
* @param[in] max_size Maximum size of the mutated output. The mutation must not
|
||||||
|
* produce data larger than max_size.
|
||||||
|
* @param[in] seed Seed used for the mutation. The mutation should produce the
|
||||||
|
* same output given the same seed.
|
||||||
|
* @return Size of the mutated output.
|
||||||
|
*/
|
||||||
|
size_t (*afl_custom_fuzz)(u8* data, size_t size, u8* mutated_out,
|
||||||
|
size_t max_size, unsigned int seed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A post-processing function to use right before AFL writes the test case to
|
||||||
|
* disk in order to execute the target.
|
||||||
|
*
|
||||||
|
* (Optional) If this functionality is not needed, simply don't define this
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* @param[in] data Buffer containing the test case to be executed.
|
||||||
|
* @param[in] size Size of the test case.
|
||||||
|
* @param[out] new_data Buffer to store the test case after processing
|
||||||
|
* @return Size of data after processing.
|
||||||
|
*/
|
||||||
|
size_t (*afl_custom_pre_save)(u8* data, size_t size, u8** new_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: figure out what `trim` is
|
||||||
|
*
|
||||||
|
* (Optional)
|
||||||
|
*/
|
||||||
|
u32 (*afl_custom_init_trim)(u8*, size_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: figure out how `trim` works
|
||||||
|
*
|
||||||
|
* (Optional)
|
||||||
|
*
|
||||||
|
* @param[out] ret (TODO: finish here)
|
||||||
|
* @param[out] ret_len (TODO: finish here)
|
||||||
|
*/
|
||||||
|
void (*afl_custom_trim)(u8** ret, size_t* ret_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A post-processing function for the last trim operation.
|
||||||
|
*
|
||||||
|
* (Optional)
|
||||||
|
*
|
||||||
|
* @param success Indicates if the last trim operation was successful.
|
||||||
|
*/
|
||||||
|
u32 (*afl_custom_post_trim)(u8 success);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct custom_mutator* mutator;
|
||||||
|
|
||||||
size_t (*custom_mutator)(u8* data, size_t size, u8* mutated_out,
|
size_t (*custom_mutator)(u8* data, size_t size, u8* mutated_out,
|
||||||
size_t max_size, unsigned int seed);
|
size_t max_size, unsigned int seed);
|
||||||
/**
|
|
||||||
* A post-processing function to use right before AFL writes the test case to
|
|
||||||
* disk in order to execute the target. If this functionality is not needed,
|
|
||||||
* Simply don't define this function.
|
|
||||||
* @param data Buffer containing the test case to be executed.
|
|
||||||
* @param size Size of the test case.
|
|
||||||
* @param new_data Buffer to store the test case after processing
|
|
||||||
* @return Size of data after processing.
|
|
||||||
*/
|
|
||||||
size_t (*pre_save_handler)(u8* data, size_t size, u8** new_data);
|
size_t (*pre_save_handler)(u8* data, size_t size, u8** new_data);
|
||||||
|
|
||||||
/* Interesting values, as per config.h */
|
/* Interesting values, as per config.h */
|
||||||
@ -524,9 +578,10 @@ enum {
|
|||||||
|
|
||||||
/* 00 */ PY_FUNC_INIT,
|
/* 00 */ PY_FUNC_INIT,
|
||||||
/* 01 */ PY_FUNC_FUZZ,
|
/* 01 */ PY_FUNC_FUZZ,
|
||||||
/* 02 */ PY_FUNC_INIT_TRIM,
|
/* 02 */ PY_FUNC_PRE_SAVE,
|
||||||
/* 03 */ PY_FUNC_POST_TRIM,
|
/* 03 */ PY_FUNC_INIT_TRIM,
|
||||||
/* 04 */ PY_FUNC_TRIM,
|
/* 04 */ PY_FUNC_POST_TRIM,
|
||||||
|
/* 05 */ PY_FUNC_TRIM,
|
||||||
PY_FUNC_COUNT
|
PY_FUNC_COUNT
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -537,11 +592,18 @@ extern PyObject* py_functions[PY_FUNC_COUNT];
|
|||||||
|
|
||||||
/**** Prototypes ****/
|
/**** Prototypes ****/
|
||||||
|
|
||||||
|
/* Custom mutators */
|
||||||
|
void setup_custom_mutator(void);
|
||||||
|
void destroy_custom_mutator(void);
|
||||||
|
void load_custom_mutator(const char*);
|
||||||
|
void load_custom_mutator_py(const char*);
|
||||||
|
|
||||||
/* Python */
|
/* Python */
|
||||||
#ifdef USE_PYTHON
|
#ifdef USE_PYTHON
|
||||||
int init_py();
|
int init_py();
|
||||||
void finalize_py();
|
void finalize_py();
|
||||||
void fuzz_py(char*, size_t, char*, size_t, char**, size_t*);
|
void fuzz_py(char*, size_t, char*, size_t, char**, size_t*);
|
||||||
|
size_t pre_save_py(u8* data, size_t size, u8** new_data);
|
||||||
u32 init_trim_py(char*, size_t);
|
u32 init_trim_py(char*, size_t);
|
||||||
u32 post_trim_py(char);
|
u32 post_trim_py(char);
|
||||||
void trim_py(char**, size_t*);
|
void trim_py(char**, size_t*);
|
||||||
@ -628,7 +690,6 @@ u8 fuzz_one(char**);
|
|||||||
void bind_to_free_cpu(void);
|
void bind_to_free_cpu(void);
|
||||||
#endif
|
#endif
|
||||||
void setup_post(void);
|
void setup_post(void);
|
||||||
void setup_custom_mutator(void);
|
|
||||||
void read_testcases(void);
|
void read_testcases(void);
|
||||||
void perform_dry_run(char**);
|
void perform_dry_run(char**);
|
||||||
void pivot_inputs(void);
|
void pivot_inputs(void);
|
||||||
|
@ -255,6 +255,9 @@ u8 *(*post_handler)(u8 *buf, u32 *len);
|
|||||||
u8 *cmplog_binary;
|
u8 *cmplog_binary;
|
||||||
s32 cmplog_child_pid, cmplog_forksrv_pid;
|
s32 cmplog_child_pid, cmplog_forksrv_pid;
|
||||||
|
|
||||||
|
/* Custom mutator */
|
||||||
|
struct custom_mutator* mutator;
|
||||||
|
|
||||||
/* hooks for the custom mutator function */
|
/* hooks for the custom mutator function */
|
||||||
size_t (*custom_mutator)(u8 *data, size_t size, u8 *mutated_out,
|
size_t (*custom_mutator)(u8 *data, size_t size, u8 *mutated_out,
|
||||||
size_t max_size, unsigned int seed);
|
size_t max_size, unsigned int seed);
|
||||||
|
@ -296,34 +296,6 @@ void setup_post(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_custom_mutator(void) {
|
|
||||||
|
|
||||||
void* dh;
|
|
||||||
u8* fn = getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
|
|
||||||
|
|
||||||
if (!fn) return;
|
|
||||||
|
|
||||||
if (limit_time_sig)
|
|
||||||
FATAL(
|
|
||||||
"MOpt and custom mutator are mutually exclusive. We accept pull "
|
|
||||||
"requests that integrates MOpt with the optional mutators "
|
|
||||||
"(custom/radamsa/redquenn/...).");
|
|
||||||
|
|
||||||
ACTF("Loading custom mutator library from '%s'...", fn);
|
|
||||||
|
|
||||||
dh = dlopen(fn, RTLD_NOW);
|
|
||||||
if (!dh) FATAL("%s", dlerror());
|
|
||||||
|
|
||||||
custom_mutator = dlsym(dh, "afl_custom_mutator");
|
|
||||||
if (!custom_mutator) FATAL("Symbol 'afl_custom_mutator' not found.");
|
|
||||||
|
|
||||||
pre_save_handler = dlsym(dh, "afl_pre_save_handler");
|
|
||||||
// if (!pre_save_handler) WARNF("Symbol 'afl_pre_save_handler' not found.");
|
|
||||||
|
|
||||||
OKF("Custom mutator installed successfully.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shuffle an array of pointers. Might be slightly biased. */
|
/* Shuffle an array of pointers. Might be slightly biased. */
|
||||||
|
|
||||||
static void shuffle_ptrs(void** ptrs, u32 cnt) {
|
static void shuffle_ptrs(void** ptrs, u32 cnt) {
|
||||||
|
149
src/afl-fuzz-mutators.c
Normal file
149
src/afl-fuzz-mutators.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
american fuzzy lop++ - custom mutators related routines
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
Originally written by Shengtuo Hu
|
||||||
|
|
||||||
|
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||||
|
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||||
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
|
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at:
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
This is the real deal: the program takes an instrumented binary and
|
||||||
|
attempts a variety of basic fuzzing tricks, paying close attention to
|
||||||
|
how they affect the execution path.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "afl-fuzz.h"
|
||||||
|
|
||||||
|
void setup_custom_mutator(void) {
|
||||||
|
|
||||||
|
u8* fn = getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
|
||||||
|
|
||||||
|
if (fn) {
|
||||||
|
if (limit_time_sig)
|
||||||
|
FATAL(
|
||||||
|
"MOpt and custom mutator are mutually exclusive. We accept pull "
|
||||||
|
"requests that integrates MOpt with the optional mutators "
|
||||||
|
"(custom/radamsa/redquenn/...).");
|
||||||
|
|
||||||
|
load_custom_mutator(fn);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_PYTHON
|
||||||
|
if (init_py()) FATAL("Failed to initialize Python module");
|
||||||
|
|
||||||
|
// u8* module_name = getenv("AFL_PYTHON_MODULE");
|
||||||
|
// if (py_module && module_name)
|
||||||
|
// load_custom_mutator_py(module_name);
|
||||||
|
#else
|
||||||
|
if (getenv("AFL_PYTHON_MODULE"))
|
||||||
|
FATAL("Your AFL binary was built without Python support");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_custom_mutator(void) {
|
||||||
|
|
||||||
|
if (mutator) {
|
||||||
|
if (mutator->dh)
|
||||||
|
dlclose(mutator->dh);
|
||||||
|
else {
|
||||||
|
/* Python mutator */
|
||||||
|
#ifdef USE_PYTHON
|
||||||
|
finalize_py();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_free(mutator);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_custom_mutator(const char* fn) {
|
||||||
|
|
||||||
|
void* dh;
|
||||||
|
mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||||
|
|
||||||
|
mutator->name = fn;
|
||||||
|
ACTF("Loading custom mutator library from '%s'...", fn);
|
||||||
|
|
||||||
|
dh = dlopen(fn, RTLD_NOW);
|
||||||
|
if (!mutator->dh) FATAL("%s", dlerror());
|
||||||
|
mutator->dh = dh;
|
||||||
|
|
||||||
|
/* Mutator */
|
||||||
|
/* "afl_custom_init", optional */
|
||||||
|
mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
|
||||||
|
if (!mutator->afl_custom_init)
|
||||||
|
WARNF("Symbol 'afl_custom_init' not found.");
|
||||||
|
|
||||||
|
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
|
||||||
|
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
|
||||||
|
if (!mutator->afl_custom_fuzz) {
|
||||||
|
/* Try "afl_custom_mutator" for backward compatibility */
|
||||||
|
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
|
||||||
|
|
||||||
|
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
|
||||||
|
if (!mutator->afl_custom_fuzz) {
|
||||||
|
FATAL("Symbol 'afl_custom_mutator' not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "afl_custom_pre_save", optional */
|
||||||
|
mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
|
||||||
|
if (!mutator->afl_custom_pre_save)
|
||||||
|
WARNF("Symbol 'afl_custom_pre_save' not found.");
|
||||||
|
|
||||||
|
/* "afl_custom_init_trim", optional */
|
||||||
|
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
||||||
|
if (!mutator->afl_custom_init_trim)
|
||||||
|
WARNF("Symbol 'afl_custom_init_trim' not found.");
|
||||||
|
|
||||||
|
/* "afl_custom_trim", optional */
|
||||||
|
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
|
||||||
|
if (!mutator->afl_custom_trim)
|
||||||
|
WARNF("Symbol 'afl_custom_trim' not found.");
|
||||||
|
|
||||||
|
/* "afl_custom_post_trim", optional */
|
||||||
|
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
|
||||||
|
if (!mutator->afl_custom_post_trim)
|
||||||
|
WARNF("Symbol 'afl_custom_post_trim' not found.");
|
||||||
|
|
||||||
|
OKF("Custom mutator '%s' installed successfully.", fn);
|
||||||
|
|
||||||
|
/* Initialize the custom mutator */
|
||||||
|
if (mutator->afl_custom_init)
|
||||||
|
mutator->afl_custom_init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// void load_custom_mutator_py(const char* module_name) {
|
||||||
|
|
||||||
|
// mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||||
|
|
||||||
|
// mutator->name = module_name;
|
||||||
|
// ACTF("Loading Python mutator library from '%s'...", module_name);
|
||||||
|
|
||||||
|
// /* Initialize of the Python mutator has been invoked in "init_py()" */
|
||||||
|
// mutator->afl_custom_init = NULL;
|
||||||
|
// mutator->afl_custom_fuzz = fuzz_py;
|
||||||
|
// mutator->afl_custom_pre_save = pre_save_py;
|
||||||
|
// mutator->afl_custom_init_trim = init_trim_py;
|
||||||
|
// mutator->afl_custom_trim = trim_py;
|
||||||
|
// mutator->afl_custom_post_trim = post_trim_py;
|
||||||
|
|
||||||
|
// OKF("Python mutator '%s' installed successfully.", module_name);
|
||||||
|
|
||||||
|
// }
|
@ -55,6 +55,8 @@ int init_py() {
|
|||||||
u8 py_notrim = 0, py_idx;
|
u8 py_notrim = 0, py_idx;
|
||||||
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
|
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
|
||||||
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
||||||
|
py_functions[PY_FUNC_PRE_SAVE] =
|
||||||
|
PyObject_GetAttrString(py_module, "pre_save");
|
||||||
py_functions[PY_FUNC_INIT_TRIM] =
|
py_functions[PY_FUNC_INIT_TRIM] =
|
||||||
PyObject_GetAttrString(py_module, "init_trim");
|
PyObject_GetAttrString(py_module, "init_trim");
|
||||||
py_functions[PY_FUNC_POST_TRIM] =
|
py_functions[PY_FUNC_POST_TRIM] =
|
||||||
|
@ -155,7 +155,7 @@ static void usage(u8* argv0, int more_help) {
|
|||||||
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
|
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
|
||||||
"AFL_BENCH_JUST_ONE: run the target just once\n"
|
"AFL_BENCH_JUST_ONE: run the target just once\n"
|
||||||
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
|
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
|
||||||
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_mutator() to mutate inputs\n"
|
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
|
||||||
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
|
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
|
||||||
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
|
"AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
|
||||||
"AFL_PYTHON_ONLY: skip AFL++'s own mutators\n"
|
"AFL_PYTHON_ONLY: skip AFL++'s own mutators\n"
|
||||||
@ -864,13 +864,6 @@ int main(int argc, char** argv, char** envp) {
|
|||||||
|
|
||||||
setup_dirs_fds();
|
setup_dirs_fds();
|
||||||
|
|
||||||
#ifdef USE_PYTHON
|
|
||||||
if (init_py()) FATAL("Failed to initialize Python module");
|
|
||||||
#else
|
|
||||||
if (getenv("AFL_PYTHON_MODULE"))
|
|
||||||
FATAL("Your AFL binary was built without Python support");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setup_cmdline_file(argv + optind);
|
setup_cmdline_file(argv + optind);
|
||||||
|
|
||||||
read_testcases();
|
read_testcases();
|
||||||
@ -1147,13 +1140,10 @@ stop_fuzzing:
|
|||||||
destroy_extras();
|
destroy_extras();
|
||||||
ck_free(target_path);
|
ck_free(target_path);
|
||||||
ck_free(sync_id);
|
ck_free(sync_id);
|
||||||
|
destroy_custom_mutator();
|
||||||
|
|
||||||
alloc_report();
|
alloc_report();
|
||||||
|
|
||||||
#ifdef USE_PYTHON
|
|
||||||
finalize_py();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
OKF("We're done here. Have a nice day!\n");
|
OKF("We're done here. Have a nice day!\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
|
Reference in New Issue
Block a user