一、源码
1.信号处理函数
static void handle_stop_sig(int sig) {
stop_soon = 1;
if (child_pid > 0) kill(child_pid, SIGKILL);
if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL);
}
static void handle_skipreq(int sig) {
skip_requested = 1;
}
static void handle_timeout(int sig) {
if (child_pid > 0) {
child_timed_out = 1;
kill(child_pid, SIGKILL);
} else if (child_pid == -1 && forksrv_pid > 0) {
child_timed_out = 1;
kill(forksrv_pid, SIGKILL);
}
}
static void handle_resize(int sig) {
clear_screen = 1;
}
* Set up signal handlers. More complicated that needs to be, because libc on
Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call
siginterrupt(), and does other unnecessary things. */
EXP_ST void setup_signal_handlers(void) {
struct sigaction sa;
sa.sa_handler = NULL;
sa.sa_flags = SA_RESTART;
sa.sa_sigaction = NULL;
sigemptyset(&sa.sa_mask);
sa.sa_handler = handle_stop_sig;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sa.sa_handler = handle_timeout;
sigaction(SIGALRM, &sa, NULL);
sa.sa_handler = handle_resize;
sigaction(SIGWINCH, &sa, NULL);
sa.sa_handler = handle_skipreq;
sigaction(SIGUSR1, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGTSTP, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
}
2.check_asan_opts(检查内存错误)
static void check_asan_opts(void) {
u8* x = getenv("ASAN_OPTIONS");
if (x) {
if (!strstr(x, "abort_on_error=1"))
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
if (!strstr(x, "symbolize=0"))
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
}
x = getenv("MSAN_OPTIONS");
if (x) {
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR)))
FATAL("Custom MSAN_OPTIONS set without exit_code="
STRINGIFY(MSAN_ERROR) " - please fix!");
if (!strstr(x, "symbolize=0"))
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
}
}
3.fix_up_sync(检查ID、sync_id是否过长,检查互斥)
static void fix_up_sync(void) {
u8* x = sync_id;
if (dumb_mode)
FATAL("-S / -M and -n are mutually exclusive");
if (skip_deterministic) {
if (force_deterministic)
FATAL("use -S instead of -M -d");
else
FATAL("-S already implies -d");
}
while (*x) {
if (!isalnum(*x) && *x != '_' && *x != '-')
FATAL("Non-alphanumeric fuzzer ID specified via -S or -M");
x++;
}
if (strlen(sync_id) > 32)
FATAL("Fuzzer ID too long");
x = alloc_printf("%s/%s", out_dir, sync_id);
sync_dir = out_dir;
out_dir = x;
if (!force_deterministic) {
skip_deterministic = 1;
use_splicing = 1;
}
}
4.save_cmdline(将当前输入参数拷贝进buf空间中)
static void save_cmdline(u32 argc, char** argv) {
u32 len = 1, i;
u8* buf;
for (i = 0; i < argc; i++)
len += strlen(argv[i]) + 1;
buf = orig_cmdline = ck_alloc(len);
for (i = 0; i < argc; i++) {
u32 l = strlen(argv[i]);
memcpy(buf, argv[i], l);
buf += l;
if (i != argc - 1) *(buf++) = ' ';
}
*buf = 0;
}
5.fix_up_banner(修剪并且创建一个运行横幅)
static void fix_up_banner(u8* name) {
if (!use_banner) {
if (sync_id) {
use_banner = sync_id;
} else {
u8* trim = strrchr(name, '/');
if (!trim)
use_banner = name;
else
use_banner = trim + 1;
}
}
if (strlen(use_banner) > 40) {
u8* tmp = ck_alloc(44);
sprintf(tmp, "%.40s...", use_banner);
use_banner = tmp;
}
}
6.check_if_tty(检查是否在tty终端上面运行)
static void check_if_tty(void) {
struct winsize ws;
if (getenv("AFL_NO_UI")) {
OKF("Disabling the UI because AFL_NO_UI is set.");
not_on_tty = 1;
return;
}
if (ioctl(1, TIOCGWINSZ, &ws)) {
if (errno == ENOTTY) {
OKF("Looks like we're not running on a tty, so I'll be a bit less verbose.");
not_on_tty = 1;
}
return;
}
}
7.get_core_count(计算逻辑CPU核的数量)
static void get_core_count(void) {
u32 cur_runnable = 0;
8.check_crash_handling(确保核心转储不会进入程序)
static void check_crash_handling(void) {
#ifdef __APPLE__
if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return;
SAYF("\n" cLRD "[-] " cRST
"Whoops, your system is configured to forward crash notifications to an\n"
" external crash reporting utility. This will cause issues due to the\n"
" extended delay between the fuzzed binary malfunctioning and this fact\n"
" being relayed to the fuzzer via the standard waitpid() API.\n\n"
" To avoid having crashes misinterpreted as timeouts, please run the\n"
" following commands:\n\n"
" SL=/System/Library; PL=com.apple.ReportCrash\n"
" launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n"
" sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n");
if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))
FATAL("Crash reporter detected");
#else
s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY);
u8 fchar;
if (fd < 0) return;
ACTF("Checking core_pattern...");
if (read(fd, &fchar, 1) == 1 && fchar == '|') {
SAYF("\n" cLRD "[-] " cRST
"Hmm, your system is configured to send core dump notifications to an\n"
" external utility. This will cause issues: there will be an extended delay\n"
" between stumbling upon a crash and having this information relayed to the\n"
" fuzzer via the standard waitpid() API.\n\n"
" To avoid having crashes misinterpreted as timeouts, please log in as root\n"
" and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n"
" echo core >/proc/sys/kernel/core_pattern\n");
if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))
FATAL("Pipe at the beginning of 'core_pattern'");
}
close(fd);
#endif
}
8.check_cpu_governor(检查CPU管理者)
static void check_cpu_governor(void) {
FILE* f;
u8 tmp[128];
u64 min = 0, max = 0;
if (getenv("AFL_SKIP_CPUFREQ"))
return;
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r");
if (!f)
return;
ACTF("Checking CPU scaling governor...");
if (!fgets(tmp, 128, f)) PFATAL("fgets() failed");
fclose(f);
if (!strncmp(tmp, "perf", 4)) return;
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r");
if (f) {
if (fscanf(f, "%llu", &min) != 1) min = 0;
fclose(f);
}
f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r");
if (f) {
if (fscanf(f, "%llu", &max) != 1) max = 0;
fclose(f);
}
if (min == max) return;
SAYF("\n" cLRD "[-] " cRST
"Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"
" between %llu and %llu MHz. Unfortunately, the scaling algorithm in the\n"
" kernel is imperfect and can miss the short-lived processes spawned by\n"
" afl-fuzz. To keep things moving, run these commands as root:\n\n"
" cd /sys/devices/system/cpu\n"
" echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
" You can later go back to the original state by replacing 'performance' with\n"
" 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ\n"
" to make afl-fuzz skip this check - but expect some performance drop.\n",
min / 1024, max / 1024);
FATAL("Suboptimal CPU scaling governor");
}
9.setup_post(加载后处理器(如果可用))
static void setup_post(void) {
void* dh;
u8* fn = getenv("AFL_POST_LIBRARY");
u32 tlen = 6;
if (!fn)
return;
ACTF("Loading postprocessor from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
if (!dh) FATAL("%s", dlerror());
post_handler = dlsym(dh, "afl_postprocess");
if (!post_handler)
FATAL("Symbol 'afl_postprocess' not found.");
post_handler("hello", &tlen);
OKF("Postprocessor installed successfully.");
}