From 1c9e7b8fa0e700ab9da82d8aeeb4a22b6999bcae Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 19 Apr 2023 06:10:07 +0200 Subject: [PATCH] new aflpp regression test (#1824) minimized the test case to 3 targets --- fuzzers/aflplusplus/builder.Dockerfile | 2 +- .../builder.Dockerfile | 2 +- .../description.md | 0 .../fuzzer.py | 0 .../runner.Dockerfile | 0 .../builder.Dockerfile | 12 +- .../description.md | 0 .../fuzzer.py | 2 +- .../runner.Dockerfile | 0 .../builder.Dockerfile | 13 +- .../description.md | 0 .../fuzzer.py | 4 +- .../runner.Dockerfile | 0 fuzzers/aflplusplus_314_3/builder.Dockerfile | 56 ++++ fuzzers/aflplusplus_314_3/description.md | 14 + fuzzers/aflplusplus_314_3/fuzzer.py | 282 ++++++++++++++++++ .../runner.Dockerfile | 5 - fuzzers/aflplusplus_314_4/builder.Dockerfile | 56 ++++ fuzzers/aflplusplus_314_4/description.md | 14 + fuzzers/aflplusplus_314_4/fuzzer.py | 282 ++++++++++++++++++ fuzzers/aflplusplus_314_4/runner.Dockerfile | 23 ++ fuzzers/aflplusplus_314_5/builder.Dockerfile | 56 ++++ fuzzers/aflplusplus_314_5/description.md | 14 + fuzzers/aflplusplus_314_5/fuzzer.py | 282 ++++++++++++++++++ fuzzers/aflplusplus_314_5/runner.Dockerfile | 23 ++ .../aflplusplus_aflphuzz/builder.Dockerfile | 56 ++++ fuzzers/aflplusplus_aflphuzz/description.md | 14 + fuzzers/aflplusplus_aflphuzz/fuzzer.py | 282 ++++++++++++++++++ .../aflplusplus_aflphuzz/runner.Dockerfile | 23 ++ .../aflplusplus_muttfuzz/builder.Dockerfile | 40 --- fuzzers/aflplusplus_muttfuzz/description.md | 9 - fuzzers/aflplusplus_muttfuzz/fuzzer.py | 84 ------ fuzzers/aflplusplus_muttfuzz/fuzzutil.py | 277 ----------------- fuzzers/aflplusplus_muttfuzz/mutate.py | 130 -------- service/experiment-requests.yaml | 22 ++ 35 files changed, 1522 insertions(+), 557 deletions(-) rename fuzzers/{aflplusplus_313_2 => aflplusplus_314_0}/builder.Dockerfile (96%) rename fuzzers/{aflplusplus_313_2 => aflplusplus_314_0}/description.md (100%) rename fuzzers/{aflplusplus_313_2 => aflplusplus_314_0}/fuzzer.py (100%) rename fuzzers/{aflplusplus_313_2 => aflplusplus_314_0}/runner.Dockerfile (100%) rename fuzzers/{aflplusplus_newqueuez => aflplusplus_314_1}/builder.Dockerfile (80%) rename fuzzers/{aflplusplus_mutsamehavoc => aflplusplus_314_1}/description.md (100%) rename fuzzers/{aflplusplus_mutsamehavoc => aflplusplus_314_1}/fuzzer.py (99%) rename fuzzers/{aflplusplus_mutsamehavoc => aflplusplus_314_1}/runner.Dockerfile (100%) rename fuzzers/{aflplusplus_mutsamehavoc => aflplusplus_314_2}/builder.Dockerfile (79%) rename fuzzers/{aflplusplus_newqueuez => aflplusplus_314_2}/description.md (100%) rename fuzzers/{aflplusplus_newqueuez => aflplusplus_314_2}/fuzzer.py (99%) rename fuzzers/{aflplusplus_newqueuez => aflplusplus_314_2}/runner.Dockerfile (100%) create mode 100644 fuzzers/aflplusplus_314_3/builder.Dockerfile create mode 100644 fuzzers/aflplusplus_314_3/description.md create mode 100755 fuzzers/aflplusplus_314_3/fuzzer.py rename fuzzers/{aflplusplus_muttfuzz => aflplusplus_314_3}/runner.Dockerfile (88%) create mode 100644 fuzzers/aflplusplus_314_4/builder.Dockerfile create mode 100644 fuzzers/aflplusplus_314_4/description.md create mode 100755 fuzzers/aflplusplus_314_4/fuzzer.py create mode 100644 fuzzers/aflplusplus_314_4/runner.Dockerfile create mode 100644 fuzzers/aflplusplus_314_5/builder.Dockerfile create mode 100644 fuzzers/aflplusplus_314_5/description.md create mode 100755 fuzzers/aflplusplus_314_5/fuzzer.py create mode 100644 fuzzers/aflplusplus_314_5/runner.Dockerfile create mode 100644 fuzzers/aflplusplus_aflphuzz/builder.Dockerfile create mode 100644 fuzzers/aflplusplus_aflphuzz/description.md create mode 100755 fuzzers/aflplusplus_aflphuzz/fuzzer.py create mode 100644 fuzzers/aflplusplus_aflphuzz/runner.Dockerfile delete mode 100644 fuzzers/aflplusplus_muttfuzz/builder.Dockerfile delete mode 100644 fuzzers/aflplusplus_muttfuzz/description.md delete mode 100755 fuzzers/aflplusplus_muttfuzz/fuzzer.py delete mode 100644 fuzzers/aflplusplus_muttfuzz/fuzzutil.py delete mode 100644 fuzzers/aflplusplus_muttfuzz/mutate.py diff --git a/fuzzers/aflplusplus/builder.Dockerfile b/fuzzers/aflplusplus/builder.Dockerfile index 60e552262..226c15e4f 100644 --- a/fuzzers/aflplusplus/builder.Dockerfile +++ b/fuzzers/aflplusplus/builder.Dockerfile @@ -37,7 +37,7 @@ RUN apt-get update && \ # Download afl++. RUN git clone -b dev https://github.com/AFLplusplus/AFLplusplus /afl && \ cd /afl && \ - git checkout 0782ed38414bed37168feafc971fd102b8294510 || \ + git checkout 97644836935020b9f42688bb6530f08f536644a9 || \ true # Build without Python support as we don't need it. diff --git a/fuzzers/aflplusplus_313_2/builder.Dockerfile b/fuzzers/aflplusplus_314_0/builder.Dockerfile similarity index 96% rename from fuzzers/aflplusplus_313_2/builder.Dockerfile rename to fuzzers/aflplusplus_314_0/builder.Dockerfile index 0ae0125be..23f1d08cd 100644 --- a/fuzzers/aflplusplus_313_2/builder.Dockerfile +++ b/fuzzers/aflplusplus_314_0/builder.Dockerfile @@ -37,7 +37,7 @@ RUN apt-get update && \ # Download afl++. RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ cd /afl && \ - git checkout a321d4102b6c3bec3471c4351692d1ad2a410e70 || \ + git checkout 6e704e8a10d0e0033b0f8f03ee2a5bdee06e2c65 || \ true RUN apt install -y lsb-release wget software-properties-common gnupg diff --git a/fuzzers/aflplusplus_313_2/description.md b/fuzzers/aflplusplus_314_0/description.md similarity index 100% rename from fuzzers/aflplusplus_313_2/description.md rename to fuzzers/aflplusplus_314_0/description.md diff --git a/fuzzers/aflplusplus_313_2/fuzzer.py b/fuzzers/aflplusplus_314_0/fuzzer.py similarity index 100% rename from fuzzers/aflplusplus_313_2/fuzzer.py rename to fuzzers/aflplusplus_314_0/fuzzer.py diff --git a/fuzzers/aflplusplus_313_2/runner.Dockerfile b/fuzzers/aflplusplus_314_0/runner.Dockerfile similarity index 100% rename from fuzzers/aflplusplus_313_2/runner.Dockerfile rename to fuzzers/aflplusplus_314_0/runner.Dockerfile diff --git a/fuzzers/aflplusplus_newqueuez/builder.Dockerfile b/fuzzers/aflplusplus_314_1/builder.Dockerfile similarity index 80% rename from fuzzers/aflplusplus_newqueuez/builder.Dockerfile rename to fuzzers/aflplusplus_314_1/builder.Dockerfile index 60e552262..2378fbb87 100644 --- a/fuzzers/aflplusplus_newqueuez/builder.Dockerfile +++ b/fuzzers/aflplusplus_314_1/builder.Dockerfile @@ -35,16 +35,22 @@ RUN apt-get update && \ libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev # Download afl++. -RUN git clone -b dev https://github.com/AFLplusplus/AFLplusplus /afl && \ +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ cd /afl && \ - git checkout 0782ed38414bed37168feafc971fd102b8294510 || \ + git checkout 21215ac21cfca26f18c5b59ceb71a3b5a2920244 || \ true +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 + # Build without Python support as we don't need it. # Set AFL_NO_X86 to skip flaky tests. RUN cd /afl && \ unset CFLAGS CXXFLAGS && \ export CC=clang AFL_NO_X86=1 && \ PYTHON_INCLUDE=/ make && \ - make install && \ + make -C utils/aflpp_driver && \ cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_mutsamehavoc/description.md b/fuzzers/aflplusplus_314_1/description.md similarity index 100% rename from fuzzers/aflplusplus_mutsamehavoc/description.md rename to fuzzers/aflplusplus_314_1/description.md diff --git a/fuzzers/aflplusplus_mutsamehavoc/fuzzer.py b/fuzzers/aflplusplus_314_1/fuzzer.py similarity index 99% rename from fuzzers/aflplusplus_mutsamehavoc/fuzzer.py rename to fuzzers/aflplusplus_314_1/fuzzer.py index 7016da75e..8738dc9ee 100755 --- a/fuzzers/aflplusplus_mutsamehavoc/fuzzer.py +++ b/fuzzers/aflplusplus_314_1/fuzzer.py @@ -116,7 +116,7 @@ def build(*args): # pylint: disable=too-many-branches,too-many-statements # Generate an extra dictionary. if 'dict2file' in build_modes or 'native' in build_modes: os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' - os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' # Enable context sentitivity for LLVM mode (non LTO only) if 'ctx' in build_modes: os.environ['AFL_LLVM_CTX'] = '1' diff --git a/fuzzers/aflplusplus_mutsamehavoc/runner.Dockerfile b/fuzzers/aflplusplus_314_1/runner.Dockerfile similarity index 100% rename from fuzzers/aflplusplus_mutsamehavoc/runner.Dockerfile rename to fuzzers/aflplusplus_314_1/runner.Dockerfile diff --git a/fuzzers/aflplusplus_mutsamehavoc/builder.Dockerfile b/fuzzers/aflplusplus_314_2/builder.Dockerfile similarity index 79% rename from fuzzers/aflplusplus_mutsamehavoc/builder.Dockerfile rename to fuzzers/aflplusplus_314_2/builder.Dockerfile index d9de12e8e..7ec04fff9 100644 --- a/fuzzers/aflplusplus_mutsamehavoc/builder.Dockerfile +++ b/fuzzers/aflplusplus_314_2/builder.Dockerfile @@ -35,9 +35,16 @@ RUN apt-get update && \ libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev # Download afl++. -RUN git clone -b muttest https://github.com/AFLplusplus/AFLplusplus /afl && \ +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ cd /afl && \ - git checkout 3c3fe89bc5e1e949b7381d476fea5f92e7845035 + git checkout 1b2637545b6b9f171ea46ed6cf5164e8d05d1776 || \ + true + +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 # Build without Python support as we don't need it. # Set AFL_NO_X86 to skip flaky tests. @@ -45,5 +52,5 @@ RUN cd /afl && \ unset CFLAGS CXXFLAGS && \ export CC=clang AFL_NO_X86=1 && \ PYTHON_INCLUDE=/ make && \ - make install && \ + make -C utils/aflpp_driver && \ cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_newqueuez/description.md b/fuzzers/aflplusplus_314_2/description.md similarity index 100% rename from fuzzers/aflplusplus_newqueuez/description.md rename to fuzzers/aflplusplus_314_2/description.md diff --git a/fuzzers/aflplusplus_newqueuez/fuzzer.py b/fuzzers/aflplusplus_314_2/fuzzer.py similarity index 99% rename from fuzzers/aflplusplus_newqueuez/fuzzer.py rename to fuzzers/aflplusplus_314_2/fuzzer.py index c5ae76f8d..8738dc9ee 100755 --- a/fuzzers/aflplusplus_newqueuez/fuzzer.py +++ b/fuzzers/aflplusplus_314_2/fuzzer.py @@ -116,7 +116,7 @@ def build(*args): # pylint: disable=too-many-branches,too-many-statements # Generate an extra dictionary. if 'dict2file' in build_modes or 'native' in build_modes: os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' - os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' # Enable context sentitivity for LLVM mode (non LTO only) if 'ctx' in build_modes: os.environ['AFL_LLVM_CTX'] = '1' @@ -261,8 +261,6 @@ def fuzz(input_corpus, if os.path.exists('./afl++.dict'): flags += ['-x', './afl++.dict'] - flags += ['-z'] - # Move the following to skip for upcoming _double tests: if os.path.exists(cmplog_target_binary) and no_cmplog is False: flags += ['-c', cmplog_target_binary] diff --git a/fuzzers/aflplusplus_newqueuez/runner.Dockerfile b/fuzzers/aflplusplus_314_2/runner.Dockerfile similarity index 100% rename from fuzzers/aflplusplus_newqueuez/runner.Dockerfile rename to fuzzers/aflplusplus_314_2/runner.Dockerfile diff --git a/fuzzers/aflplusplus_314_3/builder.Dockerfile b/fuzzers/aflplusplus_314_3/builder.Dockerfile new file mode 100644 index 000000000..0f731c564 --- /dev/null +++ b/fuzzers/aflplusplus_314_3/builder.Dockerfile @@ -0,0 +1,56 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +# Download afl++. +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ + cd /afl && \ + git checkout f1bcd378a2e55ee1559dde0d46e2bc32882c5b39 || \ + true + +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + make -C utils/aflpp_driver && \ + cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_314_3/description.md b/fuzzers/aflplusplus_314_3/description.md new file mode 100644 index 000000000..f7eb407ad --- /dev/null +++ b/fuzzers/aflplusplus_314_3/description.md @@ -0,0 +1,14 @@ +# aflplusplus + +AFL++ fuzzer instance that has the following config active for all benchmarks: + - PCGUARD instrumentation + - cmplog feature + - dict2file feature + - "fast" power schedule + - persistent mode + shared memory test cases + +Repository: [https://github.com/AFLplusplus/AFLplusplus/](https://github.com/AFLplusplus/AFLplusplus/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/aflplusplus_314_3/fuzzer.py b/fuzzers/aflplusplus_314_3/fuzzer.py new file mode 100755 index 000000000..8738dc9ee --- /dev/null +++ b/fuzzers/aflplusplus_314_3/fuzzer.py @@ -0,0 +1,282 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for AFLplusplus fuzzer.""" + +import os +import shutil + +from fuzzers.afl import fuzzer as afl_fuzzer +from fuzzers import utils + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'cmplog') + + +def get_uninstrumented_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'uninstrumented') + + +def build(*args): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + # BUILD_MODES is not already supported by fuzzbench, meanwhile we provide + # a default configuration. + + build_modes = list(args) + if 'BUILD_MODES' in os.environ: + build_modes = os.environ['BUILD_MODES'].split(',') + + # Placeholder comment. + build_directory = os.environ['OUT'] + + # If nothing was set this is the default: + if not build_modes: + build_modes = ['tracepc', 'cmplog', 'dict2file'] + + # For bug type benchmarks we have to instrument via native clang pcguard :( + build_flags = os.environ['CFLAGS'] + + if build_flags.find( + 'array-bounds' + ) != -1 and 'qemu' not in build_modes and 'classic' not in build_modes: + if 'gcc' not in build_modes: + build_modes[0] = 'native' + + # Instrumentation coverage modes: + if 'lto' in build_modes: + os.environ['CC'] = '/afl/afl-clang-lto' + os.environ['CXX'] = '/afl/afl-clang-lto++' + edge_file = build_directory + '/aflpp_edges.txt' + os.environ['AFL_LLVM_DOCUMENT_IDS'] = edge_file + if os.path.isfile('/usr/local/bin/llvm-ranlib-13'): + os.environ['RANLIB'] = 'llvm-ranlib-13' + os.environ['AR'] = 'llvm-ar-13' + os.environ['AS'] = 'llvm-as-13' + elif os.path.isfile('/usr/local/bin/llvm-ranlib-12'): + os.environ['RANLIB'] = 'llvm-ranlib-12' + os.environ['AR'] = 'llvm-ar-12' + os.environ['AS'] = 'llvm-as-12' + else: + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + elif 'qemu' in build_modes: + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + elif 'gcc' in build_modes: + os.environ['CC'] = 'afl-gcc-fast' + os.environ['CXX'] = 'afl-g++-fast' + if build_flags.find('array-bounds') != -1: + os.environ['CFLAGS'] = '-fsanitize=address -O1' + os.environ['CXXFLAGS'] = '-fsanitize=address -O1' + else: + os.environ['CFLAGS'] = '' + os.environ['CXXFLAGS'] = '' + os.environ['CPPFLAGS'] = '' + else: + os.environ['CC'] = '/afl/afl-clang-fast' + os.environ['CXX'] = '/afl/afl-clang-fast++' + + print('AFL++ build: ') + print(build_modes) + + if 'qemu' in build_modes or 'symcc' in build_modes: + os.environ['CFLAGS'] = ' '.join(utils.NO_SANITIZER_COMPAT_CFLAGS) + cxxflags = [utils.LIBCPLUSPLUS_FLAG] + utils.NO_SANITIZER_COMPAT_CFLAGS + os.environ['CXXFLAGS'] = ' '.join(cxxflags) + + if 'tracepc' in build_modes or 'pcguard' in build_modes: + os.environ['AFL_LLVM_USE_TRACE_PC'] = '1' + elif 'classic' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'CLASSIC' + elif 'native' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'LLVMNATIVE' + + # Instrumentation coverage options: + # Do not use a fixed map location (LTO only) + if 'dynamic' in build_modes: + os.environ['AFL_LLVM_MAP_DYNAMIC'] = '1' + # Use a fixed map location (LTO only) + if 'fixed' in build_modes: + os.environ['AFL_LLVM_MAP_ADDR'] = '0x10000' + # Generate an extra dictionary. + if 'dict2file' in build_modes or 'native' in build_modes: + os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + # Enable context sentitivity for LLVM mode (non LTO only) + if 'ctx' in build_modes: + os.environ['AFL_LLVM_CTX'] = '1' + # Enable N-gram coverage for LLVM mode (non LTO only) + if 'ngram2' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '2' + elif 'ngram3' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '3' + elif 'ngram4' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '4' + elif 'ngram5' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '5' + elif 'ngram6' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '6' + elif 'ngram7' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '7' + elif 'ngram8' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '8' + elif 'ngram16' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '16' + if 'ctx1' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '1' + elif 'ctx2' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '2' + elif 'ctx3' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '3' + elif 'ctx4' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '4' + + # Only one of the following OR cmplog + # enable laf-intel compare splitting + if 'laf' in build_modes: + os.environ['AFL_LLVM_LAF_SPLIT_SWITCHES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_COMPARES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_FLOATS'] = '1' + if 'autodict' not in build_modes: + os.environ['AFL_LLVM_LAF_TRANSFORM_COMPARES'] = '1' + + if 'eclipser' in build_modes: + os.environ['FUZZER_LIB'] = '/libStandaloneFuzzTarget.a' + else: + os.environ['FUZZER_LIB'] = '/libAFLDriver.a' + + # Some benchmarks like lcms. (see: + # https://github.com/mm2/Little-CMS/commit/ab1093539b4287c233aca6a3cf53b234faceb792#diff-f0e6d05e72548974e852e8e55dffc4ccR212) + # fail to compile if the compiler outputs things to stderr in unexpected + # cases. Prevent these failures by using AFL_QUIET to stop afl-clang-fast + # from writing AFL specific messages to stderr. + os.environ['AFL_QUIET'] = '1' + os.environ['AFL_MAP_SIZE'] = '2621440' + + src = os.getenv('SRC') + work = os.getenv('WORK') + + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + utils.build_benchmark() + + if 'cmplog' in build_modes and 'qemu' not in build_modes: + + # CmpLog requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['AFL_LLVM_CMPLOG'] = '1' + + # For CmpLog build, set the OUT and FUZZ_TARGET environment + # variable to point to the new CmpLog build directory. + cmplog_build_directory = get_cmplog_build_directory(build_directory) + os.mkdir(cmplog_build_directory) + new_env['OUT'] = cmplog_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for CmpLog fuzzing target') + utils.build_benchmark(env=new_env) + + if 'symcc' in build_modes: + + symcc_build_directory = get_uninstrumented_build_directory( + build_directory) + os.mkdir(symcc_build_directory) + + # symcc requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['CC'] = '/symcc/build/symcc' + new_env['CXX'] = '/symcc/build/sym++' + new_env['SYMCC_OUTPUT_DIR'] = '/tmp' + new_env['CXXFLAGS'] = new_env['CXXFLAGS'].replace('-stlib=libc++', '') + new_env['FUZZER_LIB'] = '/libfuzzer-harness.o' + new_env['OUT'] = symcc_build_directory + new_env['SYMCC_LIBCXX_PATH'] = '/libcxx_native_build' + new_env['SYMCC_NO_SYMBOLIC_INPUT'] = '1' + new_env['SYMCC_SILENT'] = '1' + + # For symcc build, set the OUT and FUZZ_TARGET environment + # variable to point to the new symcc build directory. + new_env['OUT'] = symcc_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(symcc_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for symcc fuzzing target') + utils.build_benchmark(env=new_env) + + shutil.copy('/afl/afl-fuzz', build_directory) + if os.path.exists('/afl/afl-qemu-trace'): + shutil.copy('/afl/afl-qemu-trace', build_directory) + if os.path.exists('/aflpp_qemu_driver_hook.so'): + shutil.copy('/aflpp_qemu_driver_hook.so', build_directory) + if os.path.exists('/get_frida_entry.sh'): + shutil.copy('/afl/afl-frida-trace.so', build_directory) + shutil.copy('/get_frida_entry.sh', build_directory) + + +# pylint: disable=too-many-arguments +def fuzz(input_corpus, + output_corpus, + target_binary, + flags=tuple(), + skip=False, + no_cmplog=False): # pylint: disable=too-many-arguments + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = ( + get_cmplog_build_directory(target_binary_directory)) + target_binary_name = os.path.basename(target_binary) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + target_binary_name) + + afl_fuzzer.prepare_fuzz_environment(input_corpus) + # decomment this to enable libdislocator. + # os.environ['AFL_ALIGNED_ALLOC'] = '1' # align malloc to max_align_t + # os.environ['AFL_PRELOAD'] = '/afl/libdislocator.so' + + flags = list(flags) + + if os.path.exists('./afl++.dict'): + flags += ['-x', './afl++.dict'] + + # Move the following to skip for upcoming _double tests: + if os.path.exists(cmplog_target_binary) and no_cmplog is False: + flags += ['-c', cmplog_target_binary] + + #os.environ['AFL_IGNORE_TIMEOUTS'] = '1' + os.environ['AFL_IGNORE_UNKNOWN_ENVS'] = '1' + os.environ['AFL_FAST_CAL'] = '1' + os.environ['AFL_NO_WARN_INSTABILITY'] = '1' + + if not skip: + os.environ['AFL_DISABLE_TRIM'] = '1' + os.environ['AFL_CMPLOG_ONLY_NEW'] = '1' + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + + afl_fuzzer.run_afl_fuzz(input_corpus, + output_corpus, + target_binary, + additional_flags=flags) diff --git a/fuzzers/aflplusplus_muttfuzz/runner.Dockerfile b/fuzzers/aflplusplus_314_3/runner.Dockerfile similarity index 88% rename from fuzzers/aflplusplus_muttfuzz/runner.Dockerfile rename to fuzzers/aflplusplus_314_3/runner.Dockerfile index 6237d656b..7aa1da8e4 100644 --- a/fuzzers/aflplusplus_muttfuzz/runner.Dockerfile +++ b/fuzzers/aflplusplus_314_3/runner.Dockerfile @@ -21,8 +21,3 @@ ENV PATH="$PATH:/out" ENV AFL_SKIP_CPUFREQ=1 ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 ENV AFL_TESTCACHE_SIZE=2 - -RUN apt-get update && apt-get install -y python3 - -RUN pip3 install --upgrade --force pip -RUN pip install muttfuzz \ No newline at end of file diff --git a/fuzzers/aflplusplus_314_4/builder.Dockerfile b/fuzzers/aflplusplus_314_4/builder.Dockerfile new file mode 100644 index 000000000..8079e68d4 --- /dev/null +++ b/fuzzers/aflplusplus_314_4/builder.Dockerfile @@ -0,0 +1,56 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +# Download afl++. +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ + cd /afl && \ + git checkout 6ec295db4e8188df410cf7dcccd1b3de5fbc2048 || \ + true + +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + make -C utils/aflpp_driver && \ + cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_314_4/description.md b/fuzzers/aflplusplus_314_4/description.md new file mode 100644 index 000000000..f7eb407ad --- /dev/null +++ b/fuzzers/aflplusplus_314_4/description.md @@ -0,0 +1,14 @@ +# aflplusplus + +AFL++ fuzzer instance that has the following config active for all benchmarks: + - PCGUARD instrumentation + - cmplog feature + - dict2file feature + - "fast" power schedule + - persistent mode + shared memory test cases + +Repository: [https://github.com/AFLplusplus/AFLplusplus/](https://github.com/AFLplusplus/AFLplusplus/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/aflplusplus_314_4/fuzzer.py b/fuzzers/aflplusplus_314_4/fuzzer.py new file mode 100755 index 000000000..8738dc9ee --- /dev/null +++ b/fuzzers/aflplusplus_314_4/fuzzer.py @@ -0,0 +1,282 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for AFLplusplus fuzzer.""" + +import os +import shutil + +from fuzzers.afl import fuzzer as afl_fuzzer +from fuzzers import utils + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'cmplog') + + +def get_uninstrumented_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'uninstrumented') + + +def build(*args): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + # BUILD_MODES is not already supported by fuzzbench, meanwhile we provide + # a default configuration. + + build_modes = list(args) + if 'BUILD_MODES' in os.environ: + build_modes = os.environ['BUILD_MODES'].split(',') + + # Placeholder comment. + build_directory = os.environ['OUT'] + + # If nothing was set this is the default: + if not build_modes: + build_modes = ['tracepc', 'cmplog', 'dict2file'] + + # For bug type benchmarks we have to instrument via native clang pcguard :( + build_flags = os.environ['CFLAGS'] + + if build_flags.find( + 'array-bounds' + ) != -1 and 'qemu' not in build_modes and 'classic' not in build_modes: + if 'gcc' not in build_modes: + build_modes[0] = 'native' + + # Instrumentation coverage modes: + if 'lto' in build_modes: + os.environ['CC'] = '/afl/afl-clang-lto' + os.environ['CXX'] = '/afl/afl-clang-lto++' + edge_file = build_directory + '/aflpp_edges.txt' + os.environ['AFL_LLVM_DOCUMENT_IDS'] = edge_file + if os.path.isfile('/usr/local/bin/llvm-ranlib-13'): + os.environ['RANLIB'] = 'llvm-ranlib-13' + os.environ['AR'] = 'llvm-ar-13' + os.environ['AS'] = 'llvm-as-13' + elif os.path.isfile('/usr/local/bin/llvm-ranlib-12'): + os.environ['RANLIB'] = 'llvm-ranlib-12' + os.environ['AR'] = 'llvm-ar-12' + os.environ['AS'] = 'llvm-as-12' + else: + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + elif 'qemu' in build_modes: + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + elif 'gcc' in build_modes: + os.environ['CC'] = 'afl-gcc-fast' + os.environ['CXX'] = 'afl-g++-fast' + if build_flags.find('array-bounds') != -1: + os.environ['CFLAGS'] = '-fsanitize=address -O1' + os.environ['CXXFLAGS'] = '-fsanitize=address -O1' + else: + os.environ['CFLAGS'] = '' + os.environ['CXXFLAGS'] = '' + os.environ['CPPFLAGS'] = '' + else: + os.environ['CC'] = '/afl/afl-clang-fast' + os.environ['CXX'] = '/afl/afl-clang-fast++' + + print('AFL++ build: ') + print(build_modes) + + if 'qemu' in build_modes or 'symcc' in build_modes: + os.environ['CFLAGS'] = ' '.join(utils.NO_SANITIZER_COMPAT_CFLAGS) + cxxflags = [utils.LIBCPLUSPLUS_FLAG] + utils.NO_SANITIZER_COMPAT_CFLAGS + os.environ['CXXFLAGS'] = ' '.join(cxxflags) + + if 'tracepc' in build_modes or 'pcguard' in build_modes: + os.environ['AFL_LLVM_USE_TRACE_PC'] = '1' + elif 'classic' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'CLASSIC' + elif 'native' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'LLVMNATIVE' + + # Instrumentation coverage options: + # Do not use a fixed map location (LTO only) + if 'dynamic' in build_modes: + os.environ['AFL_LLVM_MAP_DYNAMIC'] = '1' + # Use a fixed map location (LTO only) + if 'fixed' in build_modes: + os.environ['AFL_LLVM_MAP_ADDR'] = '0x10000' + # Generate an extra dictionary. + if 'dict2file' in build_modes or 'native' in build_modes: + os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + # Enable context sentitivity for LLVM mode (non LTO only) + if 'ctx' in build_modes: + os.environ['AFL_LLVM_CTX'] = '1' + # Enable N-gram coverage for LLVM mode (non LTO only) + if 'ngram2' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '2' + elif 'ngram3' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '3' + elif 'ngram4' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '4' + elif 'ngram5' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '5' + elif 'ngram6' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '6' + elif 'ngram7' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '7' + elif 'ngram8' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '8' + elif 'ngram16' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '16' + if 'ctx1' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '1' + elif 'ctx2' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '2' + elif 'ctx3' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '3' + elif 'ctx4' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '4' + + # Only one of the following OR cmplog + # enable laf-intel compare splitting + if 'laf' in build_modes: + os.environ['AFL_LLVM_LAF_SPLIT_SWITCHES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_COMPARES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_FLOATS'] = '1' + if 'autodict' not in build_modes: + os.environ['AFL_LLVM_LAF_TRANSFORM_COMPARES'] = '1' + + if 'eclipser' in build_modes: + os.environ['FUZZER_LIB'] = '/libStandaloneFuzzTarget.a' + else: + os.environ['FUZZER_LIB'] = '/libAFLDriver.a' + + # Some benchmarks like lcms. (see: + # https://github.com/mm2/Little-CMS/commit/ab1093539b4287c233aca6a3cf53b234faceb792#diff-f0e6d05e72548974e852e8e55dffc4ccR212) + # fail to compile if the compiler outputs things to stderr in unexpected + # cases. Prevent these failures by using AFL_QUIET to stop afl-clang-fast + # from writing AFL specific messages to stderr. + os.environ['AFL_QUIET'] = '1' + os.environ['AFL_MAP_SIZE'] = '2621440' + + src = os.getenv('SRC') + work = os.getenv('WORK') + + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + utils.build_benchmark() + + if 'cmplog' in build_modes and 'qemu' not in build_modes: + + # CmpLog requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['AFL_LLVM_CMPLOG'] = '1' + + # For CmpLog build, set the OUT and FUZZ_TARGET environment + # variable to point to the new CmpLog build directory. + cmplog_build_directory = get_cmplog_build_directory(build_directory) + os.mkdir(cmplog_build_directory) + new_env['OUT'] = cmplog_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for CmpLog fuzzing target') + utils.build_benchmark(env=new_env) + + if 'symcc' in build_modes: + + symcc_build_directory = get_uninstrumented_build_directory( + build_directory) + os.mkdir(symcc_build_directory) + + # symcc requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['CC'] = '/symcc/build/symcc' + new_env['CXX'] = '/symcc/build/sym++' + new_env['SYMCC_OUTPUT_DIR'] = '/tmp' + new_env['CXXFLAGS'] = new_env['CXXFLAGS'].replace('-stlib=libc++', '') + new_env['FUZZER_LIB'] = '/libfuzzer-harness.o' + new_env['OUT'] = symcc_build_directory + new_env['SYMCC_LIBCXX_PATH'] = '/libcxx_native_build' + new_env['SYMCC_NO_SYMBOLIC_INPUT'] = '1' + new_env['SYMCC_SILENT'] = '1' + + # For symcc build, set the OUT and FUZZ_TARGET environment + # variable to point to the new symcc build directory. + new_env['OUT'] = symcc_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(symcc_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for symcc fuzzing target') + utils.build_benchmark(env=new_env) + + shutil.copy('/afl/afl-fuzz', build_directory) + if os.path.exists('/afl/afl-qemu-trace'): + shutil.copy('/afl/afl-qemu-trace', build_directory) + if os.path.exists('/aflpp_qemu_driver_hook.so'): + shutil.copy('/aflpp_qemu_driver_hook.so', build_directory) + if os.path.exists('/get_frida_entry.sh'): + shutil.copy('/afl/afl-frida-trace.so', build_directory) + shutil.copy('/get_frida_entry.sh', build_directory) + + +# pylint: disable=too-many-arguments +def fuzz(input_corpus, + output_corpus, + target_binary, + flags=tuple(), + skip=False, + no_cmplog=False): # pylint: disable=too-many-arguments + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = ( + get_cmplog_build_directory(target_binary_directory)) + target_binary_name = os.path.basename(target_binary) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + target_binary_name) + + afl_fuzzer.prepare_fuzz_environment(input_corpus) + # decomment this to enable libdislocator. + # os.environ['AFL_ALIGNED_ALLOC'] = '1' # align malloc to max_align_t + # os.environ['AFL_PRELOAD'] = '/afl/libdislocator.so' + + flags = list(flags) + + if os.path.exists('./afl++.dict'): + flags += ['-x', './afl++.dict'] + + # Move the following to skip for upcoming _double tests: + if os.path.exists(cmplog_target_binary) and no_cmplog is False: + flags += ['-c', cmplog_target_binary] + + #os.environ['AFL_IGNORE_TIMEOUTS'] = '1' + os.environ['AFL_IGNORE_UNKNOWN_ENVS'] = '1' + os.environ['AFL_FAST_CAL'] = '1' + os.environ['AFL_NO_WARN_INSTABILITY'] = '1' + + if not skip: + os.environ['AFL_DISABLE_TRIM'] = '1' + os.environ['AFL_CMPLOG_ONLY_NEW'] = '1' + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + + afl_fuzzer.run_afl_fuzz(input_corpus, + output_corpus, + target_binary, + additional_flags=flags) diff --git a/fuzzers/aflplusplus_314_4/runner.Dockerfile b/fuzzers/aflplusplus_314_4/runner.Dockerfile new file mode 100644 index 000000000..7aa1da8e4 --- /dev/null +++ b/fuzzers/aflplusplus_314_4/runner.Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2020 Google LLC +# +# 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. + +FROM gcr.io/fuzzbench/base-image + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +#ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/aflplusplus_314_5/builder.Dockerfile b/fuzzers/aflplusplus_314_5/builder.Dockerfile new file mode 100644 index 000000000..0484bbe6c --- /dev/null +++ b/fuzzers/aflplusplus_314_5/builder.Dockerfile @@ -0,0 +1,56 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +# Download afl++. +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl && \ + cd /afl && \ + git checkout 046a9520f3799f01d5df557f0a577171638e0c64 || \ + true + +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + make -C utils/aflpp_driver && \ + cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_314_5/description.md b/fuzzers/aflplusplus_314_5/description.md new file mode 100644 index 000000000..f7eb407ad --- /dev/null +++ b/fuzzers/aflplusplus_314_5/description.md @@ -0,0 +1,14 @@ +# aflplusplus + +AFL++ fuzzer instance that has the following config active for all benchmarks: + - PCGUARD instrumentation + - cmplog feature + - dict2file feature + - "fast" power schedule + - persistent mode + shared memory test cases + +Repository: [https://github.com/AFLplusplus/AFLplusplus/](https://github.com/AFLplusplus/AFLplusplus/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/aflplusplus_314_5/fuzzer.py b/fuzzers/aflplusplus_314_5/fuzzer.py new file mode 100755 index 000000000..8738dc9ee --- /dev/null +++ b/fuzzers/aflplusplus_314_5/fuzzer.py @@ -0,0 +1,282 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for AFLplusplus fuzzer.""" + +import os +import shutil + +from fuzzers.afl import fuzzer as afl_fuzzer +from fuzzers import utils + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'cmplog') + + +def get_uninstrumented_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'uninstrumented') + + +def build(*args): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + # BUILD_MODES is not already supported by fuzzbench, meanwhile we provide + # a default configuration. + + build_modes = list(args) + if 'BUILD_MODES' in os.environ: + build_modes = os.environ['BUILD_MODES'].split(',') + + # Placeholder comment. + build_directory = os.environ['OUT'] + + # If nothing was set this is the default: + if not build_modes: + build_modes = ['tracepc', 'cmplog', 'dict2file'] + + # For bug type benchmarks we have to instrument via native clang pcguard :( + build_flags = os.environ['CFLAGS'] + + if build_flags.find( + 'array-bounds' + ) != -1 and 'qemu' not in build_modes and 'classic' not in build_modes: + if 'gcc' not in build_modes: + build_modes[0] = 'native' + + # Instrumentation coverage modes: + if 'lto' in build_modes: + os.environ['CC'] = '/afl/afl-clang-lto' + os.environ['CXX'] = '/afl/afl-clang-lto++' + edge_file = build_directory + '/aflpp_edges.txt' + os.environ['AFL_LLVM_DOCUMENT_IDS'] = edge_file + if os.path.isfile('/usr/local/bin/llvm-ranlib-13'): + os.environ['RANLIB'] = 'llvm-ranlib-13' + os.environ['AR'] = 'llvm-ar-13' + os.environ['AS'] = 'llvm-as-13' + elif os.path.isfile('/usr/local/bin/llvm-ranlib-12'): + os.environ['RANLIB'] = 'llvm-ranlib-12' + os.environ['AR'] = 'llvm-ar-12' + os.environ['AS'] = 'llvm-as-12' + else: + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + elif 'qemu' in build_modes: + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + elif 'gcc' in build_modes: + os.environ['CC'] = 'afl-gcc-fast' + os.environ['CXX'] = 'afl-g++-fast' + if build_flags.find('array-bounds') != -1: + os.environ['CFLAGS'] = '-fsanitize=address -O1' + os.environ['CXXFLAGS'] = '-fsanitize=address -O1' + else: + os.environ['CFLAGS'] = '' + os.environ['CXXFLAGS'] = '' + os.environ['CPPFLAGS'] = '' + else: + os.environ['CC'] = '/afl/afl-clang-fast' + os.environ['CXX'] = '/afl/afl-clang-fast++' + + print('AFL++ build: ') + print(build_modes) + + if 'qemu' in build_modes or 'symcc' in build_modes: + os.environ['CFLAGS'] = ' '.join(utils.NO_SANITIZER_COMPAT_CFLAGS) + cxxflags = [utils.LIBCPLUSPLUS_FLAG] + utils.NO_SANITIZER_COMPAT_CFLAGS + os.environ['CXXFLAGS'] = ' '.join(cxxflags) + + if 'tracepc' in build_modes or 'pcguard' in build_modes: + os.environ['AFL_LLVM_USE_TRACE_PC'] = '1' + elif 'classic' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'CLASSIC' + elif 'native' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'LLVMNATIVE' + + # Instrumentation coverage options: + # Do not use a fixed map location (LTO only) + if 'dynamic' in build_modes: + os.environ['AFL_LLVM_MAP_DYNAMIC'] = '1' + # Use a fixed map location (LTO only) + if 'fixed' in build_modes: + os.environ['AFL_LLVM_MAP_ADDR'] = '0x10000' + # Generate an extra dictionary. + if 'dict2file' in build_modes or 'native' in build_modes: + os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + # Enable context sentitivity for LLVM mode (non LTO only) + if 'ctx' in build_modes: + os.environ['AFL_LLVM_CTX'] = '1' + # Enable N-gram coverage for LLVM mode (non LTO only) + if 'ngram2' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '2' + elif 'ngram3' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '3' + elif 'ngram4' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '4' + elif 'ngram5' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '5' + elif 'ngram6' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '6' + elif 'ngram7' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '7' + elif 'ngram8' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '8' + elif 'ngram16' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '16' + if 'ctx1' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '1' + elif 'ctx2' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '2' + elif 'ctx3' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '3' + elif 'ctx4' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '4' + + # Only one of the following OR cmplog + # enable laf-intel compare splitting + if 'laf' in build_modes: + os.environ['AFL_LLVM_LAF_SPLIT_SWITCHES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_COMPARES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_FLOATS'] = '1' + if 'autodict' not in build_modes: + os.environ['AFL_LLVM_LAF_TRANSFORM_COMPARES'] = '1' + + if 'eclipser' in build_modes: + os.environ['FUZZER_LIB'] = '/libStandaloneFuzzTarget.a' + else: + os.environ['FUZZER_LIB'] = '/libAFLDriver.a' + + # Some benchmarks like lcms. (see: + # https://github.com/mm2/Little-CMS/commit/ab1093539b4287c233aca6a3cf53b234faceb792#diff-f0e6d05e72548974e852e8e55dffc4ccR212) + # fail to compile if the compiler outputs things to stderr in unexpected + # cases. Prevent these failures by using AFL_QUIET to stop afl-clang-fast + # from writing AFL specific messages to stderr. + os.environ['AFL_QUIET'] = '1' + os.environ['AFL_MAP_SIZE'] = '2621440' + + src = os.getenv('SRC') + work = os.getenv('WORK') + + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + utils.build_benchmark() + + if 'cmplog' in build_modes and 'qemu' not in build_modes: + + # CmpLog requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['AFL_LLVM_CMPLOG'] = '1' + + # For CmpLog build, set the OUT and FUZZ_TARGET environment + # variable to point to the new CmpLog build directory. + cmplog_build_directory = get_cmplog_build_directory(build_directory) + os.mkdir(cmplog_build_directory) + new_env['OUT'] = cmplog_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for CmpLog fuzzing target') + utils.build_benchmark(env=new_env) + + if 'symcc' in build_modes: + + symcc_build_directory = get_uninstrumented_build_directory( + build_directory) + os.mkdir(symcc_build_directory) + + # symcc requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['CC'] = '/symcc/build/symcc' + new_env['CXX'] = '/symcc/build/sym++' + new_env['SYMCC_OUTPUT_DIR'] = '/tmp' + new_env['CXXFLAGS'] = new_env['CXXFLAGS'].replace('-stlib=libc++', '') + new_env['FUZZER_LIB'] = '/libfuzzer-harness.o' + new_env['OUT'] = symcc_build_directory + new_env['SYMCC_LIBCXX_PATH'] = '/libcxx_native_build' + new_env['SYMCC_NO_SYMBOLIC_INPUT'] = '1' + new_env['SYMCC_SILENT'] = '1' + + # For symcc build, set the OUT and FUZZ_TARGET environment + # variable to point to the new symcc build directory. + new_env['OUT'] = symcc_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(symcc_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for symcc fuzzing target') + utils.build_benchmark(env=new_env) + + shutil.copy('/afl/afl-fuzz', build_directory) + if os.path.exists('/afl/afl-qemu-trace'): + shutil.copy('/afl/afl-qemu-trace', build_directory) + if os.path.exists('/aflpp_qemu_driver_hook.so'): + shutil.copy('/aflpp_qemu_driver_hook.so', build_directory) + if os.path.exists('/get_frida_entry.sh'): + shutil.copy('/afl/afl-frida-trace.so', build_directory) + shutil.copy('/get_frida_entry.sh', build_directory) + + +# pylint: disable=too-many-arguments +def fuzz(input_corpus, + output_corpus, + target_binary, + flags=tuple(), + skip=False, + no_cmplog=False): # pylint: disable=too-many-arguments + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = ( + get_cmplog_build_directory(target_binary_directory)) + target_binary_name = os.path.basename(target_binary) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + target_binary_name) + + afl_fuzzer.prepare_fuzz_environment(input_corpus) + # decomment this to enable libdislocator. + # os.environ['AFL_ALIGNED_ALLOC'] = '1' # align malloc to max_align_t + # os.environ['AFL_PRELOAD'] = '/afl/libdislocator.so' + + flags = list(flags) + + if os.path.exists('./afl++.dict'): + flags += ['-x', './afl++.dict'] + + # Move the following to skip for upcoming _double tests: + if os.path.exists(cmplog_target_binary) and no_cmplog is False: + flags += ['-c', cmplog_target_binary] + + #os.environ['AFL_IGNORE_TIMEOUTS'] = '1' + os.environ['AFL_IGNORE_UNKNOWN_ENVS'] = '1' + os.environ['AFL_FAST_CAL'] = '1' + os.environ['AFL_NO_WARN_INSTABILITY'] = '1' + + if not skip: + os.environ['AFL_DISABLE_TRIM'] = '1' + os.environ['AFL_CMPLOG_ONLY_NEW'] = '1' + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + + afl_fuzzer.run_afl_fuzz(input_corpus, + output_corpus, + target_binary, + additional_flags=flags) diff --git a/fuzzers/aflplusplus_314_5/runner.Dockerfile b/fuzzers/aflplusplus_314_5/runner.Dockerfile new file mode 100644 index 000000000..7aa1da8e4 --- /dev/null +++ b/fuzzers/aflplusplus_314_5/runner.Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2020 Google LLC +# +# 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. + +FROM gcr.io/fuzzbench/base-image + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +#ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/aflplusplus_aflphuzz/builder.Dockerfile b/fuzzers/aflplusplus_aflphuzz/builder.Dockerfile new file mode 100644 index 000000000..b12414ecf --- /dev/null +++ b/fuzzers/aflplusplus_aflphuzz/builder.Dockerfile @@ -0,0 +1,56 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +# Download afl++. +RUN git clone https://github.com/vanhauser-thc/Alphuzzplusplus /afl && \ + cd /afl && \ + git checkout 3ccb3724834321e550bc99ffd5cba7312f98f0c2 || \ + true + +RUN apt install -y lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 13 + +ENV LLVM_CONFIG llvm-config-13 + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + make -C utils/aflpp_driver && \ + cp utils/aflpp_driver/libAFLDriver.a / diff --git a/fuzzers/aflplusplus_aflphuzz/description.md b/fuzzers/aflplusplus_aflphuzz/description.md new file mode 100644 index 000000000..f7eb407ad --- /dev/null +++ b/fuzzers/aflplusplus_aflphuzz/description.md @@ -0,0 +1,14 @@ +# aflplusplus + +AFL++ fuzzer instance that has the following config active for all benchmarks: + - PCGUARD instrumentation + - cmplog feature + - dict2file feature + - "fast" power schedule + - persistent mode + shared memory test cases + +Repository: [https://github.com/AFLplusplus/AFLplusplus/](https://github.com/AFLplusplus/AFLplusplus/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/aflplusplus_aflphuzz/fuzzer.py b/fuzzers/aflplusplus_aflphuzz/fuzzer.py new file mode 100755 index 000000000..8738dc9ee --- /dev/null +++ b/fuzzers/aflplusplus_aflphuzz/fuzzer.py @@ -0,0 +1,282 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for AFLplusplus fuzzer.""" + +import os +import shutil + +from fuzzers.afl import fuzzer as afl_fuzzer +from fuzzers import utils + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'cmplog') + + +def get_uninstrumented_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'uninstrumented') + + +def build(*args): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + # BUILD_MODES is not already supported by fuzzbench, meanwhile we provide + # a default configuration. + + build_modes = list(args) + if 'BUILD_MODES' in os.environ: + build_modes = os.environ['BUILD_MODES'].split(',') + + # Placeholder comment. + build_directory = os.environ['OUT'] + + # If nothing was set this is the default: + if not build_modes: + build_modes = ['tracepc', 'cmplog', 'dict2file'] + + # For bug type benchmarks we have to instrument via native clang pcguard :( + build_flags = os.environ['CFLAGS'] + + if build_flags.find( + 'array-bounds' + ) != -1 and 'qemu' not in build_modes and 'classic' not in build_modes: + if 'gcc' not in build_modes: + build_modes[0] = 'native' + + # Instrumentation coverage modes: + if 'lto' in build_modes: + os.environ['CC'] = '/afl/afl-clang-lto' + os.environ['CXX'] = '/afl/afl-clang-lto++' + edge_file = build_directory + '/aflpp_edges.txt' + os.environ['AFL_LLVM_DOCUMENT_IDS'] = edge_file + if os.path.isfile('/usr/local/bin/llvm-ranlib-13'): + os.environ['RANLIB'] = 'llvm-ranlib-13' + os.environ['AR'] = 'llvm-ar-13' + os.environ['AS'] = 'llvm-as-13' + elif os.path.isfile('/usr/local/bin/llvm-ranlib-12'): + os.environ['RANLIB'] = 'llvm-ranlib-12' + os.environ['AR'] = 'llvm-ar-12' + os.environ['AS'] = 'llvm-as-12' + else: + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + elif 'qemu' in build_modes: + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + elif 'gcc' in build_modes: + os.environ['CC'] = 'afl-gcc-fast' + os.environ['CXX'] = 'afl-g++-fast' + if build_flags.find('array-bounds') != -1: + os.environ['CFLAGS'] = '-fsanitize=address -O1' + os.environ['CXXFLAGS'] = '-fsanitize=address -O1' + else: + os.environ['CFLAGS'] = '' + os.environ['CXXFLAGS'] = '' + os.environ['CPPFLAGS'] = '' + else: + os.environ['CC'] = '/afl/afl-clang-fast' + os.environ['CXX'] = '/afl/afl-clang-fast++' + + print('AFL++ build: ') + print(build_modes) + + if 'qemu' in build_modes or 'symcc' in build_modes: + os.environ['CFLAGS'] = ' '.join(utils.NO_SANITIZER_COMPAT_CFLAGS) + cxxflags = [utils.LIBCPLUSPLUS_FLAG] + utils.NO_SANITIZER_COMPAT_CFLAGS + os.environ['CXXFLAGS'] = ' '.join(cxxflags) + + if 'tracepc' in build_modes or 'pcguard' in build_modes: + os.environ['AFL_LLVM_USE_TRACE_PC'] = '1' + elif 'classic' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'CLASSIC' + elif 'native' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'LLVMNATIVE' + + # Instrumentation coverage options: + # Do not use a fixed map location (LTO only) + if 'dynamic' in build_modes: + os.environ['AFL_LLVM_MAP_DYNAMIC'] = '1' + # Use a fixed map location (LTO only) + if 'fixed' in build_modes: + os.environ['AFL_LLVM_MAP_ADDR'] = '0x10000' + # Generate an extra dictionary. + if 'dict2file' in build_modes or 'native' in build_modes: + os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' + #os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + # Enable context sentitivity for LLVM mode (non LTO only) + if 'ctx' in build_modes: + os.environ['AFL_LLVM_CTX'] = '1' + # Enable N-gram coverage for LLVM mode (non LTO only) + if 'ngram2' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '2' + elif 'ngram3' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '3' + elif 'ngram4' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '4' + elif 'ngram5' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '5' + elif 'ngram6' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '6' + elif 'ngram7' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '7' + elif 'ngram8' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '8' + elif 'ngram16' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '16' + if 'ctx1' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '1' + elif 'ctx2' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '2' + elif 'ctx3' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '3' + elif 'ctx4' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '4' + + # Only one of the following OR cmplog + # enable laf-intel compare splitting + if 'laf' in build_modes: + os.environ['AFL_LLVM_LAF_SPLIT_SWITCHES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_COMPARES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_FLOATS'] = '1' + if 'autodict' not in build_modes: + os.environ['AFL_LLVM_LAF_TRANSFORM_COMPARES'] = '1' + + if 'eclipser' in build_modes: + os.environ['FUZZER_LIB'] = '/libStandaloneFuzzTarget.a' + else: + os.environ['FUZZER_LIB'] = '/libAFLDriver.a' + + # Some benchmarks like lcms. (see: + # https://github.com/mm2/Little-CMS/commit/ab1093539b4287c233aca6a3cf53b234faceb792#diff-f0e6d05e72548974e852e8e55dffc4ccR212) + # fail to compile if the compiler outputs things to stderr in unexpected + # cases. Prevent these failures by using AFL_QUIET to stop afl-clang-fast + # from writing AFL specific messages to stderr. + os.environ['AFL_QUIET'] = '1' + os.environ['AFL_MAP_SIZE'] = '2621440' + + src = os.getenv('SRC') + work = os.getenv('WORK') + + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + utils.build_benchmark() + + if 'cmplog' in build_modes and 'qemu' not in build_modes: + + # CmpLog requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['AFL_LLVM_CMPLOG'] = '1' + + # For CmpLog build, set the OUT and FUZZ_TARGET environment + # variable to point to the new CmpLog build directory. + cmplog_build_directory = get_cmplog_build_directory(build_directory) + os.mkdir(cmplog_build_directory) + new_env['OUT'] = cmplog_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for CmpLog fuzzing target') + utils.build_benchmark(env=new_env) + + if 'symcc' in build_modes: + + symcc_build_directory = get_uninstrumented_build_directory( + build_directory) + os.mkdir(symcc_build_directory) + + # symcc requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['CC'] = '/symcc/build/symcc' + new_env['CXX'] = '/symcc/build/sym++' + new_env['SYMCC_OUTPUT_DIR'] = '/tmp' + new_env['CXXFLAGS'] = new_env['CXXFLAGS'].replace('-stlib=libc++', '') + new_env['FUZZER_LIB'] = '/libfuzzer-harness.o' + new_env['OUT'] = symcc_build_directory + new_env['SYMCC_LIBCXX_PATH'] = '/libcxx_native_build' + new_env['SYMCC_NO_SYMBOLIC_INPUT'] = '1' + new_env['SYMCC_SILENT'] = '1' + + # For symcc build, set the OUT and FUZZ_TARGET environment + # variable to point to the new symcc build directory. + new_env['OUT'] = symcc_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(symcc_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for symcc fuzzing target') + utils.build_benchmark(env=new_env) + + shutil.copy('/afl/afl-fuzz', build_directory) + if os.path.exists('/afl/afl-qemu-trace'): + shutil.copy('/afl/afl-qemu-trace', build_directory) + if os.path.exists('/aflpp_qemu_driver_hook.so'): + shutil.copy('/aflpp_qemu_driver_hook.so', build_directory) + if os.path.exists('/get_frida_entry.sh'): + shutil.copy('/afl/afl-frida-trace.so', build_directory) + shutil.copy('/get_frida_entry.sh', build_directory) + + +# pylint: disable=too-many-arguments +def fuzz(input_corpus, + output_corpus, + target_binary, + flags=tuple(), + skip=False, + no_cmplog=False): # pylint: disable=too-many-arguments + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = ( + get_cmplog_build_directory(target_binary_directory)) + target_binary_name = os.path.basename(target_binary) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + target_binary_name) + + afl_fuzzer.prepare_fuzz_environment(input_corpus) + # decomment this to enable libdislocator. + # os.environ['AFL_ALIGNED_ALLOC'] = '1' # align malloc to max_align_t + # os.environ['AFL_PRELOAD'] = '/afl/libdislocator.so' + + flags = list(flags) + + if os.path.exists('./afl++.dict'): + flags += ['-x', './afl++.dict'] + + # Move the following to skip for upcoming _double tests: + if os.path.exists(cmplog_target_binary) and no_cmplog is False: + flags += ['-c', cmplog_target_binary] + + #os.environ['AFL_IGNORE_TIMEOUTS'] = '1' + os.environ['AFL_IGNORE_UNKNOWN_ENVS'] = '1' + os.environ['AFL_FAST_CAL'] = '1' + os.environ['AFL_NO_WARN_INSTABILITY'] = '1' + + if not skip: + os.environ['AFL_DISABLE_TRIM'] = '1' + os.environ['AFL_CMPLOG_ONLY_NEW'] = '1' + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + + afl_fuzzer.run_afl_fuzz(input_corpus, + output_corpus, + target_binary, + additional_flags=flags) diff --git a/fuzzers/aflplusplus_aflphuzz/runner.Dockerfile b/fuzzers/aflplusplus_aflphuzz/runner.Dockerfile new file mode 100644 index 000000000..7aa1da8e4 --- /dev/null +++ b/fuzzers/aflplusplus_aflphuzz/runner.Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2020 Google LLC +# +# 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. + +FROM gcr.io/fuzzbench/base-image + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +#ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/aflplusplus_muttfuzz/builder.Dockerfile b/fuzzers/aflplusplus_muttfuzz/builder.Dockerfile deleted file mode 100644 index d4fc0787f..000000000 --- a/fuzzers/aflplusplus_muttfuzz/builder.Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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. - -ARG parent_image -FROM $parent_image - -# Install libstdc++ to use llvm_mode. -RUN apt-get update && \ - apt-get install -y wget libstdc++-5-dev libtool-bin automake flex bison \ - libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ - apt-utils apt-transport-https ca-certificates - -# Download and compile afl++. -RUN git clone https://github.com/AFLplusplus/AFLplusplus.git /afl && \ - cd /afl && \ - git checkout 0c122aeee65c5e91b6ecc465dcdf740aa67943d1 - -# Build without Python support as we don't need it. -# Set AFL_NO_X86 to skip flaky tests. -RUN cd /afl && unset CFLAGS && unset CXXFLAGS && \ - export CC=clang && export AFL_NO_X86=1 && \ - PYTHON_INCLUDE=/ make && make install && \ - make -C utils/aflpp_driver && \ - cp utils/aflpp_driver/libAFLDriver.a / - -RUN apt-get update && apt-get install -y python3 - -RUN pip3 install --upgrade --force pip -RUN pip install muttfuzz \ No newline at end of file diff --git a/fuzzers/aflplusplus_muttfuzz/description.md b/fuzzers/aflplusplus_muttfuzz/description.md deleted file mode 100644 index 94d15ced1..000000000 --- a/fuzzers/aflplusplus_muttfuzz/description.md +++ /dev/null @@ -1,9 +0,0 @@ -# aflplusplus - -AFL++ mutation fuzzer instance - -Repository: [https://github.com/agroce/muttfuzz](https://github.com/agroce/muttfuzz) - -[builder.Dockerfile](builder.Dockerfile) -[fuzzer.py](fuzzer.py) -[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/aflplusplus_muttfuzz/fuzzer.py b/fuzzers/aflplusplus_muttfuzz/fuzzer.py deleted file mode 100755 index 459b2ed9d..000000000 --- a/fuzzers/aflplusplus_muttfuzz/fuzzer.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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. -"""Integration code for AFLplusplus fuzzer.""" - -# This optimized afl++ variant should always be run together with -# "aflplusplus" to show the difference - a default configured afl++ vs. -# a hand-crafted optimized one. afl++ is configured not to enable the good -# stuff by default to be as close to vanilla afl as possible. -# But this means that the good stuff is hidden away in this benchmark -# otherwise. - -import os -from fuzzers.aflplusplus_muttfuzz import fuzzutil -from fuzzers.aflplusplus import fuzzer as aflplusplus_fuzzer - - -def build(): # pylint: disable=too-many-branches,too-many-statements - """Build benchmark.""" - aflplusplus_fuzzer.build() - - -def get_cmplog_build_directory(target_directory): - """Return path to CmpLog target directory.""" - return os.path.join(target_directory, 'cmplog') - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def restore_out(input_corpus, output_corpus, crashes_storage): - """Restores output dir and copies crashes after mutant is done running""" - os.system(f"rm -rf {input_corpus}/*") - os.system( - f"cp {output_corpus}/default/crashes/crashes.*/id* {crashes_storage}/") - os.system( - f"cp {output_corpus}/default/crashes/crashes.*/id* {input_corpus}/") - os.system(f"cp {output_corpus}/default/queue/* {input_corpus}/") - os.system(f"rm -rf {output_corpus}/*") - - -def fuzz(input_corpus, output_corpus, target_binary): - """Run fuzzer.""" - os.environ['AFL_SKIP_CRASHES'] = "1" - os.environ['AFL_AUTORESUME'] = "1" - print(f"{input_corpus} {output_corpus} {target_binary}") - - crashes_storage = "/storage" - os.makedirs(crashes_storage, exist_ok=True) - - aflplusplus_fuzz_fn = lambda: aflplusplus_fuzzer.fuzz( - input_corpus, output_corpus, target_binary) - - budget = 86_400 - fraction_mutant = 0.5 - time_per_mutant = 300 - initial_budget = 1_800 - post_mutant_fn = lambda: restore_out(input_corpus, output_corpus, - crashes_storage) - fuzzutil.fuzz_with_mutants_via_function(aflplusplus_fuzz_fn, - target_binary, - budget, - time_per_mutant, - fraction_mutant, - initial_fn=aflplusplus_fuzz_fn, - initial_budget=initial_budget, - post_initial_fn=post_mutant_fn, - post_mutant_fn=post_mutant_fn) diff --git a/fuzzers/aflplusplus_muttfuzz/fuzzutil.py b/fuzzers/aflplusplus_muttfuzz/fuzzutil.py deleted file mode 100644 index e7250aa03..000000000 --- a/fuzzers/aflplusplus_muttfuzz/fuzzutil.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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. -"""Utilities for running muttfuzz""" -from datetime import datetime -import os -import signal -import subprocess -from subprocess import CalledProcessError -import time -from contextlib import contextmanager - -from fuzzers.aflplusplus_muttfuzz import mutate - - -class TimeoutException(Exception): - """ "Exception thrown when timeouts occur""" - - -@contextmanager -def time_limit(seconds): - """Method to define a time limit before throwing exception""" - - def signal_handler(signum, frame): - raise TimeoutException("Timed out!") - - signal.signal(signal.SIGALRM, signal_handler) - signal.alarm(seconds) - try: - yield - finally: - signal.alarm(0) - - -def restore_executable(executable, executable_code): - """Method to restore the original executable""" - # We do this because it could still be busy if fuzzer hasn't shut down yet - with open("/tmp/new_executable", "wb") as f_name: - f_name.write(executable_code) - os.rename("/tmp/new_executable", executable) - subprocess.check_call(["chmod", "+x", executable]) - - -def silent_run_with_timeout(cmd, timeout): - """Method to run command silently with timeout""" - dnull = open(os.devnull, "w") - start_p = time.time() - try: - with open("cmd_errors.txt", "w") as cmd_errors: - process = subprocess.Popen( # pylint: disable=subprocess-popen-preexec-fn - cmd, - shell=True, - preexec_fn=os.setsid, - stdout=dnull, - stderr=cmd_errors, - ) - while (process.poll() is None) and ( - (time.time() - start_p) < timeout): - time.sleep(0.5) - if process.poll() is None: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) - with open("cmd_errors.txt", "r") as cmd_errors: - cmd_errors_out = cmd_errors.read() - if len(cmd_errors_out) > 0: - print("ERRORS:") - print(cmd_errors_out) - finally: - if process.poll() is None: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) - - -def fuzz_with_mutants( # pylint: disable=too-many-locals,too-many-arguments - fuzzer_cmd, - executable, - budget, - time_per_mutant, - fraction_mutant, - initial_fuzz_cmd="", - initial_budget=0, - post_initial_cmd="", - post_mutant_cmd="", - status_cmd="", - order=1, -): - """Function to fuzz mutants from commands""" - executable_code = mutate.get_code(executable) - executable_jumps = mutate.get_jumps(executable) - start_fuzz = time.time() - mutant_no = 1 - try: - if initial_fuzz_cmd != "": - print( - "=" * 10, - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S"), - "=" * 10, - ) - print("RUNNING INITIAL FUZZING...") - silent_run_with_timeout(initial_fuzz_cmd, initial_budget) - if status_cmd != "": - print("INITIAL STATUS:") - subprocess.call(status_cmd, shell=True) - if post_initial_cmd != "": - subprocess.call(post_initial_cmd, shell=True) - - while ((time.time() - start_fuzz) - initial_budget) < (budget * - fraction_mutant): - print( - "=" * 10, - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S"), - "=" * 10, - ) - print( - round(time.time() - start_fuzz, 2), - "ELAPSED: GENERATING MUTANT #" + str(mutant_no), - ) - mutant_no += 1 - # make a new mutant of the executable; rename - # avoids hitting a busy executable - mutate.mutate_from( - executable_code, - executable_jumps, - "/tmp/new_executable", - order=order, - ) - os.rename("/tmp/new_executable", executable) - subprocess.check_call(["chmod", "+x", executable]) - print("FUZZING MUTANT...") - start_run = time.time() - silent_run_with_timeout(fuzzer_cmd, time_per_mutant) - print( - "FINISHED FUZZING IN", - round(time.time() - start_run, 2), - "SECONDS", - ) - if post_mutant_cmd != "": - subprocess.call(post_mutant_cmd, shell=True) - if status_cmd != "": - print("STATUS:") - subprocess.call(status_cmd, shell=True) - - print( - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S")) - print(round(time.time() - start_fuzz, 2), - "ELAPSED: STARTING FINAL FUZZ") - restore_executable(executable, executable_code) - silent_run_with_timeout(fuzzer_cmd, budget - (time.time() - start_fuzz)) - print( - "COMPLETED ALL FUZZING AFTER", - round(time.time() - start_fuzz, 2), - "SECONDS", - ) - if status_cmd != "": - print("FINAL STATUS:") - subprocess.call(status_cmd, shell=True) - finally: - # always restore the original binary! - restore_executable(executable, executable_code) - - -def fuzz_with_mutants_via_function( # pylint: disable=too-many-locals,too-many-statements,too-many-arguments,too-many-branches - fuzzer_fn, - executable, - budget, - time_per_mutant, - fraction_mutant, - initial_fn=None, - initial_budget=0, - post_initial_fn=None, - post_mutant_fn=None, - status_fn=None, - order=1, -): - """Fuzz mutants from initial and post mutant functions""" - executable_code = mutate.get_code(executable) - executable_jumps = mutate.get_jumps(executable) - start_fuzz = time.time() - mutant_no = 1 - try: - if initial_fn is not None: - print( - "=" * 10, - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S"), - "=" * 10, - ) - print("RUNNING INITIAL FUZZING...") - try: - with time_limit(initial_budget): - initial_fn() - except TimeoutException: - pass - if status_fn is not None: - print("INITIAL STATUS:") - status_fn() - if post_initial_fn is not None: - post_initial_fn() - - while ((time.time() - start_fuzz) - initial_budget) < (budget * - fraction_mutant): - print( - "=" * 10, - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S"), - "=" * 10, - ) - print( - round(time.time() - start_fuzz, 2), - "ELAPSED: GENERATING MUTANT #" + str(mutant_no), - ) - mutant_no += 1 - # make a new mutant of the executable; rename avoids - # hitting a busy executable - mutate.mutate_from( - executable_code, - executable_jumps, - "/tmp/new_executable", - order=order, - ) - os.rename("/tmp/new_executable", executable) - subprocess.check_call(["chmod", "+x", executable]) - print("FUZZING MUTANT...") - start_run = time.time() - try: - with time_limit(time_per_mutant): - fuzzer_fn() - except TimeoutException: - pass - except CalledProcessError: - pass - print( - "FINISHED FUZZING IN", - round(time.time() - start_run, 2), - "SECONDS", - ) - if post_mutant_fn is not None: - post_mutant_fn() - if status_fn is not None: - print("STATUS:") - status_fn() - - print( - datetime.utcfromtimestamp( - time.time()).strftime("%Y-%m-%d %H:%M:%S")) - print(round(time.time() - start_fuzz, 2), - "ELAPSED: STARTING FINAL FUZZ") - restore_executable(executable, executable_code) - try: - with time_limit(int(budget - (time.time() - start_fuzz))): - fuzzer_fn() - except TimeoutException: - pass - except CalledProcessError: - pass - print( - "COMPLETED ALL FUZZING AFTER", - round(time.time() - start_fuzz, 2), - "SECONDS", - ) - if status_fn is not None: - print("FINAL STATUS:") - status_fn() - finally: - # always restore the original binary! - restore_executable(executable, executable_code) diff --git a/fuzzers/aflplusplus_muttfuzz/mutate.py b/fuzzers/aflplusplus_muttfuzz/mutate.py deleted file mode 100644 index e5e388a90..000000000 --- a/fuzzers/aflplusplus_muttfuzz/mutate.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2020 Google LLC -# -# 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. -"""Module to apply mutants at bytecode level""" -import random -import subprocess - -JUMP_OPCODES = ["je", "jne", "jl", "jle", "jg", "jge"] -SHORT_JUMPS = list( - map(bytes.fromhex, ["74", "75", "7C", "7D", "7E", "7F", "EB"])) -# no unconditional for near jumps, since changes opcode length, not worth it -NEAR_JUMPS = list( - map( - bytes.fromhex, - ["0F 84", "0F 85", "0F 8C", "0F 8D", "0F 8E", "0F 8F", "90 E9"], - )) - -# known markers for fuzzer/compiler injected instrumentation/etc. -INST_SET = ["__afl", "__asan", "__ubsan", "__sanitizer", "__lsan", "__sancov"] - - -def get_jumps(filename): # pylint: disable=too-many-locals - """Method to get all jumps in file""" - jumps = {} - - proc = subprocess.Popen( - ["objdump", "-d", "--file-offsets", filename], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - out, _ = proc.communicate() - output = str(out, encoding="utf-8") - - for line in output.split("\n"): - try: - if "File Offset" in line and line[-1] == ":": - section_base = int(line.split()[0], 16) - offset_hex = line.split("File Offset:")[1].split(")")[0] - section_offset = int(offset_hex, 16) - section_base - continue - found_inst = False - for i in INST_SET: - if i in line: - found_inst = True - break - if found_inst: - continue # Don't mutate these things - fields = line.split("\t") - if len(fields) > 1: - opcode = fields[2].split()[0] - if opcode in JUMP_OPCODES: - loc_bytes = fields[0].split(":")[0] - loc = int(loc_bytes, 16) + section_offset - jumps[loc] = (opcode, bytes.fromhex(fields[1])) - # pylint: disable=bare-except - except: # If we can't parse some line in the objdump, just skip it - pass - - return jumps - - -def different_jump(hexdata): - """Method to select a different jump""" - # NEAR JUMP BYTE CHECK - if hexdata[0] == 15: # pylint: disable=no-else-return - # Have a high chance of just changing near JE and JNE to a - # forced JMP, "removing" a branch - if ((hexdata[1] == NEAR_JUMPS[0][1]) or - (hexdata[1] == NEAR_JUMPS[1][1])) and (random.random() <= 0.75): - return NEAR_JUMPS[-1] - return random.choice( - list(filter(lambda j: j[1] != hexdata[1], NEAR_JUMPS))) - else: - # Have a high chance of just changing short JE and - # JNE to a forced JMP, "removing" a branch - if ((hexdata[0] == SHORT_JUMPS[0][0]) or - (hexdata[0] == SHORT_JUMPS[1][0])) and (random.random() <= 0.75): - return SHORT_JUMPS[-1] - return random.choice( - list(filter(lambda j: j[0] != hexdata[0], SHORT_JUMPS))) - - -def pick_and_change(jumps): - """Randomly change jumps""" - loc = random.choice(list(jumps.keys())) - return (loc, different_jump(jumps[loc][1])) - - -def get_code(filename): - """Read code as array of bytes""" - with open(filename, "rb") as f_name: - return bytearray(f_name.read()) - - -def mutant_from(code, jumps, order=1): - """Get new code from code and jumps""" - new_code = bytearray(code) - for _ in range( - order): # allows higher-order mutants, though can undo mutations - (loc, new_data) = pick_and_change(jumps) - for offset in range(0, len(new_data)): # pylint: disable=consider-using-enumerate - new_code[loc + offset] = new_data[offset] - return new_code - - -def mutant(filename, order=1): - """Write mutant to file""" - return mutant_from(get_code(filename), get_jumps(filename), order=order) - - -def mutate_from(code, jumps, new_filename, order=1): - """Wrap mutant_from wth order to write to new_filename""" - with open(new_filename, "wb") as f_name: - f_name.write(mutant_from(code, jumps, order=order)) - - -def mutate(filename, new_filename, order=1): - """Write mutant to new file""" - with open(new_filename, "wb") as f_name: - f_name.write(mutant(filename, order=order)) diff --git a/service/experiment-requests.yaml b/service/experiment-requests.yaml index 5d29423a1..5441fd1c3 100644 --- a/service/experiment-requests.yaml +++ b/service/experiment-requests.yaml @@ -20,6 +20,28 @@ # Please add new experiment requests towards the top of this file. # +- experiment: 2023-04-15-alphaphuzz + description: "test variant" + fuzzers: + - aflplusplus_314 + - aflplusplus_aflphuzz + +- experiment: 2023-04-13-aflpp + description: "Find regression" + fuzzers: + - aflplusplus_mega + - aflplusplus_314_0 + - aflplusplus_314_1 + - aflplusplus_314_2 + - aflplusplus_314_3 + - aflplusplus_314_4 + - aflplusplus_314_5 + - aflplusplus_314 + benchmarks: + - bloaty_fuzz_target + - libxml2_xml + - sqlite3_ossfuzz + - experiment: 2023-04-09-aflpp description: "Test new mutation engine and -z option" fuzzers: