SAYF(cCYA "afl-cc " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
} else be_quiet = 1;
if (argc < 2) {
SAYF("\n" "This is a helper application for afl-fuzz. It serves as a drop-in replacement\n" "for gcc or clang, letting you recompile third-party code with the required\n" "runtime instrumentation. A common use pattern would be one of the following:\n\n"
"You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n" "Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n", BIN_PATH, BIN_PATH);
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
return0;
}
afl-as.c
参数
1 2 3 4 5 6 7 8 9 10 11 12 13
static u8** as_params; /* Parameters passed to the real 'as' */// 传给as的参数
static u8* input_file; /* Originally specified input file */ static u8* modified_file; /* Instrumented file for the real 'as' *///as进行插桩的文件
static u8 be_quiet, /* Quiet mode (no stderr output) */ clang_mode, /* Running in clang mode? */ pass_thru, /* Just pass data through? */ just_version, /* Just show version? */ sanitizer; /* Using ASAN / MSAN */
static u32 inst_ratio = 100, /* Instrumentation probability (%) */// 插桩覆盖率 as_par_cnt = 1; /* Number of params to 'as' */
/* All right, this is where the actual fun begins. For one, we only want to instrument the .text section. So, let's keep track of that in processed files - and let's set instr_ok accordingly. */
if (line[0] == '\t' && line[1] == '.') {
/* OpenBSD puts jump tables directly inline with the code, which is a bit annoying. They use a specific format of p2align directives around them, so we use that as a signal. */
"__afl_setup:\n" "\n" " /* Do not retry setup if we had previous failures. */\n" "\n" " cmpb $0, __afl_setup_failure(%rip)\n" " jne __afl_return\n"//先检查是否为0,不是则直接返回,“防止预先可预见的失败” "\n" " /* Check out if we have a global pointer on file. */\n" "\n" " movq __afl_global_area_ptr(%rip), %rdx\n" " testq %rdx, %rdx\n" " je __afl_setup_first\n"// 如果global pointer也为空,进行初次建立 "\n" " movq %rdx, __afl_area_ptr(%rip)\n"//否则直接赋值给area ptr,然后进入store " jmp __afl_store\n"
/* If somebody is asking us to fuzz instrumented binaries in dumb mode, we don't want them to detect instrumentation, since we won't be sending fork server commands. This should be replaced with better auto-detection later on, perhaps? */
/* Be a bit more generous about timeouts when resuming sessions, or when trying to calibrate already-added finds. This helps avoid trouble due to intermittent latency. */
/* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but according to reliable sources, RLIMIT_DATA covers anonymous maps - so we should be getting good protection against OOM bugs. */
setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
#endif/* ^RLIMIT_AS */
}
/* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered before the dump is complete. */
r.rlim_max = r.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
/* Isolate the process and configure standard descriptors. If out_file is specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */
setsid();
dup2(dev_null_fd, 1); dup2(dev_null_fd, 2);
if (out_file) {
dup2(dev_null_fd, 0);
} else {
dup2(out_fd, 0); close(out_fd);
}
/* Set up control and status pipes, close the unneeded original fds. */
if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
/* If we have a four-byte "hello" message from the server, we're all set. Otherwise, try to figure out what went wrong. */
if (rlen == 4) { OKF("All right - fork server is up."); return; }
if (child_timed_out) FATAL("Timeout while initializing fork server (adjusting -t may help)");
if (waitpid(forksrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed");
if (WIFSIGNALED(status)) {
if (mem_limit && mem_limit < 500 && uses_asan) {
SAYF("\n" cLRD "[-] " cRST "Whoops, the target binary crashed suddenly, before receiving any input\n" " from the fuzzer! Since it seems to be built with ASAN and you have a\n" " restrictive memory limit configured, this is expected; please read\n" " %s/notes_for_asan.txt for help.\n", doc_path);
} elseif (!mem_limit) {
SAYF("\n" cLRD "[-] " cRST "Whoops, the target binary crashed suddenly, before receiving any input\n" " from the fuzzer! There are several probable explanations:\n\n"
" - The binary is just buggy and explodes entirely on its own. If so, you\n" " need to fix the underlying problem or find a better replacement.\n\n"
#ifdef __APPLE__
" - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" " break afl-fuzz performance optimizations when running platform-specific\n" " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n"
#endif/* __APPLE__ */
" - Less likely, there is a horrible bug in the fuzzer. If other options\n" " fail, poke <lcamtuf@coredump.cx> for troubleshooting tips.\n");
} else {
SAYF("\n" cLRD "[-] " cRST "Whoops, the target binary crashed suddenly, before receiving any input\n" " from the fuzzer! There are several probable explanations:\n\n"
" - The current memory limit (%s) is too restrictive, causing the\n" " target to hit an OOM condition in the dynamic linker. Try bumping up\n" " the limit with the -m setting in the command line. A simple way confirm\n" " this diagnosis would be:\n\n"
" Tip: you can use http://jwilk.net/software/recidivm to quickly\n" " estimate the required amount of virtual memory for the binary.\n\n"
" - The binary is just buggy and explodes entirely on its own. If so, you\n" " need to fix the underlying problem or find a better replacement.\n\n"
#ifdef __APPLE__
" - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" " break afl-fuzz performance optimizations when running platform-specific\n" " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n"
#endif/* __APPLE__ */
" - Less likely, there is a horrible bug in the fuzzer. If other options\n" " fail, poke <lcamtuf@coredump.cx> for troubleshooting tips.\n", DMS(mem_limit << 20), mem_limit - 1);
}
FATAL("Fork server crashed with signal %d", WTERMSIG(status));
}
if (*(u32*)trace_bits == EXEC_FAIL_SIG) FATAL("Unable to execute target application ('%s')", argv[0]);
if (mem_limit && mem_limit < 500 && uses_asan) {
SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated before we could complete a\n" " handshake with the injected code. Since it seems to be built with ASAN and\n" " you have a restrictive memory limit configured, this is expected; please\n" " read %s/notes_for_asan.txt for help.\n", doc_path);
} elseif (!mem_limit) {
SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated before we could complete a\n" " handshake with the injected code. Perhaps there is a horrible bug in the\n" " fuzzer. Poke <lcamtuf@coredump.cx> for troubleshooting tips.\n");
} else {
SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated before we could complete a\n" " handshake with the injected code. There are %s probable explanations:\n\n"
"%s" " - The current memory limit (%s) is too restrictive, causing an OOM\n" " fault in the dynamic linker. This can be fixed with the -m option. A\n" " simple way to confirm the diagnosis may be:\n\n"
" Tip: you can use http://jwilk.net/software/recidivm to quickly\n" " estimate the required amount of virtual memory for the binary.\n\n"
" - Less likely, there is a horrible bug in the fuzzer. If other options\n" " fail, poke <lcamtuf@coredump.cx> for troubleshooting tips.\n", getenv(DEFER_ENV_VAR) ? "three" : "two", getenv(DEFER_ENV_VAR) ? " - You are using deferred forkserver, but __AFL_INIT() is never\n" " reached before the program terminates.\n\n" : "", DMS(mem_limit << 20), mem_limit - 1);