From bdcbefb89e3cab4d014313b1fa53fd655f07bed8 Mon Sep 17 00:00:00 2001 From: Thomas HUET Date: Fri, 4 Sep 2015 05:42:07 +0200 Subject: [PATCH] 1.90b --- Makefile | 2 +- afl-fuzz.c | 4 ++-- docs/ChangeLog | 12 ++++++++++++ docs/README | 4 ++-- docs/perf_tips.txt | 31 +++++++++++++++++++------------ docs/sister_projects.txt | 2 +- llvm_mode/README.llvm | 6 ++++-- llvm_mode/afl-clang-fast.c | 12 ++++++++---- 8 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index cac830da..e6b769d5 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ # PROGNAME = afl -VERSION = 1.89b +VERSION = 1.90b PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin diff --git a/afl-fuzz.c b/afl-fuzz.c index d240e4ef..2192d4de 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -6609,7 +6609,7 @@ static void check_binary(u8* fname) { if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { - OKF("Persistent-mode binary detected."); + OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); no_var_check = 1; @@ -6617,7 +6617,7 @@ static void check_binary(u8* fname) { if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { - OKF("Deferred forkserver binary detected."); + OKF(cPIN "Deferred forkserver binary detected."); setenv(DEFER_ENV_VAR, "1", 1); } diff --git a/docs/ChangeLog b/docs/ChangeLog index 8979eaf0..f8c2bd98 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -16,6 +16,18 @@ Not sure if you should upgrade? The lowest currently recommended version is 1.76b. If you're stuck on an earlier release, it's strongly advisable to get on with the times. +-------------- +Version 1.90b: +-------------- + + - Fixed a minor typo spotted by Kai Zhao; and made several other minor updates + to docs. + + - Updated the project URL for python-afl. Requested by Jakub Wilk. + + - Fixed a potential problem with deferred mode signatures getting optimized + out by the linker (with --gc-sections). + -------------- Version 1.89b: -------------- diff --git a/docs/README b/docs/README index 6dd048ff..25dc0d0d 100644 --- a/docs/README +++ b/docs/README @@ -101,8 +101,8 @@ $ make clean all For C++ programs, you'd would also want to set CXX=/path/to/afl/afl-g++. The clang wrappers (afl-clang and afl-clang++) can be used in the same way; -clang users may opt to leverage a higher-performance instrumentation mode, too. -This is described in llvm_mode/README.llvm. +clang users may also opt to leverage a higher-performance instrumentation mode, +as described in llvm_mode/README.llvm. When testing libraries, you need to find or write a simple program that reads data from stdin or from a file and passes it to the tested library. In such a diff --git a/docs/perf_tips.txt b/docs/perf_tips.txt index daed221c..e7a8b13b 100644 --- a/docs/perf_tips.txt +++ b/docs/perf_tips.txt @@ -14,10 +14,10 @@ also make the fuzzing process dramatically less efficient in several other ways. To illustrate, let's say that you're randomly flipping bits in a file, one bit -at a time. If you flip bit #47, you will hit a security bug; flipping any -other bit just results in an invalid document. +at a time. Let's assume that if you flip bit #47, you will hit a security bug; +flipping any other bit just results in an invalid document. -If your starting test case is 100 bytes long, you will have a 71% chance of +Now, if your starting test case is 100 bytes long, you will have a 71% chance of triggering the bug within the first 1,000 execs - not bad! But if the test case is 1 kB long, the probability that we will randomly hit the right pattern in the same timeframe goes down to 11%. And if it has 10 kB of non-essential @@ -59,10 +59,13 @@ that this mode requires the use of clang and will not work with GCC. The LLVM mode also offers a "persistent", in-process fuzzing mode that can work well for certain types of self-contained libraries, and for fast targets, -can offer performance gains up to 5-10x. +can offer performance gains up to 5-10x; and a "deferred fork server" mode +that can offer huge benefits for programs with high startup overhead. Both +modes require you to edit the source code of the fuzzed program, but the +changes often amount to just strategically placing a single line or two. -4) Have a closer look at the binary ------------------------------------ +4) Profile and optimize the binary +---------------------------------- Check for any parameters or settings that obviously improve performance. For example, the djpeg utility that comes with IJG jpeg and libjpeg-turbo can be @@ -81,19 +84,21 @@ With some laid-back parsers, enabling "strict" mode (i.e., bailing out after first error) may result in smaller files and improved run time without sacrificing coverage; for example, for sqlite, you may want to specify -bail. -If you are still stumped, you can use strace -tt or an equivalent profiling -tool to see if the targeted binary is doing anything unnecessarily slow. +If the program is still too slow, you can use strace -tt or an equivalent +profiling tool to see if the targeted binary is doing anything silly. Sometimes, you can speed things up simply by specifying /dev/null as the config file, or disabling some compile-time features that aren't really needed for the job (try ./configure --help). One of the notoriously resource-consuming things would be calling other utilities via exec*(), popen(), system(), or -equivalent calls; for example, tar can invoke external decompression tools. +equivalent calls; for example, tar can invoke external decompression tools +when it decides that the input file is a compressed archive. + Some programs may also intentionally call sleep(), usleep(), or nanosleep(); vim is a good example of that. In programs that are slow due to unavoidable initialization overhead, you may want to try the LLVM deferred forkserver mode (see llvm_mode/README.llvm), -which can give you speed gains up to 10x, but needs to be used with care. +which can give you speed gains up to 10x, as mentioned above. Last but not least, if you are using ASAN and the performance is unacceptable, consider turning it off for now, and manually examining the generated corpus @@ -103,8 +108,10 @@ with an ASAN-enabled binary later on. -------------------------------- Instrument just the libraries you actually want to stress-test right now, one -at a time. Trying to simultaneously instrument glibc, zlib, gmp, OpenSSL, -and libxml2 to test a single program is an overkill. +at a time. Let the program use system-wide, non-instrumented libraries for +any functionality you don't actually want to fuzz. For example, in most +cases, it doesn't make to instrument libgmp just because you're testing a +crypto app that relies on it for bignum math. Beware of programs that come with oddball third-party libraries bundled with their source code (Spidermonkey is a good example of this). Check ./configure diff --git a/docs/sister_projects.txt b/docs/sister_projects.txt index f50509b1..6b6aad4e 100644 --- a/docs/sister_projects.txt +++ b/docs/sister_projects.txt @@ -16,7 +16,7 @@ Python AFL (Jakub Wilk) Allows fuzz-testing of Python programs. Uses custom instrumentation and its own forkserver. - https://bitbucket.org/jwilk/python-afl + http://jwilk.net/software/python-afl Go-fuzz (Dmitry Vyukov) ----------------------- diff --git a/llvm_mode/README.llvm b/llvm_mode/README.llvm index 6eebce4b..fc29922f 100644 --- a/llvm_mode/README.llvm +++ b/llvm_mode/README.llvm @@ -106,6 +106,8 @@ a location after: - The creation of any vital threads or child processes - since the forkserver can't clone them easily. + - The initialization of timers via setitimer() or equivalent calls. + - The creation of temporary files, network sockets, offset-sensitive file descriptors, and similar shared-state resources - but only provided that their state meaningfully influences the behavior of the program later on. @@ -150,13 +152,13 @@ of iterations before AFL will restart the process from scratch. This minimizes the impact of memory leaks and similar glitches; 1000 is a good starting point. A more detailed template is shown in ../experimental/persistent_demo/. -Similarly to the previous mode, the feature works only with afl-clang-gast; +Similarly to the previous mode, the feature works only with afl-clang-fast; #ifdef guards can be used to suppress it when using other compilers. Note that as with the previous mode, the feature is easy to misuse; if you do not reset the critical state fully, you may end up with false positives or waste a whole lot of CPU power doing nothing useful at all. Be particularly -wary of memory leaks. +wary of memory leaks and the state of file descriptors. When running in this mode, the execution paths will inherently vary a bit depending on whether the input loop is being entered for the first time or diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 0a221113..61c77ca1 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -179,12 +179,16 @@ static void edit_params(u32 argc, char** argv) { cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" - "({ static char _B[] __attribute__((used)) = \"" PERSIST_SIG "\"; " - "int __afl_persistent_loop(unsigned int); __afl_persistent_loop(_A); })"; + "({ static volatile char *_B __attribute__((used)); " + " _B = \"" PERSIST_SIG "\"; " + "int __afl_persistent_loop(unsigned int); " + "__afl_persistent_loop(_A); })"; cc_params[cc_par_cnt++] = "-D__AFL_INIT()=" - "do { static char _A[] __attribute__((used)) = \"" DEFER_SIG "\"; " - "void __afl_manual_init(void); __afl_manual_init(); } while (0)"; + "do { static volatile char *_A __attribute__((used)); " + " _A = \"" DEFER_SIG "\"; " + "void __afl_manual_init(void); " + "__afl_manual_init(); } while (0)"; if (maybe_linking) {