├── CONTRIBUTING.md ├── GETTING-RESULTS.md ├── GETTING-STARTED.md ├── LICENSE ├── README.md ├── base ├── libfuzzer-base-haskell │ ├── Dockerfile │ ├── README.md │ ├── cabal.config │ ├── dotemacs │ ├── ghc-asan │ ├── ghc-wrapper │ ├── hs-libfuzzer │ │ ├── LICENSE │ │ ├── Setup.hs │ │ ├── libfuzzer.cabal │ │ ├── src │ │ │ └── Libfuzzer.hs │ │ └── stack.yaml │ ├── hvr-ghc.key │ ├── hvr-ghc.list │ └── src │ │ ├── build.sh │ │ ├── hsinit.c │ │ └── test.hs └── libfuzzer-base │ ├── Dockerfile │ ├── README.md │ └── fuzz.sh ├── doc ├── meeting-20160621.md ├── meeting-20160715.md ├── pictures │ ├── fuzzing-lua.gif │ ├── infra-plan-fenris-20160705.jpg │ ├── infra-plan-wed-20160705.jpg │ ├── infra-workflow-20160621.jpg │ ├── mvp-plan-20160715.jpg │ ├── popularisation-planning-20160809.jpg │ └── project-plan-20160614.jpg ├── presentation-mikkoyli-libfuzzerfication-20160823.md ├── presentation-mikkoyli-libfuzzerfication-updates-20160705.md ├── presentation-oherrala-fuzzing-beyond-c.md ├── presentation-stub-writing.md ├── protecode-sc-top-components-20160609.txt ├── protecode-sc-top-components-native-20160609.txt └── screencast.md ├── docker-compose.yml └── stubs ├── ImageMagick ├── Dockerfile ├── ImageMagick-fuzzer.c ├── README.md ├── build.sh ├── license-samples └── samples.tar.gz ├── README.md ├── haskell-x509 ├── Dockerfile ├── README.md ├── build.sh └── test.hs ├── libmad ├── Dockerfile ├── README.md ├── build.sh ├── libmad-fuzzer.c └── samples.tar ├── libxml2 ├── Dockerfile ├── LICENSE ├── README.md ├── build.sh ├── libxml2-fuzzer.cc ├── samples.tar.gz └── xml.dict ├── libxslt ├── Dockerfile ├── README.md ├── build.sh ├── libxslt-fuzzer.cc └── samples.tar.gz ├── lua ├── Dockerfile ├── README.md ├── build.sh ├── lua-fuzzer.c └── samples │ └── simple.lua ├── mysamplelib ├── Dockerfile ├── README.md ├── build.sh ├── dictionary.txt ├── fuzzer.c ├── mysamplelib.c ├── mysamplelib.h └── samples │ └── sample1.txt └── zlib ├── Dockerfile ├── README.md ├── build.sh └── zlib-fuzzer.cc /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome! 2 | 3 | # How Can I Contribute? 4 | 5 | * See the [Getting started documentation](https://github.com/ouspg/libfuzzerfication/blob/master/GETTING-STARTED.md) 6 | * Check documentation and examples from stubs/ directory. [mysamplelib](https://github.com/ouspg/libfuzzerfication/tree/master/stubs/mysamplelib) is a good for learning purposes. 7 | * Write you own stub and add README.md file for it. 8 | * Create a pull request. 9 | * Comment the pull request if the default license is okay for you. 10 | 11 | # Abandon-*lib*-ware 12 | 13 | * Cautionary note should be written about libraries without an active upstream but which are still in wide use. 14 | -------------------------------------------------------------------------------- /GETTING-RESULTS.md: -------------------------------------------------------------------------------- 1 | # Getting results 2 | 3 | * On every kind of failure libFuzzer prints a stack trace. It dumps reproducer file to disk and then exits the process. In libFuzzerfication fuzz.sh script takes care that fuzzer is started again and is running all the time. 4 | 5 | * Every stub's container saves repro file on host machine's $HOME/results directory. Also log including stack trace and other information is saved to results directory. 6 | 7 | * You can try to reproduce errors by starting a new container and mounting a repro file in it. After that you can run fuzzer stub with that repro. 8 | -------------------------------------------------------------------------------- /GETTING-STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ## 4 | See the [screencast](https://www.youtube.com/watch?v=B46AMry7lHs&feature=youtu.be) about stub writing. 5 | 6 | ## Requirements 7 | 8 | Before getting started you need the following requirements: 9 | * [Docker version 1.11.2](https://www.docker.com/) 10 | * [docker-compose version 1.8.0](https://github.com/docker/compose/releases) 11 | 12 | ## Clone repository 13 | 14 | First thing you need to do is to clone git repository. 15 | 16 | ```console 17 | git clone https://github.com/ouspg/libfuzzerfication.git 18 | ``` 19 | 20 | ## Get the libfuzzer-base image 21 | 22 | ```console 23 | cd libfuzzerfication 24 | ``` 25 | 26 | Then you have to get the libfuzzer-base docker image. 27 | 28 | ```console 29 | docker pull ouspg/libfuzzer-base 30 | ``` 31 | 32 | **Alternatively** you can build libfuzzer-base yourself if you want but it takes longer time. 33 | 34 | ```console 35 | docker-compose build libfuzzer-base 36 | ``` 37 | 38 | ## Build the stub image (ImageMagick in this example) 39 | 40 | In this example we are going to build ImageMagick image 41 | 42 | ```console 43 | docker-compose build ImageMagick 44 | ``` 45 | 46 | ## Running fuzzer 47 | 48 | Run the container 49 | 50 | ```console 51 | docker-compose run ImageMagick 52 | ``` 53 | 54 | Fuzzer should produce output like this: 55 | 56 | ``` 57 | INFO: Seed: 802690056 58 | #0 READ units: 59 exec/s: 0 59 | #59 INITED cov: 2453 bits: 5172 indir: 22 units: 39 exec/s: 0 60 | #67 NEW cov: 2453 bits: 5188 indir: 22 units: 40 exec/s: 0 L: 393 MS: 3 ChangeBit-ChangeBit-CrossOver- 61 | #69 NEW cov: 2454 bits: 5189 indir: 22 units: 41 exec/s: 0 L: 406 MS: 5 ChangeBit-ChangeBit-CrossOver-EraseByte-AddFromTempAutoDict- DE: "id=ImageMagick"- 62 | #80 NEW cov: 2454 bits: 5195 indir: 22 units: 42 exec/s: 0 L: 393 MS: 1 ChangeByte- 63 | #90 NEW cov: 2454 bits: 5198 indir: 22 units: 43 exec/s: 0 L: 341 MS: 1 ChangeByte- 64 | #120 NEW cov: 2454 bits: 5206 indir: 22 units: 44 exec/s: 0 L: 874 MS: 1 ChangeByte- 65 | #125 NEW cov: 2454 bits: 5208 indir: 22 units: 45 exec/s: 0 L: 97 MS: 1 InsertByte- 66 | #144 NEW cov: 2454 bits: 5209 indir: 22 units: 46 exec/s: 0 L: 861 MS: 5 ChangeByte-InsertByte-InsertByte-ChangeBit-CrossOver- 67 | #148 NEW cov: 2454 bits: 5210 indir: 22 units: 47 exec/s: 0 L: 875 MS: 4 ChangeByte-ShuffleBytes-InsertByte-AddFromPersAutoDict- DE: "id=ImageMagick"- 68 | #157 NEW cov: 2455 bits: 5211 indir: 22 units: 48 exec/s: 0 L: 408 MS: 3 ShuffleBytes-InsertByte-AddFromPersAutoDict- DE: "id=ImageMagick"- 69 | ``` 70 | 71 | The NEW line appears when libFuzzer finds new interesting input. 72 | 73 | The pulse line shows current status and appears periodically 74 | 75 | ## Samples 76 | 77 | There is usually no point running fuzzers without samples. Currently samples are mounted from ~/samples/libfuzzer-target (ImageMagic example: ~/samples/libfuzzer-imagemagick) to /srv/fuzzer in container. Results are mounted from ~/results to /srv/fuzzer/results in container. Some sample files are provided in repository but larger sample sets should be used with fuzzers. 78 | 79 | ## Writing your own stubs 80 | 81 | ### General 82 | 83 | 1. Build libFuzzer itself without any compiler options (included in libfuzzer-base) 84 | 2. Build target with fresh clang using: 85 | 86 | * one of the sanitizers (asan, msan, ubsan) 87 | * fsanitize-coverage=edge[,8bit-counters,trace-cmp,indirect-calls] 88 | * Usually -O1 or -O2 for speed 89 | * But -O0 may be better for fuzzing 90 | 91 | 92 | You can start writing your own stubs in the top of the libfuzzer-base image. See [screencast](https://www.youtube.com/watch?v=B46AMry7lHs&feature=youtu.be) example of writing stub for libxml2. 93 | You can read about libFuzzer and find some examples from here: http://llvm.org/docs/LibFuzzer.html. 94 | 95 | If you want to write your own stub but don't know what you want to fuzz see our [target tracking sheet](https://docs.google.com/spreadsheets/d/1oj0L44gKTn3wlrJk6b554b9o8H0r1bVfb6LJrw62BEE/pubhtml) 96 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Oulu University Secure Programming Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libfuzzerfication 2 | LibFuzzerfication project uses libFuzzer for fuzzing popular applications and libraries. 3 | 4 | Fuzzing in action 5 | 6 | # About 7 | Purpose of fuzzing is to automatically generate lots of test input and to make code crash and increase code coverage. [libFuzzer](http://llvm.org/docs/LibFuzzer.html) is a library for in-process, coverage-guided evolutionary fuzzing of other libraries. It is similiar to [American Fuzzy Lop (AFL)](http://lcamtuf.coredump.cx/afl/) but performs fuzzing inside single process and is much faster. 8 | 9 | # Motivation 10 | There have been lots of vulnerabilities in popular libraries that should have been (theoretically) easy to test. We want to offer easy way to fuzz-test these libraries and increase awareness about the situation. We also want this to be available to everyone. 11 | 12 | # About libfuzzer 13 | * LibFuzzer is open-source library (part of LLVM) 14 | * Relies on compiler instrumentation to get coverage feedback 15 | * It is linked with the library under test 16 | * Works fully inside the running program (a process) -> Fast! 17 | * LibFuzzer itself can be built with any compiler and must be built without specific flags. 18 | * Target code must be buit with Clang using [ASan](http://clang.llvm.org/docs/AddressSanitizer.html), [USan](http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) or [MSan](http://clang.llvm.org/docs/MemorySanitizer.html) and -fsanitize-coverage=edge[,8bit-counters,trace-cmp,indirect-calls] 19 | 20 | Optional features are inside []. 21 | 22 | # How does this project work? 23 | * You pull container from Dockerhub 24 | * Start Writing your own libfuzzer stub 25 | * Share dockerfile with other users 26 | * Use libFuzzer to collect corpus so that other people can continue where you left off 27 | 28 | You can start writing stubs without docker. 29 | 30 | # Getting started 31 | * You can get started by reading our [Getting started tutorial](https://github.com/ouspg/libfuzzerfication/blob/master/GETTING-STARTED.md) 32 | * See example: [mysamplelib](https://github.com/ouspg/libfuzzerfication/tree/master/stubs/mysamplelib) 33 | 34 | # Material 35 | * [libFuzzer](http://llvm.org/docs/LibFuzzer.html) 36 | * [SanitizerCoverage](http://clang.llvm.org/docs/SanitizerCoverage.html) 37 | * You can find some nice examples from: [libfuzzer-bot repo](https://github.com/google/libfuzzer-bot) 38 | * [libFuzzer in Chrome](https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/README.md) 39 | * [Efficient Fuzzer](https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/efficient_fuzzer.md) 40 | 41 | # Tracking 42 | [Target tracking sheet](https://docs.google.com/spreadsheets/d/1oj0L44gKTn3wlrJk6b554b9o8H0r1bVfb6LJrw62BEE/pubhtml) 43 | 44 | # Found issues 45 | * [ImageMagick UAF](http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=30245&sid=22eadb3cf9cce8ed28ba1aa8914f945d) 46 | 47 | # Contributors 48 | 49 | * Atte Kettunen ([@attekett](https://github.com/attekett)) 50 | * Mikko Yliniemi ([@mikessu](https://github.com/mikessu)) 51 | * Ossi Herrala ([@oherrala](https://github.com/oherrala)) 52 | * Jani Kenttälä ([@evilon](https://github.com/evilon)) 53 | * Marko Laakso ([@ikisusi](https://github.com/ikisusi)) 54 | * Pauli Huttunen ([@WhiteEyeDoll](https://github.com/WhiteEyeDoll)) 55 | * Joonas Kuorilehto ([@joneskoo](https://github.com/joneskoo)) 56 | * Ari Kauppi ([@arikauppi](https://github.com/arikauppi)) 57 | 58 | Visit #ouspg @ IRCnet if you're interested! 59 | 60 | This is part of [OUSPG-open](https://github.com/ouspg/ouspg-open) 61 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | MAINTAINER https://github.com/ouspg/libfuzzerification 4 | 5 | ENV GHC_VERSION 8.0.1 6 | ENV CABAL_VERSION 1.24 7 | ENV GHC_LLVM 3.7 8 | 9 | # https://launchpad.net/~hvr/+archive/ubuntu/ghc 10 | COPY hvr-ghc.list /etc/apt/sources.list.d/ 11 | COPY hvr-ghc.key /tmp 12 | RUN apt-key add /tmp/hvr-ghc.key 13 | 14 | # GHC and requirements 15 | RUN apt-get -y update && \ 16 | apt-get -y install \ 17 | cabal-install-${CABAL_VERSION} \ 18 | ghc-${GHC_VERSION} \ 19 | llvm-${GHC_LLVM} 20 | 21 | # My devel tools 22 | RUN apt-get -y install emacs-nox 23 | COPY dotemacs /root/.emacs 24 | 25 | # Set Clang as default compiler 26 | RUN update-alternatives --set cc /usr/bin/clang && \ 27 | update-alternatives --set c89 /usr/bin/clang && \ 28 | update-alternatives --set c99 /usr/bin/clang && \ 29 | update-alternatives --install /usr/bin/gcc gcc /usr/bin/clang 1 30 | 31 | # GHC needs to find correct version of LLVM's opt and llc 32 | RUN update-alternatives --install /usr/bin/opt opt /usr/bin/opt-${GHC_LLVM} 1 && \ 33 | update-alternatives --install /usr/bin/llc llc /usr/bin/llc-${GHC_LLVM} 1 34 | 35 | ENV PATH /opt/ghc/${GHC_VERSION}/bin/:/opt/cabal/${CABAL_VERSION}/bin/:${PATH} 36 | 37 | COPY ghc-wrapper ghc-asan /usr/local/bin/ 38 | RUN chmod a+x /usr/local/bin/ghc-* 39 | 40 | # Build and install our libfuzzer Haskell lib 41 | WORKDIR /src/hs-libfuzzer 42 | ADD hs-libfuzzer /src/hs-libfuzzer 43 | RUN cd /src/hs-libfuzzer && \ 44 | cabal update && \ 45 | cabal install && \ 46 | rm -rf /src/hs-libfuzzer 47 | 48 | COPY cabal.config /root/.cabal/config 49 | 50 | WORKDIR /haskell/ 51 | COPY src/hsinit.c src/test.hs src/build.sh /haskell/ 52 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/README.md: -------------------------------------------------------------------------------- 1 | # Libfuzzer for Haskell libraries 2 | 3 | Libfuzzer stub should be in test.hs and then: 4 | 5 | ``` 6 | # cd /src 7 | # ghc-asan -c test.hs 8 | # ghc-wrapper -no-hs-main -o test test.o /work/libfuzzer/*.o 9 | # file test 10 | test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b73b57dfcd0b673600645f4b85d0e5694db0f69a, not stripped 11 | ``` 12 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/cabal.config: -------------------------------------------------------------------------------- 1 | repository hackage.haskell.org 2 | url: http://hackage.haskell.org/ 3 | 4 | remote-repo-cache: /root/.cabal/packages 5 | world-file: /root/.cabal/world 6 | extra-prog-path: /root/.cabal/bin 7 | build-summary: /root/.cabal/logs/build.log 8 | remote-build-reporting: anonymous 9 | jobs: $ncpus 10 | 11 | program-default-options 12 | gcc-options: -g -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp 13 | ghc-options: -fllvm -optc="-fsanitize=address" -optc="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" -optl="-fsanitize=address" -optl="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 14 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/dotemacs: -------------------------------------------------------------------------------- 1 | (require 'package) 2 | (add-to-list 3 | 'package-archives 4 | '("melpa" . "https://melpa.org/packages/") t) 5 | (package-initialize) 6 | (package-refresh-contents) 7 | (package-install 'intero) 8 | (add-hook 'haskell-mode-hook 'intero-mode) 9 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/ghc-asan: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ghc-wrapper \ 4 | -optc="-g" -optl="-g" \ 5 | -optc="-fsanitize=address" \ 6 | -optc="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" \ 7 | -optl="-fsanitize=address" \ 8 | -optl="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" \ 9 | $* 10 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/ghc-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ghc \ 4 | -fllvm \ 5 | -threaded \ 6 | -fforce-recomp \ 7 | -pgmP=clang \ 8 | -pgmc=clang \ 9 | -pgma=clang \ 10 | -pgml=clang++ \ 11 | $* 12 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hs-libfuzzer/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Oulu University Secure Programming Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hs-libfuzzer/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hs-libfuzzer/libfuzzer.cabal: -------------------------------------------------------------------------------- 1 | name: libfuzzer 2 | version: 0.1.0.0 3 | synopsis: Libfuzzer utils to help with fuzzing 4 | description: Please see README.md 5 | homepage: https://github.com/ouspg/libfuzzerfication/ 6 | license: MIT 7 | license-file: LICENSE 8 | maintainer: https://github.com/ouspg/libfuzzerfication/ 9 | copyright: 2016 OUSPG 10 | category: Testing 11 | build-type: Simple 12 | cabal-version: >=1.10 13 | 14 | library 15 | hs-source-dirs: src 16 | exposed-modules: Libfuzzer 17 | default-language: Haskell2010 18 | ghc-options: -Wall 19 | build-depends: base >= 4.7 && < 5 20 | , byteable 21 | , bytestring 22 | , cryptohash 23 | , directory 24 | , memory 25 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hs-libfuzzer/src/Libfuzzer.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | 3 | module Libfuzzer 4 | ( 5 | storeTestCase 6 | ) where 7 | 8 | import Control.Monad (unless) 9 | import Crypto.Hash.SHA1 (hash) 10 | import Data.Byteable (toBytes) 11 | import System.Directory (createDirectoryIfMissing, doesFileExist) 12 | import System.IO (withFile, IOMode(..)) 13 | 14 | import qualified Data.ByteString as BS 15 | import qualified Data.ByteString.Char8 as Char8 16 | import qualified Data.ByteArray.Encoding as BA 17 | 18 | hashInHex :: String -> String 19 | hashInHex = hashInHexBS . Char8.pack 20 | 21 | hashInHexBS :: BS.ByteString -> String 22 | hashInHexBS = Char8.unpack . BA.convertToBase BA.Base16 . toBytes . hash 23 | 24 | storeTestCase :: String -> BS.ByteString -> IO () 25 | storeTestCase name content = 26 | -- Use first 60 bytes for generating directory name. This adds 27 | -- different variants of almost same exception into same directory 28 | let dir = "results/" ++ hashInHex (take 60 name) 29 | file = hashInHexBS content 30 | readme = dir ++ "/00README" 31 | in do 32 | createDirectoryIfMissing True dir 33 | hasReadme <- doesFileExist readme 34 | unless hasReadme ( 35 | withFile readme WriteMode $ \h -> 36 | BS.hPut h $ Char8.pack (name ++ "\n") 37 | ) 38 | withFile (dir ++ "/" ++ file) WriteMode $ \h -> 39 | BS.hPut h content 40 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hs-libfuzzer/stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-6.4 2 | packages: 3 | - '.' 4 | extra-deps: [] 5 | flags: {} 6 | extra-package-dbs: [] 7 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hvr-ghc.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: SKS 1.1.5 3 | Comment: Hostname: keyserver.ubuntu.com 4 | 5 | mI0EUl8RIQEEAMqQPI0CyASSpzhGyVx6WQmoFbmMwLPMO8cCFW29YXp5j+UzOik5zThhDAZX 6 | mymYrKTqv77pFZOIdelUSmPqvNwQ03Qrh0+B07ytdlJLy0HQwdWQim9tXPjci9PftCM1g+UE 7 | tUBMoZ3Nyx4VnO022b+/CzHzN+6Bg/RZxezYpAxVABEBAAG0I0xhdW5jaHBhZCBQUEEgZm9y 8 | IEhlcmJlcnQgVi4gUmllZGVsiLgEEwECACIFAlJfESECGwMGCwkIBwMCBhUIAgkKCwQWAgMB 9 | Ah4BAheAAAoJEP866s72+IKG2rAD/2uTlEfeXA26DFUovlVkLea6IJQvNHuSM7NuFJEynS0e 10 | WEoj4N6aGFlPeqWH1UxccPRiCcb0CGulEPzKGLn29kSStWm/3n6pwabNCjYtACdQ38kfAlfA 11 | 1NJ0a3DbTYaTvsaNR281kFT+CMBUX3JfVaw5ll7oXundiHSK+BSi968c 12 | =RSCg 13 | -----END PGP PUBLIC KEY BLOCK----- 14 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/hvr-ghc.list: -------------------------------------------------------------------------------- 1 | deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main 2 | # deb-src http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main 3 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | GHCOPTS="-package libfuzzer" 6 | 7 | clang -Wall -c -I/opt/ghc/8.0.1/lib/ghc-8.0.1/include/ hsinit.c 8 | ghc-asan ${GHCOPTS} -c test.hs 9 | ghc-wrapper ${GHCOPTS} -no-hs-main -lFuzzer -o test test.o hsinit.o 10 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/src/hsinit.c: -------------------------------------------------------------------------------- 1 | #include "HsFFI.h" 2 | 3 | int LLVMFuzzerInitialize(int *argc, char ***argv) { 4 | hs_init(argc, argv); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /base/libfuzzer-base-haskell/src/test.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | module Test where 4 | 5 | import Libfuzzer (storeTestCase) 6 | 7 | import Foreign.C.Types 8 | import Foreign.C.String 9 | 10 | import qualified Data.ByteString as BS 11 | 12 | foreign export ccall "LLVMFuzzerTestOneInput" testOneInputM :: CString -> CSize -> IO CInt 13 | 14 | testOneInputM :: CString -> CSize -> IO CInt 15 | testOneInputM str size = do 16 | bs <- BS.packCStringLen (str, fromIntegral size) 17 | print $ BS.length bs 18 | return 0 -- Non-zero return values are reserved for future use. 19 | -------------------------------------------------------------------------------- /base/libfuzzer-base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | # Get upgrades and install clang and nodejs 4 | 5 | RUN apt-get update && \ 6 | apt-get upgrade -y && \ 7 | apt-get install -y git clang nodejs && \ 8 | apt-get autoremove -y && \ 9 | apt-get clean && \ 10 | rm -rf /var/lib/apt/lists/* 11 | 12 | # Create fuzzer user 13 | 14 | RUN useradd fuzzer 15 | RUN mkdir -p /samples /results 16 | RUN chown fuzzer /samples && chown fuzzer /results 17 | 18 | # Checkout & build libFuzzer 19 | 20 | RUN mkdir /src /work && \ 21 | cd /src && \ 22 | git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer && \ 23 | cd Fuzzer && \ 24 | git checkout 34a77f5afc4efc03323a70e4f68b092f36f8a89b && \ 25 | cd /src && \ 26 | clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer && \ 27 | ar ruv libFuzzer.a Fuzzer*.o && \ 28 | mkdir -p /work/libfuzzer && \ 29 | mv libFuzzer.a /usr/local/lib && \ 30 | rm *.o && \ 31 | rm -rf Fuzzer 32 | 33 | # Checkout minimizer 34 | 35 | RUN cd /src && \ 36 | git clone https://github.com/attekett/nipsu/ && \ 37 | rm -rf ./nipsu/.git 38 | 39 | # Add fuzzing script 40 | 41 | ADD ./fuzz.sh /src/scripts/fuzz.sh 42 | -------------------------------------------------------------------------------- /base/libfuzzer-base/README.md: -------------------------------------------------------------------------------- 1 | # libfuzzer-base 2 | 3 | libFuzzer base image contains clang, nodejs and libfuzzer. Also nipsu minimizer is included. Fuzzer user is created so that it can be used to prevent running fuzzers as root. 4 | 5 | ## Build 6 | 7 | ```console 8 | docker-compose build libfuzzer-base 9 | ``` 10 | 11 | ## Alternative: Pull from dockerhub 12 | 13 | ```console 14 | docker pull ouspg/libfuzzer-base 15 | ``` 16 | -------------------------------------------------------------------------------- /base/libfuzzer-base/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Print args for debug 4 | echo "fuzz.sh args: $@" 5 | 6 | #Define default arguments for fuzzing 7 | mem=`awk '/^hierarchical_memory_limit / {print $2}' /sys/fs/cgroup/memory/memory.stat` 8 | mem_limit_value=`expr $mem / 1048576` 9 | rss_limit_mb="-rss_limit_mb=$mem_limit_value" 10 | detect_leaks="-detect_leaks=0" 11 | exact_artifact_path="-exact_artifact_path=/dev/shm/repro-file" 12 | max_len="-max_len=1000" 13 | use_counters="-use_counters=1" 14 | max_total_time="-max_total_time=3600" 15 | samples="/samples/" 16 | 17 | #Check if some variables have been specified instead of using default 18 | for var in "$@" 19 | do 20 | if [[ "$var" == "-rss_limit_mb="* ]]; then 21 | $value = `cut -d "=" -f 2 <<< "$var"` 22 | rss_limit_mb="-rss_limit_mb=$value" 23 | fi 24 | if [[ "$var" == "-detect_leaks="* ]]; then 25 | $value = `cut -d "=" -f 2 <<< "$var"` 26 | detect_leaks="-detect_leaks=$value" 27 | fi 28 | if [[ "$var" == "-max_len="* ]]; then 29 | $value = `cut -d "=" -f 2 <<< "$var"` 30 | max_len="-max_len=$value" 31 | fi 32 | if [[ "$var" == "-use_counters="* ]]; then 33 | $value = `cut -d "=" -f 2 <<< "$var"` 34 | use_counters="-use_counters=$value" 35 | fi 36 | if [[ "$var" == "-max_total_time="* ]]; then 37 | $value = `cut -d "=" -f 2 <<< "$var"` 38 | max_total_time="-max_total_time=$value" 39 | fi 40 | done 41 | 42 | #Use ramdisk for fuzzing. 43 | #Docker has default shm mounted at /dev/shm 44 | cd /dev/shm; 45 | mkdir fuzzed; 46 | 47 | #SIGINT trap 48 | function control_c { 49 | echo "*** SIGINT Exiting ***" 50 | exit $? 51 | } 52 | trap control_c SIGINT 53 | 54 | #TODO: Check if we can unify parsers. 55 | 56 | #ASAN-trace parser for instrumentation 57 | #Example trace: 58 | #==1937== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60a60002bd58 at pc 0x7f187a7e4928 bp 0x7ffe8aea9c70 sp 0x7ffe8aea9c68 59 | #READ of size 8 at 0x60a60002bd58 thread T0 60 | # #0 0x7f187a7e4927 (/root/lib.so.2.40.2+0x47927) 61 | # #1 0x7f187a7e44fe (/root/lib.so.2.40.2+0x474fe) 62 | # #2 0x7f187a8062a4 (/root/lib.so.2.40.2+0x692a4) 63 | # 64 | #Example output: heap-buffer-overflow-2a4-4fe-927 65 | function parse_asan_trace { 66 | 67 | FILE=$1 68 | 69 | ERROR=$(grep 'ERROR: AddressSanitizer: ' $FILE) 70 | 71 | set -- $ERROR 72 | 73 | #ASAN-trace has two different beginnings depending on build: 74 | # 1. "====ERROR" 75 | # 2. "==== ERROR" 76 | #Extra whitespace messes up indexes. 77 | 78 | if grep -q 'ERROR' <<< $1; then 79 | ERROR=$3 80 | else 81 | ERROR=$4 82 | fi 83 | 84 | 85 | FRAME0=$(grep -oP '#0 0x\S+' $FILE | head -1) 86 | FRAME1=$(grep -oP '#1 0x\S+' $FILE | head -1) 87 | FRAME2=$(grep -oP '#2 0x\S+' $FILE | head -1) 88 | 89 | FRAME0=${FRAME0:(-3)} 90 | FRAME1=${FRAME1:(-3)} 91 | FRAME2=${FRAME2:(-3)} 92 | 93 | echo "$ERROR-$FRAME2-$FRAME1-$FRAME0" 94 | } 95 | 96 | #libFuzzer timeout-trace parser for instrumentation 97 | 98 | #Example trace: 99 | #==3833== ERROR: libFuzzer: timeout after 5 seconds 100 | # #0 0x4cc481 in __sanitizer_print_stack_trace /src/llvm/projects/compiler-rt/lib/asan/asan_stack.cc:38 101 | # #1 0x509a3a in fuzzer::Fuzzer::AlarmCallback() (/src/ImageMagick/ImageMagick_fuzzer+0x509a3a) 102 | # #2 0x5098ac in fuzzer::Fuzzer::StaticAlarmCallback() (/src/ImageMagick/ImageMagick_fuzzer+0x5098ac) 103 | # #3 0x528537 in fuzzer::AlarmHandler(int, siginfo_t*, void*) (/src/ImageMagick/ImageMagick_fuzzer+0x528537) 104 | # #4 0x7f6e55eb73cf (/lib/x86_64-linux-gnu/libpthread.so.0+0x113cf) 105 | # #5 0x522dc3 in __sanitizer_cov_trace_cmp (/src/ImageMagick/ImageMagick_fuzzer+0x522dc3) 106 | # #6 0x7f6e573bf8b9 in ReadBlobStream (/usr/lib/libMagickCore-7.Q16HDRI.so.0+0x2ea8b9) 107 | # #7 0x7f6e573d35ee in ReadBlobByte (/usr/lib/libMagickCore-7.Q16HDRI.so.0+0x2fe5ee) 108 | # #8 0x7f6e57c68e49 in ReadDPXImage (/usr/lib/libMagickCore-7.Q16HDRI.so.0+0xb93e49) 109 | # 110 | #Example output: timeout-5ee-e49 111 | function parse_timeout_trace { 112 | FILE=$1 113 | 114 | FINGERPRINT='timeout' 115 | 116 | #timeout-trace always has stack frames from instrumentation, we filter these out. 117 | #note: we cannot do this without symbolization 118 | FILE=$(cat $FILE| grep -v 'in fuzzer' | grep -v '__sanitizer' | grep -v 'libpthread') 119 | 120 | #Take first three frames and discard the first. 121 | #Timeout interrupts the current execution, so first valid frame can be with different 122 | #address even in same function. 123 | FRAMES=$(echo $FILE | grep -oP '#. 0x\S+' | head -3 | tail -2 | sed s/'#. '//g) 124 | 125 | for foo in $FRAMES; do 126 | FINGERPRINT="$FINGERPRINT-${foo:(-3)}" 127 | done 128 | 129 | echo "$FINGERPRINT" 130 | } 131 | 132 | # TODO: handle $TARGET env with a cleaner solution 133 | 134 | #TARGET_FULL=$1 135 | #TARGET=$(basename $1) 136 | echo "Target: $TARGET" 137 | 138 | export ASAN_SYMBOLIZER_PATH='/usr/lib/llvm-3.8/bin/llvm-symbolizer' 139 | #Fuzzers sometimes tries to allocate huge amounts of memory, when it does ASAN allocator fails. 140 | export ASAN_OPTIONS='allocator_may_return_null=1:detect_leaks=0:coverage=1:symbolize=1' 141 | 142 | while true; do 143 | echo "Round." 144 | $1 $rss_limit_mb $detect_leaks $exact_artifact_path $max_len $use_counters $max_total_time $samples 2>&1 | tee asan.txt 145 | if [ "$(grep "ERROR: AddressSanitizer" ./asan.txt)" ]; then 146 | RESULT=$(parse_asan_trace ./asan.txt) 147 | echo "New crash: "$TARGET-$RESULT 148 | cp ./asan.txt /results/$TARGET-$RESULT.txt && echo "Report saved: /results/$TARGET-$RESULT.txt" 149 | cp /dev/shm/repro-file /results/$TARGET-$RESULT.repro && echo "Repro-file saved: /results/$TARGET-$RESULT.repro" 150 | if [ "$MINIMIZE" == "true" ]; then 151 | nodejs /src/nipsu/nipsu.js -temp /dev/shm -i /dev/shm/repro-file -f /results/$TARGET-$RESULT-min.repro $TARGET_FULL @@ 152 | fi 153 | elif [ "$(grep "ERROR: libFuzzer: timeout" ./asan.txt)" ]; then 154 | RESULT=$(parse_timeout_trace ./asan.txt) 155 | echo "New timeout: "$TARGET-$RESULT 156 | cp ./asan.txt /results/$TARGET-$RESULT.txt && echo "Report saved: /results/$TARGET-$RESULT.txt" 157 | cp /dev/shm/repro-file /results/$TARGET-$RESULT.repro && echo "Repro-file saved: /results/$TARGET-$RESULT.repro" 158 | fi 159 | #TODO: Add dictionary collection. 160 | rm asan.txt 161 | done 162 | done 163 | -------------------------------------------------------------------------------- /doc/meeting-20160621.md: -------------------------------------------------------------------------------- 1 | * Imagejen päivittymis homma 2 | * base tarjotaan hubista 3 | * libfuzzer base ja stubs omat repot 4 | * stub repo: nimi, kansio juuressa docker filet 5 | 6 | Riittääkö yksi base jos laajennetaan monelle kielelle? 7 | aluksi pelkästään c:lle ja laajennetaan myöhemmin muille kielille? 8 | 9 | Käytetään docker hubia vai pitääkö se myöhemmin vaihtaa? 10 | * helppo: mennään docker hubilla 11 | 12 | Jani/Atte voi mainostaa twitterissä 13 | -------------------------------------------------------------------------------- /doc/meeting-20160715.md: -------------------------------------------------------------------------------- 1 | Meeting 15.7.2016 2 | 3 | Discussion about MVP 4 | 5 | libfuzzer-base documentation is tells howto run in native 6 | we dont support how to use libfuzzer natively -> use libfuzzer-base 7 | quality of libfuzzer-base is important! 8 | use ubuntu in base image, no need to change 9 | 10 | run: 11 | -docker (we document libfuzzer only in docker, not in native) 12 | --own engine 13 | --cloud engine 14 | 15 | Corpus pool: 16 | -no feedback 17 | 18 | results: 19 | - log file 20 | - documentation how to get results from log files 21 | 22 | -corpus: 23 | -we are going to use bundled corpus 24 | 25 | scale: 26 | -1 instance : 1 target 27 | 28 | -stubs: 29 | -libav is broken 30 | -policies, packaging documentation, build documentation, run documentation 31 | -stubs can also be used by other fuzzers 32 | -main product are stubs 33 | -Important: how to build and run a stub! prio high 34 | -no need to change directory structure or file locations 35 | 36 | cloud 37 | -For scaling 38 | - documentation! 39 | 40 | docker-compose: 41 | -rss_limit_mb=4096' not needed in docker-compose? 42 | -default values for fuzz.sh that can be overrided 43 | 44 | docker base image: 45 | RUN chmod +x /src/scripts/fuzz.sh not needed, 46 | chmod a+x fuzz.sh 47 | 48 | corpus, samples in documentation when to use which 49 | 50 | mikko creates initial corpus, small, use lfs 51 | 52 | corpus cloud project gets started 53 | 54 | mikko takes care of bundled corpus 55 | 56 | split project between corpus and libfuzzer 57 | -------------------------------------------------------------------------------- /doc/pictures/fuzzing-lua.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/fuzzing-lua.gif -------------------------------------------------------------------------------- /doc/pictures/infra-plan-fenris-20160705.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/infra-plan-fenris-20160705.jpg -------------------------------------------------------------------------------- /doc/pictures/infra-plan-wed-20160705.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/infra-plan-wed-20160705.jpg -------------------------------------------------------------------------------- /doc/pictures/infra-workflow-20160621.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/infra-workflow-20160621.jpg -------------------------------------------------------------------------------- /doc/pictures/mvp-plan-20160715.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/mvp-plan-20160715.jpg -------------------------------------------------------------------------------- /doc/pictures/popularisation-planning-20160809.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/popularisation-planning-20160809.jpg -------------------------------------------------------------------------------- /doc/pictures/project-plan-20160614.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/doc/pictures/project-plan-20160614.jpg -------------------------------------------------------------------------------- /doc/presentation-mikkoyli-libfuzzerfication-20160823.md: -------------------------------------------------------------------------------- 1 | class: center, middle 2 | 3 | ## LibFuzzerfication - fuzzing for the rest of us 4 | ## 2016-08-23 5 | 6 | --- 7 | Purpose of libFuzzerfication is to do fuzz-testing for applications and libraries to see if new vulnerabilities are found. 8 | 9 | Fuzzing in action 10 | 11 | Example of fuzz test running. 12 | 13 | --- 14 | # Why? 15 | 16 | * We wanted to do some fuzz testing for popular libraries. 17 | * Purpose was to create a social startup. We wanted to increase awareness about situation. 18 | * Purpose was that people could easily run libfuzzer on their own computer or cloud 19 | 20 | --- 21 | 22 | # When? 23 | 24 | * I was working as a summer trainee for 3 month in ouspg 25 | * Compulsory training that is part of my studies 26 | --- 27 | 28 | # Who? 29 | 30 | * I was responsible for the project but had a lot of help from others. Atte Kettunen worked as specialist and participated mostly at the early summer. 31 | * Also other people contributed. 32 | 33 | List of contributors: 34 | * Atte Kettunen (@attekett) 35 | * Mikko Yliniemi (@mikessu) 36 | * Ossi Herrala (@oherrala) 37 | * Jani Kenttälä (@evilon) 38 | * Marko Laakso (@ikisusi) 39 | * Pauli Huttunen (@WhiteEyeDoll) 40 | * Joonas Kuorilehto (@joneskoo) 41 | * Ari Kauppi (@arikauppi) 42 | 43 | --- 44 | 45 | # About libfuzzer 46 | * LibFuzzer is open-source library (part of LLVM) 47 | * It is similiar to AFL (American Fuzzy LOP) 48 | * Works inside process (function) -> faster 49 | * libFuzzer itself is compiled without any specific flags 50 | * Target is compiled with fresh clang using MSan, ASan or USan 51 | 52 | --- 53 | 54 | # Stubs 55 | 56 | We have following stubs: 57 | * ImageMagick 58 | * haskell-x509 59 | * libmad 60 | * libxml2 61 | * libxslt 62 | * lua 63 | * mysamplelib 64 | * zlib 65 | * rust [WIP] 66 | 67 | --- 68 | 69 | # How? 70 | 71 | * We used docker to automate the deployment of applications inside software containers. 72 | * We have dockerfile for every fuzzer 73 | * Image can be built from dockerfile 74 | * Container can be run from image 75 | --- 76 | # Findings 77 | 78 | * We fuzzed ImageMagick and found use after free 79 | * libxml and others were also fuzzed but nothing special was found (these are already heavily fuzzed) 80 | * Purpose is to fuzz rust also 81 | --- 82 | # More info 83 | 84 | https://github.com/ouspg/libfuzzerfication 85 | 86 | --- 87 | -------------------------------------------------------------------------------- /doc/presentation-mikkoyli-libfuzzerfication-updates-20160705.md: -------------------------------------------------------------------------------- 1 | class: center, middle 2 | 3 | ## LibFuzzerfication updates 4 | ## OUSPG Open, 2016-07-05 5 | 6 | --- 7 | 8 | # Team 9 | 10 | * Mikko Yliniemi (@mikessu) 11 | * Atte Kettunen (@attekett) 12 | * Pauli Huttunen (@WhiteEyeDoll) 13 | 14 | --- 15 | Purpose of libFuzzerfication is to do fuzz-testing for applications and libraries. 16 | 17 | Fuzzing in action 18 | 19 | Example of lua fuzz test running. 20 | 21 | --- 22 | # Motivation 23 | There have been lots of vulnerabilities in popular libraries that should have been (theoretically) easy to test. We want to offer easy way to fuzz-test these libraries and increase awareness about the situation. We also want this to be available to everyone. 24 | 25 | --- 26 | 27 | # About libfuzzer 28 | * LibFuzzer is open-source library (part of LLVM) 29 | * Relies on compiler instrumentation to get coverage feedback 30 | * It is linked with the library under test 31 | * Works fully inside the running program (a process) -> Fast! 32 | 33 | --- 34 | 35 | # What we have done this far? 36 | 37 | * We have currently following stubs in repository: 38 | - haskell-x509 (@oherrala) 39 | - ImageMagick (@attekett) 40 | - libav (@mikessu) 41 | - libxml2 (@attekett) 42 | 43 | # After last session: 44 | 45 | * Lua stub was committed by Joonas Kuorilehto (@joneskoo) 46 | * libxslt stub was committed by Ari Kauppi (@kauppi) 47 | 48 | --- 49 | # Docker base image 50 | 51 | * This project is using docker 52 | * We are using ubuntu:16.04 as base image 53 | * libFuzzer is included in base image 54 | * Nipsu minimizer is also included in base image (Crash repro minifier for ASan-instrumented commandline tools.) 55 | * Fuzz.sh script is used as entrypoint, it takes care of running fuzz tests and gathering results 56 | 57 | (show libfuzzer-base dockerfile) 58 | 59 | --- 60 | # Docker images for stubs 61 | 62 | * Every stub has its own dockerfile 63 | * Images are created from dockerfiles 64 | * Containers are run to do the testing 65 | 66 | (show example stub dockerfile for libav) 67 | 68 | --- 69 | 70 | # Under development 71 | * libflac stub is currently under development 72 | * Make fuzzing in container to run as non root user 73 | * Pauli (@WhiteEyeDoll) is currently working to get fuzzing running in Google cloud 74 | 75 | * Get the minimized samplesets to the cloud platform for distribution to masses 76 | * Automatic p2p container node with deluge to save in bandwith costs (the sets are from few gigs to over 100 gigs in size) 77 | * Create kubernetes pod files for different fuzzers to automate scaled fuzzing of a desired target 78 | * Easily scale from a few pods to hunderds of containers doing efficient fuzzing and generating new corpus quickly 79 | 80 | 81 | --- 82 | 83 | # Documentation 84 | 85 | We are working to make participating this project easy. Documentation is being written and improved all the time. You can find documentation from github. We are trying to make it easy to get started with libFuzzer. 86 | 87 | https://github.com/ouspg/libfuzzerfication 88 | 89 | --- 90 | 91 | # Feel free to contribute 92 | * Everyone can contribute 93 | 94 | # How does this project work? 95 | * You pull container from Dockerhub 96 | * Start Writing your own libfuzzer stub 97 | * Share dockerfile with other users 98 | * Use libFuzzer to collect corpus so that other people can continue where you left off 99 | 100 | You can start writing stubs without docker. 101 | 102 | Visit #ouspg @ IRCnet if you're interested! 103 | 104 | --- 105 | -------------------------------------------------------------------------------- /doc/presentation-oherrala-fuzzing-beyond-c.md: -------------------------------------------------------------------------------- 1 | class: center, middle 2 | 3 | # Fuzzing beyond C 4 | 5 | ## Advanced Fuzzing Workshop 6 | ## OUSPG Open, 2016-06-28 7 | 8 | --- 9 | 10 | # Self promotion 11 | 12 | * Ossi Herrala (@oherrala) 13 | * https://github.com/oherrala 14 | * Codenomicon / Synopsys / AbuseSA 15 | * Defensics fuzzers (IPv4, TLS, NFS, MPEG4, …) 16 | * Sysadmin 17 | * Bachelor's thesis work as part of OUSPG Open 18 | * this fuzzing thingie is not that thesis… 19 | 20 | --- 21 | 22 | # Agenda 23 | 24 | 1. Motivation 25 | 2. Haskell 26 | 3. Sample stub 27 | 4. Build it 28 | 5. Instrumentation 29 | 6. Example: X.509 "Exception is error" 30 | 31 | ## Feel free to ask at any time 32 | 33 | --- 34 | 35 | # Motivation 36 | 37 | ### Fuzz libs of your favorite lang! 38 | 39 | * Software has bugs. Break the myth that *hype-of-the-month-language* 40 | will lead to safer world because it eliminates all the bugs. 41 | * Learn how your favorite language and libs behave under pressure. 42 | * Fast and cost effective way to do negative testing. 43 | * Libfuzzer is easy to automate 44 | * Include some fuzzing into Continous Integration. 45 | 46 | --- 47 | 48 | # Motivation 49 | 50 | ### Some languages with LLVM backends: 51 | 52 | ActionScript, Ada, C#, Common Lisp, Crystal, D, Delphi, Fortran, 53 | OpenGL Shading Language, Halide, **Haskell**, Java bytecode, Julia, 54 | Lua, Objective-C, Pony, Python, R, Ruby, Rust, Scala, Swift 55 | 56 | Source: https://en.wikipedia.org/wiki/LLVM 57 | 58 | ### Compiles via C 59 | 60 | * Some languages provide compiler into C. 61 | * This C could be compiled with LLVM. 62 | 63 | --- 64 | 65 | # Haskell 66 | 67 | *standardized, general-purpose purely functional programming language, with non-strict semantics and strong static typing* 68 | 69 | * Standardized: There's specification how language works 70 | * General purpose: *a computer language that is broadly applicable across application domains (not DSL)* 71 | * Purely functional: *One typical approach to achieve this is by excluding destructive modifications (updates)* 72 | * Non-strict semantics: Aka lazy evaluation (infinite lists and recursions are ok) 73 | * Static typing: Type safety at compile time 74 | * Strong typing: `True == 1`, `"1" + 1` and `print 42` are all compile time errors 75 | 76 | Source: Wikipedia 77 | 78 | --- 79 | 80 | # Sample stub in C 81 | 82 | ```C 83 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 84 | DoSomethingInterestingWithMyAPI(Data, Size); 85 | return 0; // Non-zero return values are reserved for future use. 86 | } 87 | ``` 88 | 89 | Source: http://llvm.org/docs/LibFuzzer.html 90 | 91 | --- 92 | 93 | # Haskell approach to libfuzzer stub 94 | 95 | * Use Haskell's FFI (foreign function interface) 96 | * Export Haskell function via FFI (using C Calling Convention) 97 | * Minimal layer of C to initialize Haskell runtime 98 | * Compilation produces object file (test.o) which can be linked with libfuzzer 99 | * Alter Haskell packaging tools to enable SanitizerCoverage 100 | 101 | Same approach could be used for other languages. 102 | 103 | --- 104 | 105 | # Sample stub in Haskell 106 | 107 | ```haskell 108 | -- Export function via FFI: 109 | -- testOneInputM (in Haskell) to LLVMFuzzerTestOneInput() (in C) 110 | foreign export ccall "LLVMFuzzerTestOneInput" testOneInputM 111 | :: CString -> CSize -> IO CInt 112 | 113 | testOneInputM :: CString -> CSize -> IO CInt 114 | testOneInputM str size = do 115 | 116 | -- Convert C String into Haskell bytes (bytestring) 117 | bs <- BS.packCStringLen (str, fromIntegral size) 118 | 119 | -- Many decode functions want bytestring 120 | doSomethingInterestingWithMyAPI bs 121 | 122 | -- Non-zero return values are reserved for future use. 123 | return 0 124 | ``` 125 | 126 | C stub for comparison: 127 | 128 | ```C 129 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 130 | DoSomethingInterestingWithMyAPI(Data, Size); 131 | return 0; // Non-zero return values are reserved for future use. 132 | } 133 | ``` 134 | 135 | --- 136 | 137 | # Sample stub (with boilerplate) 138 | 139 | ```haskell 140 | {-# LANGUAGE ForeignFunctionInterface #-} 141 | 142 | module Test where 143 | 144 | import Foreign.C.Types 145 | import Foreign.C.String 146 | import qualified Data.ByteString as BS 147 | 148 | foreign export ccall "LLVMFuzzerTestOneInput" testOneInputM 149 | :: CString -> CSize -> IO CInt 150 | 151 | testOneInputM :: CString -> CSize -> IO CInt 152 | testOneInputM str size = do 153 | bs <- BS.packCStringLen (str, fromIntegral size) 154 | doSomethingInterestingWithMyAPI bs 155 | return 0 156 | ``` 157 | 158 | --- 159 | 160 | # Initialize Haskell Runtime (in 6 lines of C) 161 | 162 | ```c 163 | #include "HsFFI.h" 164 | 165 | int LLVMFuzzerInitialize(int *argc, char ***argv) { 166 | hs_init(argc, argv); 167 | return 0; 168 | } 169 | ``` 170 | 171 | *The call to hs_init() initializes GHC's runtime system. Do NOT try 172 | to invoke any Haskell functions before calling hs_init(): bad things 173 | will undoubtedly happen.* 174 | 175 | Source: https://downloads.haskell.org/~ghc/7.0.2/docs/html/users_guide/ffi-ghc.html 176 | 177 | 178 | --- 179 | 180 | # GHC with LLVM/clang build stack 181 | 182 | 1. Haskell compiler (GHC) 183 | 2. C compiler (clang + SanitizerCoverage) 184 | 3. Assembler (clang) 185 | 4. LLVM Optimizer (LLVM) 186 | 5. LLVM Compiler (LLVM) 187 | 6. LLVM Mangler (GHC) 188 | 7. Assembler (clang) 189 | 8. Linker (clang + SanitizerCoverage) 190 | 191 | 192 | --- 193 | 194 | # Build it 195 | 196 | ```sh 197 | #!/bin/sh 198 | set -ex 199 | 200 | GHCOPTS="-package libfuzzer" 201 | 202 | clang -Wall -c -I/opt/ghc/8.0.1/lib/ghc-8.0.1/include/ hsinit.c 203 | ghc-asan ${GHCOPTS} -c test.hs 204 | ghc-wrapper ${GHCOPTS} -no-hs-main -lFuzzer -o test test.o hsinit.o 205 | ``` 206 | 207 | Note: 208 | * `-package libfuzzer` is my Haskell utils 209 | * `-lFuzzer` is the LLVM's libFuzzer lib 210 | 211 | --- 212 | 213 | ## ghc-wrapper 214 | ```sh 215 | ghc \ 216 | -threaded \ 217 | -fforce-recomp \ 218 | -fllvm \ # Use LLVM backend 219 | -pgmP=clang \ # C preprocessor 220 | -pgmc=clang \ # C compiler 221 | -pgma=clang \ # Assembler 222 | -pgml=clang++ \ # Linker 223 | $* 224 | ``` 225 | 226 | ## ghc-asan 227 | ```sh 228 | ghc-wrapper \ 229 | -optc="-g" -optl="-g" \ 230 | -optc="-fsanitize=address" \ 231 | -optc="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" \ 232 | -optl="-fsanitize=address" \ 233 | -optl="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" \ 234 | $* 235 | ``` 236 | 237 | --- 238 | 239 | # Cabal (Haskell's build tool) 240 | 241 | `$HOME/.cabal/config`: 242 | 243 | ``` 244 | program-default-options 245 | gcc-options: -g \ 246 | -fsanitize=address \ 247 | -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp 248 | ghc-options: -fllvm \ 249 | -optc="-fsanitize=address" \ 250 | -optc="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" \ 251 | -optl="-fsanitize=address" \ 252 | -optl="-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 253 | ``` 254 | 255 | With this we can install (any) Haskell library and it's depends with 256 | SanitizerCoverage. 257 | 258 | --- 259 | 260 | # Instrumentation 261 | 262 | ## did it break or did it behave well? 263 | 264 | * Crashes (the real ones) 265 | * "Crashes" (runtime handled things smoothly and exited program) 266 | * Exceptions (produces "crashes". can be caught and handled) 267 | * For example when function returns errors as sum type 268 | * Other? 269 | 270 | *''The program is then monitored for exceptions such as crashes, or 271 | failing built-in code assertions or for finding potential memory 272 | leaks.''* 273 | 274 | Source: Wikipedia 275 | 276 | --- 277 | 278 | # Exception is error 279 | 280 | ``` 281 | Ok, modules loaded: none. 282 | Prelude> :set -XOverloadedStrings 283 | Prelude> import Data.X509 284 | 285 | Prelude Data.X509> :t Data.X509.decodeSignedCertificate 286 | Data.X509.decodeSignedCertificate 287 | :: Data.ByteString.Internal.ByteString 288 | -> Either String SignedCertificate 289 | ``` 290 | 291 | This is how it should work: 292 | ``` 293 | Prelude Data.X509> Data.X509.decodeSignedCertificate "hello world" 294 | Left "ParsingPartial" 295 | ``` 296 | 297 | This is wrong behavior: 298 | ``` 299 | Prelude Data.X509> Data.X509.decodeSignedCertificate "\DLE;\217:\131'';\189:!&6!!Ly\222(\167ri'\186;)(U\240:;:})*:t;\226(;::\189:\239')\ENQ,)(*3\248V)$\FS*\169" 300 | *** Exception: sequence not a primitive 301 | ``` 302 | 303 | --- 304 | 305 | # "Exception is error" instrumentation 306 | 307 | ```haskell 308 | decode :: BS.ByteString 309 | -> IO (Either SomeException (Either String X509.SignedCertificate)) 310 | decode = try . evaluate . X509.decodeSignedCertificate 311 | 312 | testOneInputM :: CString -> CSize -> IO CInt 313 | testOneInputM str size = do 314 | bs <- BS.packCStringLen (str, fromIntegral size) 315 | 316 | result <- decode bs 317 | case result of 318 | Right _ -> return () 319 | Left err -> do 320 | let err' = show err 321 | putStrLn $ "Exception: " ++ err' 322 | storeTestCase err' bs 323 | 324 | return 0 325 | ``` 326 | 327 | --- 328 | 329 | # 1M test cases for X.509 lib 330 | 331 | ### "Exception is error" instrumentation 332 | 333 | * `time ./test -runs=1000000` 334 | * `real 0m3.682s user 0m3.250s sys 0m0.480s` 335 | * ~270k cases/sec 336 | * Results: 337 | ``` 338 | error, called at ./Data/ASN1/Prim.hs:172:54 in asn1-encoding-0.9.4-G3Eu427lfih60n7Hu41ILm:Data.ASN1.Prim 339 | error, called at ./Data/ASN1/Serialize.hs:40:24 in asn1-encoding-0.9.4-G3Eu427lfih60n7Hu41ILm:Data.ASN1.Serialize 340 | (6 times) StreamUnexpectedSituation "Header (ASN1Header ...)" 341 | TypeDecodingFailed "Null: data length not within bound" 342 | TypeDecodingFailed "bitstring: skip number not within bound 42 "" 343 | TypeDecodingFailed "boolean: length not within bound" 344 | TypeDecodingFailed "time format invalid for TimeGeneralized : contains non ASCII characters" 345 | TypeDecodingFailed "time format invalid for TimeUTC : contains non ASCII characters" 346 | TypeNotImplemented "EMBEDDED PDV" 347 | TypeNotImplemented "External" 348 | TypeNotImplemented "Object Descriptor" 349 | TypeNotImplemented "RELATIVE-OID" 350 | TypeNotImplemented "real" 351 | not canonical encoding of tag 352 | sequence not a primitive 353 | ``` 354 | 355 | --- 356 | 357 | # Pros and cons of libfuzzer 358 | 359 | * Can be used with other languages than C/C++ 360 | * Blazing fast apparently 361 | * Setup once, run forever 362 | * Depending on instrumentation we miss some features 363 | * "Exception is error" example is probably "doing it wrong" 364 | 365 | --- 366 | 367 | # Summary 368 | 369 | * It is possible to fuzz beyond C 370 | * It can produce results 371 | * Is libfuzzer The Right Tool? 372 | 373 | ## Challenges 374 | 375 | * Instrumentation 376 | * Compiling 377 | 378 | ## Sources 379 | 380 | * https://github.com/ouspg/libfuzzerfication/ 381 | 382 | 383 | --- 384 | 385 | class: center, middle 386 | 387 | # Fuzzing beyond C 388 | 389 | ### Advanced Fuzzing Workshop 390 | ### OUSPG Open, 2016-06-28 391 | 392 | # Questions ? 393 | -------------------------------------------------------------------------------- /doc/presentation-stub-writing.md: -------------------------------------------------------------------------------- 1 | class: center, middle 2 | 3 | ## LibFuzzerfication stubs 4 | ## OUSPG Open, 2016-07-12 5 | 6 | --- 7 | 8 | # Introduction 9 | Purpose of libFuzzerfication is to do fuzz-testing for applications and libraries. Today we are going to write some libFuzzer stubs for libFuzzerfication. 10 | 11 | Fuzzing is to automatically generate lots of test input to crash your code and to increase code coverage. 12 | Some important terms: 13 | 14 | Target: 15 | - A function that consumes array of bytes and does something non trivial to them. 16 | 17 | Fuzzer engine 18 | - A tool that needs a fuzz target with different random inputs 19 | 20 | Corpus 21 | - A set on inputs that are either valid or invalid. 22 | - Collected manually or by fuzzing or by crawling from web 23 | - Can be minimized (to have only files with different code coverage) 24 | 25 | --- 26 | # Motivation 27 | There have been lots of vulnerabilities in popular libraries that should have been (theoretically) easy to test. We want to offer easy way to fuzz-test these libraries and increase awareness about the situation. We also want this to be available to everyone. 28 | 29 | --- 30 | 31 | # About libfuzzer 32 | * LibFuzzer is open-source library (part of LLVM) 33 | * Relies on compiler instrumentation to get coverage feedback 34 | * It is linked with the library under test 35 | * Works fully inside the running program (a process) -> Fast! 36 | 37 | --- 38 | 39 | # How to get started writing stubs? 40 | You need: 41 | - Docker 42 | - Clang, libFuzzer (included in libfuzzer-base image) 43 | 44 | List of targets to fuzz: 45 | - https://docs.google.com/spreadsheets/d/1oj0L44gKTn3wlrJk6b554b9o8H0r1bVfb6LJrw62BEE/pubhtml 46 | 47 | --- 48 | # How to get started writing stubs? 49 | 50 | First clone the repo: 51 | ``` 52 | git clone https://github.com/ouspg/libfuzzerfication.git 53 | ``` 54 | 55 | Second step is to build base image. Go to libfuzzerfication/docker directory and write: 56 | ``` 57 | # docker-compose build libfuzzer-base 58 | ``` 59 | Or alternatively pull the ready to go automagically built image from dockerhub: 60 | ``` 61 | # docker pull ouspg/libfuzzer-base 62 | ``` 63 | 64 | Then you can start developing: 65 | ``` 66 | # docker run -it --rm -v : --entrypoint bash 67 | ``` 68 | 69 | --- 70 | 71 | Then you can implement a fuzzing target function that accepts a sequence of bytes, like this: 72 | 73 | ``` 74 | // libxml2-fuzzer.cc 75 | #include "libxml/parser.h" 76 | void ignore(void *ctx, const char *msg, ...) { 77 | // Error handler to avoid spam of error messages from libxml parser. 78 | } 79 | extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { 80 | xmlSetGenericErrorFunc(NULL, &ignore); 81 | auto doc = xmlReadMemory(reinterpret_cast(data), size, "noname.xml", NULL, 0); 82 | //if (doc) { 83 | xmlFreeDoc(doc); 84 | xmlCleanupParser(); 85 | //} 86 | return 0; 87 | } 88 | ``` 89 | 90 | LibFuzzer is already installed in base image. 91 | (Show build.sh and Dockerfile, show example) 92 | 93 | --- 94 | 95 | libFuzzer output looks like this: 96 | 97 | ``` 98 | INFO: Seed: 219835401 99 | #0 READ units: 202 exec/s: 0 100 | #202 INITED cov: 2610 indir: 22 units: 145 exec/s: 0 101 | #928 NEW cov: 2611 indir: 22 units: 146 exec/s: 0 L: 19 MS: 1 ChangeBit- 102 | #1859 NEW cov: 2615 indir: 22 units: 147 exec/s: 1859 L: 11 MS: 2 ChangeASCIIInt-CrossOver- 103 | #4096 pulse cov: 2615 indir: 22 units: 147 exec/s: 2048 104 | #4964 NEW cov: 2616 indir: 22 units: 148 exec/s: 2482 L: 19 MS: 2 ChangeBit-ChangeASCIIInt- 105 | #5599 NEW cov: 2617 indir: 22 units: 149 exec/s: 1866 L: 23 MS: 2 ShuffleBytes-CrossOver- 106 | #5673 NEW cov: 2618 indir: 22 units: 150 exec/s: 1891 L: 31 MS: 1 CrossOver- 107 | #5699 NEW cov: 2628 indir: 22 units: 151 exec/s: 1899 L: 15 MS: 2 EraseByte-CrossOver- 108 | #5809 NEW cov: 2639 indir: 22 units: 152 exec/s: 1936 L: 210 MS: 2 ChangeBit-CrossOver- 109 | #7596 NEW cov: 2640 indir: 22 units: 153 exec/s: 1899 L: 186 MS: 4 110 | ``` 111 | 112 | The NEW line appears when libFuzzer finds new interesting input. 113 | 114 | The pulse line shows current status and appears periodically 115 | 116 | --- 117 | -------------------------------------------------------------------------------- /doc/protecode-sc-top-components-20160609.txt: -------------------------------------------------------------------------------- 1 | - From Protecode SC managed service 2016-06-09 - Only relevant in the context of source material, and is not a generic list of most popular components in the world as a whole - If a component is included multiple times in an application, it's only counted once here - Duplicate applications are not removed - List is sorted by count with most common component on top zlib openssl libpng libjpeg sqlite3 expat bgaes android-support linux_kernel libxml2 pcre curl freetype libjpeg-turbo commons-codec icu gettext gson commons-logging jackson bzip2 libtiff commons-lang asm busybox libvorbis google-play-services libxslt iproute2 boost commons-io effective_tld_names slf4j glib webkit actionbarsherlock httpcomponents-client libicu bouncycastle guava google-analytics glibc lua xerces-j httpcomponents-mime iptables xalan jaf libpcap python -------------------------------------------------------------------------------- /doc/protecode-sc-top-components-native-20160609.txt: -------------------------------------------------------------------------------- 1 | zlib* openssl* libpng* libjpeg* sqlite3* expat* bgaes linux_kernel libxml2* pcre* curl freetype* libjpeg-turbo* icu* gettext bzip2* libtiff* busybox libvorbis* libxslt iproute2 boost effective_tld_names glib webkit* libicu glibc* lua iptables libpcap opus* libvpx* portable_runtime_api python ncurses protobuf qt libiconv popt speex tdb ppp javascriptcore readline libflac openldap dash gstreamer e2fsprogs jre *) Already heavily fuzzed by someone else. -------------------------------------------------------------------------------- /doc/screencast.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * v0.1 [Just the cut](https://youtu.be/otzPyUhWzlI) 4 | * v0.2 [Texts & zooms](https://youtu.be/B46AMry7lHs) 5 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | ## Build: docker-compose build 4 | ## Run: docker-compose run 5 | 6 | ## Note: Change volumes and command to match your system. 7 | 8 | services: 9 | 10 | ## libfuzzer base image 11 | 12 | libfuzzer-base: 13 | build: ./base/libfuzzer-base 14 | image: ouspg/libfuzzer-base 15 | 16 | ## ImageMagick stub, with automatic crash-repro minimizer 17 | 18 | ImageMagick: 19 | build: ./stubs/ImageMagick 20 | image: ouspg/libfuzzer-imagemagick 21 | #volumes: 22 | #- ~/results/:/srv/fuzzer/results/ 23 | #- ~/samples/:/srv/fuzzer/samples/ 24 | mem_limit: 4g 25 | shm_size: 512M 26 | environment: 27 | MINIMIZE: "true" 28 | entrypoint: '/src/scripts/fuzz.sh' 29 | command: [ 30 | '/src/ImageMagick/ImageMagick-fuzzer', 31 | ] 32 | 33 | ## libxml2 stub 34 | 35 | libxml2: 36 | build: ./stubs/libxml2 37 | image: ouspg/libfuzzer-libxml2 38 | shm_size: 512M 39 | mem_limit: 4g 40 | #volumes: 41 | #- ~/results/:/srv/fuzzer/results/ 42 | #- ~/samples/:/srv/fuzzer/samples/ 43 | environment: 44 | LD_LIBRARY_PATH: "/src/libxml2/.libs/" 45 | command: [ 46 | '/src/libxml2/libxml2-fuzzer', 47 | '-max_len=5000', 48 | '-max_total_time=600', 49 | '/samples/' 50 | ] 51 | 52 | ## libxslt 53 | 54 | libxslt: 55 | build: ./stubs/libxslt 56 | image: ouspg/libfuzzer-libxslt 57 | shm_size: 512M 58 | mem_limit: 4g 59 | #volumes: 60 | #- ~/results/:/srv/fuzzer/results/ 61 | #- ~/samples/:/srv/fuzzer/samples/ 62 | environment: 63 | LD_LIBRARY_PATH: "/src/libxslt/libxslt/.libs/" 64 | command: [ 65 | '/src/libxslt/libxslt-fuzzer' 66 | ] 67 | 68 | ## lua stub 69 | 70 | lua: 71 | build: ./stubs/lua 72 | image: ouspg/libfuzzer-lua 73 | #volumes: 74 | #- ~/results/:/srv/fuzzer/results/ 75 | #- ~/samples/:/srv/fuzzer/samples/ 76 | mem_limit: 4g 77 | shm_size: 512M 78 | entrypoint: '/src/scripts/fuzz.sh' 79 | command: [ 80 | '/lua-fuzzer', 81 | '-timeout=5' 82 | ] 83 | 84 | ## libmad stub 85 | 86 | libmad: 87 | build: ./stubs/libmad 88 | image: ouspg/libfuzzer-libmad 89 | #volumes: 90 | #- ~/results/:/srv/fuzzer/results/ 91 | #- ~/samples/:/srv/fuzzer/samples/ 92 | mem_limit: 4g 93 | shm_size: 512M 94 | entrypoint: '/src/scripts/fuzz.sh' 95 | command: [ 96 | '/src/libmad-0.15.1b/libmad-fuzzer', 97 | '/samples/' 98 | ] 99 | 100 | ## zlib stub 101 | 102 | zlib: 103 | build: ./stubs/zlib 104 | image: ouspg/libfuzzer-zlib 105 | #volumes: 106 | #- ~/results/:/srv/fuzzer/results/ 107 | #- ~/samples/:/srv/fuzzer/samples/ 108 | mem_limit: 4g 109 | shm_size: 512M 110 | entrypoint: '/src/scripts/fuzz.sh' 111 | command: [ 112 | '/src/zlib/zlib-fuzzer', 113 | ] 114 | 115 | ## Haskell base image 116 | 117 | libfuzzer-base-haskell: 118 | build: ./base/libfuzzer-base-haskell 119 | image: ouspg/libfuzzer-base-haskell 120 | 121 | ## Haskell stub 122 | 123 | haskell-x509: 124 | build: ./stubs/haskell-x509 125 | image: ouspg/libfuzzer-haskell-x509 126 | -------------------------------------------------------------------------------- /stubs/ImageMagick/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "ImageMagick" 6 | 7 | # Install dependencies and fetch the source. 8 | 9 | RUN apt-get update && \ 10 | apt-get upgrade -y && \ 11 | apt-get build-dep imagemagick -y && \ 12 | apt-get install libiomp5 libiomp-dev -y && \ 13 | apt-get autoremove -y && \ 14 | apt-get clean && \ 15 | rm -rf /var/lib/apt/lists/* 16 | 17 | RUN cd /src && git clone https://github.com/ImageMagick/ImageMagick.git 18 | 19 | ADD ImageMagick-fuzzer.c /src/ImageMagick/ 20 | RUN mkdir -p /work/ImageMagick/ 21 | 22 | ADD samples.tar.gz / 23 | 24 | # Build 25 | 26 | ADD build.sh /src/scripts/ 27 | RUN bash /src/scripts/build.sh 28 | -------------------------------------------------------------------------------- /stubs/ImageMagick/ImageMagick-fuzzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "MagickCore/MagickCore.h" 5 | 6 | /* 7 | *We use BlobToImage to load input as an image, if successful destroy image. 8 | */ 9 | 10 | extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { 11 | Image *image; 12 | ImageInfo image_info; 13 | ExceptionInfo *exception; 14 | 15 | GetImageInfo(&image_info); 16 | exception = AcquireExceptionInfo(); 17 | 18 | image = BlobToImage(&image_info, data, size, exception); 19 | 20 | if (exception->severity != UndefinedException) { 21 | //CatchException(exception); 22 | } 23 | 24 | if (image != (Image *) NULL) { 25 | DestroyImage(image); 26 | } 27 | 28 | DestroyExceptionInfo(exception); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /stubs/ImageMagick/README.md: -------------------------------------------------------------------------------- 1 | # ImageMagick 2 | 3 | # Purpose 4 | 5 | ImageMagick is a software suite to create, edit, compose, or convert bitmap images. In the stub we use BlobToImage to load input as an image and if successful then destroy the image. 6 | 7 | What is included? 8 | 9 | * [`ImageMagick-fuzzer.c`](ImageMagick-fuzzer.c)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | * [`Samples`](samples.tar.gz) to provide sample files to get started with 13 | 14 | # Building 15 | 16 | ## Building container 17 | 18 | ```console 19 | docker-compose build ImageMagick 20 | ``` 21 | 22 | # Running 23 | 24 | ## Starting the container 25 | 26 | ```console 27 | docker-compose run ImageMagick 28 | ``` 29 | 30 | # Samples 31 | 32 | samples.tar.gz contains sample files from [imagetestsuite](https://code.google.com/archive/p/imagetestsuite/). 33 | -------------------------------------------------------------------------------- /stubs/ImageMagick/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CXXFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 4 | export CXX="clang++" 5 | export CFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 6 | export CC="clang" 7 | export LDFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 8 | 9 | #Build ImageMagick 10 | 11 | cd /src/ImageMagick 12 | ./configure --prefix=/usr/ --without-magick-plus-plus --without-perl --without-threads --without-tiff --with-gslib=no --without-dps 13 | make -j4 14 | make install 15 | 16 | 17 | #Build fuzzer 18 | 19 | $CXX $CFLAGS -std=c++11 -I$(pwd) /usr/lib/libMagick*.so -lxml2 -lm -lpthread -lz -lX11 -lfontconfig \ 20 | -lfreetype -llzma -fopenmp -lpng -ltiff -lXext -lrt -ljbig -ljpeg -lcairo -lpango-1.0 \ 21 | -lgobject-2.0 -lbz2 -lpangocairo-1.0 -llcms2 -llqr-1 -lfftw3 -lltdl \ 22 | -lFuzzer -o ImageMagick-fuzzer ImageMagick-fuzzer.c 23 | 24 | #Ghostcript is annoying 25 | 26 | apt-get remove ghostscript -y 27 | -------------------------------------------------------------------------------- /stubs/ImageMagick/license-samples: -------------------------------------------------------------------------------- 1 | License: GNU GPL v2 2 | Content License: Creative Commons 3.0 BY 3 | https://code.google.com/archive/p/imagetestsuite/ 4 | 5 | -------------------------------------------------------------------------------- /stubs/ImageMagick/samples.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/stubs/ImageMagick/samples.tar.gz -------------------------------------------------------------------------------- /stubs/README.md: -------------------------------------------------------------------------------- 1 | # libFuzzerfication stubs 2 | 3 | # About 4 | 5 | What is included in directories? 6 | 7 | Each directory consists of at least following files: 8 | 9 | * fuzzer -stub to act as the interface between the `libfuzzer` and the test target 10 | * build.sh - script to build the library, and the stub and to link them with the fuzzer 11 | * Dockerfile - to build Docker image 12 | 13 | 14 | # Building 15 | 16 | Base image can be pulled from Dockerhub to avoid building locally. 17 | 18 | ```console 19 | $ docker pull ouspg/libfuzzer-base 20 | ``` 21 | 22 | Stub images can be built using docker-compose 23 | 24 | ```console 25 | $ docker-compose build 26 | ``` 27 | 28 | # Running 29 | 30 | ## Starting the container 31 | 32 | ```console 33 | $ docker-compose run 34 | ``` 35 | 36 | Fuzzer is started automatically when container is started with docker-compose. 37 | 38 | 39 | ```console 40 | INFO: Seed: 50837522 41 | INFO: -max_len is not provided, using 64 42 | INFO: A corpus is not provided, starting from an empty corpus 43 | #0 READ units: 1 exec/s: 0 44 | #1 INITED cov: 12 bits: 12 units: 1 exec/s: 0 45 | #2 NEW cov: 15 bits: 15 units: 2 exec/s: 0 L: 64 MS: 0 46 | ... 47 | ``` 48 | 49 | # Example 50 | 51 | [mysamplelib readme](mysamplelib/README.md) is also suggested to read to get started testing and writing your own stubs. 52 | -------------------------------------------------------------------------------- /stubs/haskell-x509/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base-haskell 2 | 3 | MAINTAINER https://github.com/ouspg/libfuzzerification 4 | 5 | WORKDIR /haskell 6 | RUN cabal update && cabal install x509 7 | COPY test.hs build.sh /haskell/ 8 | RUN sh ./build.sh 9 | -------------------------------------------------------------------------------- /stubs/haskell-x509/README.md: -------------------------------------------------------------------------------- 1 | # Haskell-x509 2 | 3 | # Purpose 4 | 5 | Use Haskell's FFI (foreign function interface), export Haskell function via FFI (using C Calling Convention) and minimal layer of C to initialize Haskell runtime. 6 | Compilation produces object file named test.o which can be linked with libFuzzer. After that we use Haskell packagin tools to enable SanitizerCoverage. 7 | 8 | See presentation [Fuzzing beyond C](https://github.com/ouspg/libfuzzerfication/blob/master/doc/presentation-oherrala-fuzzing-beyond-c.md) by oherrala. 9 | 10 | # Building 11 | 12 | 13 | ```console 14 | docker-compose build haskell-x509 15 | ``` 16 | 17 | # Running 18 | 19 | ## Starting the container 20 | 21 | ```console 22 | docker-compose run haskell-x509 23 | ``` 24 | 25 | ## Starting the fuzzer 26 | 27 | ```console 28 | ./test 29 | ``` 30 | -------------------------------------------------------------------------------- /stubs/haskell-x509/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | GHCOPTS="-Wall -package libfuzzer -package x509" 6 | 7 | clang -Wall -c -I/opt/ghc/8.0.1/lib/ghc-8.0.1/include/ hsinit.c 8 | ghc-asan ${GHCOPTS} -c test.hs 9 | ghc-wrapper ${GHCOPTS} -no-hs-main -lFuzzer -o test test.o hsinit.o 10 | -------------------------------------------------------------------------------- /stubs/haskell-x509/test.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE Strict #-} 4 | 5 | module Test where 6 | 7 | import Foreign.C.Types 8 | import Foreign.C.String 9 | import qualified Data.ByteString as BS 10 | 11 | import Libfuzzer 12 | import Control.Exception (SomeException, try, evaluate) 13 | 14 | import qualified Data.X509 as X509 15 | 16 | decode :: BS.ByteString -> IO (Either SomeException (Either String X509.SignedCertificate)) 17 | decode = try . evaluate . X509.decodeSignedCertificate 18 | 19 | foreign export ccall "LLVMFuzzerTestOneInput" testOneInputM :: CString -> CSize -> IO CInt 20 | 21 | testOneInputM :: CString -> CSize -> IO CInt 22 | testOneInputM str size = do 23 | bs <- BS.packCStringLen (str, fromIntegral size) 24 | 25 | result <- decode bs 26 | case result of 27 | Right _ -> return () 28 | Left err -> do 29 | let err' = show err 30 | putStrLn $ "Exception: " ++ err' 31 | storeTestCase err' bs 32 | 33 | return 0 -- Non-zero return values are reserved for future use. 34 | -------------------------------------------------------------------------------- /stubs/libmad/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "libmad" 6 | 7 | MAINTAINER https://github.com/ouspg/libfuzzerification 8 | 9 | #Install build-deps 10 | RUN apt-get update && apt-get build-dep libmad0 -y 11 | #Download source, extract and remove downloaded files. 12 | RUN mkdir -p /src/ && cd /src/ && apt-get source libmad0 && ls -p | grep -v / | xargs rm 13 | 14 | #Copy stub 15 | ADD libmad-fuzzer.c /src/libmad-0.15.1b/ 16 | 17 | ADD samples.tar.gz / 18 | 19 | #Add build script and build 20 | ADD build.sh /src/scripts/ 21 | RUN bash /src/scripts/build.sh 22 | -------------------------------------------------------------------------------- /stubs/libmad/README.md: -------------------------------------------------------------------------------- 1 | # libmad 2 | 3 | # Purpose 4 | 5 | Libmad is MPEG audio decoder library. Libmad can be used to minimize mp3-sample collection but it cannot be currently used for fuzzing libmad because it's not currenlty in active development. 6 | 7 | What is included? 8 | 9 | * [`libmad-fuzzer.c`](libmad-fuzzer.c)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | * [`Samples`](samples.tar.gz) to provide sample files to get started with 13 | 14 | # Building 15 | 16 | ## Building container 17 | 18 | ```console 19 | docker-compose build libmad 20 | ``` 21 | 22 | # Running 23 | 24 | ## Starting the container 25 | 26 | ```console 27 | docker-compose run libmad 28 | ``` 29 | # Samples 30 | 31 | Currently samples.tar.gz contains one self made sample. 32 | 33 | # Warning! 34 | 35 | Libmad is not currently under active development but it's still widely in use. 36 | 37 | Bug has been found from it: 38 | * Invalid memory read in mad_bit_skip, @attekett tried to find active developer, but all contact channels seem inactive. 39 | 40 | * Website at http://www.underbit.com/products/mad/ has contact info for licensing and couple of links to mailing-lists that haven't been used in ages(for anything else than spam). 41 | 42 | * MAD also has a SourceForge project at https://sourceforge.net/projects/mad/. 43 | * Last update 2013 and last release update 2004. All 40 bugs reported to SourceForge are with status "open" and no activity from developer side. 44 | 45 | * @attekett decided to report this issue to Ubuntu Launchpad. https://bugs.launchpad.net/ubuntu/+source/libmad/+bug/1494164 (restricted view) 46 | 47 | Timeline: 48 | ``` 49 | 2015-09-10 - Reported to launchpad 50 | 2015-10-29 - Status update New->Confirmed 51 | forgotten 52 | 2016-07-07 - Requested info about current state 53 | 2016-07-07 - Got reply that no one is "actively" looking at the issue. Also got recommendation to contact oss-security mailing-list, if someone over there would be interested. 54 | ``` 55 | -------------------------------------------------------------------------------- /stubs/libmad/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export CXXFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 5 | export CXX="clang++" 6 | export CFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 7 | export CC="clang" 8 | export LDFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 9 | 10 | cd /src/libmad-0.15.1b/ 11 | 12 | ./configure --prefix=/usr/ --enable-speed 13 | 14 | make -j4 15 | make install 16 | 17 | $CXX $CXXFLAGS -std=c++11 ./.libs/libmad.so -Iinclude -lFuzzer \ 18 | ./libmad-fuzzer.c -o /src/libmad-0.15.1b/libmad-fuzzer 19 | -------------------------------------------------------------------------------- /stubs/libmad/libmad-fuzzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mad.h" 5 | 6 | struct buffer { 7 | unsigned char const *start; 8 | unsigned long length; 9 | }; 10 | 11 | static 12 | enum mad_flow input(void *data, 13 | struct mad_stream *stream) 14 | { 15 | struct buffer *buffer = (struct buffer*) data; 16 | 17 | if (!buffer->length) 18 | return MAD_FLOW_STOP; 19 | 20 | mad_stream_buffer(stream, buffer->start, buffer->length); 21 | 22 | buffer->length = 0; 23 | 24 | return MAD_FLOW_CONTINUE; 25 | } 26 | 27 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 28 | struct buffer buffer; 29 | struct mad_decoder decoder; 30 | 31 | /* initialize our private message structure */ 32 | 33 | buffer.start = Data; 34 | buffer.length = Size; 35 | 36 | /* configure input, output, and error functions */ 37 | 38 | mad_decoder_init(&decoder, &buffer, 39 | input, 0 /* header */, 40 | 0 /* filter */, 41 | 0 /* output */, 42 | 0, 0 /* message */); 43 | 44 | /* start decoding */ 45 | 46 | mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); 47 | 48 | /* release the decoder */ 49 | 50 | mad_decoder_finish(&decoder); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /stubs/libmad/samples.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/stubs/libmad/samples.tar -------------------------------------------------------------------------------- /stubs/libxml2/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "libxml2" 6 | ENV LD_LIBRARY_PATH="/src/libxml2/.libs/" 7 | 8 | MAINTAINER https://github.com/ouspg/libfuzzerification 9 | 10 | RUN apt-get update && apt-get install -y liblzma-dev 11 | RUN apt-get build-dep libxml2 -y 12 | RUN cd /src && git clone git://git.gnome.org/libxml2 13 | 14 | ADD libxml2-fuzzer.cc /src/libxml2/ 15 | ADD xml.dict /src/libxml2/ 16 | 17 | ADD samples.tar.gz / 18 | 19 | ADD build.sh /src/scripts/ 20 | RUN mkdir -p /work/libxml2/ 21 | RUN bash /src/scripts/build.sh 22 | -------------------------------------------------------------------------------- /stubs/libxml2/LICENSE: -------------------------------------------------------------------------------- 1 | XML samples from: https://www.w3.org/XML/Test/ 2 | -------------------------------------------------------------------------------- /stubs/libxml2/README.md: -------------------------------------------------------------------------------- 1 | # libxml2 2 | 3 | # Purpose 4 | 5 | Libxml2 is the XML C parser and toolkit. It is developed for the Gnome project but is also used outside it. The fuzzer parses an XML in-memory document and builds a tree. Then it frees memory used by document and then it cleans up memory allocated by the library itself. 6 | 7 | What is included? 8 | 9 | * [`libxml2-fuzzer.cc`](libxml2-fuzzer.cc)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | * [`Samples`](samples.tar.gz) to provide sample files to get started with 13 | 14 | # Building 15 | 16 | ## Building container 17 | 18 | ```console 19 | docker-compose build libxml2 20 | ``` 21 | 22 | # Running 23 | 24 | ## Starting the container 25 | 26 | ```console 27 | docker-compose run libxml2 28 | ``` 29 | 30 | # Samples 31 | 32 | Samples.tar.gz contains samples from [XML test suite](https://www.w3.org/XML/Test/). 33 | -------------------------------------------------------------------------------- /stubs/libxml2/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export CXXFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 5 | export CXX="clang++" 6 | export CFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 7 | export CC="clang" 8 | export LDFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 9 | 10 | 11 | cd /src/libxml2/ 12 | if [ ! -f configure ] 13 | then 14 | ./autogen.sh 15 | fi 16 | 17 | echo =========== MAKE 18 | make -j 16 19 | 20 | $CXX $CXXFLAGS -std=c++11 libxml2-fuzzer.cc \ 21 | -Iinclude -L.libs -lxml2 -llzma -lFuzzer \ 22 | -o /src/libxml2/libxml2-fuzzer 23 | -------------------------------------------------------------------------------- /stubs/libxml2/libxml2-fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | #include "libxml/parser.h" 5 | void ignore(void *ctx, const char *msg, ...) { 6 | // Error handler to avoid spam of error messages from libxml parser. 7 | } 8 | extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { 9 | xmlSetGenericErrorFunc(NULL, &ignore); 10 | auto doc = xmlReadMemory(reinterpret_cast(data), size, "noname.xml", NULL, 0); 11 | //if (doc) { 12 | xmlFreeDoc(doc); 13 | xmlCleanupParser(); 14 | //} 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /stubs/libxml2/samples.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/stubs/libxml2/samples.tar.gz -------------------------------------------------------------------------------- /stubs/libxml2/xml.dict: -------------------------------------------------------------------------------- 1 | # 2 | # AFL dictionary for XML 3 | # ---------------------- 4 | # 5 | # Several basic syntax elements and attributes, modeled on libxml2. 6 | # 7 | # Created by Michal Zalewski 8 | # 9 | 10 | attr_encoding=" encoding=\"1\"" 11 | attr_generic=" a=\"1\"" 12 | attr_href=" href=\"1\"" 13 | attr_standalone=" standalone=\"no\"" 14 | attr_version=" version=\"1\"" 15 | attr_xml_base=" xml:base=\"1\"" 16 | attr_xml_id=" xml:id=\"1\"" 17 | attr_xml_lang=" xml:lang=\"1\"" 18 | attr_xml_space=" xml:space=\"1\"" 19 | attr_xmlns=" xmlns=\"1\"" 20 | 21 | entity_builtin="<" 22 | entity_decimal="" 23 | entity_external="&a;" 24 | entity_hex="" 25 | 26 | string_any="ANY" 27 | string_brackets="[]" 28 | string_cdata="CDATA" 29 | string_col_fallback=":fallback" 30 | string_col_generic=":a" 31 | string_col_include=":include" 32 | string_dashes="--" 33 | string_empty="EMPTY" 34 | string_empty_dblquotes="\"\"" 35 | string_empty_quotes="''" 36 | string_entities="ENTITIES" 37 | string_entity="ENTITY" 38 | string_fixed="#FIXED" 39 | string_id="ID" 40 | string_idref="IDREF" 41 | string_idrefs="IDREFS" 42 | string_implied="#IMPLIED" 43 | string_nmtoken="NMTOKEN" 44 | string_nmtokens="NMTOKENS" 45 | string_notation="NOTATION" 46 | string_parentheses="()" 47 | string_pcdata="#PCDATA" 48 | string_percent="%a" 49 | string_public="PUBLIC" 50 | string_required="#REQUIRED" 51 | string_schema=":schema" 52 | string_system="SYSTEM" 53 | string_ucs4="UCS-4" 54 | string_utf16="UTF-16" 55 | string_utf8="UTF-8" 56 | string_xmlns="xmlns:" 57 | 58 | tag_attlist="" 61 | tag_doctype="" 68 | tag_open_close="" 69 | tag_open_exclamation="" 72 | tag_xml_q="" 73 | -------------------------------------------------------------------------------- /stubs/libxslt/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "libxslt" 6 | ENV LD_LIBRARY_PATH="/src/libxslt/libxslt/.libs/" 7 | 8 | MAINTAINER https://github.com/ouspg/libfuzzerification 9 | 10 | RUN apt-get update && apt-get install -y liblzma-dev 11 | RUN apt-get build-dep libxslt -y 12 | RUN cd /src && git clone git://git.gnome.org/libxslt 13 | 14 | ADD libxslt-fuzzer.cc /src/libxslt/ 15 | #ADD xslt.dict /src/libxslt/ 16 | 17 | ADD samples.tar.gz / 18 | 19 | ADD build.sh /src/scripts/ 20 | RUN mkdir -p /work/libxslt/ 21 | RUN bash /src/scripts/build.sh 22 | -------------------------------------------------------------------------------- /stubs/libxslt/README.md: -------------------------------------------------------------------------------- 1 | # libxslt 2 | 3 | # Purpose 4 | 5 | Libxslt is the XSLT C library that is developed fro Gnome project. XSLT itself is a an XML language to define transformation for XML. 6 | 7 | What is included? 8 | 9 | * [`libxslt-fuzzer.cc`](libxslt-fuzzer.cc)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | * [`Samples`](samples.tar.gz) to provide sample files to get started with 13 | 14 | # Building 15 | 16 | ## Building container 17 | 18 | ```console 19 | docker-compose build libxslt 20 | ``` 21 | 22 | # Running 23 | 24 | ## Starting the container 25 | 26 | ```console 27 | docker-compose run libxslt 28 | ``` 29 | 30 | # Samples 31 | -------------------------------------------------------------------------------- /stubs/libxslt/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export CXXFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 5 | export CXX="clang++" 6 | export CFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 7 | export CC="clang" 8 | export LDFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 9 | 10 | 11 | cd /src/libxslt/ 12 | 13 | if [ ! -f configure ] 14 | then 15 | ./autogen.sh 16 | fi 17 | 18 | echo =========== MAKE 19 | make -j 16 20 | 21 | $CXX $CXXFLAGS -std=c++11 libxslt-fuzzer.cc -Werror \ 22 | -I. $(xml2-config --cflags) \ 23 | -Llibxslt/.libs -lxslt -lFuzzer \ 24 | $(xml2-config --libs) \ 25 | -o /src/libxslt/libxslt-fuzzer 26 | -------------------------------------------------------------------------------- /stubs/libxslt/libxslt-fuzzer.cc: -------------------------------------------------------------------------------- 1 | #include "libxslt/libxslt.h" 2 | #include "libxslt/xsltconfig.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "libxslt/xslt.h" 15 | #include "libxslt/transform.h" 16 | #include "libxslt/xsltutils.h" 17 | #include "libxslt/extensions.h" 18 | #include "libxslt/security.h" 19 | 20 | #undef DEBUG_PRNT 21 | 22 | /* 23 | * Adapted from xsltproc/xsltproc.c in libxslt delivery. 24 | * xsltproc/xsltproc.c header / copyright: 25 | * xsltproc.c: user program for the XSL Transformation 1.0 engine 26 | * 27 | * See Copyright for the status of this software. 28 | * 29 | * daniel@veillard.com 30 | */ 31 | 32 | /* 33 | * Input from environment variables: 34 | * - XSLT_RAND_SEED integer for srand() seed, otherwise 0 35 | * - XSLT_HTML if non-zero, HTML parser used for input instead of XML 36 | * - XSLT_STYLE_FILE file path for static stylesheet. If not provided, 37 | * fuzzed input is used instead. 38 | * - XSLT_INPUT_FILE file path for input file. If not provided, 39 | * fuzzed input is used instead. 40 | * 41 | * Output from XSLT process is suppressed. 42 | */ 43 | 44 | #define MAX_PARAMETERS 64 45 | 46 | static const char *params[MAX_PARAMETERS + 1] = { NULL }; 47 | static int xml_options = XML_PARSE_NOERROR | XML_PARSE_NOWARNING; 48 | static int options = XSLT_PARSE_OPTIONS; 49 | static int html = 0; 50 | 51 | static int errorno = 0; 52 | 53 | void ignore(void *ctx, const char *msg, ...) { 54 | // Error handler to avoid spam of error messages from libxml parser. 55 | } 56 | 57 | void xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur) { 58 | xmlDocPtr res; 59 | xsltTransformContextPtr ctxt; 60 | 61 | ctxt = xsltNewTransformContext(cur, doc); 62 | if (ctxt == NULL) 63 | return; 64 | xsltSetCtxtParseOptions(ctxt, options); 65 | res = xsltApplyStylesheetUser(cur, doc, params, NULL, 66 | NULL, ctxt); 67 | 68 | if (ctxt->state == XSLT_STATE_ERROR) 69 | errorno = 9; 70 | else if (ctxt->state == XSLT_STATE_STOPPED) 71 | errorno = 10; 72 | 73 | xsltFreeTransformContext(ctxt); 74 | xmlFreeDoc(doc); 75 | if (res == NULL) { 76 | #ifdef DEBUG_PRNT 77 | fprintf(stderr, "no result\n"); 78 | #endif 79 | return; 80 | } 81 | 82 | xmlFreeDoc(res); 83 | } 84 | 85 | static bool doInit() { 86 | char *seed = getenv("XSLT_RAND_SEED"); 87 | srand(seed != NULL ? (unsigned int)strtoul(seed, NULL, 10) : 0); 88 | 89 | if(getenv("XSLT_HTML")) 90 | html++; 91 | #ifdef DEBUG_PRNT 92 | fprintf(stderr, "Init Done\n"); 93 | #endif 94 | 95 | xmlSetGenericErrorFunc(NULL, &ignore); 96 | 97 | return true; 98 | } 99 | 100 | extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { 101 | static bool init = doInit(); 102 | 103 | int i; 104 | 105 | xsltStylesheetPtr cur = NULL; 106 | xmlDocPtr doc, style; 107 | xsltSecurityPrefsPtr sec = NULL; 108 | 109 | errorno = 0; 110 | 111 | xmlInitMemory(); 112 | 113 | LIBXML_TEST_VERSION 114 | 115 | sec = xsltNewSecurityPrefs(); 116 | xsltSetDefaultSecurityPrefs(sec); 117 | 118 | const char *style_file = reinterpret_cast(getenv("XSLT_STYLE_FILE")); 119 | const char *input_file = reinterpret_cast(getenv("XSLT_INPUT_FILE")); 120 | 121 | if(style_file) { 122 | style = xmlReadFile(style_file, NULL, xml_options); 123 | } else { 124 | style = xmlReadMemory(reinterpret_cast(data), size, "noname.xsl", NULL, xml_options); 125 | } 126 | if(style == NULL) { 127 | #ifdef DEBUG_PRNT 128 | fprintf(stderr, "cannot parse %s\n", style_file); 129 | #endif 130 | cur = NULL; 131 | errorno = 4; 132 | goto done; 133 | } else { 134 | cur = xsltLoadStylesheetPI(style); 135 | if (cur != NULL) { 136 | /* it is an embedded stylesheet */ 137 | xsltProcess(style, cur); 138 | xsltFreeStylesheet(cur); 139 | cur = NULL; 140 | goto done; 141 | } 142 | cur = xsltParseStylesheetDoc(style); 143 | if (cur != NULL) { 144 | if (cur->errors != 0) { 145 | errorno = 5; 146 | goto done; 147 | } 148 | i++; 149 | } else { 150 | xmlFreeDoc(style); 151 | errorno = 5; 152 | goto done; 153 | } 154 | } 155 | 156 | if ((cur != NULL) && (cur->errors == 0)) { 157 | doc = NULL; 158 | #ifdef LIBXML_HTML_ENABLED 159 | if (html) 160 | if(input_file) 161 | doc = htmlReadFile(input_file, NULL, options); 162 | else 163 | doc = htmlReadMemory(reinterpret_cast(data), size, "noname.html", NULL, options); 164 | else 165 | #endif 166 | if(input_file) 167 | doc = xmlReadFile(input_file, NULL, xml_options); 168 | else 169 | doc = xmlReadMemory(reinterpret_cast(data), size, "noname.xml", NULL, xml_options); 170 | if (doc == NULL) { 171 | #ifdef DEBUG_PRNT 172 | fprintf(stderr, "unable to parse\n"); 173 | #endif 174 | errorno = 6; 175 | } else { 176 | xsltProcess(doc, cur); 177 | } 178 | } 179 | 180 | done: 181 | #ifdef DEBUG_PRNT 182 | fprintf(stderr, "Done %d\n", errorno); 183 | #endif 184 | if (cur != NULL) 185 | xsltFreeStylesheet(cur); 186 | 187 | xsltFreeSecurityPrefs(sec); 188 | xsltCleanupGlobals(); 189 | xmlCleanupParser(); 190 | xmlMemoryDump(); 191 | 192 | return 0; 193 | } 194 | -------------------------------------------------------------------------------- /stubs/libxslt/samples.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ouspg/libfuzzerfication/afa33067752d663ac51be7073308109e4d0e0785/stubs/libxslt/samples.tar.gz -------------------------------------------------------------------------------- /stubs/lua/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "lua" 6 | 7 | #Install dependencies and fetch the source. 8 | 9 | RUN apt-get update && apt-get -y build-dep lua5.3 10 | 11 | ADD https://www.lua.org/ftp/lua-5.3.3.tar.gz /src/ 12 | RUN tar -C /src -zxf /src/lua-5.3.3.tar.gz 13 | 14 | ADD lua-fuzzer.c /src/lua-5.3.3 15 | 16 | ADD samples /samples/libfuzzer-lua 17 | 18 | #Build 19 | ADD build.sh /src/scripts/ 20 | RUN bash /src/scripts/build.sh 21 | 22 | #Execute default commands 23 | ENTRYPOINT ["/src/scripts/fuzz.sh"] 24 | CMD ["/lua-fuzzer",\ 25 | "-rss_limit_mb=1024",\ 26 | "-detect_leaks=0",\ 27 | "-exact_artifact_path=/dev/shm/repro-file",\ 28 | "-max_len=1000",\ 29 | "-timeout=5",\ 30 | "-use_counters=1",\ 31 | "-max_total_time=3600",\ 32 | "/srv/fuzzer/samples/"] 33 | -------------------------------------------------------------------------------- /stubs/lua/README.md: -------------------------------------------------------------------------------- 1 | # lua 2 | 3 | # Purpose 4 | 5 | Lua is a lightweight, embeddable scripting language. The fuzzer loads lua libraries and the file that has lua script that we're going to run and runs the script. 6 | 7 | What is included? 8 | 9 | * [`lua-fuzzer.c`](lua-fuzzer.c)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | * [`Samples`](samples/) to provide sample file to get started with 13 | 14 | # Building 15 | 16 | ## Building container 17 | 18 | ```console 19 | docker-compose build lua 20 | ``` 21 | 22 | # Running 23 | 24 | ## Starting the container 25 | 26 | ```console 27 | docker-compose run lua 28 | ``` 29 | 30 | # Samples 31 | 32 | Samples directory contains simple lua script that is used by this fuzzer. 33 | -------------------------------------------------------------------------------- /stubs/lua/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | export CXXFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls -fPIC" 6 | export CXX="clang++" 7 | export CFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls -fPIC" 8 | export CC="clang" 9 | export LDFLAGS="-fsanitize=address -fsanitize-coverage=edge,indirect-calls" 10 | 11 | cd /src/lua-5.3.3 12 | ls -la 13 | 14 | # build lua 15 | make linux CC=$CC "CFLAGS=$CFLAGS" "LDFLAGS=$LDFLAGS" 16 | make install 17 | 18 | #Build fuzzer 19 | $CXX -std=c++11 -o /lua-fuzzer lua-fuzzer.c \ 20 | -I/usr/local/include \ 21 | -L/usr/local/lib \ 22 | -llua -lm -ldl \ 23 | -lFuzzer $LDFLAGS 24 | -------------------------------------------------------------------------------- /stubs/lua/lua-fuzzer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lua-fuzzer.c 3 | * libfuzzer stub for fuzzing LUA 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | extern "C" { 10 | #include 11 | #include 12 | #include 13 | } 14 | 15 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 16 | int status, result; 17 | double ret; 18 | lua_State *L; 19 | 20 | /* 21 | * All Lua contexts are held in this structure. We work with it almost 22 | * all the time. 23 | */ 24 | L = luaL_newstate(); 25 | 26 | luaL_openlibs(L); /* Load Lua libraries */ 27 | 28 | /* Load the file containing the script we are going to run */ 29 | status = luaL_loadbuffer(L, (const char *)data, size, "code"); 30 | if (status) { 31 | /* If something went wrong, error message is at the top of */ 32 | /* the stack */ 33 | //fprintf(stderr, "Couldn't load script: %s\n", lua_tostring(L, -1)); 34 | goto lua_exit; 35 | } 36 | 37 | /* Ask Lua to run our little script */ 38 | result = lua_pcall(L, 0, LUA_MULTRET, 0); 39 | if (result) { 40 | //fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1)); 41 | goto lua_exit; 42 | } 43 | 44 | /* Get the returned value at the top of the stack (index -1) */ 45 | ret = lua_tonumber(L, -1); 46 | 47 | //printf("Script returned: %.0f\n", ret); 48 | 49 | lua_exit: 50 | lua_pop(L, 1); /* Take the returned value out of the stack */ 51 | lua_close(L); /* Cya, Lua */ 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /stubs/lua/samples/simple.lua: -------------------------------------------------------------------------------- 1 | -- script.lua 2 | -- Receives a table, returns the sum of its components. 3 | io.write("The table the script received has:\n"); 4 | return 42 5 | -------------------------------------------------------------------------------- /stubs/mysamplelib/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "mysamplelib" 6 | 7 | RUN apt-get update && apt-get upgrade -y 8 | 9 | WORKDIR /src 10 | COPY build.sh dictionary.txt fuzzer.c mysamplelib.h mysamplelib.c /src/samplelib/ 11 | 12 | WORKDIR /src/samplelib 13 | COPY samples samples/ 14 | RUN ./build.sh 15 | -------------------------------------------------------------------------------- /stubs/mysamplelib/README.md: -------------------------------------------------------------------------------- 1 | # mysamplelib 2 | 3 | # Purpose 4 | 5 | This is a [libfuzzerfication stub](https://github.com/ouspg/libfuzzerfication) 6 | for demonstration purposes. 7 | 8 | `mysamplelib` is a simple library that provides `mysamplefunction()`-function as 9 | a target for Fuzz-testing. `mysamplefunction()` takes two arguments: the "string" 10 | to be tested as test input and the length of the test input. 11 | Test input is compared against the target string `"Fuzzing in Style!"`. The 12 | portion of the string that has been guessed successfully is displayed. The comparison is 13 | implemented with an artificial nested `if`-construct to simulate the 14 | basic block structure of a real protocol or file format parser. This 15 | approach makes `mysamplefunction()` a "realistic" parser-type target for 16 | the coverage guided fuzzing. 17 | 18 | What is included? 19 | 20 | * [`samplelib`](mysamplelib.c)-library with `mysamplefunction()`-function as test target 21 | * [`mysamplelib-fuzzer`](mysamplelib-fuzzer.c)-stub to act as the interface between the `libfuzzer` and the test target 22 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 23 | * [`dictionary.txt`](dictionary.txt)-file as a sample dictionary for dictionary aided fuzzing strategy 24 | * [`samples/`](samples/)-directory as a sample corpus for the corpus aided fuzzing strategy 25 | * [`Dockerfile`](Dockerfile) to make this demonstration easily repeatable 26 | 27 | Last but not least. There is at least one *crash-boom-bang* (read beyond bounds) 28 | bug that the fuzzer should find. 29 | 30 | # Building 31 | 32 | ```console 33 | $ docker build -t mysamplelib-fuzzer . 34 | ``` 35 | 36 | # Running 37 | 38 | ## Starting the container 39 | 40 | ```console 41 | $ docker run -ti --rm mysamplelib-fuzzer 42 | ``` 43 | 44 | ## Running the fuzzer 45 | 46 | ```console 47 | $ ./fuzzer 48 | INFO: Seed: 50837522 49 | INFO: -max_len is not provided, using 64 50 | INFO: A corpus is not provided, starting from an empty corpus 51 | #0 READ units: 1 exec/s: 0 52 | #1 INITED cov: 12 bits: 12 units: 1 exec/s: 0 53 | #2 NEW cov: 15 bits: 15 units: 2 exec/s: 0 L: 64 MS: 0 54 | 55 | --- You fail --- 56 | ... 57 | --- You fail --- 58 | F 59 | ... 60 | Fuzz i 61 | --- You fail --- 62 | Fuzz in Style! 63 | *** Grand success *** 64 | Fuzz in 65 | --- You fail --- 66 | ... 67 | ==33==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000518e0f at pc 0x00000048b390 bp 0x7fff6c865350 sp 0x7fff6c864b00 68 | READ of size 16 at 0x000000518e0f thread T0 69 | ... 70 | ``` 71 | 72 | # Running with different fuzzing strategies 73 | 74 | Following examples use `-seed=` to make results repeatable. 75 | In normal fuzzing you would **not** want to fix the seed. 76 | 77 | Four different fuzzing strategies are summaries below and details on how to run them are given as separate examples. 78 | 79 | fuzzing strategy | attempts until crash found 80 | ---------------- | --------------------------- 81 | coverage only | 9488 82 | dictionary | 3064 83 | corpus | 1374 84 | corpus from fuzzing | 149 85 | 86 | ## Coverage guided fuzzing 87 | 88 | ```console 89 | $ ./fuzzer -seed=2016 corpus | wc -l 90 | INFO: Seed: 2016 91 | INFO: -max_len is not provided, using 64 92 | INFO: A corpus is not provided, starting from an empty corpus 93 | ... 94 | ==276==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000518e0f at pc 0x00000048b390 bp 0x7ffe3a3c9f50 sp 0x7ffe3a3c9700 95 | ... 96 | 9488 97 | ``` 98 | 99 | ## Coverage guided fuzzing with dictionary 100 | 101 | ```console 102 | $ ./fuzzer -seed=2016 -dict=./dictionary.txt | wc -l 103 | Dictionary: 2 entries 104 | INFO: Seed: 2016 105 | INFO: -max_len is not provided, using 64 106 | INFO: A corpus is not provided, starting from an empty corpus 107 | ... 108 | ==247==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000518e0f at pc 0x00000048b390 bp 0x7fff8aa71150 sp 0x7fff8aa70900 109 | ... 110 | 3064 111 | ``` 112 | 113 | ## Coverage guided fuzzing with corpus (samples) 114 | 115 | ```console 116 | $ ./fuzzer -seed=2016 | wc -l 117 | INFO: Seed: 2016 118 | INFO: -max_len is not provided, using 64 119 | ... 120 | ==283==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000518e0f 121 | at pc 0x00000048b390 bp 0x7ffd0cdde950 sp 0x7ffd0cdde100 122 | ... 123 | 1374 124 | ``` 125 | 126 | ## Coverage guided fuzzing with new corpus (from previous run) 127 | 128 | ```console 129 | $ ./fuzzer -seed=2016 corpus | wc -l 130 | INFO: Seed: 2016 131 | INFO: -max_len is not provided, using 64 132 | ... 133 | ==234==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000518e0f at pc 0x00000048b390 bp 0x7ffc7f4b5750 sp 0x7ffc7f4b4f00 134 | ... 135 | 149 136 | ``` 137 | 138 | # Further work 139 | 140 | It appears that changing the compiler optimizations (`-On`) has a radical impact 141 | on the fuzzer performance with this sample test target. This setup would allow 142 | us to to study it further. 143 | 144 | Furthermore, in addition to using the `libfuzzer` as the coverage guided fuzzer 145 | we could implement a simple brute force fuzzer and output guided brute force 146 | fuzzer for this test target. We could also document how to run the [american 147 | fuzzy lop](http://lcamtuf.coredump.cx/afl/)-fuzzer (afl) against this target. 148 | Then we could compare all these alternative approaches. 149 | -------------------------------------------------------------------------------- /stubs/mysamplelib/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | CFLAGS="-g -Wall -O0 -fsanitize=address \ 4 | -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" 5 | 6 | ## compile the library 7 | clang ${CFLAGS} -c mysamplelib.c 8 | 9 | ## compile the fuzzing stubs 10 | clang ${CFLAGS} -c fuzzer.c 11 | 12 | ## link them together 13 | clang++ ${CFLAGS} mysamplelib.o fuzzer.o -lFuzzer -o fuzzer 14 | -------------------------------------------------------------------------------- /stubs/mysamplelib/dictionary.txt: -------------------------------------------------------------------------------- 1 | "Fuzz" 2 | "in Style" 3 | -------------------------------------------------------------------------------- /stubs/mysamplelib/fuzzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mysamplelib.h" 5 | 6 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 7 | (void) mysamplefunction(Data, Size); 8 | return 0; // Non-zero return values are reserved for future use. 9 | } 10 | -------------------------------------------------------------------------------- /stubs/mysamplelib/mysamplelib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "mysamplelib.h" 6 | 7 | const char *_mytarget = "Fuzz in Style!"; 8 | 9 | 10 | int _cmp(const uint8_t *buf, size_t len, size_t size) { 11 | if ((size < 1) || (len > size)) 12 | return 1; 13 | if (memcmp(buf, _mytarget, len)) 14 | return 1; 15 | 16 | printf("%c", _mytarget[len-1]); 17 | return 0; 18 | } 19 | 20 | 21 | int mysamplefunction(const uint8_t *buf, size_t len) { 22 | 23 | int index = 1; 24 | int ret = 1; 25 | 26 | if (!_cmp(buf, index++, len)) 27 | if (!_cmp(buf, index++, len)) 28 | if (!_cmp(buf, index++, len)) 29 | if (!_cmp(buf, index++, len)) 30 | if (!_cmp(buf, index++, len)) 31 | if (!_cmp(buf, index++, len)) 32 | if (!_cmp(buf, index++, len)) 33 | if (!_cmp(buf, index++, len)) 34 | if (!_cmp(buf, index++, len)) 35 | if (!_cmp(buf, index++, len)) 36 | if (!_cmp(buf, index++, len)) 37 | if (!_cmp(buf, index++, len)) 38 | if (!_cmp(buf, index++, len)) 39 | if (!_cmp(buf, index++, len)) 40 | if (!_cmp(buf, index++, len)) 41 | if (!_cmp(buf, index++, len)) 42 | if (!_cmp(buf, index++, len)) 43 | if (!_cmp(buf, index++, len)) 44 | if (!_cmp(buf, index++, len)) 45 | if (!_cmp(buf, index++, len)) 46 | if (!_cmp(buf, index++, len)) 47 | if (!_cmp(buf, index++, len)) 48 | ret = 0; 49 | 50 | if (index > (strlen(_mytarget) + 1)) 51 | ret = 0; 52 | 53 | if (ret) { 54 | printf("\n--- You fail ---\n"); 55 | } else { 56 | printf("\n*** Grand success ***\n"); 57 | } 58 | 59 | return ret; 60 | } 61 | -------------------------------------------------------------------------------- /stubs/mysamplelib/mysamplelib.h: -------------------------------------------------------------------------------- 1 | int mysamplefunction(const uint8_t *, size_t); 2 | -------------------------------------------------------------------------------- /stubs/mysamplelib/samples/sample1.txt: -------------------------------------------------------------------------------- 1 | Fuzz in Style 2 | -------------------------------------------------------------------------------- /stubs/zlib/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ouspg/libfuzzer-base 2 | 3 | # Enviroment variables used by the fuzzer 4 | 5 | ENV TARGET "zlib" 6 | 7 | MAINTAINER https://github.com/ouspg/libfuzzerification 8 | ENV TARGET 'zlib' 9 | 10 | RUN apt-get update && apt-get upgrade -y && apt-get install -y zlib1g-dev && apt-get build-dep zlib1g-dev -y 11 | RUN cd /src && git clone https://github.com/madler/zlib.git 12 | ADD zlib-fuzzer.cc /src/zlib/ 13 | 14 | ADD build.sh /src/zlib/ 15 | WORKDIR /src/zlib 16 | RUN bash ./build.sh 17 | -------------------------------------------------------------------------------- /stubs/zlib/README.md: -------------------------------------------------------------------------------- 1 | # zlib 2 | 3 | # Purpose 4 | 5 | Zlib is data compression library. 6 | 7 | What is included? 8 | 9 | * [`zlib-fuzzer.cc`](zlib-fuzzer.cc)-stub to act as the interface between the `libfuzzer` and the test target 10 | * [`build.sh`](build.sh)-script to build the library, and the stub and to link them with the fuzzer 11 | * [`Dockerfile`](Dockerfile) to automate build of Docker image 12 | 13 | # Building 14 | 15 | ## Building container 16 | 17 | ```console 18 | docker-compose build zlib 19 | ``` 20 | 21 | # Running 22 | 23 | ## Starting the container 24 | 25 | ```console 26 | docker-compose run zlib 27 | ``` 28 | -------------------------------------------------------------------------------- /stubs/zlib/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CXX="clang++" 4 | export CC="clang" 5 | 6 | export SANCOV="-fsanitize=address -fsanitize-coverage=edge,indirect-calls" 7 | 8 | export CXXFLAGS=$SANCOV 9 | export CFLAGS=$SANCOV 10 | export LDFLAGS=$SANCOV 11 | 12 | #Build libav 13 | cd /src/zlib 14 | ./configure --prefix=/usr/ 15 | make -j4 16 | make install 17 | 18 | 19 | #Build fuzzer 20 | $CXX $CFLAGS -std=c++11 -I$(pwd) -lFuzzer -lz -o \ 21 | zlib-fuzzer zlib-fuzzer.cc 22 | -------------------------------------------------------------------------------- /stubs/zlib/zlib-fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | #include 5 | #include 6 | #include 7 | #include "zlib.h" 8 | static Bytef buffer[256 * 1024] = { 0 }; 9 | // Entry point for LibFuzzer. 10 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 11 | uLongf buffer_length = static_cast(sizeof(buffer)); 12 | if (Z_OK != uncompress(buffer, &buffer_length, data, 13 | static_cast(size))) { 14 | return 0; 15 | } 16 | return 0; 17 | } 18 | --------------------------------------------------------------------------------