about summary refs log tree commit diff
path: root/qemu_mode
diff options
context:
space:
mode:
authorhexcoder <hexcoder-@users.noreply.github.com>2021-05-31 19:18:24 +0200
committerGitHub <noreply@github.com>2021-05-31 19:18:24 +0200
commit97a1f89881878db9bd6b4cd666b3447a63818dcf (patch)
tree46e844356f7cf88c08f9f9907caa11656a24f416 /qemu_mode
parentb246de789105750558f3d6f884ba61e54cb98441 (diff)
parent1a2da67ed0505c9ac0aa1048ba3d607f3c1aa639 (diff)
downloadafl++-97a1f89881878db9bd6b4cd666b3447a63818dcf.tar.gz
Merge branch 'dev' into going_atomic
Diffstat (limited to 'qemu_mode')
-rw-r--r--qemu_mode/README.md27
-rw-r--r--qemu_mode/README.wine.md21
-rwxr-xr-xqemu_mode/build_qemu_support.sh5
-rw-r--r--qemu_mode/libqasan/hooks.c10
-rw-r--r--qemu_mode/libqasan/libqasan.c13
5 files changed, 53 insertions, 23 deletions
diff --git a/qemu_mode/README.md b/qemu_mode/README.md
index a14cbe64..d28479d9 100644
--- a/qemu_mode/README.md
+++ b/qemu_mode/README.md
@@ -110,22 +110,23 @@ takes priority over any included ranges or AFL_INST_LIBS.
 
 CompareCoverage is a sub-instrumentation with effects similar to laf-intel.
 
-The environment variable that enables QEMU CompareCoverage is AFL_COMPCOV_LEVEL.
-There is also ./libcompcov/ which implements CompareCoverage for *cmp functions
-(splitting memcmp, strncmp, etc. to make these conditions easier solvable by
-afl-fuzz).
+You have to set `AFL_PRELOAD=/path/to/libcompcov.so` together with
+setting the AFL_COMPCOV_LEVEL you want to enable it.
 
 AFL_COMPCOV_LEVEL=1 is to instrument comparisons with only immediate
-values / read-only memory. AFL_COMPCOV_LEVEL=2 instruments all
-comparison instructions and memory comparison functions when libcompcov
-is preloaded.
-AFL_COMPCOV_LEVEL=3 has the same effects of AFL_COMPCOV_LEVEL=2 but enables also
-the instrumentation of the floating-point comparisons on x86 and x86_64 (experimental).
+values / read-only memory.
+
+AFL_COMPCOV_LEVEL=2 instruments all comparison instructions and memory
+comparison functions when libcompcov is preloaded.
+
+AFL_COMPCOV_LEVEL=3 has the same effects of AFL_COMPCOV_LEVEL=2 but enables
+also the instrumentation of the floating-point comparisons on x86 and x86_64
+(experimental).
 
 Integer comparison instructions are currently instrumented only
 on the x86, x86_64, arm and aarch64 targets.
 
-Highly recommended.
+Recommended, but not as good as CMPLOG mode (see below).
 
 ## 8) CMPLOG mode
 
@@ -141,7 +142,7 @@ To enable it you must pass on the command line of afl-fuzz:
 
 ## 9) Wine mode
 
-AFL++ QEMU can use Wine to fuzz WIn32 PE binaries. Use the -W flag of afl-fuzz.
+AFL++ QEMU can use Wine to fuzz Win32 PE binaries. Use the -W flag of afl-fuzz.
 
 Note that some binaries require user interaction with the GUI and must be patched.
 
@@ -190,8 +191,8 @@ handlers of the target.
 
 ## 13) Gotchas, feedback, bugs
 
-If you need to fix up checksums or do other cleanup on mutated test cases, see
-utils/custom_mutators/ for a viable solution.
+If you need to fix up checksums or do other cleanups on mutated test cases, see
+`afl_custom_post_process` in custom_mutators/examples/example.c for a viable solution.
 
 Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate
 the "shadow VM" trick employed by the sanitizers and will probably just
diff --git a/qemu_mode/README.wine.md b/qemu_mode/README.wine.md
new file mode 100644
index 00000000..567901cd
--- /dev/null
+++ b/qemu_mode/README.wine.md
@@ -0,0 +1,21 @@
+# How to troubleshoot AFL++'s wine mode
+
+## 1) Debugging
+To turn on wine debugging use the `WINEDEBUG` environment variable, 
+e.g. `WINEDEBUG=+timestamp,+tid,+loaddll`. 
+
+## 2) LoadLibraryA workaround
+The forked process fails to load libraries loaded via `LoadLibrary` 
+if the load happens after the entry point (error code: 87). To resolve 
+this issue, one needs to load any external libraries before the fork happens.
+
+An early DLL load can be achieved by adding the DLL name into the `Import Directory`
+in the PE file. Such an entry can be added manually in any PE editor. 
+
+Alternativly, one can generate a `.lib` file from the DLL exports and link 
+them together with the harness to create an entry in the `Import Directory`. 
+Use `dumpbin /exports <filename>.dll` to extract the exports and paste the 
+exported function names into a `.def` file. Use `lib /def:<deffile> /OUT:<libfile>`
+to generate a `.lib` and add the library to the linker options. Once the usage of 
+an export is detected (`__declspec(dllimport)`), the
+linker adds the early DLL load.
\ No newline at end of file
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index 6436d43a..84f144be 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -9,7 +9,7 @@
 # TCG instrumentation and block chaining support by Andrea Biondo
 #                                    <andrea.biondo965@gmail.com>
 #
-# QEMU 3.1.1 port, TCG thread-safety, CompareCoverage and NeverZero
+# QEMU 5+ port, TCG thread-safety, CompareCoverage and NeverZero
 # counters by Andrea Fioraldi <andreafioraldi@gmail.com>
 #
 # Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
@@ -211,8 +211,9 @@ if [ "$STATIC" = "1" ]; then
 
   echo Building STATIC binary
 
+  # static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
   QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
-    --static \
+    --static --disable-pie \
     --extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
     "
 
diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c
index 0e6c3e08..c542521c 100644
--- a/qemu_mode/libqasan/hooks.c
+++ b/qemu_mode/libqasan/hooks.c
@@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "libqasan.h"
 #include "map_macro.h"
+#include <unistd.h>
+#include <sys/syscall.h>
 
-ssize_t (*__lq_libc_write)(int, const void *, size_t);
-ssize_t (*__lq_libc_read)(int, void *, size_t);
 char *(*__lq_libc_fgets)(char *, int, FILE *);
 int (*__lq_libc_atoi)(const char *);
 long (*__lq_libc_atol)(const char *);
@@ -37,8 +37,6 @@ void __libqasan_init_hooks(void) {
 
   __libqasan_init_malloc();
 
-  __lq_libc_write = ASSERT_DLSYM(write);
-  __lq_libc_read = ASSERT_DLSYM(read);
   __lq_libc_fgets = ASSERT_DLSYM(fgets);
   __lq_libc_atoi = ASSERT_DLSYM(atoi);
   __lq_libc_atol = ASSERT_DLSYM(atol);
@@ -52,7 +50,7 @@ ssize_t write(int fd, const void *buf, size_t count) {
 
   QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count);
   QASAN_LOAD(buf, count);
-  ssize_t r = __lq_libc_write(fd, buf, count);
+  ssize_t r = syscall(SYS_write, fd, buf, count);
   QASAN_DEBUG("\t\t = %zd\n", r);
 
   return r;
@@ -65,7 +63,7 @@ ssize_t read(int fd, void *buf, size_t count) {
 
   QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count);
   QASAN_STORE(buf, count);
-  ssize_t r = __lq_libc_read(fd, buf, count);
+  ssize_t r = syscall(SYS_read, fd, buf, count);
   QASAN_DEBUG("\t\t = %zd\n", r);
 
   return r;
diff --git a/qemu_mode/libqasan/libqasan.c b/qemu_mode/libqasan/libqasan.c
index 9fc4ef7a..d4742e3e 100644
--- a/qemu_mode/libqasan/libqasan.c
+++ b/qemu_mode/libqasan/libqasan.c
@@ -61,9 +61,19 @@ void __libqasan_print_maps(void) {
 
 }
 
-/*__attribute__((constructor))*/ void __libqasan_init() {
+int __libqasan_is_initialized = 0;
+
+__attribute__((constructor)) void __libqasan_init() {
+
+  if (__libqasan_is_initialized) return;
+  __libqasan_is_initialized = 1;
 
   __libqasan_init_hooks();
+  
+  if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH"))
+    __libqasan_hotpatch();
+
+  if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) __libqasan_hotpatch();
 
 #ifdef DEBUG
   __qasan_debug = getenv("QASAN_DEBUG") != NULL;
@@ -86,7 +96,6 @@ int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
   typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main");
 
   __libqasan_init();
-  if (getenv("AFL_INST_LIBS")) __libqasan_hotpatch();
 
   return orig(main, argc, argv, init, fini, rtld_fini, stack_end);