better tritondse support

This commit is contained in:
vanhauser-thc
2023-05-10 16:09:18 +02:00
parent c97caa6e10
commit 70da0c2e40
4 changed files with 145 additions and 32 deletions

View File

@ -7,6 +7,7 @@ from tritondse import Config
from tritondse import CoverageStrategy from tritondse import CoverageStrategy
from tritondse import ProcessState from tritondse import ProcessState
from tritondse import Program from tritondse import Program
from tritondse import CleLoader
from tritondse import Seed from tritondse import Seed
from tritondse import SeedFormat from tritondse import SeedFormat
from tritondse import SymbolicExecutor from tritondse import SymbolicExecutor
@ -16,7 +17,7 @@ from tritondse import SymbolicExplorator
#logging.basicConfig(level=logging.INFO) #logging.basicConfig(level=logging.INFO)
is_debug = False is_debug = False
out_path = "out/tritondse/queue" out_path = ""
input_file = None input_file = None
prog = None prog = None
config = None config = None
@ -29,28 +30,38 @@ def pre_exec_hook(se: SymbolicExecutor, state: ProcessState):
#logging.info(f"[PRE-EXEC] Processing seed: {se.seed.hash}, \ #logging.info(f"[PRE-EXEC] Processing seed: {se.seed.hash}, \
# ({repr(se.seed.content)})") # ({repr(se.seed.content)})")
global count global count
global hasshes global hashes
print('DEBUG - prehook')
if se.seed.hash not in hashes: if se.seed.hash not in hashes:
hashes.add(se.seed.hash) hashes.add(se.seed.hash)
filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
if not os.path.exists(filename): if not os.path.exists(filename):
if is_debug:
print('Creating queue input ' + filename)
with open(filename, 'wb') as file: with open(filename, 'wb') as file:
file.write(se.seed.content) file.write(se.seed.content)
count += 1 count += 1
else:
print('has hash: ' + se.seed.hash)
if input_file: if input_file:
if is_debug:
print('Writing to ' + input_file + ' the content: ' + str(se.seed.content))
with open(input_file, 'wb') as file: with open(input_file, 'wb') as file:
file.write(se.seed.content) file.write(se.seed.content)
else:
print('no input!')
def init(seed): def init(seed):
global prog global prog
global config global config
global dse global dse
global out_path
global input_file global input_file
global is_debug global is_debug
# Load the program (LIEF-based program loader). # Load the program (LIEF-based program loader).
prog = Program(os.environ['TRITON_DSE_TARGET']) prog = CleLoader(os.environ['AFL_CUSTOM_INFO_PROGRAM'])
# Set the configuration. # Process other configuration environment variables.
argv = None argv = None
try: try:
foo = os.environ['AFL_DEBUG'] foo = os.environ['AFL_DEBUG']
@ -58,15 +69,42 @@ def init(seed):
except KeyError: except KeyError:
pass pass
try: try:
argv_list = os.environ['TRITON_DSE_TARGET_ARGV'] foo = os.environ['AFL_CUSTOM_INFO_OUT']
argv = argv_list.split() out_path = foo + '/../tritondse/queue'
except KeyError: except KeyError:
pass pass
try: try:
foo = os.environ['TRITON_DSE_TARGET_INPUT'] foo = os.environ['AFL_CUSTOM_INFO_PROGRAM_INPUT']
input_file = foo input_file = foo
except KeyError: except KeyError:
pass pass
try:
argv_list = os.environ['AFL_CUSTOM_INFO_PROGRAM_ARGV']
argv_tmp = [ os.environ['AFL_CUSTOM_INFO_PROGRAM'] ]
argv_tmp += argv_list.split()
argv = []
# now check for @@
for item in argv_tmp:
if "@@" in item:
input_file = out_path + '/../.input'
argv.append(input_file)
else:
argv.append(item)
except KeyError:
pass
# Create the output directory
os.makedirs(out_path, exist_ok=True)
# Debug
if is_debug:
print('DEBUG target: ' + os.environ['AFL_CUSTOM_INFO_PROGRAM'])
if argv:
print('DEBUG argv: ')
print(argv)
if input_file:
print('DEBUG input_file: ' + input_file)
print('DEBUG out_path: ' + out_path)
print('')
# Now set up TritonDSE
config = Config(coverage_strategy = CoverageStrategy.PATH, config = Config(coverage_strategy = CoverageStrategy.PATH,
debug = is_debug, debug = is_debug,
pipe_stdout = is_debug, pipe_stdout = is_debug,
@ -79,8 +117,6 @@ def init(seed):
dse = SymbolicExplorator(config, prog) dse = SymbolicExplorator(config, prog)
# Add callbacks. # Add callbacks.
dse.callback_manager.register_pre_execution_callback(pre_exec_hook) dse.callback_manager.register_pre_execution_callback(pre_exec_hook)
# Create the output directory
os.makedirs(out_path, exist_ok=True)
#def fuzz(buf, add_buf, max_size): #def fuzz(buf, add_buf, max_size):

View File

@ -304,6 +304,34 @@ Note: for some distributions, you might also need the package `python[3]-apt`.
In case your setup is different, set the necessary variables like this: In case your setup is different, set the necessary variables like this:
`PYTHON_INCLUDE=/path/to/python/include LDFLAGS=-L/path/to/python/lib make`. `PYTHON_INCLUDE=/path/to/python/include LDFLAGS=-L/path/to/python/lib make`.
### Helpers
For C/C++ custom mutators you get a pointer to `afl_state_t *afl` in the
`afl_custom_init()` which contains all information that you need.
Note that if you access it, you need to recompile your custom mutator if
you update AFL++ because the structure might have changed!
For mutators written in Python, Rust, GO, etc. there are a few environment
variables set to help you to get started:
`AFL_CUSTOM_INFO_PROGRAM` - the program name of the target that is executed.
If your custom mutator is used with modes like Qemu (`-Q`), this will still
contain the target program, not afl-qemu-trace.
`AFL_CUSTOM_INFO_PROGRAM_INPUT` - if the `-f` parameter is used with afl-fuzz
then this value is found in this environment variable.
`AFL_CUSTOM_INFO_PROGRAM_ARGV` - this contains the parameters given to the
target program and still has the `@@` identifier in there.
Note: If `AFL_CUSTOM_INFO_PROGRAM_INPUT` is empty and `AFL_CUSTOM_INFO_PROGRAM_ARGV`
is either empty or does not contain `@@` then the target gets the input via
`stdin`.
`AFL_CUSTOM_INFO_OUT` - This is the output directory for this fuzzer instance,
so if `afl-fuzz` was called with `-o out -S foobar`, then this will be set to
`out/foobar`.
### Custom Mutator Preparation ### Custom Mutator Preparation
For C/C++ mutators, the source code must be compiled as a shared object: For C/C++ mutators, the source code must be compiled as a shared object:

View File

@ -37,6 +37,10 @@ static char *afl_environment_variables[] = {
"AFL_CRASH_EXITCODE", "AFL_CRASH_EXITCODE",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT",
"AFL_CXX", "AFL_CXX",
"AFL_CYCLE_SCHEDULES", "AFL_CYCLE_SCHEDULES",
"AFL_DEBUG", "AFL_DEBUG",

View File

@ -1530,29 +1530,6 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
FATAL("Custom mutators are incompatible with MOpt (-L)");
}
u32 custom_fuzz = 0;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz) { custom_fuzz = 1; }
});
if (custom_fuzz) {
WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
}
}
if (afl->afl_env.afl_max_det_extras) { if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras); s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@ -1827,8 +1804,76 @@ int main(int argc, char **argv_orig, char **envp) {
printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536)); printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
#endif #endif
if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
}
if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
}
{
u8 envbuf[8096] = "", tmpbuf[8096] = "";
for (s32 i = optind + 1; i < argc; ++i) {
strcpy(tmpbuf, envbuf);
if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
!strchr(argv[i], '\'')) {
if (!strchr(argv[i], '\'')) {
snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
} else {
snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
}
} else {
snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
}
}
setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
}
setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
setup_custom_mutators(afl); setup_custom_mutators(afl);
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
FATAL("Custom mutators are incompatible with MOpt (-L)");
}
u32 custom_fuzz = 0;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz) { custom_fuzz = 1; }
});
if (custom_fuzz) {
WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
}
}
write_setup_file(afl, argc, argv); write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind); setup_cmdline_file(afl, argv + optind);