Metalnem/sharpfuzz
GitHub: Metalnem/sharpfuzz
将 AFL 模糊测试框架的覆盖引导能力引入 .NET 平台,通过 IL 插桩实现对托管程序集的自动化漏洞挖掘。
Stars: 450 | Forks: 37
# SharpFuzz:用于 .NET 的基于 AFL 的模糊测试
[][nuget-link]
[][build-link]
[][license-link]
SharpFuzz 是一款将 [afl-fuzz] 的强大功能
引入 .NET 平台的工具。如果您想了解更多关于模糊测试的内容、
我编写 SharpFuzz 的动机、它能够发现的 bug 类型、
或者关于如何与 afl-fuzz 集成的技术细节,
请阅读我的博客文章
[SharpFuzz: Bringing the power of afl-fuzz to .NET platform](https://mijailovic.net/2019/01/03/sharpfuzz/)。
## 目录
- [CVE](#cve)
- [文章](#articles)
- [战利品](#trophies)
- [环境要求](#requirements)
- [安装](#installation)
- [使用方法](#usage)
- [高级主题](#advanced-topics)
- [致谢](#acknowledgements)
## CVE
- [CVE-2019-0980: .NET Framework and .NET Core Denial of Service Vulnerability](https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2019-0980)
- [CVE-2019-0981: .NET Framework and .NET Core Denial of Service Vulnerability](https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2019-0981)
- [CVE-2025-11573: Denial of Service issue in Amazon.IonDotnet](https://aws.amazon.com/security/security-bulletins/AWS-2025-022/)
## 文章
- [SharpFuzz: Bringing the power of afl-fuzz to .NET platform](https://mijailovic.net/2019/01/03/sharpfuzz/)
- [Five years of fuzzing .NET with SharpFuzz](https://mijailovic.net/2023/07/23/sharpfuzz-anniversary/)
- [Let’s do DHCP: fuzzing](http://writeasync.net/?p=5714)
- [Fuzzing C# on Windows with SharpFuzz and libfuzzer-dotnet](https://github.com/ranweiler/libfuzzer-dotnet-windows-example/blob/main/README.md)
- [Automate Bug Finding: Fuzzing C# Code on Windows](https://blog.objektkultur.de/Automate-Bug-Finding-Fuzzing-C-Sharp-Code-on-Windows/)
- [Fuzzing .NET Libraries with AFL++ and SharpFuzz](https://allthingsreversed.io/20260308-fuzzing-dotnet-libraries.html)
## 战利品
如果您使用 SharpFuzz 发现了一些有趣的 bug,
并且愿意分享它们,我很乐意将它们
添加到此列表中。请给我发送电子邮件,
对 README 文件发起 pull request,或者提交一个 issue。
- [AngleSharp: HtmlParser.Parse 抛出 InvalidOperationException](https://github.com/AngleSharp/AngleSharp/issues/735) **已修复**
- [AngleSharp: HtmlParser.ParseDocument 抛出 IndexOutOfRangeException](https://github.com/AngleSharp/AngleSharp/issues/1174) **已修复**
- [AngleSharp: HtmlParser.ParseDocument 抛出 InvalidOperationException](https://github.com/AngleSharp/AngleSharp/issues/1176) **已修复**
- [AngleSharp: HtmlParser.ParseDocument 永久挂起](https://github.com/AngleSharp/AngleSharp/issues/1179) **已修复**
- [CoreFX: BigInteger.TryParse 越界访问](https://github.com/dotnet/corefx/issues/35176) **已修复**
- [CoreFX: BinaryFormatter.Deserialize 抛出许多意外异常](https://github.com/dotnet/corefx/issues/35491) **已修复**
- [CoreFX: DataContractJsonSerializer.ReadObject 抛出 ArgumentOutOfRangeException](https://github.com/dotnet/corefx/issues/35205)
- [CoreFX: DataContractJsonSerializer.ReadObject 抛出 IndexOutOfRangeException](https://github.com/dotnet/runtime/issues/1410)
- [CoreFX: DataContractSerializer.ReadObject 抛出 ArgumentNullException](https://github.com/dotnet/runtime/issues/1409)
- [CoreFX: Double.Parse 在 .NET Core 3.0 上抛出 AccessViolationException](https://github.com/dotnet/corefx/issues/35780) **已修复**
- [CoreFX: G17 格式说明符并不总能对 double 值进行往返转换](https://github.com/dotnet/corefx/issues/35369) **已修复**
- [CoreFX: Uri.TryCreate 抛出 IndexOutOfRangeException](https://github.com/dotnet/corefx/issues/35072)
- [CoreFX: XmlReader.Create 抛出 IndexOutOfRangeException](https://github.com/dotnet/corefx/issues/35073) **已修复**
- [DotLiquid: Template.Parse 抛出 ArgumentNullException 而非 SyntaxException](https://github.com/dotliquid/dotliquid/issues/333)
- [Esprima .NET: JavaScriptParser.ParseProgram 抛出 ArgumentOutOfRangeException](https://github.com/sebastienros/esprima-dotnet/issues/70) **已修复**
- [Esprima .NET: 解析大量起始括号时出现 StackOverflowException](https://github.com/sebastienros/esprima-dotnet/issues/104) **已修复**
- [ExcelDataReader: ExcelReaderFactory.CreateBinaryReader 可能抛出意外异常](https://github.com/ExcelDataReader/ExcelDataReader/issues/383) **已修复**
- [ExcelDataReader: ExcelReaderFactory.CreateBinaryReader 抛出 OutOfMemoryException](https://github.com/ExcelDataReader/ExcelDataReader/issues/382) **已修复**
- [ExCSS: StylesheetParser.Parse 抛出 ArgumentOutOfRangeException](https://github.com/TylerBrinks/ExCSS/issues/101) **已修复**
- [Fluid: FluidTemplate.TryParse 和 FluidTemplateExtensions.Render 抛出一些意外异常](https://github.com/sebastienros/fluid/issues/148) **已修复**
- [Fluid: FluidTemplateExtensions.Render 永久挂起](https://github.com/sebastienros/fluid/issues/149) **已修复**
- [Google.Protobuf: MessageParser.ParseFrom 抛出意外异常 (C#)](https://github.com/protocolbuffers/protobuf/issues/5513) **已修复**
- [GraphQL-Parser: Parser.Parse 解析 58K 文件耗时约 18 秒](https://github.com/graphql-dotnet/parser/issues/22) **已修复**
- [GraphQL-Parser: Parser.Parse 抛出 ArgumentOutOfRangeException](https://github.com/graphql-dotnet/parser/issues/21) **已修复**
- [Handlebars.Net: Handlebars.Compile 永久挂起](https://github.com/rexm/Handlebars.Net/issues/283) **已修复**
- [Handlebars.Net: 模板引擎抛出一些意外异常](https://github.com/rexm/Handlebars.Net/issues/282) **已修复**
- [Jil: JSON.DeserializeDynamic 抛出 ArgumentException](https://github.com/kevin-montrose/Jil/issues/316) **已修复**
- [Jint: Engine.Execute 可能抛出许多意外异常](https://github.com/sebastienros/jint/issues/571) **已修复**
- [Jint: Engine.Execute 耗时超过两分钟才能完成(即使设置了 2 秒超时)](https://github.com/sebastienros/jint/issues/586) **已修复**
- [Jint: Engine.Execute 在 45 秒后抛出 OutOfMemoryException(即使设置了 2 秒超时)](https://github.com/sebastienros/jint/issues/587) **已修复**
- [Json.NET: JsonConvert.DeserializeObject 可能抛出几种意外异常](https://github.com/JamesNK/Newtonsoft.Json/issues/1947) **[已修复](https://github.com/JamesNK/Newtonsoft.Json/pull/2922)**
- [Jurassic: ScriptEngine.Execute 以 StackOverflowException 终止进程](https://github.com/paulbartrum/jurassic/issues/141)
- [Jurassic: ScriptEngine.Execute 抛出一些意外异常](https://github.com/paulbartrum/jurassic/issues/142) **已修复**
- [Jurassic: ScriptEngine.ExecuteFile 永久挂起,而不是抛出 JavaScriptException](https://github.com/paulbartrum/jurassic/issues/138) **已修复**
- [Jurassic: ScriptEngine.ExecuteFile 抛出 FormatException](https://github.com/paulbartrum/jurassic/issues/137) **已修复**
- [LumenWorks CSV Reader: CsvReader.ReadNextRecord 抛出 IndexOutOfRangeException](https://github.com/phatcher/CsvReader/issues/67)
- [Markdig: Markdown.ToHtml 永久挂起](https://github.com/lunet-io/markdig/issues/278) **已修复**
- [Markdig: Markdown.ToHtml 处理 32K 文件耗时超过两分钟](https://github.com/lunet-io/markdig/issues/306) **已修复**
- [Markdig: Markdown.ToHtml 抛出 ArgumentOutOfRangeException](https://github.com/lunet-io/markdig/issues/275) **已修复**
- [Markdig: Markdown.ToHtml 抛出 IndexOutOfRangeException](https://github.com/lunet-io/markdig/issues/276) **已修复**
- [Markdig: Markdown.ToHtml 抛出 IndexOutOfRangeException](https://github.com/lunet-io/markdig/issues/303) **已修复**
- [Markdig: Markdown.ToHtml 在 GetCurrentDefinitionList 中针对 lastBlock 抛出 IndexOutOfRangeException](https://github.com/xoofx/markdig/issues/839) **已修复**
- [Markdig: Markdown.ToHtml 在 StringSlice.NextChar() 中抛出 IndexOutOfRangeException](https://github.com/xoofx/markdig/issues/840) **已修复**
- [Markdig: Markdown.ToHtml 抛出 InvalidOperationException "A block is already being replaced"](https://github.com/xoofx/markdig/issues/841) **已修复**
- [Markdig: Markdown.ToHtml 抛出 NullReferenceException](https://github.com/lunet-io/markdig/issues/277) **已修复**
- [Markdig: 转换特殊 markdown 为 HTML 时抛出 StackOverflowException](https://github.com/xoofx/markdig/issues/497) **已修复**
- [MarkdownSharp: Markdown.Transform 永久挂起](https://github.com/StackExchange/MarkdownSharp/issues/8)
- [MemoryPack: AcessViolationException from MemoryPackReader.ReadString](https://github.com/Cysharp/MemoryPack/issues/306)
- [MessagePack for C#: MessagePackSerializer.Deserialize 永久挂起](https://github.com/neuecc/MessagePack-CSharp/issues/359) **已修复**
- [MessagePack for CLI: Unpacking.UnpackObject 抛出几种意外异常](https://github.com/msgpack/msgpack-cli/issues/311)
- [Mono.Cecil: ModuleDefinition.ReadModule 可能抛出许多(可能)意外的异常](https://github.com/jbevain/cecil/issues/556)
- [Mono.Cecil: ModuleDefinition.ReadModule 永久挂起](https://github.com/jbevain/cecil/issues/555) **已修复**
- [NCrontab: CrontabSchedule.Parse 抛出 OverflowException 而不是 CrontabException](https://github.com/atifaziz/NCrontab/issues/43)
- [nHapi: 错误输入导致意外异常和永久挂起](https://github.com/nHapiNET/nHapi/issues/196) **已修复**
- [nHapi: 错误输入导致 StackOverflow/Access Violation](https://github.com/nHapiNET/nHapi/issues/198) **已修复**
- [NoStringEvaluating: Evaluator.Calc 抛出几种意外异常](https://github.com/KovtunV/NoStringEvaluating/issues/14) **已修复**
- [NUglify: Uglify.Js 永久挂起](https://github.com/xoofx/NUglify/issues/63) **已修复**
- [Open XML SDK: 添加一些安全/模糊测试](https://github.com/OfficeDev/Open-XML-SDK/issues/441)
- [OpenMCDF: 解析 Excel 文档时出现 OutOfMemoryException / 无限 while 循环](https://github.com/ironfede/openmcdf/issues/30) **已修复**
- [OpenMCDF: System.ArgumentOutOfRangeException 再现](https://github.com/ironfede/openmcdf/issues/39) **已修复**
- [OpenMCDF: 尝试打开某些无效文件时出现 System.ArgumentOutOfRangeException](https://github.com/ironfede/openmcdf/issues/38) **已修复**
- [OpenMCDF: 读取损坏的 Word 文档时出现 System.OutOfMemoryException](https://github.com/ironfede/openmcdf/issues/40) **已修复**
- [PdfPig: 读取损坏的 PDF 文档时出现 StackOverflowException](https://github.com/UglyToad/PdfPig/issues/33) **已修复**
- [protobuf-net: Serializer.Deserialize 可能抛出许多意外异常](https://github.com/mgravell/protobuf-net/issues/481)
- [protobuf-net: Serializer.Deserialize 永久挂起](https://github.com/mgravell/protobuf-net/issues/479) **已修复**
- [Scriban: Template.ParseLiquid 抛出 ArgumentOutOfRangeException](https://github.com/lunet-io/scriban/issues/121) **已修复**
- [Scriban: Template.ParseLiquid 抛出 NullReferenceException](https://github.com/lunet-io/scriban/issues/120) **已修复**
- [Scriban: Template.Render 抛出 InvalidCastException](https://github.com/lunet-io/scriban/issues/122) **已修复**
- [SharpCompress: 枚举 ZipArchive.Entries 集合抛出 NullReferenceException](https://github.com/adamhathcock/sharpcompress/issues/431)
- [SharpZipLib: ZipInputStream.GetNextEntry 永久挂起](https://github.com/icsharpcode/SharpZipLib/issues/300) **已修复**
- [SixLabors.Fonts: FontDescription.LoadDescription 抛出 ArgumentException](https://github.com/SixLabors/Fonts/issues/96) **已修复**
- [SixLabors.Fonts: FontDescription.LoadDescription 抛出 NullReferenceException](https://github.com/SixLabors/Fonts/issues/97) **已修复**
- [SixLabors.ImageSharp: 处理错误数据时在 Jpeg 位读取器中处理 EOF 以防止 DOS 攻击](https://github.com/SixLabors/ImageSharp/pull/2516) **已修复**
- [SixLabors.ImageSharp: Image.Load 以 AccessViolationException 终止进程](https://github.com/SixLabors/ImageSharp/issues/798) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 AccessViolationException](https://github.com/SixLabors/ImageSharp/issues/827) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 ArgumentException](https://github.com/SixLabors/ImageSharp/issues/826) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 ArgumentOutOfRangeException](https://github.com/SixLabors/ImageSharp/issues/825) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 DivideByZeroException](https://github.com/SixLabors/ImageSharp/issues/821) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 DivideByZeroException](https://github.com/SixLabors/ImageSharp/issues/822) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 ExecutionEngineException](https://github.com/SixLabors/ImageSharp/issues/839) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 IndexOutOfRangeException](https://github.com/SixLabors/ImageSharp/issues/824) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 NullReferenceException](https://github.com/SixLabors/ImageSharp/issues/797) **已修复**
- [SixLabors.ImageSharp: Image.Load 抛出 NullReferenceException](https://github.com/SixLabors/ImageSharp/issues/823) **已修复**
- [Utf8Json: JsonSerializer.Deserialize 可能抛出许多意外异常](https://github.com/neuecc/Utf8Json/issues/142)
- [Web Markup Minifier: HtmlMinifier.Minify 永久挂起](https://github.com/Taritsyn/WebMarkupMin/issues/73) **已修复**
- [Web Markup Minifier: HtmlMinifier.Minify 抛出 InvalidOperationException](https://github.com/Taritsyn/WebMarkupMin/issues/77) **已修复**
- [YamlDotNet: YamlStream.Load 解析 37K 文件耗时超过 60 秒](https://github.com/aaubry/YamlDotNet/issues/379)
- [YamlDotNet: YamlStream.Load 以 StackOverflowException 终止进程](https://github.com/aaubry/YamlDotNet/issues/375)
- [YamlDotNet: YamlStream.Load 抛出 ArgumentException](https://github.com/aaubry/YamlDotNet/issues/374)
## 环境要求
AFL 可在 Linux 和 macOS 上运行。如果您使用的是 Windows,可以使用任何
适用于 [Windows Subsystem for Linux] 的 Linux 发行版。如需原生 Windows 支持您可以使用 [libFuzzer](https://github.com/Metalnem/sharpfuzz/blob/master/docs/libFuzzer.md)
来代替 AFL。
您需要 GNU make 和一个可用的编译器
(gcc 或 clang)才能编译 afl-fuzz。
您还需要在计算机上安装 [.NET 8.0]
或更高版本,以便使用 SharpFuzz 对 .NET 程序集进行插桩。
为了简化您的模糊测试体验,也建议
安装 [PowerShell]。
## 安装
您可以通过运行以下 [脚本] 来安装 afl-fuzz 和 [SharpFuzz.CommandLine]
全局 .NET 工具:
```
#/bin/sh
set -eux
# 下载并解压最新的 afl-fuzz 源代码包
wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz
tar -xvf afl-latest.tgz
rm afl-latest.tgz
cd afl-2.52b/
# 安装 afl-fuzz
sudo make install
cd ..
rm -rf afl-2.52b/
# 安装 SharpFuzz.CommandLine global .NET tool
dotnet tool install --global SharpFuzz.CommandLine
```
## 使用方法
本教程假设您对 afl-fuzz 有一定程度的了解。
如果您对此一无所知,
应该先阅读 [AFL quick start guide] 和
[afl-fuzz README]。如果您有足够的时间,我也
建议阅读 [Understanding the status screen]
和 [Technical whitepaper for afl-fuzz]。
作为示例,我们将对 [Jil] 进行模糊测试,
这是一个快速的 JSON 序列化器和反序列化器
(更多完整的模糊测试项目示例请参见 [SharpFuzz.Samples])。
**1.** 创建一个新的 .NET 控制台项目,然后通过运行以下命令向其中添加 [Jil] 和
[SharpFuzz] 包:
```
dotnet add package Jil
dotnet add package SharpFuzz
```
**2.** 在您的 **Main** 函数中,使用您想要测试的函数作为参数调用 **SharpFuzz.Fuzzer.OutOfProcess.Run**:
```
using System;
using System.IO;
using SharpFuzz;
namespace Jil.Fuzz
{
public class Program
{
public static void Main(string[] args)
{
Fuzzer.OutOfProcess.Run(stream =>
{
try
{
using (var reader = new StreamReader(stream))
{
JSON.DeserializeDynamic(reader);
}
}
catch (DeserializationException) { }
});
}
}
}
```
我们想要对 Jil 的反序列化能力进行模糊测试,
这就是为什么我们要调用 **JSON.DeserializeDynamic**
方法。输入数据将通过 **stream** 参数提供给我们
(如果您测试的代码将输入作为字符串接收,
您可以使用 **Fuzzer.OutOfProcess.Run** 的另一个重载,
它接受 **Action<string>**)。
如果传递给 **Fuzzer.OutOfProcess.Run** 的代码抛出异常,
它将作为崩溃报告给 afl-fuzz。然而,
我们只想将*意外*异常视为 bug。
**DeserializationException** 是我们在
遇到无效 JSON 输入时所预期的,这就是为什么我们
在示例中捕获了它。
**3.** 创建一个包含一些测试用例的目录(通常
一个测试就足够了)。测试文件
应包含一些被您的代码接受为有效的输入,
并且应尽可能小。例如,这是我用于
测试 JSON 反序列化器的 JSON:
```
{"menu":{"id":1,"val":"X","pop":{"a":[{"click":"Open()"},{"click":"Close()"}]}}}
```
**4.** 假设您的项目名为 ```Fuzzing.csproj```
且您的测试用例位于 ```Testcases``` 目录中。
通过像这样运行 [fuzz.ps1] 脚本开始模糊测试:
```
pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i Testcases
```
对于 HTML、JavaScript、JSON 或 SQL 等格式,
使用 [字典] 文件可以极大地改善模糊测试过程。
AFL 附带了许多字典,
安装后您可以在 ```/usr/local/share/afl/dictionaries/``` 中找到它们。
考虑到这一点,我们可以像这样改进对 Jil 的模糊测试:
```
pwsh scripts/fuzz.ps1 Jil.Fuzz.csproj -i Testcases \
-x /usr/local/share/afl/dictionaries/json.dict
```
**5.** 休息一下吧!您通常会在几分钟内
得到一些有用的结果,但有时
可能需要超过一天的时间,所以请耐心等待。
导致未处理异常的输入文件将
出现在 ```findings/crashes``` 目录中。
唯一崩溃的总数将以红色显示在
afl-fuzz 状态屏幕上。
实际上,真正唯一的异常数量往往
低于报告的数量,这就是为什么通常
最好编写一个小程序,仅遍历
崩溃输入,对每个输入运行模糊测试函数,
并仅保存产生唯一堆栈跟踪的输入。
## 高级主题
- [模糊测试 .NET Core](https://github.com/Metalnem/sharpfuzz/blob/master/docs/fuzzing-dotnet-core.md)
- [进程外模糊测试](https://github.com/Metalnem/sharpfuzz/blob/master/docs/miscellaneous.md#out-of-process-fuzzing)
- [测试用例最小化](https://github.com/Metalnem/sharpfuzz/blob/master/docs/miscellaneous.md#test-case-minimization)
- [配合 SharpFuzz 使用 libFuzzer](https://github.com/Metalnem/sharpfuzz/blob/master/docs/libFuzzer.md)
- [旧版使用说明](https://github.com/Metalnem/sharpfuzz/blob/master/docs/legacy-usage-instructions.md)
## 致谢
- **Joe Ranweiler** 和 MORSE 团队 - [Windows 上的 libFuzzer 支持](https://github.com/Metalnem/sharpfuzz/pull/24)
- **Michal Zalewski** - [american fuzzy lop](http://lcamtuf.coredump.cx/afl/)
- **Dmitry Vyukov** - [go-fuzz: randomized testing for Go](https://github.com/dvyukov/go-fuzz)
- **Rody Kersten** - [Kelinci: AFL-based fuzzing for Java](https://github.com/isstac/kelinci)
- **Jb Evain** - [Mono.Cecil](https://github.com/jbevain/cecil)
- **0xd4d** - [dnlib](https://github.com/0xd4d/dnlib)
- **Guido Vranken** - [go-fuzz: libFuzzer support](https://github.com/dvyukov/go-fuzz/pull/217)
标签:AFL, AI合规, ASN解析, CVE, Fuzzing, SharpFuzz, 多人体追踪, 安全测试, 拒绝服务, 攻击性安全, 数字签名, 测试工具, 渗透测试辅助, 紫队, 覆盖率引导