about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--examples/README.md2
-rw-r--r--examples/persistent_mode/Makefile10
-rw-r--r--examples/persistent_mode/persistent_demo.c112
-rw-r--r--examples/persistent_mode/persistent_demo_new.c117
-rw-r--r--examples/persistent_mode/test-instr.c69
-rw-r--r--instrumentation/README.gcc_plugin.md2
-rw-r--r--instrumentation/README.persistent_mode.md9
-rwxr-xr-xtest/test-gcc-plugin.sh2
-rwxr-xr-xtest/test-llvm-lto.sh2
-rwxr-xr-xtest/test-llvm.sh2
10 files changed, 320 insertions, 7 deletions
diff --git a/examples/README.md b/examples/README.md
index 46a92c6e..7dd70d6a 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -39,7 +39,7 @@ Here's a quick overview of the stuff you can find in this directory:
 
   - libpng_no_checksum   - a sample patch for removing CRC checks in libpng.
 
-  - persistent_demo      - an example of how to use the LLVM persistent process
+  - persistent_mode      - an example of how to use the LLVM persistent process
                            mode to speed up certain fuzzing jobs.
 
   - socket_fuzzing       - a LD_PRELOAD library 'redirects' a socket to stdin
diff --git a/examples/persistent_mode/Makefile b/examples/persistent_mode/Makefile
new file mode 100644
index 00000000..6fa1c30e
--- /dev/null
+++ b/examples/persistent_mode/Makefile
@@ -0,0 +1,10 @@
+all:
+	afl-clang-fast -o persistent_demo persistent_demo.c
+	afl-clang-fast -o persistent_demo_new persistent_demo_new.c
+	AFL_DONT_OPTIMIZE=1 afl-clang-fast -o test-instr test-instr.c
+
+document:
+	AFL_DONT_OPTIMIZE=1 afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c
+
+clean:
+	rm -f persistent_demo persistent_demo_new test-instr
diff --git a/examples/persistent_mode/persistent_demo.c b/examples/persistent_mode/persistent_demo.c
new file mode 100644
index 00000000..4cedc32c
--- /dev/null
+++ b/examples/persistent_mode/persistent_demo.c
@@ -0,0 +1,112 @@
+/*
+   american fuzzy lop++ - persistent mode example
+   --------------------------------------------
+
+   Originally written by Michal Zalewski
+
+   Copyright 2015 Google Inc. 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 file demonstrates the high-performance "persistent mode" that may be
+   suitable for fuzzing certain fast and well-behaved libraries, provided that
+   they are stateless or that their internal state can be easily reset
+   across runs.
+
+   To make this work, the library and this shim need to be compiled in LLVM
+   mode using afl-clang-fast (other compiler wrappers will *not* work).
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+/* Main entry point. */
+
+int main(int argc, char **argv) {
+
+  ssize_t len;                               /* how much input did we read? */
+  char buf[100]; /* Example-only buffer, you'd replace it with other global or
+                    local variables appropriate for your use case. */
+
+  /* The number passed to __AFL_LOOP() controls the maximum number of
+     iterations before the loop exits and the program is allowed to
+     terminate normally. This limits the impact of accidental memory leaks
+     and similar hiccups. */
+
+  __AFL_INIT();
+  while (__AFL_LOOP(1000)) {
+
+    /*** PLACEHOLDER CODE ***/
+
+    /* STEP 1: Fully re-initialize all critical variables. In our example, this
+               involves zeroing buf[], our input buffer. */
+
+    memset(buf, 0, 100);
+
+    /* STEP 2: Read input data. When reading from stdin, no special preparation
+               is required. When reading from a named file, you need to close
+               the old descriptor and reopen the file first!
+
+               Beware of reading from buffered FILE* objects such as stdin. Use
+               raw file descriptors or call fopen() / fdopen() in every pass. */
+
+    len = read(0, buf, 100);
+
+    /* STEP 3: This is where we'd call the tested library on the read data.
+               We just have some trivial inline code that faults on 'foo!'. */
+
+    /* do we have enough data? */
+    if (len < 8) continue;
+
+    if (buf[0] == 'f') {
+
+      printf("one\n");
+      if (buf[1] == 'o') {
+
+        printf("two\n");
+        if (buf[2] == 'o') {
+
+          printf("three\n");
+          if (buf[3] == '!') {
+
+            printf("four\n");
+            if (buf[4] == '!') {
+
+              printf("five\n");
+              if (buf[5] == '!') {
+
+                printf("six\n");
+                abort();
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+    /*** END PLACEHOLDER CODE ***/
+
+  }
+
+  /* Once the loop is exited, terminate normally - AFL will restart the process
+     when this happens, with a clean slate when it comes to allocated memory,
+     leftover file descriptors, etc. */
+
+  return 0;
+
+}
+
diff --git a/examples/persistent_mode/persistent_demo_new.c b/examples/persistent_mode/persistent_demo_new.c
new file mode 100644
index 00000000..a29792ff
--- /dev/null
+++ b/examples/persistent_mode/persistent_demo_new.c
@@ -0,0 +1,117 @@
+/*
+   american fuzzy lop++ - persistent mode example
+   --------------------------------------------
+
+   Originally written by Michal Zalewski
+
+   Copyright 2015 Google Inc. 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 file demonstrates the high-performance "persistent mode" that may be
+   suitable for fuzzing certain fast and well-behaved libraries, provided that
+   they are stateless or that their internal state can be easily reset
+   across runs.
+
+   To make this work, the library and this shim need to be compiled in LLVM
+   mode using afl-clang-fast (other compiler wrappers will *not* work).
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+/* this lets the source compile without afl-clang-fast/lto */
+#ifndef __AFL_FUZZ_TESTCASE_LEN
+
+ssize_t       fuzz_len;
+unsigned char fuzz_buf[1024000];
+
+  #define __AFL_FUZZ_TESTCASE_LEN fuzz_len
+  #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
+  #define __AFL_FUZZ_INIT() void sync(void);
+  #define __AFL_LOOP(x) \
+    ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0)
+  #define __AFL_INIT() sync()
+
+#endif
+
+__AFL_FUZZ_INIT();
+
+/* Main entry point. */
+
+int main(int argc, char **argv) {
+
+  ssize_t        len;                        /* how much input did we read? */
+  unsigned char *buf;                        /* test case buffer pointer    */
+
+  /* The number passed to __AFL_LOOP() controls the maximum number of
+     iterations before the loop exits and the program is allowed to
+     terminate normally. This limits the impact of accidental memory leaks
+     and similar hiccups. */
+
+  __AFL_INIT();
+  buf = __AFL_FUZZ_TESTCASE_BUF;  // this must be assigned before __AFL_LOOP!
+
+  while (__AFL_LOOP(1000)) {  // increase if you have good stability
+
+    len = __AFL_FUZZ_TESTCASE_LEN;  // do not use the macro directly in a call!
+
+    fprintf(stderr, "input: %zd \"%s\"\n", len, buf);
+
+    /* do we have enough data? */
+    if (len < 8) continue;
+
+    if (strcmp((char *)buf, "thisisateststring") == 0) printf("teststring\n");
+
+    if (buf[0] == 'f') {
+
+      printf("one\n");
+      if (buf[1] == 'o') {
+
+        printf("two\n");
+        if (buf[2] == 'o') {
+
+          printf("three\n");
+          if (buf[3] == '!') {
+
+            printf("four\n");
+            if (buf[4] == '!') {
+
+              printf("five\n");
+              if (buf[6] == '!') {
+
+                printf("six\n");
+                abort();
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+    /*** END PLACEHOLDER CODE ***/
+
+  }
+
+  /* Once the loop is exited, terminate normally - AFL will restart the process
+     when this happens, with a clean slate when it comes to allocated memory,
+     leftover file descriptors, etc. */
+
+  return 0;
+
+}
+
diff --git a/examples/persistent_mode/test-instr.c b/examples/persistent_mode/test-instr.c
new file mode 100644
index 00000000..a6188b22
--- /dev/null
+++ b/examples/persistent_mode/test-instr.c
@@ -0,0 +1,69 @@
+/*
+   american fuzzy lop++ - a trivial program to test the build
+   --------------------------------------------------------
+   Originally written by Michal Zalewski
+   Copyright 2014 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+__AFL_FUZZ_INIT();
+
+int main(int argc, char **argv) {
+
+  __AFL_INIT();
+  unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
+
+  while (__AFL_LOOP(2147483647)) {  // MAX_INT if you have 100% stability
+
+    unsigned int len = __AFL_FUZZ_TESTCASE_LEN;
+
+#ifdef _AFL_DOCUMENT_MUTATIONS
+    static unsigned int counter = 0;
+    char                fn[32];
+    sprintf(fn, "%09u:test-instr", counter);
+    int fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+    if (fd_doc >= 0) {
+
+      if (write(fd_doc, buf, len) != __afl_fuzz_len) {
+
+        fprintf(stderr, "write of mutation file failed: %s\n", fn);
+        unlink(fn);
+
+      }
+
+      close(fd_doc);
+
+    }
+
+    counter++;
+#endif
+
+    // fprintf(stderr, "len: %u\n", len);
+
+    if (!len) continue;
+
+    if (buf[0] == '0')
+      printf("Looks like a zero to me!\n");
+    else if (buf[0] == '1')
+      printf("Pretty sure that is a one!\n");
+    else
+      printf("Neither one or zero? How quaint!\n");
+
+  }
+
+  return 0;
+
+}
+
diff --git a/instrumentation/README.gcc_plugin.md b/instrumentation/README.gcc_plugin.md
index 919801d1..6ccb5fd3 100644
--- a/instrumentation/README.gcc_plugin.md
+++ b/instrumentation/README.gcc_plugin.md
@@ -147,7 +147,7 @@ The numerical value specified within the loop controls the maximum number
 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 ../examples/persistent_demo/.
+A more detailed template is shown in ../examples/persistent_mode/.
 Similarly to the previous mode, the feature works only with afl-gcc-fast or
 afl-clang-fast; #ifdef guards can be used to suppress it when using other
 compilers.
diff --git a/instrumentation/README.persistent_mode.md b/instrumentation/README.persistent_mode.md
index e095f036..2fd7027d 100644
--- a/instrumentation/README.persistent_mode.md
+++ b/instrumentation/README.persistent_mode.md
@@ -23,15 +23,20 @@ __AFL_FUZZ_INIT();
 
 main() {
 
+  // anything else here, eg. command line arguments, initialization, etc.
+
 #ifdef __AFL_HAVE_MANUAL_CONTROL
   __AFL_INIT();
 #endif
 
   unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;  // must be after __AFL_INIT
+                                                 // and before __AFL_LOOP!
 
   while (__AFL_LOOP(10000)) {
 
-    int len = __AFL_FUZZ_TESTCASE_LEN;
+    int len = __AFL_FUZZ_TESTCASE_LEN;  // don't use the macro directly in a
+                                        // call!
+
     if (len < 8) continue;  // check for a required/useful minimum input length
 
     /* Setup function call, e.g. struct target *tmp = libtarget_init() */
@@ -169,7 +174,7 @@ the impact of memory leaks and similar glitches; 1000 is a good starting point,
 and going much higher increases the likelihood of hiccups without giving you
 any real performance benefits.
 
-A more detailed template is shown in ../examples/persistent_demo/.
+A more detailed template is shown in ../examples/persistent_mode/.
 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.
 
diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh
index b0ff2be0..8740eff5 100755
--- a/test/test-gcc-plugin.sh
+++ b/test/test-gcc-plugin.sh
@@ -94,7 +94,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
     CODE=1
   }
   rm -f test-compcov test.out instrumentlist.txt
-  ../afl-gcc-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  ../afl-gcc-fast -o test-persistent ../examples/persistent_mode/persistent_mode.c > /dev/null 2>&1
   test -e test-persistent && {
     echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
       $ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh
index 6b327633..bdb08559 100755
--- a/test/test-llvm-lto.sh
+++ b/test/test-llvm-lto.sh
@@ -57,7 +57,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
     CODE=1
   }
   rm -f test-compcov test.out instrumentlist.txt
-  ../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  ../afl-clang-lto -o test-persistent ../examples/persistent_mode/persistent_mode.c > /dev/null 2>&1
   test -e test-persistent && {
     echo foo | ../afl-showmap -m none -o /dev/null -q -r ./test-persistent && {
       $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly"
diff --git a/test/test-llvm.sh b/test/test-llvm.sh
index 7daac0f2..1480316a 100755
--- a/test/test-llvm.sh
+++ b/test/test-llvm.sh
@@ -209,7 +209,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
     INCOMPLETE=1
   }
   rm -rf errors test-cmplog in core.*
-  ../afl-clang-fast -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1
+  ../afl-clang-fast -o test-persistent ../examples/persistent_mode/persistent_mode.c > /dev/null 2>&1
   test -e test-persistent && {
     echo foo | ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
       $ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"