pax_global_header00006660000000000000000000000064136026331520014513gustar00rootroot0000000000000052 comment=842cd9dec3c4c83d660d96dcdb3f5cf0c6e6f4fb AFLplusplus-2.60c/000077500000000000000000000000001360263315200140175ustar00rootroot00000000000000AFLplusplus-2.60c/.clang-format000066400000000000000000000076421360263315200164030ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: Google AccessModifierOffset: -1 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: true AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: false AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: Yes BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeInheritanceComma: false BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: true DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeBlocks: Preserve IncludeCategories: - Regex: '^' Priority: 2 - Regex: '^<.*\.h>' Priority: 1 - Regex: '^<.*' Priority: 2 - Regex: '.*' Priority: 3 IncludeIsMainRegex: '([-_](test|unittest))?$' IndentCaseLabels: true IndentPPDirectives: None IndentWidth: 2 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBinPackProtocolList: Never ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Right RawStringFormats: - Language: Cpp Delimiters: - cc - CC - cpp - Cpp - CPP - 'c++' - 'C++' CanonicalDelimiter: '' BasedOnStyle: google - Language: TextProto Delimiters: - pb - PB - proto - PROTO EnclosingFunctions: - EqualsProto - EquivToProto - PARSE_PARTIAL_TEXT_PROTO - PARSE_TEST_PROTO - PARSE_TEXT_PROTO - ParseTextOrDie - ParseTextProtoOrDie CanonicalDelimiter: '' BasedOnStyle: google ReflowComments: true SortIncludes: false SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto TabWidth: 8 UseTab: Never ... AFLplusplus-2.60c/.custom-format.py000077500000000000000000000076631360263315200172660ustar00rootroot00000000000000#!/usr/bin/env python3 # # american fuzzy lop++ - custom code formatter # -------------------------------------------- # # Written and maintaned by Andrea Fioraldi # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. # Copyright 2019 AFLplusplus Project. 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 # import subprocess import sys import os import re # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use with open(".clang-format") as f: fmt = f.read() CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN") if CLANG_FORMAT_BIN is None: o = 0 try: p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE) o, _ = p.communicate() o = str(o, "utf-8") o = o[len("clang-format version "):].strip() o = o[:o.find(".")] o = int(o) except: pass if o < 7: if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0: CLANG_FORMAT_BIN = 'clang-format-7' elif subprocess.call(['which', 'clang-format-8'], stdout=subprocess.PIPE) == 0: CLANG_FORMAT_BIN = 'clang-format-8' elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0: CLANG_FORMAT_BIN = 'clang-format-9' elif subprocess.call(['which', 'clang-format-10'], stdout=subprocess.PIPE) == 0: CLANG_FORMAT_BIN = 'clang-format-10' else: print ("clang-format 7 or above is needed. Aborted.") exit(1) else: CLANG_FORMAT_BIN = 'clang-format' COLUMN_LIMIT = 80 for line in fmt.split("\n"): line = line.split(":") if line[0].strip() == "ColumnLimit": COLUMN_LIMIT = int(line[1].strip()) def custom_format(filename): p = subprocess.Popen([CLANG_FORMAT_BIN, filename], stdout=subprocess.PIPE) src, _ = p.communicate() src = str(src, "utf-8") in_define = False last_line = None out = "" for line in src.split("\n"): if line.startswith("#"): if line.startswith("#define"): in_define = True if "/*" in line and not line.strip().startswith("/*") and line.endswith("*/") and len(line) < (COLUMN_LIMIT-2): cmt_start = line.rfind("/*") line = line[:cmt_start] + " " * (COLUMN_LIMIT-2 - len(line)) + line[cmt_start:] define_padding = 0 if last_line is not None and in_define and last_line.endswith("\\"): last_line = last_line[:-1] define_padding = max(0, len(last_line[last_line.rfind("\n")+1:])) if last_line is not None and last_line.strip().endswith("{") and line.strip() != "": line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif last_line is not None and last_line.strip().startswith("}") and line.strip() != "": line = (" " * define_padding + "\\" if in_define else "") + "\n" + line elif line.strip().startswith("}") and last_line is not None and last_line.strip() != "": line = (" " * define_padding + "\\" if in_define else "") + "\n" + line if not line.endswith("\\"): in_define = False out += line + "\n" last_line = line return (out) args = sys.argv[1:] if len(args) == 0: print ("Usage: ./format.py [-i] ") print () print (" The -i option, if specified, let the script to modify in-place") print (" the source files. By default the results are written to stdout.") print() exit(1) in_place = False if args[0] == "-i": in_place = True args = args[1:] for filename in args: code = custom_format(filename) if in_place: with open(filename, "w") as f: f.write(code) else: print(code) AFLplusplus-2.60c/.gitignore000066400000000000000000000007011360263315200160050ustar00rootroot00000000000000.test .test2 *.o *.so afl-analyze afl-as afl-clang afl-clang++ afl-clang-fast afl-clang-fast++ afl-fuzz afl-g++ afl-gcc afl-gcc-fast afl-g++-fast afl-gotcpu afl-qemu-trace afl-showmap afl-tmin afl-analyze.8 afl-clang-fast++.8 afl-clang-fast.8 afl-cmin.8 afl-fuzz.8 afl-gcc.8 afl-gcc-fast.8 afl-g++-fast.8 afl-gotcpu.8 afl-plot.8 afl-showmap.8 afl-system-config.8 afl-tmin.8 afl-whatsup.8 qemu_mode/libcompcov/compcovtest as qemu_mode/qemu-* core\.* AFLplusplus-2.60c/.travis.yml000066400000000000000000000037351360263315200161400ustar00rootroot00000000000000language: c branches: only: - master matrix: include: - os: linux dist: bionic env: NAME="bionic-amd64" MODERN="yes" GCC="7" - os: linux dist: xenial env: NAME="xenial-amd64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" - os: linux dist: trusty env: NAME="trusty-amd64" MODERN="no" GCC="4.8" - os: linux dist: xenial arch: arm64 env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64" # - os: osx # osx_image: xcode11.2 # env: NAME="osx" HOMEBREW_NO_ANALYTICS="1" LINK="http://releases.llvm.org/9.0.0/" NAME="clang+llvm-9.0.0-x86_64-darwin-apple" jobs: allow_failures: - os: osx 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: # export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE} - echo Testing on $NAME - if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev ; fi - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev ; fi script: - gcc -v - clang -v - if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ; fi - if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ; fi - if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then make ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi - make tests AFLplusplus-2.60c/Android.bp000066400000000000000000000036571360263315200157350ustar00rootroot00000000000000cc_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", ], } AFLplusplus-2.60c/Android.mk000077700000000000000000000000001360263315200173632Makefileustar00rootroot00000000000000AFLplusplus-2.60c/CONTRIBUTING.md000066400000000000000000000011571360263315200162540ustar00rootroot00000000000000# How to submit a Pull Request to AFLplusplus Each modified source file, before merging, must be formatted. ``` make code-formatter ``` This should be fine if you modified one of the files already present in the project, otherwise run: ``` ./.custom-format.py -i file-that-you-have-created.c ``` Regarding the coding style, please follow the AFL style. No camel case at all and use the AFL's macros when possible (e.g. WARNF, FATAL, ...). Remember that AFLplusplus has to build and run on many platforms, so generalize your Makefiles (or your patches to our pre-existing Makefiles) to be as much general as possible. AFLplusplus-2.60c/Changelog000077700000000000000000000000001360263315200203262docs/ChangeLogustar00rootroot00000000000000AFLplusplus-2.60c/Dockerfile000066400000000000000000000013371360263315200160150ustar00rootroot00000000000000FROM ubuntu:eoan MAINTAINER David Carlier LABEL "about"="AFLplusplus docker image" RUN apt-get update && apt-get install -y \ --no-install-suggests --no-install-recommends \ automake \ bison \ build-essential \ clang \ clang-9 \ flex \ gcc-9 \ gcc-9-plugin-dev \ gcc-9-multilib \ libc++-9-dev \ libtool \ libtool-bin \ libglib2.0-dev \ llvm-9-dev \ python-setuptools \ python2.7-dev \ wget \ ca-certificates \ libpixman-1-dev \ && rm -rf /var/lib/apt/lists/* ARG CC=gcc-9 ARG CXX=g++-9 ARG LLVM_CONFIG=llvm-config-9 COPY . /app RUN cd /app && make clean && make distrib && \ make install && cd .. && rm -rf /app WORKDIR /work AFLplusplus-2.60c/LICENSE000066400000000000000000000261351360263315200150330ustar00rootroot00000000000000 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. AFLplusplus-2.60c/Makefile000066400000000000000000000433061360263315200154650ustar00rootroot00000000000000# # american fuzzy lop - makefile # ----------------------------- # # Written by Michal Zalewski # # Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. 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 # # For Heiko: #TEST_MMAP=1 PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH = $(PREFIX)/share/doc/afl MISC_PATH = $(PREFIX)/share/afl MAN_PATH = $(PREFIX)/man/man8 PROGNAME = afl VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) # 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 afl-system-config MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) CFLAGS ?= -O3 -funroll-loops CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) ifneq "($filter %3.7m, $(shell python3.7m-config --includes 2>/dev/null)" "" PYTHON_INCLUDE ?= $(shell python3.7m-config --includes) PYTHON_LIB ?= $(shell python3.7m-config --ldflags) PYTHON_VERSION = 3.7m else ifneq "($filter %3.7, $(shell python3.7-config --includes) 2> /dev/null" "" PYTHON_INCLUDE ?= $(shell python3.7-config --includes) PYTHON_LIB ?= $(shell python3.7-config --ldflags) PYTHON_VERSION = 3.7 else ifneq "($filter %2.7, $(shell python2.7-config --includes) 2> /dev/null" "" PYTHON_INCLUDE ?= $(shell python2.7-config --includes) PYTHON_LIB ?= $(shell python2.7-config --ldflags) PYTHON_VERSION = 2.7 endif endif endif PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7m && echo /usr/include/python3.7m) PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7 && echo /usr/include/python3.7) PYTHON_INCLUDE ?= $(shell test -e /usr/include/python2.7 && echo /usr/include/python2.7) ifneq "($filter %3.7m, $(PYTHON_INCLUDE))" "" PYTHON_VERSION ?= 3.7m PYTHON_LIB ?= -lpython3.7m else ifneq "($filter %3.7, $(PYTHON_INCLUDE))" "" PYTHON_VERSION ?= 3.7 else ifneq "($filter %2.7, $(PYTHON_INCLUDE))" "" PYTHON_VERSION ?= 2.7 PYTHON_LIB ?= -lpython2.7 else PYTHON_VERSION ?= none endif endif endif ifdef SOURCE_DATE_EPOCH BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -I) else BUILD_DATE ?= $(shell date -I) endif ifneq "$(filter Linux GNU%,$(shell uname))" "" LDFLAGS += -ldl endif ifneq "$(findstring FreeBSD, $(shell uname))" "" CFLAGS += -pthread endif ifneq "$(findstring NetBSD, $(shell uname))" "" CFLAGS += -pthread endif ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" TEST_CC = afl-gcc else TEST_CC = afl-clang endif COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h ifeq "$(shell echo '\#include @int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" PYTHON_OK=1 PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) else PYTHON_OK=0 PYFLAGS= endif ifdef STATIC $(info Compiling static version of binaries) # Disable python for static compilation to simplify things PYTHON_OK=0 PYFLAGS= CFLAGS += -static LDFLAGS += -lm -lrt -lpthread -lz -lutil endif ifeq "$(shell echo '\#include @\#include @int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1" SHMAT_OK=1 else SHMAT_OK=0 CFLAGS+=-DUSEMMAP=1 LDFLAGS+=-Wno-deprecated-declarations -lrt endif ifeq "$(TEST_MMAP)" "1" SHMAT_OK=0 CFLAGS+=-DUSEMMAP=1 LDFLAGS+=-Wno-deprecated-declarations -lrt endif all: test_x86 test_shm test_python27 ready $(PROGS) afl-as test_build all_done man: $(MANPAGES) -$(MAKE) -C llvm_mode -$(MAKE) -C gcc_plugin tests: source-only @cd test ; ./test.sh @rm -f test/errors performance-tests: performance-test test-performance: performance-test performance-test: source-only @cd test ; ./test-performance.sh help: @echo "HELP --- the following make targets exist:" @echo "==========================================" @echo "all: just the main afl++ binaries" @echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa" @echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa" @echo "distrib: everything (for both binary-only and source code fuzzing)" @echo "man: creates simple man pages from the help option of the programs" @echo "install: installs everything you have compiled with the build option above" @echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well" @echo "code-format: format the code, do this before you commit and send a PR please!" @echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem" @echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations" @echo "help: shows these build options :-)" @echo "==========================================" @echo "Recommended: \"distrib\" or \"source-only\", then \"install\"" ifndef AFL_NO_X86 test_x86: @echo "[*] Checking for the default compiler cc..." @which $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC='."; echo; exit 1 ) @echo "[*] Checking for the ability to compile x86 code..." @echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test1 || ( 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 .test1 else test_x86: @echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)." endif ifeq "$(SHMAT_OK)" "1" test_shm: @echo "[+] shmat seems to be working." @rm -f .test2 else test_shm: @echo "[-] shmat seems not to be working, switching to mmap implementation" endif ifeq "$(PYTHON_OK)" "1" test_python27: @rm -f .test 2> /dev/null @echo "[+] Python $(PYTHON_VERSION) support seems to be working." else test_python27: @echo "[-] You seem to need to install the package python3.7-dev or python2.7-dev (and perhaps python[23]-apt), but it is optional so we continue" endif ready: @echo "[+] Everything seems to be working, ready to compile." afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS) set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS) ln -sf afl-as as src/afl-common.o : src/afl-common.c include/common.h $(CC) $(CFLAGS) -c src/afl-common.c -o src/afl-common.o src/afl-forkserver.o : src/afl-forkserver.c include/forkserver.h $(CC) $(CFLAGS) -c src/afl-forkserver.c -o src/afl-forkserver.o src/afl-sharedmem.o : src/afl-sharedmem.c include/sharedmem.h $(CC) $(CFLAGS) -c src/afl-sharedmem.c -o src/afl-sharedmem.o radamsa: src/third_party/libradamsa/libradamsa.so cp src/third_party/libradamsa/libradamsa.so . src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h $(MAKE) -C src/third_party/libradamsa/ afl-fuzz: include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS) afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS) afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS) afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS) afl-gotcpu: src/afl-gotcpu.c $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS) # document all mutations and only do one run (use with only one input file!) document: include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(AFL_FUZZ_FILES) -D_AFL_DOCUMENT_MUTATIONS src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(LDFLAGS) $(PYFLAGS) code-format: ./.custom-format.py -i src/*.c ./.custom-format.py -i include/*.h ./.custom-format.py -i libdislocator/*.c ./.custom-format.py -i libtokencap/*.c ./.custom-format.py -i llvm_mode/*.c ./.custom-format.py -i llvm_mode/*.h ./.custom-format.py -i llvm_mode/*.cc ./.custom-format.py -i gcc_plugin/*.c #./.custom-format.py -i gcc_plugin/*.h ./.custom-format.py -i gcc_plugin/*.cc ./.custom-format.py -i experimental/*/*.c ./.custom-format.py -i experimental/*/*.h ./.custom-format.py -i qemu_mode/patches/*.h ./.custom-format.py -i qemu_mode/libcompcov/*.c ./.custom-format.py -i qemu_mode/libcompcov/*.cc ./.custom-format.py -i qemu_mode/libcompcov/*.h ./.custom-format.py -i qbdi_mode/*.c ./.custom-format.py -i qbdi_mode/*.cpp ./.custom-format.py -i *.h ./.custom-format.py -i *.c 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_CC; AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 ) ./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 post to https://github.com/vanhauser-thc/AFLplusplus/issues 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 the README.md - 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) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast *.so *.8 rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM -$(MAKE) -C llvm_mode clean -$(MAKE) -C gcc_plugin clean $(MAKE) -C libdislocator clean $(MAKE) -C libtokencap clean $(MAKE) -C experimental/socket_fuzzing clean $(MAKE) -C experimental/argv_fuzzing clean $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C src/third_party/libradamsa/ clean -rm -rf unicorn_mode/unicorn distrib: all radamsa -$(MAKE) -C llvm_mode -$(MAKE) -C gcc_plugin $(MAKE) -C libdislocator $(MAKE) -C libtokencap $(MAKE) -C experimental/socket_fuzzing $(MAKE) -C experimental/argv_fuzzing cd qemu_mode && sh ./build_qemu_support.sh cd unicorn_mode && sh ./build_unicorn_support.sh binary-only: all radamsa $(MAKE) -C libdislocator $(MAKE) -C libtokencap $(MAKE) -C experimental/socket_fuzzing $(MAKE) -C experimental/argv_fuzzing cd qemu_mode && sh ./build_qemu_support.sh cd unicorn_mode && sh ./build_unicorn_support.sh source-only: all radamsa -$(MAKE) -C llvm_mode -$(MAKE) -C gcc_plugin $(MAKE) -C libdislocator $(MAKE) -C libtokencap %.8: % @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@ @echo .SH NAME >> $@ @echo .B $* >> $@ @echo >> $@ @echo .SH SYNOPSIS >> $@ @./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@ @echo >> $@ @echo .SH OPTIONS >> $@ @echo .nf >> $@ @./$* -h 2>&1 | tail -n +4 >> $@ @echo >> $@ @echo .SH AUTHOR >> $@ @echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse , Heiko \"hexcoder-\" Eissfeldt and Andrea Fioraldi " >> $@ @echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> $@ @echo >> $@ @echo .SH LICENSE >> $@ @echo Apache License Version 2.0, January 2004 >> $@ install: all $(MANPAGES) install -d -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 if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi ifndef AFL_TRACE_PC if [ -f afl-clang-fast -a -f libLLVMInsTrim.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 libLLVMInsTrim.so 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 if [ -f compare-transform-pass.so ]; then set -e; install -m 755 compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi if [ -f split-compares-pass.so ]; then set -e; install -m 755 split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi if [ -f split-switches-pass.so ]; then set -e; install -m 755 split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi $(MAKE) -C experimental/socket_fuzzing install $(MAKE) -C experimental/argv_fuzzing install set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++ set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH) install -m0644 -D *.8 ${DESTDIR}$(MAN_PATH) install -m 755 afl-as $${DESTDIR}$(HELPER_PATH) ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as install -m 644 docs/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.md >~/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 AFLplusplus-2.60c/PATCHES000077700000000000000000000000001360263315200167662docs/PATCHESustar00rootroot00000000000000AFLplusplus-2.60c/QuickStartGuide.txt000077700000000000000000000000001360263315200243642docs/QuickStartGuide.txtustar00rootroot00000000000000AFLplusplus-2.60c/README.md000066400000000000000000000732311360263315200153040ustar00rootroot00000000000000# american fuzzy lop plus plus (afl++) ![Travis State](https://api.travis-ci.com/vanhauser-thc/AFLplusplus.svg?branch=master) Release Version: 2.59c Github Version: 2.59d includes all necessary/interesting changes from Google's afl 2.56b Originally developed by Michal "lcamtuf" Zalewski. Repository: [https://github.com/vanhauser-thc/AFLplusplus](https://github.com/vanhauser-thc/AFLplusplus) afl++ is maintained by Marc "van Hauser" Heuse , Heiko "hexcoder-" Eißfeldt and Andrea Fioraldi . Note that although afl now has a Google afl repository [https://github.com/Google/afl](https://github.com/Google/afl), it is unlikely to receive any noteable enhancements: [https://twitter.com/Dor3s/status/1154737061787660288](https://twitter.com/Dor3s/status/1154737061787660288) ## The enhancements compared to the original stock afl Many improvements were made over the official afl release - which did not get any feature improvements since November 2017. Among other changes afl++ has a more performant llvm_mode, supports llvm up to version 10, QEMU 3.1, more speed and crashfixes for QEMU, better *BSD and Android support and much, much more. Additionally the following features and patches have been integrated: * AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast) * The new excellent MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL) * InsTrim, a very effective CFG llvm_mode instrumentation implementation for large targets: [https://github.com/csienslab/instrim](https://github.com/csienslab/instrim) * C. Holler's afl-fuzz Python mutator module and llvm_mode whitelist support: [https://github.com/choller/afl](https://github.com/choller/afl) * Custom mutator by a library (instead of Python) by kyakdan * unicorn_mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk) * laf-intel or CompCov support for llvm_mode, qemu_mode and unicorn_mode * NeverZero patch for afl-gcc, llvm_mode, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage * Persistent mode and deferred forkserver for qemu_mode * Win32 PE binary-only fuzzing with QEMU and Wine * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly). * qbdi_mode: fuzz android native libraries via QBDI framework A more thorough list is available in the PATCHES file. | Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode | | ----------------------- |:-------:|:---------:|:----------:|:---------:|:------------:| | laf-intel / CompCov | | x | | x86/arm | x86/arm | | NeverZero | x | x(1) | (2) | x | x | | Persistent mode | | x | x | x86 | x | | Whitelist | | x | x | | | | InsTrim | | x | | | | neverZero: (1) only in LLVM >= 9.0 due to a bug in llvm in previous versions (2) gcc create non-performant code, hence it is disabled in gcc_plugin So all in all this is the best-of AFL that is currently out there :-) For new versions and additional information, check out: [https://github.com/vanhauser-thc/AFLplusplus](https://github.com/vanhauser-thc/AFLplusplus) To compare notes with other users or get notified about major new features, send a mail to . See [docs/QuickStartGuide.txt](docs/QuickStartGuide.txt) if you don't have time to read this file. ## 0) Building and installing afl++ afl++ has many build options. The easiest is to build and install everything: ```shell $ make distrib $ sudo make install ``` Note that "make distrib" also builds llvm_mode, qemu_mode, unicorn_mode and more. If you just want plain afl then do "make all", however compiling and using at least llvm_mode is highly recommended for much better results - hence in this case ```shell $ make source-only ``` is what you should choose. These build options exist: * all: just the main afl++ binaries * binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa * source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap, radamsa * distrib: everything (for both binary-only and source code fuzzing) * install: installs everything you have compiled with the build options above * clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well * code-format: format the code, do this before you commit and send a PR please! * tests: runs test cases to ensure that all features are still working as they should * help: shows these build options [Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the afl++ binaries by passing the STATIC=1 argument to make: ```shell $ make all STATIC=1 ``` Note that afl++ is faster and better the newer the compilers used are. Hence gcc-9 and especially llvm-9 should be the compilers of choice. If your distribution does not have them, you can use the Dockerfile: ```shell $ docker build -t aflplusplus ``` ## 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 PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++ instead of afl-gcc/afl-g++ is much faster and has a few cool features. See llvm_mode/ - however few code does not compile with llvm. We support llvm versions 3.8.0 to 10. 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.md](llvm_mode/README.md). Clang/LLVM has a much better performance and works with LLVM version 3.8.0 to 10. Using the LAF Intel performance enhancements are also recommended, see [llvm_mode/README.laf-intel.md](llvm_mode/README.laf-intel.md) Using partial instrumentation is also recommended, see [llvm_mode/README.whitelist.md](llvm_mode/README.whitelist.md) 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.md](libdislocator/README.md)) can help uncover heap corruption issues, too. PS. ASAN users are advised to review [docs/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.md](qemu_mode/README.md). The mode is approximately 2-5x slower than compile-time instrumentation, is less conductive to parallelization, and may have some other quirks. If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your binary, then you can use afl-fuzz normally and it will have twice the speed compared to qemu_mode. A more comprehensive description of these and other options can be found in [docs/binaryonly_fuzzing.txt](docs/binaryonly_fuzzing.txt) ## 5) Power schedules The power schedules were copied from Marcel Böhme's excellent AFLfast implementation and expand on the ability to discover new paths and therefore may increase the code coverage. The available schedules are: - explore (default) - fast - coe - quad - lin - exploit In parallel mode (-M/-S, several instances with shared queue), we suggest to run the master using the exploit schedule (-p exploit) and the slaves with a combination of cut-off-exponential (-p coe), exponential (-p fast; default), and explore (-p explore) schedules. In single mode, using -p fast is usually more beneficial than the default explore mode. (We don't want to change the default behaviour of afl, so "fast" has not been made the default mode). More details can be found in the paper published at the 23rd ACM Conference on Computer and Communications Security [CCS'16](https://www.sigsac.org/ccs/CCS2016/accepted-papers/) ## 6) 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. ## 7) 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. ## 8) Interpreting output See the [docs/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/). ## 9) 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 [docs/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 [docs/parallel_fuzzing.txt](docs/parallel_fuzzing.txt) for tips. ## 10) 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.md](dictionaries/README.md); 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.md](libtokencap/README.tokencap.md). ## 11) 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 [docs/technical_details.txt](docs/technical_details.txt). ## 12) 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). ## 13) 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...] ``` ## 14) 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/ (with AFL_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 [docs/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](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](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](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/](http://lcamtuf.coredump.cx/prep/). Beyond this, see INSTALL for platform-specific tips. ## 15) Special thanks Many of the improvements to the original afl and afl++ 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 Neuschaefer 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 Boehme Van-Thuan Pham Abhik Roychoudhury Joshua J. Drake Toby Hutton Rene Freingruber Sergey Davidoff Sami Liedes Craig Young Andrzej Jackowski Daniel Hodson Nathan Voss Dominik Maier Andrea Biondo Vincent Le Garrec Khaled Yakdan Kuang-che Wu ``` Thank you! ## 16) Contact Questions? Concerns? Bug reports? The contributors can be reached via [https://github.com/vanhauser-thc/AFLplusplus](https://github.com/vanhauser-thc/AFLplusplus) There is also a mailing list for the afl project; to join, send a mail to . Or, if you prefer to browse archives first, try: [https://groups.google.com/group/afl-users](https://groups.google.com/group/afl-users) AFLplusplus-2.60c/TODO000066400000000000000000000036611360263315200145150ustar00rootroot00000000000000 Roadmap 2.60: ============= afl-fuzz: - radamsa mutator (via dlopen()) gcc_plugin: - laf-intel libdislocator: - add a wrapper for posix_memalign qemu_mode: - update to 4.x (probably this will be skipped :( ) - instrim for QEMU mode via static analysis (with r2pipe? or angr?) Idea: The static analyzer outputs a map in which each edge that must be skipped is marked with 1. QEMU loads it at startup in the parent process. custom_mutators: - rip what Superion is doing into custom mutators for js, php, etc. enhance test/test.sh script for checking if compcov features are working correctly (especially float splitting) The far away future: ==================== Problem: Average targets (tiff, jpeg, unrar) go through 1500 edges. At afl's default map that means ~16 collisions and ~3 wrappings. Solution #1: increase map size. every +1 decreases fuzzing speed by ~10% and halfs the collisions birthday paradox predicts collisions at this # of edges: mapsize => collisions 2^16 = 302 2^17 = 427 2^18 = 603 2^19 = 853 2^20 = 1207 2^21 = 1706 2^22 = 2412 2^23 = 3411 2^24 = 4823 Increasing the map is an easy solution but also not a good one. Solution #2: use dynamic map size and collision free basic block IDs This only works in llvm_mode and llvm >= 9 though A potential good future solution. Heiko/hexcoder follows this up Solution #3: write instruction pointers to a big shared map 512kb/1MB shared map and the instrumented code writes the instruction pointer into the map. Map must be big enough but could be command line controlled. Good: complete coverage information, nothing is lost. choice of analysis impacts speed, but this can be decided by user options Neutral: a little bit slower but no loss of coverage Bad: completely changes how afl uses the map and the scheduling. Overall another very good solution, Marc Heuse/vanHauser follows this up AFLplusplus-2.60c/afl-cmin000077500000000000000000000265431360263315200154450ustar00rootroot00000000000000#!/usr/bin/env bash # # american fuzzy lop - corpus minimization tool # --------------------------------------------- # # Written by Michal Zalewski # # Copyright 2014, 2015 Google Inc. 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 Michal Zalewski" 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 UNICORN_MODE while getopts "+i:o:f:m:t:eQUCh" opt; do case "$opt" in "h") ;; "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 ;; "U") EXTRA_PAR="$EXTRA_PAR -U" test "$MEM_LIMIT_GIVEN" = "" && MEM_LIMIT=250 UNICORN_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) -U - use unicorn-based instrumentation (Unicorn 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" = "" -a "$UNICORN_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" -- "$@" &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" -- "$@" "$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 AFLplusplus-2.60c/afl-plot000077500000000000000000000114101360263315200154600ustar00rootroot00000000000000#!/bin/sh # # american fuzzy lop - Advanced Persistent Graphing # ------------------------------------------------- # # Written by Michal Zalewski # Based on a design & prototype by Michael Rash. # # Copyright 2014, 2015 Google Inc. 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 Michal Zalewski" echo if [ ! "$#" = "2" ]; then cat 1>&2 <<_EOF_ $0 afl_state_dir graph_output_dir This program generates gnuplot images from afl-fuzz output data. Usage: 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_
Banner:$BANNER
Directory:$1
Generated on:`date`

_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 AFLplusplus-2.60c/afl-system-config000077500000000000000000000057211360263315200173010ustar00rootroot00000000000000#!/bin/sh test "$1" = "-h" && { echo afl-system-config by Marc Heuse echo echo $0 echo echo afl-system-config has no command line options echo echo afl-system reconfigures the system to a high performance fuzzing state echo WARNING: this reduces the security of the system echo exit 1 } PLATFORM=`uname -s` echo This reconfigures the system to have a better fuzzing performance if [ '!' "$EUID" = 0 ] && [ '!' `id -u` = 0 ] ; then echo Error you need to be root to run this exit 1 fi if [ "$PLATFORM" = "Linux" ] ; then sysctl -w kernel.core_pattern=core sysctl -w kernel.randomize_va_space=0 sysctl -w kernel.sched_child_runs_first=1 sysctl -w kernel.sched_autogroup_enabled=1 sysctl -w kernel.sched_migration_cost_ns=50000000 sysctl -w kernel.sched_latency_ns=250000000 echo never > /sys/kernel/mm/transparent_hugepage/enabled test -e /sys/devices/system/cpu/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/scaling_governor test -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor test -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor test -e /sys/devices/system/cpu/intel_pstate/no_turbo && echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo test -e /sys/devices/system/cpu/cpufreq/boost && echo 1 > /sys/devices/system/cpu/cpufreq/boost echo echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this: echo '/etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"' fi if [ "$PLATFORM" = "FreeBSD" ] ; then sysctl kern.elf32.aslr.enable=0 sysctl kern.elf64.aslr.enable=0 echo echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this: echo 'sysctl hw.ibrs_disable=1' echo echo 'Setting kern.pmap.pg_ps_enabled=0 into /boot/loader.conf might be helpful too.' fi if [ "$PLATFORM" = "OpenBSD" ] ; then echo echo 'System security features cannot be disabled on OpenBSD.' fi if [ "$PLATFORM" = "NetBSD" ] ; then echo echo It is recommended to enable unprivileged users to set cpu affinity echo to be able to use afl-gotcpu meaningfully. /sbin/sysctl -w security.models.extensions.user_set_cpu_affinity=1 fi if [ "$PLATFORM" = "Darwin" ] ; then if [ $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ] ; then echo We unload the default crash reporter here SL=/System/Library; PL=com.apple.ReportCrash launchctl unload -w ${SL}/LaunchAgents/${PL}.plist sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist fi fi echo echo Also use AFL_TMPDIR to use a tmpfs for the input file AFLplusplus-2.60c/afl-whatsup000077500000000000000000000073701360263315200162070ustar00rootroot00000000000000#!/bin/sh # # american fuzzy lop - status check tool # -------------------------------------- # # Written by Michal Zalewski # # Copyright 2015 Google Inc. 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 Michal Zalewski" echo test "$1" = "-h" && { echo $0 echo echo afl-whatsup has no command line options echo exit 1 } 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` || 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 AFLplusplus-2.60c/afl-wine-trace000077500000000000000000000060001360263315200165370ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys import pefile import shutil import subprocess if len(sys.argv) < 2: print("[afl-wine-trace] usage: ./afl-wine-trace binary [args...]\n") exit(1) if os.getenv("AFL_PATH"): my_dir = os.getenv("AFL_PATH") else: my_dir = os.path.dirname(os.path.abspath(__file__)) os.environ["WINELOADERNOEXEC"] = "1" pe = pefile.PE(sys.argv[1]) if "AFL_ENTRYPOINT" not in os.environ: os.environ["AFL_ENTRYPOINT"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.AddressOfEntryPoint) if not os.getenv("AFL_INST_LIBS"): if "AFL_CODE_START" not in os.environ: os.environ["AFL_CODE_START"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode) if "AFL_CODE_END" not in os.environ: os.environ["AFL_CODE_END"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode + pe.OPTIONAL_HEADER.SizeOfCode) if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]: os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so") else: os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so") if os.getenv("WINECOV_QEMU_PATH"): qemu_path = os.getenv("WINECOV_QEMU_PATH") elif os.path.exists(os.path.join(my_dir, "afl-qemu-trace")): qemu_path = os.path.join(my_dir, "afl-qemu-trace") else: qemu_path = "qemu-" if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]: qemu_path += "x86_64" elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]: qemu_path += "i386" else: print ("[afl-wine-trace] unsuppoted architecture\n") exit(1) qemu_path = shutil.which(qemu_path) wine_path = None if os.getenv("AFL_WINE_PATH"): wine_path = os.getenv("AFL_WINE_PATH") else: if not wine_path and shutil.which("wine"): wine_path = shutil.which("wine") if not wine_path and os.path.exists("/usr/bin/wine"): wine_path = "/usr/bin/wine" if not wine_path and os.path.exists("/usr/lib/wine/wine"): wine_path = "/usr/lib/wine/wine" if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]: wine_path += "64" elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]: pass else: print ("[afl-wine-trace] unsopported architecture\n") exit(1) argv = sys.argv[1:] for i in range(len(argv)): if ".cur_input" in argv[i]: argv[i] = subprocess.run([os.path.join(os.path.dirname(wine_path), "winepath"), "--windows", argv[i]], universal_newlines=True, stdout=subprocess.PIPE).stdout break print("[afl-wine-trace] exec:", " ".join([qemu_path, wine_path] + argv)) os.execve(qemu_path, [qemu_path, wine_path] + argv, os.environ) AFLplusplus-2.60c/config.h000077700000000000000000000000001360263315200204712include/config.hustar00rootroot00000000000000AFLplusplus-2.60c/custom_mutators/000077500000000000000000000000001360263315200172675ustar00rootroot00000000000000AFLplusplus-2.60c/custom_mutators/README000066400000000000000000000001661360263315200201520ustar00rootroot00000000000000This is a simple example for the AFL_CUSTOM_MUTATOR_LIBRARY feature. For more information see docs/custom_mutator.txt AFLplusplus-2.60c/custom_mutators/simple_mutator.c000066400000000000000000000021641360263315200225020ustar00rootroot00000000000000/* Simple Custom Mutator for AFL Written by Khaled Yakdan This a simple mutator that assumes that the generates messages starting with one of the three strings GET, PUT, or DEL followed by a payload. The mutator randomly selects a commend and mutates the payload of the seed provided as input. */ #include #include #include static const char *commands[] = { "GET", "PUT", "DEL", }; static size_t data_size = 100; size_t afl_custom_mutator(uint8_t *data, size_t size, uint8_t *mutated_out, size_t max_size, unsigned int seed) { // Seed the PRNG srand(seed); // Make sure that the packet size does not exceed the maximum size expected by // the fuzzer size_t mutated_size = data_size <= max_size ? data_size : max_size; // Randomly select a command string to add as a header to the packet memcpy(mutated_out, commands[rand() % 3], 3); // Mutate the payload of the packet for (int i = 3; i < mutated_size; i++) { mutated_out[i] = (data[i] + rand() % 10) & 0xff; } return mutated_size; } AFLplusplus-2.60c/dictionaries/000077500000000000000000000000001360263315200164745ustar00rootroot00000000000000AFLplusplus-2.60c/dictionaries/README.md000066400000000000000000000035011360263315200177520ustar00rootroot00000000000000# AFL dictionaries (See [../docs/README.md](../docs/README.md) 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 10 of the "main" README.md 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 @, 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 @ 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. AFLplusplus-2.60c/dictionaries/gif.dict000066400000000000000000000004251360263315200201070ustar00rootroot00000000000000# # AFL dictionary for GIF images # ----------------------------- # # Created by Michal Zalewski # 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" AFLplusplus-2.60c/dictionaries/html_tags.dict000066400000000000000000000061231360263315200213250ustar00rootroot00000000000000# # 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 # tag_a="" tag_abbr="" tag_acronym="" tag_address="

" tag_annotation_xml="" tag_applet="" tag_area="" tag_article="
" tag_aside="