mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-12 01:58:17 +00:00
55
afl-wine-trace
Executable file
55
afl-wine-trace
Executable file
@ -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)
|
@ -27,6 +27,7 @@ Version ++2.54d (dev):
|
|||||||
- removed compile warnings from python internal stuff
|
- removed compile warnings from python internal stuff
|
||||||
- added man page for afl-clang-fast[++]
|
- added man page for afl-clang-fast[++]
|
||||||
- updated documentation
|
- updated documentation
|
||||||
|
- Wine mode to run Win32 binaries with the QEMU instrumentation (-W)
|
||||||
|
|
||||||
|
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -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.
|
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
|
UNICORN
|
||||||
-------
|
-------
|
||||||
|
@ -241,7 +241,6 @@ extern u8 *in_dir, /* Input directory with test cases */
|
|||||||
*file_extension, /* File extension */
|
*file_extension, /* File extension */
|
||||||
*orig_cmdline, /* Original command line */
|
*orig_cmdline, /* Original command line */
|
||||||
*doc_path, /* Path to documentation dir */
|
*doc_path, /* Path to documentation dir */
|
||||||
*target_path, /* Path to target binary */
|
|
||||||
*out_file; /* File to fuzz, if any */
|
*out_file; /* File to fuzz, if any */
|
||||||
|
|
||||||
extern u32 exec_tmout; /* Configurable exec timeout (ms) */
|
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? */
|
bitmap_changed, /* Time to update bitmap? */
|
||||||
qemu_mode, /* Running in QEMU mode? */
|
qemu_mode, /* Running in QEMU mode? */
|
||||||
unicorn_mode, /* Running in Unicorn mode? */
|
unicorn_mode, /* Running in Unicorn mode? */
|
||||||
|
use_wine, /* Use WINE with QEMU mode */
|
||||||
skip_requested, /* Skip request, via SIGUSR1 */
|
skip_requested, /* Skip request, via SIGUSR1 */
|
||||||
run_over10m, /* Run time over 10 minutes? */
|
run_over10m, /* Run time over 10 minutes? */
|
||||||
persistent_mode, /* Running in persistent mode? */
|
persistent_mode, /* Running in persistent mode? */
|
||||||
@ -612,6 +612,7 @@ void fix_up_banner(u8*);
|
|||||||
void check_if_tty(void);
|
void check_if_tty(void);
|
||||||
void setup_signal_handlers(void);
|
void setup_signal_handlers(void);
|
||||||
char** get_qemu_argv(u8*, char**, int);
|
char** get_qemu_argv(u8*, char**, int);
|
||||||
|
char** get_wine_argv(u8*, char**, int);
|
||||||
void save_cmdline(u32, char**);
|
void save_cmdline(u32, char**);
|
||||||
|
|
||||||
/**** Inline routines ****/
|
/**** Inline routines ****/
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
#define __AFLCOMMON_H
|
#define __AFLCOMMON_H
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
extern u8 *target_path; /* Path to target binary */
|
||||||
|
|
||||||
void detect_file_args(char **argv, u8 *prog_in);
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -61,7 +61,6 @@ u8* trace_bits; /* SHM with instrumentation bitmap */
|
|||||||
|
|
||||||
static u8 *in_file, /* Analyzer input test case */
|
static u8 *in_file, /* Analyzer input test case */
|
||||||
*prog_in, /* Targeted program input file */
|
*prog_in, /* Targeted program input file */
|
||||||
*target_path, /* Path to target binary */
|
|
||||||
*doc_path; /* Path to docs */
|
*doc_path; /* Path to docs */
|
||||||
|
|
||||||
static u8* in_data; /* Input data for analysis */
|
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"
|
" -t msec - timeout for each run (%d ms)\n"
|
||||||
" -m megs - memory limit for child process (%d MB)\n"
|
" -m megs - memory limit for child process (%d MB)\n"
|
||||||
" -Q - use binary-only instrumentation (QEMU mode)\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"
|
"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 */
|
/* Main entry point */
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
s32 opt;
|
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;
|
char** use_argv;
|
||||||
|
|
||||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||||
|
|
||||||
SAYF(cCYA "afl-analyze" VERSION cRST " by <lcamtuf@google.com>\n");
|
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) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -989,6 +930,16 @@ int main(int argc, char** argv) {
|
|||||||
unicorn_mode = 1;
|
unicorn_mode = 1;
|
||||||
break;
|
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':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1011,9 +962,14 @@ int main(int argc, char** argv) {
|
|||||||
find_binary(argv[optind]);
|
find_binary(argv[optind]);
|
||||||
detect_file_args(argv + optind, prog_in);
|
detect_file_args(argv + optind, prog_in);
|
||||||
|
|
||||||
if (qemu_mode)
|
if (qemu_mode) {
|
||||||
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
|
||||||
else
|
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;
|
use_argv = argv + optind;
|
||||||
|
|
||||||
SAYF("\n");
|
SAYF("\n");
|
||||||
|
175
src/afl-common.c
175
src/afl-common.c
@ -35,6 +35,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
u8 *target_path; /* Path to target binary */
|
||||||
|
|
||||||
void detect_file_args(char** argv, u8* prog_in) {
|
void detect_file_args(char** argv, u8* prog_in) {
|
||||||
|
|
||||||
u32 i = 0;
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ u8 *in_dir, /* Input directory with test cases */
|
|||||||
*file_extension, /* File extension */
|
*file_extension, /* File extension */
|
||||||
*orig_cmdline; /* Original command line */
|
*orig_cmdline; /* Original command line */
|
||||||
u8 *doc_path, /* Path to documentation dir */
|
u8 *doc_path, /* Path to documentation dir */
|
||||||
*target_path, /* Path to target binary */
|
|
||||||
*out_file; /* File to fuzz, if any */
|
*out_file; /* File to fuzz, if any */
|
||||||
|
|
||||||
u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */
|
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? */
|
bitmap_changed = 1, /* Time to update bitmap? */
|
||||||
qemu_mode, /* Running in QEMU mode? */
|
qemu_mode, /* Running in QEMU mode? */
|
||||||
unicorn_mode, /* Running in Unicorn mode? */
|
unicorn_mode, /* Running in Unicorn mode? */
|
||||||
|
use_wine, /* Use WINE with QEMU mode */
|
||||||
skip_requested, /* Skip request, via SIGUSR1 */
|
skip_requested, /* Skip request, via SIGUSR1 */
|
||||||
run_over10m, /* Run time over 10 minutes? */
|
run_over10m, /* Run time over 10 minutes? */
|
||||||
persistent_mode, /* Running in persistent mode? */
|
persistent_mode, /* Running in persistent mode? */
|
||||||
|
@ -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. */
|
/* 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. */
|
/* Make a copy of the current command line. */
|
||||||
|
|
||||||
void save_cmdline(u32 argc, char** argv) {
|
void save_cmdline(u32 argc, char** argv) {
|
||||||
|
@ -53,7 +53,8 @@ static void usage(u8* argv0) {
|
|||||||
" -t msec - timeout for each run (auto-scaled, 50-%d ms)\n"
|
" -t msec - timeout for each run (auto-scaled, 50-%d ms)\n"
|
||||||
" -m megs - memory limit for child process (%d MB)\n"
|
" -m megs - memory limit for child process (%d MB)\n"
|
||||||
" -Q - use binary-only instrumentation (QEMU mode)\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 "
|
" -L minutes - use MOpt(imize) mode and set the limit time for "
|
||||||
"entering the\n"
|
"entering the\n"
|
||||||
" pacemaker mode (minutes of no new paths, 0 = "
|
" pacemaker mode (minutes of no new paths, 0 = "
|
||||||
@ -131,7 +132,7 @@ int main(int argc, char** argv) {
|
|||||||
gettimeofday(&tv, &tz);
|
gettimeofday(&tv, &tz);
|
||||||
init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
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)
|
0)
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -369,6 +370,16 @@ int main(int argc, char** argv) {
|
|||||||
if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN;
|
if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN;
|
||||||
|
|
||||||
break;
|
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': {
|
case 'V': {
|
||||||
|
|
||||||
@ -709,9 +720,14 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
start_time = get_cur_time();
|
start_time = get_cur_time();
|
||||||
|
|
||||||
if (qemu_mode)
|
if (qemu_mode) {
|
||||||
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
|
||||||
else
|
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;
|
use_argv = argv + optind;
|
||||||
|
|
||||||
perform_dry_run(use_argv);
|
perform_dry_run(use_argv);
|
||||||
|
@ -64,7 +64,6 @@ u8* trace_bits; /* SHM with instrumentation bitmap */
|
|||||||
|
|
||||||
static u8 *out_file, /* Trace output file */
|
static u8 *out_file, /* Trace output file */
|
||||||
*doc_path, /* Path to docs */
|
*doc_path, /* Path to docs */
|
||||||
*target_path, /* Path to target binary */
|
|
||||||
*at_file; /* Substitution string for @@ */
|
*at_file; /* Substitution string for @@ */
|
||||||
|
|
||||||
static u32 exec_tmout; /* Exec timeout (ms) */
|
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"
|
" -m megs - memory limit for child process (%d MB)\n"
|
||||||
" -Q - use binary-only instrumentation (QEMU mode)\n"
|
" -Q - use binary-only instrumentation (QEMU mode)\n"
|
||||||
" -U - use Unicorn-based instrumentation (Unicorn 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-* "
|
" (Not necessary, here for consistency with other afl-* "
|
||||||
"tools)\n\n"
|
"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 */
|
/* Main entry point */
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
s32 opt;
|
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;
|
u32 tcnt = 0;
|
||||||
char** use_argv;
|
char** use_argv;
|
||||||
|
|
||||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
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) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -671,6 +612,16 @@ int main(int argc, char** argv) {
|
|||||||
unicorn_mode = 1;
|
unicorn_mode = 1;
|
||||||
break;
|
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':
|
case 'b':
|
||||||
|
|
||||||
/* Secret undocumented mode. Writes output in raw binary format
|
/* 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);
|
detect_file_args(argv + optind, at_file);
|
||||||
|
|
||||||
if (qemu_mode)
|
if (qemu_mode) {
|
||||||
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
|
||||||
else
|
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;
|
use_argv = argv + optind;
|
||||||
|
|
||||||
run_target(use_argv);
|
run_target(use_argv);
|
||||||
|
@ -70,7 +70,6 @@ static u8* mask_bitmap; /* Mask for trace bits (-B) */
|
|||||||
u8 *in_file, /* Minimizer input test case */
|
u8 *in_file, /* Minimizer input test case */
|
||||||
*output_file, /* Minimizer output file */
|
*output_file, /* Minimizer output file */
|
||||||
*out_file, /* Targeted program input file */
|
*out_file, /* Targeted program input file */
|
||||||
*target_path, /* Path to target binary */
|
|
||||||
*doc_path; /* Path to docs */
|
*doc_path; /* Path to docs */
|
||||||
|
|
||||||
s32 out_fd; /* Persistent fd for out_file */
|
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"
|
" -t msec - timeout for each run (%d ms)\n"
|
||||||
" -m megs - memory limit for child process (%d MB)\n"
|
" -m megs - memory limit for child process (%d MB)\n"
|
||||||
" -Q - use binary-only instrumentation (QEMU mode)\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-* "
|
" (Not necessary, here for consistency with other afl-* "
|
||||||
"tools)\n\n"
|
"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. */
|
/* Read mask bitmap from file. This is for the -B option. */
|
||||||
|
|
||||||
static void read_bitmap(u8* fname) {
|
static void read_bitmap(u8* fname) {
|
||||||
@ -1084,14 +1025,14 @@ static void read_bitmap(u8* fname) {
|
|||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
s32 opt;
|
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;
|
char** use_argv;
|
||||||
|
|
||||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||||
|
|
||||||
SAYF(cCYA "afl-tmin" VERSION cRST " by <lcamtuf@google.com>\n");
|
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) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -1192,6 +1133,16 @@ int main(int argc, char** argv) {
|
|||||||
unicorn_mode = 1;
|
unicorn_mode = 1;
|
||||||
break;
|
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 */
|
case 'B': /* load bitmap */
|
||||||
|
|
||||||
/* This is a secret undocumented option! It is speculated to be useful
|
/* 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]);
|
find_binary(argv[optind]);
|
||||||
detect_file_args(argv + optind, out_file);
|
detect_file_args(argv + optind, out_file);
|
||||||
|
|
||||||
if (qemu_mode)
|
if (qemu_mode) {
|
||||||
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
|
|
||||||
else
|
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;
|
use_argv = argv + optind;
|
||||||
|
|
||||||
exact_mode = !!getenv("AFL_TMIN_EXACT");
|
exact_mode = !!getenv("AFL_TMIN_EXACT");
|
||||||
|
Reference in New Issue
Block a user