From 3060a520de8eb5b6a0ab1a72a6180c7a45df73c4 Mon Sep 17 00:00:00 2001 From: Addison Crump Date: Fri, 22 Sep 2023 23:38:17 +0200 Subject: [PATCH] libafl_libfuzzer_best --- .../libafl_libfuzzer_best/builder.Dockerfile | 42 ++++++ fuzzers/libafl_libfuzzer_best/description.md | 11 ++ fuzzers/libafl_libfuzzer_best/fuzzer.py | 120 ++++++++++++++++++ .../libafl_libfuzzer_best/runner.Dockerfile | 15 +++ 4 files changed, 188 insertions(+) create mode 100644 fuzzers/libafl_libfuzzer_best/builder.Dockerfile create mode 100644 fuzzers/libafl_libfuzzer_best/description.md create mode 100755 fuzzers/libafl_libfuzzer_best/fuzzer.py create mode 100644 fuzzers/libafl_libfuzzer_best/runner.Dockerfile diff --git a/fuzzers/libafl_libfuzzer_best/builder.Dockerfile b/fuzzers/libafl_libfuzzer_best/builder.Dockerfile new file mode 100644 index 000000000..81512cf71 --- /dev/null +++ b/fuzzers/libafl_libfuzzer_best/builder.Dockerfile @@ -0,0 +1,42 @@ +# 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 remove -y llvm-10 && \ + apt-get install -y \ + build-essential \ + llvm-11 \ + clang-12 && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2023-08-23 -y && \ + rm /rustup.sh + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/libafl /libafl && \ + cd /libafl && \ + git checkout 579dcde04d6da6c7a80790a2aee9548f77d587cc && \ + unset CFLAGS CXXFLAGS && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./libafl_libfuzzer/libafl_libfuzzer_runtime && \ + env -i CXX=$CXX CC=$CC PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench && \ + cp ./target/release-fuzzbench/libafl_libfuzzer_runtime.a /usr/lib/libFuzzer.a diff --git a/fuzzers/libafl_libfuzzer_best/description.md b/fuzzers/libafl_libfuzzer_best/description.md new file mode 100644 index 000000000..69107e2eb --- /dev/null +++ b/fuzzers/libafl_libfuzzer_best/description.md @@ -0,0 +1,11 @@ +# libafl_libfuzzer + +`libafl_libfuzzer` is a libfuzzer shim which attempts to replicate as many of the features of libfuzzer as possible +without utilising any customisation from the compiler, making it compatible with all libfuzzer targets while also using +all the advanced features of libafl. + +Repository: [LibAFL/libfuzzer](https://github.com/AFLplusplus/LibAFL/tree/libfuzzer) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_libfuzzer_best/fuzzer.py b/fuzzers/libafl_libfuzzer_best/fuzzer.py new file mode 100755 index 000000000..c48e3612a --- /dev/null +++ b/fuzzers/libafl_libfuzzer_best/fuzzer.py @@ -0,0 +1,120 @@ +# 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 a LibAFL-based fuzzer.""" + +import os +import subprocess + +from fuzzers import utils + + +def prepare_fuzz_environment(): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:' \ + 'malloc_context_size=0:symbolize=0:' \ + 'allocator_may_return_null=1:' \ + 'detect_odr_violation=0:handle_segv=0:' \ + 'handle_sigbus=0:handle_abort=0:' \ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:' \ + 'allocator_release_to_os_interval_ms=500:' \ + 'handle_abort=0:handle_segv=0:' \ + 'handle_sigbus=0:handle_sigfpe=0:' \ + 'handle_sigill=0:print_stacktrace=0:' \ + 'symbolize=0:symbolize_inline_frames=0' + + +def build(): + """Build benchmark.""" + # With LibFuzzer we use -fsanitize=fuzzer-no-link for build CFLAGS and then + # /usr/lib/libFuzzer.a as the FUZZER_LIB for the main fuzzing binary. This + # allows us to link against a version of LibFuzzer that we specify. + cflags = ['-fsanitize=fuzzer-no-link'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + + # merge all of our lib into a single .o, then pack that into a static lib + subprocess.check_call([ + '/usr/bin/ld', '-Ur', '--whole-archive', '/usr/lib/libFuzzer.a', '-o', + '/tmp/libFuzzerMerged.o' + ]) + subprocess.check_call(['/usr/bin/rm', '/usr/lib/libFuzzer.a']) + subprocess.check_call( + ['/usr/bin/ar', 'cr', '/usr/lib/libFuzzer.a', '/tmp/libFuzzerMerged.o']) + + os.environ['FUZZER_LIB'] = '/usr/lib/libFuzzer.a' + + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer. Wrapper that uses the defaults when calling + run_fuzzer.""" + run_fuzzer(input_corpus, output_corpus, target_binary) + + +def run_fuzzer(input_corpus, output_corpus, target_binary, extra_flags=None): + """Run fuzzer.""" + if extra_flags is None: + extra_flags = [] + + # ASAN doesn't play nicely with our signal handling + # in the future, we will make this more compatible with libfuzzer, but + # for the initial implementation, we consider this sufficient + prepare_fuzz_environment() + + # Seperate out corpus and crash directories as sub-directories of + # |output_corpus| to avoid conflicts when corpus directory is reloaded. + crashes_dir = os.path.join(output_corpus, 'crashes') + output_corpus = os.path.join(output_corpus, 'corpus') + os.makedirs(crashes_dir) + os.makedirs(output_corpus) + + flags = [ + # not supported by libafl_libfuzzer currently + '-print_final_stats=1', + # `close_fd_mask` to prevent too much logging output from the target. + '-close_fd_mask=3', + # Run in fork mode to allow ignoring ooms, timeouts, crashes and + # continue fuzzing indefinitely. + '-fork=1', + '-ignore_ooms=1', + '-ignore_timeouts=1', + '-ignore_crashes=1', + + # Don't use LSAN's leak detection. Other fuzzers won't be using it and + # using it will cause libFuzzer to find "crashes" no one cares about. + # libafl_libfuzzer does not do leak checking regardless; not supported + '-detect_leaks=0', + + # Disable grimoire mutations and rely on unicode mutations + '-grimoire=0', + + # Store crashes along with corpus for bug based benchmarking. + f'-artifact_prefix={crashes_dir}/', + ] + flags += extra_flags + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + dictionary_path = utils.get_dictionary_path(target_binary) + if dictionary_path: + flags.append('-dict=' + dictionary_path) + + command = [target_binary] + flags + [output_corpus, input_corpus] + print('[run_fuzzer] Running command: ' + ' '.join(command)) + subprocess.check_call(command) diff --git a/fuzzers/libafl_libfuzzer_best/runner.Dockerfile b/fuzzers/libafl_libfuzzer_best/runner.Dockerfile new file mode 100644 index 000000000..0d6cf004e --- /dev/null +++ b/fuzzers/libafl_libfuzzer_best/runner.Dockerfile @@ -0,0 +1,15 @@ +# 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