diff options
-rwxr-xr-x | afl-wine-trace | 55 | ||||
-rw-r--r-- | docs/ChangeLog | 1 | ||||
-rw-r--r-- | docs/binaryonly_fuzzing.txt | 4 | ||||
-rw-r--r-- | include/afl-fuzz.h | 3 | ||||
-rw-r--r-- | include/common.h | 5 | ||||
-rw-r--r-- | src/afl-analyze.c | 88 | ||||
-rw-r--r-- | src/afl-common.c | 175 | ||||
-rw-r--r-- | src/afl-fuzz-globals.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 77 | ||||
-rw-r--r-- | src/afl-fuzz.c | 26 | ||||
-rw-r--r-- | src/afl-showmap.c | 86 | ||||
-rw-r--r-- | src/afl-tmin.c | 88 |
12 files changed, 330 insertions, 280 deletions
diff --git a/afl-wine-trace b/afl-wine-trace new file mode 100755 index 00000000..fa552051 --- /dev/null +++ b/afl-wine-trace @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import os +import sys +import pefile +import shutil + +if len(sys.argv) < 2: + print("[afl-wine-trace] usage: wine-cov binary [args...]\n") + exit(1) + +if os.getenv("AFL_PATH"): + my_dir = os.getenv("AFL_PATH") +else: + my_dir = os.path.dirname(os.path.abspath(__file__)) + +os.environ["WINELOADERNOEXEC"] = "1" + +pe = pefile.PE(sys.argv[1]) + +os.environ["AFL_ENTRYPOINT"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.AddressOfEntryPoint) +if not os.getenv("AFL_INST_LIBS"): + if "AFL_CODE_START" not in os.environ: + os.environ["AFL_CODE_START"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode) + if "AFL_CODE_END" not in os.environ: + os.environ["AFL_CODE_END"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode + pe.OPTIONAL_HEADER.SizeOfCode) + +if os.getenv("WINECOV_QEMU_PATH"): + qemu_path = os.getenv("WINECOV_QEMU_PATH") +elif os.path.exists(os.path.join(my_dir, "afl-qemu-trace")): + qemu_path = os.path.join(my_dir, "afl-qemu-trace") +else: + qemu_path = "qemu-" + if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]: + qemu_path += "x86_64" + elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]: + qemu_path += "i386" + else: + print ("[afl-wine-trace] unsupported architecture\n") + exit(1) + qemu_path = shutil.which(qemu_path) + +if os.getenv("WINECOV_WINE_PATH"): + wine_path = os.getenv("WINECOV_WINE_PATH") +else: + wine_path = "/usr/lib/wine/wine" + if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]: + wine_path += "64" + elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]: + pass + else: + print ("[wine-cov] unsuppoted architecture\n") + exit(1) + +os.execve(qemu_path, [qemu_path, wine_path] + sys.argv[1:], os.environ) diff --git a/docs/ChangeLog b/docs/ChangeLog index c1b401c9..4ea4e4b2 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -27,6 +27,7 @@ Version ++2.54d (dev): - removed compile warnings from python internal stuff - added man page for afl-clang-fast[++] - updated documentation + - Wine mode to run Win32 binaries with the QEMU instrumentation (-W) -------------------------- diff --git a/docs/binaryonly_fuzzing.txt b/docs/binaryonly_fuzzing.txt index 53361f5f..239fb4b0 100644 --- a/docs/binaryonly_fuzzing.txt +++ b/docs/binaryonly_fuzzing.txt @@ -26,6 +26,10 @@ It is the easiest to use alternative and even works for cross-platform binaries. As it is included in afl++ this needs no URL. +WINE+QEMU +--------- +Wine mode can run Win32 PE with the QEMU instrumentation. +It needs Wine, python3 and the pefile python package installed. UNICORN ------- diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f6874785..9536e06a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -241,7 +241,6 @@ extern u8 *in_dir, /* Input directory with test cases */ *file_extension, /* File extension */ *orig_cmdline, /* Original command line */ *doc_path, /* Path to documentation dir */ - *target_path, /* Path to target binary */ *out_file; /* File to fuzz, if any */ extern u32 exec_tmout; /* Configurable exec timeout (ms) */ @@ -294,6 +293,7 @@ extern u8 skip_deterministic, /* Skip deterministic stages? */ bitmap_changed, /* Time to update bitmap? */ qemu_mode, /* Running in QEMU mode? */ unicorn_mode, /* Running in Unicorn mode? */ + use_wine, /* Use WINE with QEMU mode */ skip_requested, /* Skip request, via SIGUSR1 */ run_over10m, /* Run time over 10 minutes? */ persistent_mode, /* Running in persistent mode? */ @@ -612,6 +612,7 @@ void fix_up_banner(u8*); void check_if_tty(void); void setup_signal_handlers(void); char** get_qemu_argv(u8*, char**, int); +char** get_wine_argv(u8*, char**, int); void save_cmdline(u32, char**); /**** Inline routines ****/ diff --git a/include/common.h b/include/common.h index 905830b5..c370044e 100644 --- a/include/common.h +++ b/include/common.h @@ -27,6 +27,11 @@ #define __AFLCOMMON_H #include "types.h" +extern u8 *target_path; /* Path to target binary */ + void detect_file_args(char **argv, u8 *prog_in); + +char** get_qemu_argv(u8* own_loc, char** argv, int argc); +char** get_wine_argv(u8* own_loc, char** argv, int argc); #endif diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 4b157973..3e15ca35 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -61,7 +61,6 @@ u8* trace_bits; /* SHM with instrumentation bitmap */ static u8 *in_file, /* Analyzer input test case */ *prog_in, /* Targeted program input file */ - *target_path, /* Path to target binary */ *doc_path; /* Path to docs */ static u8* in_data; /* Input data for analysis */ @@ -760,7 +759,8 @@ static void usage(u8* argv0) { " -t msec - timeout for each run (%d ms)\n" " -m megs - memory limit for child process (%d MB)\n" " -Q - use binary-only instrumentation (QEMU mode)\n" - " -U - use unicorn-based instrumentation (Unicorn mode)\n\n" + " -U - use unicorn-based instrumentation (Unicorn mode)\n" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n\n" "Analysis settings:\n\n" @@ -829,78 +829,19 @@ static void find_binary(u8* fname) { } -/* Fix up argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 * tmp, *cp, *rsl, *own_copy; - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - /* Now we need to actually find qemu for argv[0]. */ - - new_argv[2] = target_path; - new_argv[1] = "--"; - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else - - ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; - return new_argv; - - } - - FATAL("Unable to find 'afl-qemu-trace'."); - -} - /* Main entry point */ int main(int argc, char** argv) { s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0; + u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0, use_wine = 0; char** use_argv; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; SAYF(cCYA "afl-analyze" VERSION cRST " by <lcamtuf@google.com>\n"); - while ((opt = getopt(argc, argv, "+i:f:m:t:eQUh")) > 0) + while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) switch (opt) { @@ -989,6 +930,16 @@ int main(int argc, char** argv) { unicorn_mode = 1; break; + case 'W': /* Wine+QEMU mode */ + + if (use_wine) FATAL("Multiple -W options not supported"); + qemu_mode = 1; + use_wine = 1; + + if (!mem_limit_given) mem_limit = 0; + + break; + case 'h': usage(argv[0]); return -1; @@ -1011,9 +962,14 @@ int main(int argc, char** argv) { find_binary(argv[optind]); detect_file_args(argv + optind, prog_in); - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else + if (qemu_mode) { + + if (use_wine) + use_argv = get_wine_argv(argv[0], argv + optind, argc - optind); + else + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + + } else use_argv = argv + optind; SAYF("\n"); diff --git a/src/afl-common.c b/src/afl-common.c index 62722cb9..0d690831 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -35,6 +35,8 @@ #include <unistd.h> #endif +u8 *target_path; /* Path to target binary */ + void detect_file_args(char** argv, u8* prog_in) { u32 i = 0; @@ -95,3 +97,176 @@ void detect_file_args(char** argv, u8* prog_in) { } + +/* Rewrite argv for QEMU. */ + +char** get_qemu_argv(u8* own_loc, char** argv, int argc) { + + char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); + u8 * tmp, *cp, *rsl, *own_copy; + + memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); + + new_argv[2] = target_path; + new_argv[1] = "--"; + + /* Now we need to actually find the QEMU binary to put in argv[0]. */ + + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/afl-qemu-trace", tmp); + + if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); + + target_path = new_argv[0] = cp; + return new_argv; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + ck_free(own_copy); + + if (!access(cp, X_OK)) { + + target_path = new_argv[0] = cp; + return new_argv; + + } + + } else + + ck_free(own_copy); + + if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { + + target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); + return new_argv; + + } + + SAYF("\n" cLRD "[-] " cRST + "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be " + "built\n" + " separately by following the instructions in qemu_mode/README.qemu. " + "If you\n" + " already have the binary installed, you may need to specify " + "AFL_PATH in the\n" + " environment.\n\n" + + " Of course, even without QEMU, afl-fuzz can still work with " + "binaries that are\n" + " instrumented at compile time with afl-gcc. It is also possible to " + "use it as a\n" + " traditional \"dumb\" fuzzer by specifying '-n' in the command " + "line.\n"); + + FATAL("Failed to locate 'afl-qemu-trace'."); + +} + +/* Rewrite argv for Wine+QEMU. */ + +char** get_wine_argv(u8* own_loc, char** argv, int argc) { + + char** new_argv = ck_alloc(sizeof(char*) * (argc + 3)); + u8 * tmp, *cp, *rsl, *own_copy; + + memcpy(new_argv + 2, argv + 1, sizeof(char*) * argc); + + new_argv[1] = target_path; + + /* Now we need to actually find the QEMU binary to put in argv[0]. */ + + tmp = getenv("AFL_PATH"); + + if (tmp) { + + cp = alloc_printf("%s/afl-qemu-trace", tmp); + + if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); + + ck_free(cp); + + cp = alloc_printf("%s/afl-wine-trace", tmp); + + if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); + + target_path = new_argv[0] = cp; + return new_argv; + + } + + own_copy = ck_strdup(own_loc); + rsl = strrchr(own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + cp = alloc_printf("%s/afl-qemu-trace", own_copy); + ck_free(own_copy); + + if (!access(cp, X_OK)) { + + ck_free(cp); + + cp = alloc_printf("%s/afl-wine-trace", own_copy); + + if (!access(cp, X_OK)) { + + target_path = new_argv[0] = cp; + return new_argv; + + } + + } + + } else + + ck_free(own_copy); + + u8 *ncp = BIN_PATH "/afl-qemu-trace"; + + if (!access(ncp, X_OK)) { + + ncp = BIN_PATH "/afl-wine-trace"; + + if (!access(ncp, X_OK)) { + + target_path = new_argv[0] = ck_strdup(ncp); + return new_argv; + + } + + } + + SAYF("\n" cLRD "[-] " cRST + "Oops, unable to find the '%s' binary. The binary must be " + "built\n" + " separately by following the instructions in qemu_mode/README.qemu. " + "If you\n" + " already have the binary installed, you may need to specify " + "AFL_PATH in the\n" + " environment.\n\n" + + " Of course, even without QEMU, afl-fuzz can still work with " + "binaries that are\n" + " instrumented at compile time with afl-gcc. It is also possible to " + "use it as a\n" + " traditional \"dumb\" fuzzer by specifying '-n' in the command " + "line.\n", ncp); + + FATAL("Failed to locate '%s'.", ncp); + +} + + diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c index d457d28c..1358a1fb 100644 --- a/src/afl-fuzz-globals.c +++ b/src/afl-fuzz-globals.c @@ -74,7 +74,6 @@ u8 *in_dir, /* Input directory with test cases */ *file_extension, /* File extension */ *orig_cmdline; /* Original command line */ u8 *doc_path, /* Path to documentation dir */ - *target_path, /* Path to target binary */ *out_file; /* File to fuzz, if any */ u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */ @@ -115,6 +114,7 @@ u8 skip_deterministic, /* Skip deterministic stages? */ bitmap_changed = 1, /* Time to update bitmap? */ qemu_mode, /* Running in QEMU mode? */ unicorn_mode, /* Running in Unicorn mode? */ + use_wine, /* Use WINE with QEMU mode */ skip_requested, /* Skip request, via SIGUSR1 */ run_over10m, /* Run time over 10 minutes? */ persistent_mode, /* Running in persistent mode? */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 55464a36..e791fdde 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1728,7 +1728,7 @@ void check_binary(u8* fname) { } - if (getenv("AFL_SKIP_BIN_CHECK")) return; + if (getenv("AFL_SKIP_BIN_CHECK") || use_wine) return; /* Check for blatant user errors. */ @@ -1963,81 +1963,6 @@ void setup_signal_handlers(void) { } -/* Rewrite argv for QEMU. */ - -char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 * tmp, *cp, *rsl, *own_copy; - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - new_argv[2] = target_path; - new_argv[1] = "--"; - - /* Now we need to actually find the QEMU binary to put in argv[0]. */ - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else - - ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); - return new_argv; - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be " - "built\n" - " separately by following the instructions in qemu_mode/README.qemu. " - "If you\n" - " already have the binary installed, you may need to specify " - "AFL_PATH in the\n" - " environment.\n\n" - - " Of course, even without QEMU, afl-fuzz can still work with " - "binaries that are\n" - " instrumented at compile time with afl-gcc. It is also possible to " - "use it as a\n" - " traditional \"dumb\" fuzzer by specifying '-n' in the command " - "line.\n"); - - FATAL("Failed to locate 'afl-qemu-trace'."); - -} - /* Make a copy of the current command line. */ void save_cmdline(u32 argc, char** argv) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c2e18477..a2e3c873 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -53,7 +53,8 @@ static void usage(u8* argv0) { " -t msec - timeout for each run (auto-scaled, 50-%d ms)\n" " -m megs - memory limit for child process (%d MB)\n" " -Q - use binary-only instrumentation (QEMU mode)\n" - " -U - use Unicorn-based instrumentation (Unicorn mode)\n\n" + " -U - use unicorn-based instrumentation (Unicorn mode)\n" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n" " -L minutes - use MOpt(imize) mode and set the limit time for " "entering the\n" " pacemaker mode (minutes of no new paths, 0 = " @@ -131,7 +132,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:QUe:p:s:V:E:L:h")) > + while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:QUWe:p:s:V:E:L:h")) > 0) switch (opt) { @@ -369,6 +370,16 @@ int main(int argc, char** argv) { if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN; break; + + case 'W': /* Wine+QEMU mode */ + + if (use_wine) FATAL("Multiple -W options not supported"); + qemu_mode = 1; + use_wine = 1; + + if (!mem_limit_given) mem_limit = 0; + + break; case 'V': { @@ -709,9 +720,14 @@ int main(int argc, char** argv) { start_time = get_cur_time(); - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else + if (qemu_mode) { + + if (use_wine) + use_argv = get_wine_argv(argv[0], argv + optind, argc - optind); + else + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + + } else use_argv = argv + optind; perform_dry_run(use_argv); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index bf9306d5..0720a234 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -64,7 +64,6 @@ u8* trace_bits; /* SHM with instrumentation bitmap */ static u8 *out_file, /* Trace output file */ *doc_path, /* Path to docs */ - *target_path, /* Path to target binary */ *at_file; /* Substitution string for @@ */ static u32 exec_tmout; /* Exec timeout (ms) */ @@ -419,6 +418,7 @@ static void usage(u8* argv0) { " -m megs - memory limit for child process (%d MB)\n" " -Q - use binary-only instrumentation (QEMU mode)\n" " -U - use Unicorn-based instrumentation (Unicorn mode)\n" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n" " (Not necessary, here for consistency with other afl-* " "tools)\n\n" @@ -493,77 +493,18 @@ static void find_binary(u8* fname) { } -/* Fix up argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 * tmp, *cp, *rsl, *own_copy; - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - new_argv[2] = target_path; - new_argv[1] = "--"; - - /* Now we need to actually find qemu for argv[0]. */ - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else - - ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; - return new_argv; - - } - - FATAL("Unable to find 'afl-qemu-trace'."); - -} - /* Main entry point */ int main(int argc, char** argv) { s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0; + u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0, use_wine = 0; u32 tcnt = 0; char** use_argv; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - while ((opt = getopt(argc, argv, "+o:m:t:A:eqZQUbcrh")) > 0) + while ((opt = getopt(argc, argv, "+o:m:t:A:eqZQUWbcrh")) > 0) switch (opt) { @@ -671,6 +612,16 @@ int main(int argc, char** argv) { unicorn_mode = 1; break; + case 'W': /* Wine+QEMU mode */ + + if (use_wine) FATAL("Multiple -W options not supported"); + qemu_mode = 1; + use_wine = 1; + + if (!mem_limit_given) mem_limit = 0; + + break; + case 'b': /* Secret undocumented mode. Writes output in raw binary format @@ -719,9 +670,14 @@ int main(int argc, char** argv) { detect_file_args(argv + optind, at_file); - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else + if (qemu_mode) { + + if (use_wine) + use_argv = get_wine_argv(argv[0], argv + optind, argc - optind); + else + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + + } else use_argv = argv + optind; run_target(use_argv); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 8308d98d..fa9769b1 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -70,7 +70,6 @@ static u8* mask_bitmap; /* Mask for trace bits (-B) */ u8 *in_file, /* Minimizer input test case */ *output_file, /* Minimizer output file */ *out_file, /* Targeted program input file */ - *target_path, /* Path to target binary */ *doc_path; /* Path to docs */ s32 out_fd; /* Persistent fd for out_file */ @@ -934,7 +933,8 @@ static void usage(u8* argv0) { " -t msec - timeout for each run (%d ms)\n" " -m megs - memory limit for child process (%d MB)\n" " -Q - use binary-only instrumentation (QEMU mode)\n" - " -U - use Unicorn-based instrumentation (Unicorn mode)\n\n" + " -U - use unicorn-based instrumentation (Unicorn mode)\n" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n\n" " (Not necessary, here for consistency with other afl-* " "tools)\n\n" @@ -1006,65 +1006,6 @@ static void find_binary(u8* fname) { } -/* Fix up argv for QEMU. */ - -static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { - - char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); - u8 * tmp, *cp, *rsl, *own_copy; - - memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); - - /* Now we need to actually find qemu for argv[0]. */ - - new_argv[2] = target_path; - new_argv[1] = "--"; - - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); - - target_path = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - target_path = new_argv[0] = cp; - return new_argv; - - } - - } else - - ck_free(own_copy); - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; - return new_argv; - - } - - FATAL("Unable to find 'afl-qemu-trace'."); - -} - /* Read mask bitmap from file. This is for the -B option. */ static void read_bitmap(u8* fname) { @@ -1084,14 +1025,14 @@ static void read_bitmap(u8* fname) { int main(int argc, char** argv) { s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0; + u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0, use_wine = 0; char** use_argv; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; SAYF(cCYA "afl-tmin" VERSION cRST " by <lcamtuf@google.com>\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUh")) > 0) + while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWh")) > 0) switch (opt) { @@ -1192,6 +1133,16 @@ int main(int argc, char** argv) { unicorn_mode = 1; break; + case 'W': /* Wine+QEMU mode */ + + if (use_wine) FATAL("Multiple -W options not supported"); + qemu_mode = 1; + use_wine = 1; + + if (!mem_limit_given) mem_limit = 0; + + break; + case 'B': /* load bitmap */ /* This is a secret undocumented option! It is speculated to be useful @@ -1232,9 +1183,14 @@ int main(int argc, char** argv) { find_binary(argv[optind]); detect_file_args(argv + optind, out_file); - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else + if (qemu_mode) { + + if (use_wine) + use_argv = get_wine_argv(argv[0], argv + optind, argc - optind); + else + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + + } else use_argv = argv + optind; exact_mode = !!getenv("AFL_TMIN_EXACT"); |