项目作者: Metalnem

项目描述 :
AFL-based fuzz testing for .NET
高级语言: C#
项目地址: git://github.com/Metalnem/sharpfuzz.git
创建时间: 2018-12-19T07:19:21Z
项目社区:https://github.com/Metalnem/sharpfuzz

开源协议:MIT License

下载


SharpFuzz: AFL-based fuzz testing for .NET

NuGet
Build Status
License

SharpFuzz is a tool that brings the power of afl-fuzz
to .NET platform. If you want to learn more about fuzzing,
my motivation for writing SharpFuzz, the types of bugs
it can find, or the technical details about how the
integration with afl-fuzz works, read my blog post
SharpFuzz: Bringing the power of afl-fuzz to .NET platform.

Table of contents

CVE

Articles

Trophies

If you find some interesting bugs with SharpFuzz, and
are comfortable with sharing them, I would love to add
them to this list. Please send me an email, make a pull
request for the README file, or file an issue.

Requirements

AFL works on Linux and macOS. If you are using Windows, you can use any Linux distribution
that works under the Windows Subsystem for Linux. For native Windows support, you can use
libFuzzer
instead of AFL.

You will need GNU make and a working compiler
(gcc or clang) in order to compile afl-fuzz.
You will also need to have the .NET 8.0
or greater installed on your machine in order
to instrument .NET assemblies with SharpFuzz.

To simplify your fuzzing experience, it’s also
recommended to install PowerShell.

Installation

You can install afl-fuzz and SharpFuzz.CommandLine
global .NET tool by running the following script:

  1. #/bin/sh
  2. set -eux
  3. # Download and extract the latest afl-fuzz source package
  4. wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
  5. tar -xvf afl-latest.tgz
  6. rm afl-latest.tgz
  7. cd afl-2.52b/
  8. # Install afl-fuzz
  9. sudo make install
  10. cd ..
  11. rm -rf afl-2.52b/
  12. # Install SharpFuzz.CommandLine global .NET tool
  13. dotnet tool install --global SharpFuzz.CommandLine

Usage

This tutorial assumes that you are somewhat familiar
with afl-fuzz. If you don’t know anything about it, you
should first read the AFL quick start guide and the
afl-fuzz README. If you have enough time, I would
also recommend reading Understanding the status screen
and Technical whitepaper for afl-fuzz.

As an example, we are going to fuzz Jil,
which is a fast JSON serializer and deserializer
(see SharpFuzz.Samples for many more examples
of complete fuzzing projects).

1. Create a new .NET console project, then add Jil and
SharpFuzz packages to it by running the following commands:

  1. dotnet add package Jil
  2. dotnet add package SharpFuzz

2. In your Main function, call SharpFuzz.Fuzzer.OutOfProcess.Run
with the function that you want to test as a parameter:

  1. using System;
  2. using System.IO;
  3. using SharpFuzz;
  4. namespace Jil.Fuzz
  5. {
  6. public class Program
  7. {
  8. public static void Main(string[] args)
  9. {
  10. Fuzzer.OutOfProcess.Run(stream =>
  11. {
  12. try
  13. {
  14. using (var reader = new StreamReader(stream))
  15. {
  16. JSON.DeserializeDynamic(reader);
  17. }
  18. }
  19. catch (DeserializationException) { }
  20. });
  21. }
  22. }
  23. }

We want to fuzz the deserialization capabilities of Jil,
which is why we are calling the JSON.DeserializeDynamic
method. The input data will be provided to us via the
stream parameter (if the code you are testing takes
its input as a string, you can use an additional overload
of Fuzzer.OutOfProcess.Run that accepts Action).

If the code passed to Fuzzer.OutOfProcess.Run throws an exception,
it will be reported to afl-fuzz as a crash. However, we
want to treat only unexpected exceptions as bugs.
DeserializationException is what we expect when
we encounter an invalid JSON input, which is why we
catch it in our example.

3. Create a directory with some test cases (one
test is usually more than enough). Test files
should contain some input that is accepted by
your code as valid, and should also be as small as
possible. For example, this is the JSON I’m using
for testing JSON deserializers:

  1. {"menu":{"id":1,"val":"X","pop":{"a":[{"click":"Open()"},{"click":"Close()"}]}}}

4. Let’s say that your project is called Fuzzing.csproj
and that your test cases are in the Testcases directory.
Start fuzzing by running the fuzz.ps1 script like this:

  1. pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i Testcases

For formats such as HTML, JavaScript, JSON, or SQL,
the fuzzing process can be greatly improved with
the usage of a dictionary file. AFL comes with
bunch of dictionaries, which you can find after
installation in /usr/local/share/afl/dictionaries/.
With this in mind, we can improve our fuzzing of Jil like this:

  1. pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i Testcases \
  2. -x /usr/local/share/afl/dictionaries/json.dict

5. Sit back and relax! You will often have
some useful results within minutes, but sometimes
it can take more than a day, so be patient.

The input files responsible for unhandled exceptions will
appear in the findings/crashes directory. The total
number of unique crashes will be displayed in red on the
afl-fuzz status screen.

In practice, the real number of unique exceptions will often
be much lower than the reported number, which is why it’s
usually best to write a small program that just goes through
the crashing inputs, runs the fuzzing function on each of
them, and saves only the inputs that produce unique stack traces.

Advanced topics

Acknowledgements