diff options
-rw-r--r-- | afl-fuzz.c | 26 | ||||
-rw-r--r-- | docs/ChangeLog | 3 | ||||
-rw-r--r-- | docs/binaryonly_fuzzing.txt | 115 |
3 files changed, 139 insertions, 5 deletions
diff --git a/afl-fuzz.c b/afl-fuzz.c index 484a351c..1e27cb34 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -88,6 +88,8 @@ u64 total_puppet_find = 0; u64 temp_puppet_find = 0; u64 most_time_key = 0; u64 most_time_puppet = 0; +u64 most_execs_key = 0; +u64 most_execs = 0; u64 old_hit_count = 0; int SPLICE_CYCLES_puppet; int limit_time_sig = 0; @@ -11344,18 +11346,21 @@ static void usage(u8* argv0) { " -n - fuzz without instrumentation (dumb mode)\n" " -x dir - optional fuzzer dictionary (see README)\n\n" + "Testing settings:\n" + " -s seed - use a fixed seed for the RNG\n" + " -V seconds - fuzz for a maximum total time of seconds then terminate\n" + " -E execs - fuzz for a maximum number of total executions then terminate\n\n" + "Other stuff:\n" " -T text - text banner to show on the screen\n" " -M / -S id - distributed mode (see parallel_fuzzing.txt)\n" " -C - crash exploration mode (the peruvian rabbit thing)\n" - " -V seconds - fuzz for a maximum total time of seconds then terminate\n" - " -s seed - use a fixed seed for the rng - important to testing\n" " -e ext - File extension for the temporarily generated test case\n\n" #ifdef USE_PYTHON "Compiled with Python 2.7 module support, see docs/python_mutators.txt\n" #endif - "For additional tips, please consult %s/README.\n\n", + "For additional tips, please consult %s/README\n\n", argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); @@ -12050,7 +12055,7 @@ int main(int argc, char** argv) { gettimeofday(&tv, &tz); init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Qe:p:s:V:L:")) > 0) + while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Qe:p:s:V:E:L:")) > 0) switch (opt) { @@ -12251,13 +12256,20 @@ int main(int argc, char** argv) { break; - case 'V': { + case 'V': { most_time_key = 1; if (sscanf(optarg, "%llu", &most_time_puppet) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -V"); } break; + case 'E': { + most_execs_key = 1; + if (sscanf(optarg, "%llu", &most_execs) < 1 || optarg[0] == '-') + FATAL("Bad syntax used for -E"); + } + break; + case 'L': { /* MOpt mode */ if (limit_time_sig) FATAL("Multiple -L options not supported"); @@ -12583,6 +12595,10 @@ int main(int argc, char** argv) { if (most_time_puppet * 1000 < cur_ms_lv - start_time) break; } + if (most_execs_key == 1) { + if (most_execs >= total_execs) + break; + } } if (queue_cur) show_stats(); diff --git a/docs/ChangeLog b/docs/ChangeLog index b4aec9ec..dca674a2 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -20,6 +20,7 @@ Version ++2.52d (tbd): - added MOpt (github.com/puppet-meteor/MOpt-AFL) mode - added never zero counters for afl-gcc and optional (because of an optimization issue in llvm < 9) for llvm_mode (AFL_LLVM_NEVER_ZERO=1) + - added a new doc about binary only fuzzing: docs/binaryonly_fuzzing.txt - more cpu power for afl-system-config - added forkserver patch to afl-tmin, makes it much faster (originally from github.com/nccgroup/TriforceAFL) @@ -30,6 +31,8 @@ Version ++2.52d (tbd): see docs/python_mutators.txt (originally by choller@mozilla) - added AFL_CAL_FAST for slow applications and AFL_DEBUG_CHILD_OUTPUT for debugging + - added -V time and -E execs option to better comparison runs, runs afl-fuzz + for a specific time/executions. - added a -s seed switch to allow afl run with a fixed initial seed that is not updated. this is good for performance and path discovery tests as the random numbers are deterministic then diff --git a/docs/binaryonly_fuzzing.txt b/docs/binaryonly_fuzzing.txt new file mode 100644 index 00000000..ed654e2a --- /dev/null +++ b/docs/binaryonly_fuzzing.txt @@ -0,0 +1,115 @@ + +Fuzzing binary-only programs with afl++ +======================================= + +afl++, libfuzzer and others are great if you have the source code, and +it allows for very fast and coverage guided fuzzing. + +However, if there is only the binary program and not source code available, +then standard afl++ (dumb mode) is not effective. + +The following is a description of how these can be fuzzed with afl++ + +!!!!! +DTLR: try DYNINST with afl-dyninst. If it produces too many crashes then + use afl -Q qemu_mode. +!!!!! + + +QEMU +---- +Qemu is the "native" solution to the program. +It is available in the ./qemu_mode/ directory and once compiled it can +be accessed by the afl-fuzz -Q command line option. +The speed decrease is at about 50% +It the easiest to use alternative and even works for cross-platform binaries. + +As it is included in afl++ this needs no URL. + + +DYNINST +------- +Dyninst is a binary instrumentation framework similar to Pintool and Dynamorio +(see far below). Howver whereas Pintool and Dynamorio work at runtime, dyninst +instruments the target at load time, and then let it run. +This is great for some things, e.g. fuzzing, and not so effective for others, +e.g. malware analysis. + +So what we can do with dyninst is taking every basic block, and put afl's +instrumention code in there - and then save the binary. +Afterwards we can just fuzz the newly saved target binary with afl-fuzz. +Sounds great? It is. The issue though - this is a non-trivial problem to +insert instructions, which changes addresses in the process space and that +everything still works afterwards. Hence more often than not binaries +crash when they are run. + +The speed decrease is about 25-35% + +So if dyninst works, its the best option available. Otherwise it just doesn't +work well. + +https://github.com/vanhauser-thc/afl-dyninst + + +INTEL-PT +-------- +The big issue with Intel's PT is the small buffer size and the complex +encoding of the debug information collected through PT. +This makes the decoding very CPU intensive, hence slow and using up twice +the CPU resources. So to fairly compare Intel PT based afl fuzzers with +native afl or afl qemu we need to calculate in the higher CPU resources used. +As a result, the overall speed decrease is about 85-90% + +there are two afl intel-pt implementations: + +1. https://github.com/junxzm1990/afl-pt + => this needs Ubuntu 14.04.05 without any updates and the 4.4 kernel. + +2. https://github.com/hunter-ht-2018/ptfuzzer + => this needs a 4.14 or 4.15 kernel. the "nopti" kernel boot option must + be used + + +CORESIGHT +--------- + +Coresight is the ARM answer to Intel's PT. +There is no implementation so far which handle coresight and getting +it working on an ARM Linux is very difficult due custom kernel building +on embedded systems is difficult. And finding one that has coresight in +the ARM chip is difficult too. +My guess is that it is slower than Qemu, but faster than Intel PT. +If anyone finds any coresight implemention for afl please ping me: +vh@thc.org + + +PIN & DYNAMORIO +--------------- + +Pintool and Dynamorio are dynamic instrumentation engines, and they can be +used for getting basic block information at runtime. +Pintool is only available for Intel x32/x64 on Linux, Mac OS and Windows +whereas Dynamorio is additionally available for ARM and AARCH64. +Dynamorio is also 10x faster than Pintool. + +The big issue with Dynamorio (and therefore Pintool too) is speed. +Dynamorio has a speed decrease of 98-99% +Pintool has a speed decrease of 99.5% + +Hence Dynamorio is the option to go for if everything fails, and Pintool +only if Dynamorio fails too. + +Dynamorio solutions: + https://github.com/vanhauser-thc/afl-dynamorio + https://github.com/mxmssh/drAFL + https://github.com/googleprojectzero/winafl/ <= very good but windows only + +Pintool solutions: + https://github.com/vanhauser-thc/afl-pin + https://github.com/mothran/aflpin + https://github.com/spinpx/afl_pin_mode <= only old Pintool version supported + + +That's it! +News, corrections, updates? +Email vh@thc.org |