From f07d49e877d20e8ae52370fc7b9860744cfba214 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 27 Jun 2019 11:48:08 +0200 Subject: more power --- docs/ChangeLog | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/ChangeLog b/docs/ChangeLog index 73c69196..abb5fd46 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,6 +17,7 @@ sending a mail to . Version ++2.52d (tbd): ----------------------------- + - more power to afl-system-config :) - added whitelist support for llvm_mode via AFL_LLVM_WHITELIST to allow only to instrument what is actually interesting. Gives more speed and less map pollution (originally by choller@mozilla) -- cgit 1.4.1 From 0cd7a3d21601333be4e286c5b43a5d57c5422524 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 27 Jun 2019 18:02:29 +0200 Subject: afl-tmin forkserver patch --- afl-tmin.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++------ docs/ChangeLog | 7 ++- docs/PATCHES | 1 + 3 files changed, 177 insertions(+), 20 deletions(-) (limited to 'docs') diff --git a/afl-tmin.c b/afl-tmin.c index 2d839041..a42be6e9 100644 --- a/afl-tmin.c +++ b/afl-tmin.c @@ -44,7 +44,11 @@ #include #include -static s32 child_pid; /* PID of the tested program */ +static s32 forksrv_pid, /* PID of the fork server */ + child_pid; /* PID of the tested program */ + +static s32 fsrv_ctl_fd, /* Fork server control pipe (write) */ + fsrv_st_fd; /* Fork server status pipe (read) */ static u8 *trace_bits, /* SHM with instrumentation bitmap */ *mask_bitmap; /* Mask for trace bits (-B) */ @@ -55,6 +59,8 @@ static u8 *in_file, /* Minimizer input test case */ *target_path, /* Path to target binary */ *doc_path; /* Path to docs */ +static s32 prog_in_fd; /* Persistent fd for prog_in */ + static u8* in_data; /* Input data for trimming */ static u32 in_len, /* Input data length */ @@ -236,38 +242,70 @@ static s32 write_to_file(u8* path, u8* mem, u32 len) { } +/* Write modified data to file for testing. If use_stdin is clear, the old file + is unlinked and a new one is created. Otherwise, prog_in_fd is rewound and + truncated. */ + +static void write_to_testcase(void* mem, u32 len) { + + s32 fd = prog_in_fd; + + if (!use_stdin) { + + unlink(prog_in); /* Ignore errors. */ + + fd = open(prog_in, O_WRONLY | O_CREAT | O_EXCL, 0600); + + if (fd < 0) PFATAL("Unable to create '%s'", prog_in); + + } else lseek(fd, 0, SEEK_SET); + + ck_write(fd, mem, len, prog_in); + + if (use_stdin) { + + if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); + lseek(fd, 0, SEEK_SET); + + } else close(fd); + +} + + /* Handle timeout signal. */ static void handle_timeout(int sig) { + if (child_pid > 0) { + child_timed_out = 1; - if (child_pid > 0) kill(child_pid, SIGKILL); + kill(child_pid, SIGKILL); -} + } else if (child_pid == -1 && forksrv_pid > 0) { + child_timed_out = 1; + kill(forksrv_pid, SIGKILL); -/* Execute target application. Returns 0 if the changes are a dud, or - 1 if they should be kept. */ + } -static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) { +} +/* start the app and it's forkserver */ +static void init_forkserver(char **argv) { static struct itimerval it; + int st_pipe[2], ctl_pipe[2]; int status = 0; + s32 rlen; - s32 prog_in_fd; - u32 cksum; - - memset(trace_bits, 0, MAP_SIZE); - MEM_BARRIER(); - - prog_in_fd = write_to_file(prog_in, mem, len); + ACTF("Spinning up the fork server..."); + if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); - child_pid = fork(); + forksrv_pid = fork(); - if (child_pid < 0) PFATAL("fork() failed"); + if (forksrv_pid < 0) PFATAL("fork() failed"); - if (!child_pid) { + if (!forksrv_pid) { struct rlimit r; @@ -304,6 +342,16 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) { r.rlim_max = r.rlim_cur = 0; setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ + /* 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"); + + close(ctl_pipe[0]); + close(ctl_pipe[1]); + close(st_pipe[0]); + close(st_pipe[1]); + execv(target_path, argv); *(u32*)trace_bits = EXEC_FAIL_SIG; @@ -311,17 +359,113 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) { } - close(prog_in_fd); + /* Close the unneeded endpoints. */ + + close(ctl_pipe[0]); + close(st_pipe[1]); + + fsrv_ctl_fd = ctl_pipe[1]; + fsrv_st_fd = st_pipe[0]; + + /* Configure timeout, wait for child, cancel timeout. */ + + if (exec_tmout) { + + child_timed_out = 0; + it.it_value.tv_sec = (exec_tmout * FORK_WAIT_MULT / 1000); + it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + + } + + setitimer(ITIMER_REAL, &it, NULL); + + rlen = read(fsrv_st_fd, &status, 4); + + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &it, NULL); + + /* 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) { + ACTF("All right - fork server is up."); + return; + } + + if (waitpid(forksrv_pid, &status, 0) <= 0) + PFATAL("waitpid() failed"); + + u8 child_crashed; + + if (WIFSIGNALED(status)) + child_crashed = 1; + + if (child_timed_out) + SAYF(cLRD "\n+++ Program timed off +++\n" cRST); + else if (stop_soon) + SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); + else if (child_crashed) + SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status)); + +} + + +/* Execute target application. Returns 0 if the changes are a dud, or + 1 if they should be kept. */ + +static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) { + + static struct itimerval it; + static u32 prev_timed_out = 0; + int status = 0; + + u32 cksum; + + memset(trace_bits, 0, MAP_SIZE); + MEM_BARRIER(); + + write_to_testcase(mem, len); + + s32 res; + + /* we have the fork server up and running, so simply + tell it to have at it, and then read back PID. */ + + if ((res = write(fsrv_ctl_fd, &prev_timed_out, 4)) != 4) { + + if (stop_soon) return 0; + RPFATAL(res, "Unable to request new process from fork server (OOM?)"); + + } + + if ((res = read(fsrv_st_fd, &child_pid, 4)) != 4) { + + if (stop_soon) return 0; + RPFATAL(res, "Unable to request new process from fork server (OOM?)"); + + } + + if (child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); /* Configure timeout, wait for child, cancel timeout. */ + if (exec_tmout) { + child_timed_out = 0; it.it_value.tv_sec = (exec_tmout / 1000); it.it_value.tv_usec = (exec_tmout % 1000) * 1000; + } + setitimer(ITIMER_REAL, &it, NULL); - if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); + if ((res = read(fsrv_st_fd, &status, 4)) != 4) { + + if (stop_soon) return 0; + RPFATAL(res, "Unable to communicate with fork server (OOM?)"); + + } child_pid = 0; it.it_value.tv_sec = 0; @@ -687,6 +831,13 @@ static void set_up_environment(void) { } + unlink(prog_in); + + prog_in_fd = open(prog_in, O_RDWR | O_CREAT | O_EXCL, 0600); + + if (prog_in_fd < 0) PFATAL("Unable to create '%s'", prog_in); + + /* Set sane defaults... */ x = getenv("ASAN_OPTIONS"); @@ -1113,6 +1264,8 @@ int main(int argc, char** argv) { read_initial_file(); + init_forkserver(use_argv); + ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); diff --git a/docs/ChangeLog b/docs/ChangeLog index abb5fd46..0d730118 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,13 +17,16 @@ sending a mail to . Version ++2.52d (tbd): ----------------------------- - - more power to afl-system-config :) + - more cpu power for afl-system-config + - added forkserver patch to afl-tmin, makes it much faster (originally from + github.com/nccgroup/TriforceAFL) - added whitelist support for llvm_mode via AFL_LLVM_WHITELIST to allow only to instrument what is actually interesting. Gives more speed and less map pollution (originally by choller@mozilla) - added Python Module mutator support, python2.7-dev is autodetected. see docs/python_mutators.txt (originally by choller@mozilla) - - added AFL_CAL_FAST for slow applications and AFL_DEBUG_CHILD_OUTPUT for debugging + - added AFL_CAL_FAST for slow applications and AFL_DEBUG_CHILD_OUTPUT for + debugging - added a -s seed switch to allow afl run with a fixed initial seed that is not updated. this is good for performance and path discovery tests as the random numbers are deterministic then diff --git a/docs/PATCHES b/docs/PATCHES index c933e031..f61f8d24 100644 --- a/docs/PATCHES +++ b/docs/PATCHES @@ -21,6 +21,7 @@ afl-qemu-optimize-map.diff by mh(at)mh-sec(dot)de + Qemu 3.1 upgrade with enhancement patches (github.com/andreafioraldi/afl) + Python mutator modules support (github.com/choeller/afl) + Whitelisting in LLVM mode (github.com/choeller/afl) ++ forkserver patch for afl-tmin (github.com/nccgroup/TriforceAFL) NOT INSTALLED -- cgit 1.4.1 From 7256e6d203233b20432fd201767f1f8d4464db25 Mon Sep 17 00:00:00 2001 From: Brian Foley Date: Sat, 29 Jun 2019 14:31:46 -0700 Subject: Fix some github URL typos in docs --- docs/PATCHES | 4 ++-- docs/README | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/PATCHES b/docs/PATCHES index f61f8d24..cb050218 100644 --- a/docs/PATCHES +++ b/docs/PATCHES @@ -19,8 +19,8 @@ afl-qemu-optimize-map.diff by mh(at)mh-sec(dot)de + AFLfast additions (github.com/mboehme/aflfast) were incorporated. + Qemu 3.1 upgrade with enhancement patches (github.com/andreafioraldi/afl) -+ Python mutator modules support (github.com/choeller/afl) -+ Whitelisting in LLVM mode (github.com/choeller/afl) ++ Python mutator modules support (github.com/choller/afl) ++ Whitelisting in LLVM mode (github.com/choller/afl) + forkserver patch for afl-tmin (github.com/nccgroup/TriforceAFL) diff --git a/docs/README b/docs/README index ca8533f7..ca38223d 100644 --- a/docs/README +++ b/docs/README @@ -22,7 +22,7 @@ american fuzzy lop plus plus to it. C. Hoellers afl-fuzz Python mutator module and llvm_mode whitelist support - was added too (https://github.com/choeller/afl) + was added too (https://github.com/choller/afl) So all in all this is the best-of AFL that is currently out there :-) -- cgit 1.4.1 From 0ca6df6f09243109a14ab080d75be4fff8a5d836 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 2 Jul 2019 11:51:09 +0200 Subject: typo fix --- docs/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/README b/docs/README index ca38223d..f9734528 100644 --- a/docs/README +++ b/docs/README @@ -21,7 +21,7 @@ american fuzzy lop plus plus https://github.com/andreafioraldi/afl and got the community patches applied to it. - C. Hoellers afl-fuzz Python mutator module and llvm_mode whitelist support + C. Hollers afl-fuzz Python mutator module and llvm_mode whitelist support was added too (https://github.com/choller/afl) So all in all this is the best-of AFL that is currently out there :-) -- cgit 1.4.1 From b57b2073acf85e985f513a12d8aae725f8942689 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 3 Jul 2019 12:05:58 +0200 Subject: LAF_... -> AFL_LLVM_LAF_... --- docs/ChangeLog | 2 ++ docs/env_variables.txt | 6 +++--- llvm_mode/Makefile | 2 +- llvm_mode/README.laf-intel | 8 ++++---- llvm_mode/afl-clang-fast.c | 6 +++--- llvm_mode/split-compares-pass.so.cc | 2 ++ 6 files changed, 15 insertions(+), 11 deletions(-) (limited to 'docs') diff --git a/docs/ChangeLog b/docs/ChangeLog index 0d730118..b758b211 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -30,6 +30,8 @@ Version ++2.52d (tbd): - added a -s seed switch to allow afl run with a fixed initial seed that is not updated. this is good for performance and path discovery tests as the random numbers are deterministic then + - llvm_mode LAF_... env variables can now be specified as AFL_LLVM_LAF_... + that is longer but in line with other llvm specific env vars - ... your idea or patch? diff --git a/docs/env_variables.txt b/docs/env_variables.txt index f5db3b4f..2a824766 100644 --- a/docs/env_variables.txt +++ b/docs/env_variables.txt @@ -89,11 +89,11 @@ Then there are a few specific features that are only available in llvm_mode: This great feature will split compares to series of single byte comparisons to allow afl-fuzz to find otherwise rather impossible paths. - - Setting LAF_SPLIT_SWITCHES will split switch()es + - Setting AFL_LLVM_LAF_SPLIT_SWITCHES will split switch()es - - Setting LAF_TRANSFORM_COMPARES will split string compare functions + - Setting AFL_LLVM_LAF_TRANSFORM_COMPARES will split string compare functions - - Setting LAF_SPLIT_COMPARES will split > 8 bit CMP instructions + - Setting AFL_LLVM_LAF_SPLIT_COMPARES will split > 8 bit CMP instructions See llvm_mode/README.laf-intel for more information. diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 6b277536..3304e62d 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -110,7 +110,7 @@ endif test_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." - unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) LAF_SPLIT_SWITCHES=1 LAF_TRANSFORM_COMPARES=1 LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) + unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) echo 0 | ../afl-showmap -m none -q -o .test-instr0 ./test-instr echo 1 | ../afl-showmap -m none -q -o .test-instr1 ./test-instr @rm -f test-instr diff --git a/llvm_mode/README.laf-intel b/llvm_mode/README.laf-intel index 891ab5fd..340216c3 100644 --- a/llvm_mode/README.laf-intel +++ b/llvm_mode/README.laf-intel @@ -8,13 +8,13 @@ compile the target project. The following options exist: -export LAF_SPLIT_SWITCHES=1 Enables the split-switches pass. +export AFL_LLVM_LAF_SPLIT_SWITCHES=1 Enables the split-switches pass. -export LAF_TRANSFORM_COMPARES=1 Enables the transform-compares pass +export AFL_LLVM_LAF_TRANSFORM_COMPARES=1 Enables the transform-compares pass (strcmp, memcmp, strncmp, strcasecmp, strncasecmp). -export LAF_SPLIT_COMPARES=1 Enables the split-compares pass. +export AFL_LLVM_LAF_SPLIT_COMPARES=1 Enables the split-compares pass. By default it will split all compares with a bit width <= 64 bits. You can change this behaviour by setting - export LAF_SPLIT_COMPARES_BITW=. + export AFL_LLVM_LAF_SPLIT_COMPARES_BITW=. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 1e2e04ea..5bc4ae8c 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -120,21 +120,21 @@ static void edit_params(u32 argc, char** argv) { http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards */ // laf - if (getenv("LAF_SPLIT_SWITCHES")) { + if (getenv("LAF_SPLIT_SWITCHES")||getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/split-switches-pass.so", obj_path); } - if (getenv("LAF_TRANSFORM_COMPARES")) { + if (getenv("LAF_TRANSFORM_COMPARES")||getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/compare-transform-pass.so", obj_path); } - if (getenv("LAF_SPLIT_COMPARES")) { + if (getenv("LAF_SPLIT_COMPARES")||getenv("AFL_LLVM_LAF_SPLIT_COMPARES")) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index 25ccb3b4..2ea73aaa 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -477,6 +477,8 @@ bool SplitComparesTransform::runOnModule(Module &M) { int bitw = 64; char* bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); + if (!bitw_env) + bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); if (bitw_env) { bitw = atoi(bitw_env); } -- cgit 1.4.1