From c96238d85f4a784402db6cbf16630b977617eb1a Mon Sep 17 00:00:00 2001 From: Daniil Kuts <13482580+apach301@users.noreply.github.com> Date: Fri, 27 May 2022 13:52:31 +0300 Subject: Add AFL_SYNC_TIME variable for synchronization time tuning (#1425) * Add AFL_SYNC_TIME variable for synchronization time tuning * Documentation for AFL_SYNC_TIME variable --- docs/env_variables.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index fe9c6e07..3c69c0b6 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -517,6 +517,10 @@ checks or alter some of the more exotic semantics of the tool: (empty/non present) will add no tags to the metrics. For more information, see [rpc_statsd.md](rpc_statsd.md). + - `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes) + between fuzzing instances synchronization. Default sync time is 30 minutes, + note that time is halfed for -M main nodes. + - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would -- cgit 1.4.1 From 50c6031cc3350b3fea486774ddef89eaf2cab5c3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 31 May 2022 09:24:28 +0200 Subject: remove optimin --- .gitmodules | 3 - docs/Changelog.md | 3 + utils/README.md | 2 - utils/optimin/.gitignore | 11 - utils/optimin/CMakeLists.txt | 22 -- utils/optimin/EVALMAXSAT_VERSION | 1 - utils/optimin/EvalMaxSAT | 1 - utils/optimin/README.md | 94 ------ utils/optimin/build_optimin.sh | 131 -------- utils/optimin/src/CMakeLists.txt | 13 - utils/optimin/src/OptiMin.cpp | 702 --------------------------------------- 11 files changed, 3 insertions(+), 980 deletions(-) delete mode 100644 utils/optimin/.gitignore delete mode 100644 utils/optimin/CMakeLists.txt delete mode 100644 utils/optimin/EVALMAXSAT_VERSION delete mode 160000 utils/optimin/EvalMaxSAT delete mode 100644 utils/optimin/README.md delete mode 100755 utils/optimin/build_optimin.sh delete mode 100644 utils/optimin/src/CMakeLists.txt delete mode 100644 utils/optimin/src/OptiMin.cpp (limited to 'docs') diff --git a/.gitmodules b/.gitmodules index 8ba1c39d..18fda27e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,9 +10,6 @@ [submodule "custom_mutators/gramatron/json-c"] path = custom_mutators/gramatron/json-c url = https://github.com/json-c/json-c -[submodule "utils/optimin/EvalMaxSAT"] - path = utils/optimin/EvalMaxSAT - url = https://github.com/FlorentAvellaneda/EvalMaxSAT [submodule "coresight_mode/patchelf"] path = coresight_mode/patchelf url = https://github.com/NixOS/patchelf.git diff --git a/docs/Changelog.md b/docs/Changelog.md index b18bf30f..6269e3b1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -41,6 +41,9 @@ sending a mail to . - update to new frida release, handles now c++ throw/catch - unicorn_mode: - update unicorn engine, fix C example + - utils: + - removed optimin because it looses coverage due a bug and is + unmaintained :-( ### Version ++4.00c (release) diff --git a/utils/README.md b/utils/README.md index debc86e8..62d79193 100644 --- a/utils/README.md +++ b/utils/README.md @@ -56,8 +56,6 @@ Here's a quick overview of the stuff you can find in this directory: - libpng_no_checksum - a sample patch for removing CRC checks in libpng. - - optimin - An optimal corpus minimizer. - - persistent_mode - an example of how to use the LLVM persistent process mode to speed up certain fuzzing jobs. diff --git a/utils/optimin/.gitignore b/utils/optimin/.gitignore deleted file mode 100644 index 46f42f8f..00000000 --- a/utils/optimin/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -CMakeLists.txt.user -CMakeCache.txt -CMakeFiles -CMakeScripts -Testing -Makefile -cmake_install.cmake -install_manifest.txt -compile_commands.json -CTestTestfile.cmake -_deps diff --git a/utils/optimin/CMakeLists.txt b/utils/optimin/CMakeLists.txt deleted file mode 100644 index b45dd004..00000000 --- a/utils/optimin/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(optimin - LANGUAGES CXX - DESCRIPTION "MaxSAT-based fuzzing corpus minimizer" -) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") - -# Add LLVM -find_package(LLVM REQUIRED CONFIG) -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - -include_directories(${LLVM_INCLUDE_DIRS}) -add_definitions(${LLVM_DEFINITIONS} -DNDEBUG) - -add_subdirectory(EvalMaxSAT) -add_subdirectory(src) diff --git a/utils/optimin/EVALMAXSAT_VERSION b/utils/optimin/EVALMAXSAT_VERSION deleted file mode 100644 index d836ff1c..00000000 --- a/utils/optimin/EVALMAXSAT_VERSION +++ /dev/null @@ -1 +0,0 @@ -440bf90edf88f6ab940934129e3c5b3b93764295 diff --git a/utils/optimin/EvalMaxSAT b/utils/optimin/EvalMaxSAT deleted file mode 160000 index 440bf90e..00000000 --- a/utils/optimin/EvalMaxSAT +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 440bf90edf88f6ab940934129e3c5b3b93764295 diff --git a/utils/optimin/README.md b/utils/optimin/README.md deleted file mode 100644 index 340022b8..00000000 --- a/utils/optimin/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# OptiMin - -OptiMin is a corpus minimizer that uses a -[MaxSAT](https://en.wikipedia.org/wiki/Maximum_satisfiability_problem) solver -to identify a subset of functionally distinct files that exercise different code -paths in a target program. - -Unlike most corpus minimizers, such as `afl-cmin`, OptiMin does not rely on -heuristic and/or greedy algorithms to identify these functionally distinct -files. This means that minimized corpora are generally much smaller than those -produced by other tools. - -## Building - -To build the `optimin` just execute the `build_optimin.sh` script. - -## Running - -Running `optimin` is the same as running `afl-cmin`: - -``` -./optimin -h -OVERVIEW: Optimal corpus minimizer -USAGE: optimin [options] [target args...] - -OPTIONS: - -Color Options: - - --color - Use colors in output (default=autodetect) - -General options: - - -C - Keep crashing inputs, reject everything else - -O - Use binary-only instrumentation (FRIDA mode) - -Q - Use binary-only instrumentation (QEMU mode) - -U - Use unicorn-based instrumentation (unicorn mode) - -f - Include edge hit counts - -i dir - Input directory - -m megs - Memory limit for child process (default=none) - -o dir - Output directory - -p - Display progress bar - -t msec - Run time limit for child process (default=5000) - -w csv - Weights file - -Generic Options: - - --help - Display available options (--help-hidden for more) - --help-list - Display list of available options (--help-list-hidden for more) - --version - Display the version of this program -``` - -Example: `optimin -i files -o seeds -- ./target @@` - -### Weighted Minimizations - -OptiMin allows for weighted minimizations. For examples, seeds can be weighted -by file size (or execution time), thus preferencing the selection of smaller (or -faster) seeds. - -To perform a weighted minimization, supply a CSV file with the `-w` option. This -CSV file is formatted as follows: - -``` -SEED_1,WEIGHT_1 -SEED_2,WEIGHT_2 -... -SEED_N,WEIGHT_N -``` - -Where `SEED_N` is the file name (**not** path) of a seed in the input directory, -and `WEIGHT_N` is an integer weight. - -## Further Details and Citation - -For more details, see the paper -[Seed Selection for Successful Fuzzing](https://dl.acm.org/doi/10.1145/3460319.3464795). -If you use OptiMin in your research, please cite this paper. - -BibTeX: - -```bibtex -@inproceedings{Herrera:2021:FuzzSeedSelection, - author = {Adrian Herrera and Hendra Gunadi and Shane Magrath and Michael Norrish and Mathias Payer and Antony L. Hosking}, - title = {Seed Selection for Successful Fuzzing}, - booktitle = {30th ACM SIGSOFT International Symposium on Software Testing and Analysis}, - series = {ISSTA}, - year = {2021}, - pages = {230--243}, - numpages = {14}, - location = {Virtual, Denmark}, - publisher = {Association for Computing Machinery}, -} -``` \ No newline at end of file diff --git a/utils/optimin/build_optimin.sh b/utils/optimin/build_optimin.sh deleted file mode 100755 index aee5d0c3..00000000 --- a/utils/optimin/build_optimin.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/sh -# -# american fuzzy lop++ - optimin build script -# ------------------------------------------------ -# -# Originally written by Nathan Voss -# -# Adapted from code by Andrew Griffiths and -# Michal Zalewski -# -# Adapted for AFLplusplus by Dominik Maier -# -# Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2022 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 -# -# This script builds the OptiMin corpus minimizer. - -EVALMAXSAT_VERSION="$(cat ./EVALMAXSAT_VERSION)" -EVALMAXSAT_REPO="https://github.com/FlorentAvellaneda/EvalMaxSAT" - -echo "=================================================" -echo "OptiMin build script" -echo "=================================================" -echo - -echo "[*] Performing basic sanity checks..." - -PLT=`uname -s` - -if [ ! -f "../../config.h" ]; then - - echo "[-] Error: key files not found - wrong working directory?" - exit 1 - -fi - -LLVM_CONFIG="${LLVM_CONFIG:-llvm-config}" -CMAKECMD=cmake -MAKECMD=make -TARCMD=tar - -if [ "$PLT" = "Darwin" ]; then - CORES=`sysctl -n hw.ncpu` - TARCMD=tar -fi - -if [ "$PLT" = "FreeBSD" ]; then - MAKECMD=gmake - CORES=`sysctl -n hw.ncpu` - TARCMD=gtar -fi - -if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then - MAKECMD=gmake - CORES=`sysctl -n hw.ncpu` - TARCMD=gtar -fi - -PREREQ_NOTFOUND= -for i in git $CMAKECMD $MAKECMD $TARCMD; do - - T=`command -v "$i" 2>/dev/null` - - if [ "$T" = "" ]; then - - echo "[-] Error: '$i' not found. Run 'sudo apt-get install $i' or similar." - PREREQ_NOTFOUND=1 - - fi - -done - -if echo "$CC" | grep -qF /afl-; then - - echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool." - PREREQ_NOTFOUND=1 - -fi - -if [ "$PREREQ_NOTFOUND" = "1" ]; then - exit 1 -fi - -echo "[+] All checks passed!" - -echo "[*] Making sure EvalMaxSAT is checked out" - -git status 1>/dev/null 2>/dev/null -if [ $? -eq 0 ]; then - echo "[*] initializing EvalMaxSAT submodule" - git submodule init || exit 1 - git submodule update ./EvalMaxSAT 2>/dev/null # ignore errors -else - echo "[*] cloning EvalMaxSAT" - test -d EvalMaxSAT || { - CNT=1 - while [ '!' -d EvalMaxSAT -a "$CNT" -lt 4 ]; do - echo "Trying to clone EvalMaxSAT (attempt $CNT/3)" - git clone "$EVALMAXSAT_REPO" - CNT=`expr "$CNT" + 1` - done - } -fi - -test -d EvalMaxSAT || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; } -echo "[+] Got EvalMaxSAT." - -cd "EvalMaxSAT" || exit 1 -echo "[*] Checking out $EVALMAXSAT_VERSION" -sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null -git checkout "$EVALMAXSAT_VERSION" || exit 1 -cd .. - -echo -echo -echo "[+] EvalMaxSAT successfully prepared!" -echo "[+] Building OptiMin now." -mkdir -p build -cd build || exit 1 -cmake .. -DLLVM_DIR=`$LLVM_CONFIG --cmakedir` || exit 1 -make -j$CORES || exit 1 -cd .. -echo -cp -fv build/src/optimin . || exit 1 -echo "[+] OptiMin successfully built!" diff --git a/utils/optimin/src/CMakeLists.txt b/utils/optimin/src/CMakeLists.txt deleted file mode 100644 index 693f63f2..00000000 --- a/utils/optimin/src/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_executable(optimin OptiMin.cpp) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") - -foreach(LIB MaLib EvalMaxSAT glucose) - target_include_directories(optimin PRIVATE - "${CMAKE_SOURCE_DIR}/EvalMaxSAT/lib/${LIB}/src") - target_link_libraries(optimin ${LIB}) -endforeach(LIB) - -llvm_map_components_to_libnames(LLVM_LIBS support) -target_link_libraries(optimin ${LLVM_LIBS}) - -install(TARGETS optimin RUNTIME DESTINATION bin) diff --git a/utils/optimin/src/OptiMin.cpp b/utils/optimin/src/OptiMin.cpp deleted file mode 100644 index b0082d14..00000000 --- a/utils/optimin/src/OptiMin.cpp +++ /dev/null @@ -1,702 +0,0 @@ -/* - * OptiMin, an optimal fuzzing corpus minimizer. - * - * Author: Adrian Herrera - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "EvalMaxSAT.h" - -using namespace llvm; - -namespace { - -// -------------------------------------------------------------------------- // -// Classes -// -------------------------------------------------------------------------- // - -/// Ensure seed weights default to 1 -class Weight { - - public: - Weight() : Weight(1){}; - Weight(uint32_t V) : Value(V){}; - - operator unsigned() const { - - return Value; - - } - - private: - const unsigned Value; - -}; - -// -------------------------------------------------------------------------- // -// Typedefs -// -------------------------------------------------------------------------- // - -/// AFL tuple (edge) ID -using AFLTupleID = uint32_t; - -/// Pair of tuple ID and hit count -using AFLTuple = std::pair; - -/// Coverage for a given seed file -using AFLCoverageVector = std::vector; - -/// Map seed file paths to its coverage vector -using AFLCoverageMap = StringMap; - -/// Map seed file paths to a weight -using WeightsMap = StringMap; - -/// A seed identifier in the MaxSAT solver -using SeedID = int; - -/// Associates seed identifiers to seed files -using MaxSATSeeds = - SmallVector, 0>; - -/// Set of literal identifiers -using MaxSATSeedSet = DenseSet; - -/// Maps tuple IDs to the literal identifiers that "cover" that tuple -using MaxSATCoverageMap = DenseMap; - -// -------------------------------------------------------------------------- // -// Global variables -// -------------------------------------------------------------------------- // - -// This is based on the human class count in `count_class_human[256]` in -// `afl-showmap.c` -static constexpr uint32_t MAX_EDGE_FREQ = 8; - -// The maximum number of failures allowed when parsing a weights file -static constexpr unsigned MAX_WEIGHT_FAILURES = 5; - -static sys::TimePoint<> StartTime, EndTime; -static std::chrono::seconds Duration; - -static std::string ShowmapPath; -static bool TargetArgsHasAtAt = false; -static bool KeepTraces = false; -static bool SkipBinCheck = false; - -static const auto ErrMsg = [] { - - return WithColor(errs(), raw_ostream::RED, /*Bold=*/true) << "[-] "; - -}; - -static const auto WarnMsg = [] { - - return WithColor(errs(), raw_ostream::MAGENTA, /*Bold=*/true) << "[-] "; - -}; - -static const auto SuccMsg = [] { - - return WithColor(outs(), raw_ostream::GREEN, /*Bold=*/true) << "[+] "; - -}; - -static const auto StatMsg = [] { - - return WithColor(outs(), raw_ostream::BLUE, /*Bold=*/true) << "[*] "; - -}; - -static cl::opt InputDir("i", cl::desc("Input directory"), - cl::value_desc("dir"), cl::Required); -static cl::opt OutputDir("o", cl::desc("Output directory"), - cl::value_desc("dir"), cl::Required); - -static cl::opt EdgesOnly("f", cl::desc("Include edge hit counts"), - cl::init(true)); -static cl::opt WeightsFile("w", cl::desc("Weights file"), - cl::value_desc("csv")); - -static cl::opt TargetProg(cl::Positional, - cl::desc(""), - cl::Required); -static cl::list TargetArgs(cl::ConsumeAfter, - cl::desc("[target args...]")); - -static cl::opt MemLimit( - "m", cl::desc("Memory limit for child process (default=none)"), - cl::value_desc("megs"), cl::init("none")); -static cl::opt Timeout( - "t", cl::desc("Run time limit for child process (default=5000)"), - cl::value_desc("msec"), cl::init("5000")); - -static cl::opt CrashMode( - "C", cl::desc("Keep crashing inputs, reject everything else")); -static cl::opt FridaMode( - "O", cl::desc("Use binary-only instrumentation (FRIDA mode)")); -static cl::opt QemuMode( - "Q", cl::desc("Use binary-only instrumentation (QEMU mode)")); -static cl::opt UnicornMode( - "U", cl::desc("Use unicorn-based instrumentation (unicorn mode)")); - -} // anonymous namespace - -// -------------------------------------------------------------------------- // -// Helper functions -// -------------------------------------------------------------------------- // - -static void GetWeights(const MemoryBuffer &MB, WeightsMap &Weights) { - - SmallVector Lines; - MB.getBuffer().trim().split(Lines, '\n'); - - unsigned FailureCount = 0; - unsigned Weight = 0; - - for (const auto &Line : Lines) { - - const auto &[Seed, WeightStr] = Line.split(','); - - if (to_integer(WeightStr, Weight, 10)) { - - Weights.try_emplace(Seed, Weight); - - } else { - - if (FailureCount >= MAX_WEIGHT_FAILURES) { - ErrMsg() << "Too many failures. Aborting\n"; - std::exit(1); - } - - WarnMsg() << "Failed to read weight for '" << Seed << "'. Skipping...\n"; - FailureCount++; - - } - - } - -} - -static std::error_code readCov(const StringRef Trace, AFLCoverageVector &Cov) { - - const auto CovOrErr = MemoryBuffer::getFile(Trace); - if (const auto EC = CovOrErr.getError()) return EC; - - SmallVector Lines; - CovOrErr.get()->getBuffer().trim().split(Lines, '\n'); - - AFLTupleID Edge = 0; - unsigned Freq = 0; - - for (const auto &Line : Lines) { - - const auto &[EdgeStr, FreqStr] = Line.split(':'); - - to_integer(EdgeStr, Edge, 10); - to_integer(FreqStr, Freq, 10); - Cov.push_back({Edge, Freq}); - - } - - return std::error_code(); - -} - -static Error runShowmap(AFLCoverageMap &CovMap, const StringRef Input, - bool BinCheck = false) { - - const bool InputIsFile = !sys::fs::is_directory(Input); - Optional Redirects[] = {None, None, None}; - - SmallString<32> TraceDir{OutputDir}; - sys::path::append(TraceDir, ".traces"); - - SmallString<32> Output{TraceDir}; - SmallString<32> StdinFile{TraceDir}; - - // ------------------------------------------------------------------------ // - // Prepare afl-showmap arguments - // - // If the given input is a file, then feed this directly into stdin. - // Otherwise, if it is a directory, specify this on the afl-showmap command - // line. - // ------------------------------------------------------------------------ // - - SmallVector ShowmapArgs{ShowmapPath, "-q", - "-m", MemLimit, - "-t", Timeout}; - - if (InputIsFile) { - - StdinFile = Input; - sys::path::append(Output, - BinCheck ? ".run_test" : sys::path::filename(Input)); - - } else { - - sys::path::append(StdinFile, ".cur_input"); - ShowmapArgs.append({"-i", Input}); - - } - - - if (TargetArgsHasAtAt) { - - ShowmapArgs.append({"-H", StdinFile}); - Redirects[/* stdin */ 0] = "/dev/null"; - - } else if (InputIsFile) { - - Redirects[/* stdin */ 0] = Input; - - } - - if (FridaMode) ShowmapArgs.push_back("-O"); - if (QemuMode) ShowmapArgs.push_back("-Q"); - if (UnicornMode) ShowmapArgs.push_back("-U"); - - ShowmapArgs.append({"-o", Output, "--", TargetProg}); - ShowmapArgs.append(TargetArgs.begin(), TargetArgs.end()); - - // ------------------------------------------------------------------------ // - // Run afl-showmap - // ------------------------------------------------------------------------ // - - const int RC = sys::ExecuteAndWait(ShowmapPath, ShowmapArgs, - /*env=*/None, Redirects); - if (RC && !CrashMode) { - - ErrMsg() << "Exit code " << RC << " != 0 received from afl-showmap\n"; - return createStringError(inconvertibleErrorCode(), "afl-showmap failed"); - - } - - // ------------------------------------------------------------------------ // - // Parse afl-showmap output - // ------------------------------------------------------------------------ // - - AFLCoverageVector Cov; - std::error_code EC; - sys::fs::file_status Status; - - if (InputIsFile) { - - // Read a single output coverage file - if ((EC = readCov(Output, Cov))) { - - sys::fs::remove(Output); - return errorCodeToError(EC); - - } - - CovMap.try_emplace(sys::path::filename(Input), Cov); - if (!KeepTraces) sys::fs::remove(Output); - - } else { - - // Read a directory of output coverage files - for (sys::fs::recursive_directory_iterator Dir(TraceDir, EC), DirEnd; - Dir != DirEnd && !EC; Dir.increment(EC)) { - - if (EC) return errorCodeToError(EC); - - const auto &Path = Dir->path(); - if ((EC = sys::fs::status(Path, Status))) return errorCodeToError(EC); - - switch (Status.type()) { - - case sys::fs::file_type::regular_file: - case sys::fs::file_type::symlink_file: - case sys::fs::file_type::type_unknown: - Cov.clear(); - if ((EC = readCov(Path, Cov))) { - - sys::fs::remove(Path); - return errorCodeToError(EC); - - } - - CovMap.try_emplace(sys::path::filename(Path), Cov); - default: - // Ignore - break; - - } - - } - - if (!KeepTraces) sys::fs::remove_directories(TraceDir); - - } - - return Error::success(); - -} - -static inline void StartTimer() { - - StartTime = std::chrono::system_clock::now(); - -} - -static inline void EndTimer() { - - EndTime = std::chrono::system_clock::now(); - Duration = - std::chrono::duration_cast(EndTime - StartTime); - - SuccMsg() << " Completed in " << Duration.count() << " s\n"; - -} - -// -------------------------------------------------------------------------- // -// Main function -// -------------------------------------------------------------------------- // - -int main(int argc, char *argv[]) { - - WeightsMap Weights; - std::error_code EC; - - // ------------------------------------------------------------------------ // - // Parse command-line options and environment variables - // - // Also check the target arguments, as this determines how we run afl-showmap. - // ------------------------------------------------------------------------ // - - cl::ParseCommandLineOptions(argc, argv, "Optimal corpus minimizer"); - - KeepTraces = !!std::getenv("AFL_KEEP_TRACES"); - SkipBinCheck = !!std::getenv("AFL_SKIP_BIN_CHECK"); - const auto AFLPath = std::getenv("AFL_PATH"); - - if (CrashMode) ::setenv("AFL_CMIN_CRASHES_ONLY", "1", /*overwrite=*/true); - - for (const auto &Arg : TargetArgs) - if (Arg == "@@") TargetArgsHasAtAt = true; - - // ------------------------------------------------------------------------ // - // Find afl-showmap - // ------------------------------------------------------------------------ // - - SmallVector EnvPaths; - - if (const char *PathEnv = std::getenv("PATH")) - SplitString(PathEnv, EnvPaths, ":"); - if (AFLPath) EnvPaths.push_back(AFLPath); - - const auto ShowmapOrErr = sys::findProgramByName("afl-showmap", EnvPaths); - if (ShowmapOrErr.getError()) { - - ErrMsg() << "Failed to find afl-showmap. Check your PATH\n"; - return 1; - - } - - ShowmapPath = *ShowmapOrErr; - - // ------------------------------------------------------------------------ // - // Parse weights - // - // Weights are stored in CSV file mapping a seed file name to an integer - // greater than zero. - // ------------------------------------------------------------------------ // - - if (WeightsFile != "") { - - StatMsg() << "Reading weights from '" << WeightsFile << "'...\n"; - StartTimer(); - - const auto WeightsOrErr = MemoryBuffer::getFile(WeightsFile); - if ((EC = WeightsOrErr.getError())) { - - ErrMsg() << "Failed to read weights from '" << WeightsFile - << "': " << EC.message() << '\n'; - return 1; - - } - - GetWeights(*WeightsOrErr.get(), Weights); - - EndTimer(); - - } - - // ------------------------------------------------------------------------ // - // Traverse input directory - // - // Find the seed files inside this directory (and subdirectories). - // ------------------------------------------------------------------------ // - - StatMsg() << "Locating seeds in '" << InputDir << "'...\n"; - StartTimer(); - - bool IsDirResult; - if ((EC = sys::fs::is_directory(InputDir, IsDirResult))) { - - ErrMsg() << "Invalid input directory '" << InputDir << "': " << EC.message() - << '\n'; - return 1; - - } - - sys::fs::file_status Status; - StringMap SeedFiles; - - for (sys::fs::recursive_directory_iterator Dir(InputDir, EC), DirEnd; - Dir != DirEnd && !EC; Dir.increment(EC)) { - - if (EC) { - - ErrMsg() << "Failed to traverse input directory '" << InputDir - << "': " << EC.message() << '\n'; - return 1; - - } - - const auto &Path = Dir->path(); - if ((EC = sys::fs::status(Path, Status))) { - - ErrMsg() << "Failed to access '" << Path << "': " << EC.message() << '\n'; - return 1; - - } - - switch (Status.type()) { - - case sys::fs::file_type::regular_file: - case sys::fs::file_type::symlink_file: - case sys::fs::file_type::type_unknown: - SeedFiles.try_emplace(sys::path::filename(Path), - sys::path::parent_path(Path)); - default: - /* Ignore */ - break; - - } - - } - - EndTimer(); - - if (SeedFiles.empty()) { - - ErrMsg() << "Failed to find any seed files in '" << InputDir << "'\n"; - return 1; - - } - - // ------------------------------------------------------------------------ // - // Setup output directory - // ------------------------------------------------------------------------ // - - SmallString<32> TraceDir{OutputDir}; - sys::path::append(TraceDir, ".traces"); - - if ((EC = sys::fs::remove_directories(TraceDir))) { - - ErrMsg() << "Failed to remove existing trace directory in '" << OutputDir - << "': " << EC.message() << '\n'; - return 1; - - } - - if ((EC = sys::fs::create_directories(TraceDir))) { - - ErrMsg() << "Failed to create output directory '" << OutputDir - << "': " << EC.message() << '\n'; - return 1; - - } - - // ------------------------------------------------------------------------ // - // Test the target binary - // ------------------------------------------------------------------------ // - - AFLCoverageMap CovMap; - - if (!SkipBinCheck) { - - const auto It = SeedFiles.begin(); - SmallString<32> TestSeed{It->second}; - sys::path::append(TestSeed, It->first()); - - StatMsg() << "Testing the target binary with '" << TestSeed << "`...\n"; - StartTimer(); - - if (auto Err = runShowmap(CovMap, TestSeed, /*BinCheck=*/true)) { - - ErrMsg() << "No instrumentation output detected \n"; - return 1; - - } - - EndTimer(); - SuccMsg() << "OK, " << CovMap.begin()->second.size() - << " tuples recorded\n"; - - } - - // ------------------------------------------------------------------------ // - // Generate seed coverage - // - // Iterate over the corpus directory, which should contain seed files. Execute - // these seeds in the target program to generate coverage information, and - // then store this coverage information in the appropriate data structures. - // ------------------------------------------------------------------------ // - - StatMsg() << "Running afl-showmap on " << SeedFiles.size() << " seeds...\n"; - StartTimer(); - - MaxSATSeeds SeedVars; - MaxSATCoverageMap SeedCoverage; - EvalMaxSAT Solver(/*nbMinimizeThread=*/0); - - CovMap.clear(); - if (auto Err = runShowmap(CovMap, InputDir)) { - - ErrMsg() << "Failed to generate coverage: " << Err << '\n'; - return 1; - - } - - for (const auto &SeedCov : CovMap) { - - // Create a variable to represent the seed - const SeedID Var = Solver.newVar(); - SeedVars.emplace_back(Var, SeedCov.first()); - - // Record the set of seeds that cover a particular edge - for (auto &[Edge, Freq] : SeedCov.second) { - - if (EdgesOnly) { - - // Ignore edge frequency - SeedCoverage[Edge].insert(Var); - - } else { - - // Executing edge `E` `N` times means that it was executed `N - 1` times - for (unsigned I = 0; I < Freq; ++I) - SeedCoverage[MAX_EDGE_FREQ * Edge + I].insert(Var); - - } - - } - - } - - EndTimer(); - - // ------------------------------------------------------------------------ // - // Set the hard and soft constraints in the solver - // ------------------------------------------------------------------------ // - - StatMsg() << "Generating constraints...\n"; - StartTimer(); - - size_t SeedCount = 0; - - // Ensure that at least one seed is selected that covers a particular edge - // (hard constraint) - std::vector Clauses; - for (const auto &[_, Seeds] : SeedCoverage) { - - if (Seeds.empty()) continue; - - Clauses.clear(); - for (const auto &Seed : Seeds) - Clauses.push_back(Seed); - - Solver.addClause(Clauses); - - } - - // Select the minimum number of seeds that cover a particular set of edges - // (soft constraint) - for (const auto &[Var, Seed] : SeedVars) - Solver.addWeightedClause({-Var}, Weights[sys::path::filename(Seed)]); - - EndTimer(); - - // ------------------------------------------------------------------------ // - // Generate a solution - // ------------------------------------------------------------------------ // - - StatMsg() << "Solving...\n"; - StartTimer(); - - const bool Solved = Solver.solve(); - - EndTimer(); - - // ------------------------------------------------------------------------ // - // Save the solution - // - // This will copy the selected seeds to the given output directory. - // ------------------------------------------------------------------------ // - - SmallVector Solution; - SmallString<32> InputSeed, OutputSeed; - - if (Solved) { - - for (const auto &[Var, Seed] : SeedVars) - if (Solver.getValue(Var) > 0) Solution.push_back(Seed); - - } else { - - ErrMsg() << "Failed to find an optimal solution for '" << InputDir << "'\n"; - return 1; - - } - - StatMsg() << "Copying " << Solution.size() << " seeds to '" << OutputDir - << "'...\n"; - StartTimer(); - - SeedCount = 0; - - for (const auto &Seed : Solution) { - - InputSeed = SeedFiles[Seed]; - sys::path::append(InputSeed, Seed); - - OutputSeed = OutputDir; - sys::path::append(OutputSeed, Seed); - - if ((EC = sys::fs::copy_file(InputSeed, OutputSeed))) { - - ErrMsg() << "Failed to copy '" << Seed << "' to '" << OutputDir - << "': " << EC.message() << '\n'; - return 1; - - } - - } - - EndTimer(); - SuccMsg() << "Done!\n"; - - return 0; - -} - -- cgit 1.4.1 From da1b0410984c244881d818239372ba7ac07e36c3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 12 Jun 2022 08:24:32 +0200 Subject: update changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 6269e3b1..4091c5f9 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -28,6 +28,7 @@ sending a mail to . kept), unless AFL_KEEP_TIMEOUTS are set - AFL never implemented auto token inserts (but user token inserts, user token overwrite and auto token overwrite), added now! + - fixed for a mutation type in havoc mode - Mopt fix to always select the correct algorithm - fix effector map calculation (deterministic mode) - fix custom mutator post_process functionality -- cgit 1.4.1 From ba21e20695313d538535788cdc55f4b26304e56a Mon Sep 17 00:00:00 2001 From: hexcoder Date: Tue, 14 Jun 2022 14:56:10 +0200 Subject: typo --- docs/env_variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index 3c69c0b6..a63aad10 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -519,7 +519,7 @@ checks or alter some of the more exotic semantics of the tool: - `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes) between fuzzing instances synchronization. Default sync time is 30 minutes, - note that time is halfed for -M main nodes. + note that time is halved for -M main nodes. - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz -- cgit 1.4.1 From 80892b8fc597fcfa73bd9f105d3f0f4171a92c57 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Tue, 14 Jun 2022 14:57:31 +0200 Subject: typos --- docs/Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 4091c5f9..44939b16 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -28,7 +28,7 @@ sending a mail to . kept), unless AFL_KEEP_TIMEOUTS are set - AFL never implemented auto token inserts (but user token inserts, user token overwrite and auto token overwrite), added now! - - fixed for a mutation type in havoc mode + - fixed a mutation type in havoc mode - Mopt fix to always select the correct algorithm - fix effector map calculation (deterministic mode) - fix custom mutator post_process functionality @@ -43,7 +43,7 @@ sending a mail to . - unicorn_mode: - update unicorn engine, fix C example - utils: - - removed optimin because it looses coverage due a bug and is + - removed optimin because it looses coverage due to a bug and is unmaintained :-( -- cgit 1.4.1 From 3d1a57deed63bdff6c817e1b1a8098df94ea5eac Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Fri, 17 Jun 2022 21:03:46 +0200 Subject: feat: allow to skip readme creation on crash --- docs/env_variables.md | 4 ++++ include/afl-fuzz.h | 3 +-- include/envs.h | 2 +- src/afl-fuzz-bitmap.c | 3 +-- src/afl-fuzz-state.c | 9 ++++++++- 5 files changed, 15 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/env_variables.md b/docs/env_variables.md index a63aad10..0598a809 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -619,6 +619,10 @@ The QEMU wrapper used to instrument binary-only code supports several settings: emulation" variables (e.g., `QEMU_STACK_SIZE`), but there should be no reason to touch them. + - Normally a `README.txt` is written to the `crashes/` directory when a first + crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when + counting crashes based on a file count in that directory. + ## 7) Settings for afl-frida-trace The FRIDA wrapper used to instrument binary-only code supports many of the same diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 24af426f..b78d0b98 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -386,7 +386,7 @@ typedef struct afl_env_vars { afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, - afl_keep_timeouts, afl_pizza_mode; + afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, @@ -1267,4 +1267,3 @@ void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem); #endif #endif - diff --git a/include/envs.h b/include/envs.h index f4cccc96..4105ac6d 100644 --- a/include/envs.h +++ b/include/envs.h @@ -159,6 +159,7 @@ static char *afl_environment_variables[] = { "AFL_NO_COLOUR", #endif "AFL_NO_CPU_RED", + "AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", @@ -234,4 +235,3 @@ static char *afl_environment_variables[] = { extern char *afl_environment_variables[]; #endif - diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 26e70d81..fffcef89 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -720,7 +720,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - if (unlikely(!afl->saved_crashes)) { write_crash_readme(afl); } + if (unlikely(!afl->saved_crashes) && (afl->afl_env.afl_no_crash_readme != 1)) { write_crash_readme(afl); } #ifndef SIMPLE_FILES @@ -821,4 +821,3 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { return keeping; } - diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 8334af75..4d16811f 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -510,6 +510,14 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_pizza_mode = atoi((u8 *)get_afl_env(afl_environment_variables[i])); + + } else if (!strncmp(env, "AFL_NO_CRASH_README", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_crash_readme = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + if (afl->afl_env.afl_pizza_mode == 0) { afl->afl_env.afl_pizza_mode = 1; @@ -665,4 +673,3 @@ void afl_states_request_skip(void) { LIST_FOREACH(&afl_states, afl_state_t, { el->skip_requested = 1; }); } - -- cgit 1.4.1 From dc3e2e8200037b4f7d14a15459ed7fa6fa3260a2 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 18 Jun 2022 09:06:27 +0200 Subject: update docs --- README.md | 3 +++ docs/INSTALL.md | 3 +++ docs/tutorials.md | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/README.md b/README.md index a29ce792..c3a627ec 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,9 @@ This image is automatically generated when a push to the stable repo happens (see [branches](#branches)). If you use the command above, you will find your target source code in `/src` in the container. +Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current +development state of AFL++. + To build AFL++ yourself - *which we recommend* - continue at [docs/INSTALL.md](docs/INSTALL.md). diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 01343b7f..754621b5 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -15,6 +15,9 @@ docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus This image is automatically generated when a push to the stable repo happens. You will find your target source code in `/src` in the container. +Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current +development state of AFL++. + If you want to build AFL++ yourself, you have many options. The easiest choice is to build and install everything: diff --git a/docs/tutorials.md b/docs/tutorials.md index 64d2b376..477ff98b 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -1,5 +1,9 @@ # Tutorials +If you are a total newbie, try this guide: + +* [https://github.com/alex-maleno/Fuzzing-Module](https://github.com/alex-maleno/Fuzzing-Module) + Here are some good write-ups to show how to effectively use AFL++: * [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/) @@ -17,7 +21,7 @@ training, then we can highly recommend the following: * [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101) If you are interested in fuzzing structured data (where you define what the -structure is), these links have you covered: +structure is), these links have you covered (some are outdated though): * libprotobuf for AFL++: [https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator) -- cgit 1.4.1 From b0e58baca2e5f67ce7304545e656868005ff73bd Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Sat, 18 Jun 2022 08:21:25 -0400 Subject: add stable tag to docs --- README.md | 8 ++++---- docs/INSTALL.md | 4 ++-- docs/fuzzing_in_depth.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index c3a627ec..d8498520 100644 --- a/README.md +++ b/README.md @@ -50,14 +50,14 @@ Here is some information to get you started: ## Building and installing AFL++ To have AFL++ easily available with everything compiled, pull the image directly -from the Docker Hub (available for x86_64 and arm64): +from the Docker Hub (available for both x86_64 and arm64): ```shell -docker pull aflplusplus/aflplusplus -docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus +docker pull aflplusplus/aflplusplus:stable +docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus:stable ``` -This image is automatically generated when a push to the stable repo happens +This image is automatically published when a push to the stable branch happens (see [branches](#branches)). If you use the command above, you will find your target source code in `/src` in the container. diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 754621b5..ac7b5486 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -8,8 +8,8 @@ hence afl-clang-lto is available) or just pull directly from the Docker Hub (for x86_64 and arm64): ```shell -docker pull aflplusplus/aflplusplus -docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus +docker pull aflplusplus/aflplusplus:stable +docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus:stable ``` This image is automatically generated when a push to the stable repo happens. diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 2c27dfe1..d5fae0a6 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -47,7 +47,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular: example, the following line will run a Docker container with all this preset: ```shell - # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk aflplusplus/aflplusplus + # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk aflplusplus/aflplusplus:stable ``` ## 1. Instrumenting the target -- cgit 1.4.1 From 85b1ce00a8c2c955f33d412d2f288807fe9b4d3e Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Sat, 18 Jun 2022 08:35:25 -0400 Subject: fully qualified names --- README.md | 4 ++-- docs/INSTALL.md | 4 ++-- docs/fuzzing_in_depth.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index d8498520..91345d0c 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ To have AFL++ easily available with everything compiled, pull the image directly from the Docker Hub (available for both x86_64 and arm64): ```shell -docker pull aflplusplus/aflplusplus:stable -docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus:stable +docker pull docker.io/aflplusplus/aflplusplus:stable +docker run -ti -v /location/of/your/target:/src docker.io/aflplusplus/aflplusplus:stable ``` This image is automatically published when a push to the stable branch happens diff --git a/docs/INSTALL.md b/docs/INSTALL.md index ac7b5486..e29fca96 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -8,8 +8,8 @@ hence afl-clang-lto is available) or just pull directly from the Docker Hub (for x86_64 and arm64): ```shell -docker pull aflplusplus/aflplusplus:stable -docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus:stable +docker pull docker.io/aflplusplus/aflplusplus:stable +docker run -ti -v /location/of/your/target:/src docker.io/aflplusplus/aflplusplus:stable ``` This image is automatically generated when a push to the stable repo happens. diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index d5fae0a6..8963c635 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -47,7 +47,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular: example, the following line will run a Docker container with all this preset: ```shell - # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk aflplusplus/aflplusplus:stable + # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk docker.io/aflplusplus/aflplusplus:stable ``` ## 1. Instrumenting the target -- cgit 1.4.1 From 48c2d516899dcd77f1c167b195eb45b2a71cc303 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 27 Jun 2022 08:31:03 +0200 Subject: nits --- README.md | 4 +- .../gramatron/build_gramatron_mutator.sh | 4 +- custom_mutators/gramatron/gramfuzz-mutators.c | 3 +- custom_mutators/gramatron/gramfuzz.c | 48 ++-------------------- custom_mutators/gramatron/hashmap.c | 6 +-- custom_mutators/gramatron/testMakefile.mk | 3 -- custom_mutators/gramatron/uthash.h | 41 +++++++++--------- docs/INSTALL.md | 9 ++-- instrumentation/afl-llvm-common.cc | 4 +- test/test-frida-mode.sh | 2 +- 10 files changed, 39 insertions(+), 85 deletions(-) delete mode 100644 custom_mutators/gramatron/testMakefile.mk (limited to 'docs') diff --git a/README.md b/README.md index 91345d0c..e851359e 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ To have AFL++ easily available with everything compiled, pull the image directly from the Docker Hub (available for both x86_64 and arm64): ```shell -docker pull docker.io/aflplusplus/aflplusplus:stable -docker run -ti -v /location/of/your/target:/src docker.io/aflplusplus/aflplusplus:stable +docker pull aflplusplus/aflplusplus +docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus ``` This image is automatically published when a push to the stable branch happens diff --git a/custom_mutators/gramatron/build_gramatron_mutator.sh b/custom_mutators/gramatron/build_gramatron_mutator.sh index 0638e3b2..9952e7f5 100755 --- a/custom_mutators/gramatron/build_gramatron_mutator.sh +++ b/custom_mutators/gramatron/build_gramatron_mutator.sh @@ -125,7 +125,7 @@ else } fi -test -f json-c/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; } +test -d json-c/.git || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; } echo "[+] Got json-c." test -e json-c/.libs/libjson-c.a || { @@ -144,6 +144,6 @@ echo echo echo "[+] Json-c successfully prepared!" echo "[+] Builing gramatron now." -$CC -O3 -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o gramatron.so -shared -I. -I/prg/dev/include gramfuzz.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c automaton-parser.c ../../src/afl-performance.o json-c/.libs/libjson-c.a || exit 1 +$CC -O3 -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o gramatron.so -shared -I. -I/prg/dev/include gramfuzz.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c ../../src/afl-performance.o json-c/.libs/libjson-c.a || exit 1 echo echo "[+] gramatron successfully built!" diff --git a/custom_mutators/gramatron/gramfuzz-mutators.c b/custom_mutators/gramatron/gramfuzz-mutators.c index 789a36fd..0fc9c307 100644 --- a/custom_mutators/gramatron/gramfuzz-mutators.c +++ b/custom_mutators/gramatron/gramfuzz-mutators.c @@ -58,8 +58,7 @@ Array *performSpliceOne(Array *originput, IdxMap_new *statemap_orig, int length = utarray_len(stateptr); if (length) { - int *splice_idx = - (int *)utarray_eltptr(stateptr, rand_below(global_afl, length)); + int *splice_idx = (int *)utarray_eltptr(stateptr, rand_below(global_afl, length)); ip.orig_idx = *splice_idx; ip.splice_idx = x; utarray_push_back(pairs, &ip); diff --git a/custom_mutators/gramatron/gramfuzz.c b/custom_mutators/gramatron/gramfuzz.c index f25dfead..9c9dbb43 100644 --- a/custom_mutators/gramatron/gramfuzz.c +++ b/custom_mutators/gramatron/gramfuzz.c @@ -9,7 +9,6 @@ #include "afl-fuzz.h" #include "gramfuzz.h" -#include "automaton-parser.h" #define MUTATORS 4 // Specify the total number of mutators @@ -164,12 +163,6 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { if (automaton_file) { pda = create_pda(automaton_file); - symbols = create_array_of_chars(); - pda_map = create_pda_hashmap((struct state *)pda, symbols); - print_symbols_arr(symbols); - first_chars = create_array_of_chars(); - first_char_to_symbols_map = - create_first_char_to_symbols_hashmap(symbols, first_chars); } else { @@ -289,27 +282,11 @@ u8 afl_custom_queue_new_entry(my_mutator_t * data, if (filename_orig_queue) { - if (data->mutated_walk) { - - write_input(data->mutated_walk, automaton_fn); - - } else { - - Array *parsed_walk = automaton_parser(filename_new_queue); - if (!parsed_walk) PFATAL("Parser unsuccessful on %s", filename_new_queue); - write_input(parsed_walk, automaton_fn); - free(parsed_walk->start); - free(parsed_walk); - - } + write_input(data->mutated_walk, automaton_fn); } else { - // TODO: try to parse the input seeds here, if they can be parsed, then - // generate the corresponding automaton file if not, then generate a new - // input - new_input = automaton_parser(filename_new_queue); - if (new_input == NULL) { new_input = gen_input(pda, NULL); } + new_input = gen_input(pda, NULL); write_input(new_input, automaton_fn); // Update the placeholder file @@ -350,21 +327,7 @@ u8 afl_custom_queue_new_entry(my_mutator_t * data, uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) { // get the filename - u8 *automaton_fn = alloc_printf("%s.aut", filename); - // find the automaton file, if the automaton file cannot be found, do not fuzz - // the current entry on the queue - FILE *fp; - fp = fopen(automaton_fn, "rb"); - if (fp == NULL) { - - printf( - "File '%s' does not exist, exiting. Would not fuzz current entry on " - "the queue\n", - automaton_fn); - return 0; - - } - + u8 * automaton_fn = alloc_printf("%s.aut", filename); IdxMap_new *statemap_ptr; terminal * term_ptr; int state; @@ -461,11 +424,6 @@ void afl_custom_deinit(my_mutator_t *data) { free(data->mutator_buf); free(data); - free_hashmap(pda_map, &free_terminal_arr); - free_hashmap(first_char_to_symbols_map, &free_array_of_chars); - free_pda(pda); - free_array_of_chars(NULL, symbols); // free the array of symbols - free_array_of_chars(NULL, first_chars); } diff --git a/custom_mutators/gramatron/hashmap.c b/custom_mutators/gramatron/hashmap.c index db4f9f98..09715b87 100644 --- a/custom_mutators/gramatron/hashmap.c +++ b/custom_mutators/gramatron/hashmap.c @@ -151,7 +151,7 @@ static unsigned long crc32_tab[] = { /* Return a 32-bit CRC of the contents of the buffer. */ -unsigned long custom_crc32(const unsigned char *s, unsigned int len) { +unsigned long crc32(const unsigned char *s, unsigned int len) { unsigned int i; unsigned long crc32val; @@ -172,9 +172,7 @@ unsigned long custom_crc32(const unsigned char *s, unsigned int len) { */ unsigned int hashmap_hash_int(hashmap_map *m, char *keystring) { - unsigned int keystring_len = strlen(keystring); - - unsigned long key = custom_crc32((unsigned char *)(keystring), keystring_len); + unsigned long key = crc32((unsigned char *)(keystring), strlen(keystring)); /* Robert Jenkins' 32 bit Mix Function */ key += (key << 12); diff --git a/custom_mutators/gramatron/testMakefile.mk b/custom_mutators/gramatron/testMakefile.mk deleted file mode 100644 index ff19826b..00000000 --- a/custom_mutators/gramatron/testMakefile.mk +++ /dev/null @@ -1,3 +0,0 @@ -test: test.c - gcc -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o test -I. -I/prg/dev/include test.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c ../../src/afl-performance.o json-c/.libs/libjson-c.a - diff --git a/custom_mutators/gramatron/uthash.h b/custom_mutators/gramatron/uthash.h index 93322d5b..05c8abe6 100644 --- a/custom_mutators/gramatron/uthash.h +++ b/custom_mutators/gramatron/uthash.h @@ -127,8 +127,6 @@ typedef unsigned char uint8_t; #if HASH_NONFATAL_OOM /* malloc failures can be recovered from */ - #define IF_HASH_NONFATAL_OOM(x) x - #ifndef uthash_nonfatal_oom #define uthash_nonfatal_oom(obj) \ do { \ @@ -142,6 +140,8 @@ typedef unsigned char uint8_t; (oomed) = 1; \ \ } while (0) +\ + #define IF_HASH_NONFATAL_OOM(x) x #else /* malloc failures result in lost memory, hash tables are unusable */ @@ -156,10 +156,11 @@ typedef unsigned char uint8_t; #endif /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets \ - */ -#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 \ + 5U /* lg2 of initial number of buckets \ + */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ /* calculate the element whose hash handle address is hhp */ #define ELMT_FROM_HH(tbl, hhp) ((void *)(((char *)(hhp)) - ((tbl)->hho))) @@ -646,7 +647,7 @@ typedef unsigned char uint8_t; HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ \ } while (0) - +\ #define HASH_ADD_STR(head, strfield, add) \ do { \ \ @@ -654,7 +655,7 @@ typedef unsigned char uint8_t; HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ \ } while (0) - +\ #define HASH_REPLACE_STR(head, strfield, add, replaced) \ do { \ \ @@ -662,7 +663,7 @@ typedef unsigned char uint8_t; HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ \ } while (0) - +\ #define HASH_FIND_INT(head, findint, out) \ HASH_FIND(hh, head, findint, sizeof(int), out) #define HASH_ADD_INT(head, intfield, add) \ @@ -682,17 +683,17 @@ typedef unsigned char uint8_t; * isn't defined. */ #ifdef HASH_DEBUG - #define HASH_OOPS(...) \ + #define HASH_OOPS(...) \ + do { \ + \ + fprintf(stderr, __VA_ARGS__); \ + exit(-1); \ + \ + } while (0) +\ + #define HASH_FSCK(hh, head, where) \ do { \ \ - fprintf(stderr, __VA_ARGS__); \ - exit(-1); \ - \ - } while (0) \ - \ - \ - #define HASH_FSCK(hh, head, where) do { \ - \ struct UT_hash_handle *_thh; \ if (head) { \ \ @@ -758,8 +759,7 @@ typedef unsigned char uint8_t; \ } \ \ - } \ - while (0) + } while (0) #else #define HASH_FSCK(hh, head, where) @@ -1352,7 +1352,6 @@ typedef unsigned char uint8_t; \ } else if ((cmpfcn(DECLTYPE(head)( \ \ - \ ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, \ _hs_q)))) <= 0) { \ diff --git a/docs/INSTALL.md b/docs/INSTALL.md index e29fca96..41ec8561 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -8,11 +8,11 @@ hence afl-clang-lto is available) or just pull directly from the Docker Hub (for x86_64 and arm64): ```shell -docker pull docker.io/aflplusplus/aflplusplus:stable -docker run -ti -v /location/of/your/target:/src docker.io/aflplusplus/aflplusplus:stable +docker pull aflplusplus/aflplusplus: +docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus ``` -This image is automatically generated when a push to the stable repo happens. +This image is automatically generated when a push to the stable branch happens. You will find your target source code in `/src` in the container. Note: you can also pull `aflplusplus/aflplusplus:dev` which is the most current @@ -21,6 +21,9 @@ development state of AFL++. If you want to build AFL++ yourself, you have many options. The easiest choice is to build and install everything: +NOTE: depending on your Debian/Ubuntu/Kali/... version replease `-12` with +whatever llvm version is available! + ```shell sudo apt-get update sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index 9483da83..5fcf27fb 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -291,7 +291,7 @@ void scanForDangerousFunctions(llvm::Module *M) { StringRef r_name = cast(r->getOperand(0))->getName(); if (!be_quiet) fprintf(stderr, - "Info: Found an ifunc with name %s that points to resolver " + "Note: Found an ifunc with name %s that points to resolver " "function %s, we will not instrument this, putting it into the " "block list.\n", ifunc_name.str().c_str(), r_name.str().c_str()); @@ -329,7 +329,7 @@ void scanForDangerousFunctions(llvm::Module *M) { if (!be_quiet) fprintf(stderr, - "Info: Found constructor function %s with prio " + "Note: Found constructor function %s with prio " "%u, we will not instrument this, putting it into a " "block list.\n", F->getName().str().c_str(), Priority); diff --git a/test/test-frida-mode.sh b/test/test-frida-mode.sh index 59b8e307..9e1f756d 100755 --- a/test/test-frida-mode.sh +++ b/test/test-frida-mode.sh @@ -62,7 +62,7 @@ test -e ../afl-frida-trace.so && { #else #fi export AFL_FRIDA_PERSISTENT_ADDR=0x`nm test-instr | grep -Ei "T _main|T main" | awk '{print $1}'` - $ECHO "Info: AFL_FRIDA_PERSISTENT_ADDR=$AFL_FRIDA_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')" + $ECHO "Note: AFL_FRIDA_PERSISTENT_ADDR=$AFL_FRIDA_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')" env|grep AFL_|sort file test-instr export AFL_DEBUG_CHILD=1 -- cgit 1.4.1 From cfb0257c99fa8c9ec4a4a33980092d1afd580638 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 27 Jun 2022 08:37:21 +0200 Subject: nits --- docs/fuzzing_in_depth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 8963c635..2c27dfe1 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -47,7 +47,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular: example, the following line will run a Docker container with all this preset: ```shell - # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk docker.io/aflplusplus/aflplusplus:stable + # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk aflplusplus/aflplusplus ``` ## 1. Instrumenting the target -- cgit 1.4.1 From 88077d4136fe36942d28ba956aa8536feb717638 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 27 Jun 2022 08:44:35 +0200 Subject: prepare release --- README.md | 4 ++-- docs/Changelog.md | 6 ++++-- include/config.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index e851359e..53b2b8d0 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.00c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.01c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.01a +GitHub version: 4.02a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 44939b16..737df7fa 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,8 +8,8 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++4.01a (dev) - - fix */build_...sh scripts to work outside of git +### Version ++4.01c (release) + - fixed */build_...sh scripts to work outside of git - new custom_mutator: libafl with token fuzzing :) - afl-fuzz: - when you just want to compile once and set CMPLOG, then just @@ -17,6 +17,8 @@ sending a mail to . CMPLOG. - new commandline options -g/G to set min/max length of generated fuzz inputs + - you can set the time for syncing to other fuzzer now with + AFL_SYNC_TIME - reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow persistent mode and manual forkserver support if these are not in the target binary (e.g. are in a shared library) diff --git a/include/config.h b/include/config.h index 9fc92b06..aefea9cd 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.01a" +#define VERSION "++4.01c" /****************************************************** * * -- cgit 1.4.1