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 ProcessState
from tritondse import Program
from tritondse import CleLoader
from tritondse import Seed
from tritondse import SeedFormat
from tritondse import SymbolicExecutor
@ -16,7 +17,7 @@ from tritondse import SymbolicExplorator
#logging.basicConfig(level=logging.INFO)
is_debug = False
out_path = "out/tritondse/queue"
out_path = ""
input_file = None
prog = 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}, \
# ({repr(se.seed.content)})")
global count
global hasshes
global hashes
print('DEBUG - prehook')
if se.seed.hash not in hashes:
hashes.add(se.seed.hash)
filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
if not os.path.exists(filename):
if is_debug:
print('Creating queue input ' + filename)
with open(filename, 'wb') as file:
file.write(se.seed.content)
count += 1
else:
print('has hash: ' + se.seed.hash)
if input_file:
if is_debug:
print('Writing to ' + input_file + ' the content: ' + str(se.seed.content))
with open(input_file, 'wb') as file:
file.write(se.seed.content)
else:
print('no input!')
def init(seed):
global prog
global config
global dse
global out_path
global input_file
global is_debug
# Load the program (LIEF-based program loader).
prog = Program(os.environ['TRITON_DSE_TARGET'])
# Set the configuration.
prog = CleLoader(os.environ['AFL_CUSTOM_INFO_PROGRAM'])
# Process other configuration environment variables.
argv = None
try:
foo = os.environ['AFL_DEBUG']
@ -58,15 +69,42 @@ def init(seed):
except KeyError:
pass
try:
argv_list = os.environ['TRITON_DSE_TARGET_ARGV']
argv = argv_list.split()
foo = os.environ['AFL_CUSTOM_INFO_OUT']
out_path = foo + '/../tritondse/queue'
except KeyError:
pass
try:
foo = os.environ['TRITON_DSE_TARGET_INPUT']
foo = os.environ['AFL_CUSTOM_INFO_PROGRAM_INPUT']
input_file = foo
except KeyError:
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,
debug = is_debug,
pipe_stdout = is_debug,
@ -79,8 +117,6 @@ def init(seed):
dse = SymbolicExplorator(config, prog)
# Add callbacks.
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):

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:
`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
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_CUSTOM_MUTATOR_LIBRARY",
"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_CYCLE_SCHEDULES",
"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) {
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));
#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);
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);
setup_cmdline_file(afl, argv + optind);