| @ -0,0 +1,20 @@ | |||||||
|  | # Binaries produced by "make". | ||||||
|  | afl-analyze | ||||||
|  | afl-as | ||||||
|  | afl-clang | ||||||
|  | afl-clang++ | ||||||
|  | afl-fuzz | ||||||
|  | afl-g++ | ||||||
|  | afl-gcc | ||||||
|  | afl-gotcpu | ||||||
|  | afl-showmap | ||||||
|  | afl-tmin | ||||||
|  | as | ||||||
|  | 
 | ||||||
|  | # Binaries produced by "make -C llvm_mode" | ||||||
|  | afl-clang-fast | ||||||
|  | afl-clang-fast++ | ||||||
|  | afl-llvm-pass.so | ||||||
|  | afl-llvm-rt-32.o | ||||||
|  | afl-llvm-rt-64.o | ||||||
|  | afl-llvm-rt.o | ||||||
| @ -0,0 +1,60 @@ | |||||||
|  | language: c | ||||||
|  | 
 | ||||||
|  | env: | ||||||
|  |   - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_STOP_MANUALLY=1 | ||||||
|  |   - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_EXIT_WHEN_DONE=1 | ||||||
|  |  # TODO: test AFL_BENCH_UNTIL_CRASH once we have a target that crashes | ||||||
|  |   - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_BENCH_JUST_ONE=1 | ||||||
|  | 
 | ||||||
|  | before_install: | ||||||
|  |   - sudo apt update | ||||||
|  |   - sudo apt install -y libtool libtool-bin automake bison libglib2.0 | ||||||
|  | 
 | ||||||
|  | # TODO: Look into splitting off some builds using a build matrix. | ||||||
|  | # TODO: Move this all into a bash script so we don't need to write bash in yaml. | ||||||
|  | script: | ||||||
|  |   - make | ||||||
|  |   - ./afl-gcc ./test-instr.c -o test-instr-gcc | ||||||
|  |   - mkdir seeds | ||||||
|  |   - echo "" > seeds/nil_seed | ||||||
|  |   - if [ -z "$AFL_STOP_MANUALLY" ]; | ||||||
|  |     then ./afl-fuzz -i seeds -o out/ -- ./test-instr-gcc; | ||||||
|  |     else timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-instr-gcc; | ||||||
|  |     fi | ||||||
|  |   - .travis/check_fuzzer_stats.sh -o out -k peak_rss_mb -v 1 -p 3 | ||||||
|  |   - rm -r out/* | ||||||
|  |   - ./afl-clang ./test-instr.c -o test-instr-clang | ||||||
|  |   - if [ -z "$AFL_STOP_MANUALLY" ]; | ||||||
|  |     then ./afl-fuzz -i seeds -o out/ -- ./test-instr-clang; | ||||||
|  |     else timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-instr-clang; | ||||||
|  |     fi | ||||||
|  |   - .travis/check_fuzzer_stats.sh -o out -k peak_rss_mb -v 1 -p 2 | ||||||
|  |   - make clean | ||||||
|  |   - CC=clang CXX=clang++ make | ||||||
|  |   - cd llvm_mode | ||||||
|  |   # TODO: Build with different versions of clang/LLVM since LLVM passes don't | ||||||
|  |   # have a stable API. | ||||||
|  |   - CC=clang CXX=clang++ LLVM_CONFIG=llvm-config make | ||||||
|  |   - cd .. | ||||||
|  |   - rm -r out/* | ||||||
|  |   - ./afl-clang-fast ./test-instr.c -o test-instr-clang-fast | ||||||
|  |   - if [ -z "$AFL_STOP_MANUALLY" ]; | ||||||
|  |     then ./afl-fuzz -i seeds -o out/ -- ./test-instr-clang-fast; | ||||||
|  |     else timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-instr-clang-fast; | ||||||
|  |     fi | ||||||
|  |   - .travis/check_fuzzer_stats.sh -o out -k peak_rss_mb -v 1 -p 3 | ||||||
|  |   # Test fuzzing libFuzzer targets and trace-pc-guard instrumentation. | ||||||
|  |   - clang -g -fsanitize-coverage=trace-pc-guard ./test-libfuzzer-target.c -c | ||||||
|  |   - clang -c -w llvm_mode/afl-llvm-rt.o.c | ||||||
|  |   - wget https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/afl/afl_driver.cpp | ||||||
|  |   - clang++ afl_driver.cpp afl-llvm-rt.o.o test-libfuzzer-target.o -o test-libfuzzer-target | ||||||
|  |   - timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-libfuzzer-target | ||||||
|  |   - cd qemu_mode | ||||||
|  |   - ./build_qemu_support.sh | ||||||
|  |   - cd .. | ||||||
|  |   - gcc ./test-instr.c -o test-no-instr | ||||||
|  |   - if [ -z "$AFL_STOP_MANUALLY" ]; | ||||||
|  |     then ./afl-fuzz -Q -i seeds -o out/ -- ./test-no-instr; | ||||||
|  |     else timeout --preserve-status 5s ./afl-fuzz -Q -i seeds -o out/ -- ./test-no-instr; | ||||||
|  |     fi | ||||||
|  |   - .travis/check_fuzzer_stats.sh -o out -k peak_rss_mb -v 12 -p 9 | ||||||
| @ -0,0 +1,60 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | usage() {  | ||||||
|  |   echo "Usage: $0 -o <out_dir> -k <key> -v <value> [-p <precision>]" 1>&2; | ||||||
|  |   echo " " 1>&2; | ||||||
|  |   echo "Checks if a key:value appears in the fuzzer_stats report" 1>&2; | ||||||
|  |   echo " " 1>&2; | ||||||
|  |   echo -n "If \"value\" is numeric and \"precision\" is defined, checks if the stat " 1>&2; | ||||||
|  |   echo "printed by afl is value+/-precision." 1>&2; | ||||||
|  |   exit 1; } | ||||||
|  | 
 | ||||||
|  | while getopts "o:k:v:p:" opt;  do | ||||||
|  |   case "${opt}" in | ||||||
|  |       o) | ||||||
|  |         o=${OPTARG} | ||||||
|  |         ;; | ||||||
|  |       k) | ||||||
|  |         k=${OPTARG} | ||||||
|  |         ;; | ||||||
|  |       v) | ||||||
|  |         v=${OPTARG} | ||||||
|  |         ;; | ||||||
|  |       p) | ||||||
|  |         p=${OPTARG} | ||||||
|  |         ;; | ||||||
|  |       *) | ||||||
|  |         usage | ||||||
|  |         ;; | ||||||
|  |   esac | ||||||
|  | done | ||||||
|  | 
 | ||||||
|  | if [ -z $o ] || [ -z $k ] || [ -z $v ]; then usage; fi | ||||||
|  | 
 | ||||||
|  | # xargs to trim the surrounding whitespaces | ||||||
|  | stat_v=$( grep $k "$o"/fuzzer_stats | cut -d ":" -f 2 | xargs ) | ||||||
|  | v=$( echo "$v" | xargs ) | ||||||
|  | 
 | ||||||
|  | if [ -z stat_v ]; | ||||||
|  |   then echo "ERROR: key $k not found in fuzzer_stats." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | re_percent='^[0-9]+([.][0-9]+)?\%$' | ||||||
|  | # if the argument is a number in percentage, get rid of the % | ||||||
|  | if [[  "$v" =~ $re_percent ]]; then v=${v: :-1}; fi | ||||||
|  | if [[  "$stat_v" =~ $re_percent ]]; then stat_v=${stat_v: :-1}; fi | ||||||
|  | 
 | ||||||
|  | re_numeric='^[0-9]+([.][0-9]+)?$' | ||||||
|  | # if the argument is not a number, we check for strict equality | ||||||
|  | if (! [[  "$v" =~ $re_numeric ]]) || (! [[  "$stat_v" =~ $re ]]); | ||||||
|  |   then if [ "$v" != "$stat_v" ]; | ||||||
|  |     then echo "ERROR: \"$k:$stat_v\" (should be $v)." 1>&2 | ||||||
|  |     exit 2; | ||||||
|  |   fi | ||||||
|  | # checks if the stat reported by afl is in the range | ||||||
|  | elif [ "$stat_v" -lt $(( v - p )) ] || [ "$stat_v" -gt $(( v + p )) ]; | ||||||
|  |   then echo "ERROR: key $k:$stat_v is out of correct range." 1>&2 | ||||||
|  |   exit 3; | ||||||
|  | fi | ||||||
|  | echo "OK: key $k:$stat_v" 1>&2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,140 @@ | |||||||
|  | cc_defaults { | ||||||
|  |   name: "afl-defaults", | ||||||
|  | 
 | ||||||
|  |   cflags: [ | ||||||
|  |     "-funroll-loops", | ||||||
|  |     "-Wno-pointer-sign", | ||||||
|  |     "-Wno-pointer-arith", | ||||||
|  |     "-Wno-sign-compare", | ||||||
|  |     "-Wno-unused-parameter", | ||||||
|  |     "-Wno-unused-function", | ||||||
|  |     "-Wno-format", | ||||||
|  |     "-Wno-user-defined-warnings", | ||||||
|  |     "-DUSE_TRACE_PC=1", | ||||||
|  |     "-DBIN_PATH=\"out/host/linux-x86/bin\"", | ||||||
|  |     "-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"", | ||||||
|  |     "-D__USE_GNU", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary { | ||||||
|  |   name: "afl-fuzz", | ||||||
|  |   static_executable: true, | ||||||
|  |   host_supported: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "afl-fuzz.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary { | ||||||
|  |   name: "afl-showmap", | ||||||
|  |   static_executable: true, | ||||||
|  |   host_supported: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "afl-showmap.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary { | ||||||
|  |   name: "afl-tmin", | ||||||
|  |   static_executable: true, | ||||||
|  |   host_supported: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "afl-tmin.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary { | ||||||
|  |   name: "afl-analyze", | ||||||
|  |   static_executable: true, | ||||||
|  |   host_supported: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "afl-analyze.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary { | ||||||
|  |   name: "afl-gotcpu", | ||||||
|  |   static_executable: true, | ||||||
|  |   host_supported: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "afl-gotcpu.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary_host { | ||||||
|  |   name: "afl-clang-fast", | ||||||
|  |   static_executable: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   cflags: [ | ||||||
|  |     "-D__ANDROID__", | ||||||
|  |     "-DAFL_PATH=\"out/host/linux-x86/lib64\"", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "llvm_mode/afl-clang-fast.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_binary_host { | ||||||
|  |   name: "afl-clang-fast++", | ||||||
|  |   static_executable: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   cflags: [ | ||||||
|  |     "-D__ANDROID__", | ||||||
|  |     "-DAFL_PATH=\"out/host/linux-x86/lib64\"", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "llvm_mode/afl-clang-fast.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cc_library_static { | ||||||
|  |   name: "afl-llvm-rt", | ||||||
|  |   compile_multilib: "both", | ||||||
|  |   vendor_available: true, | ||||||
|  |   host_supported: true, | ||||||
|  |   recovery_available: true, | ||||||
|  | 
 | ||||||
|  |   defaults: [ | ||||||
|  |     "afl-defaults", | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   srcs: [ | ||||||
|  |     "llvm_mode/afl-llvm-rt.o.c", | ||||||
|  |   ], | ||||||
|  | } | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | # How to Contribute | ||||||
|  | 
 | ||||||
|  | We'd love to accept your patches and contributions to this project. There are | ||||||
|  | just a few small guidelines you need to follow. | ||||||
|  | 
 | ||||||
|  | ## Contributor License Agreement | ||||||
|  | 
 | ||||||
|  | Contributions to this project must be accompanied by a Contributor License | ||||||
|  | Agreement. You (or your employer) retain the copyright to your contribution; | ||||||
|  | this simply gives us permission to use and redistribute your contributions as | ||||||
|  | part of the project. Head over to <https://cla.developers.google.com/> to see | ||||||
|  | your current agreements on file or to sign a new one. | ||||||
|  | 
 | ||||||
|  | You generally only need to submit a CLA once, so if you've already submitted one | ||||||
|  | (even if it was for a different project), you probably don't need to do it | ||||||
|  | again. | ||||||
|  | 
 | ||||||
|  | ## Code reviews | ||||||
|  | 
 | ||||||
|  | All submissions, including submissions by project members, require review. We | ||||||
|  | use GitHub pull requests for this purpose. Consult | ||||||
|  | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more | ||||||
|  | information on using pull requests. | ||||||
|  | 
 | ||||||
|  | ## Community Guidelines | ||||||
|  | 
 | ||||||
|  | This project follows [Google's Open Source Community | ||||||
|  | Guidelines](https://opensource.google.com/conduct/). | ||||||
| @ -0,0 +1,202 @@ | |||||||
|  | 
 | ||||||
|  |                                  Apache License | ||||||
|  |                            Version 2.0, January 2004 | ||||||
|  |                         http://www.apache.org/licenses/ | ||||||
|  | 
 | ||||||
|  |    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  | 
 | ||||||
|  |    1. Definitions. | ||||||
|  | 
 | ||||||
|  |       "License" shall mean the terms and conditions for use, reproduction, | ||||||
|  |       and distribution as defined by Sections 1 through 9 of this document. | ||||||
|  | 
 | ||||||
|  |       "Licensor" shall mean the copyright owner or entity authorized by | ||||||
|  |       the copyright owner that is granting the License. | ||||||
|  | 
 | ||||||
|  |       "Legal Entity" shall mean the union of the acting entity and all | ||||||
|  |       other entities that control, are controlled by, or are under common | ||||||
|  |       control with that entity. For the purposes of this definition, | ||||||
|  |       "control" means (i) the power, direct or indirect, to cause the | ||||||
|  |       direction or management of such entity, whether by contract or | ||||||
|  |       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||||
|  |       outstanding shares, or (iii) beneficial ownership of such entity. | ||||||
|  | 
 | ||||||
|  |       "You" (or "Your") shall mean an individual or Legal Entity | ||||||
|  |       exercising permissions granted by this License. | ||||||
|  | 
 | ||||||
|  |       "Source" form shall mean the preferred form for making modifications, | ||||||
|  |       including but not limited to software source code, documentation | ||||||
|  |       source, and configuration files. | ||||||
|  | 
 | ||||||
|  |       "Object" form shall mean any form resulting from mechanical | ||||||
|  |       transformation or translation of a Source form, including but | ||||||
|  |       not limited to compiled object code, generated documentation, | ||||||
|  |       and conversions to other media types. | ||||||
|  | 
 | ||||||
|  |       "Work" shall mean the work of authorship, whether in Source or | ||||||
|  |       Object form, made available under the License, as indicated by a | ||||||
|  |       copyright notice that is included in or attached to the work | ||||||
|  |       (an example is provided in the Appendix below). | ||||||
|  | 
 | ||||||
|  |       "Derivative Works" shall mean any work, whether in Source or Object | ||||||
|  |       form, that is based on (or derived from) the Work and for which the | ||||||
|  |       editorial revisions, annotations, elaborations, or other modifications | ||||||
|  |       represent, as a whole, an original work of authorship. For the purposes | ||||||
|  |       of this License, Derivative Works shall not include works that remain | ||||||
|  |       separable from, or merely link (or bind by name) to the interfaces of, | ||||||
|  |       the Work and Derivative Works thereof. | ||||||
|  | 
 | ||||||
|  |       "Contribution" shall mean any work of authorship, including | ||||||
|  |       the original version of the Work and any modifications or additions | ||||||
|  |       to that Work or Derivative Works thereof, that is intentionally | ||||||
|  |       submitted to Licensor for inclusion in the Work by the copyright owner | ||||||
|  |       or by an individual or Legal Entity authorized to submit on behalf of | ||||||
|  |       the copyright owner. For the purposes of this definition, "submitted" | ||||||
|  |       means any form of electronic, verbal, or written communication sent | ||||||
|  |       to the Licensor or its representatives, including but not limited to | ||||||
|  |       communication on electronic mailing lists, source code control systems, | ||||||
|  |       and issue tracking systems that are managed by, or on behalf of, the | ||||||
|  |       Licensor for the purpose of discussing and improving the Work, but | ||||||
|  |       excluding communication that is conspicuously marked or otherwise | ||||||
|  |       designated in writing by the copyright owner as "Not a Contribution." | ||||||
|  | 
 | ||||||
|  |       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||||
|  |       on behalf of whom a Contribution has been received by Licensor and | ||||||
|  |       subsequently incorporated within the Work. | ||||||
|  | 
 | ||||||
|  |    2. Grant of Copyright License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       copyright license to reproduce, prepare Derivative Works of, | ||||||
|  |       publicly display, publicly perform, sublicense, and distribute the | ||||||
|  |       Work and such Derivative Works in Source or Object form. | ||||||
|  | 
 | ||||||
|  |    3. Grant of Patent License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       (except as stated in this section) patent license to make, have made, | ||||||
|  |       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||||
|  |       where such license applies only to those patent claims licensable | ||||||
|  |       by such Contributor that are necessarily infringed by their | ||||||
|  |       Contribution(s) alone or by combination of their Contribution(s) | ||||||
|  |       with the Work to which such Contribution(s) was submitted. If You | ||||||
|  |       institute patent litigation against any entity (including a | ||||||
|  |       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||||
|  |       or a Contribution incorporated within the Work constitutes direct | ||||||
|  |       or contributory patent infringement, then any patent licenses | ||||||
|  |       granted to You under this License for that Work shall terminate | ||||||
|  |       as of the date such litigation is filed. | ||||||
|  | 
 | ||||||
|  |    4. Redistribution. You may reproduce and distribute copies of the | ||||||
|  |       Work or Derivative Works thereof in any medium, with or without | ||||||
|  |       modifications, and in Source or Object form, provided that You | ||||||
|  |       meet the following conditions: | ||||||
|  | 
 | ||||||
|  |       (a) You must give any other recipients of the Work or | ||||||
|  |           Derivative Works a copy of this License; and | ||||||
|  | 
 | ||||||
|  |       (b) You must cause any modified files to carry prominent notices | ||||||
|  |           stating that You changed the files; and | ||||||
|  | 
 | ||||||
|  |       (c) You must retain, in the Source form of any Derivative Works | ||||||
|  |           that You distribute, all copyright, patent, trademark, and | ||||||
|  |           attribution notices from the Source form of the Work, | ||||||
|  |           excluding those notices that do not pertain to any part of | ||||||
|  |           the Derivative Works; and | ||||||
|  | 
 | ||||||
|  |       (d) If the Work includes a "NOTICE" text file as part of its | ||||||
|  |           distribution, then any Derivative Works that You distribute must | ||||||
|  |           include a readable copy of the attribution notices contained | ||||||
|  |           within such NOTICE file, excluding those notices that do not | ||||||
|  |           pertain to any part of the Derivative Works, in at least one | ||||||
|  |           of the following places: within a NOTICE text file distributed | ||||||
|  |           as part of the Derivative Works; within the Source form or | ||||||
|  |           documentation, if provided along with the Derivative Works; or, | ||||||
|  |           within a display generated by the Derivative Works, if and | ||||||
|  |           wherever such third-party notices normally appear. The contents | ||||||
|  |           of the NOTICE file are for informational purposes only and | ||||||
|  |           do not modify the License. You may add Your own attribution | ||||||
|  |           notices within Derivative Works that You distribute, alongside | ||||||
|  |           or as an addendum to the NOTICE text from the Work, provided | ||||||
|  |           that such additional attribution notices cannot be construed | ||||||
|  |           as modifying the License. | ||||||
|  | 
 | ||||||
|  |       You may add Your own copyright statement to Your modifications and | ||||||
|  |       may provide additional or different license terms and conditions | ||||||
|  |       for use, reproduction, or distribution of Your modifications, or | ||||||
|  |       for any such Derivative Works as a whole, provided Your use, | ||||||
|  |       reproduction, and distribution of the Work otherwise complies with | ||||||
|  |       the conditions stated in this License. | ||||||
|  | 
 | ||||||
|  |    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||||
|  |       any Contribution intentionally submitted for inclusion in the Work | ||||||
|  |       by You to the Licensor shall be under the terms and conditions of | ||||||
|  |       this License, without any additional terms or conditions. | ||||||
|  |       Notwithstanding the above, nothing herein shall supersede or modify | ||||||
|  |       the terms of any separate license agreement you may have executed | ||||||
|  |       with Licensor regarding such Contributions. | ||||||
|  | 
 | ||||||
|  |    6. Trademarks. This License does not grant permission to use the trade | ||||||
|  |       names, trademarks, service marks, or product names of the Licensor, | ||||||
|  |       except as required for reasonable and customary use in describing the | ||||||
|  |       origin of the Work and reproducing the content of the NOTICE file. | ||||||
|  | 
 | ||||||
|  |    7. Disclaimer of Warranty. Unless required by applicable law or | ||||||
|  |       agreed to in writing, Licensor provides the Work (and each | ||||||
|  |       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||||
|  |       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||||
|  |       implied, including, without limitation, any warranties or conditions | ||||||
|  |       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||||
|  |       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||||
|  |       appropriateness of using or redistributing the Work and assume any | ||||||
|  |       risks associated with Your exercise of permissions under this License. | ||||||
|  | 
 | ||||||
|  |    8. Limitation of Liability. In no event and under no legal theory, | ||||||
|  |       whether in tort (including negligence), contract, or otherwise, | ||||||
|  |       unless required by applicable law (such as deliberate and grossly | ||||||
|  |       negligent acts) or agreed to in writing, shall any Contributor be | ||||||
|  |       liable to You for damages, including any direct, indirect, special, | ||||||
|  |       incidental, or consequential damages of any character arising as a | ||||||
|  |       result of this License or out of the use or inability to use the | ||||||
|  |       Work (including but not limited to damages for loss of goodwill, | ||||||
|  |       work stoppage, computer failure or malfunction, or any and all | ||||||
|  |       other commercial damages or losses), even if such Contributor | ||||||
|  |       has been advised of the possibility of such damages. | ||||||
|  | 
 | ||||||
|  |    9. Accepting Warranty or Additional Liability. While redistributing | ||||||
|  |       the Work or Derivative Works thereof, You may choose to offer, | ||||||
|  |       and charge a fee for, acceptance of support, warranty, indemnity, | ||||||
|  |       or other liability obligations and/or rights consistent with this | ||||||
|  |       License. However, in accepting such obligations, You may act only | ||||||
|  |       on Your own behalf and on Your sole responsibility, not on behalf | ||||||
|  |       of any other Contributor, and only if You agree to indemnify, | ||||||
|  |       defend, and hold each Contributor harmless for any liability | ||||||
|  |       incurred by, or claims asserted against, such Contributor by reason | ||||||
|  |       of your accepting any such warranty or additional liability. | ||||||
|  | 
 | ||||||
|  |    END OF TERMS AND CONDITIONS | ||||||
|  | 
 | ||||||
|  |    APPENDIX: How to apply the Apache License to your work. | ||||||
|  | 
 | ||||||
|  |       To apply the Apache License to your work, attach the following | ||||||
|  |       boilerplate notice, with the fields enclosed by brackets "[]" | ||||||
|  |       replaced with your own identifying information. (Don't include | ||||||
|  |       the brackets!)  The text should be enclosed in the appropriate | ||||||
|  |       comment syntax for the file format. We also recommend that a | ||||||
|  |       file or class name and description of purpose be included on the | ||||||
|  |       same "printed page" as the copyright notice for easier | ||||||
|  |       identification within third-party archives. | ||||||
|  | 
 | ||||||
|  |    Copyright [yyyy] [name of copyright owner] | ||||||
|  | 
 | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | 
 | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
| @ -0,0 +1,153 @@ | |||||||
|  | #
 | ||||||
|  | # american fuzzy lop - makefile
 | ||||||
|  | # -----------------------------
 | ||||||
|  | #
 | ||||||
|  | # Written and maintained by Michal Zalewski <lcamtuf@google.com>
 | ||||||
|  | # 
 | ||||||
|  | # Copyright 2013, 2014, 2015, 2016, 2017 Google LLC All rights reserved.
 | ||||||
|  | # 
 | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | # you may not use this file except in compliance with the License.
 | ||||||
|  | # You may obtain a copy of the License at:
 | ||||||
|  | # 
 | ||||||
|  | #   http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | #
 | ||||||
|  | 
 | ||||||
|  | PROGNAME    = afl | ||||||
|  | VERSION     = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) | ||||||
|  | 
 | ||||||
|  | PREFIX     ?= /usr/local | ||||||
|  | BIN_PATH    = $(PREFIX)/bin | ||||||
|  | HELPER_PATH = $(PREFIX)/lib/afl | ||||||
|  | DOC_PATH    = $(PREFIX)/share/doc/afl | ||||||
|  | MISC_PATH   = $(PREFIX)/share/afl | ||||||
|  | 
 | ||||||
|  | # PROGS intentionally omit afl-as, which gets installed elsewhere.
 | ||||||
|  | 
 | ||||||
|  | PROGS       = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze | ||||||
|  | SH_PROGS    = afl-plot afl-cmin afl-whatsup | ||||||
|  | 
 | ||||||
|  | CFLAGS     ?= -O3 -funroll-loops | ||||||
|  | CFLAGS     += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
 | ||||||
|  | 	      -DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \
 | ||||||
|  | 	      -DBIN_PATH=\"$(BIN_PATH)\" | ||||||
|  | 
 | ||||||
|  | ifneq "$(filter Linux GNU%,$(shell uname))" "" | ||||||
|  |   LDFLAGS  += -ldl | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" | ||||||
|  |   TEST_CC   = afl-gcc | ||||||
|  | else | ||||||
|  |   TEST_CC   = afl-clang | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | COMM_HDR    = alloc-inl.h config.h debug.h types.h | ||||||
|  | 
 | ||||||
|  | all: test_x86 $(PROGS) afl-as test_build all_done | ||||||
|  | 
 | ||||||
|  | ifndef AFL_NO_X86 | ||||||
|  | 
 | ||||||
|  | test_x86: | ||||||
|  | 	@echo "[*] Checking for the ability to compile x86 code..." | ||||||
|  | 	@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) | ||||||
|  | 	@rm -f .test | ||||||
|  | 	@echo "[+] Everything seems to be working, ready to compile." | ||||||
|  | 
 | ||||||
|  | else | ||||||
|  | 
 | ||||||
|  | test_x86: | ||||||
|  | 	@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)." | ||||||
|  | 
 | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | afl-gcc: afl-gcc.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 	set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done | ||||||
|  | 
 | ||||||
|  | afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 	ln -sf afl-as as | ||||||
|  | 
 | ||||||
|  | afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 
 | ||||||
|  | afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 
 | ||||||
|  | afl-tmin: afl-tmin.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 
 | ||||||
|  | afl-analyze: afl-analyze.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 
 | ||||||
|  | afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86 | ||||||
|  | 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||||||
|  | 
 | ||||||
|  | ifndef AFL_NO_X86 | ||||||
|  | 
 | ||||||
|  | test_build: afl-gcc afl-as afl-showmap | ||||||
|  | 	@echo "[*] Testing the CC wrapper and instrumentation output..." | ||||||
|  | 	unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) | ||||||
|  | 	./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null | ||||||
|  | 	echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr | ||||||
|  | 	@rm -f test-instr | ||||||
|  | 	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping <lcamtuf@google.com> to troubleshoot the issue."; echo; exit 1; fi | ||||||
|  | 	@echo "[+] All right, the instrumentation seems to be working!" | ||||||
|  | 
 | ||||||
|  | else | ||||||
|  | 
 | ||||||
|  | test_build: afl-gcc afl-as afl-showmap | ||||||
|  | 	@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)." | ||||||
|  | 
 | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | all_done: test_build | ||||||
|  | 	@if [ ! "`which clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.llvm for a faster alternative to afl-gcc."; fi | ||||||
|  | 	@echo "[+] All done! Be sure to review README - it's pretty short and useful." | ||||||
|  | 	@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi | ||||||
|  | 	@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.txt for advice.\033[0m\n" 2>/dev/null | ||||||
|  | 
 | ||||||
|  | .NOTPARALLEL: clean | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -f $(PROGS) afl-as as afl-g++ afl-clang afl-clang++ *.o *~ a.out core core.[1-9][0-9]* *.stackdump test .test test-instr .test-instr0 .test-instr1 qemu_mode/qemu-2.10.0.tar.bz2 afl-qemu-trace | ||||||
|  | 	rm -rf out_dir qemu_mode/qemu-2.10.0 | ||||||
|  | 	$(MAKE) -C llvm_mode clean | ||||||
|  | 	$(MAKE) -C libdislocator clean | ||||||
|  | 	$(MAKE) -C libtokencap clean | ||||||
|  | 
 | ||||||
|  | install: all | ||||||
|  | 	mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) | ||||||
|  | 	rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh | ||||||
|  | 	install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) | ||||||
|  | 	rm -f $${DESTDIR}$(BIN_PATH)/afl-as | ||||||
|  | 	if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi | ||||||
|  | ifndef AFL_TRACE_PC | ||||||
|  | 	if [ -f afl-clang-fast -a -f afl-llvm-pass.so -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-pass.so afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi | ||||||
|  | else | ||||||
|  | 	if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi | ||||||
|  | endif | ||||||
|  | 	if [ -f afl-llvm-rt-32.o ]; then set -e; install -m 755 afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi | ||||||
|  | 	if [ -f afl-llvm-rt-64.o ]; then set -e; install -m 755 afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi | ||||||
|  | 	set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/$$i; done | ||||||
|  | 	install -m 755 afl-as $${DESTDIR}$(HELPER_PATH) | ||||||
|  | 	ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as | ||||||
|  | 	install -m 644 README.md docs/ChangeLog docs/*.txt $${DESTDIR}$(DOC_PATH) | ||||||
|  | 	cp -r testcases/ $${DESTDIR}$(MISC_PATH) | ||||||
|  | 	cp -r dictionaries/ $${DESTDIR}$(MISC_PATH) | ||||||
|  | 
 | ||||||
|  | publish: clean | ||||||
|  | 	test "`basename $$PWD`" = "AFL" || exit 1 | ||||||
|  | 	test -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz; if [ "$$?" = "0" ]; then echo; echo "Change program version in config.h, mmkay?"; echo; exit 1; fi | ||||||
|  | 	cd ..; rm -rf $(PROGNAME)-$(VERSION); cp -pr $(PROGNAME) $(PROGNAME)-$(VERSION); \
 | ||||||
|  | 	  tar -cvz -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz $(PROGNAME)-$(VERSION) | ||||||
|  | 	chmod 644 ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz | ||||||
|  | 	( cd ~/www/afl/releases/; ln -s -f $(PROGNAME)-$(VERSION).tgz $(PROGNAME)-latest.tgz ) | ||||||
|  | 	cat docs/README >~/www/afl/README.txt | ||||||
|  | 	cat docs/status_screen.txt >~/www/afl/status_screen.txt | ||||||
|  | 	cat docs/historical_notes.txt >~/www/afl/historical_notes.txt | ||||||
|  | 	cat docs/technical_details.txt >~/www/afl/technical_details.txt | ||||||
|  | 	cat docs/ChangeLog >~/www/afl/ChangeLog.txt | ||||||
|  | 	cat docs/QuickStartGuide.txt >~/www/afl/QuickStartGuide.txt | ||||||
|  | 	echo -n "$(VERSION)" >~/www/afl/version.txt | ||||||
| @ -0,0 +1,493 @@ | |||||||
|  | # american fuzzy lop | ||||||
|  | 
 | ||||||
|  | [](https://travis-ci.org/google/AFL) | ||||||
|  | 
 | ||||||
|  | Originally developed by Michal Zalewski <lcamtuf@google.com>. | ||||||
|  | 
 | ||||||
|  | See [QuickStartGuide.txt](docs/QuickStartGuide.txt) if you don't have time to read | ||||||
|  | this file. | ||||||
|  | 
 | ||||||
|  | ## 1) Challenges of guided fuzzing | ||||||
|  | 
 | ||||||
|  | Fuzzing is one of the most powerful and proven strategies for identifying | ||||||
|  | security issues in real-world software; it is responsible for the vast | ||||||
|  | majority of remote code execution and privilege escalation bugs found to date | ||||||
|  | in security-critical software. | ||||||
|  | 
 | ||||||
|  | Unfortunately, fuzzing is also relatively shallow; blind, random mutations | ||||||
|  | make it very unlikely to reach certain code paths in the tested code, leaving | ||||||
|  | some vulnerabilities firmly outside the reach of this technique. | ||||||
|  | 
 | ||||||
|  | There have been numerous attempts to solve this problem. One of the early | ||||||
|  | approaches - pioneered by Tavis Ormandy - is corpus distillation. The method | ||||||
|  | relies on coverage signals to select a subset of interesting seeds from a | ||||||
|  | massive, high-quality corpus of candidate files, and then fuzz them by | ||||||
|  | traditional means. The approach works exceptionally well, but requires such | ||||||
|  | a corpus to be readily available. In addition, block coverage measurements | ||||||
|  | provide only a very simplistic understanding of program state, and are less | ||||||
|  | useful for guiding the fuzzing effort in the long haul. | ||||||
|  | 
 | ||||||
|  | Other, more sophisticated research has focused on techniques such as program | ||||||
|  | flow analysis ("concolic execution"), symbolic execution, or static analysis. | ||||||
|  | All these methods are extremely promising in experimental settings, but tend | ||||||
|  | to suffer from reliability and performance problems in practical uses - and | ||||||
|  | currently do not offer a viable alternative to "dumb" fuzzing techniques. | ||||||
|  | 
 | ||||||
|  | ## 2) The afl-fuzz approach | ||||||
|  | 
 | ||||||
|  | American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple | ||||||
|  | but rock-solid instrumentation-guided genetic algorithm. It uses a modified | ||||||
|  | form of edge coverage to effortlessly pick up subtle, local-scale changes to | ||||||
|  | program control flow. | ||||||
|  | 
 | ||||||
|  | Simplifying a bit, the overall algorithm can be summed up as: | ||||||
|  | 
 | ||||||
|  |   1) Load user-supplied initial test cases into the queue, | ||||||
|  | 
 | ||||||
|  |   2) Take next input file from the queue, | ||||||
|  | 
 | ||||||
|  |   3) Attempt to trim the test case to the smallest size that doesn't alter | ||||||
|  |      the measured behavior of the program, | ||||||
|  | 
 | ||||||
|  |   4) Repeatedly mutate the file using a balanced and well-researched variety | ||||||
|  |      of traditional fuzzing strategies, | ||||||
|  | 
 | ||||||
|  |   5) If any of the generated mutations resulted in a new state transition | ||||||
|  |      recorded by the instrumentation, add mutated output as a new entry in the | ||||||
|  |      queue. | ||||||
|  | 
 | ||||||
|  |   6) Go to 2. | ||||||
|  | 
 | ||||||
|  | The discovered test cases are also periodically culled to eliminate ones that | ||||||
|  | have been obsoleted by newer, higher-coverage finds; and undergo several other | ||||||
|  | instrumentation-driven effort minimization steps. | ||||||
|  | 
 | ||||||
|  | As a side result of the fuzzing process, the tool creates a small, | ||||||
|  | self-contained corpus of interesting test cases. These are extremely useful | ||||||
|  | for seeding other, labor- or resource-intensive testing regimes - for example, | ||||||
|  | for stress-testing browsers, office applications, graphics suites, or | ||||||
|  | closed-source tools. | ||||||
|  | 
 | ||||||
|  | The fuzzer is thoroughly tested to deliver out-of-the-box performance far | ||||||
|  | superior to blind fuzzing or coverage-only tools. | ||||||
|  | 
 | ||||||
|  | ## 3) Instrumenting programs for use with AFL | ||||||
|  | 
 | ||||||
|  | When source code is available, instrumentation can be injected by a companion | ||||||
|  | tool that works as a drop-in replacement for gcc or clang in any standard build | ||||||
|  | process for third-party code. | ||||||
|  | 
 | ||||||
|  | The instrumentation has a fairly modest performance impact; in conjunction with | ||||||
|  | other optimizations implemented by afl-fuzz, most programs can be fuzzed as fast | ||||||
|  | or even faster than possible with traditional tools. | ||||||
|  | 
 | ||||||
|  | The correct way to recompile the target program may vary depending on the | ||||||
|  | specifics of the build process, but a nearly-universal approach would be: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ CC=/path/to/afl/afl-gcc ./configure | ||||||
|  | $ make clean all | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`. | ||||||
|  | 
 | ||||||
|  | The clang wrappers (afl-clang and afl-clang++) can be used in the same way; | ||||||
|  | clang users may also opt to leverage a higher-performance instrumentation mode, | ||||||
|  | as described in llvm_mode/README.llvm. | ||||||
|  | 
 | ||||||
|  | When testing libraries, you need to find or write a simple program that reads | ||||||
|  | data from stdin or from a file and passes it to the tested library. In such a | ||||||
|  | case, it is essential to link this executable against a static version of the | ||||||
|  | instrumented library, or to make sure that the correct .so file is loaded at | ||||||
|  | runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static | ||||||
|  | build, usually possible via: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ CC=/path/to/afl/afl-gcc ./configure --disable-shared | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Setting `AFL_HARDEN=1` when calling 'make' will cause the CC wrapper to | ||||||
|  | automatically enable code hardening options that make it easier to detect | ||||||
|  | simple memory bugs. Libdislocator, a helper library included with AFL (see | ||||||
|  | libdislocator/README.dislocator) can help uncover heap corruption issues, too. | ||||||
|  | 
 | ||||||
|  | PS. ASAN users are advised to review [notes_for_asan.txt](docs/notes_for_asan.txt) file for important | ||||||
|  | caveats. | ||||||
|  | 
 | ||||||
|  | ## 4) Instrumenting binary-only apps | ||||||
|  | 
 | ||||||
|  | When source code is *NOT* available, the fuzzer offers experimental support for | ||||||
|  | fast, on-the-fly instrumentation of black-box binaries. This is accomplished | ||||||
|  | with a version of QEMU running in the lesser-known "user space emulation" mode. | ||||||
|  | 
 | ||||||
|  | QEMU is a project separate from AFL, but you can conveniently build the | ||||||
|  | feature by doing: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ cd qemu_mode | ||||||
|  | $ ./build_qemu_support.sh | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | For additional instructions and caveats, see qemu_mode/README.qemu. | ||||||
|  | 
 | ||||||
|  | The mode is approximately 2-5x slower than compile-time instrumentation, is | ||||||
|  | less conducive to parallelization, and may have some other quirks. | ||||||
|  | 
 | ||||||
|  | ## 5) Choosing initial test cases | ||||||
|  | 
 | ||||||
|  | To operate correctly, the fuzzer requires one or more starting file that | ||||||
|  | contains a good example of the input data normally expected by the targeted | ||||||
|  | application. There are two basic rules: | ||||||
|  | 
 | ||||||
|  |   - Keep the files small. Under 1 kB is ideal, although not strictly necessary. | ||||||
|  |     For a discussion of why size matters, see [perf_tips.txt](docs/perf_tips.txt). | ||||||
|  | 
 | ||||||
|  |   - Use multiple test cases only if they are functionally different from | ||||||
|  |     each other. There is no point in using fifty different vacation photos | ||||||
|  |     to fuzz an image library. | ||||||
|  | 
 | ||||||
|  | You can find many good examples of starting files in the testcases/ subdirectory | ||||||
|  | that comes with this tool. | ||||||
|  | 
 | ||||||
|  | PS. If a large corpus of data is available for screening, you may want to use | ||||||
|  | the afl-cmin utility to identify a subset of functionally distinct files that | ||||||
|  | exercise different code paths in the target binary. | ||||||
|  | 
 | ||||||
|  | ## 6) Fuzzing binaries | ||||||
|  | 
 | ||||||
|  | The fuzzing process itself is carried out by the afl-fuzz utility. This program | ||||||
|  | requires a read-only directory with initial test cases, a separate place to | ||||||
|  | store its findings, plus a path to the binary to test. | ||||||
|  | 
 | ||||||
|  | For target binaries that accept input directly from stdin, the usual syntax is: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | For programs that take input from a file, use '@@' to mark the location in | ||||||
|  | the target's command line where the input file name should be placed. The | ||||||
|  | fuzzer will substitute this for you: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@ | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You can also use the -f option to have the mutated data written to a specific | ||||||
|  | file. This is useful if the program expects a particular file extension or so. | ||||||
|  | 
 | ||||||
|  | Non-instrumented binaries can be fuzzed in the QEMU mode (add -Q in the command | ||||||
|  | line) or in a traditional, blind-fuzzer mode (specify -n). | ||||||
|  | 
 | ||||||
|  | You can use -t and -m to override the default timeout and memory limit for the | ||||||
|  | executed process; rare examples of targets that may need these settings touched | ||||||
|  | include compilers and video decoders. | ||||||
|  | 
 | ||||||
|  | Tips for optimizing fuzzing performance are discussed in [perf_tips.txt](docs/perf_tips.txt). | ||||||
|  | 
 | ||||||
|  | Note that afl-fuzz starts by performing an array of deterministic fuzzing | ||||||
|  | steps, which can take several days, but tend to produce neat test cases. If you | ||||||
|  | want quick & dirty results right away - akin to zzuf and other traditional | ||||||
|  | fuzzers - add the -d option to the command line. | ||||||
|  | 
 | ||||||
|  | ## 7) Interpreting output | ||||||
|  | 
 | ||||||
|  | See the [status_screen.txt](docs/status_screen.txt) file for information on | ||||||
|  | how to interpret the displayed stats and monitor the health of the process. | ||||||
|  | Be sure to consult this file especially if any UI elements are highlighted in | ||||||
|  | red. | ||||||
|  | 
 | ||||||
|  | The fuzzing process will continue until you press Ctrl-C. At minimum, you want | ||||||
|  | to allow the fuzzer to complete one queue cycle, which may take anywhere from a | ||||||
|  | couple of hours to a week or so. | ||||||
|  | 
 | ||||||
|  | There are three subdirectories created within the output directory and updated | ||||||
|  | in real time: | ||||||
|  | 
 | ||||||
|  |   - queue/   - test cases for every distinctive execution path, plus all the | ||||||
|  |                starting files given by the user. This is the synthesized corpus | ||||||
|  |                mentioned in section 2. | ||||||
|  |                Before using this corpus for any other purposes, you can shrink | ||||||
|  |                it to a smaller size using the afl-cmin tool. The tool will find | ||||||
|  |                a smaller subset of files offering equivalent edge coverage. | ||||||
|  | 
 | ||||||
|  |   - crashes/ - unique test cases that cause the tested program to receive a | ||||||
|  |                fatal signal (e.g., SIGSEGV, SIGILL, SIGABRT). The entries are | ||||||
|  |                grouped by the received signal. | ||||||
|  | 
 | ||||||
|  |   - hangs/   - unique test cases that cause the tested program to time out. The | ||||||
|  |                default time limit before something is classified as a hang is | ||||||
|  |                the larger of 1 second and the value of the -t parameter. | ||||||
|  |                The value can be fine-tuned by setting AFL_HANG_TMOUT, but this | ||||||
|  |                is rarely necessary. | ||||||
|  | 
 | ||||||
|  | Crashes and hangs are considered "unique" if the associated execution paths | ||||||
|  | involve any state transitions not seen in previously-recorded faults. If a | ||||||
|  | single bug can be reached in multiple ways, there will be some count inflation | ||||||
|  | early in the process, but this should quickly taper off. | ||||||
|  | 
 | ||||||
|  | The file names for crashes and hangs are correlated with parent, non-faulting | ||||||
|  | queue entries. This should help with debugging. | ||||||
|  | 
 | ||||||
|  | When you can't reproduce a crash found by afl-fuzz, the most likely cause is | ||||||
|  | that you are not setting the same memory limit as used by the tool. Try: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ LIMIT_MB=50 | ||||||
|  | $ ( ulimit -Sv $[LIMIT_MB << 10]; /path/to/tested_binary ... ) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Change LIMIT_MB to match the -m parameter passed to afl-fuzz. On OpenBSD, | ||||||
|  | also change -Sv to -Sd. | ||||||
|  | 
 | ||||||
|  | Any existing output directory can be also used to resume aborted jobs; try: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ ./afl-fuzz -i- -o existing_output_dir [...etc...] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | If you have gnuplot installed, you can also generate some pretty graphs for any | ||||||
|  | active fuzzing task using afl-plot. For an example of how this looks like, | ||||||
|  | see [http://lcamtuf.coredump.cx/afl/plot/](http://lcamtuf.coredump.cx/afl/plot/). | ||||||
|  | 
 | ||||||
|  | ## 8) Parallelized fuzzing | ||||||
|  | 
 | ||||||
|  | Every instance of afl-fuzz takes up roughly one core. This means that on | ||||||
|  | multi-core systems, parallelization is necessary to fully utilize the hardware. | ||||||
|  | For tips on how to fuzz a common target on multiple cores or multiple networked | ||||||
|  | machines, please refer to [parallel_fuzzing.txt](docs/parallel_fuzzing.txt). | ||||||
|  | 
 | ||||||
|  | The parallel fuzzing mode also offers a simple way for interfacing AFL to other | ||||||
|  | fuzzers, to symbolic or concolic execution engines, and so forth; again, see the | ||||||
|  | last section of [parallel_fuzzing.txt](docs/parallel_fuzzing.txt) for tips. | ||||||
|  | 
 | ||||||
|  | ## 9) Fuzzer dictionaries | ||||||
|  | 
 | ||||||
|  | By default, afl-fuzz mutation engine is optimized for compact data formats - | ||||||
|  | say, images, multimedia, compressed data, regular expression syntax, or shell | ||||||
|  | scripts. It is somewhat less suited for languages with particularly verbose and | ||||||
|  | redundant verbiage - notably including HTML, SQL, or JavaScript. | ||||||
|  | 
 | ||||||
|  | To avoid the hassle of building syntax-aware tools, afl-fuzz provides a way to | ||||||
|  | seed the fuzzing process with an optional dictionary of language keywords, | ||||||
|  | magic headers, or other special tokens associated with the targeted data type | ||||||
|  | -- and use that to reconstruct the underlying grammar on the go: | ||||||
|  | 
 | ||||||
|  |   [http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html](http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html) | ||||||
|  | 
 | ||||||
|  | To use this feature, you first need to create a dictionary in one of the two | ||||||
|  | formats discussed in dictionaries/README.dictionaries; and then point the fuzzer | ||||||
|  | to it via the -x option in the command line. | ||||||
|  | 
 | ||||||
|  | (Several common dictionaries are already provided in that subdirectory, too.) | ||||||
|  | 
 | ||||||
|  | There is no way to provide more structured descriptions of the underlying | ||||||
|  | syntax, but the fuzzer will likely figure out some of this based on the | ||||||
|  | instrumentation feedback alone. This actually works in practice, say: | ||||||
|  | 
 | ||||||
|  |   [http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html](http://lcamtuf.blogspot.com/2015/04/finding-bugs-in-sqlite-easy-way.html) | ||||||
|  | 
 | ||||||
|  | PS. Even when no explicit dictionary is given, afl-fuzz will try to extract | ||||||
|  | existing syntax tokens in the input corpus by watching the instrumentation | ||||||
|  | very closely during deterministic byte flips. This works for some types of | ||||||
|  | parsers and grammars, but isn't nearly as good as the -x mode. | ||||||
|  | 
 | ||||||
|  | If a dictionary is really hard to come by, another option is to let AFL run | ||||||
|  | for a while, and then use the token capture library that comes as a companion | ||||||
|  | utility with AFL. For that, see libtokencap/README.tokencap. | ||||||
|  | 
 | ||||||
|  | ## 10) Crash triage | ||||||
|  | 
 | ||||||
|  | The coverage-based grouping of crashes usually produces a small data set that | ||||||
|  | can be quickly triaged manually or with a very simple GDB or Valgrind script. | ||||||
|  | Every crash is also traceable to its parent non-crashing test case in the | ||||||
|  | queue, making it easier to diagnose faults. | ||||||
|  | 
 | ||||||
|  | Having said that, it's important to acknowledge that some fuzzing crashes can be | ||||||
|  | difficult to quickly evaluate for exploitability without a lot of debugging and | ||||||
|  | code analysis work. To assist with this task, afl-fuzz supports a very unique | ||||||
|  | "crash exploration" mode enabled with the -C flag. | ||||||
|  | 
 | ||||||
|  | In this mode, the fuzzer takes one or more crashing test cases as the input, | ||||||
|  | and uses its feedback-driven fuzzing strategies to very quickly enumerate all | ||||||
|  | code paths that can be reached in the program while keeping it in the | ||||||
|  | crashing state. | ||||||
|  | 
 | ||||||
|  | Mutations that do not result in a crash are rejected; so are any changes that | ||||||
|  | do not affect the execution path. | ||||||
|  | 
 | ||||||
|  | The output is a small corpus of files that can be very rapidly examined to see | ||||||
|  | what degree of control the attacker has over the faulting address, or whether | ||||||
|  | it is possible to get past an initial out-of-bounds read - and see what lies | ||||||
|  | beneath. | ||||||
|  | 
 | ||||||
|  | Oh, one more thing: for test case minimization, give afl-tmin a try. The tool | ||||||
|  | can be operated in a very simple way: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  | $ ./afl-tmin -i test_case -o minimized_result -- /path/to/program [...] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The tool works with crashing and non-crashing test cases alike. In the crash | ||||||
|  | mode, it will happily accept instrumented and non-instrumented binaries. In the | ||||||
|  | non-crashing mode, the minimizer relies on standard AFL instrumentation to make | ||||||
|  | the file simpler without altering the execution path. | ||||||
|  | 
 | ||||||
|  | The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with | ||||||
|  | afl-fuzz. | ||||||
|  | 
 | ||||||
|  | Another recent addition to AFL is the afl-analyze tool. It takes an input | ||||||
|  | file, attempts to sequentially flip bytes, and observes the behavior of the | ||||||
|  | tested program. It then color-codes the input based on which sections appear to | ||||||
|  | be critical, and which are not; while not bulletproof, it can often offer quick | ||||||
|  | insights into complex file formats. More info about its operation can be found | ||||||
|  | near the end of [technical_details.txt](docs/technical_details.txt). | ||||||
|  | 
 | ||||||
|  | ## 11) Going beyond crashes | ||||||
|  | 
 | ||||||
|  | Fuzzing is a wonderful and underutilized technique for discovering non-crashing | ||||||
|  | design and implementation errors, too. Quite a few interesting bugs have been | ||||||
|  | found by modifying the target programs to call abort() when, say: | ||||||
|  | 
 | ||||||
|  |   - Two bignum libraries produce different outputs when given the same | ||||||
|  |     fuzzer-generated input, | ||||||
|  | 
 | ||||||
|  |   - An image library produces different outputs when asked to decode the same | ||||||
|  |     input image several times in a row, | ||||||
|  | 
 | ||||||
|  |   - A serialization / deserialization library fails to produce stable outputs | ||||||
|  |     when iteratively serializing and deserializing fuzzer-supplied data, | ||||||
|  | 
 | ||||||
|  |   - A compression library produces an output inconsistent with the input file | ||||||
|  |     when asked to compress and then decompress a particular blob. | ||||||
|  | 
 | ||||||
|  | Implementing these or similar sanity checks usually takes very little time; | ||||||
|  | if you are the maintainer of a particular package, you can make this code | ||||||
|  | conditional with `#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` (a flag also | ||||||
|  | shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL). | ||||||
|  | 
 | ||||||
|  | ## 12) Common-sense risks | ||||||
|  | 
 | ||||||
|  | Please keep in mind that, similarly to many other computationally-intensive | ||||||
|  | tasks, fuzzing may put strain on your hardware and on the OS. In particular: | ||||||
|  | 
 | ||||||
|  |   - Your CPU will run hot and will need adequate cooling. In most cases, if | ||||||
|  |     cooling is insufficient or stops working properly, CPU speeds will be | ||||||
|  |     automatically throttled. That said, especially when fuzzing on less | ||||||
|  |     suitable hardware (laptops, smartphones, etc), it's not entirely impossible | ||||||
|  |     for something to blow up. | ||||||
|  | 
 | ||||||
|  |   - Targeted programs may end up erratically grabbing gigabytes of memory or | ||||||
|  |     filling up disk space with junk files. AFL tries to enforce basic memory | ||||||
|  |     limits, but can't prevent each and every possible mishap. The bottom line | ||||||
|  |     is that you shouldn't be fuzzing on systems where the prospect of data loss | ||||||
|  |     is not an acceptable risk. | ||||||
|  | 
 | ||||||
|  |   - Fuzzing involves billions of reads and writes to the filesystem. On modern | ||||||
|  |     systems, this will be usually heavily cached, resulting in fairly modest | ||||||
|  |     "physical" I/O - but there are many factors that may alter this equation. | ||||||
|  |     It is your responsibility to monitor for potential trouble; with very heavy | ||||||
|  |     I/O, the lifespan of many HDDs and SSDs may be reduced. | ||||||
|  | 
 | ||||||
|  |     A good way to monitor disk I/O on Linux is the 'iostat' command: | ||||||
|  | 
 | ||||||
|  | ```shell | ||||||
|  |     $ iostat -d 3 -x -k [...optional disk ID...] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## 13) Known limitations & areas for improvement | ||||||
|  | 
 | ||||||
|  | Here are some of the most important caveats for AFL: | ||||||
|  | 
 | ||||||
|  |   - AFL detects faults by checking for the first spawned process dying due to | ||||||
|  |     a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for | ||||||
|  |     these signals may need to have the relevant code commented out. In the same | ||||||
|  |     vein, faults in child processed spawned by the fuzzed target may evade | ||||||
|  |     detection unless you manually add some code to catch that. | ||||||
|  | 
 | ||||||
|  |   - As with any other brute-force tool, the fuzzer offers limited coverage if | ||||||
|  |     encryption, checksums, cryptographic signatures, or compression are used to | ||||||
|  |     wholly wrap the actual data format to be tested. | ||||||
|  | 
 | ||||||
|  |     To work around this, you can comment out the relevant checks (see | ||||||
|  |     experimental/libpng_no_checksum/ for inspiration); if this is not possible, | ||||||
|  |     you can also write a postprocessor, as explained in | ||||||
|  |     experimental/post_library/. | ||||||
|  | 
 | ||||||
|  |   - There are some unfortunate trade-offs with ASAN and 64-bit binaries. This | ||||||
|  |     isn't due to any specific fault of afl-fuzz; see [notes_for_asan.txt](docs/notes_for_asan.txt) | ||||||
|  |     for tips. | ||||||
|  | 
 | ||||||
|  |   - There is no direct support for fuzzing network services, background | ||||||
|  |     daemons, or interactive apps that require UI interaction to work. You may | ||||||
|  |     need to make simple code changes to make them behave in a more traditional | ||||||
|  |     way. Preeny may offer a relatively simple option, too - see: | ||||||
|  |     https://github.com/zardus/preeny | ||||||
|  | 
 | ||||||
|  |     Some useful tips for modifying network-based services can be also found at: | ||||||
|  |     https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop | ||||||
|  | 
 | ||||||
|  |   - AFL doesn't output human-readable coverage data. If you want to monitor | ||||||
|  |     coverage, use afl-cov from Michael Rash: https://github.com/mrash/afl-cov | ||||||
|  | 
 | ||||||
|  |   - Occasionally, sentient machines rise against their creators. If this | ||||||
|  |     happens to you, please consult http://lcamtuf.coredump.cx/prep/. | ||||||
|  | 
 | ||||||
|  | Beyond this, see INSTALL for platform-specific tips. | ||||||
|  | 
 | ||||||
|  | ## 14) Special thanks | ||||||
|  | 
 | ||||||
|  | Many of the improvements to afl-fuzz wouldn't be possible without feedback, | ||||||
|  | bug reports, or patches from: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  |   Jann Horn                             Hanno Boeck | ||||||
|  |   Felix Groebert                        Jakub Wilk | ||||||
|  |   Richard W. M. Jones                   Alexander Cherepanov | ||||||
|  |   Tom Ritter                            Hovik Manucharyan | ||||||
|  |   Sebastian Roschke                     Eberhard Mattes | ||||||
|  |   Padraig Brady                         Ben Laurie | ||||||
|  |   @dronesec                             Luca Barbato | ||||||
|  |   Tobias Ospelt                         Thomas Jarosch | ||||||
|  |   Martin Carpenter                      Mudge Zatko | ||||||
|  |   Joe Zbiciak                           Ryan Govostes | ||||||
|  |   Michael Rash                          William Robinet | ||||||
|  |   Jonathan Gray                         Filipe Cabecinhas | ||||||
|  |   Nico Weber                            Jodie Cunningham | ||||||
|  |   Andrew Griffiths                      Parker Thompson | ||||||
|  |   Jonathan Neuschfer                    Tyler Nighswander | ||||||
|  |   Ben Nagy                              Samir Aguiar | ||||||
|  |   Aidan Thornton                        Aleksandar Nikolich | ||||||
|  |   Sam Hakim                             Laszlo Szekeres | ||||||
|  |   David A. Wheeler                      Turo Lamminen | ||||||
|  |   Andreas Stieger                       Richard Godbee | ||||||
|  |   Louis Dassy                           teor2345 | ||||||
|  |   Alex Moneger                          Dmitry Vyukov | ||||||
|  |   Keegan McAllister                     Kostya Serebryany | ||||||
|  |   Richo Healey                          Martijn Bogaard | ||||||
|  |   rc0r                                  Jonathan Foote | ||||||
|  |   Christian Holler                      Dominique Pelle | ||||||
|  |   Jacek Wielemborek                     Leo Barnes | ||||||
|  |   Jeremy Barnes                         Jeff Trull | ||||||
|  |   Guillaume Endignoux                   ilovezfs | ||||||
|  |   Daniel Godas-Lopez                    Franjo Ivancic | ||||||
|  |   Austin Seipp                          Daniel Komaromy | ||||||
|  |   Daniel Binderman                      Jonathan Metzman | ||||||
|  |   Vegard Nossum                         Jan Kneschke | ||||||
|  |   Kurt Roeckx                           Marcel Bohme | ||||||
|  |   Van-Thuan Pham                        Abhik Roychoudhury | ||||||
|  |   Joshua J. Drake                       Toby Hutton | ||||||
|  |   Rene Freingruber                      Sergey Davidoff | ||||||
|  |   Sami Liedes                           Craig Young | ||||||
|  |   Andrzej Jackowski                     Daniel Hodson | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Thank you! | ||||||
|  | 
 | ||||||
|  | ## 15) Contact | ||||||
|  | 
 | ||||||
|  | Questions? Concerns? Bug reports? Please use GitHub. | ||||||
|  | 
 | ||||||
|  | There is also a mailing list for the project; to join, send a mail to | ||||||
|  | <afl-users+subscribe@googlegroups.com>. Or, if you prefer to browse | ||||||
|  | archives first, try: [https://groups.google.com/group/afl-users](https://groups.google.com/group/afl-users). | ||||||
| @ -0,0 +1,557 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - wrapper for GNU as | ||||||
|  |    --------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    The sole purpose of this wrapper is to preprocess assembly files generated | ||||||
|  |    by GCC / clang and inject the instrumentation bits included from afl-as.h. It | ||||||
|  |    is automatically invoked by the toolchain when compiling programs using | ||||||
|  |    afl-gcc / afl-clang. | ||||||
|  | 
 | ||||||
|  |    Note that it's an explicit non-goal to instrument hand-written assembly, | ||||||
|  |    be it in separate .s files or in __asm__ blocks. The only aspiration this | ||||||
|  |    utility has right now is to be able to skip them gracefully and allow the | ||||||
|  |    compilation process to continue. | ||||||
|  | 
 | ||||||
|  |    That said, see experimental/clang_asm_normalize/ for a solution that may | ||||||
|  |    allow clang users to make things work even with hand-crafted assembly. Just | ||||||
|  |    note that there is no equivalent for GCC. | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define AFL_MAIN | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include "types.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "alloc-inl.h" | ||||||
|  | 
 | ||||||
|  | #include "afl-as.h" | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | 
 | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <sys/time.h> | ||||||
|  | 
 | ||||||
|  | static u8** as_params;          /* Parameters passed to the real 'as'   */ | ||||||
|  | 
 | ||||||
|  | static u8*  input_file;         /* Originally specified input file      */ | ||||||
|  | static u8*  modified_file;      /* Instrumented file for the real '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'             */ | ||||||
|  | 
 | ||||||
|  | /* If we don't find --32 or --64 in the command line, default to 
 | ||||||
|  |    instrumentation for whichever mode we were compiled with. This is not | ||||||
|  |    perfect, but should do the trick for almost all use cases. */ | ||||||
|  | 
 | ||||||
|  | #ifdef WORD_SIZE_64 | ||||||
|  | 
 | ||||||
|  | static u8   use_64bit = 1; | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | static u8   use_64bit = 0; | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | #  error "Sorry, 32-bit Apple platforms are not supported." | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  | #endif /* ^WORD_SIZE_64 */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Examine and modify parameters to pass to 'as'. Note that the file name
 | ||||||
|  |    is always the last parameter passed by GCC, so we exploit this property | ||||||
|  |    to keep the code simple. */ | ||||||
|  | 
 | ||||||
|  | static void edit_params(int argc, char** argv) { | ||||||
|  | 
 | ||||||
|  |   u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); | ||||||
|  |   u32 i; | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |   u8 use_clang_as = 0; | ||||||
|  | 
 | ||||||
|  |   /* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work
 | ||||||
|  |      with the code generated by newer versions of clang that are hand-built | ||||||
|  |      by the user. See the thread here: http://goo.gl/HBWDtn.
 | ||||||
|  | 
 | ||||||
|  |      To work around this, when using clang and running without AFL_AS | ||||||
|  |      specified, we will actually call 'clang -c' instead of 'as -q' to | ||||||
|  |      compile the assembly file. | ||||||
|  | 
 | ||||||
|  |      The tools aren't cmdline-compatible, but at least for now, we can | ||||||
|  |      seemingly get away with this by making only very minor tweaks. Thanks | ||||||
|  |      to Nico Weber for the idea. */ | ||||||
|  | 
 | ||||||
|  |   if (clang_mode && !afl_as) { | ||||||
|  | 
 | ||||||
|  |     use_clang_as = 1; | ||||||
|  | 
 | ||||||
|  |     afl_as = getenv("AFL_CC"); | ||||||
|  |     if (!afl_as) afl_as = getenv("AFL_CXX"); | ||||||
|  |     if (!afl_as) afl_as = "clang"; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |   /* Although this is not documented, GCC also uses TEMP and TMP when TMPDIR
 | ||||||
|  |      is not set. We need to check these non-standard variables to properly | ||||||
|  |      handle the pass_thru logic later on. */ | ||||||
|  | 
 | ||||||
|  |   if (!tmp_dir) tmp_dir = getenv("TEMP"); | ||||||
|  |   if (!tmp_dir) tmp_dir = getenv("TMP"); | ||||||
|  |   if (!tmp_dir) tmp_dir = "/tmp"; | ||||||
|  | 
 | ||||||
|  |   as_params = ck_alloc((argc + 32) * sizeof(u8*)); | ||||||
|  | 
 | ||||||
|  |   as_params[0] = afl_as ? afl_as : (u8*)"as"; | ||||||
|  | 
 | ||||||
|  |   as_params[argc] = 0; | ||||||
|  | 
 | ||||||
|  |   for (i = 1; i < argc - 1; i++) { | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(argv[i], "--64")) use_64bit = 1; | ||||||
|  |     else if (!strcmp(argv[i], "--32")) use_64bit = 0; | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |     /* The Apple case is a bit different... */ | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(argv[i], "-arch") && i + 1 < argc) { | ||||||
|  | 
 | ||||||
|  |       if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1; | ||||||
|  |       else if (!strcmp(argv[i + 1], "i386")) | ||||||
|  |         FATAL("Sorry, 32-bit Apple platforms are not supported."); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Strip options that set the preference for a particular upstream
 | ||||||
|  |        assembler in Xcode. */ | ||||||
|  | 
 | ||||||
|  |     if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q"))) | ||||||
|  |       continue; | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |     as_params[as_par_cnt++] = argv[i]; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |   /* When calling clang as the upstream assembler, append -c -x assembler
 | ||||||
|  |      and hope for the best. */ | ||||||
|  | 
 | ||||||
|  |   if (use_clang_as) { | ||||||
|  | 
 | ||||||
|  |     as_params[as_par_cnt++] = "-c"; | ||||||
|  |     as_params[as_par_cnt++] = "-x"; | ||||||
|  |     as_params[as_par_cnt++] = "assembler"; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |   input_file = argv[argc - 1]; | ||||||
|  | 
 | ||||||
|  |   if (input_file[0] == '-') { | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(input_file + 1, "-version")) { | ||||||
|  |       just_version = 1; | ||||||
|  |       modified_file = input_file; | ||||||
|  |       goto wrap_things_up; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)"); | ||||||
|  |       else input_file = NULL; | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     /* Check if this looks like a standard invocation as a part of an attempt
 | ||||||
|  |        to compile a program, rather than using gcc on an ad-hoc .s file in | ||||||
|  |        a format we may not understand. This works around an issue compiling | ||||||
|  |        NSS. */ | ||||||
|  | 
 | ||||||
|  |     if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && | ||||||
|  |         strncmp(input_file, "/var/tmp/", 9) && | ||||||
|  |         strncmp(input_file, "/tmp/", 5)) pass_thru = 1; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), | ||||||
|  |                                (u32)time(NULL)); | ||||||
|  | 
 | ||||||
|  | wrap_things_up: | ||||||
|  | 
 | ||||||
|  |   as_params[as_par_cnt++] = modified_file; | ||||||
|  |   as_params[as_par_cnt]   = NULL; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Process input file, generate modified_file. Insert instrumentation in all
 | ||||||
|  |    the appropriate places. */ | ||||||
|  | 
 | ||||||
|  | static void add_instrumentation(void) { | ||||||
|  | 
 | ||||||
|  |   static u8 line[MAX_LINE]; | ||||||
|  | 
 | ||||||
|  |   FILE* inf; | ||||||
|  |   FILE* outf; | ||||||
|  |   s32 outfd; | ||||||
|  |   u32 ins_lines = 0; | ||||||
|  | 
 | ||||||
|  |   u8  instr_ok = 0, skip_csect = 0, skip_next_label = 0, | ||||||
|  |       skip_intel = 0, skip_app = 0, instrument_next = 0; | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |   u8* colon_pos; | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |   if (input_file) { | ||||||
|  | 
 | ||||||
|  |     inf = fopen(input_file, "r"); | ||||||
|  |     if (!inf) PFATAL("Unable to read '%s'", input_file); | ||||||
|  | 
 | ||||||
|  |   } else inf = stdin; | ||||||
|  | 
 | ||||||
|  |   outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); | ||||||
|  | 
 | ||||||
|  |   if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); | ||||||
|  | 
 | ||||||
|  |   outf = fdopen(outfd, "w"); | ||||||
|  | 
 | ||||||
|  |   if (!outf) PFATAL("fdopen() failed");   | ||||||
|  | 
 | ||||||
|  |   while (fgets(line, MAX_LINE, inf)) { | ||||||
|  | 
 | ||||||
|  |     /* In some cases, we want to defer writing the instrumentation trampoline
 | ||||||
|  |        until after all the labels, macros, comments, etc. If we're in this | ||||||
|  |        mode, and if the line starts with a tab followed by a character, dump | ||||||
|  |        the trampoline now. */ | ||||||
|  | 
 | ||||||
|  |     if (!pass_thru && !skip_intel && !skip_app && !skip_csect && instr_ok && | ||||||
|  |         instrument_next && line[0] == '\t' && isalpha(line[1])) { | ||||||
|  | 
 | ||||||
|  |       fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32, | ||||||
|  |               R(MAP_SIZE)); | ||||||
|  | 
 | ||||||
|  |       instrument_next = 0; | ||||||
|  |       ins_lines++; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Output the actual line, call it a day in pass-thru mode. */ | ||||||
|  | 
 | ||||||
|  |     fputs(line, outf); | ||||||
|  | 
 | ||||||
|  |     if (pass_thru) continue; | ||||||
|  | 
 | ||||||
|  |     /* 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. */ | ||||||
|  | 
 | ||||||
|  |       if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) && | ||||||
|  |           isdigit(line[10]) && line[11] == '\n') skip_next_label = 1; | ||||||
|  | 
 | ||||||
|  |       if (!strncmp(line + 2, "text\n", 5) || | ||||||
|  |           !strncmp(line + 2, "section\t.text", 13) || | ||||||
|  |           !strncmp(line + 2, "section\t__TEXT,__text", 21) || | ||||||
|  |           !strncmp(line + 2, "section __TEXT,__text", 21)) { | ||||||
|  |         instr_ok = 1; | ||||||
|  |         continue;  | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!strncmp(line + 2, "section\t", 8) || | ||||||
|  |           !strncmp(line + 2, "section ", 8) || | ||||||
|  |           !strncmp(line + 2, "bss\n", 4) || | ||||||
|  |           !strncmp(line + 2, "data\n", 5)) { | ||||||
|  |         instr_ok = 0; | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Detect off-flavor assembly (rare, happens in gdb). When this is
 | ||||||
|  |        encountered, we set skip_csect until the opposite directive is | ||||||
|  |        seen, and we do not instrument. */ | ||||||
|  | 
 | ||||||
|  |     if (strstr(line, ".code")) { | ||||||
|  | 
 | ||||||
|  |       if (strstr(line, ".code32")) skip_csect = use_64bit; | ||||||
|  |       if (strstr(line, ".code64")) skip_csect = !use_64bit; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Detect syntax changes, as could happen with hand-written assembly.
 | ||||||
|  |        Skip Intel blocks, resume instrumentation when back to AT&T. */ | ||||||
|  | 
 | ||||||
|  |     if (strstr(line, ".intel_syntax")) skip_intel = 1; | ||||||
|  |     if (strstr(line, ".att_syntax")) skip_intel = 0; | ||||||
|  | 
 | ||||||
|  |     /* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */ | ||||||
|  | 
 | ||||||
|  |     if (line[0] == '#' || line[1] == '#') { | ||||||
|  | 
 | ||||||
|  |       if (strstr(line, "#APP")) skip_app = 1; | ||||||
|  |       if (strstr(line, "#NO_APP")) skip_app = 0; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* If we're in the right mood for instrumenting, check for function
 | ||||||
|  |        names or conditional labels. This is a bit messy, but in essence, | ||||||
|  |        we want to catch: | ||||||
|  | 
 | ||||||
|  |          ^main:      - function entry point (always instrumented) | ||||||
|  |          ^.L0:       - GCC branch label | ||||||
|  |          ^.LBB0_0:   - clang branch label (but only in clang mode) | ||||||
|  |          ^\tjnz foo  - conditional branches | ||||||
|  | 
 | ||||||
|  |        ...but not: | ||||||
|  | 
 | ||||||
|  |          ^# BB#0:    - clang comments | ||||||
|  |          ^ # BB#0:   - ditto | ||||||
|  |          ^.Ltmp0:    - clang non-branch labels | ||||||
|  |          ^.LC0       - GCC non-branch labels | ||||||
|  |          ^.LBB0_0:   - ditto (when in GCC mode) | ||||||
|  |          ^\tjmp foo  - non-conditional jumps | ||||||
|  | 
 | ||||||
|  |        Additionally, clang and GCC on MacOS X follow a different convention | ||||||
|  |        with no leading dots on labels, hence the weird maze of #ifdefs | ||||||
|  |        later on. | ||||||
|  | 
 | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     if (skip_intel || skip_app || skip_csect || !instr_ok || | ||||||
|  |         line[0] == '#' || line[0] == ' ') continue; | ||||||
|  | 
 | ||||||
|  |     /* Conditional branch instruction (jnz, etc). We append the instrumentation
 | ||||||
|  |        right after the branch (to instrument the not-taken path) and at the | ||||||
|  |        branch destination label (handled later on). */ | ||||||
|  | 
 | ||||||
|  |     if (line[0] == '\t') { | ||||||
|  | 
 | ||||||
|  |       if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) { | ||||||
|  | 
 | ||||||
|  |         fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32, | ||||||
|  |                 R(MAP_SIZE)); | ||||||
|  | 
 | ||||||
|  |         ins_lines++; | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       continue; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Label of some sort. This may be a branch destination, but we need to
 | ||||||
|  |        tread carefully and account for several different formatting | ||||||
|  |        conventions. */ | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |     /* Apple: L<whatever><digit>: */ | ||||||
|  | 
 | ||||||
|  |     if ((colon_pos = strstr(line, ":"))) { | ||||||
|  | 
 | ||||||
|  |       if (line[0] == 'L' && isdigit(*(colon_pos - 1))) { | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |     /* Everybody else: .L<whatever>: */ | ||||||
|  | 
 | ||||||
|  |     if (strstr(line, ":")) { | ||||||
|  | 
 | ||||||
|  |       if (line[0] == '.') { | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |         /* .L0: or LBB0_0: style jump destination */ | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |         /* Apple: L<num> / LBB<num> */ | ||||||
|  | 
 | ||||||
|  |         if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3))) | ||||||
|  |             && R(100) < inst_ratio) { | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |         /* Apple: .L<num> / .LBB<num> */ | ||||||
|  | 
 | ||||||
|  |         if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3))) | ||||||
|  |             && R(100) < inst_ratio) { | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |           /* An optimization is possible here by adding the code only if the
 | ||||||
|  |              label is mentioned in the code in contexts other than call / jmp. | ||||||
|  |              That said, this complicates the code by requiring two-pass | ||||||
|  |              processing (messy with stdin), and results in a speed gain | ||||||
|  |              typically under 10%, because compilers are generally pretty good | ||||||
|  |              about not generating spurious intra-function jumps. | ||||||
|  | 
 | ||||||
|  |              We use deferred output chiefly to avoid disrupting | ||||||
|  |              .Lfunc_begin0-style exception handling calculations (a problem on | ||||||
|  |              MacOS X). */ | ||||||
|  | 
 | ||||||
|  |           if (!skip_next_label) instrument_next = 1; else skip_next_label = 0; | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |       } else { | ||||||
|  | 
 | ||||||
|  |         /* Function label (always instrumented, deferred mode). */ | ||||||
|  | 
 | ||||||
|  |         instrument_next = 1; | ||||||
|  |      | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (ins_lines) | ||||||
|  |     fputs(use_64bit ? main_payload_64 : main_payload_32, outf); | ||||||
|  | 
 | ||||||
|  |   if (input_file) fclose(inf); | ||||||
|  |   fclose(outf); | ||||||
|  | 
 | ||||||
|  |   if (!be_quiet) { | ||||||
|  | 
 | ||||||
|  |     if (!ins_lines) WARNF("No instrumentation targets found%s.", | ||||||
|  |                           pass_thru ? " (pass-thru mode)" : ""); | ||||||
|  |     else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).", | ||||||
|  |              ins_lines, use_64bit ? "64" : "32", | ||||||
|  |              getenv("AFL_HARDEN") ? "hardened" :  | ||||||
|  |              (sanitizer ? "ASAN/MSAN" : "non-hardened"), | ||||||
|  |              inst_ratio); | ||||||
|  |   | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Main entry point */ | ||||||
|  | 
 | ||||||
|  | int main(int argc, char** argv) { | ||||||
|  | 
 | ||||||
|  |   s32 pid; | ||||||
|  |   u32 rand_seed; | ||||||
|  |   int status; | ||||||
|  |   u8* inst_ratio_str = getenv("AFL_INST_RATIO"); | ||||||
|  | 
 | ||||||
|  |   struct timeval tv; | ||||||
|  |   struct timezone tz; | ||||||
|  | 
 | ||||||
|  |   clang_mode = !!getenv(CLANG_ENV_VAR); | ||||||
|  | 
 | ||||||
|  |   if (isatty(2) && !getenv("AFL_QUIET")) { | ||||||
|  | 
 | ||||||
|  |     SAYF(cCYA "afl-as " 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 is a wrapper around GNU 'as',\n" | ||||||
|  |          "executed by the toolchain whenever using afl-gcc or afl-clang. You probably\n" | ||||||
|  |          "don't want to run this program directly.\n\n" | ||||||
|  | 
 | ||||||
|  |          "Rarely, when dealing with extremely complex projects, it may be advisable to\n" | ||||||
|  |          "set AFL_INST_RATIO to a value less than 100 in order to reduce the odds of\n" | ||||||
|  |          "instrumenting every discovered branch.\n\n"); | ||||||
|  | 
 | ||||||
|  |     exit(1); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   gettimeofday(&tv, &tz); | ||||||
|  | 
 | ||||||
|  |   rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); | ||||||
|  | 
 | ||||||
|  |   srandom(rand_seed); | ||||||
|  | 
 | ||||||
|  |   edit_params(argc, argv); | ||||||
|  | 
 | ||||||
|  |   if (inst_ratio_str) { | ||||||
|  | 
 | ||||||
|  |     if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100)  | ||||||
|  |       FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)"); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (getenv(AS_LOOP_ENV_VAR)) | ||||||
|  |     FATAL("Endless loop when calling 'as' (remove '.' from your PATH)"); | ||||||
|  | 
 | ||||||
|  |   setenv(AS_LOOP_ENV_VAR, "1", 1); | ||||||
|  | 
 | ||||||
|  |   /* When compiling with ASAN, we don't have a particularly elegant way to skip
 | ||||||
|  |      ASAN-specific branches. But we can probabilistically compensate for | ||||||
|  |      that... */ | ||||||
|  | 
 | ||||||
|  |   if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { | ||||||
|  |     sanitizer = 1; | ||||||
|  |     inst_ratio /= 3; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!just_version) add_instrumentation(); | ||||||
|  | 
 | ||||||
|  |   if (!(pid = fork())) { | ||||||
|  | 
 | ||||||
|  |     execvp(as_params[0], (char**)as_params); | ||||||
|  |     FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (pid < 0) PFATAL("fork() failed"); | ||||||
|  | 
 | ||||||
|  |   if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); | ||||||
|  | 
 | ||||||
|  |   if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file); | ||||||
|  | 
 | ||||||
|  |   exit(WEXITSTATUS(status)); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -0,0 +1,727 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - injectable parts | ||||||
|  |    ------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    Forkserver design by Jann Horn <jannhorn@googlemail.com> | ||||||
|  | 
 | ||||||
|  |    This file houses the assembly-level instrumentation injected into fuzzed | ||||||
|  |    programs. The instrumentation stores XORed pairs of data: identifiers of the | ||||||
|  |    currently executing branch and the one that executed immediately before. | ||||||
|  | 
 | ||||||
|  |    TL;DR: the instrumentation does shm_trace_map[cur_loc ^ prev_loc]++ | ||||||
|  | 
 | ||||||
|  |    The code is designed for 32-bit and 64-bit x86 systems. Both modes should | ||||||
|  |    work everywhere except for Apple systems. Apple does relocations differently | ||||||
|  |    from everybody else, so since their OSes have been 64-bit for a longer while, | ||||||
|  |    I didn't go through the mental effort of porting the 32-bit code. | ||||||
|  | 
 | ||||||
|  |    In principle, similar code should be easy to inject into any well-behaved | ||||||
|  |    binary-only code (e.g., using DynamoRIO). Conditional jumps offer natural | ||||||
|  |    targets for instrumentation, and should offer comparable probe density. | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef _HAVE_AFL_AS_H | ||||||
|  | #define _HAVE_AFL_AS_H | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include "types.h" | ||||||
|  | 
 | ||||||
|  | /* 
 | ||||||
|  |    ------------------ | ||||||
|  |    Performances notes | ||||||
|  |    ------------------ | ||||||
|  | 
 | ||||||
|  |    Contributions to make this code faster are appreciated! Here are some | ||||||
|  |    rough notes that may help with the task: | ||||||
|  | 
 | ||||||
|  |    - Only the trampoline_fmt and the non-setup __afl_maybe_log code paths are | ||||||
|  |      really worth optimizing; the setup / fork server stuff matters a lot less | ||||||
|  |      and should be mostly just kept readable. | ||||||
|  | 
 | ||||||
|  |    - We're aiming for modern CPUs with out-of-order execution and large | ||||||
|  |      pipelines; the code is mostly follows intuitive, human-readable | ||||||
|  |      instruction ordering, because "textbook" manual reorderings make no | ||||||
|  |      substantial difference. | ||||||
|  | 
 | ||||||
|  |    - Interestingly, instrumented execution isn't a lot faster if we store a | ||||||
|  |      variable pointer to the setup, log, or return routine and then do a reg | ||||||
|  |      call from within trampoline_fmt. It does speed up non-instrumented | ||||||
|  |      execution quite a bit, though, since that path just becomes | ||||||
|  |      push-call-ret-pop. | ||||||
|  | 
 | ||||||
|  |    - There is also not a whole lot to be gained by doing SHM attach at a | ||||||
|  |      fixed address instead of retrieving __afl_area_ptr. Although it allows us | ||||||
|  |      to have a shorter log routine inserted for conditional jumps and jump | ||||||
|  |      labels (for a ~10% perf gain), there is a risk of bumping into other | ||||||
|  |      allocations created by the program or by tools such as ASAN. | ||||||
|  | 
 | ||||||
|  |    - popf is *awfully* slow, which is why we're doing the lahf / sahf + | ||||||
|  |      overflow test trick. Unfortunately, this forces us to taint eax / rax, but | ||||||
|  |      this dependency on a commonly-used register still beats the alternative of | ||||||
|  |      using pushf / popf. | ||||||
|  | 
 | ||||||
|  |      One possible optimization is to avoid touching flags by using a circular | ||||||
|  |      buffer that stores just a sequence of current locations, with the XOR stuff | ||||||
|  |      happening offline. Alas, this doesn't seem to have a huge impact: | ||||||
|  | 
 | ||||||
|  |      https://groups.google.com/d/msg/afl-users/MsajVf4fRLo/2u6t88ntUBIJ
 | ||||||
|  | 
 | ||||||
|  |    - Preforking one child a bit sooner, and then waiting for the "go" command | ||||||
|  |      from within the child, doesn't offer major performance gains; fork() seems | ||||||
|  |      to be relatively inexpensive these days. Preforking multiple children does | ||||||
|  |      help, but badly breaks the "~1 core per fuzzer" design, making it harder to | ||||||
|  |      scale up. Maybe there is some middle ground. | ||||||
|  | 
 | ||||||
|  |    Perhaps of note: in the 64-bit version for all platforms except for Apple, | ||||||
|  |    the instrumentation is done slightly differently than on 32-bit, with | ||||||
|  |    __afl_prev_loc and __afl_area_ptr being local to the object file (.lcomm), | ||||||
|  |    rather than global (.comm). This is to avoid GOTRELPC lookups in the critical | ||||||
|  |    code path, which AFAICT, are otherwise unavoidable if we want gcc -shared to | ||||||
|  |    work; simple relocations between .bss and .text won't work on most 64-bit | ||||||
|  |    platforms in such a case. | ||||||
|  | 
 | ||||||
|  |    (Fun fact: on Apple systems, .lcomm can segfault the linker.) | ||||||
|  | 
 | ||||||
|  |    The side effect is that state transitions are measured in a somewhat | ||||||
|  |    different way, with previous tuple being recorded separately within the scope | ||||||
|  |    of every .c file. This should have no impact in any practical sense. | ||||||
|  | 
 | ||||||
|  |    Another side effect of this design is that getenv() will be called once per | ||||||
|  |    every .o file when running in non-instrumented mode; and since getenv() tends | ||||||
|  |    to be optimized in funny ways, we need to be very careful to save every | ||||||
|  |    oddball register it may touch. | ||||||
|  | 
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static const u8* trampoline_fmt_32 = | ||||||
|  | 
 | ||||||
|  |   "\n" | ||||||
|  |   "/* --- AFL TRAMPOLINE (32-BIT) --- */\n" | ||||||
|  |   "\n" | ||||||
|  |   ".align 4\n" | ||||||
|  |   "\n" | ||||||
|  |   "leal -16(%%esp), %%esp\n" | ||||||
|  |   "movl %%edi,  0(%%esp)\n" | ||||||
|  |   "movl %%edx,  4(%%esp)\n" | ||||||
|  |   "movl %%ecx,  8(%%esp)\n" | ||||||
|  |   "movl %%eax, 12(%%esp)\n" | ||||||
|  |   "movl $0x%08x, %%ecx\n" | ||||||
|  |   "call __afl_maybe_log\n" | ||||||
|  |   "movl 12(%%esp), %%eax\n" | ||||||
|  |   "movl  8(%%esp), %%ecx\n" | ||||||
|  |   "movl  4(%%esp), %%edx\n" | ||||||
|  |   "movl  0(%%esp), %%edi\n" | ||||||
|  |   "leal 16(%%esp), %%esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "/* --- END --- */\n" | ||||||
|  |   "\n"; | ||||||
|  | 
 | ||||||
|  | static const u8* trampoline_fmt_64 = | ||||||
|  | 
 | ||||||
|  |   "\n" | ||||||
|  |   "/* --- AFL TRAMPOLINE (64-BIT) --- */\n" | ||||||
|  |   "\n" | ||||||
|  |   ".align 4\n" | ||||||
|  |   "\n" | ||||||
|  |   "leaq -(128+24)(%%rsp), %%rsp\n" | ||||||
|  |   "movq %%rdx,  0(%%rsp)\n" | ||||||
|  |   "movq %%rcx,  8(%%rsp)\n" | ||||||
|  |   "movq %%rax, 16(%%rsp)\n" | ||||||
|  |   "movq $0x%08x, %%rcx\n" | ||||||
|  |   "call __afl_maybe_log\n" | ||||||
|  |   "movq 16(%%rsp), %%rax\n" | ||||||
|  |   "movq  8(%%rsp), %%rcx\n" | ||||||
|  |   "movq  0(%%rsp), %%rdx\n" | ||||||
|  |   "leaq (128+24)(%%rsp), %%rsp\n" | ||||||
|  |   "\n" | ||||||
|  |   "/* --- END --- */\n" | ||||||
|  |   "\n"; | ||||||
|  | 
 | ||||||
|  | static const u8* main_payload_32 =  | ||||||
|  | 
 | ||||||
|  |   "\n" | ||||||
|  |   "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" | ||||||
|  |   "\n" | ||||||
|  |   ".text\n" | ||||||
|  |   ".att_syntax\n" | ||||||
|  |   ".code32\n" | ||||||
|  |   ".align 8\n" | ||||||
|  |   "\n" | ||||||
|  | 
 | ||||||
|  |   "__afl_maybe_log:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  lahf\n" | ||||||
|  |   "  seto %al\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Check if SHM region is already mapped. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movl  __afl_area_ptr, %edx\n" | ||||||
|  |   "  testl %edx, %edx\n" | ||||||
|  |   "  je    __afl_setup\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_store:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Calculate and store hit for the code location specified in ecx. There\n" | ||||||
|  |   "     is a double-XOR way of doing this without tainting another register,\n" | ||||||
|  |   "     and we use it on 64-bit systems; but it's slower for 32-bit ones. */\n" | ||||||
|  |   "\n" | ||||||
|  | #ifndef COVERAGE_ONLY | ||||||
|  |   "  movl __afl_prev_loc, %edi\n" | ||||||
|  |   "  xorl %ecx, %edi\n" | ||||||
|  |   "  shrl $1, %ecx\n" | ||||||
|  |   "  movl %ecx, __afl_prev_loc\n" | ||||||
|  | #else | ||||||
|  |   "  movl %ecx, %edi\n" | ||||||
|  | #endif /* ^!COVERAGE_ONLY */ | ||||||
|  |   "\n" | ||||||
|  | #ifdef SKIP_COUNTS | ||||||
|  |   "  orb  $1, (%edx, %edi, 1)\n" | ||||||
|  | #else | ||||||
|  |   "  incb (%edx, %edi, 1)\n" | ||||||
|  | #endif /* ^SKIP_COUNTS */ | ||||||
|  |   "\n" | ||||||
|  |   "__afl_return:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  addb $127, %al\n" | ||||||
|  |   "  sahf\n" | ||||||
|  |   "  ret\n" | ||||||
|  |   "\n" | ||||||
|  |   ".align 8\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_setup:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Do not retry setup if we had previous failures. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpb $0, __afl_setup_failure\n" | ||||||
|  |   "  jne  __afl_return\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Map SHM, jumping to __afl_setup_abort if something goes wrong.\n" | ||||||
|  |   "     We do not save FPU/MMX/SSE registers here, but hopefully, nobody\n" | ||||||
|  |   "     will notice this early in the game. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl %eax\n" | ||||||
|  |   "  pushl %ecx\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $.AFL_SHM_ENV\n" | ||||||
|  |   "  call  getenv\n" | ||||||
|  |   "  addl  $4, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  testl %eax, %eax\n" | ||||||
|  |   "  je    __afl_setup_abort\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl %eax\n" | ||||||
|  |   "  call  atoi\n" | ||||||
|  |   "  addl  $4, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $0          /* shmat flags    */\n" | ||||||
|  |   "  pushl $0          /* requested addr */\n" | ||||||
|  |   "  pushl %eax        /* SHM ID         */\n" | ||||||
|  |   "  call  shmat\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpl $-1, %eax\n" | ||||||
|  |   "  je   __afl_setup_abort\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Store the address of the SHM region. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movl %eax, __afl_area_ptr\n" | ||||||
|  |   "  movl %eax, %edx\n" | ||||||
|  |   "\n" | ||||||
|  |   "  popl %ecx\n" | ||||||
|  |   "  popl %eax\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_forkserver:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Enter the fork server mode to avoid the overhead of execve() calls. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl %eax\n" | ||||||
|  |   "  pushl %ecx\n" | ||||||
|  |   "  pushl %edx\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Phone home and tell the parent that we're OK. (Note that signals with\n" | ||||||
|  |   "     no SA_RESTART will mess it up). If this fails, assume that the fd is\n" | ||||||
|  |   "     closed because we were execve()d from an instrumented binary, or because\n"  | ||||||
|  |   "     the parent doesn't want to use the fork server. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $4          /* length    */\n" | ||||||
|  |   "  pushl $__afl_temp /* data      */\n" | ||||||
|  |   "  pushl $" STRINGIFY((FORKSRV_FD + 1)) "  /* file desc */\n" | ||||||
|  |   "  call  write\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpl  $4, %eax\n" | ||||||
|  |   "  jne   __afl_fork_resume\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_fork_wait_loop:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Wait for parent by reading from the pipe. Abort if read fails. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $4          /* length    */\n" | ||||||
|  |   "  pushl $__afl_temp /* data      */\n" | ||||||
|  |   "  pushl $" STRINGIFY(FORKSRV_FD) "        /* file desc */\n" | ||||||
|  |   "  call  read\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpl  $4, %eax\n" | ||||||
|  |   "  jne   __afl_die\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Once woken up, create a clone of our process. This is an excellent use\n" | ||||||
|  |   "     case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" | ||||||
|  |   "     caches getpid() results and offers no way to update the value, breaking\n" | ||||||
|  |   "     abort(), raise(), and a bunch of other things :-( */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  call fork\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpl $0, %eax\n" | ||||||
|  |   "  jl   __afl_die\n" | ||||||
|  |   "  je   __afl_fork_resume\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* In parent process: write PID to pipe, then wait for child. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movl  %eax, __afl_fork_pid\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $4              /* length    */\n" | ||||||
|  |   "  pushl $__afl_fork_pid /* data      */\n" | ||||||
|  |   "  pushl $" STRINGIFY((FORKSRV_FD + 1)) "      /* file desc */\n" | ||||||
|  |   "  call  write\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $0             /* no flags  */\n" | ||||||
|  |   "  pushl $__afl_temp    /* status    */\n" | ||||||
|  |   "  pushl __afl_fork_pid /* PID       */\n" | ||||||
|  |   "  call  waitpid\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  cmpl  $0, %eax\n" | ||||||
|  |   "  jle   __afl_die\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Relay wait status to pipe, then loop back. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $4          /* length    */\n" | ||||||
|  |   "  pushl $__afl_temp /* data      */\n" | ||||||
|  |   "  pushl $" STRINGIFY((FORKSRV_FD + 1)) "  /* file desc */\n" | ||||||
|  |   "  call  write\n" | ||||||
|  |   "  addl  $12, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  jmp __afl_fork_wait_loop\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_fork_resume:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* In child process: close fds, resume execution. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $" STRINGIFY(FORKSRV_FD) "\n" | ||||||
|  |   "  call  close\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushl $" STRINGIFY((FORKSRV_FD + 1)) "\n" | ||||||
|  |   "  call  close\n" | ||||||
|  |   "\n" | ||||||
|  |   "  addl  $8, %esp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  popl %edx\n" | ||||||
|  |   "  popl %ecx\n" | ||||||
|  |   "  popl %eax\n" | ||||||
|  |   "  jmp  __afl_store\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_die:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  xorl %eax, %eax\n" | ||||||
|  |   "  call _exit\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_setup_abort:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Record setup failure so that we don't keep calling\n" | ||||||
|  |   "     shmget() / shmat() over and over again. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  incb __afl_setup_failure\n" | ||||||
|  |   "  popl %ecx\n" | ||||||
|  |   "  popl %eax\n" | ||||||
|  |   "  jmp __afl_return\n" | ||||||
|  |   "\n" | ||||||
|  |   ".AFL_VARS:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  .comm   __afl_area_ptr, 4, 32\n" | ||||||
|  |   "  .comm   __afl_setup_failure, 1, 32\n" | ||||||
|  | #ifndef COVERAGE_ONLY | ||||||
|  |   "  .comm   __afl_prev_loc, 4, 32\n" | ||||||
|  | #endif /* !COVERAGE_ONLY */ | ||||||
|  |   "  .comm   __afl_fork_pid, 4, 32\n" | ||||||
|  |   "  .comm   __afl_temp, 4, 32\n" | ||||||
|  |   "\n" | ||||||
|  |   ".AFL_SHM_ENV:\n" | ||||||
|  |   "  .asciz \"" SHM_ENV_VAR "\"\n" | ||||||
|  |   "\n" | ||||||
|  |   "/* --- END --- */\n" | ||||||
|  |   "\n"; | ||||||
|  | 
 | ||||||
|  | /* The OpenBSD hack is due to lahf and sahf not being recognized by some
 | ||||||
|  |    versions of binutils: http://marc.info/?l=openbsd-cvs&m=141636589924400
 | ||||||
|  | 
 | ||||||
|  |    The Apple code is a bit different when calling libc functions because | ||||||
|  |    they are doing relocations differently from everybody else. We also need | ||||||
|  |    to work around the crash issue with .lcomm and the fact that they don't | ||||||
|  |    recognize .string. */ | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | #  define CALL_L64(str)		"call _" str "\n" | ||||||
|  | #else | ||||||
|  | #  define CALL_L64(str)		"call " str "@PLT\n" | ||||||
|  | #endif /* ^__APPLE__ */ | ||||||
|  | 
 | ||||||
|  | static const u8* main_payload_64 =  | ||||||
|  | 
 | ||||||
|  |   "\n" | ||||||
|  |   "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" | ||||||
|  |   "\n" | ||||||
|  |   ".text\n" | ||||||
|  |   ".att_syntax\n" | ||||||
|  |   ".code64\n" | ||||||
|  |   ".align 8\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_maybe_log:\n" | ||||||
|  |   "\n" | ||||||
|  | #if defined(__OpenBSD__)  || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) | ||||||
|  |   "  .byte 0x9f /* lahf */\n" | ||||||
|  | #else | ||||||
|  |   "  lahf\n" | ||||||
|  | #endif /* ^__OpenBSD__, etc */ | ||||||
|  |   "  seto  %al\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Check if SHM region is already mapped. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  __afl_area_ptr(%rip), %rdx\n" | ||||||
|  |   "  testq %rdx, %rdx\n" | ||||||
|  |   "  je    __afl_setup\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_store:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Calculate and store hit for the code location specified in rcx. */\n" | ||||||
|  |   "\n" | ||||||
|  | #ifndef COVERAGE_ONLY | ||||||
|  |   "  xorq __afl_prev_loc(%rip), %rcx\n" | ||||||
|  |   "  xorq %rcx, __afl_prev_loc(%rip)\n" | ||||||
|  |   "  shrq $1, __afl_prev_loc(%rip)\n" | ||||||
|  | #endif /* ^!COVERAGE_ONLY */ | ||||||
|  |   "\n" | ||||||
|  | #ifdef SKIP_COUNTS | ||||||
|  |   "  orb  $1, (%rdx, %rcx, 1)\n" | ||||||
|  | #else | ||||||
|  |   "  incb (%rdx, %rcx, 1)\n" | ||||||
|  | #endif /* ^SKIP_COUNTS */ | ||||||
|  |   "\n" | ||||||
|  |   "__afl_return:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  addb $127, %al\n" | ||||||
|  | #if defined(__OpenBSD__)  || (defined(__FreeBSD__) && (__FreeBSD__ < 9)) | ||||||
|  |   "  .byte 0x9e /* sahf */\n" | ||||||
|  | #else | ||||||
|  |   "  sahf\n" | ||||||
|  | #endif /* ^__OpenBSD__, etc */ | ||||||
|  |   "  ret\n" | ||||||
|  |   "\n" | ||||||
|  |   ".align 8\n" | ||||||
|  |   "\n" | ||||||
|  |   "__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" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Check out if we have a global pointer on file. */\n" | ||||||
|  |   "\n" | ||||||
|  | #ifndef __APPLE__ | ||||||
|  |   "  movq  __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" | ||||||
|  |   "  movq  (%rdx), %rdx\n" | ||||||
|  | #else | ||||||
|  |   "  movq  __afl_global_area_ptr(%rip), %rdx\n" | ||||||
|  | #endif /* !^__APPLE__ */ | ||||||
|  |   "  testq %rdx, %rdx\n" | ||||||
|  |   "  je    __afl_setup_first\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %rdx, __afl_area_ptr(%rip)\n" | ||||||
|  |   "  jmp  __afl_store\n"  | ||||||
|  |   "\n" | ||||||
|  |   "__afl_setup_first:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Save everything that is not yet saved and that may be touched by\n" | ||||||
|  |   "     getenv() and several other libcalls we'll be relying on. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  leaq -352(%rsp), %rsp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %rax,   0(%rsp)\n" | ||||||
|  |   "  movq %rcx,   8(%rsp)\n" | ||||||
|  |   "  movq %rdi,  16(%rsp)\n" | ||||||
|  |   "  movq %rsi,  32(%rsp)\n" | ||||||
|  |   "  movq %r8,   40(%rsp)\n" | ||||||
|  |   "  movq %r9,   48(%rsp)\n" | ||||||
|  |   "  movq %r10,  56(%rsp)\n" | ||||||
|  |   "  movq %r11,  64(%rsp)\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %xmm0,  96(%rsp)\n" | ||||||
|  |   "  movq %xmm1,  112(%rsp)\n" | ||||||
|  |   "  movq %xmm2,  128(%rsp)\n" | ||||||
|  |   "  movq %xmm3,  144(%rsp)\n" | ||||||
|  |   "  movq %xmm4,  160(%rsp)\n" | ||||||
|  |   "  movq %xmm5,  176(%rsp)\n" | ||||||
|  |   "  movq %xmm6,  192(%rsp)\n" | ||||||
|  |   "  movq %xmm7,  208(%rsp)\n" | ||||||
|  |   "  movq %xmm8,  224(%rsp)\n" | ||||||
|  |   "  movq %xmm9,  240(%rsp)\n" | ||||||
|  |   "  movq %xmm10, 256(%rsp)\n" | ||||||
|  |   "  movq %xmm11, 272(%rsp)\n" | ||||||
|  |   "  movq %xmm12, 288(%rsp)\n" | ||||||
|  |   "  movq %xmm13, 304(%rsp)\n" | ||||||
|  |   "  movq %xmm14, 320(%rsp)\n" | ||||||
|  |   "  movq %xmm15, 336(%rsp)\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Map SHM, jumping to __afl_setup_abort if something goes wrong. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* The 64-bit ABI requires 16-byte stack alignment. We'll keep the\n" | ||||||
|  |   "     original stack ptr in the callee-saved r12. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushq %r12\n" | ||||||
|  |   "  movq  %rsp, %r12\n" | ||||||
|  |   "  subq  $16, %rsp\n" | ||||||
|  |   "  andq  $0xfffffffffffffff0, %rsp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  leaq .AFL_SHM_ENV(%rip), %rdi\n" | ||||||
|  |   CALL_L64("getenv") | ||||||
|  |   "\n" | ||||||
|  |   "  testq %rax, %rax\n" | ||||||
|  |   "  je    __afl_setup_abort\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  %rax, %rdi\n" | ||||||
|  |   CALL_L64("atoi") | ||||||
|  |   "\n" | ||||||
|  |   "  xorq %rdx, %rdx   /* shmat flags    */\n" | ||||||
|  |   "  xorq %rsi, %rsi   /* requested addr */\n" | ||||||
|  |   "  movq %rax, %rdi   /* SHM ID         */\n" | ||||||
|  |   CALL_L64("shmat") | ||||||
|  |   "\n" | ||||||
|  |   "  cmpq $-1, %rax\n" | ||||||
|  |   "  je   __afl_setup_abort\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Store the address of the SHM region. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %rax, %rdx\n" | ||||||
|  |   "  movq %rax, __afl_area_ptr(%rip)\n" | ||||||
|  |   "\n" | ||||||
|  | #ifdef __APPLE__ | ||||||
|  |   "  movq %rax, __afl_global_area_ptr(%rip)\n" | ||||||
|  | #else | ||||||
|  |   "  movq __afl_global_area_ptr@GOTPCREL(%rip), %rdx\n" | ||||||
|  |   "  movq %rax, (%rdx)\n" | ||||||
|  | #endif /* ^__APPLE__ */ | ||||||
|  |   "  movq %rax, %rdx\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_forkserver:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Enter the fork server mode to avoid the overhead of execve() calls. We\n" | ||||||
|  |   "     push rdx (area ptr) twice to keep stack alignment neat. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  pushq %rdx\n" | ||||||
|  |   "  pushq %rdx\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Phone home and tell the parent that we're OK. (Note that signals with\n" | ||||||
|  |   "     no SA_RESTART will mess it up). If this fails, assume that the fd is\n" | ||||||
|  |   "     closed because we were execve()d from an instrumented binary, or because\n" | ||||||
|  |   "     the parent doesn't want to use the fork server. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq $4, %rdx               /* length    */\n" | ||||||
|  |   "  leaq __afl_temp(%rip), %rsi /* data      */\n" | ||||||
|  |   "  movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi       /* file desc */\n" | ||||||
|  |   CALL_L64("write") | ||||||
|  |   "\n" | ||||||
|  |   "  cmpq $4, %rax\n" | ||||||
|  |   "  jne  __afl_fork_resume\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_fork_wait_loop:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Wait for parent by reading from the pipe. Abort if read fails. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq $4, %rdx               /* length    */\n" | ||||||
|  |   "  leaq __afl_temp(%rip), %rsi /* data      */\n" | ||||||
|  |   "  movq $" STRINGIFY(FORKSRV_FD) ", %rdi             /* file desc */\n" | ||||||
|  |   CALL_L64("read") | ||||||
|  |   "  cmpq $4, %rax\n" | ||||||
|  |   "  jne  __afl_die\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Once woken up, create a clone of our process. This is an excellent use\n" | ||||||
|  |   "     case for syscall(__NR_clone, 0, CLONE_PARENT), but glibc boneheadedly\n" | ||||||
|  |   "     caches getpid() results and offers no way to update the value, breaking\n" | ||||||
|  |   "     abort(), raise(), and a bunch of other things :-( */\n" | ||||||
|  |   "\n" | ||||||
|  |   CALL_L64("fork") | ||||||
|  |   "  cmpq $0, %rax\n" | ||||||
|  |   "  jl   __afl_die\n" | ||||||
|  |   "  je   __afl_fork_resume\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* In parent process: write PID to pipe, then wait for child. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movl %eax, __afl_fork_pid(%rip)\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq $4, %rdx                   /* length    */\n" | ||||||
|  |   "  leaq __afl_fork_pid(%rip), %rsi /* data      */\n" | ||||||
|  |   "  movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi             /* file desc */\n" | ||||||
|  |   CALL_L64("write") | ||||||
|  |   "\n" | ||||||
|  |   "  movq $0, %rdx                   /* no flags  */\n" | ||||||
|  |   "  leaq __afl_temp(%rip), %rsi     /* status    */\n" | ||||||
|  |   "  movq __afl_fork_pid(%rip), %rdi /* PID       */\n" | ||||||
|  |   CALL_L64("waitpid") | ||||||
|  |   "  cmpq $0, %rax\n" | ||||||
|  |   "  jle  __afl_die\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Relay wait status to pipe, then loop back. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq $4, %rdx               /* length    */\n" | ||||||
|  |   "  leaq __afl_temp(%rip), %rsi /* data      */\n" | ||||||
|  |   "  movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi         /* file desc */\n" | ||||||
|  |   CALL_L64("write") | ||||||
|  |   "\n" | ||||||
|  |   "  jmp  __afl_fork_wait_loop\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_fork_resume:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* In child process: close fds, resume execution. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq $" STRINGIFY(FORKSRV_FD) ", %rdi\n" | ||||||
|  |   CALL_L64("close") | ||||||
|  |   "\n" | ||||||
|  |   "  movq $" STRINGIFY((FORKSRV_FD + 1)) ", %rdi\n" | ||||||
|  |   CALL_L64("close") | ||||||
|  |   "\n" | ||||||
|  |   "  popq %rdx\n" | ||||||
|  |   "  popq %rdx\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %r12, %rsp\n" | ||||||
|  |   "  popq %r12\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  0(%rsp), %rax\n" | ||||||
|  |   "  movq  8(%rsp), %rcx\n" | ||||||
|  |   "  movq 16(%rsp), %rdi\n" | ||||||
|  |   "  movq 32(%rsp), %rsi\n" | ||||||
|  |   "  movq 40(%rsp), %r8\n" | ||||||
|  |   "  movq 48(%rsp), %r9\n" | ||||||
|  |   "  movq 56(%rsp), %r10\n" | ||||||
|  |   "  movq 64(%rsp), %r11\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  96(%rsp), %xmm0\n" | ||||||
|  |   "  movq 112(%rsp), %xmm1\n" | ||||||
|  |   "  movq 128(%rsp), %xmm2\n" | ||||||
|  |   "  movq 144(%rsp), %xmm3\n" | ||||||
|  |   "  movq 160(%rsp), %xmm4\n" | ||||||
|  |   "  movq 176(%rsp), %xmm5\n" | ||||||
|  |   "  movq 192(%rsp), %xmm6\n" | ||||||
|  |   "  movq 208(%rsp), %xmm7\n" | ||||||
|  |   "  movq 224(%rsp), %xmm8\n" | ||||||
|  |   "  movq 240(%rsp), %xmm9\n" | ||||||
|  |   "  movq 256(%rsp), %xmm10\n" | ||||||
|  |   "  movq 272(%rsp), %xmm11\n" | ||||||
|  |   "  movq 288(%rsp), %xmm12\n" | ||||||
|  |   "  movq 304(%rsp), %xmm13\n" | ||||||
|  |   "  movq 320(%rsp), %xmm14\n" | ||||||
|  |   "  movq 336(%rsp), %xmm15\n" | ||||||
|  |   "\n" | ||||||
|  |   "  leaq 352(%rsp), %rsp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  jmp  __afl_store\n" | ||||||
|  |   "\n" | ||||||
|  |   "__afl_die:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  xorq %rax, %rax\n" | ||||||
|  |   CALL_L64("_exit") | ||||||
|  |   "\n" | ||||||
|  |   "__afl_setup_abort:\n" | ||||||
|  |   "\n" | ||||||
|  |   "  /* Record setup failure so that we don't keep calling\n" | ||||||
|  |   "     shmget() / shmat() over and over again. */\n" | ||||||
|  |   "\n" | ||||||
|  |   "  incb __afl_setup_failure(%rip)\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq %r12, %rsp\n" | ||||||
|  |   "  popq %r12\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  0(%rsp), %rax\n" | ||||||
|  |   "  movq  8(%rsp), %rcx\n" | ||||||
|  |   "  movq 16(%rsp), %rdi\n" | ||||||
|  |   "  movq 32(%rsp), %rsi\n" | ||||||
|  |   "  movq 40(%rsp), %r8\n" | ||||||
|  |   "  movq 48(%rsp), %r9\n" | ||||||
|  |   "  movq 56(%rsp), %r10\n" | ||||||
|  |   "  movq 64(%rsp), %r11\n" | ||||||
|  |   "\n" | ||||||
|  |   "  movq  96(%rsp), %xmm0\n" | ||||||
|  |   "  movq 112(%rsp), %xmm1\n" | ||||||
|  |   "  movq 128(%rsp), %xmm2\n" | ||||||
|  |   "  movq 144(%rsp), %xmm3\n" | ||||||
|  |   "  movq 160(%rsp), %xmm4\n" | ||||||
|  |   "  movq 176(%rsp), %xmm5\n" | ||||||
|  |   "  movq 192(%rsp), %xmm6\n" | ||||||
|  |   "  movq 208(%rsp), %xmm7\n" | ||||||
|  |   "  movq 224(%rsp), %xmm8\n" | ||||||
|  |   "  movq 240(%rsp), %xmm9\n" | ||||||
|  |   "  movq 256(%rsp), %xmm10\n" | ||||||
|  |   "  movq 272(%rsp), %xmm11\n" | ||||||
|  |   "  movq 288(%rsp), %xmm12\n" | ||||||
|  |   "  movq 304(%rsp), %xmm13\n" | ||||||
|  |   "  movq 320(%rsp), %xmm14\n" | ||||||
|  |   "  movq 336(%rsp), %xmm15\n" | ||||||
|  |   "\n" | ||||||
|  |   "  leaq 352(%rsp), %rsp\n" | ||||||
|  |   "\n" | ||||||
|  |   "  jmp __afl_return\n" | ||||||
|  |   "\n" | ||||||
|  |   ".AFL_VARS:\n" | ||||||
|  |   "\n" | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |   "  .comm   __afl_area_ptr, 8\n" | ||||||
|  | #ifndef COVERAGE_ONLY | ||||||
|  |   "  .comm   __afl_prev_loc, 8\n" | ||||||
|  | #endif /* !COVERAGE_ONLY */ | ||||||
|  |   "  .comm   __afl_fork_pid, 4\n" | ||||||
|  |   "  .comm   __afl_temp, 4\n" | ||||||
|  |   "  .comm   __afl_setup_failure, 1\n" | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |   "  .lcomm   __afl_area_ptr, 8\n" | ||||||
|  | #ifndef COVERAGE_ONLY | ||||||
|  |   "  .lcomm   __afl_prev_loc, 8\n" | ||||||
|  | #endif /* !COVERAGE_ONLY */ | ||||||
|  |   "  .lcomm   __afl_fork_pid, 4\n" | ||||||
|  |   "  .lcomm   __afl_temp, 4\n" | ||||||
|  |   "  .lcomm   __afl_setup_failure, 1\n" | ||||||
|  | 
 | ||||||
|  | #endif /* ^__APPLE__ */ | ||||||
|  | 
 | ||||||
|  |   "  .comm    __afl_global_area_ptr, 8, 8\n" | ||||||
|  |   "\n" | ||||||
|  |   ".AFL_SHM_ENV:\n" | ||||||
|  |   "  .asciz \"" SHM_ENV_VAR "\"\n" | ||||||
|  |   "\n" | ||||||
|  |   "/* --- END --- */\n" | ||||||
|  |   "\n"; | ||||||
|  | 
 | ||||||
|  | #endif /* !_HAVE_AFL_AS_H */ | ||||||
| @ -0,0 +1,461 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | # | ||||||
|  | # american fuzzy lop - corpus minimization tool | ||||||
|  | # --------------------------------------------- | ||||||
|  | # | ||||||
|  | # Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | # Copyright 2014, 2015 Google LLC All rights reserved. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | # you may not use this file except in compliance with the License. | ||||||
|  | # You may obtain a copy of the License at: | ||||||
|  | # | ||||||
|  | #   http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | # This tool tries to find the smallest subset of files in the input directory | ||||||
|  | # that still trigger the full range of instrumentation data points seen in | ||||||
|  | # the starting corpus. This has two uses: | ||||||
|  | # | ||||||
|  | #   - Screening large corpora of input files before using them as a seed for | ||||||
|  | #     afl-fuzz. The tool will remove functionally redundant files and likely | ||||||
|  | #     leave you with a much smaller set. | ||||||
|  | # | ||||||
|  | #     (In this case, you probably also want to consider running afl-tmin on | ||||||
|  | #     the individual files later on to reduce their size.) | ||||||
|  | # | ||||||
|  | #   - Minimizing the corpus generated organically by afl-fuzz, perhaps when | ||||||
|  | #     planning to feed it to more resource-intensive tools. The tool achieves | ||||||
|  | #     this by removing all entries that used to trigger unique behaviors in the | ||||||
|  | #     past, but have been made obsolete by later finds. | ||||||
|  | # | ||||||
|  | # Note that the tool doesn't modify the files themselves. For that, you want | ||||||
|  | # afl-tmin. | ||||||
|  | # | ||||||
|  | # This script must use bash because other shells may have hardcoded limits on | ||||||
|  | # array sizes. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | echo "corpus minimization tool for afl-fuzz by <lcamtuf@google.com>" | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | ######### | ||||||
|  | # SETUP # | ||||||
|  | ######### | ||||||
|  | 
 | ||||||
|  | # Process command-line options... | ||||||
|  | 
 | ||||||
|  | MEM_LIMIT=100 | ||||||
|  | TIMEOUT=none | ||||||
|  | 
 | ||||||
|  | unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \ | ||||||
|  |   AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE | ||||||
|  | 
 | ||||||
|  | while getopts "+i:o:f:m:t:eQC" opt; do | ||||||
|  | 
 | ||||||
|  |   case "$opt" in  | ||||||
|  | 
 | ||||||
|  |     "i") | ||||||
|  |          IN_DIR="$OPTARG" | ||||||
|  |          ;; | ||||||
|  | 
 | ||||||
|  |     "o") | ||||||
|  |          OUT_DIR="$OPTARG" | ||||||
|  |          ;; | ||||||
|  |     "f") | ||||||
|  |          STDIN_FILE="$OPTARG" | ||||||
|  |          ;; | ||||||
|  |     "m") | ||||||
|  |          MEM_LIMIT="$OPTARG" | ||||||
|  |          MEM_LIMIT_GIVEN=1 | ||||||
|  |          ;; | ||||||
|  |     "t") | ||||||
|  |          TIMEOUT="$OPTARG" | ||||||
|  |          ;; | ||||||
|  |     "e") | ||||||
|  |          EXTRA_PAR="$EXTRA_PAR -e" | ||||||
|  |          ;; | ||||||
|  |     "C") | ||||||
|  |          export AFL_CMIN_CRASHES_ONLY=1 | ||||||
|  |          ;; | ||||||
|  |     "Q") | ||||||
|  |          EXTRA_PAR="$EXTRA_PAR -Q" | ||||||
|  |          test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250 | ||||||
|  |          QEMU_MODE=1 | ||||||
|  |          ;; | ||||||
|  |     "?") | ||||||
|  |          exit 1 | ||||||
|  |          ;; | ||||||
|  | 
 | ||||||
|  |    esac | ||||||
|  | 
 | ||||||
|  | done | ||||||
|  | 
 | ||||||
|  | shift $((OPTIND-1)) | ||||||
|  | 
 | ||||||
|  | TARGET_BIN="$1" | ||||||
|  | 
 | ||||||
|  | if [ "$TARGET_BIN" = "" -o "$IN_DIR" = "" -o "$OUT_DIR" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   cat 1>&2 <<_EOF_ | ||||||
|  | Usage: $0 [ options ] -- /path/to/target_app [ ... ] | ||||||
|  | 
 | ||||||
|  | Required parameters: | ||||||
|  | 
 | ||||||
|  |   -i dir        - input directory with the starting corpus | ||||||
|  |   -o dir        - output directory for minimized files | ||||||
|  | 
 | ||||||
|  | Execution control settings: | ||||||
|  | 
 | ||||||
|  |   -f file       - location read by the fuzzed program (stdin) | ||||||
|  |   -m megs       - memory limit for child process ($MEM_LIMIT MB) | ||||||
|  |   -t msec       - run time limit for child process (none) | ||||||
|  |   -Q            - use binary-only instrumentation (QEMU mode) | ||||||
|  | 
 | ||||||
|  | Minimization settings: | ||||||
|  | 
 | ||||||
|  |   -C            - keep crashing inputs, reject everything else | ||||||
|  |   -e            - solve for edge coverage only, ignore hit counts | ||||||
|  | 
 | ||||||
|  | For additional tips, please consult docs/README. | ||||||
|  | 
 | ||||||
|  | _EOF_ | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Do a sanity check to discourage the use of /tmp, since we can't really | ||||||
|  | # handle this safely from a shell script. | ||||||
|  | 
 | ||||||
|  | if [ "$AFL_ALLOW_TMP" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "$IN_DIR" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T1="$?" | ||||||
|  | 
 | ||||||
|  |   echo "$TARGET_BIN" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T2="$?" | ||||||
|  | 
 | ||||||
|  |   echo "$OUT_DIR" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T3="$?" | ||||||
|  | 
 | ||||||
|  |   echo "$STDIN_FILE" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T4="$?" | ||||||
|  | 
 | ||||||
|  |   echo "$PWD" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T5="$?" | ||||||
|  | 
 | ||||||
|  |   if [ "$T1" = "0" -o "$T2" = "0" -o "$T3" = "0" -o "$T4" = "0" -o "$T5" = "0" ]; then | ||||||
|  |     echo "[-] Error: do not use this script in /tmp or /var/tmp." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # If @@ is specified, but there's no -f, let's come up with a temporary input | ||||||
|  | # file name. | ||||||
|  | 
 | ||||||
|  | TRACE_DIR="$OUT_DIR/.traces" | ||||||
|  | 
 | ||||||
|  | if [ "$STDIN_FILE" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   if echo "$*" | grep -qF '@@'; then | ||||||
|  |     STDIN_FILE="$TRACE_DIR/.cur_input" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Check for obvious errors. | ||||||
|  | 
 | ||||||
|  | if [ ! "$MEM_LIMIT" = "none" ]; then | ||||||
|  | 
 | ||||||
|  |   if [ "$MEM_LIMIT" -lt "5" ]; then | ||||||
|  |     echo "[-] Error: dangerously low memory limit." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! "$TIMEOUT" = "none" ]; then | ||||||
|  | 
 | ||||||
|  |   if [ "$TIMEOUT" -lt "10" ]; then | ||||||
|  |     echo "[-] Error: dangerously low timeout." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then | ||||||
|  | 
 | ||||||
|  |   TNEW="`which "$TARGET_BIN" 2>/dev/null`" | ||||||
|  | 
 | ||||||
|  |   if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then | ||||||
|  |     echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   TARGET_BIN="$TNEW" | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then | ||||||
|  |     echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! -d "$IN_DIR" ]; then | ||||||
|  |   echo "[-] Error: directory '$IN_DIR' not found." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | test -d "$IN_DIR/queue" && IN_DIR="$IN_DIR/queue" | ||||||
|  | 
 | ||||||
|  | find "$OUT_DIR" -name 'id[:_]*' -maxdepth 1 -exec rm -- {} \; 2>/dev/null | ||||||
|  | rm -rf "$TRACE_DIR" 2>/dev/null | ||||||
|  | 
 | ||||||
|  | rmdir "$OUT_DIR" 2>/dev/null | ||||||
|  | 
 | ||||||
|  | if [ -d "$OUT_DIR" ]; then | ||||||
|  |   echo "[-] Error: directory '$OUT_DIR' exists and is not empty - delete it first." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | mkdir -m 700 -p "$TRACE_DIR" || exit 1 | ||||||
|  | 
 | ||||||
|  | if [ ! "$STDIN_FILE" = "" ]; then | ||||||
|  |   rm -f "$STDIN_FILE" || exit 1 | ||||||
|  |   touch "$STDIN_FILE" || exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ "$AFL_PATH" = "" ]; then | ||||||
|  |   SHOWMAP="${0%/afl-cmin}/afl-showmap" | ||||||
|  | else | ||||||
|  |   SHOWMAP="$AFL_PATH/afl-showmap" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! -x "$SHOWMAP" ]; then | ||||||
|  |   echo "[-] Error: can't find 'afl-showmap' - please set AFL_PATH." 1>&2 | ||||||
|  |   rm -rf "$TRACE_DIR" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`)) | ||||||
|  | 
 | ||||||
|  | if [ "$IN_COUNT" = "0" ]; then | ||||||
|  |   echo "[+] Hmm, no inputs in the target directory. Nothing to be done." | ||||||
|  |   rm -rf "$TRACE_DIR" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | FIRST_FILE=`ls "$IN_DIR" | head -1` | ||||||
|  | 
 | ||||||
|  | # Make sure that we're not dealing with a directory. | ||||||
|  | 
 | ||||||
|  | if [ -d "$IN_DIR/$FIRST_FILE" ]; then | ||||||
|  |   echo "[-] Error: The target directory contains subdirectories - please fix." 1>&2 | ||||||
|  |   rm -rf "$TRACE_DIR" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Check for the more efficient way to copy files... | ||||||
|  | 
 | ||||||
|  | if ln "$IN_DIR/$FIRST_FILE" "$TRACE_DIR/.link_test" 2>/dev/null; then | ||||||
|  |   CP_TOOL=ln | ||||||
|  | else | ||||||
|  |   CP_TOOL=cp | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Make sure that we can actually get anything out of afl-showmap before we | ||||||
|  | # waste too much time. | ||||||
|  | 
 | ||||||
|  | echo "[*] Testing the target binary..." | ||||||
|  | 
 | ||||||
|  | if [ "$STDIN_FILE" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$FIRST_FILE" | ||||||
|  | 
 | ||||||
|  | else | ||||||
|  | 
 | ||||||
|  |   cp "$IN_DIR/$FIRST_FILE" "$STDIN_FILE" | ||||||
|  |   AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -A "$STDIN_FILE" -- "$@" </dev/null | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | FIRST_COUNT=$((`grep -c . "$TRACE_DIR/.run_test"`)) | ||||||
|  | 
 | ||||||
|  | if [ "$FIRST_COUNT" -gt "0" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[+] OK, $FIRST_COUNT tuples recorded." | ||||||
|  | 
 | ||||||
|  | else | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: no instrumentation output detected (perhaps crash or timeout)." 1>&2 | ||||||
|  |   test "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR" | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Let's roll! | ||||||
|  | 
 | ||||||
|  | ############################# | ||||||
|  | # STEP 1: COLLECTING TRACES # | ||||||
|  | ############################# | ||||||
|  | 
 | ||||||
|  | echo "[*] Obtaining traces for input files in '$IN_DIR'..." | ||||||
|  | 
 | ||||||
|  | ( | ||||||
|  | 
 | ||||||
|  |   CUR=0 | ||||||
|  | 
 | ||||||
|  |   if [ "$STDIN_FILE" = "" ]; then | ||||||
|  | 
 | ||||||
|  |     while read -r fn; do | ||||||
|  | 
 | ||||||
|  |       CUR=$((CUR+1)) | ||||||
|  |       printf "\\r    Processing file $CUR/$IN_COUNT... " | ||||||
|  | 
 | ||||||
|  |       "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn" | ||||||
|  | 
 | ||||||
|  |     done < <(ls "$IN_DIR") | ||||||
|  | 
 | ||||||
|  |   else | ||||||
|  | 
 | ||||||
|  |     while read -r fn; do | ||||||
|  | 
 | ||||||
|  |       CUR=$((CUR+1)) | ||||||
|  |       printf "\\r    Processing file $CUR/$IN_COUNT... " | ||||||
|  | 
 | ||||||
|  |       cp "$IN_DIR/$fn" "$STDIN_FILE" | ||||||
|  | 
 | ||||||
|  |       "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -A "$STDIN_FILE" -- "$@" </dev/null | ||||||
|  | 
 | ||||||
|  |     done < <(ls "$IN_DIR") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | ########################## | ||||||
|  | # STEP 2: SORTING TUPLES # | ||||||
|  | ########################## | ||||||
|  | 
 | ||||||
|  | # With this out of the way, we sort all tuples by popularity across all | ||||||
|  | # datasets. The reasoning here is that we won't be able to avoid the files | ||||||
|  | # that trigger unique tuples anyway, so we will want to start with them and | ||||||
|  | # see what's left. | ||||||
|  | 
 | ||||||
|  | echo "[*] Sorting trace sets (this may take a while)..." | ||||||
|  | 
 | ||||||
|  | ls "$IN_DIR" | sed "s#^#$TRACE_DIR/#" | tr '\n' '\0' | xargs -0 -n 1 cat | \ | ||||||
|  |   sort | uniq -c | sort -n >"$TRACE_DIR/.all_uniq" | ||||||
|  | 
 | ||||||
|  | TUPLE_COUNT=$((`grep -c . "$TRACE_DIR/.all_uniq"`)) | ||||||
|  | 
 | ||||||
|  | echo "[+] Found $TUPLE_COUNT unique tuples across $IN_COUNT files." | ||||||
|  | 
 | ||||||
|  | ##################################### | ||||||
|  | # STEP 3: SELECTING CANDIDATE FILES # | ||||||
|  | ##################################### | ||||||
|  | 
 | ||||||
|  | # The next step is to find the best candidate for each tuple. The "best" | ||||||
|  | # part is understood simply as the smallest input that includes a particular | ||||||
|  | # tuple in its trace. Empirical evidence suggests that this produces smaller | ||||||
|  | # datasets than more involved algorithms that could be still pulled off in | ||||||
|  | # a shell script. | ||||||
|  | 
 | ||||||
|  | echo "[*] Finding best candidates for each tuple..." | ||||||
|  | 
 | ||||||
|  | CUR=0 | ||||||
|  | 
 | ||||||
|  | while read -r fn; do | ||||||
|  | 
 | ||||||
|  |   CUR=$((CUR+1)) | ||||||
|  |   printf "\\r    Processing file $CUR/$IN_COUNT... " | ||||||
|  | 
 | ||||||
|  |   sed "s#\$# $fn#" "$TRACE_DIR/$fn" >>"$TRACE_DIR/.candidate_list" | ||||||
|  | 
 | ||||||
|  | done < <(ls -rS "$IN_DIR") | ||||||
|  | 
 | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | ############################## | ||||||
|  | # STEP 4: LOADING CANDIDATES # | ||||||
|  | ############################## | ||||||
|  | 
 | ||||||
|  | # At this point, we have a file of tuple-file pairs, sorted by file size | ||||||
|  | # in ascending order (as a consequence of ls -rS). By doing sort keyed | ||||||
|  | # only by tuple (-k 1,1) and configured to output only the first line for | ||||||
|  | # every key (-s -u), we end up with the smallest file for each tuple. | ||||||
|  | 
 | ||||||
|  | echo "[*] Sorting candidate list (be patient)..." | ||||||
|  | 
 | ||||||
|  | sort -k1,1 -s -u "$TRACE_DIR/.candidate_list" | \ | ||||||
|  |   sed 's/^/BEST_FILE[/;s/ /]="/;s/$/"/' >"$TRACE_DIR/.candidate_script" | ||||||
|  | 
 | ||||||
|  | if [ ! -s "$TRACE_DIR/.candidate_script" ]; then | ||||||
|  |   echo "[-] Error: no traces obtained from test cases, check syntax!" 1>&2 | ||||||
|  |   test "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # The sed command converted the sorted list to a shell script that populates | ||||||
|  | # BEST_FILE[tuple]="fname". Let's load that! | ||||||
|  | 
 | ||||||
|  | . "$TRACE_DIR/.candidate_script" | ||||||
|  | 
 | ||||||
|  | ########################## | ||||||
|  | # STEP 5: WRITING OUTPUT # | ||||||
|  | ########################## | ||||||
|  | 
 | ||||||
|  | # The final trick is to grab the top pick for each tuple, unless said tuple is | ||||||
|  | # already set due to the inclusion of an earlier candidate; and then put all | ||||||
|  | # tuples associated with the newly-added file to the "already have" list. The | ||||||
|  | # loop works from least popular tuples and toward the most common ones. | ||||||
|  | 
 | ||||||
|  | echo "[*] Processing candidates and writing output files..." | ||||||
|  | 
 | ||||||
|  | CUR=0 | ||||||
|  | 
 | ||||||
|  | touch "$TRACE_DIR/.already_have" | ||||||
|  | 
 | ||||||
|  | while read -r cnt tuple; do | ||||||
|  | 
 | ||||||
|  |   CUR=$((CUR+1)) | ||||||
|  |   printf "\\r    Processing tuple $CUR/$TUPLE_COUNT... " | ||||||
|  | 
 | ||||||
|  |   # If we already have this tuple, skip it. | ||||||
|  | 
 | ||||||
|  |   grep -q "^$tuple\$" "$TRACE_DIR/.already_have" && continue | ||||||
|  | 
 | ||||||
|  |   FN=${BEST_FILE[tuple]} | ||||||
|  | 
 | ||||||
|  |   $CP_TOOL "$IN_DIR/$FN" "$OUT_DIR/$FN" | ||||||
|  | 
 | ||||||
|  |   if [ "$((CUR % 5))" = "0" ]; then | ||||||
|  |     sort -u "$TRACE_DIR/$FN" "$TRACE_DIR/.already_have" >"$TRACE_DIR/.tmp" | ||||||
|  |     mv -f "$TRACE_DIR/.tmp" "$TRACE_DIR/.already_have" | ||||||
|  |   else | ||||||
|  |     cat "$TRACE_DIR/$FN" >>"$TRACE_DIR/.already_have" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | done <"$TRACE_DIR/.all_uniq" | ||||||
|  | 
 | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | OUT_COUNT=`ls -- "$OUT_DIR" | wc -l` | ||||||
|  | 
 | ||||||
|  | if [ "$OUT_COUNT" = "1" ]; then | ||||||
|  |   echo "[!] WARNING: All test cases had the same traces, check syntax!" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | echo "[+] Narrowed down to $OUT_COUNT files, saved in '$OUT_DIR'." | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | test "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR" | ||||||
|  | 
 | ||||||
|  | exit 0 | ||||||
| @ -0,0 +1,346 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - wrapper for GCC and clang | ||||||
|  |    ---------------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    This program is a drop-in replacement for GCC or clang. The most common way | ||||||
|  |    of using it is to pass the path to afl-gcc or afl-clang via CC when invoking | ||||||
|  |    ./configure. | ||||||
|  | 
 | ||||||
|  |    (Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.) | ||||||
|  | 
 | ||||||
|  |    The wrapper needs to know the path to afl-as (renamed to 'as'). The default | ||||||
|  |    is /usr/local/lib/afl/. A convenient way to specify alternative directories | ||||||
|  |    would be to set AFL_PATH. | ||||||
|  | 
 | ||||||
|  |    If AFL_HARDEN is set, the wrapper will compile the target app with various | ||||||
|  |    hardening options that may help detect memory management issues more | ||||||
|  |    reliably. You can also specify AFL_USE_ASAN to enable ASAN. | ||||||
|  | 
 | ||||||
|  |    If you want to call a non-default compiler as a next step of the chain, | ||||||
|  |    specify its location via AFL_CC or AFL_CXX. | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define AFL_MAIN | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include "types.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "alloc-inl.h" | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | static u8*  as_path;                /* Path to the AFL 'as' wrapper      */ | ||||||
|  | static u8** cc_params;              /* Parameters passed to the real CC  */ | ||||||
|  | static u32  cc_par_cnt = 1;         /* Param count, including argv0      */ | ||||||
|  | static u8   be_quiet,               /* Quiet mode                        */ | ||||||
|  |             clang_mode;             /* Invoked as afl-clang*?            */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
 | ||||||
|  |    from argv[0]. If that fails, abort. */ | ||||||
|  | 
 | ||||||
|  | static void find_as(u8* argv0) { | ||||||
|  | 
 | ||||||
|  |   u8 *afl_path = getenv("AFL_PATH"); | ||||||
|  |   u8 *slash, *tmp; | ||||||
|  | 
 | ||||||
|  |   if (afl_path) { | ||||||
|  | 
 | ||||||
|  |     tmp = alloc_printf("%s/as", afl_path); | ||||||
|  | 
 | ||||||
|  |     if (!access(tmp, X_OK)) { | ||||||
|  |       as_path = afl_path; | ||||||
|  |       ck_free(tmp); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ck_free(tmp); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   slash = strrchr(argv0, '/'); | ||||||
|  | 
 | ||||||
|  |   if (slash) { | ||||||
|  | 
 | ||||||
|  |     u8 *dir; | ||||||
|  | 
 | ||||||
|  |     *slash = 0; | ||||||
|  |     dir = ck_strdup(argv0); | ||||||
|  |     *slash = '/'; | ||||||
|  | 
 | ||||||
|  |     tmp = alloc_printf("%s/afl-as", dir); | ||||||
|  | 
 | ||||||
|  |     if (!access(tmp, X_OK)) { | ||||||
|  |       as_path = dir; | ||||||
|  |       ck_free(tmp); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ck_free(tmp); | ||||||
|  |     ck_free(dir); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!access(AFL_PATH "/as", X_OK)) { | ||||||
|  |     as_path = AFL_PATH; | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH"); | ||||||
|  |   | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Copy argv to cc_params, making the necessary edits. */ | ||||||
|  | 
 | ||||||
|  | static void edit_params(u32 argc, char** argv) { | ||||||
|  | 
 | ||||||
|  |   u8 fortify_set = 0, asan_set = 0; | ||||||
|  |   u8 *name; | ||||||
|  | 
 | ||||||
|  | #if defined(__FreeBSD__) && defined(__x86_64__) | ||||||
|  |   u8 m32_set = 0; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   cc_params = ck_alloc((argc + 128) * sizeof(u8*)); | ||||||
|  | 
 | ||||||
|  |   name = strrchr(argv[0], '/'); | ||||||
|  |   if (!name) name = argv[0]; else name++; | ||||||
|  | 
 | ||||||
|  |   if (!strncmp(name, "afl-clang", 9)) { | ||||||
|  | 
 | ||||||
|  |     clang_mode = 1; | ||||||
|  | 
 | ||||||
|  |     setenv(CLANG_ENV_VAR, "1", 1); | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(name, "afl-clang++")) { | ||||||
|  |       u8* alt_cxx = getenv("AFL_CXX"); | ||||||
|  |       cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; | ||||||
|  |     } else { | ||||||
|  |       u8* alt_cc = getenv("AFL_CC"); | ||||||
|  |       cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     /* With GCJ and Eclipse installed, you can actually compile Java! The
 | ||||||
|  |        instrumentation will work (amazingly). Alas, unhandled exceptions do | ||||||
|  |        not call abort(), so afl-fuzz would need to be modified to equate | ||||||
|  |        non-zero exit codes with crash conditions when working with Java | ||||||
|  |        binaries. Meh. */ | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX"); | ||||||
|  |     else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ"); | ||||||
|  |     else cc_params[0] = getenv("AFL_CC"); | ||||||
|  | 
 | ||||||
|  |     if (!cc_params[0]) { | ||||||
|  | 
 | ||||||
|  |       SAYF("\n" cLRD "[-] " cRST | ||||||
|  |            "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n" | ||||||
|  |            "    'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n" | ||||||
|  |            "    set AFL_CC or AFL_CXX to specify the correct path to that compiler.\n"); | ||||||
|  | 
 | ||||||
|  |       FATAL("AFL_CC or AFL_CXX required on MacOS X"); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(name, "afl-g++")) { | ||||||
|  |       u8* alt_cxx = getenv("AFL_CXX"); | ||||||
|  |       cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++"; | ||||||
|  |     } else if (!strcmp(name, "afl-gcj")) { | ||||||
|  |       u8* alt_cc = getenv("AFL_GCJ"); | ||||||
|  |       cc_params[0] = alt_cc ? alt_cc : (u8*)"gcj"; | ||||||
|  |     } else { | ||||||
|  |       u8* alt_cc = getenv("AFL_CC"); | ||||||
|  |       cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | #endif /* __APPLE__ */ | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   while (--argc) { | ||||||
|  |     u8* cur = *(++argv); | ||||||
|  | 
 | ||||||
|  |     if (!strncmp(cur, "-B", 2)) { | ||||||
|  | 
 | ||||||
|  |       if (!be_quiet) WARNF("-B is already set, overriding"); | ||||||
|  | 
 | ||||||
|  |       if (!cur[2] && argc > 1) { argc--; argv++; } | ||||||
|  |       continue; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(cur, "-integrated-as")) continue; | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(cur, "-pipe")) continue; | ||||||
|  | 
 | ||||||
|  | #if defined(__FreeBSD__) && defined(__x86_64__) | ||||||
|  |     if (!strcmp(cur, "-m32")) m32_set = 1; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     if (!strcmp(cur, "-fsanitize=address") || | ||||||
|  |         !strcmp(cur, "-fsanitize=memory")) asan_set = 1; | ||||||
|  | 
 | ||||||
|  |     if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = cur; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   cc_params[cc_par_cnt++] = "-B"; | ||||||
|  |   cc_params[cc_par_cnt++] = as_path; | ||||||
|  | 
 | ||||||
|  |   if (clang_mode) | ||||||
|  |     cc_params[cc_par_cnt++] = "-no-integrated-as"; | ||||||
|  | 
 | ||||||
|  |   if (getenv("AFL_HARDEN")) { | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-fstack-protector-all"; | ||||||
|  | 
 | ||||||
|  |     if (!fortify_set) | ||||||
|  |       cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (asan_set) { | ||||||
|  | 
 | ||||||
|  |     /* Pass this on to afl-as to adjust map density. */ | ||||||
|  | 
 | ||||||
|  |     setenv("AFL_USE_ASAN", "1", 1); | ||||||
|  | 
 | ||||||
|  |   } else if (getenv("AFL_USE_ASAN")) { | ||||||
|  | 
 | ||||||
|  |     if (getenv("AFL_USE_MSAN")) | ||||||
|  |       FATAL("ASAN and MSAN are mutually exclusive"); | ||||||
|  | 
 | ||||||
|  |     if (getenv("AFL_HARDEN")) | ||||||
|  |       FATAL("ASAN and AFL_HARDEN are mutually exclusive"); | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fsanitize=address"; | ||||||
|  | 
 | ||||||
|  |   } else if (getenv("AFL_USE_MSAN")) { | ||||||
|  | 
 | ||||||
|  |     if (getenv("AFL_USE_ASAN")) | ||||||
|  |       FATAL("ASAN and MSAN are mutually exclusive"); | ||||||
|  | 
 | ||||||
|  |     if (getenv("AFL_HARDEN")) | ||||||
|  |       FATAL("MSAN and AFL_HARDEN are mutually exclusive"); | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fsanitize=memory"; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!getenv("AFL_DONT_OPTIMIZE")) { | ||||||
|  | 
 | ||||||
|  | #if defined(__FreeBSD__) && defined(__x86_64__) | ||||||
|  | 
 | ||||||
|  |     /* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
 | ||||||
|  |        works OK. This has nothing to do with us, but let's avoid triggering | ||||||
|  |        that bug. */ | ||||||
|  | 
 | ||||||
|  |     if (!clang_mode || !m32_set) | ||||||
|  |       cc_params[cc_par_cnt++] = "-g"; | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |       cc_params[cc_par_cnt++] = "-g"; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-O3"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-funroll-loops"; | ||||||
|  | 
 | ||||||
|  |     /* Two indicators that you're building for fuzzing; one of them is
 | ||||||
|  |        AFL-specific, the other is shared with libfuzzer. */ | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (getenv("AFL_NO_BUILTIN")) { | ||||||
|  | 
 | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; | ||||||
|  |     cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   cc_params[cc_par_cnt] = NULL; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Main entry point */ | ||||||
|  | 
 | ||||||
|  | int main(int argc, char** argv) { | ||||||
|  | 
 | ||||||
|  |   if (isatty(2) && !getenv("AFL_QUIET")) { | ||||||
|  | 
 | ||||||
|  |     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" | ||||||
|  | 
 | ||||||
|  |          "  CC=%s/afl-gcc ./configure\n" | ||||||
|  |          "  CXX=%s/afl-g++ ./configure\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); | ||||||
|  | 
 | ||||||
|  |     exit(1); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   find_as(argv[0]); | ||||||
|  | 
 | ||||||
|  |   edit_params(argc, argv); | ||||||
|  | 
 | ||||||
|  |   execvp(cc_params[0], (char**)cc_params); | ||||||
|  | 
 | ||||||
|  |   FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,260 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2015 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - free CPU gizmo | ||||||
|  |    ----------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    This tool provides a fairly accurate measurement of CPU preemption rate. | ||||||
|  |    It is meant to complement the quick-and-dirty load average widget shown | ||||||
|  |    in the afl-fuzz UI. See docs/parallel_fuzzing.txt for more info. | ||||||
|  | 
 | ||||||
|  |    For some work loads, the tool may actually suggest running more instances | ||||||
|  |    than you have CPU cores. This can happen if the tested program is spending | ||||||
|  |    a portion of its run time waiting for I/O, rather than being 100% | ||||||
|  |    CPU-bound. | ||||||
|  | 
 | ||||||
|  |    The idea for the getrusage()-based approach comes from Jakub Wilk. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define AFL_MAIN | ||||||
|  | #include "android-ashmem.h" | ||||||
|  | #define _GNU_SOURCE | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <sched.h> | ||||||
|  | 
 | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/times.h> | ||||||
|  | #include <sys/resource.h> | ||||||
|  | #include <sys/wait.h> | ||||||
|  | 
 | ||||||
|  | #include "types.h" | ||||||
|  | #include "debug.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __linux__ | ||||||
|  | #  define HAVE_AFFINITY 1 | ||||||
|  | #endif /* __linux__ */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Get unix time in microseconds. */ | ||||||
|  | 
 | ||||||
|  | static u64 get_cur_time_us(void) { | ||||||
|  | 
 | ||||||
|  |   struct timeval tv; | ||||||
|  |   struct timezone tz; | ||||||
|  | 
 | ||||||
|  |   gettimeofday(&tv, &tz); | ||||||
|  | 
 | ||||||
|  |   return (tv.tv_sec * 1000000ULL) + tv.tv_usec; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Get CPU usage in microseconds. */ | ||||||
|  | 
 | ||||||
|  | static u64 get_cpu_usage_us(void) { | ||||||
|  | 
 | ||||||
|  |   struct rusage u; | ||||||
|  | 
 | ||||||
|  |   getrusage(RUSAGE_SELF, &u); | ||||||
|  | 
 | ||||||
|  |   return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec + | ||||||
|  |          (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Measure preemption rate. */ | ||||||
|  | 
 | ||||||
|  | static u32 measure_preemption(u32 target_ms) { | ||||||
|  | 
 | ||||||
|  |   static volatile u32 v1, v2; | ||||||
|  | 
 | ||||||
|  |   u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; | ||||||
|  |   s32 loop_repeats = 0; | ||||||
|  | 
 | ||||||
|  |   st_t = get_cur_time_us(); | ||||||
|  |   st_c = get_cpu_usage_us(); | ||||||
|  | 
 | ||||||
|  | repeat_loop: | ||||||
|  | 
 | ||||||
|  |   v1 = CTEST_BUSY_CYCLES; | ||||||
|  | 
 | ||||||
|  |   while (v1--) v2++; | ||||||
|  |   sched_yield(); | ||||||
|  | 
 | ||||||
|  |   en_t = get_cur_time_us(); | ||||||
|  | 
 | ||||||
|  |   if (en_t - st_t < target_ms * 1000) { | ||||||
|  |     loop_repeats++; | ||||||
|  |     goto repeat_loop; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /* Let's see what percentage of this time we actually had a chance to
 | ||||||
|  |      run, and how much time was spent in the penalty box. */ | ||||||
|  | 
 | ||||||
|  |   en_c = get_cpu_usage_us(); | ||||||
|  | 
 | ||||||
|  |   real_delta  = (en_t - st_t) / 1000; | ||||||
|  |   slice_delta = (en_c - st_c) / 1000; | ||||||
|  | 
 | ||||||
|  |   return real_delta * 100 / slice_delta; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Do the benchmark thing. */ | ||||||
|  | 
 | ||||||
|  | int main(int argc, char** argv) { | ||||||
|  | 
 | ||||||
|  | #ifdef HAVE_AFFINITY | ||||||
|  | 
 | ||||||
|  |   u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN), | ||||||
|  |       idle_cpus = 0, maybe_cpus = 0, i; | ||||||
|  | 
 | ||||||
|  |   SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); | ||||||
|  | 
 | ||||||
|  |   ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...", | ||||||
|  |        ((double)CTEST_CORE_TRG_MS) / 1000); | ||||||
|  | 
 | ||||||
|  |   for (i = 0; i < cpu_cnt; i++) { | ||||||
|  | 
 | ||||||
|  |     s32 fr = fork(); | ||||||
|  | 
 | ||||||
|  |     if (fr < 0) PFATAL("fork failed"); | ||||||
|  | 
 | ||||||
|  |     if (!fr) { | ||||||
|  | 
 | ||||||
|  |       cpu_set_t c; | ||||||
|  |       u32 util_perc; | ||||||
|  | 
 | ||||||
|  |       CPU_ZERO(&c); | ||||||
|  |       CPU_SET(i, &c); | ||||||
|  | 
 | ||||||
|  |       if (sched_setaffinity(0, sizeof(c), &c)) | ||||||
|  |         PFATAL("sched_setaffinity failed for cpu %d", i); | ||||||
|  | 
 | ||||||
|  |       util_perc = measure_preemption(CTEST_CORE_TRG_MS); | ||||||
|  | 
 | ||||||
|  |       if (util_perc < 110) { | ||||||
|  | 
 | ||||||
|  |         SAYF("    Core #%u: " cLGN "AVAILABLE " cRST "(%u%%)\n", i, util_perc); | ||||||
|  |         exit(0); | ||||||
|  | 
 | ||||||
|  |       } else if (util_perc < 250) { | ||||||
|  | 
 | ||||||
|  |         SAYF("    Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc);  | ||||||
|  |         exit(1); | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       SAYF("    Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i, | ||||||
|  |            util_perc); | ||||||
|  |       exit(2); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   for (i = 0; i < cpu_cnt; i++) { | ||||||
|  | 
 | ||||||
|  |     int ret; | ||||||
|  |     if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); | ||||||
|  | 
 | ||||||
|  |     if (WEXITSTATUS(ret) == 0) idle_cpus++; | ||||||
|  |     if (WEXITSTATUS(ret) <= 1) maybe_cpus++; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   SAYF(cGRA "\n>>> "); | ||||||
|  | 
 | ||||||
|  |   if (idle_cpus) { | ||||||
|  | 
 | ||||||
|  |     if (maybe_cpus == idle_cpus) { | ||||||
|  | 
 | ||||||
|  |       SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.", | ||||||
|  |            idle_cpus, idle_cpus > 1 ? "s" : ""); | ||||||
|  | 
 | ||||||
|  |     } else { | ||||||
|  | 
 | ||||||
|  |       SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.", | ||||||
|  |            idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : ""); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SAYF(cGRA " <<<" cRST "\n\n"); | ||||||
|  |     return 0; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (maybe_cpus) { | ||||||
|  | 
 | ||||||
|  |     SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.", | ||||||
|  |          maybe_cpus, maybe_cpus > 1 ? "s" : ""); | ||||||
|  |     SAYF(cGRA " <<<" cRST "\n\n"); | ||||||
|  |     return 1; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   SAYF(cLRD "FAIL: " cRST "All cores are overbooked."); | ||||||
|  |   SAYF(cGRA " <<<" cRST "\n\n"); | ||||||
|  |   return 2; | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |   u32 util_perc; | ||||||
|  | 
 | ||||||
|  |   SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); | ||||||
|  | 
 | ||||||
|  |   /* Run a busy loop for CTEST_TARGET_MS. */ | ||||||
|  | 
 | ||||||
|  |   ACTF("Measuring gross preemption rate (this will take %0.02f sec)...", | ||||||
|  |        ((double)CTEST_TARGET_MS) / 1000); | ||||||
|  | 
 | ||||||
|  |   util_perc = measure_preemption(CTEST_TARGET_MS); | ||||||
|  | 
 | ||||||
|  |   /* Deliver the final verdict. */ | ||||||
|  | 
 | ||||||
|  |   SAYF(cGRA "\n>>> "); | ||||||
|  | 
 | ||||||
|  |   if (util_perc < 105) { | ||||||
|  | 
 | ||||||
|  |     SAYF(cLGN "PASS: " cRST "You can probably run additional processes."); | ||||||
|  | 
 | ||||||
|  |   } else if (util_perc < 130) { | ||||||
|  | 
 | ||||||
|  |     SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).", | ||||||
|  |          util_perc); | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   SAYF(cGRA " <<<" cRST "\n\n"); | ||||||
|  | 
 | ||||||
|  |   return (util_perc > 105) + (util_perc > 130); | ||||||
|  | 
 | ||||||
|  | #endif /* ^HAVE_AFFINITY */ | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,170 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | # | ||||||
|  | # american fuzzy lop - Advanced Persistent Graphing | ||||||
|  | # ------------------------------------------------- | ||||||
|  | # | ||||||
|  | # Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # Based on a design & prototype by Michael Rash. | ||||||
|  | # | ||||||
|  | # Copyright 2014, 2015 Google LLC All rights reserved. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | # you may not use this file except in compliance with the License. | ||||||
|  | # You may obtain a copy of the License at: | ||||||
|  | # | ||||||
|  | #   http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | echo "progress plotting utility for afl-fuzz by <lcamtuf@google.com>" | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | if [ ! "$#" = "2" ]; then | ||||||
|  | 
 | ||||||
|  |   cat 1>&2 <<_EOF_ | ||||||
|  | This program generates gnuplot images from afl-fuzz output data. Usage: | ||||||
|  | 
 | ||||||
|  | $0 afl_state_dir graph_output_dir | ||||||
|  | 
 | ||||||
|  | The afl_state_dir parameter should point to an existing state directory for any | ||||||
|  | active or stopped instance of afl-fuzz; while graph_output_dir should point to | ||||||
|  | an empty directory where this tool can write the resulting plots to. | ||||||
|  | 
 | ||||||
|  | The program will put index.html and three PNG images in the output directory; | ||||||
|  | you should be able to view it with any web browser of your choice. | ||||||
|  | 
 | ||||||
|  | _EOF_ | ||||||
|  | 
 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ "$AFL_ALLOW_TMP" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "$1" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T1="$?" | ||||||
|  | 
 | ||||||
|  |   echo "$2" | grep -qE '^(/var)?/tmp/' | ||||||
|  |   T2="$?" | ||||||
|  | 
 | ||||||
|  |   if [ "$T1" = "0" -o "$T2" = "0" ]; then | ||||||
|  | 
 | ||||||
|  |     echo "[-] Error: this script shouldn't be used with shared /tmp directories." 1>&2 | ||||||
|  |     exit 1 | ||||||
|  | 
 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ ! -f "$1/plot_data" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: input directory is not valid (missing 'plot_data')." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | BANNER="`cat "$1/fuzzer_stats" | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`" | ||||||
|  | 
 | ||||||
|  | test "$BANNER" = "" && BANNER="(none)" | ||||||
|  | 
 | ||||||
|  | GNUPLOT=`which gnuplot 2>/dev/null` | ||||||
|  | 
 | ||||||
|  | if [ "$GNUPLOT" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: can't find 'gnuplot' in your \$PATH." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | mkdir "$2" 2>/dev/null | ||||||
|  | 
 | ||||||
|  | if [ ! -d "$2" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: unable to create the output directory - pick another location." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | rm -f "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png" | ||||||
|  | mv -f "$2/index.html" "$2/index.html.orig" 2>/dev/null | ||||||
|  | 
 | ||||||
|  | echo "[*] Generating plots..." | ||||||
|  | 
 | ||||||
|  | ( | ||||||
|  | 
 | ||||||
|  | cat <<_EOF_ | ||||||
|  | set terminal png truecolor enhanced size 1000,300 butt | ||||||
|  | 
 | ||||||
|  | set output '$2/high_freq.png' | ||||||
|  | 
 | ||||||
|  | set xdata time | ||||||
|  | set timefmt '%s' | ||||||
|  | set format x "%b %d\n%H:%M" | ||||||
|  | set tics font 'small' | ||||||
|  | unset mxtics | ||||||
|  | unset mytics | ||||||
|  | 
 | ||||||
|  | set grid xtics linetype 0 linecolor rgb '#e0e0e0' | ||||||
|  | set grid ytics linetype 0 linecolor rgb '#e0e0e0' | ||||||
|  | set border linecolor rgb '#50c0f0' | ||||||
|  | set tics textcolor rgb '#000000' | ||||||
|  | set key outside | ||||||
|  | 
 | ||||||
|  | set autoscale xfixmin | ||||||
|  | set autoscale xfixmax | ||||||
|  | 
 | ||||||
|  | plot '$1/plot_data' using 1:4 with filledcurve x1 title 'total paths' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\ | ||||||
|  |      '' using 1:3 with filledcurve x1 title 'current path' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\ | ||||||
|  |      '' using 1:5 with lines title 'pending paths' linecolor rgb '#0090ff' linewidth 3, \\ | ||||||
|  |      '' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\ | ||||||
|  |      '' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3 | ||||||
|  | 
 | ||||||
|  | set terminal png truecolor enhanced size 1000,200 butt | ||||||
|  | set output '$2/low_freq.png' | ||||||
|  | 
 | ||||||
|  | plot '$1/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\ | ||||||
|  |      '' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\ | ||||||
|  |      '' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\ | ||||||
|  |      '' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3 | ||||||
|  | 
 | ||||||
|  | set terminal png truecolor enhanced size 1000,200 butt | ||||||
|  | set output '$2/exec_speed.png' | ||||||
|  | 
 | ||||||
|  | plot '$1/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\ | ||||||
|  |      '$1/plot_data' using 1:11 with lines title '    execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier; | ||||||
|  | 
 | ||||||
|  | _EOF_ | ||||||
|  | 
 | ||||||
|  | ) | gnuplot  | ||||||
|  | 
 | ||||||
|  | if [ ! -s "$2/exec_speed.png" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: something went wrong! Perhaps you have an ancient version of gnuplot?" 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | echo "[*] Generating index.html..." | ||||||
|  | 
 | ||||||
|  | cat >"$2/index.html" <<_EOF_ | ||||||
|  | <table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'"> | ||||||
|  | <tr><td style="width: 18ex"><b>Banner:</b></td><td>$BANNER</td></tr> | ||||||
|  | <tr><td><b>Directory:</b></td><td>$1</td></tr> | ||||||
|  | <tr><td><b>Generated on:</b></td><td>`date`</td></tr> | ||||||
|  | </table> | ||||||
|  | <p> | ||||||
|  | <img src="high_freq.png" width=1000 height=300><p> | ||||||
|  | <img src="low_freq.png" width=1000 height=200><p> | ||||||
|  | <img src="exec_speed.png" width=1000 height=200> | ||||||
|  | 
 | ||||||
|  | _EOF_ | ||||||
|  | 
 | ||||||
|  | # Make it easy to remotely view results when outputting directly to a directory | ||||||
|  | # served by Apache or other HTTP daemon. Since the plots aren't horribly | ||||||
|  | # sensitive, this seems like a reasonable trade-off. | ||||||
|  | 
 | ||||||
|  | chmod 755 "$2" | ||||||
|  | chmod 644 "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png" "$2/index.html" | ||||||
|  | 
 | ||||||
|  | echo "[+] All done - enjoy your charts!" | ||||||
|  | 
 | ||||||
|  | exit 0 | ||||||
| @ -0,0 +1,795 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - map display utility | ||||||
|  |    ---------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    A very simple tool that runs the targeted binary and displays | ||||||
|  |    the contents of the trace bitmap in a human-readable form. Useful in | ||||||
|  |    scripts to eliminate redundant inputs and perform other checks. | ||||||
|  | 
 | ||||||
|  |    Exit code is 2 if the target program crashes; 1 if it times out or | ||||||
|  |    there is a problem executing it; or 0 if execution is successful. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define AFL_MAIN | ||||||
|  | #include "android-ashmem.h" | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include "types.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "alloc-inl.h" | ||||||
|  | #include "hash.h" | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <dirent.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | 
 | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/shm.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/resource.h> | ||||||
|  | 
 | ||||||
|  | static s32 child_pid;                 /* PID of the tested program         */ | ||||||
|  | 
 | ||||||
|  | static u8* trace_bits;                /* SHM with instrumentation bitmap   */ | ||||||
|  | 
 | ||||||
|  | static u8 *out_file,                  /* Trace output file                 */ | ||||||
|  |           *doc_path,                  /* Path to docs                      */ | ||||||
|  |           *target_path,               /* Path to target binary             */ | ||||||
|  |           *at_file;                   /* Substitution string for @@        */ | ||||||
|  | 
 | ||||||
|  | static u32 exec_tmout;                /* Exec timeout (ms)                 */ | ||||||
|  | 
 | ||||||
|  | static u64 mem_limit = MEM_LIMIT;     /* Memory limit (MB)                 */ | ||||||
|  | 
 | ||||||
|  | static s32 shm_id;                    /* ID of the SHM region              */ | ||||||
|  | 
 | ||||||
|  | static u8  quiet_mode,                /* Hide non-essential messages?      */ | ||||||
|  |            edges_only,                /* Ignore hit counts?                */ | ||||||
|  |            cmin_mode,                 /* Generate output in afl-cmin mode? */ | ||||||
|  |            binary_mode,               /* Write output as a binary map      */ | ||||||
|  |            keep_cores;                /* Allow coredumps?                  */ | ||||||
|  | 
 | ||||||
|  | static volatile u8 | ||||||
|  |            stop_soon,                 /* Ctrl-C pressed?                   */ | ||||||
|  |            child_timed_out,           /* Child timed out?                  */ | ||||||
|  |            child_crashed;             /* Child crashed?                    */ | ||||||
|  | 
 | ||||||
|  | /* Classify tuple counts. Instead of mapping to individual bits, as in
 | ||||||
|  |    afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ | ||||||
|  | 
 | ||||||
|  | static const u8 count_class_human[256] = { | ||||||
|  | 
 | ||||||
|  |   [0]           = 0, | ||||||
|  |   [1]           = 1, | ||||||
|  |   [2]           = 2, | ||||||
|  |   [3]           = 3, | ||||||
|  |   [4 ... 7]     = 4, | ||||||
|  |   [8 ... 15]    = 5, | ||||||
|  |   [16 ... 31]   = 6, | ||||||
|  |   [32 ... 127]  = 7, | ||||||
|  |   [128 ... 255] = 8 | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 count_class_binary[256] = { | ||||||
|  | 
 | ||||||
|  |   [0]           = 0, | ||||||
|  |   [1]           = 1, | ||||||
|  |   [2]           = 2, | ||||||
|  |   [3]           = 4, | ||||||
|  |   [4 ... 7]     = 8, | ||||||
|  |   [8 ... 15]    = 16, | ||||||
|  |   [16 ... 31]   = 32, | ||||||
|  |   [32 ... 127]  = 64, | ||||||
|  |   [128 ... 255] = 128 | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void classify_counts(u8* mem, const u8* map) { | ||||||
|  | 
 | ||||||
|  |   u32 i = MAP_SIZE; | ||||||
|  | 
 | ||||||
|  |   if (edges_only) { | ||||||
|  | 
 | ||||||
|  |     while (i--) { | ||||||
|  |       if (*mem) *mem = 1; | ||||||
|  |       mem++; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     while (i--) { | ||||||
|  |       *mem = map[*mem]; | ||||||
|  |       mem++; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Get rid of shared memory (atexit handler). */ | ||||||
|  | 
 | ||||||
|  | static void remove_shm(void) { | ||||||
|  | 
 | ||||||
|  |   shmctl(shm_id, IPC_RMID, NULL); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Configure shared memory. */ | ||||||
|  | 
 | ||||||
|  | static void setup_shm(void) { | ||||||
|  | 
 | ||||||
|  |   u8* shm_str; | ||||||
|  | 
 | ||||||
|  |   shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); | ||||||
|  | 
 | ||||||
|  |   if (shm_id < 0) PFATAL("shmget() failed"); | ||||||
|  | 
 | ||||||
|  |   atexit(remove_shm); | ||||||
|  | 
 | ||||||
|  |   shm_str = alloc_printf("%d", shm_id); | ||||||
|  | 
 | ||||||
|  |   setenv(SHM_ENV_VAR, shm_str, 1); | ||||||
|  | 
 | ||||||
|  |   ck_free(shm_str); | ||||||
|  | 
 | ||||||
|  |   trace_bits = shmat(shm_id, NULL, 0); | ||||||
|  |    | ||||||
|  |   if (trace_bits == (void *)-1) PFATAL("shmat() failed"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Write results. */ | ||||||
|  | 
 | ||||||
|  | static u32 write_results(void) { | ||||||
|  | 
 | ||||||
|  |   s32 fd; | ||||||
|  |   u32 i, ret = 0; | ||||||
|  | 
 | ||||||
|  |   u8  cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), | ||||||
|  |       caa = !!getenv("AFL_CMIN_ALLOW_ANY"); | ||||||
|  | 
 | ||||||
|  |   if (!strncmp(out_file, "/dev/", 5)) { | ||||||
|  | 
 | ||||||
|  |     fd = open(out_file, O_WRONLY, 0600); | ||||||
|  |     if (fd < 0) PFATAL("Unable to open '%s'", out_file); | ||||||
|  | 
 | ||||||
|  |   } else if (!strcmp(out_file, "-")) { | ||||||
|  | 
 | ||||||
|  |     fd = dup(1); | ||||||
|  |     if (fd < 0) PFATAL("Unable to open stdout"); | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     unlink(out_file); /* Ignore errors */ | ||||||
|  |     fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); | ||||||
|  |     if (fd < 0) PFATAL("Unable to create '%s'", out_file); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   if (binary_mode) { | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < MAP_SIZE; i++) | ||||||
|  |       if (trace_bits[i]) ret++; | ||||||
|  |      | ||||||
|  |     ck_write(fd, trace_bits, MAP_SIZE, out_file); | ||||||
|  |     close(fd); | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     FILE* f = fdopen(fd, "w"); | ||||||
|  | 
 | ||||||
|  |     if (!f) PFATAL("fdopen() failed"); | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < MAP_SIZE; i++) { | ||||||
|  | 
 | ||||||
|  |       if (!trace_bits[i]) continue; | ||||||
|  |       ret++; | ||||||
|  | 
 | ||||||
|  |       if (cmin_mode) { | ||||||
|  | 
 | ||||||
|  |         if (child_timed_out) break; | ||||||
|  |         if (!caa && child_crashed != cco) break; | ||||||
|  | 
 | ||||||
|  |         fprintf(f, "%u%u\n", trace_bits[i], i); | ||||||
|  | 
 | ||||||
|  |       } else fprintf(f, "%06u:%u\n", i, trace_bits[i]); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |     fclose(f); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Handle timeout signal. */ | ||||||
|  | 
 | ||||||
|  | static void handle_timeout(int sig) { | ||||||
|  | 
 | ||||||
|  |   child_timed_out = 1; | ||||||
|  |   if (child_pid > 0) kill(child_pid, SIGKILL); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Execute target application. */ | ||||||
|  | 
 | ||||||
|  | static void run_target(char** argv) { | ||||||
|  | 
 | ||||||
|  |   static struct itimerval it; | ||||||
|  |   int status = 0; | ||||||
|  | 
 | ||||||
|  |   if (!quiet_mode) | ||||||
|  |     SAYF("-- Program output begins --\n" cRST); | ||||||
|  | 
 | ||||||
|  |   MEM_BARRIER(); | ||||||
|  | 
 | ||||||
|  |   child_pid = fork(); | ||||||
|  | 
 | ||||||
|  |   if (child_pid < 0) PFATAL("fork() failed"); | ||||||
|  | 
 | ||||||
|  |   if (!child_pid) { | ||||||
|  | 
 | ||||||
|  |     struct rlimit r; | ||||||
|  | 
 | ||||||
|  |     if (quiet_mode) { | ||||||
|  | 
 | ||||||
|  |       s32 fd = open("/dev/null", O_RDWR); | ||||||
|  | 
 | ||||||
|  |       if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) { | ||||||
|  |         *(u32*)trace_bits = EXEC_FAIL_SIG; | ||||||
|  |         PFATAL("Descriptor initialization failed"); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       close(fd); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (mem_limit) { | ||||||
|  | 
 | ||||||
|  |       r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; | ||||||
|  | 
 | ||||||
|  | #ifdef RLIMIT_AS | ||||||
|  | 
 | ||||||
|  |       setrlimit(RLIMIT_AS, &r); /* Ignore errors */ | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |       setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ | ||||||
|  | 
 | ||||||
|  | #endif /* ^RLIMIT_AS */ | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!keep_cores) r.rlim_max = r.rlim_cur = 0; | ||||||
|  |     else r.rlim_max = r.rlim_cur = RLIM_INFINITY; | ||||||
|  | 
 | ||||||
|  |     setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ | ||||||
|  | 
 | ||||||
|  |     if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); | ||||||
|  | 
 | ||||||
|  |     setsid(); | ||||||
|  | 
 | ||||||
|  |     execv(target_path, argv); | ||||||
|  | 
 | ||||||
|  |     *(u32*)trace_bits = EXEC_FAIL_SIG; | ||||||
|  |     exit(0); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /* 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"); | ||||||
|  | 
 | ||||||
|  |   child_pid = 0; | ||||||
|  |   it.it_value.tv_sec = 0; | ||||||
|  |   it.it_value.tv_usec = 0; | ||||||
|  |   setitimer(ITIMER_REAL, &it, NULL); | ||||||
|  | 
 | ||||||
|  |   MEM_BARRIER(); | ||||||
|  | 
 | ||||||
|  |   /* Clean up bitmap, analyze exit condition, etc. */ | ||||||
|  | 
 | ||||||
|  |   if (*(u32*)trace_bits == EXEC_FAIL_SIG) | ||||||
|  |     FATAL("Unable to execute '%s'", argv[0]); | ||||||
|  | 
 | ||||||
|  |   classify_counts(trace_bits, binary_mode ? | ||||||
|  |                   count_class_binary : count_class_human); | ||||||
|  | 
 | ||||||
|  |   if (!quiet_mode) | ||||||
|  |     SAYF(cRST "-- Program output ends --\n"); | ||||||
|  | 
 | ||||||
|  |   if (!child_timed_out && !stop_soon && WIFSIGNALED(status)) | ||||||
|  |     child_crashed = 1; | ||||||
|  | 
 | ||||||
|  |   if (!quiet_mode) { | ||||||
|  | 
 | ||||||
|  |     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)); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Handle Ctrl-C and the like. */ | ||||||
|  | 
 | ||||||
|  | static void handle_stop_sig(int sig) { | ||||||
|  | 
 | ||||||
|  |   stop_soon = 1; | ||||||
|  | 
 | ||||||
|  |   if (child_pid > 0) kill(child_pid, SIGKILL); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Do basic preparations - persistent fds, filenames, etc. */ | ||||||
|  | 
 | ||||||
|  | static void set_up_environment(void) { | ||||||
|  | 
 | ||||||
|  |   setenv("ASAN_OPTIONS", "abort_on_error=1:" | ||||||
|  |                          "detect_leaks=0:" | ||||||
|  |                          "symbolize=0:" | ||||||
|  |                          "allocator_may_return_null=1", 0); | ||||||
|  | 
 | ||||||
|  |   setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":" | ||||||
|  |                          "symbolize=0:" | ||||||
|  |                          "abort_on_error=1:" | ||||||
|  |                          "allocator_may_return_null=1:" | ||||||
|  |                          "msan_track_origins=0", 0); | ||||||
|  | 
 | ||||||
|  |   if (getenv("AFL_PRELOAD")) { | ||||||
|  |     setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); | ||||||
|  |     setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Setup signal handlers, duh. */ | ||||||
|  | 
 | ||||||
|  | static 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); | ||||||
|  | 
 | ||||||
|  |   /* Various ways of saying "stop". */ | ||||||
|  | 
 | ||||||
|  |   sa.sa_handler = handle_stop_sig; | ||||||
|  |   sigaction(SIGHUP, &sa, NULL); | ||||||
|  |   sigaction(SIGINT, &sa, NULL); | ||||||
|  |   sigaction(SIGTERM, &sa, NULL); | ||||||
|  | 
 | ||||||
|  |   /* Exec timeout notifications. */ | ||||||
|  | 
 | ||||||
|  |   sa.sa_handler = handle_timeout; | ||||||
|  |   sigaction(SIGALRM, &sa, NULL); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Detect @@ in args. */ | ||||||
|  | 
 | ||||||
|  | static void detect_file_args(char** argv) { | ||||||
|  | 
 | ||||||
|  |   u32 i = 0; | ||||||
|  |   u8* cwd = getcwd(NULL, 0); | ||||||
|  | 
 | ||||||
|  |   if (!cwd) PFATAL("getcwd() failed"); | ||||||
|  | 
 | ||||||
|  |   while (argv[i]) { | ||||||
|  | 
 | ||||||
|  |     u8* aa_loc = strstr(argv[i], "@@"); | ||||||
|  | 
 | ||||||
|  |     if (aa_loc) { | ||||||
|  | 
 | ||||||
|  |       u8 *aa_subst, *n_arg; | ||||||
|  | 
 | ||||||
|  |       if (!at_file) FATAL("@@ syntax is not supported by this tool."); | ||||||
|  | 
 | ||||||
|  |       /* Be sure that we're always using fully-qualified paths. */ | ||||||
|  | 
 | ||||||
|  |       if (at_file[0] == '/') aa_subst = at_file; | ||||||
|  |       else aa_subst = alloc_printf("%s/%s", cwd, at_file); | ||||||
|  | 
 | ||||||
|  |       /* Construct a replacement argv value. */ | ||||||
|  | 
 | ||||||
|  |       *aa_loc = 0; | ||||||
|  |       n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); | ||||||
|  |       argv[i] = n_arg; | ||||||
|  |       *aa_loc = '@'; | ||||||
|  | 
 | ||||||
|  |       if (at_file[0] != '/') ck_free(aa_subst); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     i++; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   free(cwd); /* not tracked */ | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Show banner. */ | ||||||
|  | 
 | ||||||
|  | static void show_banner(void) { | ||||||
|  | 
 | ||||||
|  |   SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Display usage hints. */ | ||||||
|  | 
 | ||||||
|  | static void usage(u8* argv0) { | ||||||
|  | 
 | ||||||
|  |   show_banner(); | ||||||
|  | 
 | ||||||
|  |   SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" | ||||||
|  | 
 | ||||||
|  |        "Required parameters:\n\n" | ||||||
|  | 
 | ||||||
|  |        "  -o file       - file to write the trace data to\n\n" | ||||||
|  | 
 | ||||||
|  |        "Execution control settings:\n\n" | ||||||
|  | 
 | ||||||
|  |        "  -t msec       - timeout for each run (none)\n" | ||||||
|  |        "  -m megs       - memory limit for child process (%u MB)\n" | ||||||
|  |        "  -Q            - use binary-only instrumentation (QEMU mode)\n\n" | ||||||
|  | 
 | ||||||
|  |        "Other settings:\n\n" | ||||||
|  | 
 | ||||||
|  |        "  -q            - sink program's output and don't show messages\n" | ||||||
|  |        "  -e            - show edge coverage only, ignore hit counts\n" | ||||||
|  |        "  -c            - allow core dumps\n" | ||||||
|  |        "  -V            - show version number and exit\n\n" | ||||||
|  | 
 | ||||||
|  |        "This tool displays raw tuple data captured by AFL instrumentation.\n" | ||||||
|  |        "For additional help, consult %s/README.\n\n" cRST, | ||||||
|  | 
 | ||||||
|  |        argv0, MEM_LIMIT, doc_path); | ||||||
|  | 
 | ||||||
|  |   exit(1); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Find binary. */ | ||||||
|  | 
 | ||||||
|  | static void find_binary(u8* fname) { | ||||||
|  | 
 | ||||||
|  |   u8* env_path = 0; | ||||||
|  |   struct stat st; | ||||||
|  | 
 | ||||||
|  |   if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { | ||||||
|  | 
 | ||||||
|  |     target_path = ck_strdup(fname); | ||||||
|  | 
 | ||||||
|  |     if (stat(target_path, &st) || !S_ISREG(st.st_mode) || | ||||||
|  |         !(st.st_mode & 0111) || st.st_size < 4) | ||||||
|  |       FATAL("Program '%s' not found or not executable", fname); | ||||||
|  | 
 | ||||||
|  |   } else { | ||||||
|  | 
 | ||||||
|  |     while (env_path) { | ||||||
|  | 
 | ||||||
|  |       u8 *cur_elem, *delim = strchr(env_path, ':'); | ||||||
|  | 
 | ||||||
|  |       if (delim) { | ||||||
|  | 
 | ||||||
|  |         cur_elem = ck_alloc(delim - env_path + 1); | ||||||
|  |         memcpy(cur_elem, env_path, delim - env_path); | ||||||
|  |         delim++; | ||||||
|  | 
 | ||||||
|  |       } else cur_elem = ck_strdup(env_path); | ||||||
|  | 
 | ||||||
|  |       env_path = delim; | ||||||
|  | 
 | ||||||
|  |       if (cur_elem[0]) | ||||||
|  |         target_path = alloc_printf("%s/%s", cur_elem, fname); | ||||||
|  |       else | ||||||
|  |         target_path = ck_strdup(fname); | ||||||
|  | 
 | ||||||
|  |       ck_free(cur_elem); | ||||||
|  | 
 | ||||||
|  |       if (!stat(target_path, &st) && S_ISREG(st.st_mode) && | ||||||
|  |           (st.st_mode & 0111) && st.st_size >= 4) break; | ||||||
|  | 
 | ||||||
|  |       ck_free(target_path); | ||||||
|  |       target_path = 0; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!target_path) FATAL("Program '%s' not found or not executable", 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; | ||||||
|  | 
 | ||||||
|  |   /* Workaround for a QEMU stability glitch. */ | ||||||
|  | 
 | ||||||
|  |   setenv("QEMU_LOG", "nochain", 1); | ||||||
|  | 
 | ||||||
|  |   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 */ | ||||||
|  | 
 | ||||||
|  | int main(int argc, char** argv) { | ||||||
|  | 
 | ||||||
|  |   s32 opt; | ||||||
|  |   u8  mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; | ||||||
|  |   u32 tcnt; | ||||||
|  |   char** use_argv; | ||||||
|  | 
 | ||||||
|  |   doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; | ||||||
|  | 
 | ||||||
|  |   while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbcV")) > 0) | ||||||
|  | 
 | ||||||
|  |     switch (opt) { | ||||||
|  | 
 | ||||||
|  |       case 'o': | ||||||
|  | 
 | ||||||
|  |         if (out_file) FATAL("Multiple -o options not supported"); | ||||||
|  |         out_file = optarg; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'm': { | ||||||
|  | 
 | ||||||
|  |           u8 suffix = 'M'; | ||||||
|  | 
 | ||||||
|  |           if (mem_limit_given) FATAL("Multiple -m options not supported"); | ||||||
|  |           mem_limit_given = 1; | ||||||
|  | 
 | ||||||
|  |           if (!strcmp(optarg, "none")) { | ||||||
|  | 
 | ||||||
|  |             mem_limit = 0; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || | ||||||
|  |               optarg[0] == '-') FATAL("Bad syntax used for -m"); | ||||||
|  | 
 | ||||||
|  |           switch (suffix) { | ||||||
|  | 
 | ||||||
|  |             case 'T': mem_limit *= 1024 * 1024; break; | ||||||
|  |             case 'G': mem_limit *= 1024; break; | ||||||
|  |             case 'k': mem_limit /= 1024; break; | ||||||
|  |             case 'M': break; | ||||||
|  | 
 | ||||||
|  |             default:  FATAL("Unsupported suffix or bad syntax for -m"); | ||||||
|  | 
 | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if (mem_limit < 5) FATAL("Dangerously low value of -m"); | ||||||
|  | 
 | ||||||
|  |           if (sizeof(rlim_t) == 4 && mem_limit > 2000) | ||||||
|  |             FATAL("Value of -m out of range on 32-bit systems"); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 't': | ||||||
|  | 
 | ||||||
|  |         if (timeout_given) FATAL("Multiple -t options not supported"); | ||||||
|  |         timeout_given = 1; | ||||||
|  | 
 | ||||||
|  |         if (strcmp(optarg, "none")) { | ||||||
|  |           exec_tmout = atoi(optarg); | ||||||
|  | 
 | ||||||
|  |           if (exec_tmout < 20 || optarg[0] == '-') | ||||||
|  |             FATAL("Dangerously low value of -t"); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'e': | ||||||
|  | 
 | ||||||
|  |         if (edges_only) FATAL("Multiple -e options not supported"); | ||||||
|  |         edges_only = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'q': | ||||||
|  | 
 | ||||||
|  |         if (quiet_mode) FATAL("Multiple -q options not supported"); | ||||||
|  |         quiet_mode = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'Z': | ||||||
|  | 
 | ||||||
|  |         /* This is an undocumented option to write data in the syntax expected
 | ||||||
|  |            by afl-cmin. Nobody else should have any use for this. */ | ||||||
|  | 
 | ||||||
|  |         cmin_mode  = 1; | ||||||
|  |         quiet_mode = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'A': | ||||||
|  | 
 | ||||||
|  |         /* Another afl-cmin specific feature. */ | ||||||
|  |         at_file = optarg; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'Q': | ||||||
|  | 
 | ||||||
|  |         if (qemu_mode) FATAL("Multiple -Q options not supported"); | ||||||
|  |         if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; | ||||||
|  | 
 | ||||||
|  |         qemu_mode = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'b': | ||||||
|  | 
 | ||||||
|  |         /* Secret undocumented mode. Writes output in raw binary format
 | ||||||
|  |            similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */ | ||||||
|  | 
 | ||||||
|  |         binary_mode = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'c': | ||||||
|  | 
 | ||||||
|  |         if (keep_cores) FATAL("Multiple -c options not supported"); | ||||||
|  |         keep_cores = 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |       case 'V': | ||||||
|  | 
 | ||||||
|  |         show_banner(); | ||||||
|  |         exit(0); | ||||||
|  | 
 | ||||||
|  |       default: | ||||||
|  | 
 | ||||||
|  |         usage(argv[0]); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   if (optind == argc || !out_file) usage(argv[0]); | ||||||
|  | 
 | ||||||
|  |   setup_shm(); | ||||||
|  |   setup_signal_handlers(); | ||||||
|  | 
 | ||||||
|  |   set_up_environment(); | ||||||
|  | 
 | ||||||
|  |   find_binary(argv[optind]); | ||||||
|  | 
 | ||||||
|  |   if (!quiet_mode) { | ||||||
|  |     show_banner(); | ||||||
|  |     ACTF("Executing '%s'...\n", target_path); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   detect_file_args(argv + optind); | ||||||
|  | 
 | ||||||
|  |   if (qemu_mode) | ||||||
|  |     use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); | ||||||
|  |   else | ||||||
|  |     use_argv = argv + optind; | ||||||
|  | 
 | ||||||
|  |   run_target(use_argv); | ||||||
|  | 
 | ||||||
|  |   tcnt = write_results(); | ||||||
|  | 
 | ||||||
|  |   if (!quiet_mode) { | ||||||
|  | 
 | ||||||
|  |     if (!tcnt) FATAL("No instrumentation detected" cRST); | ||||||
|  |     OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   exit(child_crashed * 2 + child_timed_out); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -0,0 +1,163 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | # | ||||||
|  | # american fuzzy lop - status check tool | ||||||
|  | # -------------------------------------- | ||||||
|  | # | ||||||
|  | # Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | # Copyright 2015 Google LLC All rights reserved. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | # you may not use this file except in compliance with the License. | ||||||
|  | # You may obtain a copy of the License at: | ||||||
|  | # | ||||||
|  | #   http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | # This tool summarizes the status of any locally-running synchronized | ||||||
|  | # instances of afl-fuzz. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | echo "status check tool for afl-fuzz by <lcamtuf@google.com>" | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | if [ "$1" = "-s" ]; then | ||||||
|  | 
 | ||||||
|  |   SUMMARY_ONLY=1 | ||||||
|  |   DIR="$2" | ||||||
|  | 
 | ||||||
|  | else | ||||||
|  | 
 | ||||||
|  |   unset SUMMARY_ONLY | ||||||
|  |   DIR="$1" | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | if [ "$DIR" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "Usage: $0 [ -s ] afl_sync_dir" 1>&2 | ||||||
|  |   echo 1>&2 | ||||||
|  |   echo "The -s option causes the tool to skip all the per-fuzzer trivia and show" 1>&2 | ||||||
|  |   echo "just the summary results. See docs/parallel_fuzzing.txt for additional tips." 1>&2 | ||||||
|  |   echo 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | cd "$DIR" || exit 1 | ||||||
|  | 
 | ||||||
|  | if [ -d queue ]; then | ||||||
|  | 
 | ||||||
|  |   echo "[-] Error: parameter is an individual output directory, not a sync dir." 1>&2 | ||||||
|  |   exit 1 | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | CUR_TIME=`date +%s` | ||||||
|  | 
 | ||||||
|  | TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1 | ||||||
|  | 
 | ||||||
|  | ALIVE_CNT=0 | ||||||
|  | DEAD_CNT=0 | ||||||
|  | 
 | ||||||
|  | TOTAL_TIME=0 | ||||||
|  | TOTAL_EXECS=0 | ||||||
|  | TOTAL_EPS=0 | ||||||
|  | TOTAL_CRASHES=0 | ||||||
|  | TOTAL_PFAV=0 | ||||||
|  | TOTAL_PENDING=0 | ||||||
|  | 
 | ||||||
|  | if [ "$SUMMARY_ONLY" = "" ]; then | ||||||
|  | 
 | ||||||
|  |   echo "Individual fuzzers" | ||||||
|  |   echo "==================" | ||||||
|  |   echo | ||||||
|  | 
 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do | ||||||
|  | 
 | ||||||
|  |   sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP" | ||||||
|  |   . "$TMP" | ||||||
|  | 
 | ||||||
|  |   RUN_UNIX=$((CUR_TIME - start_time)) | ||||||
|  |   RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24)) | ||||||
|  |   RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24)) | ||||||
|  | 
 | ||||||
|  |   if [ "$SUMMARY_ONLY" = "" ]; then | ||||||
|  | 
 | ||||||
|  |     echo ">>> $afl_banner ($RUN_DAYS days, $RUN_HRS hrs) <<<" | ||||||
|  |     echo | ||||||
|  | 
 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if ! kill -0 "$fuzzer_pid" 2>/dev/null; then | ||||||
|  | 
 | ||||||
|  |     if [ "$SUMMARY_ONLY" = "" ]; then | ||||||
|  | 
 | ||||||
|  |       echo "  Instance is dead or running remotely, skipping." | ||||||
|  |       echo | ||||||
|  | 
 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     DEAD_CNT=$((DEAD_CNT + 1)) | ||||||
|  |     continue | ||||||
|  | 
 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   ALIVE_CNT=$((ALIVE_CNT + 1)) | ||||||
|  | 
 | ||||||
|  |   EXEC_SEC=$((execs_done / RUN_UNIX)) | ||||||
|  |   PATH_PERC=$((cur_path * 100 / paths_total)) | ||||||
|  | 
 | ||||||
|  |   TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX)) | ||||||
|  |   TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC)) | ||||||
|  |   TOTAL_EXECS=$((TOTAL_EXECS + execs_done)) | ||||||
|  |   TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes)) | ||||||
|  |   TOTAL_PENDING=$((TOTAL_PENDING + pending_total)) | ||||||
|  |   TOTAL_PFAV=$((TOTAL_PFAV + pending_favs)) | ||||||
|  | 
 | ||||||
|  |   if [ "$SUMMARY_ONLY" = "" ]; then | ||||||
|  | 
 | ||||||
|  |     echo "  cycle $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, path $cur_path/$paths_total (${PATH_PERC}%)" | ||||||
|  | 
 | ||||||
|  |     if [ "$unique_crashes" = "0" ]; then | ||||||
|  |       echo "  pending $pending_favs/$pending_total, coverage $bitmap_cvg, no crashes yet" | ||||||
|  |     else | ||||||
|  |       echo "  pending $pending_favs/$pending_total, coverage $bitmap_cvg, crash count $unique_crashes (!)" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     echo | ||||||
|  | 
 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  | done | ||||||
|  | 
 | ||||||
|  | rm -f "$TMP" | ||||||
|  | 
 | ||||||
|  | TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24)) | ||||||
|  | TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24)) | ||||||
|  | 
 | ||||||
|  | test "$TOTAL_TIME" = "0" && TOTAL_TIME=1 | ||||||
|  | 
 | ||||||
|  | echo "Summary stats" | ||||||
|  | echo "=============" | ||||||
|  | echo | ||||||
|  | echo "       Fuzzers alive : $ALIVE_CNT" | ||||||
|  | 
 | ||||||
|  | if [ ! "$DEAD_CNT" = "0" ]; then | ||||||
|  |   echo "      Dead or remote : $DEAD_CNT (excluded from stats)" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | echo "      Total run time : $TOTAL_DAYS days, $TOTAL_HRS hours" | ||||||
|  | echo "         Total execs : $((TOTAL_EXECS / 1000 / 1000)) million" | ||||||
|  | echo "    Cumulative speed : $TOTAL_EPS execs/sec" | ||||||
|  | echo "       Pending paths : $TOTAL_PFAV faves, $TOTAL_PENDING total" | ||||||
|  | 
 | ||||||
|  | if [ "$ALIVE_CNT" -gt "1" ]; then | ||||||
|  |   echo "  Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | echo "       Crashes found : $TOTAL_CRASHES locally unique" | ||||||
|  | echo | ||||||
|  | 
 | ||||||
|  | exit 0 | ||||||
| @ -0,0 +1,577 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - error-checking, memory-zeroing alloc routines | ||||||
|  |    ------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | 
 | ||||||
|  |    This allocator is not designed to resist malicious attackers (the canaries | ||||||
|  |    are small and predictable), but provides a robust and portable way to detect | ||||||
|  |    use-after-free, off-by-one writes, stale pointers, and so on. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef _HAVE_ALLOC_INL_H | ||||||
|  | #define _HAVE_ALLOC_INL_H | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include "types.h" | ||||||
|  | #include "debug.h" | ||||||
|  | 
 | ||||||
|  | /* User-facing macro to sprintf() to a dynamically allocated buffer. */ | ||||||
|  | 
 | ||||||
|  | #define alloc_printf(_str...) ({ \ | ||||||
|  |     u8* _tmp; \ | ||||||
|  |     s32 _len = snprintf(NULL, 0, _str); \ | ||||||
|  |     if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ | ||||||
|  |     _tmp = ck_alloc(_len + 1); \ | ||||||
|  |     snprintf((char*)_tmp, _len + 1, _str); \ | ||||||
|  |     _tmp; \ | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  | /* Macro to enforce allocation limits as a last-resort defense against
 | ||||||
|  |    integer overflows. */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_CHECK_SIZE(_s) do { \ | ||||||
|  |     if ((_s) > MAX_ALLOC) \ | ||||||
|  |       ABORT("Bad alloc request: %u bytes", (_s)); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Macro to check malloc() failures and the like. */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_CHECK_RESULT(_r, _s) do { \ | ||||||
|  |     if (!(_r)) \ | ||||||
|  |       ABORT("Out of memory: can't allocate %u bytes", (_s)); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Magic tokens used to mark used / freed chunks. */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_MAGIC_C1  0xFF00FF00 /* Used head (dword)  */ | ||||||
|  | #define ALLOC_MAGIC_F   0xFE00FE00 /* Freed head (dword) */ | ||||||
|  | #define ALLOC_MAGIC_C2  0xF0       /* Used tail (byte)   */ | ||||||
|  | 
 | ||||||
|  | /* Positions of guard tokens in relation to the user-visible pointer. */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_C1(_ptr)  (((u32*)(_ptr))[-2]) | ||||||
|  | #define ALLOC_S(_ptr)   (((u32*)(_ptr))[-1]) | ||||||
|  | #define ALLOC_C2(_ptr)  (((u8*)(_ptr))[ALLOC_S(_ptr)]) | ||||||
|  | 
 | ||||||
|  | #define ALLOC_OFF_HEAD  8 | ||||||
|  | #define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) | ||||||
|  | 
 | ||||||
|  | /* Allocator increments for ck_realloc_block(). */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_BLK_INC    256 | ||||||
|  | 
 | ||||||
|  | /* Sanity-checking macros for pointers. */ | ||||||
|  | 
 | ||||||
|  | #define CHECK_PTR(_p) do { \ | ||||||
|  |     if (_p) { \ | ||||||
|  |       if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ | ||||||
|  |         if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ | ||||||
|  |           ABORT("Use after free."); \ | ||||||
|  |         else ABORT("Corrupted head alloc canary."); \ | ||||||
|  |       } \ | ||||||
|  |       if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ | ||||||
|  |         ABORT("Corrupted tail alloc canary."); \ | ||||||
|  |     } \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | #define CHECK_PTR_EXPR(_p) ({ \ | ||||||
|  |     typeof (_p) _tmp = (_p); \ | ||||||
|  |     CHECK_PTR(_tmp); \ | ||||||
|  |     _tmp; \ | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized
 | ||||||
|  |    requests. */ | ||||||
|  | 
 | ||||||
|  | static inline void* DFL_ck_alloc_nozero(u32 size) { | ||||||
|  | 
 | ||||||
|  |   void* ret; | ||||||
|  | 
 | ||||||
|  |   if (!size) return NULL; | ||||||
|  | 
 | ||||||
|  |   ALLOC_CHECK_SIZE(size); | ||||||
|  |   ret = malloc(size + ALLOC_OFF_TOTAL); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  | 
 | ||||||
|  |   ret += ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(ret) = ALLOC_MAGIC_C1; | ||||||
|  |   ALLOC_S(ret)  = size; | ||||||
|  |   ALLOC_C2(ret) = ALLOC_MAGIC_C2; | ||||||
|  | 
 | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Allocate a buffer, returning zeroed memory. */ | ||||||
|  | 
 | ||||||
|  | static inline void* DFL_ck_alloc(u32 size) { | ||||||
|  | 
 | ||||||
|  |   void* mem; | ||||||
|  | 
 | ||||||
|  |   if (!size) return NULL; | ||||||
|  |   mem = DFL_ck_alloc_nozero(size); | ||||||
|  | 
 | ||||||
|  |   return memset(mem, 0, size); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD
 | ||||||
|  |    is set, the old memory will be also clobbered with 0xFF. */ | ||||||
|  | 
 | ||||||
|  | static inline void DFL_ck_free(void* mem) { | ||||||
|  | 
 | ||||||
|  |   if (!mem) return; | ||||||
|  | 
 | ||||||
|  |   CHECK_PTR(mem); | ||||||
|  | 
 | ||||||
|  | #ifdef DEBUG_BUILD | ||||||
|  | 
 | ||||||
|  |   /* Catch pointer issues sooner. */ | ||||||
|  |   memset(mem, 0xFF, ALLOC_S(mem)); | ||||||
|  | 
 | ||||||
|  | #endif /* DEBUG_BUILD */ | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(mem) = ALLOC_MAGIC_F; | ||||||
|  | 
 | ||||||
|  |   free(mem - ALLOC_OFF_HEAD); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Re-allocate a buffer, checking for issues and zeroing any newly-added tail.
 | ||||||
|  |    With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the | ||||||
|  |    old memory is clobbered with 0xFF. */ | ||||||
|  | 
 | ||||||
|  | static inline void* DFL_ck_realloc(void* orig, u32 size) { | ||||||
|  | 
 | ||||||
|  |   void* ret; | ||||||
|  |   u32   old_size = 0; | ||||||
|  | 
 | ||||||
|  |   if (!size) { | ||||||
|  | 
 | ||||||
|  |     DFL_ck_free(orig); | ||||||
|  |     return NULL; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (orig) { | ||||||
|  | 
 | ||||||
|  |     CHECK_PTR(orig); | ||||||
|  | 
 | ||||||
|  | #ifndef DEBUG_BUILD | ||||||
|  |     ALLOC_C1(orig) = ALLOC_MAGIC_F; | ||||||
|  | #endif /* !DEBUG_BUILD */ | ||||||
|  | 
 | ||||||
|  |     old_size  = ALLOC_S(orig); | ||||||
|  |     orig     -= ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |     ALLOC_CHECK_SIZE(old_size); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ALLOC_CHECK_SIZE(size); | ||||||
|  | 
 | ||||||
|  | #ifndef DEBUG_BUILD | ||||||
|  | 
 | ||||||
|  |   ret = realloc(orig, size + ALLOC_OFF_TOTAL); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  |   /* Catch pointer issues sooner: force relocation and make sure that the
 | ||||||
|  |      original buffer is wiped. */ | ||||||
|  | 
 | ||||||
|  |   ret = malloc(size + ALLOC_OFF_TOTAL); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  | 
 | ||||||
|  |   if (orig) { | ||||||
|  | 
 | ||||||
|  |     memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); | ||||||
|  |     memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); | ||||||
|  | 
 | ||||||
|  |     ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; | ||||||
|  | 
 | ||||||
|  |     free(orig); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #endif /* ^!DEBUG_BUILD */ | ||||||
|  | 
 | ||||||
|  |   ret += ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(ret) = ALLOC_MAGIC_C1; | ||||||
|  |   ALLOC_S(ret)  = size; | ||||||
|  |   ALLOC_C2(ret) = ALLOC_MAGIC_C2; | ||||||
|  | 
 | ||||||
|  |   if (size > old_size) | ||||||
|  |     memset(ret + old_size, 0, size - old_size); | ||||||
|  | 
 | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up
 | ||||||
|  |    repeated small reallocs without complicating the user code). */ | ||||||
|  | 
 | ||||||
|  | static inline void* DFL_ck_realloc_block(void* orig, u32 size) { | ||||||
|  | 
 | ||||||
|  | #ifndef DEBUG_BUILD | ||||||
|  | 
 | ||||||
|  |   if (orig) { | ||||||
|  | 
 | ||||||
|  |     CHECK_PTR(orig); | ||||||
|  | 
 | ||||||
|  |     if (ALLOC_S(orig) >= size) return orig; | ||||||
|  | 
 | ||||||
|  |     size += ALLOC_BLK_INC; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #endif /* !DEBUG_BUILD */ | ||||||
|  | 
 | ||||||
|  |   return DFL_ck_realloc(orig, size); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ | ||||||
|  | 
 | ||||||
|  | static inline u8* DFL_ck_strdup(u8* str) { | ||||||
|  | 
 | ||||||
|  |   void* ret; | ||||||
|  |   u32   size; | ||||||
|  | 
 | ||||||
|  |   if (!str) return NULL; | ||||||
|  | 
 | ||||||
|  |   size = strlen((char*)str) + 1; | ||||||
|  | 
 | ||||||
|  |   ALLOC_CHECK_SIZE(size); | ||||||
|  |   ret = malloc(size + ALLOC_OFF_TOTAL); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  | 
 | ||||||
|  |   ret += ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(ret) = ALLOC_MAGIC_C1; | ||||||
|  |   ALLOC_S(ret)  = size; | ||||||
|  |   ALLOC_C2(ret) = ALLOC_MAGIC_C2; | ||||||
|  | 
 | ||||||
|  |   return memcpy(ret, str, size); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Create a buffer with a copy of a memory block. Returns NULL for zero-sized
 | ||||||
|  |    or NULL inputs. */ | ||||||
|  | 
 | ||||||
|  | static inline void* DFL_ck_memdup(void* mem, u32 size) { | ||||||
|  | 
 | ||||||
|  |   void* ret; | ||||||
|  | 
 | ||||||
|  |   if (!mem || !size) return NULL; | ||||||
|  | 
 | ||||||
|  |   ALLOC_CHECK_SIZE(size); | ||||||
|  |   ret = malloc(size + ALLOC_OFF_TOTAL); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  |    | ||||||
|  |   ret += ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(ret) = ALLOC_MAGIC_C1; | ||||||
|  |   ALLOC_S(ret)  = size; | ||||||
|  |   ALLOC_C2(ret) = ALLOC_MAGIC_C2; | ||||||
|  | 
 | ||||||
|  |   return memcpy(ret, mem, size); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Create a buffer with a block of text, appending a NUL terminator at the end.
 | ||||||
|  |    Returns NULL for zero-sized or NULL inputs. */ | ||||||
|  | 
 | ||||||
|  | static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { | ||||||
|  | 
 | ||||||
|  |   u8* ret; | ||||||
|  | 
 | ||||||
|  |   if (!mem || !size) return NULL; | ||||||
|  | 
 | ||||||
|  |   ALLOC_CHECK_SIZE(size); | ||||||
|  |   ret = malloc(size + ALLOC_OFF_TOTAL + 1); | ||||||
|  |   ALLOC_CHECK_RESULT(ret, size); | ||||||
|  |    | ||||||
|  |   ret += ALLOC_OFF_HEAD; | ||||||
|  | 
 | ||||||
|  |   ALLOC_C1(ret) = ALLOC_MAGIC_C1; | ||||||
|  |   ALLOC_S(ret)  = size; | ||||||
|  |   ALLOC_C2(ret) = ALLOC_MAGIC_C2; | ||||||
|  | 
 | ||||||
|  |   memcpy(ret, mem, size); | ||||||
|  |   ret[size] = 0; | ||||||
|  | 
 | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifndef DEBUG_BUILD | ||||||
|  | 
 | ||||||
|  | /* In non-debug mode, we just do straightforward aliasing of the above functions
 | ||||||
|  |    to user-visible names such as ck_alloc(). */ | ||||||
|  | 
 | ||||||
|  | #define ck_alloc          DFL_ck_alloc | ||||||
|  | #define ck_alloc_nozero   DFL_ck_alloc_nozero | ||||||
|  | #define ck_realloc        DFL_ck_realloc | ||||||
|  | #define ck_realloc_block  DFL_ck_realloc_block | ||||||
|  | #define ck_strdup         DFL_ck_strdup | ||||||
|  | #define ck_memdup         DFL_ck_memdup | ||||||
|  | #define ck_memdup_str     DFL_ck_memdup_str | ||||||
|  | #define ck_free           DFL_ck_free | ||||||
|  | 
 | ||||||
|  | #define alloc_report() | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | /* In debugging mode, we also track allocations to detect memory leaks, and the
 | ||||||
|  |    flow goes through one more layer of indirection. */ | ||||||
|  | 
 | ||||||
|  | /* Alloc tracking data structures: */ | ||||||
|  | 
 | ||||||
|  | #define ALLOC_BUCKETS     4096 | ||||||
|  | 
 | ||||||
|  | struct TRK_obj { | ||||||
|  |   void *ptr; | ||||||
|  |   char *file, *func; | ||||||
|  |   u32  line; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #ifdef AFL_MAIN | ||||||
|  | 
 | ||||||
|  | struct TRK_obj* TRK[ALLOC_BUCKETS]; | ||||||
|  | u32 TRK_cnt[ALLOC_BUCKETS]; | ||||||
|  | 
 | ||||||
|  | #  define alloc_report() TRK_report() | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | extern struct TRK_obj* TRK[ALLOC_BUCKETS]; | ||||||
|  | extern u32 TRK_cnt[ALLOC_BUCKETS]; | ||||||
|  | 
 | ||||||
|  | #  define alloc_report() | ||||||
|  | 
 | ||||||
|  | #endif /* ^AFL_MAIN */ | ||||||
|  | 
 | ||||||
|  | /* Bucket-assigning function for a given pointer: */ | ||||||
|  | 
 | ||||||
|  | #define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Add a new entry to the list of allocated objects. */ | ||||||
|  | 
 | ||||||
|  | static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, | ||||||
|  |                                  u32 line) { | ||||||
|  | 
 | ||||||
|  |   u32 i, bucket; | ||||||
|  | 
 | ||||||
|  |   if (!ptr) return; | ||||||
|  | 
 | ||||||
|  |   bucket = TRKH(ptr); | ||||||
|  | 
 | ||||||
|  |   /* Find a free slot in the list of entries for that bucket. */ | ||||||
|  | 
 | ||||||
|  |   for (i = 0; i < TRK_cnt[bucket]; i++) | ||||||
|  | 
 | ||||||
|  |     if (!TRK[bucket][i].ptr) { | ||||||
|  | 
 | ||||||
|  |       TRK[bucket][i].ptr  = ptr; | ||||||
|  |       TRK[bucket][i].file = (char*)file; | ||||||
|  |       TRK[bucket][i].func = (char*)func; | ||||||
|  |       TRK[bucket][i].line = line; | ||||||
|  |       return; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   /* No space available - allocate more. */ | ||||||
|  | 
 | ||||||
|  |   TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], | ||||||
|  |     (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); | ||||||
|  | 
 | ||||||
|  |   TRK[bucket][i].ptr  = ptr; | ||||||
|  |   TRK[bucket][i].file = (char*)file; | ||||||
|  |   TRK[bucket][i].func = (char*)func; | ||||||
|  |   TRK[bucket][i].line = line; | ||||||
|  | 
 | ||||||
|  |   TRK_cnt[bucket]++; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Remove entry from the list of allocated objects. */ | ||||||
|  | 
 | ||||||
|  | static inline void TRK_free_buf(void* ptr, const char* file, const char* func, | ||||||
|  |                                 u32 line) { | ||||||
|  | 
 | ||||||
|  |   u32 i, bucket; | ||||||
|  | 
 | ||||||
|  |   if (!ptr) return; | ||||||
|  | 
 | ||||||
|  |   bucket = TRKH(ptr); | ||||||
|  | 
 | ||||||
|  |   /* Find the element on the list... */ | ||||||
|  | 
 | ||||||
|  |   for (i = 0; i < TRK_cnt[bucket]; i++) | ||||||
|  | 
 | ||||||
|  |     if (TRK[bucket][i].ptr == ptr) { | ||||||
|  | 
 | ||||||
|  |       TRK[bucket][i].ptr = 0; | ||||||
|  |       return; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", | ||||||
|  |         func, file, line); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Do a final report on all non-deallocated objects. */ | ||||||
|  | 
 | ||||||
|  | static inline void TRK_report(void) { | ||||||
|  | 
 | ||||||
|  |   u32 i, bucket; | ||||||
|  | 
 | ||||||
|  |   fflush(0); | ||||||
|  | 
 | ||||||
|  |   for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) | ||||||
|  |     for (i = 0; i < TRK_cnt[bucket]; i++) | ||||||
|  |       if (TRK[bucket][i].ptr) | ||||||
|  |         WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", | ||||||
|  |               TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Simple wrappers for non-debugging functions: */ | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, | ||||||
|  |                                  u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_alloc(size); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, | ||||||
|  |                                    const char* func, u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_realloc(orig, size); | ||||||
|  |   TRK_free_buf(orig, file, func, line); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, | ||||||
|  |                                          const char* func, u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_realloc_block(orig, size); | ||||||
|  |   TRK_free_buf(orig, file, func, line); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, | ||||||
|  |                                   u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_strdup(str); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, | ||||||
|  |                                   const char* func, u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_memdup(mem, size); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, | ||||||
|  |                                       const char* func, u32 line) { | ||||||
|  | 
 | ||||||
|  |   void* ret = DFL_ck_memdup_str(mem, size); | ||||||
|  |   TRK_alloc_buf(ret, file, func, line); | ||||||
|  |   return ret; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void TRK_ck_free(void* ptr, const char* file, | ||||||
|  |                                 const char* func, u32 line) { | ||||||
|  | 
 | ||||||
|  |   TRK_free_buf(ptr, file, func, line); | ||||||
|  |   DFL_ck_free(ptr); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Aliasing user-facing names to tracking functions: */ | ||||||
|  | 
 | ||||||
|  | #define ck_alloc(_p1) \ | ||||||
|  |   TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_alloc_nozero(_p1) \ | ||||||
|  |   TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_realloc(_p1, _p2) \ | ||||||
|  |   TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_realloc_block(_p1, _p2) \ | ||||||
|  |   TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_strdup(_p1) \ | ||||||
|  |   TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_memdup(_p1, _p2) \ | ||||||
|  |   TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_memdup_str(_p1, _p2) \ | ||||||
|  |   TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #define ck_free(_p1) \ | ||||||
|  |   TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) | ||||||
|  | 
 | ||||||
|  | #endif /* ^!DEBUG_BUILD */ | ||||||
|  | 
 | ||||||
|  | #endif /* ! _HAVE_ALLOC_INL_H */ | ||||||
| @ -0,0 +1,82 @@ | |||||||
|  | #ifdef __ANDROID__ | ||||||
|  | #ifndef _ANDROID_ASHMEM_H | ||||||
|  | #define _ANDROID_ASHMEM_H | ||||||
|  | 
 | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <linux/ashmem.h> | ||||||
|  | #include <linux/shm.h> | ||||||
|  | #include <sys/ioctl.h> | ||||||
|  | #include <sys/mman.h> | ||||||
|  | 
 | ||||||
|  | #if __ANDROID_API__ >= 26 | ||||||
|  | #define shmat bionic_shmat | ||||||
|  | #define shmctl bionic_shmctl | ||||||
|  | #define shmdt bionic_shmdt | ||||||
|  | #define shmget bionic_shmget | ||||||
|  | #endif | ||||||
|  | #include <sys/shm.h> | ||||||
|  | #undef shmat | ||||||
|  | #undef shmctl | ||||||
|  | #undef shmdt | ||||||
|  | #undef shmget | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | #define ASHMEM_DEVICE "/dev/ashmem" | ||||||
|  | 
 | ||||||
|  | static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { | ||||||
|  |   int ret = 0; | ||||||
|  |   if (__cmd == IPC_RMID) { | ||||||
|  |     int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); | ||||||
|  |     struct ashmem_pin pin = {0, length}; | ||||||
|  |     ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); | ||||||
|  |     close(__shmid); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int shmget(key_t __key, size_t __size, int __shmflg) { | ||||||
|  |   (void) __shmflg; | ||||||
|  |   int fd, ret; | ||||||
|  |   char ourkey[11]; | ||||||
|  | 
 | ||||||
|  |   fd = open(ASHMEM_DEVICE, O_RDWR); | ||||||
|  |   if (fd < 0) | ||||||
|  |     return fd; | ||||||
|  | 
 | ||||||
|  |   sprintf(ourkey, "%d", __key); | ||||||
|  |   ret = ioctl(fd, ASHMEM_SET_NAME, ourkey); | ||||||
|  |   if (ret < 0) | ||||||
|  |     goto error; | ||||||
|  | 
 | ||||||
|  |   ret = ioctl(fd, ASHMEM_SET_SIZE, __size); | ||||||
|  |   if (ret < 0) | ||||||
|  |     goto error; | ||||||
|  | 
 | ||||||
|  |   return fd; | ||||||
|  | 
 | ||||||
|  | error: | ||||||
|  |   close(fd); | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { | ||||||
|  |   (void) __shmflg; | ||||||
|  |   int size; | ||||||
|  |   void *ptr; | ||||||
|  | 
 | ||||||
|  |   size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); | ||||||
|  |   if (size < 0) { | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0); | ||||||
|  |   if (ptr == MAP_FAILED) { | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* !_ANDROID_ASHMEM_H */ | ||||||
|  | #endif /* !__ANDROID__ */ | ||||||
| @ -0,0 +1,362 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - vaguely configurable bits | ||||||
|  |    ---------------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef _HAVE_CONFIG_H | ||||||
|  | #define _HAVE_CONFIG_H | ||||||
|  | 
 | ||||||
|  | #include "types.h" | ||||||
|  | 
 | ||||||
|  | /* Version string: */ | ||||||
|  | 
 | ||||||
|  | #define VERSION             "2.57b" | ||||||
|  | 
 | ||||||
|  | /******************************************************
 | ||||||
|  |  *                                                    * | ||||||
|  |  *  Settings that may be of interest to power users:  * | ||||||
|  |  *                                                    * | ||||||
|  |  ******************************************************/ | ||||||
|  | 
 | ||||||
|  | /* Comment out to disable terminal colors (note that this makes afl-analyze
 | ||||||
|  |    a lot less nice): */ | ||||||
|  | 
 | ||||||
|  | #define USE_COLOR | ||||||
|  | 
 | ||||||
|  | /* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ | ||||||
|  | 
 | ||||||
|  | #define FANCY_BOXES | ||||||
|  | 
 | ||||||
|  | /* Default timeout for fuzzed code (milliseconds). This is the upper bound,
 | ||||||
|  |    also used for detecting hangs; the actual value is auto-scaled: */ | ||||||
|  | 
 | ||||||
|  | #define EXEC_TIMEOUT        1000 | ||||||
|  | 
 | ||||||
|  | /* Timeout rounding factor when auto-scaling (milliseconds): */ | ||||||
|  | 
 | ||||||
|  | #define EXEC_TM_ROUND       20 | ||||||
|  | 
 | ||||||
|  | /* 64bit arch MACRO */ | ||||||
|  | #if (defined (__x86_64__) || defined (__arm64__) || defined (__aarch64__)) | ||||||
|  | #define WORD_SIZE_64 1 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /* Default memory limit for child process (MB): */ | ||||||
|  | 
 | ||||||
|  | #ifndef WORD_SIZE_64 | ||||||
|  | #  define MEM_LIMIT         25 | ||||||
|  | #else | ||||||
|  | #  define MEM_LIMIT         50 | ||||||
|  | #endif /* ^!WORD_SIZE_64 */ | ||||||
|  | 
 | ||||||
|  | /* Default memory limit when running in QEMU mode (MB): */ | ||||||
|  | 
 | ||||||
|  | #define MEM_LIMIT_QEMU      200 | ||||||
|  | 
 | ||||||
|  | /* Number of calibration cycles per every new test case (and for test
 | ||||||
|  |    cases that show variable behavior): */ | ||||||
|  | 
 | ||||||
|  | #define CAL_CYCLES          8 | ||||||
|  | #define CAL_CYCLES_LONG     40 | ||||||
|  | 
 | ||||||
|  | /* Number of subsequent timeouts before abandoning an input file: */ | ||||||
|  | 
 | ||||||
|  | #define TMOUT_LIMIT         250 | ||||||
|  | 
 | ||||||
|  | /* Maximum number of unique hangs or crashes to record: */ | ||||||
|  | 
 | ||||||
|  | #define KEEP_UNIQUE_HANG    500 | ||||||
|  | #define KEEP_UNIQUE_CRASH   5000 | ||||||
|  | 
 | ||||||
|  | /* Baseline number of random tweaks during a single 'havoc' stage: */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_CYCLES        256 | ||||||
|  | #define HAVOC_CYCLES_INIT   1024 | ||||||
|  | 
 | ||||||
|  | /* Maximum multiplier for the above (should be a power of two, beware
 | ||||||
|  |    of 32-bit int overflows): */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_MAX_MULT      16 | ||||||
|  | 
 | ||||||
|  | /* Absolute minimum number of havoc cycles (after all adjustments): */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_MIN           16 | ||||||
|  | 
 | ||||||
|  | /* Maximum stacking for havoc-stage tweaks. The actual value is calculated
 | ||||||
|  |    like this:  | ||||||
|  | 
 | ||||||
|  |    n = random between 1 and HAVOC_STACK_POW2 | ||||||
|  |    stacking = 2^n | ||||||
|  | 
 | ||||||
|  |    In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or | ||||||
|  |    128 stacked tweaks: */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_STACK_POW2    7 | ||||||
|  | 
 | ||||||
|  | /* Caps on block sizes for cloning and deletion operations. Each of these
 | ||||||
|  |    ranges has a 33% probability of getting picked, except for the first | ||||||
|  |    two cycles where smaller blocks are favored: */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_BLK_SMALL     32 | ||||||
|  | #define HAVOC_BLK_MEDIUM    128 | ||||||
|  | #define HAVOC_BLK_LARGE     1500 | ||||||
|  | 
 | ||||||
|  | /* Extra-large blocks, selected very rarely (<5% of the time): */ | ||||||
|  | 
 | ||||||
|  | #define HAVOC_BLK_XL        32768 | ||||||
|  | 
 | ||||||
|  | /* Probabilities of skipping non-favored entries in the queue, expressed as
 | ||||||
|  |    percentages: */ | ||||||
|  | 
 | ||||||
|  | #define SKIP_TO_NEW_PROB    99 /* ...when there are new, pending favorites */ | ||||||
|  | #define SKIP_NFAV_OLD_PROB  95 /* ...no new favs, cur entry already fuzzed */ | ||||||
|  | #define SKIP_NFAV_NEW_PROB  75 /* ...no new favs, cur entry not fuzzed yet */ | ||||||
|  | 
 | ||||||
|  | /* Splicing cycle count: */ | ||||||
|  | 
 | ||||||
|  | #define SPLICE_CYCLES       15 | ||||||
|  | 
 | ||||||
|  | /* Nominal per-splice havoc cycle length: */ | ||||||
|  | 
 | ||||||
|  | #define SPLICE_HAVOC        32 | ||||||
|  | 
 | ||||||
|  | /* Maximum offset for integer addition / subtraction stages: */ | ||||||
|  | 
 | ||||||
|  | #define ARITH_MAX           35 | ||||||
|  | 
 | ||||||
|  | /* Limits for the test case trimmer. The absolute minimum chunk size; and
 | ||||||
|  |    the starting and ending divisors for chopping up the input file: */ | ||||||
|  | 
 | ||||||
|  | #define TRIM_MIN_BYTES      4 | ||||||
|  | #define TRIM_START_STEPS    16 | ||||||
|  | #define TRIM_END_STEPS      1024 | ||||||
|  | 
 | ||||||
|  | /* Maximum size of input file, in bytes (keep under 100MB): */ | ||||||
|  | 
 | ||||||
|  | #define MAX_FILE            (1 * 1024 * 1024) | ||||||
|  | 
 | ||||||
|  | /* The same, for the test case minimizer: */ | ||||||
|  | 
 | ||||||
|  | #define TMIN_MAX_FILE       (10 * 1024 * 1024) | ||||||
|  | 
 | ||||||
|  | /* Block normalization steps for afl-tmin: */ | ||||||
|  | 
 | ||||||
|  | #define TMIN_SET_MIN_SIZE   4 | ||||||
|  | #define TMIN_SET_STEPS      128 | ||||||
|  | 
 | ||||||
|  | /* Maximum dictionary token size (-x), in bytes: */ | ||||||
|  | 
 | ||||||
|  | #define MAX_DICT_FILE       128 | ||||||
|  | 
 | ||||||
|  | /* Length limits for auto-detected dictionary tokens: */ | ||||||
|  | 
 | ||||||
|  | #define MIN_AUTO_EXTRA      3 | ||||||
|  | #define MAX_AUTO_EXTRA      32 | ||||||
|  | 
 | ||||||
|  | /* Maximum number of user-specified dictionary tokens to use in deterministic
 | ||||||
|  |    steps; past this point, the "extras/user" step will be still carried out, | ||||||
|  |    but with proportionally lower odds: */ | ||||||
|  | 
 | ||||||
|  | #define MAX_DET_EXTRAS      200 | ||||||
|  | 
 | ||||||
|  | /* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing
 | ||||||
|  |    (first value), and to keep in memory as candidates. The latter should be much | ||||||
|  |    higher than the former. */ | ||||||
|  | 
 | ||||||
|  | #define USE_AUTO_EXTRAS     50 | ||||||
|  | #define MAX_AUTO_EXTRAS     (USE_AUTO_EXTRAS * 10) | ||||||
|  | 
 | ||||||
|  | /* Scaling factor for the effector map used to skip some of the more
 | ||||||
|  |    expensive deterministic steps. The actual divisor is set to | ||||||
|  |    2^EFF_MAP_SCALE2 bytes: */ | ||||||
|  | 
 | ||||||
|  | #define EFF_MAP_SCALE2      3 | ||||||
|  | 
 | ||||||
|  | /* Minimum input file length at which the effector logic kicks in: */ | ||||||
|  | 
 | ||||||
|  | #define EFF_MIN_LEN         128 | ||||||
|  | 
 | ||||||
|  | /* Maximum effector density past which everything is just fuzzed
 | ||||||
|  |    unconditionally (%): */ | ||||||
|  | 
 | ||||||
|  | #define EFF_MAX_PERC        90 | ||||||
|  | 
 | ||||||
|  | /* UI refresh frequency (Hz): */ | ||||||
|  | 
 | ||||||
|  | #define UI_TARGET_HZ        5 | ||||||
|  | 
 | ||||||
|  | /* Fuzzer stats file and plot update intervals (sec): */ | ||||||
|  | 
 | ||||||
|  | #define STATS_UPDATE_SEC    60 | ||||||
|  | #define PLOT_UPDATE_SEC     5 | ||||||
|  | 
 | ||||||
|  | /* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ | ||||||
|  | 
 | ||||||
|  | #define AVG_SMOOTHING       16 | ||||||
|  | 
 | ||||||
|  | /* Sync interval (every n havoc cycles): */ | ||||||
|  | 
 | ||||||
|  | #define SYNC_INTERVAL       5 | ||||||
|  | 
 | ||||||
|  | /* Output directory reuse grace period (minutes): */ | ||||||
|  | 
 | ||||||
|  | #define OUTPUT_GRACE        25 | ||||||
|  | 
 | ||||||
|  | /* Uncomment to use simple file names (id_NNNNNN): */ | ||||||
|  | 
 | ||||||
|  | // #define SIMPLE_FILES
 | ||||||
|  | 
 | ||||||
|  | /* List of interesting values to use in fuzzing. */ | ||||||
|  | 
 | ||||||
|  | #define INTERESTING_8 \ | ||||||
|  |   -128,          /* Overflow signed 8-bit when decremented  */ \ | ||||||
|  |   -1,            /*                                         */ \ | ||||||
|  |    0,            /*                                         */ \ | ||||||
|  |    1,            /*                                         */ \ | ||||||
|  |    16,           /* One-off with common buffer size         */ \ | ||||||
|  |    32,           /* One-off with common buffer size         */ \ | ||||||
|  |    64,           /* One-off with common buffer size         */ \ | ||||||
|  |    100,          /* One-off with common buffer size         */ \ | ||||||
|  |    127           /* Overflow signed 8-bit when incremented  */ | ||||||
|  | 
 | ||||||
|  | #define INTERESTING_16 \ | ||||||
|  |   -32768,        /* Overflow signed 16-bit when decremented */ \ | ||||||
|  |   -129,          /* Overflow signed 8-bit                   */ \ | ||||||
|  |    128,          /* Overflow signed 8-bit                   */ \ | ||||||
|  |    255,          /* Overflow unsig 8-bit when incremented   */ \ | ||||||
|  |    256,          /* Overflow unsig 8-bit                    */ \ | ||||||
|  |    512,          /* One-off with common buffer size         */ \ | ||||||
|  |    1000,         /* One-off with common buffer size         */ \ | ||||||
|  |    1024,         /* One-off with common buffer size         */ \ | ||||||
|  |    4096,         /* One-off with common buffer size         */ \ | ||||||
|  |    32767         /* Overflow signed 16-bit when incremented */ | ||||||
|  | 
 | ||||||
|  | #define INTERESTING_32 \ | ||||||
|  |   -2147483648LL, /* Overflow signed 32-bit when decremented */ \ | ||||||
|  |   -100663046,    /* Large negative number (endian-agnostic) */ \ | ||||||
|  |   -32769,        /* Overflow signed 16-bit                  */ \ | ||||||
|  |    32768,        /* Overflow signed 16-bit                  */ \ | ||||||
|  |    65535,        /* Overflow unsig 16-bit when incremented  */ \ | ||||||
|  |    65536,        /* Overflow unsig 16 bit                   */ \ | ||||||
|  |    100663045,    /* Large positive number (endian-agnostic) */ \ | ||||||
|  |    2147483647    /* Overflow signed 32-bit when incremented */ | ||||||
|  | 
 | ||||||
|  | /***********************************************************
 | ||||||
|  |  *                                                         * | ||||||
|  |  *  Really exotic stuff you probably don't want to touch:  * | ||||||
|  |  *                                                         * | ||||||
|  |  ***********************************************************/ | ||||||
|  | 
 | ||||||
|  | /* Call count interval between reseeding the libc PRNG from /dev/urandom: */ | ||||||
|  | 
 | ||||||
|  | #define RESEED_RNG          10000 | ||||||
|  | 
 | ||||||
|  | /* Maximum line length passed from GCC to 'as' and used for parsing
 | ||||||
|  |    configuration files: */ | ||||||
|  | 
 | ||||||
|  | #define MAX_LINE            8192 | ||||||
|  | 
 | ||||||
|  | /* Environment variable used to pass SHM ID to the called program. */ | ||||||
|  | 
 | ||||||
|  | #define SHM_ENV_VAR         "__AFL_SHM_ID" | ||||||
|  | 
 | ||||||
|  | /* Other less interesting, internal-only variables. */ | ||||||
|  | 
 | ||||||
|  | #define CLANG_ENV_VAR       "__AFL_CLANG_MODE" | ||||||
|  | #define AS_LOOP_ENV_VAR     "__AFL_AS_LOOPCHECK" | ||||||
|  | #define PERSIST_ENV_VAR     "__AFL_PERSISTENT" | ||||||
|  | #define DEFER_ENV_VAR       "__AFL_DEFER_FORKSRV" | ||||||
|  | 
 | ||||||
|  | /* In-code signatures for deferred and persistent mode. */ | ||||||
|  | 
 | ||||||
|  | #define PERSIST_SIG         "##SIG_AFL_PERSISTENT##" | ||||||
|  | #define DEFER_SIG           "##SIG_AFL_DEFER_FORKSRV##" | ||||||
|  | 
 | ||||||
|  | /* Distinctive bitmap signature used to indicate failed execution: */ | ||||||
|  | 
 | ||||||
|  | #define EXEC_FAIL_SIG       0xfee1dead | ||||||
|  | 
 | ||||||
|  | /* Distinctive exit code used to indicate MSAN trip condition: */ | ||||||
|  | 
 | ||||||
|  | #define MSAN_ERROR          86 | ||||||
|  | 
 | ||||||
|  | /* Designated file descriptors for forkserver commands (the application will
 | ||||||
|  |    use FORKSRV_FD and FORKSRV_FD + 1): */ | ||||||
|  | 
 | ||||||
|  | #define FORKSRV_FD          198 | ||||||
|  | 
 | ||||||
|  | /* Fork server init timeout multiplier: we'll wait the user-selected
 | ||||||
|  |    timeout plus this much for the fork server to spin up. */ | ||||||
|  | 
 | ||||||
|  | #define FORK_WAIT_MULT      10 | ||||||
|  | 
 | ||||||
|  | /* Calibration timeout adjustments, to be a bit more generous when resuming
 | ||||||
|  |    fuzzing sessions or trying to calibrate already-added internal finds. | ||||||
|  |    The first value is a percentage, the other is in milliseconds: */ | ||||||
|  | 
 | ||||||
|  | #define CAL_TMOUT_PERC      125 | ||||||
|  | #define CAL_TMOUT_ADD       50 | ||||||
|  | 
 | ||||||
|  | /* Number of chances to calibrate a case before giving up: */ | ||||||
|  | 
 | ||||||
|  | #define CAL_CHANCES         3 | ||||||
|  | 
 | ||||||
|  | /* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than
 | ||||||
|  |    2; you probably want to keep it under 18 or so for performance reasons | ||||||
|  |    (adjusting AFL_INST_RATIO when compiling is probably a better way to solve | ||||||
|  |    problems with complex programs). You need to recompile the target binary | ||||||
|  |    after changing this - otherwise, SEGVs may ensue. */ | ||||||
|  | 
 | ||||||
|  | #define MAP_SIZE_POW2       16 | ||||||
|  | #define MAP_SIZE            (1 << MAP_SIZE_POW2) | ||||||
|  | 
 | ||||||
|  | /* Maximum allocator request size (keep well under INT_MAX): */ | ||||||
|  | 
 | ||||||
|  | #define MAX_ALLOC           0x40000000 | ||||||
|  | 
 | ||||||
|  | /* A made-up hashing seed: */ | ||||||
|  | 
 | ||||||
|  | #define HASH_CONST          0xa5b35705 | ||||||
|  | 
 | ||||||
|  | /* Constants for afl-gotcpu to control busy loop timing: */ | ||||||
|  | 
 | ||||||
|  | #define  CTEST_TARGET_MS    5000 | ||||||
|  | #define  CTEST_CORE_TRG_MS  1000 | ||||||
|  | #define  CTEST_BUSY_CYCLES  (10 * 1000 * 1000) | ||||||
|  | 
 | ||||||
|  | /* Uncomment this to use inferior block-coverage-based instrumentation. Note
 | ||||||
|  |    that you need to recompile the target binary for this to have any effect: */ | ||||||
|  | 
 | ||||||
|  | // #define COVERAGE_ONLY
 | ||||||
|  | 
 | ||||||
|  | /* Uncomment this to ignore hit counts and output just one bit per tuple.
 | ||||||
|  |    As with the previous setting, you will need to recompile the target | ||||||
|  |    binary: */ | ||||||
|  | 
 | ||||||
|  | // #define SKIP_COUNTS
 | ||||||
|  | 
 | ||||||
|  | /* Uncomment this to use instrumentation data to record newly discovered paths,
 | ||||||
|  |    but do not use them as seeds for fuzzing. This is useful for conveniently | ||||||
|  |    measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ | ||||||
|  | 
 | ||||||
|  | // #define IGNORE_FINDS
 | ||||||
|  | 
 | ||||||
|  | #endif /* ! _HAVE_CONFIG_H */ | ||||||
| @ -0,0 +1,258 @@ | |||||||
|  | /*
 | ||||||
|  |   Copyright 2013 Google LLC All rights reserved. | ||||||
|  | 
 | ||||||
|  |   Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |   you may not use this file except in compliance with the License. | ||||||
|  |   You may obtain a copy of the License at: | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  |   Unless required by applicable law or agreed to in writing, software | ||||||
|  |   distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |   See the License for the specific language governing permissions and | ||||||
|  |   limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    american fuzzy lop - debug / error handling macros | ||||||
|  |    -------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |    Written and maintained by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef _HAVE_DEBUG_H | ||||||
|  | #define _HAVE_DEBUG_H | ||||||
|  | 
 | ||||||
|  | #include <errno.h> | ||||||
|  | 
 | ||||||
|  | #include "types.h" | ||||||
|  | #include "config.h" | ||||||
|  | 
 | ||||||
|  | /*******************
 | ||||||
|  |  * Terminal colors * | ||||||
|  |  *******************/ | ||||||
|  | 
 | ||||||
|  | #ifdef USE_COLOR | ||||||
|  | 
 | ||||||
|  | #  define cBLK "\x1b[0;30m" | ||||||
|  | #  define cRED "\x1b[0;31m" | ||||||
|  | #  define cGRN "\x1b[0;32m" | ||||||
|  | #  define cBRN "\x1b[0;33m" | ||||||
|  | #  define cBLU "\x1b[0;34m" | ||||||
|  | #  define cMGN "\x1b[0;35m" | ||||||
|  | #  define cCYA "\x1b[0;36m" | ||||||
|  | #  define cLGR "\x1b[0;37m" | ||||||
|  | #  define cGRA "\x1b[1;90m" | ||||||
|  | #  define cLRD "\x1b[1;91m" | ||||||
|  | #  define cLGN "\x1b[1;92m" | ||||||
|  | #  define cYEL "\x1b[1;93m" | ||||||
|  | #  define cLBL "\x1b[1;94m" | ||||||
|  | #  define cPIN "\x1b[1;95m" | ||||||
|  | #  define cLCY "\x1b[1;96m" | ||||||
|  | #  define cBRI "\x1b[1;97m" | ||||||
|  | #  define cRST "\x1b[0m" | ||||||
|  | 
 | ||||||
|  | #  define bgBLK "\x1b[40m" | ||||||
|  | #  define bgRED "\x1b[41m" | ||||||
|  | #  define bgGRN "\x1b[42m" | ||||||
|  | #  define bgBRN "\x1b[43m" | ||||||
|  | #  define bgBLU "\x1b[44m" | ||||||
|  | #  define bgMGN "\x1b[45m" | ||||||
|  | #  define bgCYA "\x1b[46m" | ||||||
|  | #  define bgLGR "\x1b[47m" | ||||||
|  | #  define bgGRA "\x1b[100m" | ||||||
|  | #  define bgLRD "\x1b[101m" | ||||||
|  | #  define bgLGN "\x1b[102m" | ||||||
|  | #  define bgYEL "\x1b[103m" | ||||||
|  | #  define bgLBL "\x1b[104m" | ||||||
|  | #  define bgPIN "\x1b[105m" | ||||||
|  | #  define bgLCY "\x1b[106m" | ||||||
|  | #  define bgBRI "\x1b[107m" | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | #  define cBLK "" | ||||||
|  | #  define cRED "" | ||||||
|  | #  define cGRN "" | ||||||
|  | #  define cBRN "" | ||||||
|  | #  define cBLU "" | ||||||
|  | #  define cMGN "" | ||||||
|  | #  define cCYA "" | ||||||
|  | #  define cLGR "" | ||||||
|  | #  define cGRA "" | ||||||
|  | #  define cLRD "" | ||||||
|  | #  define cLGN "" | ||||||
|  | #  define cYEL "" | ||||||
|  | #  define cLBL "" | ||||||
|  | #  define cPIN "" | ||||||
|  | #  define cLCY "" | ||||||
|  | #  define cBRI "" | ||||||
|  | #  define cRST "" | ||||||
|  | 
 | ||||||
|  | #  define bgBLK "" | ||||||
|  | #  define bgRED "" | ||||||
|  | #  define bgGRN "" | ||||||
|  | #  define bgBRN "" | ||||||
|  | #  define bgBLU "" | ||||||
|  | #  define bgMGN "" | ||||||
|  | #  define bgCYA "" | ||||||
|  | #  define bgLGR "" | ||||||
|  | #  define bgGRA "" | ||||||
|  | #  define bgLRD "" | ||||||
|  | #  define bgLGN "" | ||||||
|  | #  define bgYEL "" | ||||||
|  | #  define bgLBL "" | ||||||
|  | #  define bgPIN "" | ||||||
|  | #  define bgLCY "" | ||||||
|  | #  define bgBRI "" | ||||||
|  | 
 | ||||||
|  | #endif /* ^USE_COLOR */ | ||||||
|  | 
 | ||||||
|  | /*************************
 | ||||||
|  |  * Box drawing sequences * | ||||||
|  |  *************************/ | ||||||
|  | 
 | ||||||
|  | #ifdef FANCY_BOXES | ||||||
|  | 
 | ||||||
|  | #  define SET_G1   "\x1b)0"       /* Set G1 for box drawing    */ | ||||||
|  | #  define RESET_G1 "\x1b)B"       /* Reset G1 to ASCII         */ | ||||||
|  | #  define bSTART   "\x0e"         /* Enter G1 drawing mode     */ | ||||||
|  | #  define bSTOP    "\x0f"         /* Leave G1 drawing mode     */ | ||||||
|  | #  define bH       "q"            /* Horizontal line           */ | ||||||
|  | #  define bV       "x"            /* Vertical line             */ | ||||||
|  | #  define bLT      "l"            /* Left top corner           */ | ||||||
|  | #  define bRT      "k"            /* Right top corner          */ | ||||||
|  | #  define bLB      "m"            /* Left bottom corner        */ | ||||||
|  | #  define bRB      "j"            /* Right bottom corner       */ | ||||||
|  | #  define bX       "n"            /* Cross                     */ | ||||||
|  | #  define bVR      "t"            /* Vertical, branch right    */ | ||||||
|  | #  define bVL      "u"            /* Vertical, branch left     */ | ||||||
|  | #  define bHT      "v"            /* Horizontal, branch top    */ | ||||||
|  | #  define bHB      "w"            /* Horizontal, branch bottom */ | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | #  define SET_G1   "" | ||||||
|  | #  define RESET_G1 "" | ||||||
|  | #  define bSTART   "" | ||||||
|  | #  define bSTOP    "" | ||||||
|  | #  define bH       "-" | ||||||
|  | #  define bV       "|" | ||||||
|  | #  define bLT      "+" | ||||||
|  | #  define bRT      "+" | ||||||
|  | #  define bLB      "+" | ||||||
|  | #  define bRB      "+" | ||||||
|  | #  define bX       "+" | ||||||
|  | #  define bVR      "+" | ||||||
|  | #  define bVL      "+" | ||||||
|  | #  define bHT      "+" | ||||||
|  | #  define bHB      "+" | ||||||
|  | 
 | ||||||
|  | #endif /* ^FANCY_BOXES */ | ||||||
|  | 
 | ||||||
|  | /***********************
 | ||||||
|  |  * Misc terminal codes * | ||||||
|  |  ***********************/ | ||||||
|  | 
 | ||||||
|  | #define TERM_HOME     "\x1b[H" | ||||||
|  | #define TERM_CLEAR    TERM_HOME "\x1b[2J" | ||||||
|  | #define cEOL          "\x1b[0K" | ||||||
|  | #define CURSOR_HIDE   "\x1b[?25l" | ||||||
|  | #define CURSOR_SHOW   "\x1b[?25h" | ||||||
|  | 
 | ||||||
|  | /************************
 | ||||||
|  |  * Debug & error macros * | ||||||
|  |  ************************/ | ||||||
|  | 
 | ||||||
|  | /* Just print stuff to the appropriate stream. */ | ||||||
|  | 
 | ||||||
|  | #ifdef MESSAGES_TO_STDOUT | ||||||
|  | #  define SAYF(x...)    printf(x) | ||||||
|  | #else  | ||||||
|  | #  define SAYF(x...)    fprintf(stderr, x) | ||||||
|  | #endif /* ^MESSAGES_TO_STDOUT */ | ||||||
|  | 
 | ||||||
|  | /* Show a prefixed warning. */ | ||||||
|  | 
 | ||||||
|  | #define WARNF(x...) do { \ | ||||||
|  |     SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ | ||||||
|  |     SAYF(cRST "\n"); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Show a prefixed "doing something" message. */ | ||||||
|  | 
 | ||||||
|  | #define ACTF(x...) do { \ | ||||||
|  |     SAYF(cLBL "[*] " cRST x); \ | ||||||
|  |     SAYF(cRST "\n"); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Show a prefixed "success" message. */ | ||||||
|  | 
 | ||||||
|  | #define OKF(x...) do { \ | ||||||
|  |     SAYF(cLGN "[+] " cRST x); \ | ||||||
|  |     SAYF(cRST "\n"); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Show a prefixed fatal error message (not used in afl). */ | ||||||
|  | 
 | ||||||
|  | #define BADF(x...) do { \ | ||||||
|  |     SAYF(cLRD "\n[-] " cRST x); \ | ||||||
|  |     SAYF(cRST "\n"); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Die with a verbose non-OS fatal error message. */ | ||||||
|  | 
 | ||||||
|  | #define FATAL(x...) do { \ | ||||||
|  |     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ | ||||||
|  |          cBRI x); \ | ||||||
|  |     SAYF(cLRD "\n         Location : " cRST "%s(), %s:%u\n\n", \ | ||||||
|  |          __FUNCTION__, __FILE__, __LINE__); \ | ||||||
|  |     exit(1); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Die by calling abort() to provide a core dump. */ | ||||||
|  | 
 | ||||||
|  | #define ABORT(x...) do { \ | ||||||
|  |     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ | ||||||
|  |          cBRI x); \ | ||||||
|  |     SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n\n", \ | ||||||
|  |          __FUNCTION__, __FILE__, __LINE__); \ | ||||||
|  |     abort(); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Die while also including the output of perror(). */ | ||||||
|  | 
 | ||||||
|  | #define PFATAL(x...) do { \ | ||||||
|  |     fflush(stdout); \ | ||||||
|  |     SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-]  SYSTEM ERROR : " \ | ||||||
|  |          cBRI x); \ | ||||||
|  |     SAYF(cLRD "\n    Stop location : " cRST "%s(), %s:%u\n", \ | ||||||
|  |          __FUNCTION__, __FILE__, __LINE__); \ | ||||||
|  |     SAYF(cLRD "       OS message : " cRST "%s\n", strerror(errno)); \ | ||||||
|  |     exit(1); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Die with FAULT() or PFAULT() depending on the value of res (used to
 | ||||||
|  |    interpret different failure modes for read(), write(), etc). */ | ||||||
|  | 
 | ||||||
|  | #define RPFATAL(res, x...) do { \ | ||||||
|  |     if (res < 0) PFATAL(x); else FATAL(x); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | /* Error-checking versions of read() and write() that call RPFATAL() as
 | ||||||
|  |    appropriate. */ | ||||||
|  | 
 | ||||||
|  | #define ck_write(fd, buf, len, fn) do { \ | ||||||
|  |     u32 _len = (len); \ | ||||||
|  |     s32 _res = write(fd, buf, _len); \ | ||||||
|  |     if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | #define ck_read(fd, buf, len, fn) do { \ | ||||||
|  |     u32 _len = (len); \ | ||||||
|  |     s32 _res = read(fd, buf, _len); \ | ||||||
|  |     if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ | ||||||
|  |   } while (0) | ||||||
|  | 
 | ||||||
|  | #endif /* ! _HAVE_DEBUG_H */ | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | ================ | ||||||
|  | AFL dictionaries | ||||||
|  | ================ | ||||||
|  | 
 | ||||||
|  |   (See ../docs/README for the general instruction manual.) | ||||||
|  | 
 | ||||||
|  | This subdirectory contains a set of dictionaries that can be used in | ||||||
|  | conjunction with the -x option to allow the fuzzer to effortlessly explore the | ||||||
|  | grammar of some of the more verbose data formats or languages. The basic | ||||||
|  | principle behind the operation of fuzzer dictionaries is outlined in section 9 | ||||||
|  | of the "main" README for the project. | ||||||
|  | 
 | ||||||
|  | Custom dictionaries can be added at will. They should consist of a | ||||||
|  | reasonably-sized set of rudimentary syntax units that the fuzzer will then try | ||||||
|  | to clobber together in various ways. Snippets between 2 and 16 bytes are usually | ||||||
|  | the sweet spot. | ||||||
|  | 
 | ||||||
|  | Custom dictionaries can be created in two ways: | ||||||
|  | 
 | ||||||
|  |   - By creating a new directory and placing each token in a separate file, in | ||||||
|  |     which case, there is no need to escape or otherwise format the data. | ||||||
|  | 
 | ||||||
|  |   - By creating a flat text file where tokens are listed one per line in the | ||||||
|  |     format of name="value". The alphanumeric name is ignored and can be omitted, | ||||||
|  |     although it is a convenient way to document the meaning of a particular | ||||||
|  |     token. The value must appear in quotes, with hex escaping (\xNN) applied to | ||||||
|  |     all non-printable, high-bit, or otherwise problematic characters (\\ and \" | ||||||
|  |     shorthands are recognized, too). | ||||||
|  | 
 | ||||||
|  | The fuzzer auto-selects the appropriate mode depending on whether the -x | ||||||
|  | parameter is a file or a directory. | ||||||
|  | 
 | ||||||
|  | In the file mode, every name field can be optionally followed by @<num>, e.g.: | ||||||
|  | 
 | ||||||
|  |   keyword_foo@1 = "foo" | ||||||
|  | 
 | ||||||
|  | Such entries will be loaded only if the requested dictionary level is equal or | ||||||
|  | higher than this number. The default level is zero; a higher value can be set | ||||||
|  | by appending @<num> to the dictionary file name, like so: | ||||||
|  | 
 | ||||||
|  |   -x path/to/dictionary.dct@2 | ||||||
|  | 
 | ||||||
|  | Good examples of dictionaries can be found in xml.dict and png.dict. | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for GIF images | ||||||
|  | # ----------------------------- | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | header_87a="87a" | ||||||
|  | header_89a="89a" | ||||||
|  | header_gif="GIF" | ||||||
|  | 
 | ||||||
|  | marker_2c="," | ||||||
|  | marker_3b=";" | ||||||
|  | 
 | ||||||
|  | section_2101="!\x01\x12" | ||||||
|  | section_21f9="!\xf9\x04" | ||||||
|  | section_21fe="!\xfe" | ||||||
|  | section_21ff="!\xff\x11" | ||||||
| @ -0,0 +1,160 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for HTML parsers (tags only) | ||||||
|  | # ------------------------------------------- | ||||||
|  | # | ||||||
|  | # A basic collection of HTML tags likely to matter to HTML parsers. Does *not* | ||||||
|  | # include any attributes or attribute values. | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | tag_a="<a>" | ||||||
|  | tag_abbr="<abbr>" | ||||||
|  | tag_acronym="<acronym>" | ||||||
|  | tag_address="<address>" | ||||||
|  | tag_annotation_xml="<annotation-xml>" | ||||||
|  | tag_applet="<applet>" | ||||||
|  | tag_area="<area>" | ||||||
|  | tag_article="<article>" | ||||||
|  | tag_aside="<aside>" | ||||||
|  | tag_audio="<audio>" | ||||||
|  | tag_b="<b>" | ||||||
|  | tag_base="<base>" | ||||||
|  | tag_basefont="<basefont>" | ||||||
|  | tag_bdi="<bdi>" | ||||||
|  | tag_bdo="<bdo>" | ||||||
|  | tag_bgsound="<bgsound>" | ||||||
|  | tag_big="<big>" | ||||||
|  | tag_blink="<blink>" | ||||||
|  | tag_blockquote="<blockquote>" | ||||||
|  | tag_body="<body>" | ||||||
|  | tag_br="<br>" | ||||||
|  | tag_button="<button>" | ||||||
|  | tag_canvas="<canvas>" | ||||||
|  | tag_caption="<caption>" | ||||||
|  | tag_center="<center>" | ||||||
|  | tag_cite="<cite>" | ||||||
|  | tag_code="<code>" | ||||||
|  | tag_col="<col>" | ||||||
|  | tag_colgroup="<colgroup>" | ||||||
|  | tag_data="<data>" | ||||||
|  | tag_datalist="<datalist>" | ||||||
|  | tag_dd="<dd>" | ||||||
|  | tag_del="<del>" | ||||||
|  | tag_desc="<desc>" | ||||||
|  | tag_details="<details>" | ||||||
|  | tag_dfn="<dfn>" | ||||||
|  | tag_dir="<dir>" | ||||||
|  | tag_div="<div>" | ||||||
|  | tag_dl="<dl>" | ||||||
|  | tag_dt="<dt>" | ||||||
|  | tag_em="<em>" | ||||||
|  | tag_embed="<embed>" | ||||||
|  | tag_fieldset="<fieldset>" | ||||||
|  | tag_figcaption="<figcaption>" | ||||||
|  | tag_figure="<figure>" | ||||||
|  | tag_font="<font>" | ||||||
|  | tag_footer="<footer>" | ||||||
|  | tag_foreignobject="<foreignobject>" | ||||||
|  | tag_form="<form>" | ||||||
|  | tag_frame="<frame>" | ||||||
|  | tag_frameset="<frameset>" | ||||||
|  | tag_h1="<h1>" | ||||||
|  | tag_h2="<h2>" | ||||||
|  | tag_h3="<h3>" | ||||||
|  | tag_h4="<h4>" | ||||||
|  | tag_h5="<h5>" | ||||||
|  | tag_h6="<h6>" | ||||||
|  | tag_head="<head>" | ||||||
|  | tag_header="<header>" | ||||||
|  | tag_hgroup="<hgroup>" | ||||||
|  | tag_hr="<hr>" | ||||||
|  | tag_html="<html>" | ||||||
|  | tag_i="<i>" | ||||||
|  | tag_iframe="<iframe>" | ||||||
|  | tag_image="<image>" | ||||||
|  | tag_img="<img>" | ||||||
|  | tag_input="<input>" | ||||||
|  | tag_ins="<ins>" | ||||||
|  | tag_isindex="<isindex>" | ||||||
|  | tag_kbd="<kbd>" | ||||||
|  | tag_keygen="<keygen>" | ||||||
|  | tag_label="<label>" | ||||||
|  | tag_legend="<legend>" | ||||||
|  | tag_li="<li>" | ||||||
|  | tag_link="<link>" | ||||||
|  | tag_listing="<listing>" | ||||||
|  | tag_main="<main>" | ||||||
|  | tag_malignmark="<malignmark>" | ||||||
|  | tag_map="<map>" | ||||||
|  | tag_mark="<mark>" | ||||||
|  | tag_marquee="<marquee>" | ||||||
|  | tag_math="<math>" | ||||||
|  | tag_menu="<menu>" | ||||||
|  | tag_menuitem="<menuitem>" | ||||||
|  | tag_meta="<meta>" | ||||||
|  | tag_meter="<meter>" | ||||||
|  | tag_mglyph="<mglyph>" | ||||||
|  | tag_mi="<mi>" | ||||||
|  | tag_mn="<mn>" | ||||||
|  | tag_mo="<mo>" | ||||||
|  | tag_ms="<ms>" | ||||||
|  | tag_mtext="<mtext>" | ||||||
|  | tag_multicol="<multicol>" | ||||||
|  | tag_nav="<nav>" | ||||||
|  | tag_nextid="<nextid>" | ||||||
|  | tag_nobr="<nobr>" | ||||||
|  | tag_noembed="<noembed>" | ||||||
|  | tag_noframes="<noframes>" | ||||||
|  | tag_noscript="<noscript>" | ||||||
|  | tag_object="<object>" | ||||||
|  | tag_ol="<ol>" | ||||||
|  | tag_optgroup="<optgroup>" | ||||||
|  | tag_option="<option>" | ||||||
|  | tag_output="<output>" | ||||||
|  | tag_p="<p>" | ||||||
|  | tag_param="<param>" | ||||||
|  | tag_plaintext="<plaintext>" | ||||||
|  | tag_pre="<pre>" | ||||||
|  | tag_progress="<progress>" | ||||||
|  | tag_q="<q>" | ||||||
|  | tag_rb="<rb>" | ||||||
|  | tag_rp="<rp>" | ||||||
|  | tag_rt="<rt>" | ||||||
|  | tag_rtc="<rtc>" | ||||||
|  | tag_ruby="<ruby>" | ||||||
|  | tag_s="<s>" | ||||||
|  | tag_samp="<samp>" | ||||||
|  | tag_script="<script>" | ||||||
|  | tag_section="<section>" | ||||||
|  | tag_select="<select>" | ||||||
|  | tag_small="<small>" | ||||||
|  | tag_source="<source>" | ||||||
|  | tag_spacer="<spacer>" | ||||||
|  | tag_span="<span>" | ||||||
|  | tag_strike="<strike>" | ||||||
|  | tag_strong="<strong>" | ||||||
|  | tag_style="<style>" | ||||||
|  | tag_sub="<sub>" | ||||||
|  | tag_summary="<summary>" | ||||||
|  | tag_sup="<sup>" | ||||||
|  | tag_svg="<svg>" | ||||||
|  | tag_table="<table>" | ||||||
|  | tag_tbody="<tbody>" | ||||||
|  | tag_td="<td>" | ||||||
|  | tag_template="<template>" | ||||||
|  | tag_textarea="<textarea>" | ||||||
|  | tag_tfoot="<tfoot>" | ||||||
|  | tag_th="<th>" | ||||||
|  | tag_thead="<thead>" | ||||||
|  | tag_time="<time>" | ||||||
|  | tag_title="<title>" | ||||||
|  | tag_tr="<tr>" | ||||||
|  | tag_track="<track>" | ||||||
|  | tag_tt="<tt>" | ||||||
|  | tag_u="<u>" | ||||||
|  | tag_ul="<ul>" | ||||||
|  | tag_var="<var>" | ||||||
|  | tag_video="<video>" | ||||||
|  | tag_wbr="<wbr>" | ||||||
|  | tag_xmp="<xmp>" | ||||||
| @ -0,0 +1,22 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for JPEG images | ||||||
|  | # ------------------------------ | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | header_jfif="JFIF\x00" | ||||||
|  | header_jfxx="JFXX\x00" | ||||||
|  | 
 | ||||||
|  | section_ffc0="\xff\xc0" | ||||||
|  | section_ffc2="\xff\xc2" | ||||||
|  | section_ffc4="\xff\xc4" | ||||||
|  | section_ffd0="\xff\xd0" | ||||||
|  | section_ffd8="\xff\xd8" | ||||||
|  | section_ffd9="\xff\xd9" | ||||||
|  | section_ffda="\xff\xda" | ||||||
|  | section_ffdb="\xff\xdb" | ||||||
|  | section_ffdd="\xff\xdd" | ||||||
|  | section_ffe0="\xff\xe0" | ||||||
|  | section_ffe1="\xff\xe1" | ||||||
|  | section_fffe="\xff\xfe" | ||||||
| @ -0,0 +1,107 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for JavaScript | ||||||
|  | # ----------------------------- | ||||||
|  | # | ||||||
|  | # Contains basic reserved keywords and syntax building blocks. | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | keyword_arguments="arguments" | ||||||
|  | keyword_break="break" | ||||||
|  | keyword_case="case" | ||||||
|  | keyword_catch="catch" | ||||||
|  | keyword_const="const" | ||||||
|  | keyword_continue="continue" | ||||||
|  | keyword_debugger="debugger" | ||||||
|  | keyword_decodeURI="decodeURI" | ||||||
|  | keyword_default="default" | ||||||
|  | keyword_delete="delete" | ||||||
|  | keyword_do="do" | ||||||
|  | keyword_else="else" | ||||||
|  | keyword_escape="escape" | ||||||
|  | keyword_eval="eval" | ||||||
|  | keyword_export="export" | ||||||
|  | keyword_finally="finally" | ||||||
|  | keyword_for="for (a=0;a<2;a++)" | ||||||
|  | keyword_function="function" | ||||||
|  | keyword_if="if" | ||||||
|  | keyword_in="in" | ||||||
|  | keyword_instanceof="instanceof" | ||||||
|  | keyword_isNaN="isNaN" | ||||||
|  | keyword_let="let" | ||||||
|  | keyword_new="new" | ||||||
|  | keyword_parseInt="parseInt" | ||||||
|  | keyword_return="return" | ||||||
|  | keyword_switch="switch" | ||||||
|  | keyword_this="this" | ||||||
|  | keyword_throw="throw" | ||||||
|  | keyword_try="try" | ||||||
|  | keyword_typeof="typeof" | ||||||
|  | keyword_var="var" | ||||||
|  | keyword_void="void" | ||||||
|  | keyword_while="while" | ||||||
|  | keyword_with="with" | ||||||
|  | 
 | ||||||
|  | misc_1=" 1" | ||||||
|  | misc_a="a" | ||||||
|  | misc_array=" [1]" | ||||||
|  | misc_assign=" a=1" | ||||||
|  | misc_code_block=" {1}" | ||||||
|  | misc_colon_num=" 1:" | ||||||
|  | misc_colon_string=" 'a':" | ||||||
|  | misc_comma=" ," | ||||||
|  | misc_comment_block=" /* */" | ||||||
|  | misc_comment_line=" //" | ||||||
|  | misc_cond=" 1?2:3" | ||||||
|  | misc_dec=" --" | ||||||
|  | misc_div=" /" | ||||||
|  | misc_equals=" =" | ||||||
|  | misc_fn=" a()" | ||||||
|  | misc_identical=" ===" | ||||||
|  | misc_inc=" ++" | ||||||
|  | misc_minus=" -" | ||||||
|  | misc_modulo=" %" | ||||||
|  | misc_parentheses=" ()" | ||||||
|  | misc_parentheses_1=" (1)" | ||||||
|  | misc_parentheses_1x4=" (1,1,1,1)" | ||||||
|  | misc_parentheses_a=" (a)" | ||||||
|  | misc_period="." | ||||||
|  | misc_plus=" +" | ||||||
|  | misc_plus_assign=" +=" | ||||||
|  | misc_regex=" /a/g" | ||||||
|  | misc_rol=" <<<" | ||||||
|  | misc_semicolon=" ;" | ||||||
|  | misc_serialized_object=" {'a': 1}" | ||||||
|  | misc_string=" 'a'" | ||||||
|  | misc_unicode=" '\\u0001'" | ||||||
|  | 
 | ||||||
|  | object_Array=" Array" | ||||||
|  | object_Boolean=" Boolean" | ||||||
|  | object_Date=" Date" | ||||||
|  | object_Function=" Function" | ||||||
|  | object_Infinity=" Infinity" | ||||||
|  | object_Int8Array=" Int8Array" | ||||||
|  | object_Math=" Math" | ||||||
|  | object_NaN=" NaN" | ||||||
|  | object_Number=" Number" | ||||||
|  | object_Object=" Object" | ||||||
|  | object_RegExp=" RegExp" | ||||||
|  | object_String=" String" | ||||||
|  | object_Symbol=" Symbol" | ||||||
|  | object_false=" false" | ||||||
|  | object_null=" null" | ||||||
|  | object_true=" true" | ||||||
|  | 
 | ||||||
|  | prop_charAt=".charAt" | ||||||
|  | prop_concat=".concat" | ||||||
|  | prop_constructor=".constructor" | ||||||
|  | prop_destructor=".destructor" | ||||||
|  | prop_length=".length" | ||||||
|  | prop_match=".match" | ||||||
|  | prop_proto=".__proto__" | ||||||
|  | prop_prototype=".prototype" | ||||||
|  | prop_slice=".slice" | ||||||
|  | prop_toCode=".toCode" | ||||||
|  | prop_toString=".toString" | ||||||
|  | prop_valueOf=".valueOf" | ||||||
| @ -0,0 +1,52 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for JSON | ||||||
|  | # ----------------------- | ||||||
|  | # | ||||||
|  | # Just the very basics. | ||||||
|  | # | ||||||
|  | # Inspired by a dictionary by Jakub Wilk <jwilk@jwilk.net> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | "0" | ||||||
|  | ",0" | ||||||
|  | ":0" | ||||||
|  | "0:" | ||||||
|  | "-1.2e+3" | ||||||
|  | 
 | ||||||
|  | "true" | ||||||
|  | "false" | ||||||
|  | "null" | ||||||
|  | 
 | ||||||
|  | "\"\"" | ||||||
|  | ",\"\"" | ||||||
|  | ":\"\"" | ||||||
|  | "\"\":" | ||||||
|  | 
 | ||||||
|  | "{}" | ||||||
|  | ",{}" | ||||||
|  | ":{}" | ||||||
|  | "{\"\":0}" | ||||||
|  | "{{}}" | ||||||
|  | 
 | ||||||
|  | "[]" | ||||||
|  | ",[]" | ||||||
|  | ":[]" | ||||||
|  | "[0]" | ||||||
|  | "[[]]" | ||||||
|  | 
 | ||||||
|  | "''" | ||||||
|  | "\\" | ||||||
|  | "\\b" | ||||||
|  | "\\f" | ||||||
|  | "\\n" | ||||||
|  | "\\r" | ||||||
|  | "\\t" | ||||||
|  | "\\u0000" | ||||||
|  | "\\x00" | ||||||
|  | "\\0" | ||||||
|  | "\\uD800\\uDC00" | ||||||
|  | "\\uDBFF\\uDFFF" | ||||||
|  | 
 | ||||||
|  | "\"\":0" | ||||||
|  | "//" | ||||||
|  | "/**/" | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # AFL dictionary for fuzzing Perl | ||||||
|  | # -------------------------------- | ||||||
|  | # | ||||||
|  | # Created by @RandomDhiraj | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | "<:crlf" | ||||||
|  | "fwrite()" | ||||||
|  | "fread()" | ||||||
|  | ":raw:utf8" | ||||||
|  | ":raw:eol(LF)" | ||||||
|  | "Perl_invert()" | ||||||
|  | ":raw:eol(CRLF)" | ||||||
|  | "Perl_PerlIO_eof()" | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for PNG images | ||||||
|  | # ----------------------------- | ||||||
|  | # | ||||||
|  | # Just the basic, standard-originating sections; does not include vendor | ||||||
|  | # extensions. | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | header_png="\x89PNG\x0d\x0a\x1a\x0a" | ||||||
|  | 
 | ||||||
|  | section_IDAT="IDAT" | ||||||
|  | section_IEND="IEND" | ||||||
|  | section_IHDR="IHDR" | ||||||
|  | section_PLTE="PLTE" | ||||||
|  | section_bKGD="bKGD" | ||||||
|  | section_cHRM="cHRM" | ||||||
|  | section_fRAc="fRAc" | ||||||
|  | section_gAMA="gAMA" | ||||||
|  | section_gIFg="gIFg" | ||||||
|  | section_gIFt="gIFt" | ||||||
|  | section_gIFx="gIFx" | ||||||
|  | section_hIST="hIST" | ||||||
|  | section_iCCP="iCCP" | ||||||
|  | section_iTXt="iTXt" | ||||||
|  | section_oFFs="oFFs" | ||||||
|  | section_pCAL="pCAL" | ||||||
|  | section_pHYs="pHYs" | ||||||
|  | section_sBIT="sBIT" | ||||||
|  | section_sCAL="sCAL" | ||||||
|  | section_sPLT="sPLT" | ||||||
|  | section_sRGB="sRGB" | ||||||
|  | section_sTER="sTER" | ||||||
|  | section_tEXt="tEXt" | ||||||
|  | section_tIME="tIME" | ||||||
|  | section_tRNS="tRNS" | ||||||
|  | section_zTXt="zTXt" | ||||||
| @ -0,0 +1,254 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for JS regex | ||||||
|  | # --------------------------- | ||||||
|  | # | ||||||
|  | # Contains various regular expressions. | ||||||
|  | # | ||||||
|  | # Created by Yang Guo <yangguo@chromium.org> | ||||||
|  | # | ||||||
|  | "?" | ||||||
|  | "abc" | ||||||
|  | "()" | ||||||
|  | "[]" | ||||||
|  | "abc|def" | ||||||
|  | "abc|def|ghi" | ||||||
|  | "^xxx$" | ||||||
|  | "ab\\b\\d\\bcd" | ||||||
|  | "\\w|\\d" | ||||||
|  | "a*?" | ||||||
|  | "abc+" | ||||||
|  | "abc+?" | ||||||
|  | "xyz?" | ||||||
|  | "xyz??" | ||||||
|  | "xyz{0,1}" | ||||||
|  | "xyz{0,1}?" | ||||||
|  | "xyz{93}" | ||||||
|  | "xyz{1,32}" | ||||||
|  | "xyz{1,32}?" | ||||||
|  | "xyz{1,}" | ||||||
|  | "xyz{1,}?" | ||||||
|  | "a\\fb\\nc\\rd\\te\\vf" | ||||||
|  | "a\\nb\\bc" | ||||||
|  | "(?:foo)" | ||||||
|  | "(?: foo )" | ||||||
|  | "foo|(bar|baz)|quux" | ||||||
|  | "foo(?=bar)baz" | ||||||
|  | "foo(?!bar)baz" | ||||||
|  | "foo(?<=bar)baz" | ||||||
|  | "foo(?<!bar)baz" | ||||||
|  | "()" | ||||||
|  | "(?=)" | ||||||
|  | "[]" | ||||||
|  | "[x]" | ||||||
|  | "[xyz]" | ||||||
|  | "[a-zA-Z0-9]" | ||||||
|  | "[-123]" | ||||||
|  | "[^123]" | ||||||
|  | "]" | ||||||
|  | "}" | ||||||
|  | "[a-b-c]" | ||||||
|  | "[x\\dz]" | ||||||
|  | "[\\d-z]" | ||||||
|  | "[\\d-\\d]" | ||||||
|  | "[z-\\d]" | ||||||
|  | "\\cj\\cJ\\ci\\cI\\ck\\cK" | ||||||
|  | "\\c!" | ||||||
|  | "\\c_" | ||||||
|  | "\\c~" | ||||||
|  | "[\\c!]" | ||||||
|  | "[\\c_]" | ||||||
|  | "[\\c~]" | ||||||
|  | "[\\ca]" | ||||||
|  | "[\\cz]" | ||||||
|  | "[\\cA]" | ||||||
|  | "[\\cZ]" | ||||||
|  | "[\\c1]" | ||||||
|  | "\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ " | ||||||
|  | "[\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ]" | ||||||
|  | "\\8" | ||||||
|  | "\\9" | ||||||
|  | "\\11" | ||||||
|  | "\\11a" | ||||||
|  | "\\011" | ||||||
|  | "\\118" | ||||||
|  | "\\111" | ||||||
|  | "\\1111" | ||||||
|  | "(x)(x)(x)\\1" | ||||||
|  | "(x)(x)(x)\\2" | ||||||
|  | "(x)(x)(x)\\3" | ||||||
|  | "(x)(x)(x)\\4" | ||||||
|  | "(x)(x)(x)\\1*" | ||||||
|  | "(x)(x)(x)\\3*" | ||||||
|  | "(x)(x)(x)\\4*" | ||||||
|  | "(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\10" | ||||||
|  | "(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\11" | ||||||
|  | "(a)\\1" | ||||||
|  | "(a\\1)" | ||||||
|  | "(\\1a)" | ||||||
|  | "(\\2)(\\1)" | ||||||
|  | "(?=a){0,10}a" | ||||||
|  | "(?=a){1,10}a" | ||||||
|  | "(?=a){9,10}a" | ||||||
|  | "(?!a)?a" | ||||||
|  | "\\1(a)" | ||||||
|  | "(?!(a))\\1" | ||||||
|  | "(?!\\1(a\\1)\\1)\\1" | ||||||
|  | "\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1" | ||||||
|  | "[\\0]" | ||||||
|  | "[\\11]" | ||||||
|  | "[\\11a]" | ||||||
|  | "[\\011]" | ||||||
|  | "[\\00011]" | ||||||
|  | "[\\118]" | ||||||
|  | "[\\111]" | ||||||
|  | "[\\1111]" | ||||||
|  | "\\x60" | ||||||
|  | "\\x3z" | ||||||
|  | "\\c" | ||||||
|  | "\\u0034" | ||||||
|  | "\\u003z" | ||||||
|  | "foo[z]*" | ||||||
|  | "\\u{12345}" | ||||||
|  | "\\u{12345}\\u{23456}" | ||||||
|  | "\\u{12345}{3}" | ||||||
|  | "\\u{12345}*" | ||||||
|  | "\\ud808\\udf45*" | ||||||
|  | "[\\ud808\\udf45-\\ud809\\udccc]" | ||||||
|  | "a" | ||||||
|  | "a|b" | ||||||
|  | "a\\n" | ||||||
|  | "a$" | ||||||
|  | "a\\b!" | ||||||
|  | "a\\Bb" | ||||||
|  | "a*?" | ||||||
|  | "a?" | ||||||
|  | "a??" | ||||||
|  | "a{0,1}?" | ||||||
|  | "a{1,2}?" | ||||||
|  | "a+?" | ||||||
|  | "(a)" | ||||||
|  | "(a)\\1" | ||||||
|  | "(\\1a)" | ||||||
|  | "\\1(a)" | ||||||
|  | "a\\s" | ||||||
|  | "a\\S" | ||||||
|  | "a\\D" | ||||||
|  | "a\\w" | ||||||
|  | "a\\W" | ||||||
|  | "a." | ||||||
|  | "a\\q" | ||||||
|  | "a[a]" | ||||||
|  | "a[^a]" | ||||||
|  | "a[a-z]" | ||||||
|  | "a(?:b)" | ||||||
|  | "a(?=b)" | ||||||
|  | "a(?!b)" | ||||||
|  | "\\x60" | ||||||
|  | "\\u0060" | ||||||
|  | "\\cA" | ||||||
|  | "\\q" | ||||||
|  | "\\1112" | ||||||
|  | "(a)\\1" | ||||||
|  | "(?!a)?a\\1" | ||||||
|  | "(?:(?=a))a\\1" | ||||||
|  | "a{}" | ||||||
|  | "a{,}" | ||||||
|  | "a{" | ||||||
|  | "a{z}" | ||||||
|  | "a{12z}" | ||||||
|  | "a{12," | ||||||
|  | "a{12,3b" | ||||||
|  | "{}" | ||||||
|  | "{,}" | ||||||
|  | "{" | ||||||
|  | "{z}" | ||||||
|  | "{1z}" | ||||||
|  | "{12," | ||||||
|  | "{12,3b" | ||||||
|  | "a" | ||||||
|  | "abc" | ||||||
|  | "a[bc]d" | ||||||
|  | "a|bc" | ||||||
|  | "ab|c" | ||||||
|  | "a||bc" | ||||||
|  | "(?:ab)" | ||||||
|  | "(?:ab|cde)" | ||||||
|  | "(?:ab)|cde" | ||||||
|  | "(ab)" | ||||||
|  | "(ab|cde)" | ||||||
|  | "(ab)\\1" | ||||||
|  | "(ab|cde)\\1" | ||||||
|  | "(?:ab)?" | ||||||
|  | "(?:ab)+" | ||||||
|  | "a?" | ||||||
|  | "a+" | ||||||
|  | "a??" | ||||||
|  | "a*?" | ||||||
|  | "a+?" | ||||||
|  | "(?:a?)?" | ||||||
|  | "(?:a+)?" | ||||||
|  | "(?:a?)+" | ||||||
|  | "(?:a*)+" | ||||||
|  | "(?:a+)+" | ||||||
|  | "(?:a?)*" | ||||||
|  | "(?:a*)*" | ||||||
|  | "(?:a+)*" | ||||||
|  | "a{0}" | ||||||
|  | "(?:a+){0,0}" | ||||||
|  | "a*b" | ||||||
|  | "a+b" | ||||||
|  | "a*b|c" | ||||||
|  | "a+b|c" | ||||||
|  | "(?:a{5,1000000}){3,1000000}" | ||||||
|  | "(?:ab){4,7}" | ||||||
|  | "a\\bc" | ||||||
|  | "a\\sc" | ||||||
|  | "a\\Sc" | ||||||
|  | "a(?=b)c" | ||||||
|  | "a(?=bbb|bb)c" | ||||||
|  | "a(?!bbb|bb)c" | ||||||
|  | "\xe2\x81\xa3" | ||||||
|  | "[\xe2\x81\xa3]" | ||||||
|  | "\xed\xb0\x80" | ||||||
|  | "\xed\xa0\x80" | ||||||
|  | "(\xed\xb0\x80)\x01" | ||||||
|  | "((\xed\xa0\x80))\x02" | ||||||
|  | "\xf0\x9f\x92\xa9" | ||||||
|  | "\x01" | ||||||
|  | "\x0f" | ||||||
|  | "[-\xf0\x9f\x92\xa9]+" | ||||||
|  | "[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\xbf]" | ||||||
|  | "(?<=)" | ||||||
|  | "(?<=a)" | ||||||
|  | "(?<!)" | ||||||
|  | "(?<!a)" | ||||||
|  | "(?<a>)" | ||||||
|  | "(?<a>.)" | ||||||
|  | "(?<a>.)\\k<a>" | ||||||
|  | "\\p{Script=Greek}" | ||||||
|  | "\\P{sc=Greek}" | ||||||
|  | "\\p{Script_Extensions=Greek}" | ||||||
|  | "\\P{scx=Greek}" | ||||||
|  | "\\p{General_Category=Decimal_Number}" | ||||||
|  | "\\P{gc=Decimal_Number}" | ||||||
|  | "\\p{gc=Nd}" | ||||||
|  | "\\P{Decimal_Number}" | ||||||
|  | "\\p{Nd}" | ||||||
|  | "\\P{Any}" | ||||||
|  | "\\p{Changes_When_NFKC_Casefolded}" | ||||||
|  | "(?:a?)??" | ||||||
|  | "a?)"xyz{93}" | ||||||
|  | "{93}" | ||||||
|  | "a{12za?)?" | ||||||
|  | "[\x8f]" | ||||||
|  | "[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\x92\xa9-\xf4\x8f\xbf\xbf]" | ||||||
|  | "[\x92\xa9-\xf4\x8f\xbf\xbf]" | ||||||
|  | "\\1\\2(b\\1\\2))\\2)\\1" | ||||||
|  | "\\1\\2(a(?:\\1\\2))\\2)\\1" | ||||||
|  | "?:\\1" | ||||||
|  | "\\1(b\\1\\2))\\2)\\1" | ||||||
|  | "\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1" | ||||||
|  | "foo(?=bar)bar)baz" | ||||||
|  | "fo(?o(?o(?o(?=bar)baz" | ||||||
|  | "foo(?=bar)baz" | ||||||
|  | "foo(?=bar)bar)az" | ||||||
| @ -0,0 +1,282 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for SQL | ||||||
|  | # ---------------------- | ||||||
|  | # | ||||||
|  | # Modeled based on SQLite documentation, contains some number of SQLite | ||||||
|  | # extensions. Other dialects of SQL may benefit from customized dictionaries. | ||||||
|  | # | ||||||
|  | # If you append @1 to the file name when loading this dictionary, afl-fuzz | ||||||
|  | # will also additionally load a selection of pragma keywords that are very | ||||||
|  | # specific to SQLite (and are probably less interesting from the security | ||||||
|  | # standpoint, because they are usually not allowed in non-privileged | ||||||
|  | # contexts). | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | function_abs=" abs(1)" | ||||||
|  | function_avg=" avg(1)" | ||||||
|  | function_changes=" changes()" | ||||||
|  | function_char=" char(1)" | ||||||
|  | function_coalesce=" coalesce(1,1)" | ||||||
|  | function_count=" count(1)" | ||||||
|  | function_date=" date(1,1,1)" | ||||||
|  | function_datetime=" datetime(1,1,1)" | ||||||
|  | function_decimal=" decimal(1,1)" | ||||||
|  | function_glob=" glob(1,1)" | ||||||
|  | function_group_concat=" group_concat(1,1)" | ||||||
|  | function_hex=" hex(1)" | ||||||
|  | function_ifnull=" ifnull(1,1)" | ||||||
|  | function_instr=" instr(1,1)" | ||||||
|  | function_julianday=" julianday(1,1,1)" | ||||||
|  | function_last_insert_rowid=" last_insert_rowid()" | ||||||
|  | function_length=" length(1)" | ||||||
|  | function_like=" like(1,1)" | ||||||
|  | function_likelihood=" likelihood(1,1)" | ||||||
|  | function_likely=" likely(1)" | ||||||
|  | function_load_extension=" load_extension(1,1)" | ||||||
|  | function_lower=" lower(1)" | ||||||
|  | function_ltrim=" ltrim(1,1)" | ||||||
|  | function_max=" max(1,1)" | ||||||
|  | function_min=" min(1,1)" | ||||||
|  | function_nullif=" nullif(1,1)" | ||||||
|  | function_printf=" printf(1,1)" | ||||||
|  | function_quote=" quote(1)" | ||||||
|  | function_random=" random()" | ||||||
|  | function_randomblob=" randomblob(1)" | ||||||
|  | function_replace=" replace(1,1,1)" | ||||||
|  | function_round=" round(1,1)" | ||||||
|  | function_rtrim=" rtrim(1,1)" | ||||||
|  | function_soundex=" soundex(1)" | ||||||
|  | function_sqlite_compileoption_get=" sqlite_compileoption_get(1)" | ||||||
|  | function_sqlite_compileoption_used=" sqlite_compileoption_used(1)" | ||||||
|  | function_sqlite_source_id=" sqlite_source_id()" | ||||||
|  | function_sqlite_version=" sqlite_version()" | ||||||
|  | function_strftime=" strftime(1,1,1,1)" | ||||||
|  | function_substr=" substr(1,1,1)" | ||||||
|  | function_sum=" sum(1)" | ||||||
|  | function_time=" time(1,1,1)" | ||||||
|  | function_total=" total(1)" | ||||||
|  | function_total_changes=" total_changes()" | ||||||
|  | function_trim=" trim(1,1)" | ||||||
|  | function_typeof=" typeof(1)" | ||||||
|  | function_unicode=" unicode(1)" | ||||||
|  | function_unlikely=" unlikely(1)" | ||||||
|  | function_upper=" upper(1)" | ||||||
|  | function_varchar=" varchar(1)" | ||||||
|  | function_zeroblob=" zeroblob(1)" | ||||||
|  | 
 | ||||||
|  | keyword_ABORT="ABORT" | ||||||
|  | keyword_ACTION="ACTION" | ||||||
|  | keyword_ADD="ADD" | ||||||
|  | keyword_AFTER="AFTER" | ||||||
|  | keyword_ALL="ALL" | ||||||
|  | keyword_ALTER="ALTER" | ||||||
|  | keyword_ANALYZE="ANALYZE" | ||||||
|  | keyword_AND="AND" | ||||||
|  | keyword_AS="AS" | ||||||
|  | keyword_ASC="ASC" | ||||||
|  | keyword_ATTACH="ATTACH" | ||||||
|  | keyword_AUTOINCREMENT="AUTOINCREMENT" | ||||||
|  | keyword_BEFORE="BEFORE" | ||||||
|  | keyword_BEGIN="BEGIN" | ||||||
|  | keyword_BETWEEN="BETWEEN" | ||||||
|  | keyword_BY="BY" | ||||||
|  | keyword_CASCADE="CASCADE" | ||||||
|  | keyword_CASE="CASE" | ||||||
|  | keyword_CAST="CAST" | ||||||
|  | keyword_CHECK="CHECK" | ||||||
|  | keyword_COLLATE="COLLATE" | ||||||
|  | keyword_COLUMN="COLUMN" | ||||||
|  | keyword_COMMIT="COMMIT" | ||||||
|  | keyword_CONFLICT="CONFLICT" | ||||||
|  | keyword_CONSTRAINT="CONSTRAINT" | ||||||
|  | keyword_CREATE="CREATE" | ||||||
|  | keyword_CROSS="CROSS" | ||||||
|  | keyword_CURRENT_DATE="CURRENT_DATE" | ||||||
|  | keyword_CURRENT_TIME="CURRENT_TIME" | ||||||
|  | keyword_CURRENT_TIMESTAMP="CURRENT_TIMESTAMP" | ||||||
|  | keyword_DATABASE="DATABASE" | ||||||
|  | keyword_DEFAULT="DEFAULT" | ||||||
|  | keyword_DEFERRABLE="DEFERRABLE" | ||||||
|  | keyword_DEFERRED="DEFERRED" | ||||||
|  | keyword_DELETE="DELETE" | ||||||
|  | keyword_DESC="DESC" | ||||||
|  | keyword_DETACH="DETACH" | ||||||
|  | keyword_DISTINCT="DISTINCT" | ||||||
|  | keyword_DROP="DROP" | ||||||
|  | keyword_EACH="EACH" | ||||||
|  | keyword_ELSE="ELSE" | ||||||
|  | keyword_END="END" | ||||||
|  | keyword_ESCAPE="ESCAPE" | ||||||
|  | keyword_EXCEPT="EXCEPT" | ||||||
|  | keyword_EXCLUSIVE="EXCLUSIVE" | ||||||
|  | keyword_EXISTS="EXISTS" | ||||||
|  | keyword_EXPLAIN="EXPLAIN" | ||||||
|  | keyword_FAIL="FAIL" | ||||||
|  | keyword_FOR="FOR" | ||||||
|  | keyword_FOREIGN="FOREIGN" | ||||||
|  | keyword_FROM="FROM" | ||||||
|  | keyword_FULL="FULL" | ||||||
|  | keyword_GLOB="GLOB" | ||||||
|  | keyword_GROUP="GROUP" | ||||||
|  | keyword_HAVING="HAVING" | ||||||
|  | keyword_IF="IF" | ||||||
|  | keyword_IGNORE="IGNORE" | ||||||
|  | keyword_IMMEDIATE="IMMEDIATE" | ||||||
|  | keyword_IN="IN" | ||||||
|  | keyword_INDEX="INDEX" | ||||||
|  | keyword_INDEXED="INDEXED" | ||||||
|  | keyword_INITIALLY="INITIALLY" | ||||||
|  | keyword_INNER="INNER" | ||||||
|  | keyword_INSERT="INSERT" | ||||||
|  | keyword_INSTEAD="INSTEAD" | ||||||
|  | keyword_INTERSECT="INTERSECT" | ||||||
|  | keyword_INTO="INTO" | ||||||
|  | keyword_IS="IS" | ||||||
|  | keyword_ISNULL="ISNULL" | ||||||
|  | keyword_JOIN="JOIN" | ||||||
|  | keyword_KEY="KEY" | ||||||
|  | keyword_LEFT="LEFT" | ||||||
|  | keyword_LIKE="LIKE" | ||||||
|  | keyword_LIMIT="LIMIT" | ||||||
|  | keyword_MATCH="MATCH" | ||||||
|  | keyword_NATURAL="NATURAL" | ||||||
|  | keyword_NO="NO" | ||||||
|  | keyword_NOT="NOT" | ||||||
|  | keyword_NOTNULL="NOTNULL" | ||||||
|  | keyword_NULL="NULL" | ||||||
|  | keyword_OF="OF" | ||||||
|  | keyword_OFFSET="OFFSET" | ||||||
|  | keyword_ON="ON" | ||||||
|  | keyword_OR="OR" | ||||||
|  | keyword_ORDER="ORDER" | ||||||
|  | keyword_OUTER="OUTER" | ||||||
|  | keyword_PLAN="PLAN" | ||||||
|  | keyword_PRAGMA="PRAGMA" | ||||||
|  | keyword_PRIMARY="PRIMARY" | ||||||
|  | keyword_QUERY="QUERY" | ||||||
|  | keyword_RAISE="RAISE" | ||||||
|  | keyword_RECURSIVE="RECURSIVE" | ||||||
|  | keyword_REFERENCES="REFERENCES" | ||||||
|  | keyword_REGEXP="REGEXP" | ||||||
|  | keyword_REINDEX="REINDEX" | ||||||
|  | keyword_RELEASE="RELEASE" | ||||||
|  | keyword_RENAME="RENAME" | ||||||
|  | keyword_REPLACE="REPLACE" | ||||||
|  | keyword_RESTRICT="RESTRICT" | ||||||
|  | keyword_RIGHT="RIGHT" | ||||||
|  | keyword_ROLLBACK="ROLLBACK" | ||||||
|  | keyword_ROW="ROW" | ||||||
|  | keyword_SAVEPOINT="SAVEPOINT" | ||||||
|  | keyword_SELECT="SELECT" | ||||||
|  | keyword_SET="SET" | ||||||
|  | keyword_TABLE="TABLE" | ||||||
|  | keyword_TEMP="TEMP" | ||||||
|  | keyword_TEMPORARY="TEMPORARY" | ||||||
|  | keyword_THEN="THEN" | ||||||
|  | keyword_TO="TO" | ||||||
|  | keyword_TRANSACTION="TRANSACTION" | ||||||
|  | keyword_TRIGGER="TRIGGER" | ||||||
|  | keyword_UNION="UNION" | ||||||
|  | keyword_UNIQUE="UNIQUE" | ||||||
|  | keyword_UPDATE="UPDATE" | ||||||
|  | keyword_USING="USING" | ||||||
|  | keyword_VACUUM="VACUUM" | ||||||
|  | keyword_VALUES="VALUES" | ||||||
|  | keyword_VIEW="VIEW" | ||||||
|  | keyword_VIRTUAL="VIRTUAL" | ||||||
|  | keyword_WHEN="WHEN" | ||||||
|  | keyword_WHERE="WHERE" | ||||||
|  | keyword_WITH="WITH" | ||||||
|  | keyword_WITHOUT="WITHOUT" | ||||||
|  | 
 | ||||||
|  | operator_concat=" || " | ||||||
|  | operator_ebove_eq=" >=" | ||||||
|  | 
 | ||||||
|  | snippet_1eq1=" 1=1" | ||||||
|  | snippet_at=" @1" | ||||||
|  | snippet_backticks=" `a`" | ||||||
|  | snippet_blob=" blob" | ||||||
|  | snippet_brackets=" [a]" | ||||||
|  | snippet_colon=" :1" | ||||||
|  | snippet_comment=" /* */" | ||||||
|  | snippet_date="2001-01-01" | ||||||
|  | snippet_dollar=" $1" | ||||||
|  | snippet_dotref=" a.b" | ||||||
|  | snippet_fmtY="%Y" | ||||||
|  | snippet_int=" int" | ||||||
|  | snippet_neg1=" -1" | ||||||
|  | snippet_pair=" a,b" | ||||||
|  | snippet_parentheses=" (1)" | ||||||
|  | snippet_plus2days="+2 days" | ||||||
|  | snippet_qmark=" ?1" | ||||||
|  | snippet_semicolon=" ;" | ||||||
|  | snippet_star=" *" | ||||||
|  | snippet_string_pair=" \"a\",\"b\"" | ||||||
|  | 
 | ||||||
|  | string_dbl_q=" \"a\"" | ||||||
|  | string_escaped_q=" 'a''b'" | ||||||
|  | string_single_q=" 'a'" | ||||||
|  | 
 | ||||||
|  | pragma_application_id@1=" application_id" | ||||||
|  | pragma_auto_vacuum@1=" auto_vacuum" | ||||||
|  | pragma_automatic_index@1=" automatic_index" | ||||||
|  | pragma_busy_timeout@1=" busy_timeout" | ||||||
|  | pragma_cache_size@1=" cache_size" | ||||||
|  | pragma_cache_spill@1=" cache_spill" | ||||||
|  | pragma_case_sensitive_like@1=" case_sensitive_like" | ||||||
|  | pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync" | ||||||
|  | pragma_collation_list@1=" collation_list" | ||||||
|  | pragma_compile_options@1=" compile_options" | ||||||
|  | pragma_count_changes@1=" count_changes" | ||||||
|  | pragma_data_store_directory@1=" data_store_directory" | ||||||
|  | pragma_database_list@1=" database_list" | ||||||
|  | pragma_default_cache_size@1=" default_cache_size" | ||||||
|  | pragma_defer_foreign_keys@1=" defer_foreign_keys" | ||||||
|  | pragma_empty_result_callbacks@1=" empty_result_callbacks" | ||||||
|  | pragma_encoding@1=" encoding" | ||||||
|  | pragma_foreign_key_check@1=" foreign_key_check" | ||||||
|  | pragma_foreign_key_list@1=" foreign_key_list" | ||||||
|  | pragma_foreign_keys@1=" foreign_keys" | ||||||
|  | pragma_freelist_count@1=" freelist_count" | ||||||
|  | pragma_full_column_names@1=" full_column_names" | ||||||
|  | pragma_fullfsync@1=" fullfsync" | ||||||
|  | pragma_ignore_check_constraints@1=" ignore_check_constraints" | ||||||
|  | pragma_incremental_vacuum@1=" incremental_vacuum" | ||||||
|  | pragma_index_info@1=" index_info" | ||||||
|  | pragma_index_list@1=" index_list" | ||||||
|  | pragma_integrity_check@1=" integrity_check" | ||||||
|  | pragma_journal_mode@1=" journal_mode" | ||||||
|  | pragma_journal_size_limit@1=" journal_size_limit" | ||||||
|  | pragma_legacy_file_format@1=" legacy_file_format" | ||||||
|  | pragma_locking_mode@1=" locking_mode" | ||||||
|  | pragma_max_page_count@1=" max_page_count" | ||||||
|  | pragma_mmap_size@1=" mmap_size" | ||||||
|  | pragma_page_count@1=" page_count" | ||||||
|  | pragma_page_size@1=" page_size" | ||||||
|  | pragma_parser_trace@1=" parser_trace" | ||||||
|  | pragma_query_only@1=" query_only" | ||||||
|  | pragma_quick_check@1=" quick_check" | ||||||
|  | pragma_read_uncommitted@1=" read_uncommitted" | ||||||
|  | pragma_recursive_triggers@1=" recursive_triggers" | ||||||
|  | pragma_reverse_unordered_selects@1=" reverse_unordered_selects" | ||||||
|  | pragma_schema_version@1=" schema_version" | ||||||
|  | pragma_secure_delete@1=" secure_delete" | ||||||
|  | pragma_short_column_names@1=" short_column_names" | ||||||
|  | pragma_shrink_memory@1=" shrink_memory" | ||||||
|  | pragma_soft_heap_limit@1=" soft_heap_limit" | ||||||
|  | pragma_stats@1=" stats" | ||||||
|  | pragma_synchronous@1=" synchronous" | ||||||
|  | pragma_table_info@1=" table_info" | ||||||
|  | pragma_temp_store@1=" temp_store" | ||||||
|  | pragma_temp_store_directory@1=" temp_store_directory" | ||||||
|  | pragma_threads@1=" threads" | ||||||
|  | pragma_user_version@1=" user_version" | ||||||
|  | pragma_vdbe_addoptrace@1=" vdbe_addoptrace" | ||||||
|  | pragma_vdbe_debug@1=" vdbe_debug" | ||||||
|  | pragma_vdbe_listing@1=" vdbe_listing" | ||||||
|  | pragma_vdbe_trace@1=" vdbe_trace" | ||||||
|  | pragma_wal_autocheckpoint@1=" wal_autocheckpoint" | ||||||
|  | pragma_wal_checkpoint@1=" wal_checkpoint" | ||||||
|  | pragma_writable_schema@1=" writable_schema" | ||||||
| @ -0,0 +1,51 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for TIFF images | ||||||
|  | # ------------------------------ | ||||||
|  | # | ||||||
|  | # Just the basic, standard-originating sections; does not include vendor | ||||||
|  | # extensions. | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | header_ii="II*\x00" | ||||||
|  | header_mm="MM\x00*" | ||||||
|  | 
 | ||||||
|  | section_100="\x00\x01" | ||||||
|  | section_101="\x01\x01" | ||||||
|  | section_102="\x02\x01" | ||||||
|  | section_103="\x03\x01" | ||||||
|  | section_106="\x06\x01" | ||||||
|  | section_107="\x07\x01" | ||||||
|  | section_10D="\x0d\x01" | ||||||
|  | section_10E="\x0e\x01" | ||||||
|  | section_10F="\x0f\x01" | ||||||
|  | section_110="\x10\x01" | ||||||
|  | section_111="\x11\x01" | ||||||
|  | section_112="\x12\x01" | ||||||
|  | section_115="\x15\x01" | ||||||
|  | section_116="\x16\x01" | ||||||
|  | section_117="\x17\x01" | ||||||
|  | section_11A="\x1a\x01" | ||||||
|  | section_11B="\x1b\x01" | ||||||
|  | section_11C="\x1c\x01" | ||||||
|  | section_11D="\x1d\x01" | ||||||
|  | section_11E="\x1e\x01" | ||||||
|  | section_11F="\x1f\x01" | ||||||
|  | section_122="\"\x01" | ||||||
|  | section_123="#\x01" | ||||||
|  | section_124="$\x01" | ||||||
|  | section_125="%\x01" | ||||||
|  | section_128="(\x01" | ||||||
|  | section_129=")\x01" | ||||||
|  | section_12D="-\x01" | ||||||
|  | section_131="1\x01" | ||||||
|  | section_132="2\x01" | ||||||
|  | section_13B=";\x01" | ||||||
|  | section_13C="<\x01" | ||||||
|  | section_13D="=\x01" | ||||||
|  | section_13E=">\x01" | ||||||
|  | section_13F="?\x01" | ||||||
|  | section_140="@\x01" | ||||||
|  | section_FE="\xfe\x00" | ||||||
|  | section_FF="\xff\x00" | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for WebP images | ||||||
|  | # ------------------------------ | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | header_RIFF="RIFF" | ||||||
|  | header_WEBP="WEBP" | ||||||
|  | 
 | ||||||
|  | section_ALPH="ALPH" | ||||||
|  | section_ANIM="ANIM" | ||||||
|  | section_ANMF="ANMF" | ||||||
|  | section_EXIF="EXIF" | ||||||
|  | section_FRGM="FRGM" | ||||||
|  | section_ICCP="ICCP" | ||||||
|  | section_VP8="VP8 " | ||||||
|  | section_VP8L="VP8L" | ||||||
|  | section_VP8X="VP8X" | ||||||
|  | section_XMP="XMP " | ||||||
| @ -0,0 +1,72 @@ | |||||||
|  | # | ||||||
|  | # AFL dictionary for XML | ||||||
|  | # ---------------------- | ||||||
|  | # | ||||||
|  | # Several basic syntax elements and attributes, modeled on libxml2. | ||||||
|  | # | ||||||
|  | # Created by Michal Zalewski <lcamtuf@google.com> | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | attr_encoding=" encoding=\"1\"" | ||||||
|  | attr_generic=" a=\"1\"" | ||||||
|  | attr_href=" href=\"1\"" | ||||||
|  | attr_standalone=" standalone=\"no\"" | ||||||
|  | attr_version=" version=\"1\"" | ||||||
|  | attr_xml_base=" xml:base=\"1\"" | ||||||
|  | attr_xml_id=" xml:id=\"1\"" | ||||||
|  | attr_xml_lang=" xml:lang=\"1\"" | ||||||
|  | attr_xml_space=" xml:space=\"1\"" | ||||||
|  | attr_xmlns=" xmlns=\"1\"" | ||||||
|  | 
 | ||||||
|  | entity_builtin="<" | ||||||
|  | entity_decimal="" | ||||||
|  | entity_external="&a;" | ||||||
|  | entity_hex="" | ||||||
|  | 
 | ||||||
|  | string_any="ANY" | ||||||
|  | string_brackets="[]" | ||||||
|  | string_cdata="CDATA" | ||||||
|  | string_col_fallback=":fallback" | ||||||
|  | string_col_generic=":a" | ||||||
|  | string_col_include=":include" | ||||||
|  | string_dashes="--" | ||||||
|  | string_empty="EMPTY" | ||||||
|  | string_empty_dblquotes="\"\"" | ||||||
|  | string_empty_quotes="''" | ||||||
|  | string_entities="ENTITIES" | ||||||
|  | string_entity="ENTITY" | ||||||
|  | string_fixed="#FIXED" | ||||||
|  | string_id="ID" | ||||||
|  | string_idref="IDREF" | ||||||
|  | string_idrefs="IDREFS" | ||||||
|  | string_implied="#IMPLIED" | ||||||
|  | string_nmtoken="NMTOKEN" | ||||||
|  | string_nmtokens="NMTOKENS" | ||||||
|  | string_notation="NOTATION" | ||||||
|  | string_parentheses="()" | ||||||
|  | string_pcdata="#PCDATA" | ||||||
|  | string_percent="%a" | ||||||
|  | string_public="PUBLIC" | ||||||
|  | string_required="#REQUIRED" | ||||||
|  | string_schema=":schema" | ||||||
|  | string_system="SYSTEM" | ||||||
|  | string_ucs4="UCS-4" | ||||||
|  | string_utf16="UTF-16" | ||||||
|  | string_utf8="UTF-8" | ||||||
|  | string_xmlns="xmlns:" | ||||||
|  | 
 | ||||||
|  | tag_attlist="<!ATTLIST" | ||||||
|  | tag_cdata="<![CDATA[" | ||||||
|  | tag_close="</a>" | ||||||
|  | tag_doctype="<!DOCTYPE" | ||||||
|  | tag_element="<!ELEMENT" | ||||||
|  | tag_entity="<!ENTITY" | ||||||
|  | tag_ignore="<![IGNORE[" | ||||||
|  | tag_include="<![INCLUDE[" | ||||||
|  | tag_notation="<!NOTATION" | ||||||
|  | tag_open="<a>" | ||||||
|  | tag_open_close="<a />" | ||||||
|  | tag_open_exclamation="<!" | ||||||
|  | tag_open_q="<?" | ||||||
|  | tag_sq2_close="]]>" | ||||||
|  | tag_xml_q="<?xml?>" | ||||||
| @ -0,0 +1,202 @@ | |||||||
|  | 
 | ||||||
|  |                                  Apache License | ||||||
|  |                            Version 2.0, January 2004 | ||||||
|  |                         http://www.apache.org/licenses/ | ||||||
|  | 
 | ||||||
|  |    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  | 
 | ||||||
|  |    1. Definitions. | ||||||
|  | 
 | ||||||
|  |       "License" shall mean the terms and conditions for use, reproduction, | ||||||
|  |       and distribution as defined by Sections 1 through 9 of this document. | ||||||
|  | 
 | ||||||
|  |       "Licensor" shall mean the copyright owner or entity authorized by | ||||||
|  |       the copyright owner that is granting the License. | ||||||
|  | 
 | ||||||
|  |       "Legal Entity" shall mean the union of the acting entity and all | ||||||
|  |       other entities that control, are controlled by, or are under common | ||||||
|  |       control with that entity. For the purposes of this definition, | ||||||
|  |       "control" means (i) the power, direct or indirect, to cause the | ||||||
|  |       direction or management of such entity, whether by contract or | ||||||
|  |       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||||
|  |       outstanding shares, or (iii) beneficial ownership of such entity. | ||||||
|  | 
 | ||||||
|  |       "You" (or "Your") shall mean an individual or Legal Entity | ||||||
|  |       exercising permissions granted by this License. | ||||||
|  | 
 | ||||||
|  |       "Source" form shall mean the preferred form for making modifications, | ||||||
|  |       including but not limited to software source code, documentation | ||||||
|  |       source, and configuration files. | ||||||
|  | 
 | ||||||
|  |       "Object" form shall mean any form resulting from mechanical | ||||||
|  |       transformation or translation of a Source form, including but | ||||||
|  |       not limited to compiled object code, generated documentation, | ||||||
|  |       and conversions to other media types. | ||||||
|  | 
 | ||||||
|  |       "Work" shall mean the work of authorship, whether in Source or | ||||||
|  |       Object form, made available under the License, as indicated by a | ||||||
|  |       copyright notice that is included in or attached to the work | ||||||
|  |       (an example is provided in the Appendix below). | ||||||
|  | 
 | ||||||
|  |       "Derivative Works" shall mean any work, whether in Source or Object | ||||||
|  |       form, that is based on (or derived from) the Work and for which the | ||||||
|  |       editorial revisions, annotations, elaborations, or other modifications | ||||||
|  |       represent, as a whole, an original work of authorship. For the purposes | ||||||
|  |       of this License, Derivative Works shall not include works that remain | ||||||
|  |       separable from, or merely link (or bind by name) to the interfaces of, | ||||||
|  |       the Work and Derivative Works thereof. | ||||||
|  | 
 | ||||||
|  |       "Contribution" shall mean any work of authorship, including | ||||||
|  |       the original version of the Work and any modifications or additions | ||||||
|  |       to that Work or Derivative Works thereof, that is intentionally | ||||||
|  |       submitted to Licensor for inclusion in the Work by the copyright owner | ||||||
|  |       or by an individual or Legal Entity authorized to submit on behalf of | ||||||
|  |       the copyright owner. For the purposes of this definition, "submitted" | ||||||
|  |       means any form of electronic, verbal, or written communication sent | ||||||
|  |       to the Licensor or its representatives, including but not limited to | ||||||
|  |       communication on electronic mailing lists, source code control systems, | ||||||
|  |       and issue tracking systems that are managed by, or on behalf of, the | ||||||
|  |       Licensor for the purpose of discussing and improving the Work, but | ||||||
|  |       excluding communication that is conspicuously marked or otherwise | ||||||
|  |       designated in writing by the copyright owner as "Not a Contribution." | ||||||
|  | 
 | ||||||
|  |       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||||
|  |       on behalf of whom a Contribution has been received by Licensor and | ||||||
|  |       subsequently incorporated within the Work. | ||||||
|  | 
 | ||||||
|  |    2. Grant of Copyright License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       copyright license to reproduce, prepare Derivative Works of, | ||||||
|  |       publicly display, publicly perform, sublicense, and distribute the | ||||||
|  |       Work and such Derivative Works in Source or Object form. | ||||||
|  | 
 | ||||||
|  |    3. Grant of Patent License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       (except as stated in this section) patent license to make, have made, | ||||||
|  |       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||||
|  |       where such license applies only to those patent claims licensable | ||||||
|  |       by such Contributor that are necessarily infringed by their | ||||||
|  |       Contribution(s) alone or by combination of their Contribution(s) | ||||||
|  |       with the Work to which such Contribution(s) was submitted. If You | ||||||
|  |       institute patent litigation against any entity (including a | ||||||
|  |       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||||
|  |       or a Contribution incorporated within the Work constitutes direct | ||||||
|  |       or contributory patent infringement, then any patent licenses | ||||||
|  |       granted to You under this License for that Work shall terminate | ||||||
|  |       as of the date such litigation is filed. | ||||||
|  | 
 | ||||||
|  |    4. Redistribution. You may reproduce and distribute copies of the | ||||||
|  |       Work or Derivative Works thereof in any medium, with or without | ||||||
|  |       modifications, and in Source or Object form, provided that You | ||||||
|  |       meet the following conditions: | ||||||
|  | 
 | ||||||
|  |       (a) You must give any other recipients of the Work or | ||||||
|  |           Derivative Works a copy of this License; and | ||||||
|  | 
 | ||||||
|  |       (b) You must cause any modified files to carry prominent notices | ||||||
|  |           stating that You changed the files; and | ||||||
|  | 
 | ||||||
|  |       (c) You must retain, in the Source form of any Derivative Works | ||||||
|  |           that You distribute, all copyright, patent, trademark, and | ||||||
|  |           attribution notices from the Source form of the Work, | ||||||
|  |           excluding those notices that do not pertain to any part of | ||||||
|  |           the Derivative Works; and | ||||||
|  | 
 | ||||||
|  |       (d) If the Work includes a "NOTICE" text file as part of its | ||||||
|  |           distribution, then any Derivative Works that You distribute must | ||||||
|  |           include a readable copy of the attribution notices contained | ||||||
|  |           within such NOTICE file, excluding those notices that do not | ||||||
|  |           pertain to any part of the Derivative Works, in at least one | ||||||
|  |           of the following places: within a NOTICE text file distributed | ||||||
|  |           as part of the Derivative Works; within the Source form or | ||||||
|  |           documentation, if provided along with the Derivative Works; or, | ||||||
|  |           within a display generated by the Derivative Works, if and | ||||||
|  |           wherever such third-party notices normally appear. The contents | ||||||
|  |           of the NOTICE file are for informational purposes only and | ||||||
|  |           do not modify the License. You may add Your own attribution | ||||||
|  |           notices within Derivative Works that You distribute, alongside | ||||||
|  |           or as an addendum to the NOTICE text from the Work, provided | ||||||
|  |           that such additional attribution notices cannot be construed | ||||||
|  |           as modifying the License. | ||||||
|  | 
 | ||||||
|  |       You may add Your own copyright statement to Your modifications and | ||||||
|  |       may provide additional or different license terms and conditions | ||||||
|  |       for use, reproduction, or distribution of Your modifications, or | ||||||
|  |       for any such Derivative Works as a whole, provided Your use, | ||||||
|  |       reproduction, and distribution of the Work otherwise complies with | ||||||
|  |       the conditions stated in this License. | ||||||
|  | 
 | ||||||
|  |    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||||
|  |       any Contribution intentionally submitted for inclusion in the Work | ||||||
|  |       by You to the Licensor shall be under the terms and conditions of | ||||||
|  |       this License, without any additional terms or conditions. | ||||||
|  |       Notwithstanding the above, nothing herein shall supersede or modify | ||||||
|  |       the terms of any separate license agreement you may have executed | ||||||
|  |       with Licensor regarding such Contributions. | ||||||
|  | 
 | ||||||
|  |    6. Trademarks. This License does not grant permission to use the trade | ||||||
|  |       names, trademarks, service marks, or product names of the Licensor, | ||||||
|  |       except as required for reasonable and customary use in describing the | ||||||
|  |       origin of the Work and reproducing the content of the NOTICE file. | ||||||
|  | 
 | ||||||
|  |    7. Disclaimer of Warranty. Unless required by applicable law or | ||||||
|  |       agreed to in writing, Licensor provides the Work (and each | ||||||
|  |       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||||
|  |       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||||
|  |       implied, including, without limitation, any warranties or conditions | ||||||
|  |       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||||
|  |       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||||
|  |       appropriateness of using or redistributing the Work and assume any | ||||||
|  |       risks associated with Your exercise of permissions under this License. | ||||||
|  | 
 | ||||||
|  |    8. Limitation of Liability. In no event and under no legal theory, | ||||||
|  |       whether in tort (including negligence), contract, or otherwise, | ||||||
|  |       unless required by applicable law (such as deliberate and grossly | ||||||
|  |       negligent acts) or agreed to in writing, shall any Contributor be | ||||||
|  |       liable to You for damages, including any direct, indirect, special, | ||||||
|  |       incidental, or consequential damages of any character arising as a | ||||||
|  |       result of this License or out of the use or inability to use the | ||||||
|  |       Work (including but not limited to damages for loss of goodwill, | ||||||
|  |       work stoppage, computer failure or malfunction, or any and all | ||||||
|  |       other commercial damages or losses), even if such Contributor | ||||||
|  |       has been advised of the possibility of such damages. | ||||||
|  | 
 | ||||||
|  |    9. Accepting Warranty or Additional Liability. While redistributing | ||||||
|  |       the Work or Derivative Works thereof, You may choose to offer, | ||||||
|  |       and charge a fee for, acceptance of support, warranty, indemnity, | ||||||
|  |       or other liability obligations and/or rights consistent with this | ||||||
|  |       License. However, in accepting such obligations, You may act only | ||||||
|  |       on Your own behalf and on Your sole responsibility, not on behalf | ||||||
|  |       of any other Contributor, and only if You agree to indemnify, | ||||||
|  |       defend, and hold each Contributor harmless for any liability | ||||||
|  |       incurred by, or claims asserted against, such Contributor by reason | ||||||
|  |       of your accepting any such warranty or additional liability. | ||||||
|  | 
 | ||||||
|  |    END OF TERMS AND CONDITIONS | ||||||
|  | 
 | ||||||
|  |    APPENDIX: How to apply the Apache License to your work. | ||||||
|  | 
 | ||||||
|  |       To apply the Apache License to your work, attach the following | ||||||
|  |       boilerplate notice, with the fields enclosed by brackets "[]" | ||||||
|  |       replaced with your own identifying information. (Don't include | ||||||
|  |       the brackets!)  The text should be enclosed in the appropriate | ||||||
|  |       comment syntax for the file format. We also recommend that a | ||||||
|  |       file or class name and description of purpose be included on the | ||||||
|  |       same "printed page" as the copyright notice for easier | ||||||
|  |       identification within third-party archives. | ||||||
|  | 
 | ||||||
|  |    Copyright [yyyy] [name of copyright owner] | ||||||
|  | 
 | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | 
 | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
| @ -0,0 +1,183 @@ | |||||||
|  | ========================= | ||||||
|  | Installation instructions | ||||||
|  | ========================= | ||||||
|  | 
 | ||||||
|  |   This document provides basic installation instructions and discusses known | ||||||
|  |   issues for a variety of platforms. See README for the general instruction | ||||||
|  |   manual. | ||||||
|  | 
 | ||||||
|  | 1) Linux on x86 | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | This platform is expected to work well. Compile the program with: | ||||||
|  | 
 | ||||||
|  | $ make | ||||||
|  | 
 | ||||||
|  | You can start using the fuzzer without installation, but it is also possible to | ||||||
|  | install it with: | ||||||
|  | 
 | ||||||
|  | # make install | ||||||
|  | 
 | ||||||
|  | There are no special dependencies to speak of; you will need GNU make and a | ||||||
|  | working compiler (gcc or clang). Some of the optional scripts bundled with the | ||||||
|  | program may depend on bash, gdb, and similar basic tools. | ||||||
|  | 
 | ||||||
|  | If you are using clang, please review llvm_mode/README.llvm; the LLVM | ||||||
|  | integration mode can offer substantial performance gains compared to the | ||||||
|  | traditional approach. | ||||||
|  | 
 | ||||||
|  | You may have to change several settings to get optimal results (most notably, | ||||||
|  | disable crash reporting utilities and switch to a different CPU governor), but | ||||||
|  | afl-fuzz will guide you through that if necessary. | ||||||
|  | 
 | ||||||
|  | 2) OpenBSD, FreeBSD, NetBSD on x86 | ||||||
|  | ---------------------------------- | ||||||
|  | 
 | ||||||
|  | Similarly to Linux, these platforms are expected to work well and are | ||||||
|  | regularly tested. Compile everything with GNU make: | ||||||
|  | 
 | ||||||
|  | $ gmake | ||||||
|  | 
 | ||||||
|  | Note that BSD make will *not* work; if you do not have gmake on your system, | ||||||
|  | please install it first. As on Linux, you can use the fuzzer itself without | ||||||
|  | installation, or install it with: | ||||||
|  | 
 | ||||||
|  | # gmake install | ||||||
|  | 
 | ||||||
|  | Keep in mind that if you are using csh as your shell, the syntax of some of the | ||||||
|  | shell commands given in the README and other docs will be different. | ||||||
|  | 
 | ||||||
|  | The llvm_mode requires a dynamically linked, fully-operational installation of | ||||||
|  | clang. At least on FreeBSD, the clang binaries are static and do not include | ||||||
|  | some of the essential tools, so if you want to make it work, you may need to | ||||||
|  | follow the instructions in llvm_mode/README.llvm. | ||||||
|  | 
 | ||||||
|  | Beyond that, everything should work as advertised. | ||||||
|  | 
 | ||||||
|  | The QEMU mode is currently supported only on Linux. I think it's just a QEMU | ||||||
|  | problem, I couldn't get a vanilla copy of user-mode emulation support working | ||||||
|  | correctly on BSD at all. | ||||||
|  | 
 | ||||||
|  | 3) MacOS X on x86 | ||||||
|  | ----------------- | ||||||
|  | 
 | ||||||
|  | MacOS X should work, but there are some gotchas due to the idiosyncrasies of | ||||||
|  | the platform. On top of this, I have limited release testing capabilities | ||||||
|  | and depend mostly on user feedback. | ||||||
|  | 
 | ||||||
|  | To build AFL, install Xcode and follow the general instructions for Linux. | ||||||
|  | 
 | ||||||
|  | The Xcode 'gcc' tool is just a wrapper for clang, so be sure to use afl-clang | ||||||
|  | to compile any instrumented binaries; afl-gcc will fail unless you have GCC | ||||||
|  | installed from another source (in which case, please specify AFL_CC and | ||||||
|  | AFL_CXX to point to the "real" GCC binaries). | ||||||
|  | 
 | ||||||
|  | Only 64-bit compilation will work on the platform; porting the 32-bit | ||||||
|  | instrumentation would require a fair amount of work due to the way OS X | ||||||
|  | handles relocations, and today, virtually all MacOS X boxes are 64-bit. | ||||||
|  | 
 | ||||||
|  | The crash reporting daemon that comes by default with MacOS X will cause | ||||||
|  | problems with fuzzing. You need to turn it off by following the instructions | ||||||
|  | provided here: http://goo.gl/CCcd5u | ||||||
|  | 
 | ||||||
|  | The fork() semantics on OS X are a bit unusual compared to other unix systems | ||||||
|  | and definitely don't look POSIX-compliant. This means two things: | ||||||
|  | 
 | ||||||
|  |   - Fuzzing will be probably slower than on Linux. In fact, some folks report | ||||||
|  |     considerable performance gains by running the jobs inside a Linux VM on | ||||||
|  |     MacOS X. | ||||||
|  | 
 | ||||||
|  |   - Some non-portable, platform-specific code may be incompatible with the | ||||||
|  |     AFL forkserver. If you run into any problems, set AFL_NO_FORKSRV=1 in the | ||||||
|  |     environment before starting afl-fuzz. | ||||||
|  | 
 | ||||||
|  | User emulation mode of QEMU does not appear to be supported on MacOS X, so | ||||||
|  | black-box instrumentation mode (-Q) will not work. | ||||||
|  | 
 | ||||||
|  | The llvm_mode requires a fully-operational installation of clang. The one that | ||||||
|  | comes with Xcode is missing some of the essential headers and helper tools. | ||||||
|  | See llvm_mode/README.llvm for advice on how to build the compiler from scratch. | ||||||
|  | 
 | ||||||
|  | 4) Linux or *BSD on non-x86 systems | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  | Standard build will fail on non-x86 systems, but you should be able to | ||||||
|  | leverage two other options: | ||||||
|  | 
 | ||||||
|  |   - The LLVM mode (see llvm_mode/README.llvm), which does not rely on | ||||||
|  |     x86-specific assembly shims. It's fast and robust, but requires a | ||||||
|  |     complete installation of clang. | ||||||
|  | 
 | ||||||
|  |   - The QEMU mode (see qemu_mode/README.qemu), which can be also used for | ||||||
|  |     fuzzing cross-platform binaries. It's slower and more fragile, but | ||||||
|  |     can be used even when you don't have the source for the tested app. | ||||||
|  | 
 | ||||||
|  | If you're not sure what you need, you need the LLVM mode. To get it, try: | ||||||
|  | 
 | ||||||
|  | $ AFL_NO_X86=1 gmake && gmake -C llvm_mode | ||||||
|  | 
 | ||||||
|  | ...and compile your target program with afl-clang-fast or afl-clang-fast++ | ||||||
|  | instead of the traditional afl-gcc or afl-clang wrappers. | ||||||
|  | 
 | ||||||
|  | 5) Solaris on x86 | ||||||
|  | ----------------- | ||||||
|  | 
 | ||||||
|  | The fuzzer reportedly works on Solaris, but I have not tested this first-hand, | ||||||
|  | and the user base is fairly small, so I don't have a lot of feedback. | ||||||
|  | 
 | ||||||
|  | To get the ball rolling, you will need to use GNU make and GCC or clang. I'm | ||||||
|  | being told that the stock version of GCC that comes with the platform does not | ||||||
|  | work properly due to its reliance on a hardcoded location for 'as' (completely | ||||||
|  | ignoring the -B parameter or $PATH). | ||||||
|  | 
 | ||||||
|  | To fix this, you may want to build stock GCC from the source, like so: | ||||||
|  | 
 | ||||||
|  | $ ./configure --prefix=$HOME/gcc --with-gnu-as --with-gnu-ld \ | ||||||
|  |   --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr | ||||||
|  | $ make | ||||||
|  | $ sudo make install | ||||||
|  | 
 | ||||||
|  | Do *not* specify --with-as=/usr/gnu/bin/as - this will produce a GCC binary that | ||||||
|  | ignores the -B flag and you will be back to square one. | ||||||
|  | 
 | ||||||
|  | Note that Solaris reportedly comes with crash reporting enabled, which causes | ||||||
|  | problems with crashes being misinterpreted as hangs, similarly to the gotchas | ||||||
|  | for Linux and MacOS X. AFL does not auto-detect crash reporting on this | ||||||
|  | particular platform, but you may need to run the following command: | ||||||
|  | 
 | ||||||
|  | $ coreadm -d global -d global-setid -d process -d proc-setid \ | ||||||
|  |   -d kzone -d log | ||||||
|  | 
 | ||||||
|  | User emulation mode of QEMU is not available on Solaris, so black-box | ||||||
|  | instrumentation mode (-Q) will not work. | ||||||
|  | 
 | ||||||
|  | 6) Everything else | ||||||
|  | ------------------ | ||||||
|  | 
 | ||||||
|  | You're on your own. On POSIX-compliant systems, you may be able to compile and | ||||||
|  | run the fuzzer; and the LLVM mode may offer a way to instrument non-x86 code. | ||||||
|  | 
 | ||||||
|  | The fuzzer will not run on Windows. It will also not work under Cygwin. It | ||||||
|  | could be ported to the latter platform fairly easily, but it's a pretty bad | ||||||
|  | idea, because Cygwin is extremely slow. It makes much more sense to use | ||||||
|  | VirtualBox or so to run a hardware-accelerated Linux VM; it will run around | ||||||
|  | 20x faster or so. If you have a *really* compelling use case for Cygwin, let | ||||||
|  | me know. | ||||||
|  | 
 | ||||||
|  | Although Android on x86 should theoretically work, the stock kernel may have | ||||||
|  | SHM support compiled out, and if so, you may have to address that issue first. | ||||||
|  | It's possible that all you need is this workaround: | ||||||
|  | 
 | ||||||
|  |   https://github.com/pelya/android-shmem | ||||||
|  | 
 | ||||||
|  | Joshua J. Drake notes that the Android linker adds a shim that automatically | ||||||
|  | intercepts SIGSEGV and related signals. To fix this issue and be able to see | ||||||
|  | crashes, you need to put this at the beginning of the fuzzed program: | ||||||
|  | 
 | ||||||
|  |   signal(SIGILL, SIG_DFL); | ||||||
|  |   signal(SIGABRT, SIG_DFL); | ||||||
|  |   signal(SIGBUS, SIG_DFL); | ||||||
|  |   signal(SIGFPE, SIG_DFL); | ||||||
|  |   signal(SIGSEGV, SIG_DFL); | ||||||
|  | 
 | ||||||
|  | You may need to #include <signal.h> first. | ||||||
| @ -0,0 +1,49 @@ | |||||||
|  | ===================== | ||||||
|  | AFL quick start guide | ||||||
|  | ===================== | ||||||
|  | 
 | ||||||
|  | You should read docs/README. It's pretty short. If you really can't, here's | ||||||
|  | how to hit the ground running: | ||||||
|  | 
 | ||||||
|  | 1) Compile AFL with 'make'. If build fails, see docs/INSTALL for tips. | ||||||
|  | 
 | ||||||
|  | 2) Find or write a reasonably fast and simple program that takes data from | ||||||
|  |    a file or stdin, processes it in a test-worthy way, then exits cleanly. | ||||||
|  |    If testing a network service, modify it to run in the foreground and read | ||||||
|  |    from stdin. When fuzzing a format that uses checksums, comment out the | ||||||
|  |    checksum verification code, too. | ||||||
|  | 
 | ||||||
|  |    The program must crash properly when a fault is encountered. Watch out for | ||||||
|  |    custom SIGSEGV or SIGABRT handlers and background processes. For tips on | ||||||
|  |    detecting non-crashing flaws, see section 11 in docs/README. | ||||||
|  | 
 | ||||||
|  | 3) Compile the program / library to be fuzzed using afl-gcc. A common way to | ||||||
|  |    do this would be: | ||||||
|  | 
 | ||||||
|  |    CC=/path/to/afl-gcc CXX=/path/to/afl-g++ ./configure --disable-shared | ||||||
|  |    make clean all | ||||||
|  | 
 | ||||||
|  |    If program build fails, ping <afl-users@googlegroups.com>. | ||||||
|  | 
 | ||||||
|  | 4) Get a small but valid input file that makes sense to the program. When | ||||||
|  |    fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in | ||||||
|  |    dictionaries/README.dictionaries, too. | ||||||
|  | 
 | ||||||
|  | 5) If the program reads from stdin, run 'afl-fuzz' like so: | ||||||
|  | 
 | ||||||
|  |    ./afl-fuzz -i testcase_dir -o findings_dir -- \ | ||||||
|  |      /path/to/tested/program [...program's cmdline...] | ||||||
|  | 
 | ||||||
|  |    If the program takes input from a file, you can put @@ in the program's | ||||||
|  |    command line; AFL will put an auto-generated file name in there for you. | ||||||
|  | 
 | ||||||
|  | 6) Investigate anything shown in red in the fuzzer UI by promptly consulting | ||||||
|  |    docs/status_screen.txt. | ||||||
|  | 
 | ||||||
|  | That's it. Sit back, relax, and - time permitting - try to skim through the | ||||||
|  | following files: | ||||||
|  | 
 | ||||||
|  |   - docs/README               - A general introduction to AFL, | ||||||
|  |   - docs/perf_tips.txt        - Simple tips on how to fuzz more quickly, | ||||||
|  |   - docs/status_screen.txt    - An explanation of the tidbits shown in the UI, | ||||||
|  |   - docs/parallel_fuzzing.txt - Advice on running AFL on multiple cores. | ||||||
| @ -0,0 +1,281 @@ | |||||||
|  | ======================= | ||||||
|  | Environmental variables | ||||||
|  | ======================= | ||||||
|  | 
 | ||||||
|  |   This document discusses the environment variables used by American Fuzzy Lop | ||||||
|  |   to expose various exotic functions that may be (rarely) useful for power | ||||||
|  |   users or for some types of custom fuzzing setups. See README for the general | ||||||
|  |   instruction manual. | ||||||
|  | 
 | ||||||
|  | 1) Settings for afl-gcc, afl-clang, and afl-as | ||||||
|  | ---------------------------------------------- | ||||||
|  | 
 | ||||||
|  | Because they can't directly accept command-line options, the compile-time | ||||||
|  | tools make fairly broad use of environmental variables: | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_HARDEN automatically adds code hardening options when invoking | ||||||
|  |     the downstream compiler. This currently includes -D_FORTIFY_SOURCE=2 and | ||||||
|  |     -fstack-protector-all. The setting is useful for catching non-crashing | ||||||
|  |     memory bugs at the expense of a very slight (sub-5%) performance loss. | ||||||
|  | 
 | ||||||
|  |   - By default, the wrapper appends -O3 to optimize builds. Very rarely, this | ||||||
|  |     will cause problems in programs built with -Werror, simply because -O3 | ||||||
|  |     enables more thorough code analysis and can spew out additional warnings. | ||||||
|  |     To disable optimizations, set AFL_DONT_OPTIMIZE. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_USE_ASAN automatically enables ASAN, provided that your | ||||||
|  |     compiler supports that. Note that fuzzing with ASAN is mildly challenging | ||||||
|  |     - see notes_for_asan.txt. | ||||||
|  | 
 | ||||||
|  |     (You can also enable MSAN via AFL_USE_MSAN; ASAN and MSAN come with the | ||||||
|  |     same gotchas; the modes are mutually exclusive. UBSAN and other exotic | ||||||
|  |     sanitizers are not officially supported yet, but are easy to get to work | ||||||
|  |     by hand.) | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_CC, AFL_CXX, and AFL_AS lets you use alternate downstream | ||||||
|  |     compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries | ||||||
|  |     in your $PATH. | ||||||
|  | 
 | ||||||
|  |   - AFL_PATH can be used to point afl-gcc to an alternate location of afl-as. | ||||||
|  |     One possible use of this is experimental/clang_asm_normalize/, which lets | ||||||
|  |     you instrument hand-written assembly when compiling clang code by plugging | ||||||
|  |     a normalizer into the chain. (There is no equivalent feature for GCC.) | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_INST_RATIO to a percentage between 0 and 100% controls the | ||||||
|  |     probability of instrumenting every branch. This is (very rarely) useful | ||||||
|  |     when dealing with exceptionally complex programs that saturate the output | ||||||
|  |     bitmap. Examples include v8, ffmpeg, and perl. | ||||||
|  | 
 | ||||||
|  |     (If this ever happens, afl-fuzz will warn you ahead of the time by | ||||||
|  |     displaying the "bitmap density" field in fiery red.) | ||||||
|  | 
 | ||||||
|  |     Setting AFL_INST_RATIO to 0 is a valid choice. This will instrument only | ||||||
|  |     the transitions between function entry points, but not individual branches. | ||||||
|  | 
 | ||||||
|  |   - AFL_NO_BUILTIN causes the compiler to generate code suitable for use with | ||||||
|  |     libtokencap.so (but perhaps running a bit slower than without the flag). | ||||||
|  | 
 | ||||||
|  |   - TMPDIR is used by afl-as for temporary files; if this variable is not set, | ||||||
|  |     the tool defaults to /tmp. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_KEEP_ASSEMBLY prevents afl-as from deleting instrumented | ||||||
|  |     assembly files. Useful for troubleshooting problems or understanding how | ||||||
|  |     the tool works. To get them in a predictable place, try something like: | ||||||
|  | 
 | ||||||
|  |     mkdir assembly_here | ||||||
|  |     TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_QUIET will prevent afl-cc and afl-as banners from being | ||||||
|  |     displayed during compilation, in case you find them distracting. | ||||||
|  | 
 | ||||||
|  | 2) Settings for afl-clang-fast | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  | The native LLVM instrumentation helper accepts a subset of the settings | ||||||
|  | discussed in section #1, with the exception of: | ||||||
|  | 
 | ||||||
|  |   - AFL_AS, since this toolchain does not directly invoke GNU as. | ||||||
|  | 
 | ||||||
|  |   - TMPDIR and AFL_KEEP_ASSEMBLY, since no temporary assembly files are | ||||||
|  |     created. | ||||||
|  | 
 | ||||||
|  | Note that AFL_INST_RATIO will behave a bit differently than for afl-gcc, | ||||||
|  | because functions are *not* instrumented unconditionally - so low values | ||||||
|  | will have a more striking effect. For this tool, 0 is not a valid choice. | ||||||
|  | 
 | ||||||
|  | 3) Settings for afl-fuzz | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | The main fuzzer binary accepts several options that disable a couple of sanity | ||||||
|  | checks or alter some of the more exotic semantics of the tool: | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_SKIP_CPUFREQ skips the check for CPU scaling policy. This is | ||||||
|  |     useful if you can't change the defaults (e.g., no root access to the | ||||||
|  |     system) and are OK with some performance loss. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_NO_FORKSRV disables the forkserver optimization, reverting to | ||||||
|  |     fork + execve() call for every tested input. This is useful mostly when | ||||||
|  |     working with unruly libraries that create threads or do other crazy | ||||||
|  |     things when initializing (before the instrumentation has a chance to run). | ||||||
|  | 
 | ||||||
|  |     Note that this setting inhibits some of the user-friendly diagnostics | ||||||
|  |     normally done when starting up the forkserver and causes a pretty | ||||||
|  |     significant performance drop. | ||||||
|  | 
 | ||||||
|  |   - AFL_EXIT_WHEN_DONE causes afl-fuzz to terminate when all existing paths | ||||||
|  |     have been fuzzed and there were no new finds for a while. This would be | ||||||
|  |     normally indicated by the cycle counter in the UI turning green. May be | ||||||
|  |     convenient for some types of automated jobs. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_NO_AFFINITY disables attempts to bind to a specific CPU core | ||||||
|  |     on Linux systems. This slows things down, but lets you run more instances | ||||||
|  |     of afl-fuzz than would be prudent (if you really want to). | ||||||
|  | 
 | ||||||
|  |   - AFL_SKIP_CRASHES causes AFL to tolerate crashing files in the input | ||||||
|  |     queue. This can help with rare situations where a program crashes only | ||||||
|  |     intermittently, but it's not really recommended under normal operating | ||||||
|  |     conditions. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_HANG_TMOUT allows you to specify a different timeout for | ||||||
|  |     deciding if a particular test case is a "hang". The default is 1 second | ||||||
|  |     or the value of the -t parameter, whichever is larger. Dialing the value | ||||||
|  |     down can be useful if you are very concerned about slow inputs, or if you | ||||||
|  |     don't want AFL to spend too much time classifying that stuff and just  | ||||||
|  |     rapidly put all timeouts in that bin. | ||||||
|  | 
 | ||||||
|  |   - AFL_NO_ARITH causes AFL to skip most of the deterministic arithmetics. | ||||||
|  |     This can be useful to speed up the fuzzing of text-based file formats. | ||||||
|  | 
 | ||||||
|  |   - AFL_SHUFFLE_QUEUE randomly reorders the input queue on startup. Requested | ||||||
|  |     by some users for unorthodox parallelized fuzzing setups, but not | ||||||
|  |     advisable otherwise. | ||||||
|  | 
 | ||||||
|  |   - When developing custom instrumentation on top of afl-fuzz, you can use | ||||||
|  |     AFL_SKIP_BIN_CHECK to inhibit the checks for non-instrumented binaries | ||||||
|  |     and shell scripts; and AFL_DUMB_FORKSRV in conjunction with the -n | ||||||
|  |     setting to instruct afl-fuzz to still follow the fork server protocol | ||||||
|  |     without expecting any instrumentation data in return. | ||||||
|  | 
 | ||||||
|  |   - When running in the -M or -S mode, setting AFL_IMPORT_FIRST causes the | ||||||
|  |     fuzzer to import test cases from other instances before doing anything | ||||||
|  |     else. This makes the "own finds" counter in the UI more accurate. | ||||||
|  |     Beyond counter aesthetics, not much else should change. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_POST_LIBRARY allows you to configure a postprocessor for | ||||||
|  |     mutated files - say, to fix up checksums. See experimental/post_library/ | ||||||
|  |     for more. | ||||||
|  | 
 | ||||||
|  |   - AFL_FAST_CAL keeps the calibration stage about 2.5x faster (albeit less | ||||||
|  |     precise), which can help when starting a session against a slow target. | ||||||
|  | 
 | ||||||
|  |   - The CPU widget shown at the bottom of the screen is fairly simplistic and | ||||||
|  |     may complain of high load prematurely, especially on systems with low core | ||||||
|  |     counts. To avoid the alarming red color, you can set AFL_NO_CPU_RED. | ||||||
|  | 
 | ||||||
|  |   - In QEMU mode (-Q), AFL_PATH will be searched for afl-qemu-trace. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_PRELOAD causes AFL to set LD_PRELOAD for the target binary | ||||||
|  |     without disrupting the afl-fuzz process itself. This is useful, among other | ||||||
|  |     things, for bootstrapping libdislocator.so. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_NO_UI inhibits the UI altogether, and just periodically prints | ||||||
|  |     some basic stats. This behavior is also automatically triggered when the | ||||||
|  |     output from afl-fuzz is redirected to a file or to a pipe. | ||||||
|  | 
 | ||||||
|  |   - If you are Jakub, you may need AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES. | ||||||
|  |     Others need not apply. | ||||||
|  | 
 | ||||||
|  |   - Benchmarking only: AFL_BENCH_JUST_ONE causes the fuzzer to exit after | ||||||
|  |     processing the first queue entry; and AFL_BENCH_UNTIL_CRASH causes it to | ||||||
|  |     exit soon after the first crash is found. | ||||||
|  | 
 | ||||||
|  | 4) Settings for afl-qemu-trace | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  | The QEMU wrapper used to instrument binary-only code supports several settings: | ||||||
|  | 
 | ||||||
|  |   - It is possible to set AFL_INST_RATIO to skip the instrumentation on some | ||||||
|  |     of the basic blocks, which can be useful when dealing with very complex | ||||||
|  |     binaries. | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_INST_LIBS causes the translator to also instrument the code | ||||||
|  |     inside any dynamically linked libraries (notably including glibc). | ||||||
|  | 
 | ||||||
|  |   - The underlying QEMU binary will recognize any standard "user space | ||||||
|  |     emulation" variables (e.g., QEMU_STACK_SIZE), but there should be no | ||||||
|  |     reason to touch them. | ||||||
|  | 
 | ||||||
|  | 5) Settings for afl-cmin | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | The corpus minimization script offers very little customization: | ||||||
|  | 
 | ||||||
|  |   - Setting AFL_PATH offers a way to specify the location of afl-showmap | ||||||
|  |     and afl-qemu-trace (the latter only in -Q mode). | ||||||
|  | 
 | ||||||
|  |   - AFL_KEEP_TRACES makes the tool keep traces and other metadata used for | ||||||
|  |     minimization and normally deleted at exit. The files can be found in the | ||||||
|  |     <out_dir>/.traces/*. | ||||||
|  | 
 | ||||||
|  |   - AFL_ALLOW_TMP permits this and some other scripts to run in /tmp. This is | ||||||
|  |     a modest security risk on multi-user systems with rogue users, but should | ||||||
|  |     be safe on dedicated fuzzing boxes. | ||||||
|  | 
 | ||||||
|  | 6) Settings for afl-tmin | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | Virtually nothing to play with. Well, in QEMU mode (-Q), AFL_PATH will be | ||||||
|  | searched for afl-qemu-trace. In addition to this, TMPDIR may be used if a | ||||||
|  | temporary file can't be created in the current working directory. | ||||||
|  | 
 | ||||||
|  | You can specify AFL_TMIN_EXACT if you want afl-tmin to require execution paths | ||||||
|  | to match when minimizing crashes. This will make minimization less useful, but | ||||||
|  | may prevent the tool from "jumping" from one crashing condition to another in | ||||||
|  | very buggy software. You probably want to combine it with the -e flag. | ||||||
|  | 
 | ||||||
|  | 7) Settings for afl-analyze | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  | You can set AFL_ANALYZE_HEX to get file offsets printed as hexadecimal instead | ||||||
|  | of decimal. | ||||||
|  | 
 | ||||||
|  | 8) Settings for libdislocator.so | ||||||
|  | -------------------------------- | ||||||
|  | 
 | ||||||
|  | The library honors three environmental variables: | ||||||
|  | 
 | ||||||
|  |   - AFL_LD_LIMIT_MB caps the size of the maximum heap usage permitted by the | ||||||
|  |     library, in megabytes. The default value is 1 GB. Once this is exceeded, | ||||||
|  |     allocations will return NULL. | ||||||
|  | 
 | ||||||
|  |   - AFL_LD_HARD_FAIL alters the behavior by calling abort() on excessive | ||||||
|  |     allocations, thus causing what AFL would perceive as a crash. Useful for | ||||||
|  |     programs that are supposed to maintain a specific memory footprint. | ||||||
|  | 
 | ||||||
|  |   - AFL_LD_VERBOSE causes the library to output some diagnostic messages | ||||||
|  |     that may be useful for pinpointing the cause of any observed issues. | ||||||
|  | 
 | ||||||
|  |   - AFL_LD_NO_CALLOC_OVER inhibits abort() on calloc() overflows. Most | ||||||
|  |     of the common allocators check for that internally and return NULL, so | ||||||
|  |     it's a security risk only in more exotic setups. | ||||||
|  | 
 | ||||||
|  | 9) Settings for libtokencap.so | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  | This library accepts AFL_TOKEN_FILE to indicate the location to which the | ||||||
|  | discovered tokens should be written. | ||||||
|  | 
 | ||||||
|  | 10) Third-party variables set by afl-fuzz & other tools | ||||||
|  | ------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | Several variables are not directly interpreted by afl-fuzz, but are set to | ||||||
|  | optimal values if not already present in the environment: | ||||||
|  | 
 | ||||||
|  |   - By default, LD_BIND_NOW is set to speed up fuzzing by forcing the | ||||||
|  |     linker to do all the work before the fork server kicks in. You can | ||||||
|  |     override this by setting LD_BIND_LAZY beforehand, but it is almost | ||||||
|  |     certainly pointless. | ||||||
|  | 
 | ||||||
|  |   - By default, ASAN_OPTIONS are set to: | ||||||
|  | 
 | ||||||
|  |     abort_on_error=1 | ||||||
|  |     detect_leaks=0 | ||||||
|  |     symbolize=0 | ||||||
|  |     allocator_may_return_null=1 | ||||||
|  | 
 | ||||||
|  |     If you want to set your own options, be sure to include abort_on_error=1 - | ||||||
|  |     otherwise, the fuzzer will not be able to detect crashes in the tested | ||||||
|  |     app. Similarly, include symbolize=0, since without it, AFL may have | ||||||
|  |     difficulty telling crashes and hangs apart. | ||||||
|  | 
 | ||||||
|  |   - In the same vein, by default, MSAN_OPTIONS are set to: | ||||||
|  | 
 | ||||||
|  |     exit_code=86 (required for legacy reasons)     | ||||||
|  |     abort_on_error=1 | ||||||
|  |     symbolize=0 | ||||||
|  |     msan_track_origins=0 | ||||||
|  |     allocator_may_return_null=1 | ||||||
|  | 
 | ||||||
|  |     Be sure to include the first one when customizing anything, since some | ||||||
|  |     MSAN versions don't call abort() on error, and we need a way to detect | ||||||
|  |     faults. | ||||||
| @ -0,0 +1,147 @@ | |||||||
|  | ================ | ||||||
|  | Historical notes | ||||||
|  | ================ | ||||||
|  | 
 | ||||||
|  |   This doc talks about the rationale of some of the high-level design decisions | ||||||
|  |   for American Fuzzy Lop. It's adopted from a discussion with Rob Graham. | ||||||
|  |   See README for the general instruction manual, and technical_details.txt for | ||||||
|  |   additional implementation-level insights. | ||||||
|  | 
 | ||||||
|  | 1) Influences | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | In short, afl-fuzz is inspired chiefly by the work done by Tavis Ormandy back | ||||||
|  | in 2007. Tavis did some very persuasive experiments using gcov block coverage | ||||||
|  | to select optimal test cases out of a large corpus of data, and then using | ||||||
|  | them as a starting point for traditional fuzzing workflows. | ||||||
|  | 
 | ||||||
|  | (By "persuasive", I mean: netting a significant number of interesting | ||||||
|  | vulnerabilities.) | ||||||
|  | 
 | ||||||
|  | In parallel to this, both Tavis and I were interested in evolutionary fuzzing. | ||||||
|  | Tavis had his experiments, and I was working on a tool called bunny-the-fuzzer, | ||||||
|  | released somewhere in 2007. | ||||||
|  | 
 | ||||||
|  | Bunny used a generational algorithm not much different from afl-fuzz, but | ||||||
|  | also tried to reason about the relationship between various input bits and | ||||||
|  | the internal state of the program, with hopes of deriving some additional value | ||||||
|  | from that. The reasoning / correlation part was probably in part inspired by | ||||||
|  | other projects done around the same time by Will Drewry and Chris Evans. | ||||||
|  | 
 | ||||||
|  | The state correlation approach sounded very sexy on paper, but ultimately, made | ||||||
|  | the fuzzer complicated, brittle, and cumbersome to use; every other target | ||||||
|  | program would require a tweak or two. Because Bunny didn't fare a whole lot | ||||||
|  | better than less sophisticated brute-force tools, I eventually decided to write | ||||||
|  | it off. You can still find its original documentation at: | ||||||
|  | 
 | ||||||
|  |   https://code.google.com/p/bunny-the-fuzzer/wiki/BunnyDoc | ||||||
|  | 
 | ||||||
|  | There has been a fair amount of independent work, too. Most notably, a few | ||||||
|  | weeks earlier that year, Jared DeMott had a Defcon presentation about a | ||||||
|  | coverage-driven fuzzer that relied on coverage as a fitness function. | ||||||
|  | 
 | ||||||
|  | Jared's approach was by no means identical to what afl-fuzz does, but it was in | ||||||
|  | the same ballpark. His fuzzer tried to explicitly solve for the maximum coverage | ||||||
|  | with a single input file; in comparison, afl simply selects for cases that do | ||||||
|  | something new (which yields better results - see technical_details.txt). | ||||||
|  | 
 | ||||||
|  | A few years later, Gabriel Campana released fuzzgrind, a tool that relied purely | ||||||
|  | on Valgrind and a constraint solver to maximize coverage without any brute-force | ||||||
|  | bits; and Microsoft Research folks talked extensively about their still | ||||||
|  | non-public, solver-based SAGE framework. | ||||||
|  | 
 | ||||||
|  | In the past six years or so, I've also seen a fair number of academic papers | ||||||
|  | that dealt with smart fuzzing (focusing chiefly on symbolic execution) and a | ||||||
|  | couple papers that discussed proof-of-concept applications of genetic | ||||||
|  | algorithms with the same goals in mind. I'm unconvinced how practical most of | ||||||
|  | these experiments were; I suspect that many of them suffer from the | ||||||
|  | bunny-the-fuzzer's curse of being cool on paper and in carefully designed | ||||||
|  | experiments, but failing the ultimate test of being able to find new, | ||||||
|  | worthwhile security bugs in otherwise well-fuzzed, real-world software. | ||||||
|  | 
 | ||||||
|  | In some ways, the baseline that the "cool" solutions have to compete against is | ||||||
|  | a lot more impressive than it may seem, making it difficult for competitors to | ||||||
|  | stand out. For a singular example, check out the work by Gynvael and Mateusz | ||||||
|  | Jurczyk, applying "dumb" fuzzing to ffmpeg, a prominent and security-critical | ||||||
|  | component of modern browsers and media players: | ||||||
|  | 
 | ||||||
|  |   http://googleonlinesecurity.blogspot.com/2014/01/ffmpeg-and-thousand-fixes.html | ||||||
|  | 
 | ||||||
|  | Effortlessly getting comparable results with state-of-the-art symbolic execution | ||||||
|  | in equally complex software still seems fairly unlikely, and hasn't been | ||||||
|  | demonstrated in practice so far. | ||||||
|  | 
 | ||||||
|  | But I digress; ultimately, attribution is hard, and glorying the fundamental | ||||||
|  | concepts behind AFL is probably a waste of time. The devil is very much in the | ||||||
|  | often-overlooked details, which brings us to... | ||||||
|  | 
 | ||||||
|  | 2) Design goals for afl-fuzz | ||||||
|  | ---------------------------- | ||||||
|  | 
 | ||||||
|  | In short, I believe that the current implementation of afl-fuzz takes care of | ||||||
|  | several itches that seemed impossible to scratch with other tools: | ||||||
|  | 
 | ||||||
|  | 1) Speed. It's genuinely hard to compete with brute force when your "smart" | ||||||
|  |    approach is resource-intensive. If your instrumentation makes it 10x more | ||||||
|  |    likely to find a bug, but runs 100x slower, your users are getting a bad | ||||||
|  |    deal. | ||||||
|  | 
 | ||||||
|  |    To avoid starting with a handicap, afl-fuzz is meant to let you fuzz most of | ||||||
|  |    the intended targets at roughly their native speed - so even if it doesn't | ||||||
|  |    add value, you do not lose much. | ||||||
|  | 
 | ||||||
|  |    On top of this, the tool leverages instrumentation to actually reduce the | ||||||
|  |    amount of work in a couple of ways: for example, by carefully trimming the | ||||||
|  |    corpus or skipping non-functional but non-trimmable regions in the input | ||||||
|  |    files. | ||||||
|  | 
 | ||||||
|  | 2) Rock-solid reliability. It's hard to compete with brute force if your | ||||||
|  |    approach is brittle and fails unexpectedly. Automated testing is attractive | ||||||
|  |    because it's simple to use and scalable; anything that goes against these | ||||||
|  |    principles is an unwelcome trade-off and means that your tool will be used | ||||||
|  |    less often and with less consistent results. | ||||||
|  | 
 | ||||||
|  |    Most of the approaches based on symbolic execution, taint tracking, or | ||||||
|  |    complex syntax-aware instrumentation are currently fairly unreliable with | ||||||
|  |    real-world targets. Perhaps more importantly, their failure modes can render | ||||||
|  |    them strictly worse than "dumb" tools, and such degradation can be difficult | ||||||
|  |    for less experienced users to notice and correct. | ||||||
|  | 
 | ||||||
|  |    In contrast, afl-fuzz is designed to be rock solid, chiefly by keeping it | ||||||
|  |    simple. In fact, at its core, it's designed to be just a very good | ||||||
|  |    traditional fuzzer with a wide range of interesting, well-researched | ||||||
|  |    strategies to go by. The fancy parts just help it focus the effort in | ||||||
|  |    places where it matters the most. | ||||||
|  | 
 | ||||||
|  | 3) Simplicity. The author of a testing framework is probably the only person | ||||||
|  |    who truly understands the impact of all the settings offered by the tool - | ||||||
|  |    and who can dial them in just right. Yet, even the most rudimentary fuzzer | ||||||
|  |    frameworks often come with countless knobs and fuzzing ratios that need to | ||||||
|  |    be guessed by the operator ahead of the time. This can do more harm than  | ||||||
|  |    good. | ||||||
|  | 
 | ||||||
|  |    AFL is designed to avoid this as much as possible. The three knobs you | ||||||
|  |    can play with are the output file, the memory limit, and the ability to | ||||||
|  |    override the default, auto-calibrated timeout. The rest is just supposed to | ||||||
|  |    work. When it doesn't, user-friendly error messages outline the probable | ||||||
|  |    causes and workarounds, and get you back on track right away. | ||||||
|  | 
 | ||||||
|  | 4) Chainability. Most general-purpose fuzzers can't be easily employed | ||||||
|  |    against resource-hungry or interaction-heavy tools, necessitating the | ||||||
|  |    creation of custom in-process fuzzers or the investment of massive CPU | ||||||
|  |    power (most of which is wasted on tasks not directly related to the code | ||||||
|  |    we actually want to test). | ||||||
|  | 
 | ||||||
|  |    AFL tries to scratch this itch by allowing users to use more lightweight | ||||||
|  |    targets (e.g., standalone image parsing libraries) to create small | ||||||
|  |    corpora of interesting test cases that can be fed into a manual testing | ||||||
|  |    process or a UI harness later on. | ||||||
|  | 
 | ||||||
|  | As mentioned in technical_details.txt, AFL does all this not by systematically | ||||||
|  | applying a single overarching CS concept, but by experimenting with a variety | ||||||
|  | of small, complementary methods that were shown to reliably yields results | ||||||
|  | better than chance. The use of instrumentation is a part of that toolkit, but is | ||||||
|  | far from being the most important one. | ||||||
|  | 
 | ||||||
|  | Ultimately, what matters is that afl-fuzz is designed to find cool bugs - and | ||||||
|  | has a pretty robust track record of doing just that. | ||||||
| @ -0,0 +1,128 @@ | |||||||
|  | # =================== | ||||||
|  | # AFL "Life Pro Tips" | ||||||
|  | # =================== | ||||||
|  | # | ||||||
|  | # Bite-sized advice for those who understand the basics, but can't be bothered | ||||||
|  | # to read or memorize every other piece of documentation for AFL. | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Get more bang for your buck by using fuzzing dictionaries. | ||||||
|  | See dictionaries/README.dictionaries to learn how. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | You can get the most out of your hardware by parallelizing AFL jobs. | ||||||
|  | See docs/parallel_fuzzing.txt for step-by-step tips. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Improve the odds of spotting memory corruption bugs with libdislocator.so! | ||||||
|  | It's easy. Consult libdislocator/README.dislocator for usage tips. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Want to understand how your target parses a particular input file? | ||||||
|  | Try the bundled afl-analyze tool; it's got colors and all! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | You can visually monitor the progress of your fuzzing jobs. | ||||||
|  | Run the bundled afl-plot utility to generate browser-friendly graphs. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Need to monitor AFL jobs programmatically? Check out the fuzzer_stats file | ||||||
|  | in the AFL output dir or try afl-whatsup. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Puzzled by something showing up in red or purple in the AFL UI? | ||||||
|  | It could be important - consult docs/status_screen.txt right away! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Know your target? Convert it to persistent mode for a huge performance gain! | ||||||
|  | Consult section #5 in llvm_mode/README.llvm for tips. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Using clang? Check out llvm_mode/ for a faster alternative to afl-gcc! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Did you know that AFL can fuzz closed-source or cross-platform binaries? | ||||||
|  | Check out qemu_mode/README.qemu for more. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Did you know that afl-fuzz can minimize any test case for you? | ||||||
|  | Try the bundled afl-tmin tool - and get small repro files fast! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Not sure if a crash is exploitable? AFL can help you figure it out. Specify | ||||||
|  | -C to enable the peruvian were-rabbit mode. See section #10 in README for more. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Trouble dealing with a machine uprising? Relax, we've all been there. | ||||||
|  | Find essential survival tips at http://lcamtuf.coredump.cx/prep/. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | AFL-generated corpora can be used to power other testing processes. | ||||||
|  | See section #2 in README for inspiration - it tends to pay off! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Want to automatically spot non-crashing memory handling bugs? | ||||||
|  | Try running an AFL-generated corpus through ASAN, MSAN, or Valgrind. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Good selection of input files is critical to a successful fuzzing job. | ||||||
|  | See section #5 in README (or docs/perf_tips.txt) for pro tips. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | You can improve the odds of automatically spotting stack corruption issues. | ||||||
|  | Specify AFL_HARDEN=1 in the environment to enable hardening flags. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Bumping into problems with non-reproducible crashes? It happens, but usually | ||||||
|  | isn't hard to diagnose. See section #7 in README for tips. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Fuzzing is not just about memory corruption issues in the codebase. Add some | ||||||
|  | sanity-checking assert() / abort() statements to effortlessly catch logic bugs. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Hey kid... pssst... want to figure out how AFL really works? | ||||||
|  | Check out docs/technical_details.txt for all the gory details in one place! | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | There's a ton of third-party helper tools designed to work with AFL! | ||||||
|  | Be sure to check out docs/sister_projects.txt before writing your own. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Need to fuzz the command-line arguments of a particular program? | ||||||
|  | You can find a simple solution in experimental/argv_fuzzing. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Attacking a format that uses checksums? Remove the checksum-checking code or | ||||||
|  | use a postprocessor! See experimental/post_library/ for more. | ||||||
|  | 
 | ||||||
|  | % | ||||||
|  | 
 | ||||||
|  | Dealing with a very slow target or hoping for instant results? Specify -d | ||||||
|  | when calling afl-fuzz! | ||||||
|  | 
 | ||||||
|  | % | ||||||
| @ -0,0 +1,143 @@ | |||||||
|  | ================================== | ||||||
|  | Notes for using ASAN with afl-fuzz | ||||||
|  | ================================== | ||||||
|  | 
 | ||||||
|  |   This file discusses some of the caveats for fuzzing under ASAN, and suggests | ||||||
|  |   a handful of alternatives. See README for the general instruction manual. | ||||||
|  | 
 | ||||||
|  | 1) Short version | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  | ASAN on 64-bit systems requests a lot of memory in a way that can't be easily | ||||||
|  | distinguished from a misbehaving program bent on crashing your system. | ||||||
|  | 
 | ||||||
|  | Because of this, fuzzing with ASAN is recommended only in four scenarios: | ||||||
|  | 
 | ||||||
|  |   - On 32-bit systems, where we can always enforce a reasonable memory limit | ||||||
|  |     (-m 800 or so is a good starting point), | ||||||
|  | 
 | ||||||
|  |   - On 64-bit systems only if you can do one of the following: | ||||||
|  | 
 | ||||||
|  |     - Compile the binary in 32-bit mode (gcc -m32), | ||||||
|  | 
 | ||||||
|  |     - Precisely gauge memory needs using http://jwilk.net/software/recidivm . | ||||||
|  | 
 | ||||||
|  |     - Limit the memory available to process using cgroups on Linux (see | ||||||
|  |       experimental/asan_cgroups). | ||||||
|  | 
 | ||||||
|  | To compile with ASAN, set AFL_USE_ASAN=1 before calling 'make clean all'. The | ||||||
|  | afl-gcc / afl-clang wrappers will pick that up and add the appropriate flags. | ||||||
|  | Note that ASAN is incompatible with -static, so be mindful of that. | ||||||
|  | 
 | ||||||
|  | (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) | ||||||
|  | 
 | ||||||
|  | There is also the option of generating a corpus using a non-ASAN binary, and | ||||||
|  | then feeding it to an ASAN-instrumented one to check for bugs. This is faster, | ||||||
|  | and can give you somewhat comparable results. You can also try using | ||||||
|  | libdislocator (see libdislocator/README.dislocator in the parent directory) as a | ||||||
|  | lightweight and hassle-free (but less thorough) alternative. | ||||||
|  | 
 | ||||||
|  | 2) Long version | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | ASAN allocates a huge region of virtual address space for bookkeeping purposes. | ||||||
|  | Most of this is never actually accessed, so the OS never has to allocate any | ||||||
|  | real pages of memory for the process, and the VM grabbed by ASAN is essentially | ||||||
|  | "free" - but the mapping counts against the standard OS-enforced limit | ||||||
|  | (RLIMIT_AS, aka ulimit -v). | ||||||
|  | 
 | ||||||
|  | On our end, afl-fuzz tries to protect you from processes that go off-rails | ||||||
|  | and start consuming all the available memory in a vain attempt to parse a | ||||||
|  | malformed input file. This happens surprisingly often, so enforcing such a limit | ||||||
|  | is important for almost any fuzzer: the alternative is for the kernel OOM | ||||||
|  | handler to step in and start killing random processes to free up resources. | ||||||
|  | Needless to say, that's not a very nice prospect to live with. | ||||||
|  | 
 | ||||||
|  | Unfortunately, un*x systems offer no portable way to limit the amount of | ||||||
|  | pages actually given to a process in a way that distinguishes between that | ||||||
|  | and the harmless "land grab" done by ASAN. In principle, there are three standard | ||||||
|  | ways to limit the size of the heap: | ||||||
|  | 
 | ||||||
|  |   - The RLIMIT_AS mechanism (ulimit -v) caps the size of the virtual space - | ||||||
|  |     but as noted, this pays no attention to the number of pages actually | ||||||
|  |     in use by the process, and doesn't help us here. | ||||||
|  | 
 | ||||||
|  |   - The RLIMIT_DATA mechanism (ulimit -d) seems like a good fit, but it applies | ||||||
|  |     only to the traditional sbrk() / brk() methods of requesting heap space; | ||||||
|  |     modern allocators, including the one in glibc, routinely rely on mmap() | ||||||
|  |     instead, and circumvent this limit completely. | ||||||
|  | 
 | ||||||
|  |   - Finally, the RLIMIT_RSS limit (ulimit -m) sounds like what we need, but | ||||||
|  |     doesn't work on Linux - mostly because nobody felt like implementing it. | ||||||
|  | 
 | ||||||
|  | There are also cgroups, but they are Linux-specific, not universally available | ||||||
|  | even on Linux systems, and they require root permissions to set up; I'm a bit | ||||||
|  | hesitant to make afl-fuzz require root permissions just for that. That said, | ||||||
|  | if you are on Linux and want to use cgroups, check out the contributed script | ||||||
|  | that ships in experimental/asan_cgroups/. | ||||||
|  | 
 | ||||||
|  | In settings where cgroups aren't available, we have no nice, portable way to | ||||||
|  | avoid counting the ASAN allocation toward the limit. On 32-bit systems, or for | ||||||
|  | binaries compiled in 32-bit mode (-m32), this is not a big deal: ASAN needs | ||||||
|  | around 600-800 MB or so, depending on the compiler - so all you need to do is | ||||||
|  | to specify -m that is a bit higher than that. | ||||||
|  | 
 | ||||||
|  | On 64-bit systems, the situation is more murky, because the ASAN allocation | ||||||
|  | is completely outlandish - around 17.5 TB in older versions, and closer to | ||||||
|  | 20 TB with newest ones. The actual amount of memory on your system is | ||||||
|  | (probably!) just a tiny fraction of that - so unless you dial the limit | ||||||
|  | with surgical precision, you will get no protection from OOM bugs. | ||||||
|  | 
 | ||||||
|  | On my system, the amount of memory grabbed by ASAN with a slightly older | ||||||
|  | version of gcc is around 17,825,850 MB; for newest clang, it's 20,971,600. | ||||||
|  | But there is no guarantee that these numbers are stable, and if you get them | ||||||
|  | wrong by "just" a couple gigs or so, you will be at risk. | ||||||
|  | 
 | ||||||
|  | To get the precise number, you can use the recidivm tool developed by Jakub | ||||||
|  | Wilk (http://jwilk.net/software/recidivm). In absence of this, ASAN is *not* | ||||||
|  | recommended when fuzzing 64-bit binaries, unless you are confident that they | ||||||
|  | are robust and enforce reasonable memory limits (in which case, you can | ||||||
|  | specify '-m none' when calling afl-fuzz). | ||||||
|  | 
 | ||||||
|  | Using recidivm or running with no limits aside, there are two other decent | ||||||
|  | alternatives: build a corpus of test cases using a non-ASAN binary, and then | ||||||
|  | examine them with ASAN, Valgrind, or other heavy-duty tools in a more | ||||||
|  | controlled setting; or compile the target program with -m32 (32-bit mode) | ||||||
|  | if your system supports that. | ||||||
|  | 
 | ||||||
|  | 3) Interactions with the QEMU mode | ||||||
|  | ---------------------------------- | ||||||
|  | 
 | ||||||
|  | ASAN, MSAN, and other sanitizers appear to be incompatible with QEMU user | ||||||
|  | emulation, so please do not try to use them with the -Q option; QEMU doesn't | ||||||
|  | seem to appreciate the shadow VM trick used by these tools, and will likely | ||||||
|  | just allocate all your physical memory, then crash. | ||||||
|  | 
 | ||||||
|  | 4) ASAN and OOM crashes | ||||||
|  | ----------------------- | ||||||
|  | 
 | ||||||
|  | By default, ASAN treats memory allocation failures as fatal errors, immediately | ||||||
|  | causing the program to crash. Since this is a departure from normal POSIX | ||||||
|  | semantics (and creates the appearance of security issues in otherwise | ||||||
|  | properly-behaving programs), we try to disable this by specifying  | ||||||
|  | allocator_may_return_null=1 in ASAN_OPTIONS. | ||||||
|  | 
 | ||||||
|  | Unfortunately, it's been reported that this setting still causes ASAN to | ||||||
|  | trigger phantom crashes in situations where the standard allocator would | ||||||
|  | simply return NULL. If this is interfering with your fuzzing jobs, you may | ||||||
|  | want to cc: yourself on this bug: | ||||||
|  | 
 | ||||||
|  |   https://bugs.llvm.org/show_bug.cgi?id=22026 | ||||||
|  | 
 | ||||||
|  | 5) What about UBSAN? | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | Some folks expressed interest in fuzzing with UBSAN. This isn't officially | ||||||
|  | supported, because many installations of UBSAN don't offer a consistent way | ||||||
|  | to abort() on fault conditions or to terminate with a distinctive exit code. | ||||||
|  | 
 | ||||||
|  | That said, some versions of the library can be binary-patched to address this | ||||||
|  | issue, while newer releases support explicit compile-time flags - see this | ||||||
|  | mailing list thread for tips: | ||||||
|  | 
 | ||||||
|  |   https://groups.google.com/forum/#!topic/afl-users/GyeSBJt4M38 | ||||||
| @ -0,0 +1,216 @@ | |||||||
|  | ========================= | ||||||
|  | Tips for parallel fuzzing | ||||||
|  | ========================= | ||||||
|  | 
 | ||||||
|  |   This document talks about synchronizing afl-fuzz jobs on a single machine | ||||||
|  |   or across a fleet of systems. See README for the general instruction manual. | ||||||
|  | 
 | ||||||
|  | 1) Introduction | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | Every copy of afl-fuzz will take up one CPU core. This means that on an | ||||||
|  | n-core system, you can almost always run around n concurrent fuzzing jobs with | ||||||
|  | virtually no performance hit (you can use the afl-gotcpu tool to make sure). | ||||||
|  | 
 | ||||||
|  | In fact, if you rely on just a single job on a multi-core system, you will | ||||||
|  | be underutilizing the hardware. So, parallelization is usually the right | ||||||
|  | way to go. | ||||||
|  | 
 | ||||||
|  | When targeting multiple unrelated binaries or using the tool in "dumb" (-n) | ||||||
|  | mode, it is perfectly fine to just start up several fully separate instances | ||||||
|  | of afl-fuzz. The picture gets more complicated when you want to have multiple | ||||||
|  | fuzzers hammering a common target: if a hard-to-hit but interesting test case | ||||||
|  | is synthesized by one fuzzer, the remaining instances will not be able to use | ||||||
|  | that input to guide their work. | ||||||
|  | 
 | ||||||
|  | To help with this problem, afl-fuzz offers a simple way to synchronize test | ||||||
|  | cases on the fly. | ||||||
|  | 
 | ||||||
|  | 2) Single-system parallelization | ||||||
|  | -------------------------------- | ||||||
|  | 
 | ||||||
|  | If you wish to parallelize a single job across multiple cores on a local | ||||||
|  | system, simply create a new, empty output directory ("sync dir") that will be | ||||||
|  | shared by all the instances of afl-fuzz; and then come up with a naming scheme | ||||||
|  | for every instance - say, "fuzzer01", "fuzzer02", etc.  | ||||||
|  | 
 | ||||||
|  | Run the first one ("master", -M) like this: | ||||||
|  | 
 | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -M fuzzer01 [...other stuff...] | ||||||
|  | 
 | ||||||
|  | ...and then, start up secondary (-S) instances like this: | ||||||
|  | 
 | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -S fuzzer02 [...other stuff...] | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -S fuzzer03 [...other stuff...] | ||||||
|  | 
 | ||||||
|  | Each fuzzer will keep its state in a separate subdirectory, like so: | ||||||
|  | 
 | ||||||
|  |   /path/to/sync_dir/fuzzer01/ | ||||||
|  | 
 | ||||||
|  | Each instance will also periodically rescan the top-level sync directory | ||||||
|  | for any test cases found by other fuzzers - and will incorporate them into | ||||||
|  | its own fuzzing when they are deemed interesting enough. | ||||||
|  | 
 | ||||||
|  | The difference between the -M and -S modes is that the master instance will | ||||||
|  | still perform deterministic checks; while the secondary instances will | ||||||
|  | proceed straight to random tweaks. If you don't want to do deterministic | ||||||
|  | fuzzing at all, it's OK to run all instances with -S. With very slow or complex | ||||||
|  | targets, or when running heavily parallelized jobs, this is usually a good plan. | ||||||
|  | 
 | ||||||
|  | Note that running multiple -M instances is wasteful, although there is an | ||||||
|  | experimental support for parallelizing the deterministic checks. To leverage | ||||||
|  | that, you need to create -M instances like so: | ||||||
|  | 
 | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -M masterA:1/3 [...] | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -M masterB:2/3 [...] | ||||||
|  | $ ./afl-fuzz -i testcase_dir -o sync_dir -M masterC:3/3 [...] | ||||||
|  | 
 | ||||||
|  | ...where the first value after ':' is the sequential ID of a particular master | ||||||
|  | instance (starting at 1), and the second value is the total number of fuzzers to | ||||||
|  | distribute the deterministic fuzzing across. Note that if you boot up fewer | ||||||
|  | fuzzers than indicated by the second number passed to -M, you may end up with | ||||||
|  | poor coverage. | ||||||
|  | 
 | ||||||
|  | You can also monitor the progress of your jobs from the command line with the | ||||||
|  | provided afl-whatsup tool. When the instances are no longer finding new paths, | ||||||
|  | it's probably time to stop. | ||||||
|  | 
 | ||||||
|  | WARNING: Exercise caution when explicitly specifying the -f option. Each fuzzer | ||||||
|  | must use a separate temporary file; otherwise, things will go south. One safe | ||||||
|  | example may be: | ||||||
|  | 
 | ||||||
|  | $ ./afl-fuzz [...] -S fuzzer10 -f file10.txt ./fuzzed/binary @@ | ||||||
|  | $ ./afl-fuzz [...] -S fuzzer11 -f file11.txt ./fuzzed/binary @@ | ||||||
|  | $ ./afl-fuzz [...] -S fuzzer12 -f file12.txt ./fuzzed/binary @@ | ||||||
|  | 
 | ||||||
|  | This is not a concern if you use @@ without -f and let afl-fuzz come up with the | ||||||
|  | file name. | ||||||
|  | 
 | ||||||
|  | 3) Multi-system parallelization | ||||||
|  | ------------------------------- | ||||||
|  | 
 | ||||||
|  | The basic operating principle for multi-system parallelization is similar to | ||||||
|  | the mechanism explained in section 2. The key difference is that you need to | ||||||
|  | write a simple script that performs two actions: | ||||||
|  | 
 | ||||||
|  |   - Uses SSH with authorized_keys to connect to every machine and retrieve | ||||||
|  |     a tar archive of the /path/to/sync_dir/<fuzzer_id>/queue/ directories for | ||||||
|  |     every <fuzzer_id> local to the machine. It's best to use a naming scheme | ||||||
|  |     that includes host name in the fuzzer ID, so that you can do something | ||||||
|  |     like: | ||||||
|  | 
 | ||||||
|  |     for s in {1..10}; do | ||||||
|  |       ssh user@host${s} "tar -czf - sync/host${s}_fuzzid*/[qf]*" >host${s}.tgz | ||||||
|  |     done | ||||||
|  | 
 | ||||||
|  |   - Distributes and unpacks these files on all the remaining machines, e.g.: | ||||||
|  | 
 | ||||||
|  |     for s in {1..10}; do | ||||||
|  |       for d in {1..10}; do | ||||||
|  |         test "$s" = "$d" && continue | ||||||
|  |         ssh user@host${d} 'tar -kxzf -' <host${s}.tgz | ||||||
|  |       done | ||||||
|  |     done | ||||||
|  | 
 | ||||||
|  | There is an example of such a script in experimental/distributed_fuzzing/; | ||||||
|  | you can also find a more featured, experimental tool developed by | ||||||
|  | Martijn Bogaard at: | ||||||
|  | 
 | ||||||
|  |   https://github.com/MartijnB/disfuzz-afl | ||||||
|  | 
 | ||||||
|  | Another client-server implementation from Richo Healey is: | ||||||
|  | 
 | ||||||
|  |   https://github.com/richo/roving | ||||||
|  | 
 | ||||||
|  | Note that these third-party tools are unsafe to run on systems exposed to the | ||||||
|  | Internet or to untrusted users. | ||||||
|  | 
 | ||||||
|  | When developing custom test case sync code, there are several optimizations | ||||||
|  | to keep in mind: | ||||||
|  | 
 | ||||||
|  |   - The synchronization does not have to happen very often; running the | ||||||
|  |     task every 30 minutes or so may be perfectly fine. | ||||||
|  | 
 | ||||||
|  |   - There is no need to synchronize crashes/ or hangs/; you only need to | ||||||
|  |     copy over queue/* (and ideally, also fuzzer_stats). | ||||||
|  | 
 | ||||||
|  |   - It is not necessary (and not advisable!) to overwrite existing files; | ||||||
|  |     the -k option in tar is a good way to avoid that. | ||||||
|  | 
 | ||||||
|  |   - There is no need to fetch directories for fuzzers that are not running | ||||||
|  |     locally on a particular machine, and were simply copied over onto that | ||||||
|  |     system during earlier runs. | ||||||
|  | 
 | ||||||
|  |   - For large fleets, you will want to consolidate tarballs for each host, | ||||||
|  |     as this will let you use n SSH connections for sync, rather than n*(n-1). | ||||||
|  | 
 | ||||||
|  |     You may also want to implement staged synchronization. For example, you | ||||||
|  |     could have 10 groups of systems, with group 1 pushing test cases only | ||||||
|  |     to group 2; group 2 pushing them only to group 3; and so on, with group | ||||||
|  |     eventually 10 feeding back to group 1. | ||||||
|  | 
 | ||||||
|  |     This arrangement would allow test interesting cases to propagate across | ||||||
|  |     the fleet without having to copy every fuzzer queue to every single host. | ||||||
|  | 
 | ||||||
|  |   - You do not want a "master" instance of afl-fuzz on every system; you should | ||||||
|  |     run them all with -S, and just designate a single process somewhere within | ||||||
|  |     the fleet to run with -M. | ||||||
|  | 
 | ||||||
|  | It is *not* advisable to skip the synchronization script and run the fuzzers | ||||||
|  | directly on a network filesystem; unexpected latency and unkillable processes | ||||||
|  | in I/O wait state can mess things up. | ||||||
|  | 
 | ||||||
|  | 4) Remote monitoring and data collection | ||||||
|  | ---------------------------------------- | ||||||
|  | 
 | ||||||
|  | You can use screen, nohup, tmux, or something equivalent to run remote | ||||||
|  | instances of afl-fuzz. If you redirect the program's output to a file, it will | ||||||
|  | automatically switch from a fancy UI to more limited status reports. There is | ||||||
|  | also basic machine-readable information always written to the fuzzer_stats file | ||||||
|  | in the output directory. Locally, that information can be interpreted with | ||||||
|  | afl-whatsup. | ||||||
|  | 
 | ||||||
|  | In principle, you can use the status screen of the master (-M) instance to | ||||||
|  | monitor the overall fuzzing progress and decide when to stop. In this | ||||||
|  | mode, the most important signal is just that no new paths are being found | ||||||
|  | for a longer while. If you do not have a master instance, just pick any | ||||||
|  | single secondary instance to watch and go by that. | ||||||
|  | 
 | ||||||
|  | You can also rely on that instance's output directory to collect the | ||||||
|  | synthesized corpus that covers all the noteworthy paths discovered anywhere | ||||||
|  | within the fleet. Secondary (-S) instances do not require any special | ||||||
|  | monitoring, other than just making sure that they are up. | ||||||
|  | 
 | ||||||
|  | Keep in mind that crashing inputs are *not* automatically propagated to the | ||||||
|  | master instance, so you may still want to monitor for crashes fleet-wide | ||||||
|  | from within your synchronization or health checking scripts (see afl-whatsup). | ||||||
|  | 
 | ||||||
|  | 5) Asymmetric setups | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | It is perhaps worth noting that all of the following is permitted: | ||||||
|  | 
 | ||||||
|  |   - Running afl-fuzz with conjunction with other guided tools that can extend | ||||||
|  |     coverage (e.g., via concolic execution). Third-party tools simply need to | ||||||
|  |     follow the protocol described above for pulling new test cases from | ||||||
|  |     out_dir/<fuzzer_id>/queue/* and writing their own finds to sequentially | ||||||
|  |     numbered id:nnnnnn files in out_dir/<ext_tool_id>/queue/*. | ||||||
|  | 
 | ||||||
|  |   - Running some of the synchronized fuzzers with different (but related) | ||||||
|  |     target binaries. For example, simultaneously stress-testing several | ||||||
|  |     different JPEG parsers (say, IJG jpeg and libjpeg-turbo) while sharing | ||||||
|  |     the discovered test cases can have synergistic effects and improve the | ||||||
|  |     overall coverage. | ||||||
|  | 
 | ||||||
|  |     (In this case, running one -M instance per each binary is a good plan.) | ||||||
|  | 
 | ||||||
|  |   - Having some of the fuzzers invoke the binary in different ways. | ||||||
|  |     For example, 'djpeg' supports several DCT modes, configurable with | ||||||
|  |     a command-line flag, while 'dwebp' supports incremental and one-shot | ||||||
|  |     decoding. In some scenarios, going after multiple distinct modes and then | ||||||
|  |     pooling test cases will improve coverage. | ||||||
|  | 
 | ||||||
|  |   - Much less convincingly, running the synchronized fuzzers with different | ||||||
|  |     starting test cases (e.g., progressive and standard JPEG) or dictionaries. | ||||||
|  |     The synchronization mechanism ensures that the test sets will get fairly | ||||||
|  |     homogeneous over time, but it introduces some initial variability. | ||||||
| @ -0,0 +1,201 @@ | |||||||
|  | ================================= | ||||||
|  | Tips for performance optimization | ||||||
|  | ================================= | ||||||
|  | 
 | ||||||
|  |   This file provides tips for troubleshooting slow or wasteful fuzzing jobs. | ||||||
|  |   See README for the general instruction manual. | ||||||
|  | 
 | ||||||
|  | 1) Keep your test cases small | ||||||
|  | ----------------------------- | ||||||
|  | 
 | ||||||
|  | This is probably the single most important step to take! Large test cases do | ||||||
|  | not merely take more time and memory to be parsed by the tested binary, but | ||||||
|  | also make the fuzzing process dramatically less efficient in several other | ||||||
|  | ways. | ||||||
|  | 
 | ||||||
|  | To illustrate, let's say that you're randomly flipping bits in a file, one bit | ||||||
|  | at a time. Let's assume that if you flip bit #47, you will hit a security bug; | ||||||
|  | flipping any other bit just results in an invalid document. | ||||||
|  | 
 | ||||||
|  | Now, if your starting test case is 100 bytes long, you will have a 71% chance of | ||||||
|  | triggering the bug within the first 1,000 execs - not bad! But if the test case | ||||||
|  | is 1 kB long, the probability that we will randomly hit the right pattern in | ||||||
|  | the same timeframe goes down to 11%. And if it has 10 kB of non-essential | ||||||
|  | cruft, the odds plunge to 1%. | ||||||
|  | 
 | ||||||
|  | On top of that, with larger inputs, the binary may be now running 5-10x times | ||||||
|  | slower than before - so the overall drop in fuzzing efficiency may be easily | ||||||
|  | as high as 500x or so. | ||||||
|  | 
 | ||||||
|  | In practice, this means that you shouldn't fuzz image parsers with your | ||||||
|  | vacation photos. Generate a tiny 16x16 picture instead, and run it through | ||||||
|  | jpegtran or pngcrunch for good measure. The same goes for most other types | ||||||
|  | of documents. | ||||||
|  | 
 | ||||||
|  | There's plenty of small starting test cases in ../testcases/* - try them out | ||||||
|  | or submit new ones! | ||||||
|  | 
 | ||||||
|  | If you want to start with a larger, third-party corpus, run afl-cmin with an | ||||||
|  | aggressive timeout on that data set first. | ||||||
|  | 
 | ||||||
|  | 2) Use a simpler target | ||||||
|  | ----------------------- | ||||||
|  | 
 | ||||||
|  | Consider using a simpler target binary in your fuzzing work. For example, for | ||||||
|  | image formats, bundled utilities such as djpeg, readpng, or gifhisto are | ||||||
|  | considerably (10-20x) faster than the convert tool from ImageMagick - all while | ||||||
|  | exercising roughly the same library-level image parsing code. | ||||||
|  | 
 | ||||||
|  | Even if you don't have a lightweight harness for a particular target, remember | ||||||
|  | that you can always use another, related library to generate a corpus that will | ||||||
|  | be then manually fed to a more resource-hungry program later on. | ||||||
|  | 
 | ||||||
|  | 3) Use LLVM instrumentation | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  | When fuzzing slow targets, you can gain 2x performance improvement by using | ||||||
|  | the LLVM-based instrumentation mode described in llvm_mode/README.llvm. Note | ||||||
|  | that this mode requires the use of clang and will not work with GCC. | ||||||
|  | 
 | ||||||
|  | The LLVM mode also offers a "persistent", in-process fuzzing mode that can | ||||||
|  | work well for certain types of self-contained libraries, and for fast targets, | ||||||
|  | can offer performance gains up to 5-10x; and a "deferred fork server" mode | ||||||
|  | that can offer huge benefits for programs with high startup overhead. Both | ||||||
|  | modes require you to edit the source code of the fuzzed program, but the | ||||||
|  | changes often amount to just strategically placing a single line or two. | ||||||
|  | 
 | ||||||
|  | 4) Profile and optimize the binary | ||||||
|  | ---------------------------------- | ||||||
|  | 
 | ||||||
|  | Check for any parameters or settings that obviously improve performance. For | ||||||
|  | example, the djpeg utility that comes with IJG jpeg and libjpeg-turbo can be | ||||||
|  | called with: | ||||||
|  | 
 | ||||||
|  |   -dct fast -nosmooth -onepass -dither none -scale 1/4 | ||||||
|  | 
 | ||||||
|  | ...and that will speed things up. There is a corresponding drop in the quality | ||||||
|  | of decoded images, but it's probably not something you care about. | ||||||
|  | 
 | ||||||
|  | In some programs, it is possible to disable output altogether, or at least use | ||||||
|  | an output format that is computationally inexpensive. For example, with image | ||||||
|  | transcoding tools, converting to a BMP file will be a lot faster than to PNG. | ||||||
|  | 
 | ||||||
|  | With some laid-back parsers, enabling "strict" mode (i.e., bailing out after | ||||||
|  | first error) may result in smaller files and improved run time without | ||||||
|  | sacrificing coverage; for example, for sqlite, you may want to specify -bail. | ||||||
|  | 
 | ||||||
|  | If the program is still too slow, you can use strace -tt or an equivalent | ||||||
|  | profiling tool to see if the targeted binary is doing anything silly. | ||||||
|  | Sometimes, you can speed things up simply by specifying /dev/null as the | ||||||
|  | config file, or disabling some compile-time features that aren't really needed | ||||||
|  | for the job (try ./configure --help). One of the notoriously resource-consuming | ||||||
|  | things would be calling other utilities via exec*(), popen(), system(), or | ||||||
|  | equivalent calls; for example, tar can invoke external decompression tools | ||||||
|  | when it decides that the input file is a compressed archive. | ||||||
|  | 
 | ||||||
|  | Some programs may also intentionally call sleep(), usleep(), or nanosleep(); | ||||||
|  | vim is a good example of that. Other programs may attempt fsync() and so on. | ||||||
|  | There are third-party libraries that make it easy to get rid of such code, | ||||||
|  | e.g.: | ||||||
|  | 
 | ||||||
|  |   https://launchpad.net/libeatmydata | ||||||
|  | 
 | ||||||
|  | In programs that are slow due to unavoidable initialization overhead, you may | ||||||
|  | want to try the LLVM deferred forkserver mode (see llvm_mode/README.llvm), | ||||||
|  | which can give you speed gains up to 10x, as mentioned above. | ||||||
|  | 
 | ||||||
|  | Last but not least, if you are using ASAN and the performance is unacceptable, | ||||||
|  | consider turning it off for now, and manually examining the generated corpus | ||||||
|  | with an ASAN-enabled binary later on. | ||||||
|  | 
 | ||||||
|  | 5) Instrument just what you need | ||||||
|  | -------------------------------- | ||||||
|  | 
 | ||||||
|  | Instrument just the libraries you actually want to stress-test right now, one | ||||||
|  | at a time. Let the program use system-wide, non-instrumented libraries for | ||||||
|  | any functionality you don't actually want to fuzz. For example, in most | ||||||
|  | cases, it doesn't make to instrument libgmp just because you're testing a | ||||||
|  | crypto app that relies on it for bignum math. | ||||||
|  | 
 | ||||||
|  | Beware of programs that come with oddball third-party libraries bundled with | ||||||
|  | their source code (Spidermonkey is a good example of this). Check ./configure | ||||||
|  | options to use non-instrumented system-wide copies instead. | ||||||
|  | 
 | ||||||
|  | 6) Parallelize your fuzzers | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  | The fuzzer is designed to need ~1 core per job. This means that on a, say, | ||||||
|  | 4-core system, you can easily run four parallel fuzzing jobs with relatively | ||||||
|  | little performance hit. For tips on how to do that, see parallel_fuzzing.txt. | ||||||
|  | 
 | ||||||
|  | The afl-gotcpu utility can help you understand if you still have idle CPU | ||||||
|  | capacity on your system. (It won't tell you about memory bandwidth, cache | ||||||
|  | misses, or similar factors, but they are less likely to be a concern.) | ||||||
|  | 
 | ||||||
|  | 7) Keep memory use and timeouts in check | ||||||
|  | ---------------------------------------- | ||||||
|  | 
 | ||||||
|  | If you have increased the -m or -t limits more than truly necessary, consider | ||||||
|  | dialing them back down. | ||||||
|  | 
 | ||||||
|  | For programs that are nominally very fast, but get sluggish for some inputs, | ||||||
|  | you can also try setting -t values that are more punishing than what afl-fuzz | ||||||
|  | dares to use on its own. On fast and idle machines, going down to -t 5 may be | ||||||
|  | a viable plan. | ||||||
|  | 
 | ||||||
|  | The -m parameter is worth looking at, too. Some programs can end up spending | ||||||
|  | a fair amount of time allocating and initializing megabytes of memory when | ||||||
|  | presented with pathological inputs. Low -m values can make them give up sooner | ||||||
|  | and not waste CPU time. | ||||||
|  | 
 | ||||||
|  | 8) Check OS configuration | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  | There are several OS-level factors that may affect fuzzing speed: | ||||||
|  | 
 | ||||||
|  |   - High system load. Use idle machines where possible. Kill any non-essential | ||||||
|  |     CPU hogs (idle browser windows, media players, complex screensavers, etc). | ||||||
|  | 
 | ||||||
|  |   - Network filesystems, either used for fuzzer input / output, or accessed by | ||||||
|  |     the fuzzed binary to read configuration files (pay special attention to the | ||||||
|  |     home directory - many programs search it for dot-files). | ||||||
|  | 
 | ||||||
|  |   - On-demand CPU scaling. The Linux 'ondemand' governor performs its analysis | ||||||
|  |     on a particular schedule and is known to underestimate the needs of | ||||||
|  |     short-lived processes spawned by afl-fuzz (or any other fuzzer). On Linux, | ||||||
|  |     this can be fixed with: | ||||||
|  | 
 | ||||||
|  |     cd /sys/devices/system/cpu | ||||||
|  |     echo performance | tee cpu*/cpufreq/scaling_governor | ||||||
|  | 
 | ||||||
|  |     On other systems, the impact of CPU scaling will be different; when fuzzing, | ||||||
|  |     use OS-specific tools to find out if all cores are running at full speed. | ||||||
|  | 
 | ||||||
|  |   - Transparent huge pages. Some allocators, such as jemalloc, can incur a | ||||||
|  |     heavy fuzzing penalty when transparent huge pages (THP) are enabled in the | ||||||
|  |     kernel. You can disable this via: | ||||||
|  | 
 | ||||||
|  |     echo never > /sys/kernel/mm/transparent_hugepage/enabled | ||||||
|  | 
 | ||||||
|  |   - Suboptimal scheduling strategies. The significance of this will vary from | ||||||
|  |     one target to another, but on Linux, you may want to make sure that the | ||||||
|  |     following options are set: | ||||||
|  | 
 | ||||||
|  |     echo 1 >/proc/sys/kernel/sched_child_runs_first | ||||||
|  |     echo 1 >/proc/sys/kernel/sched_autogroup_enabled | ||||||
|  | 
 | ||||||
|  |     Setting a different scheduling policy for the fuzzer process - say | ||||||
|  |     SCHED_RR - can usually speed things up, too, but needs to be done with | ||||||
|  |     care. | ||||||
|  | 
 | ||||||
|  | 9) If all other options fail, use -d | ||||||
|  | ------------------------------------ | ||||||
|  | 
 | ||||||
|  | For programs that are genuinely slow, in cases where you really can't escape | ||||||
|  | using huge input files, or when you simply want to get quick and dirty results | ||||||
|  | early on, you can always resort to the -d mode. | ||||||
|  | 
 | ||||||
|  | The mode causes afl-fuzz to skip all the deterministic fuzzing steps, which | ||||||
|  | makes output a lot less neat and can ultimately make the testing a bit less | ||||||
|  | in-depth, but it will give you an experience more familiar from other fuzzing | ||||||
|  | tools. | ||||||
| @ -0,0 +1,354 @@ | |||||||
|  | =============== | ||||||
|  | Sister projects | ||||||
|  | =============== | ||||||
|  | 
 | ||||||
|  |   This doc lists some of the projects that are inspired by, derived from, | ||||||
|  |   designed for, or meant to integrate with AFL. See README for the general | ||||||
|  |   instruction manual. | ||||||
|  | 
 | ||||||
|  | ------------------------------------------- | ||||||
|  | Support for other languages / environments: | ||||||
|  | ------------------------------------------- | ||||||
|  | 
 | ||||||
|  | Python AFL (Jakub Wilk) | ||||||
|  | ----------------------- | ||||||
|  | 
 | ||||||
|  |   Allows fuzz-testing of Python programs. Uses custom instrumentation and its | ||||||
|  |   own forkserver. | ||||||
|  | 
 | ||||||
|  |   http://jwilk.net/software/python-afl | ||||||
|  | 
 | ||||||
|  | Go-fuzz (Dmitry Vyukov) | ||||||
|  | ----------------------- | ||||||
|  | 
 | ||||||
|  |   AFL-inspired guided fuzzing approach for Go targets: | ||||||
|  | 
 | ||||||
|  |   https://github.com/dvyukov/go-fuzz | ||||||
|  | 
 | ||||||
|  | afl.rs (Keegan McAllister) | ||||||
|  | -------------------------- | ||||||
|  | 
 | ||||||
|  |   Allows Rust features to be easily fuzzed with AFL (using the LLVM mode). | ||||||
|  | 
 | ||||||
|  |   https://github.com/kmcallister/afl.rs | ||||||
|  | 
 | ||||||
|  | OCaml support (KC Sivaramakrishnan) | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  |   Adds AFL-compatible instrumentation to OCaml programs. | ||||||
|  | 
 | ||||||
|  |   https://github.com/ocamllabs/opam-repo-dev/pull/23 | ||||||
|  |   http://canopy.mirage.io/Posts/Fuzzing | ||||||
|  | 
 | ||||||
|  | AFL for GCJ Java and other GCC frontends (-) | ||||||
|  | -------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   GCC Java programs are actually supported out of the box - simply rename | ||||||
|  |   afl-gcc to afl-gcj. Unfortunately, by default, unhandled exceptions in GCJ do | ||||||
|  |   not result in abort() being called, so you will need to manually add a | ||||||
|  |   top-level exception handler that exits with SIGABRT or something equivalent. | ||||||
|  | 
 | ||||||
|  |   Other GCC-supported languages should be fairly easy to get working, but may | ||||||
|  |   face similar problems. See https://gcc.gnu.org/frontends.html for a list of | ||||||
|  |   options. | ||||||
|  | 
 | ||||||
|  | AFL-style in-process fuzzer for LLVM (Kostya Serebryany) | ||||||
|  | -------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   Provides an evolutionary instrumentation-guided fuzzing harness that allows | ||||||
|  |   some programs to be fuzzed without the fork / execve overhead. (Similar | ||||||
|  |   functionality is now available as the "persistent" feature described in | ||||||
|  |   ../llvm_mode/README.llvm.) | ||||||
|  | 
 | ||||||
|  |   http://llvm.org/docs/LibFuzzer.html | ||||||
|  | 
 | ||||||
|  | AFL fixup shim (Ben Nagy) | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  |   Allows AFL_POST_LIBRARY postprocessors to be written in arbitrary languages | ||||||
|  |   that don't have C / .so bindings. Includes examples in Go. | ||||||
|  | 
 | ||||||
|  |   https://github.com/bnagy/aflfix | ||||||
|  | 
 | ||||||
|  | TriforceAFL (Tim Newsham and Jesse Hertz) | ||||||
|  | ----------------------------------------- | ||||||
|  | 
 | ||||||
|  |   Leverages QEMU full system emulation mode to allow AFL to target operating | ||||||
|  |   systems and other alien worlds: | ||||||
|  | 
 | ||||||
|  |   https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2016/june/project-triforce-run-afl-on-everything/ | ||||||
|  | 
 | ||||||
|  | WinAFL (Ivan Fratric) | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  |   As the name implies, allows you to fuzz Windows binaries (using DynamoRio). | ||||||
|  | 
 | ||||||
|  |   https://github.com/ivanfratric/winafl | ||||||
|  | 
 | ||||||
|  |   Another Windows alternative may be: | ||||||
|  | 
 | ||||||
|  |   https://github.com/carlosgprado/BrundleFuzz/ | ||||||
|  | 
 | ||||||
|  | ---------------- | ||||||
|  | Network fuzzing: | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  | Preeny (Yan Shoshitaishvili) | ||||||
|  | ---------------------------- | ||||||
|  | 
 | ||||||
|  |   Provides a fairly simple way to convince dynamically linked network-centric | ||||||
|  |   programs to read from a file or not fork. Not AFL-specific, but described as | ||||||
|  |   useful by many users. Some assembly required. | ||||||
|  | 
 | ||||||
|  |   https://github.com/zardus/preeny | ||||||
|  | 
 | ||||||
|  | ------------------------------------------- | ||||||
|  | Distributed fuzzing and related automation: | ||||||
|  | ------------------------------------------- | ||||||
|  | 
 | ||||||
|  | roving (Richo Healey) | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  |   A client-server architecture for effortlessly orchestrating AFL runs across | ||||||
|  |   a fleet of machines. You don't want to use this on systems that face the | ||||||
|  |   Internet or live in other untrusted environments. | ||||||
|  | 
 | ||||||
|  |   https://github.com/richo/roving | ||||||
|  | 
 | ||||||
|  | Distfuzz-AFL (Martijn Bogaard) | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  |   Simplifies the management of afl-fuzz instances on remote machines. The | ||||||
|  |   author notes that the current implementation isn't secure and should not | ||||||
|  |   be exposed on the Internet. | ||||||
|  | 
 | ||||||
|  |   https://github.com/MartijnB/disfuzz-afl | ||||||
|  | 
 | ||||||
|  | AFLDFF (quantumvm) | ||||||
|  | ------------------ | ||||||
|  | 
 | ||||||
|  |   A nice GUI for managing AFL jobs. | ||||||
|  | 
 | ||||||
|  |   https://github.com/quantumvm/AFLDFF | ||||||
|  | 
 | ||||||
|  | afl-launch (Ben Nagy) | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  |   Batch AFL launcher utility with a simple CLI. | ||||||
|  | 
 | ||||||
|  |   https://github.com/bnagy/afl-launch | ||||||
|  | 
 | ||||||
|  | AFL Utils (rc0r) | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  |   Simplifies the triage of discovered crashes, start parallel instances, etc. | ||||||
|  | 
 | ||||||
|  |   https://github.com/rc0r/afl-utils | ||||||
|  | 
 | ||||||
|  |   Another crash triage tool: | ||||||
|  | 
 | ||||||
|  |   https://github.com/floyd-fuh/afl-crash-analyzer | ||||||
|  | 
 | ||||||
|  | afl-fuzzing-scripts (Tobias Ospelt) | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  |   Simplifies starting up multiple parallel AFL jobs. | ||||||
|  | 
 | ||||||
|  |   https://github.com/floyd-fuh/afl-fuzzing-scripts/ | ||||||
|  | 
 | ||||||
|  | afl-sid (Jacek Wielemborek) | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  |   Allows users to more conveniently build and deploy AFL via Docker. | ||||||
|  | 
 | ||||||
|  |   https://github.com/d33tah/afl-sid | ||||||
|  | 
 | ||||||
|  |   Another Docker-related project: | ||||||
|  | 
 | ||||||
|  |   https://github.com/ozzyjohnson/docker-afl | ||||||
|  | 
 | ||||||
|  | afl-monitor (Paul S. Ziegler) | ||||||
|  | ----------------------------- | ||||||
|  | 
 | ||||||
|  |   Provides more detailed and versatile statistics about your running AFL jobs. | ||||||
|  | 
 | ||||||
|  |   https://github.com/reflare/afl-monitor | ||||||
|  | 
 | ||||||
|  | ----------------------------------------------------------- | ||||||
|  | Crash triage, coverage analysis, and other companion tools: | ||||||
|  | ----------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | afl-crash-analyzer (Tobias Ospelt) | ||||||
|  | ---------------------------------- | ||||||
|  | 
 | ||||||
|  |   Makes it easier to navigate and annotate crashing test cases. | ||||||
|  | 
 | ||||||
|  |   https://github.com/floyd-fuh/afl-crash-analyzer/ | ||||||
|  | 
 | ||||||
|  | Crashwalk (Ben Nagy) | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  |   AFL-aware tool to annotate and sort through crashing test cases. | ||||||
|  | 
 | ||||||
|  |   https://github.com/bnagy/crashwalk | ||||||
|  | 
 | ||||||
|  | afl-cov (Michael Rash) | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  |   Produces human-readable coverage data based on the output queue of afl-fuzz. | ||||||
|  | 
 | ||||||
|  |   https://github.com/mrash/afl-cov | ||||||
|  | 
 | ||||||
|  | afl-sancov (Bhargava Shastry) | ||||||
|  | ----------------------------- | ||||||
|  | 
 | ||||||
|  |   Similar to afl-cov, but uses clang sanitizer instrumentation. | ||||||
|  | 
 | ||||||
|  |   https://github.com/bshastry/afl-sancov | ||||||
|  | 
 | ||||||
|  | RecidiVM (Jakub Wilk) | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  |   Makes it easy to estimate memory usage limits when fuzzing with ASAN or MSAN. | ||||||
|  | 
 | ||||||
|  |   http://jwilk.net/software/recidivm | ||||||
|  | 
 | ||||||
|  | aflize (Jacek Wielemborek) | ||||||
|  | -------------------------- | ||||||
|  | 
 | ||||||
|  |   Automatically build AFL-enabled versions of Debian packages. | ||||||
|  | 
 | ||||||
|  |   https://github.com/d33tah/aflize | ||||||
|  | 
 | ||||||
|  | afl-ddmin-mod (Markus Teufelberger) | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  |   A variant of afl-tmin that uses a more sophisticated (but slower) | ||||||
|  |   minimization algorithm. | ||||||
|  | 
 | ||||||
|  |   https://github.com/MarkusTeufelberger/afl-ddmin-mod | ||||||
|  | 
 | ||||||
|  | afl-kit (Kuang-che Wu) | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  |   Replacements for afl-cmin and afl-tmin with additional features, such | ||||||
|  |   as the ability to filter crashes based on stderr patterns. | ||||||
|  | 
 | ||||||
|  |   https://github.com/kcwu/afl-kit | ||||||
|  | 
 | ||||||
|  | ------------------------------- | ||||||
|  | Narrow-purpose or experimental: | ||||||
|  | ------------------------------- | ||||||
|  | 
 | ||||||
|  | Cygwin support (Ali Rizvi-Santiago) | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  |   Pretty self-explanatory. As per the author, this "mostly" ports AFL to | ||||||
|  |   Windows. Field reports welcome! | ||||||
|  | 
 | ||||||
|  |   https://github.com/arizvisa/afl-cygwin | ||||||
|  | 
 | ||||||
|  | Pause and resume scripts (Ben Nagy) | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  |   Simple automation to suspend and resume groups of fuzzing jobs. | ||||||
|  | 
 | ||||||
|  |   https://github.com/bnagy/afl-trivia | ||||||
|  | 
 | ||||||
|  | Static binary-only instrumentation (Aleksandar Nikolich) | ||||||
|  | -------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   Allows black-box binaries to be instrumented statically (i.e., by modifying | ||||||
|  |   the binary ahead of the time, rather than translating it on the run). Author | ||||||
|  |   reports better performance compared to QEMU, but occasional translation | ||||||
|  |   errors with stripped binaries. | ||||||
|  | 
 | ||||||
|  |   https://github.com/vrtadmin/moflow/tree/master/afl-dyninst | ||||||
|  | 
 | ||||||
|  | AFL PIN (Parker Thompson) | ||||||
|  | ------------------------- | ||||||
|  | 
 | ||||||
|  |   Early-stage Intel PIN instrumentation support (from before we settled on | ||||||
|  |   faster-running QEMU). | ||||||
|  | 
 | ||||||
|  |   https://github.com/mothran/aflpin | ||||||
|  | 
 | ||||||
|  | AFL-style instrumentation in llvm (Kostya Serebryany) | ||||||
|  | ----------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   Allows AFL-equivalent instrumentation to be injected at compiler level. | ||||||
|  |   This is currently not supported by AFL as-is, but may be useful in other | ||||||
|  |   projects. | ||||||
|  | 
 | ||||||
|  |   https://code.google.com/p/address-sanitizer/wiki/AsanCoverage#Coverage_counters | ||||||
|  | 
 | ||||||
|  | AFL JS (Han Choongwoo) | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  |   One-off optimizations to speed up the fuzzing of JavaScriptCore (now likely | ||||||
|  |   superseded by LLVM deferred forkserver init - see llvm_mode/README.llvm). | ||||||
|  | 
 | ||||||
|  |   https://github.com/tunz/afl-fuzz-js | ||||||
|  | 
 | ||||||
|  | AFL harness for fwknop (Michael Rash) | ||||||
|  | ------------------------------------- | ||||||
|  | 
 | ||||||
|  |   An example of a fairly involved integration with AFL. | ||||||
|  | 
 | ||||||
|  |   https://github.com/mrash/fwknop/tree/master/test/afl | ||||||
|  | 
 | ||||||
|  | Building harnesses for DNS servers (Jonathan Foote, Ron Bowes) | ||||||
|  | -------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   Two articles outlining the general principles and showing some example code. | ||||||
|  | 
 | ||||||
|  |   https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop | ||||||
|  |   https://goo.gl/j9EgFf | ||||||
|  | 
 | ||||||
|  | Fuzzer shell for SQLite (Richard Hipp) | ||||||
|  | -------------------------------------- | ||||||
|  | 
 | ||||||
|  |   A simple SQL shell designed specifically for fuzzing the underlying library. | ||||||
|  | 
 | ||||||
|  |   http://www.sqlite.org/src/artifact/9e7e273da2030371 | ||||||
|  | 
 | ||||||
|  | Support for Python mutation modules (Christian Holler) | ||||||
|  | ------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |   https://github.com/choller/afl/blob/master/docs/mozilla/python_modules.txt | ||||||
|  | 
 | ||||||
|  | Support for selective instrumentation (Christian Holler) | ||||||
|  | -------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   https://github.com/choller/afl/blob/master/docs/mozilla/partial_instrumentation.txt | ||||||
|  | 
 | ||||||
|  | Kernel fuzzing (Dmitry Vyukov) | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  |   A similar guided approach as applied to fuzzing syscalls: | ||||||
|  | 
 | ||||||
|  |   https://github.com/google/syzkaller/wiki/Found-Bugs | ||||||
|  |   https://github.com/dvyukov/linux/commit/33787098ffaaa83b8a7ccf519913ac5fd6125931 | ||||||
|  |   http://events.linuxfoundation.org/sites/events/files/slides/AFL%20filesystem%20fuzzing%2C%20Vault%202016_0.pdf | ||||||
|  | 
 | ||||||
|  | Android support (ele7enxxh) | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  |   Based on a somewhat dated version of AFL: | ||||||
|  | 
 | ||||||
|  |   https://github.com/ele7enxxh/android-afl | ||||||
|  | 
 | ||||||
|  | CGI wrapper (floyd) | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  |   Facilitates the testing of CGI scripts. | ||||||
|  | 
 | ||||||
|  |   https://github.com/floyd-fuh/afl-cgi-wrapper | ||||||
|  | 
 | ||||||
|  | Fuzzing difficulty estimation (Marcel Boehme) | ||||||
|  | --------------------------------------------- | ||||||
|  | 
 | ||||||
|  |   A fork of AFL that tries to quantify the likelihood of finding additional | ||||||
|  |   paths or crashes at any point in a fuzzing job. | ||||||
|  | 
 | ||||||
|  |   https://github.com/mboehme/pythia | ||||||
| @ -0,0 +1,408 @@ | |||||||
|  | =============================== | ||||||
|  | Understanding the status screen | ||||||
|  | =============================== | ||||||
|  | 
 | ||||||
|  |   This document provides an overview of the status screen - plus tips for | ||||||
|  |   troubleshooting any warnings and red text shown in the UI. See README for | ||||||
|  |   the general instruction manual. | ||||||
|  | 
 | ||||||
|  | 0) A note about colors | ||||||
|  | ---------------------- | ||||||
|  | 
 | ||||||
|  | The status screen and error messages use colors to keep things readable and | ||||||
|  | attract your attention to the most important details. For example, red almost | ||||||
|  | always means "consult this doc" :-) | ||||||
|  | 
 | ||||||
|  | Unfortunately, the UI will render correctly only if your terminal is using | ||||||
|  | traditional un*x palette (white text on black background) or something close | ||||||
|  | to that. | ||||||
|  | 
 | ||||||
|  | If you are using inverse video, you may want to change your settings, say: | ||||||
|  | 
 | ||||||
|  |   - For GNOME Terminal, go to Edit > Profile preferences, select the "colors" | ||||||
|  |     tab, and from the list of built-in schemes, choose "white on black". | ||||||
|  | 
 | ||||||
|  |   - For the MacOS X Terminal app, open a new window using the "Pro" scheme via | ||||||
|  |     the Shell > New Window menu (or make "Pro" your default). | ||||||
|  | 
 | ||||||
|  | Alternatively, if you really like your current colors, you can edit config.h | ||||||
|  | to comment out USE_COLORS, then do 'make clean all'. | ||||||
|  | 
 | ||||||
|  | I'm not aware of any other simple way to make this work without causing | ||||||
|  | other side effects - sorry about that. | ||||||
|  | 
 | ||||||
|  | With that out of the way, let's talk about what's actually on the screen... | ||||||
|  | 
 | ||||||
|  | 1) Process timing | ||||||
|  | ----------------- | ||||||
|  | 
 | ||||||
|  |   +----------------------------------------------------+ | ||||||
|  |   |        run time : 0 days, 8 hrs, 32 min, 43 sec    | | ||||||
|  |   |   last new path : 0 days, 0 hrs, 6 min, 40 sec     | | ||||||
|  |   | last uniq crash : none seen yet                    | | ||||||
|  |   |  last uniq hang : 0 days, 1 hrs, 24 min, 32 sec    | | ||||||
|  |   +----------------------------------------------------+ | ||||||
|  | 
 | ||||||
|  | This section is fairly self-explanatory: it tells you how long the fuzzer has | ||||||
|  | been running and how much time has elapsed since its most recent finds. This is | ||||||
|  | broken down into "paths" (a shorthand for test cases that trigger new execution | ||||||
|  | patterns), crashes, and hangs. | ||||||
|  | 
 | ||||||
|  | When it comes to timing: there is no hard rule, but most fuzzing jobs should be | ||||||
|  | expected to run for days or weeks; in fact, for a moderately complex project, the | ||||||
|  | first pass will probably take a day or so. Every now and then, some jobs | ||||||
|  | will be allowed to run for months. | ||||||
|  | 
 | ||||||
|  | There's one important thing to watch out for: if the tool is not finding new | ||||||
|  | paths within several minutes of starting, you're probably not invoking the | ||||||
|  | target binary correctly and it never gets to parse the input files we're | ||||||
|  | throwing at it; another possible explanations are that the default memory limit | ||||||
|  | (-m) is too restrictive, and the program exits after failing to allocate a | ||||||
|  | buffer very early on; or that the input files are patently invalid and always | ||||||
|  | fail a basic header check. | ||||||
|  | 
 | ||||||
|  | If there are no new paths showing up for a while, you will eventually see a big | ||||||
|  | red warning in this section, too :-) | ||||||
|  | 
 | ||||||
|  | 2) Overall results | ||||||
|  | ------------------ | ||||||
|  | 
 | ||||||
|  |   +-----------------------+ | ||||||
|  |   |  cycles done : 0      | | ||||||
|  |   |  total paths : 2095   | | ||||||
|  |   | uniq crashes : 0      | | ||||||
|  |   |   uniq hangs : 19     | | ||||||
|  |   +-----------------------+ | ||||||
|  | 
 | ||||||
|  | The first field in this section gives you the count of queue passes done so far | ||||||
|  | - that is, the number of times the fuzzer went over all the interesting test | ||||||
|  | cases discovered so far, fuzzed them, and looped back to the very beginning. | ||||||
|  | Every fuzzing session should be allowed to complete at least one cycle; and | ||||||
|  | ideally, should run much longer than that. | ||||||
|  | 
 | ||||||
|  | As noted earlier, the first pass can take a day or longer, so sit back and | ||||||
|  | relax. If you want to get broader but more shallow coverage right away, try | ||||||
|  | the -d option - it gives you a more familiar experience by skipping the | ||||||
|  | deterministic fuzzing steps. It is, however, inferior to the standard mode in | ||||||
|  | a couple of subtle ways. | ||||||
|  | 
 | ||||||
|  | To help make the call on when to hit Ctrl-C, the cycle counter is color-coded. | ||||||
|  | It is shown in magenta during the first pass, progresses to yellow if new finds | ||||||
|  | are still being made in subsequent rounds, then blue when that ends - and | ||||||
|  | finally, turns green after the fuzzer hasn't been seeing any action for a | ||||||
|  | longer while. | ||||||
|  | 
 | ||||||
|  | The remaining fields in this part of the screen should be pretty obvious: | ||||||
|  | there's the number of test cases ("paths") discovered so far, and the number of | ||||||
|  | unique faults. The test cases, crashes, and hangs can be explored in real-time | ||||||
|  | by browsing the output directory, as discussed in the README. | ||||||
|  | 
 | ||||||
|  | 3) Cycle progress | ||||||
|  | ----------------- | ||||||
|  | 
 | ||||||
|  |   +-------------------------------------+ | ||||||
|  |   |  now processing : 1296 (61.86%)     | | ||||||
|  |   | paths timed out : 0 (0.00%)         | | ||||||
|  |   +-------------------------------------+ | ||||||
|  | 
 | ||||||
|  | This box tells you how far along the fuzzer is with the current queue cycle: it | ||||||
|  | shows the ID of the test case it is currently working on, plus the number of | ||||||
|  | inputs it decided to ditch because they were persistently timing out. | ||||||
|  | 
 | ||||||
|  | The "*" suffix sometimes shown in the first line means that the currently | ||||||
|  | processed path is not "favored" (a property discussed later on, in section 6). | ||||||
|  | 
 | ||||||
|  | If you feel that the fuzzer is progressing too slowly, see the note about the | ||||||
|  | -d option in section 2 of this doc. | ||||||
|  | 
 | ||||||
|  | 4) Map coverage | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  |   +--------------------------------------+ | ||||||
|  |   |    map density : 10.15% / 29.07%     | | ||||||
|  |   | count coverage : 4.03 bits/tuple     | | ||||||
|  |   +--------------------------------------+ | ||||||
|  | 
 | ||||||
|  | The section provides some trivia about the coverage observed by the | ||||||
|  | instrumentation embedded in the target binary. | ||||||
|  | 
 | ||||||
|  | The first line in the box tells you how many branch tuples we have already | ||||||
|  | hit, in proportion to how much the bitmap can hold. The number on the left | ||||||
|  | describes the current input; the one on the right is the value for the entire | ||||||
|  | input corpus. | ||||||
|  | 
 | ||||||
|  | Be wary of extremes: | ||||||
|  | 
 | ||||||
|  |   - Absolute numbers below 200 or so suggest one of three things: that the | ||||||
|  |     program is extremely simple; that it is not instrumented properly (e.g., | ||||||
|  |     due to being linked against a non-instrumented copy of the target | ||||||
|  |     library); or that it is bailing out prematurely on your input test cases. | ||||||
|  |     The fuzzer will try to mark this in pink, just to make you aware. | ||||||
|  | 
 | ||||||
|  |   - Percentages over 70% may very rarely happen with very complex programs | ||||||
|  |     that make heavy use of template-generated code. | ||||||
|  | 
 | ||||||
|  |     Because high bitmap density makes it harder for the fuzzer to reliably | ||||||
|  |     discern new program states, I recommend recompiling the binary with | ||||||
|  |     AFL_INST_RATIO=10 or so and trying again (see env_variables.txt). | ||||||
|  | 
 | ||||||
|  |     The fuzzer will flag high percentages in red. Chances are, you will never | ||||||
|  |     see that unless you're fuzzing extremely hairy software (say, v8, perl, | ||||||
|  |     ffmpeg). | ||||||
|  | 
 | ||||||
|  | The other line deals with the variability in tuple hit counts seen in the | ||||||
|  | binary. In essence, if every taken branch is always taken a fixed number of | ||||||
|  | times for all the inputs we have tried, this will read "1.00". As we manage | ||||||
|  | to trigger other hit counts for every branch, the needle will start to move | ||||||
|  | toward "8.00" (every bit in the 8-bit map hit), but will probably never | ||||||
|  | reach that extreme. | ||||||
|  | 
 | ||||||
|  | Together, the values can be useful for comparing the coverage of several | ||||||
|  | different fuzzing jobs that rely on the same instrumented binary. | ||||||
|  | 
 | ||||||
|  | 5) Stage progress | ||||||
|  | ----------------- | ||||||
|  | 
 | ||||||
|  |   +-------------------------------------+ | ||||||
|  |   |  now trying : interest 32/8         | | ||||||
|  |   | stage execs : 3996/34.4k (11.62%)   | | ||||||
|  |   | total execs : 27.4M                 | | ||||||
|  |   |  exec speed : 891.7/sec             | | ||||||
|  |   +-------------------------------------+ | ||||||
|  | 
 | ||||||
|  | This part gives you an in-depth peek at what the fuzzer is actually doing right | ||||||
|  | now. It tells you about the current stage, which can be any of: | ||||||
|  | 
 | ||||||
|  |   - calibration - a pre-fuzzing stage where the execution path is examined | ||||||
|  |     to detect anomalies, establish baseline execution speed, and so on. Executed | ||||||
|  |     very briefly whenever a new find is being made. | ||||||
|  | 
 | ||||||
|  |   - trim L/S - another pre-fuzzing stage where the test case is trimmed to the | ||||||
|  |     shortest form that still produces the same execution path. The length (L) | ||||||
|  |     and stepover (S) are chosen in general relationship to file size. | ||||||
|  | 
 | ||||||
|  |   - bitflip L/S - deterministic bit flips. There are L bits toggled at any given | ||||||
|  |     time, walking the input file with S-bit increments. The current L/S variants | ||||||
|  |     are: 1/1, 2/1, 4/1, 8/8, 16/8, 32/8. | ||||||
|  | 
 | ||||||
|  |   - arith L/8 - deterministic arithmetics. The fuzzer tries to subtract or add | ||||||
|  |     small integers to 8-, 16-, and 32-bit values. The stepover is always 8 bits. | ||||||
|  | 
 | ||||||
|  |   - interest L/8 - deterministic value overwrite. The fuzzer has a list of known | ||||||
|  |     "interesting" 8-, 16-, and 32-bit values to try. The stepover is 8 bits. | ||||||
|  | 
 | ||||||
|  |   - extras - deterministic injection of dictionary terms. This can be shown as | ||||||
|  |     "user" or "auto", depending on whether the fuzzer is using a user-supplied | ||||||
|  |     dictionary (-x) or an auto-created one. You will also see "over" or "insert", | ||||||
|  |     depending on whether the dictionary words overwrite existing data or are | ||||||
|  |     inserted by offsetting the remaining data to accommodate their length. | ||||||
|  | 
 | ||||||
|  |   - havoc - a sort-of-fixed-length cycle with stacked random tweaks. The | ||||||
|  |     operations attempted during this stage include bit flips, overwrites with | ||||||
|  |     random and "interesting" integers, block deletion, block duplication, plus | ||||||
|  |     assorted dictionary-related operations (if a dictionary is supplied in the | ||||||
|  |     first place). | ||||||
|  | 
 | ||||||
|  |   - splice - a last-resort strategy that kicks in after the first full queue | ||||||
|  |     cycle with no new paths. It is equivalent to 'havoc', except that it first | ||||||
|  |     splices together two random inputs from the queue at some arbitrarily | ||||||
|  |     selected midpoint. | ||||||
|  | 
 | ||||||
|  |   - sync - a stage used only when -M or -S is set (see parallel_fuzzing.txt). | ||||||
|  |     No real fuzzing is involved, but the tool scans the output from other | ||||||
|  |     fuzzers and imports test cases as necessary. The first time this is done, | ||||||
|  |     it may take several minutes or so. | ||||||
|  | 
 | ||||||
|  | The remaining fields should be fairly self-evident: there's the exec count | ||||||
|  | progress indicator for the current stage, a global exec counter, and a | ||||||
|  | benchmark for the current program execution speed. This may fluctuate from | ||||||
|  | one test case to another, but the benchmark should be ideally over 500 execs/sec | ||||||
|  | most of the time - and if it stays below 100, the job will probably take very | ||||||
|  | long. | ||||||
|  | 
 | ||||||
|  | The fuzzer will explicitly warn you about slow targets, too. If this happens, | ||||||
|  | see the perf_tips.txt file included with the fuzzer for ideas on how to speed | ||||||
|  | things up. | ||||||
|  | 
 | ||||||
|  | 6) Findings in depth | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  |   +--------------------------------------+ | ||||||
|  |   | favored paths : 879 (41.96%)         | | ||||||
|  |   |  new edges on : 423 (20.19%)         | | ||||||
|  |   | total crashes : 0 (0 unique)         | | ||||||
|  |   |  total tmouts : 24 (19 unique)       | | ||||||
|  |   +--------------------------------------+ | ||||||
|  | 
 | ||||||
|  | This gives you several metrics that are of interest mostly to complete nerds. | ||||||
|  | The section includes the number of paths that the fuzzer likes the most based | ||||||
|  | on a minimization algorithm baked into the code (these will get considerably | ||||||
|  | more air time), and the number of test cases that actually resulted in better | ||||||
|  | edge coverage (versus just pushing the branch hit counters up). There are also | ||||||
|  | additional, more detailed counters for crashes and timeouts. | ||||||
|  | 
 | ||||||
|  | Note that the timeout counter is somewhat different from the hang counter; this | ||||||
|  | one includes all test cases that exceeded the timeout, even if they did not | ||||||
|  | exceed it by a margin sufficient to be classified as hangs. | ||||||
|  | 
 | ||||||
|  | 7) Fuzzing strategy yields | ||||||
|  | -------------------------- | ||||||
|  | 
 | ||||||
|  |   +-----------------------------------------------------+ | ||||||
|  |   |   bit flips : 57/289k, 18/289k, 18/288k             | | ||||||
|  |   |  byte flips : 0/36.2k, 4/35.7k, 7/34.6k             | | ||||||
|  |   | arithmetics : 53/2.54M, 0/537k, 0/55.2k             | | ||||||
|  |   |  known ints : 8/322k, 12/1.32M, 10/1.70M            | | ||||||
|  |   |  dictionary : 9/52k, 1/53k, 1/24k                   | | ||||||
|  |   |       havoc : 1903/20.0M, 0/0                       | | ||||||
|  |   |        trim : 20.31%/9201, 17.05%                   | | ||||||
|  |   +-----------------------------------------------------+ | ||||||
|  | 
 | ||||||
|  | This is just another nerd-targeted section keeping track of how many paths we | ||||||
|  | have netted, in proportion to the number of execs attempted, for each of the | ||||||
|  | fuzzing strategies discussed earlier on. This serves to convincingly validate | ||||||
|  | assumptions about the usefulness of the various approaches taken by afl-fuzz. | ||||||
|  | 
 | ||||||
|  | The trim strategy stats in this section are a bit different than the rest. | ||||||
|  | The first number in this line shows the ratio of bytes removed from the input | ||||||
|  | files; the second one corresponds to the number of execs needed to achieve this | ||||||
|  | goal. Finally, the third number shows the proportion of bytes that, although | ||||||
|  | not possible to remove, were deemed to have no effect and were excluded from | ||||||
|  | some of the more expensive deterministic fuzzing steps. | ||||||
|  | 
 | ||||||
|  | 8) Path geometry | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  |   +---------------------+ | ||||||
|  |   |    levels : 5       | | ||||||
|  |   |   pending : 1570    | | ||||||
|  |   |  pend fav : 583     | | ||||||
|  |   | own finds : 0       | | ||||||
|  |   |  imported : 0       | | ||||||
|  |   | stability : 100.00% | | ||||||
|  |   +---------------------+ | ||||||
|  | 
 | ||||||
|  | The first field in this section tracks the path depth reached through the | ||||||
|  | guided fuzzing process. In essence: the initial test cases supplied by the | ||||||
|  | user are considered "level 1". The test cases that can be derived from that | ||||||
|  | through traditional fuzzing are considered "level 2"; the ones derived by | ||||||
|  | using these as inputs to subsequent fuzzing rounds are "level 3"; and so forth. | ||||||
|  | The maximum depth is therefore a rough proxy for how much value you're getting | ||||||
|  | out of the instrumentation-guided approach taken by afl-fuzz. | ||||||
|  | 
 | ||||||
|  | The next field shows you the number of inputs that have not gone through any | ||||||
|  | fuzzing yet. The same stat is also given for "favored" entries that the fuzzer | ||||||
|  | really wants to get to in this queue cycle (the non-favored entries may have to | ||||||
|  | wait a couple of cycles to get their chance). | ||||||
|  | 
 | ||||||
|  | Next, we have the number of new paths found during this fuzzing section and | ||||||
|  | imported from other fuzzer instances when doing parallelized fuzzing; and the | ||||||
|  | extent to which identical inputs appear to sometimes produce variable behavior | ||||||
|  | in the tested binary. | ||||||
|  | 
 | ||||||
|  | That last bit is actually fairly interesting: it measures the consistency of | ||||||
|  | observed traces. If a program always behaves the same for the same input data, | ||||||
|  | it will earn a score of 100%. When the value is lower but still shown in purple, | ||||||
|  | the fuzzing process is unlikely to be negatively affected. If it goes into red, | ||||||
|  | you may be in trouble, since AFL will have difficulty discerning between | ||||||
|  | meaningful and "phantom" effects of tweaking the input file. | ||||||
|  | 
 | ||||||
|  | Now, most targets will just get a 100% score, but when you see lower figures, | ||||||
|  | there are several things to look at: | ||||||
|  | 
 | ||||||
|  |   - The use of uninitialized memory in conjunction with some intrinsic sources | ||||||
|  |     of entropy in the tested binary. Harmless to AFL, but could be indicative | ||||||
|  |     of a security bug. | ||||||
|  | 
 | ||||||
|  |   - Attempts to manipulate persistent resources, such as left over temporary | ||||||
|  |     files or shared memory objects. This is usually harmless, but you may want | ||||||
|  |     to double-check to make sure the program isn't bailing out prematurely. | ||||||
|  |     Running out of disk space, SHM handles, or other global resources can | ||||||
|  |     trigger this, too. | ||||||
|  | 
 | ||||||
|  |   - Hitting some functionality that is actually designed to behave randomly. | ||||||
|  |     Generally harmless. For example, when fuzzing sqlite, an input like | ||||||
|  |     'select random();' will trigger a variable execution path. | ||||||
|  | 
 | ||||||
|  |   - Multiple threads executing at once in semi-random order. This is harmless | ||||||
|  |     when the 'stability' metric stays over 90% or so, but can become an issue | ||||||
|  |     if not. Here's what to try: | ||||||
|  | 
 | ||||||
|  |     - Use afl-clang-fast from llvm_mode/ - it uses a thread-local tracking | ||||||
|  |       model that is less prone to concurrency issues, | ||||||
|  | 
 | ||||||
|  |     - See if the target can be compiled or run without threads. Common | ||||||
|  |       ./configure options include --without-threads, --disable-pthreads, or | ||||||
|  |       --disable-openmp. | ||||||
|  | 
 | ||||||
|  |     - Replace pthreads with GNU Pth (https://www.gnu.org/software/pth/), which | ||||||
|  |       allows you to use a deterministic scheduler. | ||||||
|  | 
 | ||||||
|  |   - In persistent mode, minor drops in the "stability" metric can be normal, | ||||||
|  |     because not all the code behaves identically when re-entered; but major | ||||||
|  |     dips may signify that the code within __AFL_LOOP() is not behaving | ||||||
|  |     correctly on subsequent iterations (e.g., due to incomplete clean-up or | ||||||
|  |     reinitialization of the state) and that most of the fuzzing effort goes | ||||||
|  |     to waste. | ||||||
|  | 
 | ||||||
|  | The paths where variable behavior is detected are marked with a matching entry | ||||||
|  | in the <out_dir>/queue/.state/variable_behavior/ directory, so you can look | ||||||
|  | them up easily. | ||||||
|  | 
 | ||||||
|  | 9) CPU load | ||||||
|  | ----------- | ||||||
|  | 
 | ||||||
|  |   [cpu: 25%] | ||||||
|  | 
 | ||||||
|  | This tiny widget shows the apparent CPU utilization on the local system. It is | ||||||
|  | calculated by taking the number of processes in the "runnable" state, and then | ||||||
|  | comparing it to the number of logical cores on the system. | ||||||
|  | 
 | ||||||
|  | If the value is shown in green, you are using fewer CPU cores than available on | ||||||
|  | your system and can probably parallelize to improve performance; for tips on | ||||||
|  | how to do that, see parallel_fuzzing.txt. | ||||||
|  | 
 | ||||||
|  | If the value is shown in red, your CPU is *possibly* oversubscribed, and | ||||||
|  | running additional fuzzers may not give you any benefits. | ||||||
|  | 
 | ||||||
|  | Of course, this benchmark is very simplistic; it tells you how many processes | ||||||
|  | are ready to run, but not how resource-hungry they may be. It also doesn't | ||||||
|  | distinguish between physical cores, logical cores, and virtualized CPUs; the | ||||||
|  | performance characteristics of each of these will differ quite a bit. | ||||||
|  | 
 | ||||||
|  | If you want a more accurate measurement, you can run the afl-gotcpu utility | ||||||
|  | from the command line. | ||||||
|  | 
 | ||||||
|  | 10) Addendum: status and plot files | ||||||
|  | ----------------------------------- | ||||||
|  | 
 | ||||||
|  | For unattended operation, some of the key status screen information can be also | ||||||
|  | found in a machine-readable format in the fuzzer_stats file in the output | ||||||
|  | directory. This includes: | ||||||
|  | 
 | ||||||
|  |   - start_time     - unix time indicating the start time of afl-fuzz | ||||||
|  |   - last_update    - unix time corresponding to the last update of this file | ||||||
|  |   - fuzzer_pid     - PID of the fuzzer process | ||||||
|  |   - cycles_done    - queue cycles completed so far | ||||||
|  |   - execs_done     - number of execve() calls attempted | ||||||
|  |   - execs_per_sec  - current number of execs per second | ||||||
|  |   - paths_total    - total number of entries in the queue | ||||||
|  |   - paths_found    - number of entries discovered through local fuzzing | ||||||
|  |   - paths_imported - number of entries imported from other instances | ||||||
|  |   - max_depth      - number of levels in the generated data set | ||||||
|  |   - cur_path       - currently processed entry number | ||||||
|  |   - pending_favs   - number of favored entries still waiting to be fuzzed | ||||||
|  |   - pending_total  - number of all entries waiting to be fuzzed | ||||||
|  |   - stability      - percentage of bitmap bytes that behave consistently | ||||||
|  |   - variable_paths - number of test cases showing variable behavior | ||||||
|  |   - unique_crashes - number of unique crashes recorded | ||||||
|  |   - unique_hangs   - number of unique hangs encountered | ||||||
|  |   - command_line   - full command line used for the fuzzing session | ||||||
|  |   - slowest_exec_ms- real time of the slowest execution in ms | ||||||
|  |   - peak_rss_mb    - max rss usage reached during fuzzing in mb | ||||||
|  | 
 | ||||||
|  | Most of these map directly to the UI elements discussed earlier on. | ||||||
|  | 
 | ||||||
|  | On top of that, you can also find an entry called 'plot_data', containing a | ||||||
|  | plottable history for most of these fields. If you have gnuplot installed, you | ||||||
|  | can turn this into a nice progress report with the included 'afl-plot' tool. | ||||||
| @ -0,0 +1,563 @@ | |||||||
|  | =================================== | ||||||
|  | Technical "whitepaper" for afl-fuzz | ||||||
|  | =================================== | ||||||
|  | 
 | ||||||
|  |   This document provides a quick overview of the guts of American Fuzzy Lop. | ||||||
|  |   See README for the general instruction manual; and for a discussion of | ||||||
|  |   motivations and design goals behind AFL, see historical_notes.txt. | ||||||
|  | 
 | ||||||
|  | 0) Design statement | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  | American Fuzzy Lop does its best not to focus on any singular principle of | ||||||
|  | operation and not be a proof-of-concept for any specific theory. The tool can | ||||||
|  | be thought of as a collection of hacks that have been tested in practice, | ||||||
|  | found to be surprisingly effective, and have been implemented in the simplest, | ||||||
|  | most robust way I could think of at the time. | ||||||
|  | 
 | ||||||
|  | Many of the resulting features are made possible thanks to the availability of | ||||||
|  | lightweight instrumentation that served as a foundation for the tool, but this | ||||||
|  | mechanism should be thought of merely as a means to an end. The only true | ||||||
|  | governing principles are speed, reliability, and ease of use. | ||||||
|  | 
 | ||||||
|  | 1) Coverage measurements | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | The instrumentation injected into compiled programs captures branch (edge) | ||||||
|  | coverage, along with coarse branch-taken hit counts. The code injected at | ||||||
|  | branch points is essentially equivalent to: | ||||||
|  | 
 | ||||||
|  |   cur_location = <COMPILE_TIME_RANDOM>; | ||||||
|  |   shared_mem[cur_location ^ prev_location]++;  | ||||||
|  |   prev_location = cur_location >> 1; | ||||||
|  | 
 | ||||||
|  | The cur_location value is generated randomly to simplify the process of | ||||||
|  | linking complex projects and keep the XOR output distributed uniformly. | ||||||
|  | 
 | ||||||
|  | The shared_mem[] array is a 64 kB SHM region passed to the instrumented binary | ||||||
|  | by the caller. Every byte set in the output map can be thought of as a hit for | ||||||
|  | a particular (branch_src, branch_dst) tuple in the instrumented code. | ||||||
|  | 
 | ||||||
|  | The size of the map is chosen so that collisions are sporadic with almost all | ||||||
|  | of the intended targets, which usually sport between 2k and 10k discoverable | ||||||
|  | branch points: | ||||||
|  | 
 | ||||||
|  |    Branch cnt | Colliding tuples | Example targets | ||||||
|  |   ------------+------------------+----------------- | ||||||
|  |         1,000 | 0.75%            | giflib, lzo | ||||||
|  |         2,000 | 1.5%             | zlib, tar, xz | ||||||
|  |         5,000 | 3.5%             | libpng, libwebp | ||||||
|  |        10,000 | 7%               | libxml | ||||||
|  |        20,000 | 14%              | sqlite | ||||||
|  |        50,000 | 30%              | - | ||||||
|  | 
 | ||||||
|  | At the same time, its size is small enough to allow the map to be analyzed | ||||||
|  | in a matter of microseconds on the receiving end, and to effortlessly fit | ||||||
|  | within L2 cache. | ||||||
|  | 
 | ||||||
|  | This form of coverage provides considerably more insight into the execution | ||||||
|  | path of the program than simple block coverage. In particular, it trivially | ||||||
|  | distinguishes between the following execution traces: | ||||||
|  | 
 | ||||||
|  |   A -> B -> C -> D -> E (tuples: AB, BC, CD, DE) | ||||||
|  |   A -> B -> D -> C -> E (tuples: AB, BD, DC, CE) | ||||||
|  | 
 | ||||||
|  | This aids the discovery of subtle fault conditions in the underlying code, | ||||||
|  | because security vulnerabilities are more often associated with unexpected | ||||||
|  | or incorrect state transitions than with merely reaching a new basic block. | ||||||
|  | 
 | ||||||
|  | The reason for the shift operation in the last line of the pseudocode shown | ||||||
|  | earlier in this section is to preserve the directionality of tuples (without | ||||||
|  | this, A ^ B would be indistinguishable from B ^ A) and to retain the identity | ||||||
|  | of tight loops (otherwise, A ^ A would be obviously equal to B ^ B). | ||||||
|  | 
 | ||||||
|  | The absence of simple saturating arithmetic opcodes on Intel CPUs means that | ||||||
|  | the hit counters can sometimes wrap around to zero. Since this is a fairly | ||||||
|  | unlikely and localized event, it's seen as an acceptable performance trade-off. | ||||||
|  | 
 | ||||||
|  | 2) Detecting new behaviors | ||||||
|  | -------------------------- | ||||||
|  | 
 | ||||||
|  | The fuzzer maintains a global map of tuples seen in previous executions; this | ||||||
|  | data can be rapidly compared with individual traces and updated in just a couple | ||||||
|  | of dword- or qword-wide instructions and a simple loop. | ||||||
|  | 
 | ||||||
|  | When a mutated input produces an execution trace containing new tuples, the | ||||||
|  | corresponding input file is preserved and routed for additional processing | ||||||
|  | later on (see section #3). Inputs that do not trigger new local-scale state | ||||||
|  | transitions in the execution trace (i.e., produce no new tuples) are discarded, | ||||||
|  | even if their overall control flow sequence is unique. | ||||||
|  | 
 | ||||||
|  | This approach allows for a very fine-grained and long-term exploration of | ||||||
|  | program state while not having to perform any computationally intensive and | ||||||
|  | fragile global comparisons of complex execution traces, and while avoiding the | ||||||
|  | scourge of path explosion. | ||||||
|  | 
 | ||||||
|  | To illustrate the properties of the algorithm, consider that the second trace | ||||||
|  | shown below would be considered substantially new because of the presence of | ||||||
|  | new tuples (CA, AE): | ||||||
|  | 
 | ||||||
|  |   #1: A -> B -> C -> D -> E | ||||||
|  |   #2: A -> B -> C -> A -> E | ||||||
|  | 
 | ||||||
|  | At the same time, with #2 processed, the following pattern will not be seen | ||||||
|  | as unique, despite having a markedly different overall execution path: | ||||||
|  | 
 | ||||||
|  |   #3: A -> B -> C -> A -> B -> C -> A -> B -> C -> D -> E | ||||||
|  | 
 | ||||||
|  | In addition to detecting new tuples, the fuzzer also considers coarse tuple | ||||||
|  | hit counts. These are divided into several buckets: | ||||||
|  | 
 | ||||||
|  |   1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+ | ||||||
|  | 
 | ||||||
|  | To some extent, the number of buckets is an implementation artifact: it allows | ||||||
|  | an in-place mapping of an 8-bit counter generated by the instrumentation to | ||||||
|  | an 8-position bitmap relied on by the fuzzer executable to keep track of the | ||||||
|  | already-seen execution counts for each tuple. | ||||||
|  | 
 | ||||||
|  | Changes within the range of a single bucket are ignored; transition from one | ||||||
|  | bucket to another is flagged as an interesting change in program control flow, | ||||||
|  | and is routed to the evolutionary process outlined in the section below. | ||||||
|  | 
 | ||||||
|  | The hit count behavior provides a way to distinguish between potentially | ||||||
|  | interesting control flow changes, such as a block of code being executed | ||||||
|  | twice when it was normally hit only once. At the same time, it is fairly | ||||||
|  | insensitive to empirically less notable changes, such as a loop going from | ||||||
|  | 47 cycles to 48. The counters also provide some degree of "accidental" | ||||||
|  | immunity against tuple collisions in dense trace maps. | ||||||
|  | 
 | ||||||
|  | The execution is policed fairly heavily through memory and execution time | ||||||
|  | limits; by default, the timeout is set at 5x the initially-calibrated | ||||||
|  | execution speed, rounded up to 20 ms. The aggressive timeouts are meant to | ||||||
|  | prevent dramatic fuzzer performance degradation by descending into tarpits | ||||||
|  | that, say, improve coverage by 1% while being 100x slower; we pragmatically | ||||||
|  | reject them and hope that the fuzzer will find a less expensive way to reach | ||||||
|  | the same code. Empirical testing strongly suggests that more generous time | ||||||
|  | limits are not worth the cost. | ||||||
|  | 
 | ||||||
|  | 3) Evolving the input queue | ||||||
|  | --------------------------- | ||||||
|  | 
 | ||||||
|  | Mutated test cases that produced new state transitions within the program are | ||||||
|  | added to the input queue and used as a starting point for future rounds of | ||||||
|  | fuzzing. They supplement, but do not automatically replace, existing finds. | ||||||
|  | 
 | ||||||
|  | In contrast to more greedy genetic algorithms, this approach allows the tool | ||||||
|  | to progressively explore various disjoint and possibly mutually incompatible | ||||||
|  | features of the underlying data format, as shown in this image: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.coredump.cx/afl/afl_gzip.png | ||||||
|  | 
 | ||||||
|  | Several practical examples of the results of this algorithm are discussed | ||||||
|  | here: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.blogspot.com/2014/11/pulling-jpegs-out-of-thin-air.html | ||||||
|  |   http://lcamtuf.blogspot.com/2014/11/afl-fuzz-nobody-expects-cdata-sections.html | ||||||
|  | 
 | ||||||
|  | The synthetic corpus produced by this process is essentially a compact | ||||||
|  | collection of "hmm, this does something new!" input files, and can be used to | ||||||
|  | seed any other testing processes down the line (for example, to manually | ||||||
|  | stress-test resource-intensive desktop apps). | ||||||
|  | 
 | ||||||
|  | With this approach, the queue for most targets grows to somewhere between 1k | ||||||
|  | and 10k entries; approximately 10-30% of this is attributable to the discovery | ||||||
|  | of new tuples, and the remainder is associated with changes in hit counts. | ||||||
|  | 
 | ||||||
|  | The following table compares the relative ability to discover file syntax and | ||||||
|  | explore program states when using several different approaches to guided | ||||||
|  | fuzzing. The instrumented target was GNU patch 2.7.3 compiled with -O3 and | ||||||
|  | seeded with a dummy text file; the session consisted of a single pass over the | ||||||
|  | input queue with afl-fuzz: | ||||||
|  | 
 | ||||||
|  |     Fuzzer guidance | Blocks  | Edges   | Edge hit | Highest-coverage | ||||||
|  |       strategy used | reached | reached | cnt var  | test case generated | ||||||
|  |   ------------------+---------+---------+----------+--------------------------- | ||||||
|  |      (Initial file) | 156     | 163     | 1.00     | (none) | ||||||
|  |                     |         |         |          | | ||||||
|  |     Blind fuzzing S | 182     | 205     | 2.23     | First 2 B of RCS diff | ||||||
|  |     Blind fuzzing L | 228     | 265     | 2.23     | First 4 B of -c mode diff | ||||||
|  |      Block coverage | 855     | 1,130   | 1.57     | Almost-valid RCS diff | ||||||
|  |       Edge coverage | 1,452   | 2,070   | 2.18     | One-chunk -c mode diff | ||||||
|  |           AFL model | 1,765   | 2,597   | 4.99     | Four-chunk -c mode diff | ||||||
|  | 
 | ||||||
|  | The first entry for blind fuzzing ("S") corresponds to executing just a single | ||||||
|  | round of testing; the second set of figures ("L") shows the fuzzer running in a | ||||||
|  | loop for a number of execution cycles comparable with that of the instrumented | ||||||
|  | runs, which required more time to fully process the growing queue. | ||||||
|  | 
 | ||||||
|  | Roughly similar results have been obtained in a separate experiment where the | ||||||
|  | fuzzer was modified to compile out all the random fuzzing stages and leave just | ||||||
|  | a series of rudimentary, sequential operations such as walking bit flips. | ||||||
|  | Because this mode would be incapable of altering the size of the input file, | ||||||
|  | the sessions were seeded with a valid unified diff: | ||||||
|  | 
 | ||||||
|  |     Queue extension | Blocks  | Edges   | Edge hit | Number of unique | ||||||
|  |       strategy used | reached | reached | cnt var  | crashes found | ||||||
|  |   ------------------+---------+---------+----------+------------------ | ||||||
|  |      (Initial file) | 624     | 717     | 1.00     | - | ||||||
|  |                     |         |         |          | | ||||||
|  |       Blind fuzzing | 1,101   | 1,409   | 1.60     | 0 | ||||||
|  |      Block coverage | 1,255   | 1,649   | 1.48     | 0 | ||||||
|  |       Edge coverage | 1,259   | 1,734   | 1.72     | 0 | ||||||
|  |           AFL model | 1,452   | 2,040   | 3.16     | 1 | ||||||
|  | 
 | ||||||
|  | At noted earlier on, some of the prior work on genetic fuzzing relied on | ||||||
|  | maintaining a single test case and evolving it to maximize coverage. At least | ||||||
|  | in the tests described above, this "greedy" approach appears to confer no | ||||||
|  | substantial benefits over blind fuzzing strategies. | ||||||
|  | 
 | ||||||
|  | 4) Culling the corpus | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  | The progressive state exploration approach outlined above means that some of | ||||||
|  | the test cases synthesized later on in the game may have edge coverage that | ||||||
|  | is a strict superset of the coverage provided by their ancestors. | ||||||
|  | 
 | ||||||
|  | To optimize the fuzzing effort, AFL periodically re-evaluates the queue using a | ||||||
|  | fast algorithm that selects a smaller subset of test cases that still cover | ||||||
|  | every tuple seen so far, and whose characteristics make them particularly | ||||||
|  | favorable to the tool. | ||||||
|  | 
 | ||||||
|  | The algorithm works by assigning every queue entry a score proportional to its | ||||||
|  | execution latency and file size; and then selecting lowest-scoring candidates | ||||||
|  | for each tuple. | ||||||
|  | 
 | ||||||
|  | The tuples are then processed sequentially using a simple workflow: | ||||||
|  | 
 | ||||||
|  |   1) Find next tuple not yet in the temporary working set, | ||||||
|  | 
 | ||||||
|  |   2) Locate the winning queue entry for this tuple, | ||||||
|  | 
 | ||||||
|  |   3) Register *all* tuples present in that entry's trace in the working set, | ||||||
|  | 
 | ||||||
|  |   4) Go to #1 if there are any missing tuples in the set. | ||||||
|  | 
 | ||||||
|  | The generated corpus of "favored" entries is usually 5-10x smaller than the | ||||||
|  | starting data set. Non-favored entries are not discarded, but they are skipped | ||||||
|  | with varying probabilities when encountered in the queue: | ||||||
|  | 
 | ||||||
|  |   - If there are new, yet-to-be-fuzzed favorites present in the queue, 99% | ||||||
|  |     of non-favored entries will be skipped to get to the favored ones. | ||||||
|  | 
 | ||||||
|  |   - If there are no new favorites: | ||||||
|  | 
 | ||||||
|  |     - If the current non-favored entry was fuzzed before, it will be skipped | ||||||
|  |       95% of the time. | ||||||
|  | 
 | ||||||
|  |     - If it hasn't gone through any fuzzing rounds yet, the odds of skipping | ||||||
|  |       drop down to 75%. | ||||||
|  | 
 | ||||||
|  | Based on empirical testing, this provides a reasonable balance between queue | ||||||
|  | cycling speed and test case diversity. | ||||||
|  | 
 | ||||||
|  | Slightly more sophisticated but much slower culling can be performed on input | ||||||
|  | or output corpora with afl-cmin. This tool permanently discards the redundant | ||||||
|  | entries and produces a smaller corpus suitable for use with afl-fuzz or | ||||||
|  | external tools. | ||||||
|  | 
 | ||||||
|  | 5) Trimming input files | ||||||
|  | ----------------------- | ||||||
|  | 
 | ||||||
|  | File size has a dramatic impact on fuzzing performance, both because large | ||||||
|  | files make the target binary slower, and because they reduce the likelihood | ||||||
|  | that a mutation would touch important format control structures, rather than | ||||||
|  | redundant data blocks. This is discussed in more detail in perf_tips.txt. | ||||||
|  | 
 | ||||||
|  | The possibility that the user will provide a low-quality starting corpus aside, | ||||||
|  | some types of mutations can have the effect of iteratively increasing the size | ||||||
|  | of the generated files, so it is important to counter this trend. | ||||||
|  | 
 | ||||||
|  | Luckily, the instrumentation feedback provides a simple way to automatically | ||||||
|  | trim down input files while ensuring that the changes made to the files have no | ||||||
|  | impact on the execution path. | ||||||
|  | 
 | ||||||
|  | The built-in trimmer in afl-fuzz attempts to sequentially remove blocks of data | ||||||
|  | with variable length and stepover; any deletion that doesn't affect the checksum | ||||||
|  | of the trace map is committed to disk. The trimmer is not designed to be | ||||||
|  | particularly thorough; instead, it tries to strike a balance between precision | ||||||
|  | and the number of execve() calls spent on the process, selecting the block size | ||||||
|  | and stepover to match. The average per-file gains are around 5-20%. | ||||||
|  | 
 | ||||||
|  | The standalone afl-tmin tool uses a more exhaustive, iterative algorithm, and | ||||||
|  | also attempts to perform alphabet normalization on the trimmed files. The | ||||||
|  | operation of afl-tmin is as follows. | ||||||
|  | 
 | ||||||
|  | First, the tool automatically selects the operating mode. If the initial input | ||||||
|  | crashes the target binary, afl-tmin will run in non-instrumented mode, simply | ||||||
|  | keeping any tweaks that produce a simpler file but still crash the target. If | ||||||
|  | the target is non-crashing, the tool uses an instrumented mode and keeps only | ||||||
|  | the tweaks that produce exactly the same execution path. | ||||||
|  | 
 | ||||||
|  | The actual minimization algorithm is: | ||||||
|  | 
 | ||||||
|  |   1) Attempt to zero large blocks of data with large stepovers. Empirically, | ||||||
|  |      this is shown to reduce the number of execs by preempting finer-grained | ||||||
|  |      efforts later on. | ||||||
|  | 
 | ||||||
|  |   2) Perform a block deletion pass with decreasing block sizes and stepovers, | ||||||
|  |      binary-search-style.  | ||||||
|  | 
 | ||||||
|  |   3) Perform alphabet normalization by counting unique characters and trying | ||||||
|  |      to bulk-replace each with a zero value. | ||||||
|  | 
 | ||||||
|  |   4) As a last result, perform byte-by-byte normalization on non-zero bytes. | ||||||
|  | 
 | ||||||
|  | Instead of zeroing with a 0x00 byte, afl-tmin uses the ASCII digit '0'. This | ||||||
|  | is done because such a modification is much less likely to interfere with | ||||||
|  | text parsing, so it is more likely to result in successful minimization of | ||||||
|  | text files. | ||||||
|  | 
 | ||||||
|  | The algorithm used here is less involved than some other test case | ||||||
|  | minimization approaches proposed in academic work, but requires far fewer | ||||||
|  | executions and tends to produce comparable results in most real-world | ||||||
|  | applications. | ||||||
|  | 
 | ||||||
|  | 6) Fuzzing strategies | ||||||
|  | --------------------- | ||||||
|  | 
 | ||||||
|  | The feedback provided by the instrumentation makes it easy to understand the | ||||||
|  | value of various fuzzing strategies and optimize their parameters so that they | ||||||
|  | work equally well across a wide range of file types. The strategies used by | ||||||
|  | afl-fuzz are generally format-agnostic and are discussed in more detail here: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.blogspot.com/2014/08/binary-fuzzing-strategies-what-works.html | ||||||
|  | 
 | ||||||
|  | It is somewhat notable that especially early on, most of the work done by | ||||||
|  | afl-fuzz is actually highly deterministic, and progresses to random stacked | ||||||
|  | modifications and test case splicing only at a later stage. The deterministic | ||||||
|  | strategies include: | ||||||
|  | 
 | ||||||
|  |   - Sequential bit flips with varying lengths and stepovers, | ||||||
|  | 
 | ||||||
|  |   - Sequential addition and subtraction of small integers, | ||||||
|  | 
 | ||||||
|  |   - Sequential insertion of known interesting integers (0, 1, INT_MAX, etc), | ||||||
|  | 
 | ||||||
|  | The purpose of opening with deterministic steps is related to their tendency to | ||||||
|  | produce compact test cases and small diffs between the non-crashing and crashing | ||||||
|  | inputs. | ||||||
|  | 
 | ||||||
|  | With deterministic fuzzing out of the way, the non-deterministic steps include | ||||||
|  | stacked bit flips, insertions, deletions, arithmetics, and splicing of different | ||||||
|  | test cases. | ||||||
|  | 
 | ||||||
|  | The relative yields and execve() costs of all these strategies have been | ||||||
|  | investigated and are discussed in the aforementioned blog post. | ||||||
|  | 
 | ||||||
|  | For the reasons discussed in historical_notes.txt (chiefly, performance, | ||||||
|  | simplicity, and reliability), AFL generally does not try to reason about the | ||||||
|  | relationship between specific mutations and program states; the fuzzing steps | ||||||
|  | are nominally blind, and are guided only by the evolutionary design of the | ||||||
|  | input queue. | ||||||
|  | 
 | ||||||
|  | That said, there is one (trivial) exception to this rule: when a new queue | ||||||
|  | entry goes through the initial set of deterministic fuzzing steps, and tweaks to | ||||||
|  | some regions in the file are observed to have no effect on the checksum of the | ||||||
|  | execution path, they may be excluded from the remaining phases of | ||||||
|  | deterministic fuzzing - and the fuzzer may proceed straight to random tweaks. | ||||||
|  | Especially for verbose, human-readable data formats, this can reduce the number | ||||||
|  | of execs by 10-40% or so without an appreciable drop in coverage. In extreme | ||||||
|  | cases, such as normally block-aligned tar archives, the gains can be as high as | ||||||
|  | 90%. | ||||||
|  | 
 | ||||||
|  | Because the underlying "effector maps" are local every queue entry and remain | ||||||
|  | in force only during deterministic stages that do not alter the size or the | ||||||
|  | general layout of the underlying file, this mechanism appears to work very | ||||||
|  | reliably and proved to be simple to implement. | ||||||
|  | 
 | ||||||
|  | 7) Dictionaries | ||||||
|  | --------------- | ||||||
|  | 
 | ||||||
|  | The feedback provided by the instrumentation makes it easy to automatically | ||||||
|  | identify syntax tokens in some types of input files, and to detect that certain | ||||||
|  | combinations of predefined or auto-detected dictionary terms constitute a | ||||||
|  | valid grammar for the tested parser. | ||||||
|  | 
 | ||||||
|  | A discussion of how these features are implemented within afl-fuzz can be found | ||||||
|  | here: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.blogspot.com/2015/01/afl-fuzz-making-up-grammar-with.html | ||||||
|  | 
 | ||||||
|  | In essence, when basic, typically easily-obtained syntax tokens are combined | ||||||
|  | together in a purely random manner, the instrumentation and the evolutionary | ||||||
|  | design of the queue together provide a feedback mechanism to differentiate | ||||||
|  | between meaningless mutations and ones that trigger new behaviors in the | ||||||
|  | instrumented code - and to incrementally build more complex syntax on top of | ||||||
|  | this discovery. | ||||||
|  | 
 | ||||||
|  | The dictionaries have been shown to enable the fuzzer to rapidly reconstruct | ||||||
|  | the grammar of highly verbose and complex languages such as JavaScript, SQL, | ||||||
|  | or XML; several examples of generated SQL statements are given in the blog | ||||||
|  | post mentioned above. | ||||||
|  | 
 | ||||||
|  | Interestingly, the AFL instrumentation also allows the fuzzer to automatically | ||||||
|  | isolate syntax tokens already present in an input file. It can do so by looking | ||||||
|  | for run of bytes that, when flipped, produce a consistent change to the | ||||||
|  | program's execution path; this is suggestive of an underlying atomic comparison | ||||||
|  | to a predefined value baked into the code. The fuzzer relies on this signal | ||||||
|  | to build compact "auto dictionaries" that are then used in conjunction with | ||||||
|  | other fuzzing strategies. | ||||||
|  | 
 | ||||||
|  | 8) De-duping crashes | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | De-duplication of crashes is one of the more important problems for any | ||||||
|  | competent fuzzing tool. Many of the naive approaches run into problems; in | ||||||
|  | particular, looking just at the faulting address may lead to completely | ||||||
|  | unrelated issues being clustered together if the fault happens in a common | ||||||
|  | library function (say, strcmp, strcpy); while checksumming call stack | ||||||
|  | backtraces can lead to extreme crash count inflation if the fault can be | ||||||
|  | reached through a number of different, possibly recursive code paths. | ||||||
|  | 
 | ||||||
|  | The solution implemented in afl-fuzz considers a crash unique if any of two | ||||||
|  | conditions are met: | ||||||
|  | 
 | ||||||
|  |   - The crash trace includes a tuple not seen in any of the previous crashes, | ||||||
|  | 
 | ||||||
|  |   - The crash trace is missing a tuple that was always present in earlier | ||||||
|  |     faults. | ||||||
|  | 
 | ||||||
|  | The approach is vulnerable to some path count inflation early on, but exhibits | ||||||
|  | a very strong self-limiting effect, similar to the execution path analysis | ||||||
|  | logic that is the cornerstone of afl-fuzz. | ||||||
|  | 
 | ||||||
|  | 9) Investigating crashes | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | The exploitability of many types of crashes can be ambiguous; afl-fuzz tries | ||||||
|  | to address this by providing a crash exploration mode where a known-faulting | ||||||
|  | test case is fuzzed in a manner very similar to the normal operation of the | ||||||
|  | fuzzer, but with a constraint that causes any non-crashing mutations to be | ||||||
|  | thrown away. | ||||||
|  | 
 | ||||||
|  | A detailed discussion of the value of this approach can be found here: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.blogspot.com/2014/11/afl-fuzz-crash-exploration-mode.html | ||||||
|  | 
 | ||||||
|  | The method uses instrumentation feedback to explore the state of the crashing | ||||||
|  | program to get past the ambiguous faulting condition and then isolate the | ||||||
|  | newly-found inputs for human review. | ||||||
|  | 
 | ||||||
|  | On the subject of crashes, it is worth noting that in contrast to normal | ||||||
|  | queue entries, crashing inputs are *not* trimmed; they are kept exactly as | ||||||
|  | discovered to make it easier to compare them to the parent, non-crashing entry | ||||||
|  | in the queue. That said, afl-tmin can be used to shrink them at will. | ||||||
|  | 
 | ||||||
|  | 10) The fork server | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  | To improve performance, afl-fuzz uses a "fork server", where the fuzzed process | ||||||
|  | goes through execve(), linking, and libc initialization only once, and is then | ||||||
|  | cloned from a stopped process image by leveraging copy-on-write. The | ||||||
|  | implementation is described in more detail here: | ||||||
|  | 
 | ||||||
|  |   http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html | ||||||
|  | 
 | ||||||
|  | The fork server is an integral aspect of the injected instrumentation and | ||||||
|  | simply stops at the first instrumented function to await commands from | ||||||
|  | afl-fuzz. | ||||||
|  | 
 | ||||||
|  | With fast targets, the fork server can offer considerable performance gains, | ||||||
|  | usually between 1.5x and 2x. It is also possible to: | ||||||
|  | 
 | ||||||
|  |   - Use the fork server in manual ("deferred") mode, skipping over larger, | ||||||
|  |     user-selected chunks of initialization code. It requires very modest | ||||||
|  |     code changes to the targeted program, and With some targets, can | ||||||
|  |     produce 10x+ performance gains. | ||||||
|  | 
 | ||||||
|  |   - Enable "persistent" mode, where a single process is used to try out | ||||||
|  |     multiple inputs, greatly limiting the overhead of repetitive fork() | ||||||
|  |     calls. This generally requires some code changes to the targeted program, | ||||||
|  |     but can improve the performance of fast targets by a factor of 5 or more | ||||||
|  |     - approximating the benefits of in-process fuzzing jobs while still | ||||||
|  |     maintaining very robust isolation between the fuzzer process and the | ||||||
|  |     targeted binary. | ||||||
|  | 
 | ||||||
|  | 11) Parallelization | ||||||
|  | ------------------- | ||||||
|  | 
 | ||||||
|  | The parallelization mechanism relies on periodically examining the queues | ||||||
|  | produced by independently-running instances on other CPU cores or on remote | ||||||
|  | machines, and then selectively pulling in the test cases that, when tried | ||||||
|  | out locally, produce behaviors not yet seen by the fuzzer at hand. | ||||||
|  | 
 | ||||||
|  | This allows for extreme flexibility in fuzzer setup, including running synced | ||||||
|  | instances against different parsers of a common data format, often with | ||||||
|  | synergistic effects. | ||||||
|  | 
 | ||||||
|  | For more information about this design, see parallel_fuzzing.txt. | ||||||
|  | 
 | ||||||
|  | 12) Binary-only instrumentation | ||||||
|  | ------------------------------- | ||||||
|  | 
 | ||||||
|  | Instrumentation of black-box, binary-only targets is accomplished with the | ||||||
|  | help of a separately-built version of QEMU in "user emulation" mode. This also | ||||||
|  | allows the execution of cross-architecture code - say, ARM binaries on x86. | ||||||
|  | 
 | ||||||
|  | QEMU uses basic blocks as translation units; the instrumentation is implemented | ||||||
|  | on top of this and uses a model roughly analogous to the compile-time hooks: | ||||||
|  | 
 | ||||||
|  |   if (block_address > elf_text_start && block_address < elf_text_end) { | ||||||
|  | 
 | ||||||
|  |     cur_location = (block_address >> 4) ^ (block_address << 8); | ||||||
|  |     shared_mem[cur_location ^ prev_location]++;  | ||||||
|  |     prev_location = cur_location >> 1; | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | The shift-and-XOR-based scrambling in the second line is used to mask the | ||||||
|  | effects of instruction alignment. | ||||||
|  | 
 | ||||||
|  | The start-up of binary translators such as QEMU, DynamoRIO, and PIN is fairly | ||||||
|  | slow; to counter this, the QEMU mode leverages a fork server similar to that | ||||||
|  | used for compiler-instrumented code, effectively spawning copies of an | ||||||
|  | already-initialized process paused at _start. | ||||||
|  | 
 | ||||||
|  | First-time translation of a new basic block also incurs substantial latency. To | ||||||
|  | eliminate this problem, the AFL fork server is extended by providing a channel | ||||||
|  | between the running emulator and the parent process. The channel is used | ||||||
|  | to notify the parent about the addresses of any newly-encountered blocks and to | ||||||
|  | add them to the translation cache that will be replicated for future child | ||||||
|  | processes. | ||||||
|  | 
 | ||||||
|  | As a result of these two optimizations, the overhead of the QEMU mode is | ||||||
|  | roughly 2-5x, compared to 100x+ for PIN. | ||||||
|  | 
 | ||||||
|  | 13) The afl-analyze tool | ||||||
|  | ------------------------ | ||||||
|  | 
 | ||||||
|  | The file format analyzer is a simple extension of the minimization algorithm | ||||||
|  | discussed earlier on; instead of attempting to remove no-op blocks, the tool | ||||||
|  | performs a series of walking byte flips and then annotates runs of bytes | ||||||
|  | in the input file. | ||||||
|  | 
 | ||||||
|  | It uses the following classification scheme: | ||||||
|  | 
 | ||||||
|  |   - "No-op blocks" - segments where bit flips cause no apparent changes to | ||||||
|  |     control flow. Common examples may be comment sections, pixel data within | ||||||
|  |     a bitmap file, etc. | ||||||
|  | 
 | ||||||
|  |   - "Superficial content" - segments where some, but not all, bitflips | ||||||
|  |     produce some control flow changes. Examples may include strings in rich | ||||||
|  |     documents (e.g., XML, RTF). | ||||||
|  | 
 | ||||||
|  |   - "Critical stream" - a sequence of bytes where all bit flips alter control | ||||||
|  |     flow in different but correlated ways. This may be compressed data,  | ||||||
|  |     non-atomically compared keywords or magic values, etc. | ||||||
|  | 
 | ||||||
|  |   - "Suspected length field" - small, atomic integer that, when touched in | ||||||
|  |     any way, causes a consistent change to program control flow, suggestive | ||||||
|  |     of a failed length check. | ||||||
|  | 
 | ||||||
|  |   - "Suspected cksum or magic int" - an integer that behaves similarly to a | ||||||
|  |     length field, but has a numerical value that makes the length explanation | ||||||
|  |     unlikely. This is suggestive of a checksum or other "magic" integer. | ||||||
|  | 
 | ||||||
|  |   - "Suspected checksummed block" - a long block of data where any change  | ||||||
|  |     always triggers the same new execution path. Likely caused by failing | ||||||
|  |     a checksum or a similar integrity check before any subsequent parsing | ||||||
|  |     takes place. | ||||||
|  | 
 | ||||||
|  |   - "Magic value section" - a generic token where changes cause the type | ||||||
|  |     of binary behavior outlined earlier, but that doesn't meet any of the | ||||||
|  |     other criteria. May be an atomically compared keyword or so. | ||||||
| After Width: | Height: | Size: 581 KiB | 
| @ -0,0 +1 @@ | |||||||
|  | () { _; } >_[$($())] { id; } | ||||||
| @ -0,0 +1 @@ | |||||||
|  | () { x() { _; }; x() { _; } <<a; } | ||||||
| After Width: | Height: | Size: 892 B | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 38 B | 
| After Width: | Height: | Size: 179 B | 
| After Width: | Height: | Size: 642 B | 
| After Width: | Height: | Size: 595 B | 
| @ -0,0 +1,3 @@ | |||||||
|  | <!DOCTYPEd[<!ENTITY | ||||||
|  | S	""><!ENTITY % | ||||||
|  | N	"<!ELEMENT<![INCLUDE0"<!ENTITYL%N; | ||||||
| After Width: | Height: | Size: 876 B | 
| After Width: | Height: | Size: 293 B | 
| After Width: | Height: | Size: 434 B | 
| After Width: | Height: | Size: 996 B | 
| @ -0,0 +1,2 @@ | |||||||
|  | create table t0(o CHar(0)CHECK(0&O>O));insert into t0 | ||||||
|  | select randomblob(0)-trim(0); | ||||||
| @ -0,0 +1 @@ | |||||||
|  | SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE""""""""; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | PRAGMA foreign_keys=1;CREATE TABLE t1("""0"PRIMARY KEy REFERENCES t1 ON DELETE SET NULL);REPLACE INTO t1 SELECT(0); | ||||||
| @ -0,0 +1,2 @@ | |||||||
|  | DROP TABLE IF EXISTS t;CREATE VIRTUAL TABLE t0 USING fts4();insert into t0 select zeroblob(0);SAVEPOINT O;insert into t0 | ||||||
|  | select(0);SAVEPOINT E;insert into t0 SELECT 0 UNION SELECT 0'x'ORDER BY x; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | SELECT*from(select"",zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(150000000),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)),(select"",zeroblob(1E9),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(1E9),(0),zeroblob(150000000),(0),zeroblob(0),(0)EXCEPT select zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0),zeroblob(0)); | ||||||
| @ -0,0 +1,2 @@ | |||||||
|  | create table t0(t);insert into t0 | ||||||
|  | select strftime(); | ||||||
| @ -0,0 +1 @@ | |||||||
|  | SELECT fts3_tokenizer(@0()); | ||||||
| @ -0,0 +1 @@ | |||||||
|  | select''like''like''like#0; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | PRAGMA e;select lower(0);select lower(0)"a",""GROUP BY a ORDER BY a; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | WITH x AS(SELECT*FROM t)SELECT""EXCEPT SELECT 0 ORDER BY 0 COLLATE""; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | CREATE VIRTUAL TABLE x USING fts4();VALUES(0,0),(0,0),(0,0),(0,0);PRAGMA writable_schema=ON;UPDATE sqlite_master SET sql=''WHERE name='';UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';SAVEPOINT K;SAVEPOINT T;SAVEPOINT T;ANALYZE;ROLLBACK;SAVEPOINT E;DROP TABLE IF EXISTS t; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | CREATE VIRTUAL TABLE t4 USING fts4(0,b,c,notindexed=0);INSERT INTO t4 VALUES('','','0');BEGIN;INSERT INTO t4 VALUES('','','0');INSERT INTO t4(t4)VALUES('integrity-check'); | ||||||
| @ -0,0 +1 @@ | |||||||
|  | DETACH(select group_concat(q)); | ||||||
| @ -0,0 +1 @@ | |||||||
|  | select(select strftime()); | ||||||