├── 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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------