diff options
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | afl-fuzz.c | 84 | ||||
-rwxr-xr-x | afl-system-config | 4 | ||||
-rw-r--r-- | afl-tmin.c | 2 | ||||
-rw-r--r-- | docs/ChangeLog | 9 | ||||
-rw-r--r-- | docs/README.MOpt | 30 | ||||
-rw-r--r-- | docs/binaryonly_fuzzing.txt | 27 | ||||
-rw-r--r-- | docs/env_variables.txt | 9 | ||||
-rw-r--r-- | docs/sister_projects.txt | 6 | ||||
-rw-r--r-- | gcc_plugin/CRASH | 23 | ||||
-rw-r--r-- | gcc_plugin/Makefile | 4 | ||||
-rw-r--r-- | gcc_plugin/README.gcc | 10 | ||||
-rw-r--r-- | gcc_plugin/afl-gcc-pass.so.cc | 9 | ||||
-rw-r--r-- | llvm_mode/README.llvm | 4 | ||||
-rw-r--r-- | qemu_mode/README.qemu | 2 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-inl.h | 50 |
16 files changed, 182 insertions, 95 deletions
diff --git a/TODO b/TODO index 7a75afe3..6631350c 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,8 @@ Roadmap 2.53d: - README.md + - update docs/sister_projects.txt + - better defaults: * laf-intel activated, needs deactiatation * fast mode schedule @@ -15,7 +17,7 @@ afl-fuzz: - reuse forkserver for showmap, afl-cmin, etc. gcc_plugin: - (see TODOs) + - fix crashes when compiling :( - whitelist support - skip over uninteresting blocks - laf-intel diff --git a/afl-fuzz.c b/afl-fuzz.c index 87ad814a..53840f9a 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -108,24 +108,24 @@ int g_max = 5000; u64 tmp_core_time = 0; int swarm_now = 0 ; double x_now[swarm_num][operator_num], - L_best[swarm_num][operator_num], - eff_best[swarm_num][operator_num], - G_best[operator_num], - v_now[swarm_num][operator_num], + L_best[swarm_num][operator_num], + eff_best[swarm_num][operator_num], + G_best[operator_num], + v_now[swarm_num][operator_num], probability_now[swarm_num][operator_num], - swarm_fitness[swarm_num]; + swarm_fitness[swarm_num]; static u64 stage_finds_puppet[swarm_num][operator_num], /* Patterns found per fuzz stage */ stage_finds_puppet_v2[swarm_num][operator_num], stage_cycles_puppet_v2[swarm_num][operator_num], stage_cycles_puppet_v3[swarm_num][operator_num], stage_cycles_puppet[swarm_num][operator_num], - operator_finds_puppet[operator_num], - core_operator_finds_puppet[operator_num], - core_operator_finds_puppet_v2[operator_num], - core_operator_cycles_puppet[operator_num], - core_operator_cycles_puppet_v2[operator_num], - core_operator_cycles_puppet_v3[operator_num]; /* Execs per fuzz stage */ + operator_finds_puppet[operator_num], + core_operator_finds_puppet[operator_num], + core_operator_finds_puppet_v2[operator_num], + core_operator_cycles_puppet[operator_num], + core_operator_cycles_puppet_v2[operator_num], + core_operator_cycles_puppet_v3[operator_num]; /* Execs per fuzz stage */ #define RAND_C (rand()%1000*0.001) #define v_max 1 @@ -3428,6 +3428,8 @@ static void write_crash_readme(void) { static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) { + if (len == 0) return 0; + u8 *fn = ""; u8 hnb; s32 fd; @@ -4321,13 +4323,13 @@ static void show_stats(void) { /* Let's start by drawing a centered banner. */ - banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner) + strlen(power_name) + 3; + banner_len = (crash_mode ? 24 : 22) + strlen(VERSION) + strlen(use_banner) + strlen(power_name) + 3 + 5; banner_pad = (79 - banner_len) / 2; memset(tmp, ' ', banner_pad); sprintf(tmp + banner_pad, "%s " cLCY VERSION cLGN - " (%s) " cPIN "[%s]", crash_mode ? cPIN "peruvian were-rabbit" : - cYEL "american fuzzy lop", use_banner, power_name); + " (%s) " cPIN "[%s]" cBLU " {%d}", crash_mode ? cPIN "peruvian were-rabbit" : + cYEL "american fuzzy lop", use_banner, power_name, cpu_aff); SAYF("\n%s\n", tmp); @@ -8462,7 +8464,6 @@ static u8 pilot_fuzzing(char** argv) { s32 temp_len_puppet; cur_ms_lv = get_cur_time(); - { @@ -8844,6 +8845,14 @@ static u8 pilot_fuzzing(char** argv) { } new_hit_cnt = queued_paths + unique_crashes; + + if (!splice_cycle) { + stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; + stage_cycles[STAGE_HAVOC] += stage_max; + } else { + stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; + stage_cycles[STAGE_SPLICE] += stage_max; + } #ifndef IGNORE_FINDS @@ -8958,10 +8967,8 @@ static u8 pilot_fuzzing(char** argv) { ck_free(eff_map); - if (key_puppet == 1) - { - if (unlikely(queued_paths + unique_crashes > ((queued_paths + unique_crashes)*limit_time_bound + orig_hit_cnt_puppet))) - { + if (key_puppet == 1) { + if (unlikely(queued_paths + unique_crashes > ((queued_paths + unique_crashes)*limit_time_bound + orig_hit_cnt_puppet))) { key_puppet = 0; cur_ms_lv = get_cur_time(); new_hit_cnt = queued_paths + unique_crashes; @@ -8971,8 +8978,7 @@ static u8 pilot_fuzzing(char** argv) { } - if (unlikely(tmp_pilot_time > period_pilot)) - { + if (unlikely(tmp_pilot_time > period_pilot)) { total_pacemaker_time += tmp_pilot_time; new_hit_cnt = queued_paths + unique_crashes; swarm_fitness[swarm_now] = (double)(total_puppet_find - temp_puppet_find) / ((double)(tmp_pilot_time)/ period_pilot_tmp); @@ -8980,16 +8986,14 @@ static u8 pilot_fuzzing(char** argv) { temp_puppet_find = total_puppet_find; u64 temp_stage_finds_puppet = 0; - for (i = 0; i < operator_num; i++) - { + for (i = 0; i < operator_num; i++) { double temp_eff = 0.0; if (stage_cycles_puppet_v2[swarm_now][i] > stage_cycles_puppet[swarm_now][i]) temp_eff = (double)(stage_finds_puppet_v2[swarm_now][i] - stage_finds_puppet[swarm_now][i]) / (double)(stage_cycles_puppet_v2[swarm_now][i] - stage_cycles_puppet[swarm_now][i]); - if (eff_best[swarm_now][i] < temp_eff) - { + if (eff_best[swarm_now][i] < temp_eff) { eff_best[swarm_now][i] = temp_eff; L_best[swarm_now][i] = x_now[swarm_now][i]; } @@ -9000,11 +9004,9 @@ static u8 pilot_fuzzing(char** argv) { } swarm_now = swarm_now + 1; - if (swarm_now == swarm_num) - { + if (swarm_now == swarm_num) { key_module = 1; - for (i = 0; i < operator_num; i++) - { + for (i = 0; i < operator_num; i++) { core_operator_cycles_puppet_v2[i] = core_operator_cycles_puppet[i]; core_operator_cycles_puppet_v3[i] = core_operator_cycles_puppet[i]; core_operator_finds_puppet_v2[i] = core_operator_finds_puppet[i]; @@ -9012,10 +9014,8 @@ static u8 pilot_fuzzing(char** argv) { double swarm_eff = 0.0; swarm_now = 0; - for (i = 0; i < swarm_num; i++) - { - if (swarm_fitness[i] > swarm_eff) - { + for (i = 0; i < swarm_num; i++) { + if (swarm_fitness[i] > swarm_eff) { swarm_eff = swarm_fitness[i]; swarm_now = i; } @@ -9024,8 +9024,6 @@ static u8 pilot_fuzzing(char** argv) { PFATAL("swarm_now error number %d", swarm_now); } - - } return ret_val; } @@ -9037,12 +9035,10 @@ static u8 pilot_fuzzing(char** argv) { } - static u8 core_fuzzing(char** argv) { int i; - if (swarm_num == 1) - { + if (swarm_num == 1) { key_module = 2; return 0; } @@ -9076,8 +9072,7 @@ static u8 core_fuzzing(char** argv) { if ((queue_cur->was_fuzzed || !queue_cur->favored) && UR(100) < SKIP_TO_NEW_PROB) return 1; - } - else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { + } else if (!dumb_mode && !queue_cur->favored && queued_paths > 10) { /* Otherwise, still possibly skip non-favored cases, albeit less often. The odds of skipping stuff are higher for already-fuzzed inputs and @@ -9087,8 +9082,7 @@ static u8 core_fuzzing(char** argv) { if (UR(100) < SKIP_NFAV_NEW_PROB) return 1; - } - else { + } else { if (UR(100) < SKIP_NFAV_OLD_PROB) return 1; @@ -11253,7 +11247,7 @@ static void usage(u8* argv0) { " -Q - use binary-only instrumentation (QEMU 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 = immediately).\n" - " see docs/README.MOpt\n\n" + " a recommended value is 10-60. see docs/README.MOpt\n\n" "Fuzzing behavior settings:\n" " -d - quick & dirty mode (skips deterministic steps)\n" @@ -12267,6 +12261,8 @@ int main(int argc, char** argv) { if (qemu_mode) FATAL("-Q and -n are mutually exclusive"); } + + if (index(argv[optind], '/') == NULL) WARNF(cLRD "Target binary called without a prefixed path, make sure you are fuzzing the right binary: " cRST "%s", argv[optind]); OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" Eissfeldt and Andrea Fioraldi"); OKF("afl++ is open source, get it at https://github.com/vanhauser-thc/AFLplusplus"); @@ -12525,7 +12521,7 @@ stop_fuzzing: SAYF("\n" cYEL "[!] " cRST "Stopped during the first cycle, results may be incomplete.\n" - " (For info on resuming, see %s/README.)\n", doc_path); + " (For info on resuming, see %s/README)\n", doc_path); } diff --git a/afl-system-config b/afl-system-config index fa24d473..97f95c09 100755 --- a/afl-system-config +++ b/afl-system-config @@ -1,5 +1,9 @@ #!/bin/sh echo This reconfigures the system to have a better fuzzing performance +if [[ $EUID -ne 0 ]] || ! [ `id -u` = 0 ]; then + echo if you are root \(which you are currently not\) + exit 1 +fi sysctl -w kernel.core_pattern=core sysctl -w kernel.randomize_va_space=0 sysctl -w kernel.sched_child_runs_first=1 diff --git a/afl-tmin.c b/afl-tmin.c index d6fd27fc..f62a144f 100644 --- a/afl-tmin.c +++ b/afl-tmin.c @@ -671,7 +671,7 @@ next_del_blksize: alpha_del1 = 0; syms_removed = 0; - memset(alpha_map, 0, 256 * sizeof(u32)); + memset(alpha_map, 0, sizeof(alpha_map)); for (i = 0; i < in_len; i++) { if (!alpha_map[in_data[i]]) alpha_size++; diff --git a/docs/ChangeLog b/docs/ChangeLog index f2709877..44eb4012 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,6 +17,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. Version ++2.52d (tbd): ----------------------------- + - afl-fuzz now displays the selected core in the status screen (blue {#}) - updated afl-fuzz and afl-system-config for new scaling governor location in modern kernels - using the old ineffective afl-gcc will now show a deprecation warning @@ -30,7 +31,7 @@ Version ++2.52d (tbd): path discovery. See llvm_mode/README.instrim (https://github.com/csienslab/instrim) - added MOpt (github.com/puppet-meteor/MOpt-AFL) mode, see docs/README.MOpt - added code to make it more portable to other platforms than Intel Linux - - added never zero counters for afl-gcc and optional (because of an + - added never zero counters for afl-gcc and optionally (because of an optimization issue in llvm < 9) for llvm_mode (AFL_LLVM_NEVER_ZERO=1) - added a new doc about binary only fuzzing: docs/binaryonly_fuzzing.txt - more cpu power for afl-system-config @@ -45,8 +46,8 @@ Version ++2.52d (tbd): debugging - added -V time and -E execs option to better comparison runs, runs afl-fuzz for a specific time/executions. - - 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 + - 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 @@ -59,7 +60,7 @@ Version ++2.52c (2019-06-05): - Applied community patches. See docs/PATCHES for the full list. LLVM and Qemu modes are now faster. Important changes: - afl-fuzz: -e EXTENSION commandline option + afl-fuzz: -e EXTENSION commandline option llvm_mode: LAF-intel performance (needs activation, see llvm/README.laf-intel) a few new environment variables for afl-fuzz, llvm and qemu, see docs/env_variables.txt - Added the power schedules of AFLfast by Marcel Boehme, but set the default diff --git a/docs/README.MOpt b/docs/README.MOpt index 5575189c..94e63959 100644 --- a/docs/README.MOpt +++ b/docs/README.MOpt @@ -17,7 +17,8 @@ We open source all the seed sets used in the paper ### 4. Experiment Results The experiment results can be found in -https://drive.google.com/drive/folders/184GOzkZGls1H2NuLuUfSp9gfqp1E2-lL?usp=sharing. We only open source the crash files since the space is limited. +https://drive.google.com/drive/folders/184GOzkZGls1H2NuLuUfSp9gfqp1E2-lL?usp=sharing. +We only open source the crash files since the space is limited. ### 5. Technical Report MOpt_TechReport.pdf is the technical report of the paper @@ -26,18 +27,25 @@ MOpt_TechReport.pdf is the technical report of the paper ### 6. Parameter Introduction Most important, you must add the parameter `-L` (e.g., `-L 0`) to launch the MOpt scheme. -<br>`-L` controls the time to move on to the pacemaker fuzzing mode. -<br>`-L t:` when MOpt-AFL finishes the mutation of one input, if it has not -discovered any new unique crash or path for more than t min, MOpt-AFL will + +Option '-L' controls the time to move on to the pacemaker fuzzing mode. +'-L t': when MOpt-AFL finishes the mutation of one input, if it has not +discovered any new unique crash or path for more than t minutes, MOpt-AFL will enter the pacemaker fuzzing mode. -<br>Setting 0 will enter the pacemaker fuzzing mode at first, which is + +Setting 0 will enter the pacemaker fuzzing mode at first, which is recommended in a short time-scale evaluation. Other important parameters can be found in afl-fuzz.c, for instance, -<br>`swarm_num:` the number of the PSO swarms used in the fuzzing process. -<br>`period_pilot:` how many times MOpt-AFL will execute the target program in the pilot fuzzing module, then it will enter the core fuzzing module. -<br>`period_core:` how many times MOpt-AFL will execute the target program in the core fuzzing module, then it will enter the PSO updating module. -<br>`limit_time_bound:` control how many interesting test cases need to be found before MOpt-AFL quits the pacemaker fuzzing mode and reuses the deterministic stage. -0 < `limit_time_bound` < 1, MOpt-AFL-tmp. `limit_time_bound` >= 1, MOpt-AFL-ever. -Having fun with MOpt in AFL! +'swarm_num': the number of the PSO swarms used in the fuzzing process. +'period_pilot': how many times MOpt-AFL will execute the target program + in the pilot fuzzing module, then it will enter the core fuzzing module. +'period_core': how many times MOpt-AFL will execute the target program in the + core fuzzing module, then it will enter the PSO updating module. +'limit_time_bound': control how many interesting test cases need to be found + before MOpt-AFL quits the pacemaker fuzzing mode and reuses the deterministic stage. + 0 < 'limit_time_bound' < 1, MOpt-AFL-tmp. + 'limit_time_bound' >= 1, MOpt-AFL-ever. + +Have fun with MOpt in AFL! diff --git a/docs/binaryonly_fuzzing.txt b/docs/binaryonly_fuzzing.txt index f370ec74..ae5269f0 100644 --- a/docs/binaryonly_fuzzing.txt +++ b/docs/binaryonly_fuzzing.txt @@ -11,7 +11,7 @@ then standard afl++ (dumb mode) is not effective. The following is a description of how these can be fuzzed with afl++ !!!!! -DTLR: try DYNINST with afl-dyninst. If it produces too many crashes then +TL;DR: try DYNINST with afl-dyninst. If it produces too many crashes then use afl -Q qemu_mode. !!!!! @@ -22,7 +22,7 @@ Qemu is the "native" solution to the program. It is available in the ./qemu_mode/ directory and once compiled it can be accessed by the afl-fuzz -Q command line option. The speed decrease is at about 50% -It the easiest to use alternative and even works for cross-platform binaries. +It is the easiest to use alternative and even works for cross-platform binaries. As it is included in afl++ this needs no URL. @@ -30,7 +30,7 @@ As it is included in afl++ this needs no URL. DYNINST ------- Dyninst is a binary instrumentation framework similar to Pintool and Dynamorio -(see far below). Howver whereas Pintool and Dynamorio work at runtime, dyninst +(see far below). However whereas Pintool and Dynamorio work at runtime, dyninst instruments the target at load time, and then let it run. This is great for some things, e.g. fuzzing, and not so effective for others, e.g. malware analysis. @@ -38,15 +38,15 @@ e.g. malware analysis. So what we can do with dyninst is taking every basic block, and put afl's instrumention code in there - and then save the binary. Afterwards we can just fuzz the newly saved target binary with afl-fuzz. -Sounds great? It is. The issue though - this is a non-trivial problem to -insert instructions, which changes addresses in the process space and that -everything still works afterwards. Hence more often than not binaries -crash when they are run. +Sounds great? It is. The issue though - it is a non-trivial problem to +insert instructions, which change addresses in the process space, so +everything is still working afterwards. Hence more often than not binaries +crash when they are run (because of instrumentation). The speed decrease is about 15-35%, depending on the optimization options used with afl-dyninst. -So if dyninst works, its the best option available. Otherwise it just doesn't +So if dyninst works, it is the best option available. Otherwise it just doesn't work well. https://github.com/vanhauser-thc/afl-dyninst @@ -54,13 +54,14 @@ https://github.com/vanhauser-thc/afl-dyninst INTEL-PT -------- +If you have a newer Intel CPU, you can make use of Intels processor trace. The big issue with Intel's PT is the small buffer size and the complex encoding of the debug information collected through PT. This makes the decoding very CPU intensive and hence slow. As a result, the overall speed decrease is about 70-90% (depending on -the implementation and other factors) +the implementation and other factors). -there are two afl intel-pt implementations: +There are two afl intel-pt implementations: 1. https://github.com/junxzm1990/afl-pt => this needs Ubuntu 14.04.05 without any updates and the 4.4 kernel. @@ -73,13 +74,13 @@ there are two afl intel-pt implementations: CORESIGHT --------- -Coresight is the ARM answer to Intel's PT. +Coresight is ARM's answer to Intel's PT. There is no implementation so far which handle coresight and getting -it working on an ARM Linux is very difficult due custom kernel building +it working on an ARM Linux is very difficult due to custom kernel building on embedded systems is difficult. And finding one that has coresight in the ARM chip is difficult too. My guess is that it is slower than Qemu, but faster than Intel PT. -If anyone finds any coresight implemention for afl please ping me: +If anyone finds any coresight implementation for afl please ping me: vh@thc.org diff --git a/docs/env_variables.txt b/docs/env_variables.txt index 1d035c68..36fdc369 100644 --- a/docs/env_variables.txt +++ b/docs/env_variables.txt @@ -90,7 +90,8 @@ Then there are a few specific features that are only available in llvm_mode: LAF-INTEL ========= This great feature will split compares to series of single byte comparisons - to allow afl-fuzz to find otherwise rather impossible paths. + to allow afl-fuzz to find otherwise rather impossible paths. It is not + restricted to Intel CPUs ;-) - Setting AFL_LLVM_LAF_SPLIT_SWITCHES will split switch()es @@ -105,20 +106,20 @@ Then there are a few specific features that are only available in llvm_mode: This feature allows selectively instrumentation of the source - Setting AFL_LLVM_WHITELIST with a filename will only instrument those - files that match these names. + files that match the names listed in this file. See llvm_mode/README.whitelist for more information. INSTRIM ======= This feature increases the speed by whopping 20% but at the cost of a - lower path discovery and thefore coverage. + lower path discovery and therefore coverage. - Setting AFL_LLVM_INSTRIM activates this mode - Setting AFL_LLVM_INSTRIM_LOOPHEAD=1 expands on INSTRIM to optimize loops. afl-fuzz will only be able to see the path the loop took, but not how - many times it was called (unless its a complex loop). + many times it was called (unless it is a complex loop). See llvm_mode/README.instrim diff --git a/docs/sister_projects.txt b/docs/sister_projects.txt index 41701e2f..a2eb2a22 100644 --- a/docs/sister_projects.txt +++ b/docs/sister_projects.txt @@ -6,6 +6,10 @@ Sister projects designed for, or meant to integrate with AFL. See README for the general instruction manual. +!!! +!!! This list is outdated and needs an update, missing: e.g. Angora, FairFuzz +!!! + ------------------------------------------- Support for other languages / environments: ------------------------------------------- @@ -263,7 +267,7 @@ Static binary-only instrumentation (Aleksandar Nikolich) reports better performance compared to QEMU, but occasional translation errors with stripped binaries. - https://github.com/vrtadmin/moflow/tree/master/afl-dyninst + https://github.com/vanhauser-thc/afl-dyninst AFL PIN (Parker Thompson) ------------------------- diff --git a/gcc_plugin/CRASH b/gcc_plugin/CRASH new file mode 100644 index 00000000..51930bb3 --- /dev/null +++ b/gcc_plugin/CRASH @@ -0,0 +1,23 @@ +to reproduce: +============= +tiff-4.0.4.tar.gz +CC=afl-gcc-fast CXX=afl-g++-fast ./configure --disable-shared +make + +result +====== +[+] Instrumented 11 locations in TIFFInitJPEG +during GIMPLE pass: evrp +tif_jpeg.c: In function ‘JPEGFixupTagsSubsamplingSec’: +tif_jpeg.c:2388:1: internal compiler error: Segmentation fault + } + ^ +0x7ffff758e83f ??? + /build/glibc-vjB4T1/glibc-2.28/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0 +0x7ffff757b09a __libc_start_main + ../csu/libc-start.c:308 +Please submit a full bug report, +with preprocessed source if appropriate. +Please include the complete backtrace with any bug report. +See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions. +make[2]: *** [Makefile:696: tif_jpeg.lo] Error 1 diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index 721ce0ad..2f4c5db0 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -57,8 +57,8 @@ test_deps: test_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." -# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) - unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) + unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) +# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-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/gcc_plugin/README.gcc b/gcc_plugin/README.gcc index b3e9c853..a002c741 100644 --- a/gcc_plugin/README.gcc +++ b/gcc_plugin/README.gcc @@ -5,6 +5,12 @@ Fast GCC-based instrumentation for afl-fuzz (See ../docs/README for the general instruction manual.) (See ../llvm_mode/README.llvm for the LLVM-based instrumentation.) + +!!! +!!! gcc_plugin is not stable yet and can crash when compiling +!!! + + 1) Introduction --------------- @@ -65,8 +71,8 @@ directory. This is an early-stage mechanism, so field reports are welcome. You can send bug reports to <aseipp@pobox.com>. -4) Bonus feature #1: deferred instrumentation ---------------------------------------------- +4) Bonus feature #1: deferred initialization +-------------------------------------------- AFL tries to optimize performance by executing the targeted binary just once, stopping it just before main(), and then cloning this "master" process to get diff --git a/gcc_plugin/afl-gcc-pass.so.cc b/gcc_plugin/afl-gcc-pass.so.cc index 8d1888ef..b1ca8325 100644 --- a/gcc_plugin/afl-gcc-pass.so.cc +++ b/gcc_plugin/afl-gcc-pass.so.cc @@ -1,7 +1,9 @@ // -// There are two TODOs in this file: +// There are some TODOs in this file: // - dont instrument blocks that are uninterested // - implement whitelist feature +// - implement notZero +// - fix crash // /* @@ -102,7 +104,7 @@ static unsigned int ext_call_instrument(function *fun) { if (!fcnt_blocks++) continue; /* skip block 0 */ - // TODO: if the predecessor does not have to destinations + // TODO: if the predecessor does not have ast least two destinations // then skip this block :TODO /* Bail on this block if we trip the specified ratio */ @@ -223,6 +225,9 @@ static unsigned int inline_instrument(function *fun) { g = gimple_build_assign(tmp3, PLUS_EXPR, tmp2, one); gimple_seq_add_stmt(&seq, g); // tmp3 = tmp2 + 1 + // TODO: neverZero: here we have to check if tmp3 == 0 + // and add 1 if so + // tree tmp4 = create_tmp_var(map_type, "tmp4"); // g = gimple_build_assign(tmp4, PLUS_EXPR, map_ptr_g, area_off); // gimple_seq_add_stmt(&seq, g); // tmp4 = __afl_area_ptr + area_off diff --git a/llvm_mode/README.llvm b/llvm_mode/README.llvm index aaa7b81f..00528a46 100644 --- a/llvm_mode/README.llvm +++ b/llvm_mode/README.llvm @@ -109,8 +109,8 @@ See README.neverzero This is an early-stage mechanism, so field reports are welcome. You can send bug reports to <afl-users@googlegroups.com>. -5) Bonus feature #1: deferred instrumentation ---------------------------------------------- +5) Bonus feature #1: deferred initialization +-------------------------------------------- AFL tries to optimize performance by executing the targeted binary just once, stopping it just before main(), and then cloning this "master" process to get diff --git a/qemu_mode/README.qemu b/qemu_mode/README.qemu index cf29088b..124fce12 100644 --- a/qemu_mode/README.qemu +++ b/qemu_mode/README.qemu @@ -117,7 +117,7 @@ program control flow without actually executing each and every code path. If you want to experiment with this mode of operation, there is a module contributed by Aleksandar Nikolich: - https://github.com/vrtadmin/moflow/tree/master/afl-dyninst + https://github.com/vanhauser-thc/afl-dyninst https://groups.google.com/forum/#!topic/afl-users/HlSQdbOTlpg At this point, the author reports the possibility of hiccups with stripped diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index bfeb62ea..03951fea 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -278,6 +278,25 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags, ui } + +/* Check if an address is valid in the current mapping */ + +static inline int is_valid_addr(target_ulong addr) { + + int l, flags; + target_ulong page; + void * p; + + page = addr & TARGET_PAGE_MASK; + l = (page + TARGET_PAGE_SIZE) - addr; + + flags = page_get_flags(page); + if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) + return 0; + + return 1; +} + /* This is the other side of the same channel. Since timeouts are handled by afl-fuzz simply killing the child, we can just wait until the pipe breaks. */ @@ -289,6 +308,8 @@ static void afl_wait_tsl(CPUState *cpu, int fd) { while (1) { + u8 invalid_pc = 0; + /* Broken pipe means it's time to return to the fork server routine. */ if (read(fd, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) @@ -297,19 +318,34 @@ static void afl_wait_tsl(CPUState *cpu, int fd) { tb = tb_htable_lookup(cpu, t.tb.pc, t.tb.cs_base, t.tb.flags, t.tb.cf_mask); if(!tb) { - mmap_lock(); - tb = tb_gen_code(cpu, t.tb.pc, t.tb.cs_base, t.tb.flags, 0); - mmap_unlock(); + + /* The child may request to transate a block of memory that is not + mapped in the parent (e.g. jitted code or dlopened code). + This causes a SIGSEV in gen_intermediate_code() and associated + subroutines. We simply avoid caching of such blocks. */ + + if (is_valid_addr(t.tb.pc)) { + + mmap_lock(); + tb = tb_gen_code(cpu, t.tb.pc, t.tb.cs_base, t.tb.flags, 0); + mmap_unlock(); + } else { + + invalid_pc = 1; + } } if (t.is_chain) { if (read(fd, &c, sizeof(struct afl_chain)) != sizeof(struct afl_chain)) break; - last_tb = tb_htable_lookup(cpu, c.last_tb.pc, c.last_tb.cs_base, - c.last_tb.flags, c.cf_mask); - if (last_tb) { - tb_add_jump(last_tb, c.tb_exit, tb); + if (!invalid_pc) { + + last_tb = tb_htable_lookup(cpu, c.last_tb.pc, c.last_tb.cs_base, + c.last_tb.flags, c.cf_mask); + if (last_tb) { + tb_add_jump(last_tb, c.tb_exit, tb); + } } } |