首页
论坛
课程
招聘
[原创]协议Fuzz工具整合
2021-11-3 10:32 30220

[原创]协议Fuzz工具整合

2021-11-3 10:32
30220

TL; DR

概括整理协议fuzz相关的工具,针对其实现原理和过程进行总结,分析各工具优势和不足,进行横向和纵向的对比。
因为有些论文工具暂时没有包括进来,所以会长期更新完善,争取覆盖掉所有的主流协议fuzz工具。而且针对论文性质的工具,后续会出论文解读的详细内容,该文章中只做工具的整理。

一、传统工具

1. Peach

source:https://github.com/MozillaSecurity/peach

 

​ https://github.com/asudhak/peachfuzz-code

1. Description

peach是第一款综合的遵守MIT开源许可的fuzz框架,包括数据模型(数据类型、变异器接口等)、状态模型(数据模型接口、状态、动作-输入输出等)、代理(本地调试器和网络监视器)、测试引擎(代理接口、状态模型接口、Publisher、日志记录等)等,其中创建fuzzer由XML语言实现。支持对文件格式、ActiveX、网络协议、API等进行fuzz测试。peach属于基于生成的fuzz工具,使用peach进行fuzz工作的关键是编写peach pit配置文件。

 

peach首发于2004年,起初使用python开发;2013年发布peach3,转用C#开发。工具开发时间较久,目前已停止维护。

 

peach框架的体系结构可以简化如下:

 

image-20211104200322888

 

对以上各部分做简要说明:

  1. 数据模型:表示输入和输出所需要的数据结构。
  2. 变异器:使用不同的变异策略,对数据执行变异。
  3. 生成器:生成字符串数据、整型数值等简单类型的数据,还可以生成复杂的分层的二进制数据,甚至是将简单的数据使用生成器拼接起来生成更复杂的数据类型的数据。
  4. 状态模型:在每个测试用例中,用户根据状态模型配置初始有限状态机,并进行维护。
  5. 代理:与测试引擎进行通信,对被测目标进行状态监视并对其进行执行控制。
  6. 测试引擎:使用解析器对配置文件pit进行解析,根据配置文件创建相应的组件并初始化,然后进入执行测试用例的住循环。其中还包含Publisher和Logger。

2. Installation

目前官方仓库已清空所有release,所以目前只能使用网上公开的版本。在后续的测试中我们使用Windows版本,其他系统下的使用基本相同。

 

在Windows下使用peach3需要预先安装Microsoft.NET4运行时和windbg调试工具。在Windows下,解压完成压缩包后,直接使用即可:

 

image-20211220150915487

3. Usage

使用peach进行fuzz的主要步骤如下:

  1. 创建模型
  2. 选择/配置Publisher
  3. 配置代理/监视器
  4. 配置记录

我们将在后续的样例中详细介绍完整的实战使用过程。

4. Pit 文件

Peach 中定义数据的文件称为 Peach pit file,文件格式为 xml,可以理解成 Peach 根据这个 xml 模板来生成对应的数据进行 fuzz。一个 pit 文件的基本构成如下:

1
2
3
4
5
6
7
8
9
<?xml... 版本,编码等信息...>
<Peach ... 版本,作者介绍等信息...> 
<Include ...包含的外部文件/>
<DataModel>原始数据结构定义</DataModel>
<StateModel>测试逻辑、状态转换定义,如收到什么样的数据包之后,发出什么样对应的数据包</StateModel>
<Agent>检测 exception,crash等</Agent>
<Test>指定将要使用到的state,agent,publisher等</Test>
<Run>Fuzzer 执行的进入点</Run>
</Peach>

整个文件被<Peach></Peach>大标签包裹;文件中的第二级标签包括 IncludeDataModelSatateModelAgentTestRun 总计 6 种;

  1. Include: 包含的外部文件,其中 defaults.xmlPeachTypes.xml 是必须的,这俩文件中包含 Peach 的基本方法、类、数据类型等。引用被包含的 Pit 文件时, 使用名称空间前缀和冒号的格式来命名,格式为 name:DataMpdel ,如下所示:

    1
    2
    3
    <Include ns="v4ler1an" src="file:v4ler1an.xml">
    <DataModel name="DataModel"  ref="v4ler1an:NewModel">
    </DataModel>

    说明: ns,必须,名称空间前缀;src,必须,源码 URL,使用 “file: ” 前缀来命名文件名。

  2. DataModel 用于定义数据结构,标签下还可以有若干级、若干种下级标签。使用子标签可以容易地定义数据类型、大小、数据块之间的关系、CRC 校验和等,也可以定义多个 DataModel ,多个 DataModel 之间可以存在关系也可以不存在。 pit 文件中至少包含 一个 DataModel 元素,其描述的数据包括类型信息、关系信息(大小、数目、偏移)和其他让 fuzzer 执行智能变异的信息。

    1. 属性:

      • name:必须,命名需要合理,方便引用模型货调试
      • ref:必须,应用一个 DataModel 模板
      • mutable:可选,默认为真,指定该元素是否可变异
      • constraint:可选,确定一个表达式,辅助 Peach 确定数据元素是否被正确使用
    2. 子元素

      DataModel 中可以包含的子元素有:Block、Choice、Custom、Flag、Flags、Number、Padding、String、XmlAttribute、XmlElement、Relation、Fixup、Transformer、Placement

    一个 DataModel 简单的例子如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <DataModel name="Templete">
        <string name="key" />
        <string value=": " token="true"/>
        <string name="Value" />
        <string value="\r\n" token="true"/>
    </DataModel>
     
    <DataModel name="v4ler1an"  ref="Template">
        <string name="Key" value="Content-Length" />
        <string name="Value">
            <Relation type="size" of="HttpBody" />
        </string>
        <Blob name="HttpBody" />
    </DataModel>

    上面例子中,第二个 DataModel 会填充第一个的相关内容,然后进行输出。

  3. StateModel 用于定义测试的逻辑,本质上相当于一个状态机,下级标签包括 State ,每个 State 中又可以包含若干个 ActionState 表示一个状态,不同的 State 之间可以根据一些判断进行跳转,Action 用于执行打开文件,发送数据包之类的命令,Action 是发送命令给 Publisher 的一种主要方式,它能发送输出,接收输入或打开一个连接。

    一个 SateModel 简单的例子如下:

    1
    2
    3
    4
    5
    6
    7
    8
    <StateModel name="StateModel" initialState="InitialState">
        <state name="InitialState">
            <Action name="SendData" type="output">
                <DataModel ref="v4ler1an" />
                <Data name="load defaults" filename="template.bin" />
            </Action>
        </state>
    </StateModel>
  4. Test 指定使用哪个 AgentStateModel 以及发送数据的方法等;

    一个常见的 Test 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <Test name="Default">
        <!- Optionally exclude some elements from mutation ->
        <Exclude xpath="//Reserved"/>
        <Exclude xpath="//Magic" />
     
        <!--Optional agent references-->                   
        <Agent ref="LocalWindowsAgent" platform="windows" />
        <Agent ref="LocalOsxAgent" platform="osx" />
        <Agent ref="LocalLinuxAgent" platform="linux" />
        <Agent ref="RemoteAgent" />
     
        <!-- Indicate which state model to use (required) -->
        <StateModel ref="TheState" />
        <!-- Configure the publisher to use (required) -->
        <Publisher class="Tcp">
            <Param name="Host" value="127.0.0.1" />
            <Param name="Port" value="9001"
        </Publisher>
     
        <!-- Use a different fuzzing strategy -->
        <Strategy class="Random" />
     
        <!-- Log output to disk-->
        <Logger class="File">
            <Param name="Path" value="logs" />
        </Logger>
    </Test>
  5. Run ,指定当前这次 Fuzz 使用哪个 Test

5. 变异策略

  • Random:默认随机选择最大6个元素,利用随机变异器进行变异
  • Sequential:顺序对每个元素使用其所有可用的变异器进行变异
  • RandomDeterministic:默认规则,对 pit 文件中元素根据变异器生成的 lterations 链表做相对随机的顺序混淆。

Peach 3 的变异器包括元素增、删、改、交换、逐位、双字等。

1
2
3
4
5
6
7
8
9
10
11
12
<Test name="Default">
    <SateModel ref="TheStateModel" />
 
    <Publisher name="writer" class="File">
        <Param name="FileName" value="fuzzed.tmp" />
    </Publisher>
 
    <Strategy class="Random">
        <Param name="MaxFieldsToMutate" value="15" />
        <Param name="SwitchCount" value="100" />
    </Strategy>
</Test>

部分支持的变异器列表如下:

 

image-20211220200400780

6. Example

1. HelloWorld
1. pit 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<Peach xmlns="http://peachfuzzer.com/2012/Peach" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://peachfuzzer.com/2012/Peach ../peach.xsd">
 
    <DataModel name="TheDataModel">       
        <String value="Hello World!" />
    </DataModel>
 
    <StateModel name="State" initialState="State1" >
        <State name="State1"  >
            <Action type="output" >
                <DataModel ref="TheDataModel"/>
            </Action>
        </State>
    </StateModel>
 
 
    <Test name="Default">
        <StateModel ref="State"/>
        <Publisher class="Console" />
        <Logger class="File">
            <Param name="Path" value="log.txt" />
        </Logger>
 
 
    </Test>
 
</Peach>
2. 运行 Peach
1
.\Peach.exe E:\Fuzz\training\peach\HelloWorld.xml

Peach 会输出 fuzz 的目标、使用的变异器、使用的变异的数据等等:

 

image-20211220173236714

 

在 Peach 的可执行文件的同级目录下的 log.txt 文件夹中会保存运行日志:

 

image-20211220172755811

2. HTTP Fuzz
1. 环境搭建
 

搭建一个简易的 cms 来实践对 http 协议的 fuzz。

  • 源码:empirecms7.5
  • 工具:PHPStudy

按照源码的官方文档搭建即可。

2. 编写 pit 文件
 

我们使用 Burp 抓一下管理端登录流量:

 

image-20211220191635513

 

然后以此请求为基础,开发 pit 文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?xml version="1.0" encoding="utf-8"?>
<Peach xmlns="http://peachfuzzer.com/2012/Peach" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://peachfuzzer.com/2012/Peach /peach/peach.xsd">
<DataModel name="Headermodel">
    <String name="Header" />
    <String value=": "/>
    <String name="Value" />
    <String value="\r\n" />
</DataModel>
 
 
<DataModel name="HttpRequest">
    <Block name= "RequestLine">
        <String name="Method"/>
        <String value=" "/>
        <String name="RequestUri"/>
        <String value=" "/>
        <String name="HttpVersion"/>
        <String value="\r\n"/>
    </Block>
 
    <Block name="HeaderHost" ref="Headermodel">
        <String name="Header" value="Host" />
    </Block>
 
    <Block name="HeaderContentLength" ref="Headermodel">
        <String name="Header" value="Content-Length" />
        <String name="Value">
            <Relation type="size" of="httpBody.content"/>
        </String>
    </Block>
 
    <Block name="httpBody">
        <String name="content" value="length is 12" />
    </Block>
</DataModel>
 
 
 <Data name="HttpGet" >
    <Field name="RequestLine.Method" value="GET"/>
    <Field name="RequestLine.RequestUri" value="http://192.168.199.247/diguocms/e/admin/" />
    <Field name="RequestLine.HttpVersion" value="HTTP/1.1"/>
    <Field name="HeaderHost.Value" value="http://192.168.199.247"/>
    <Field name="httpBody.content" value="\r\nfuzz"/>
 </Data>
 
 <Data name="HttpOptions" ref="HttpGet">
    <Field name="RequestLine.Method" value="OPTIONS"/>
    <Field name="RequestLine.RequestUri" value="*" />
    <Field name="HeaderHost.Value" value="" />
 </Data>
 
 <StateModel name="State1" initialState="Initial">
    <State name="Initial">
        <Action type="output">
            <DataModel ref="HttpRequest"/>
            <Data ref="HttpGet"/>
        </Action>
    </State>
</StateModel>
 
<StateModel name="State2" initialState="Initial">
    <State name="Initial">
        <Action type="output">
            <DataModel ref="HttpRequest" />
            <Data ref="HttpOptions" />
        </Action>
    </State>
</StateModel>
 
<Test name="Default">
        <StateModel ref="State1"/>
 
        <Publisher class="TcpClient">
                <Param name="Host" value="192.168.199.247" />
                <Param name="Port" value="80" />
        </Publisher>
        <Logger class="File">
            <Param name="Path" value="E:\Fuzz\training\peach\logs.txt"/>
        </Logger>
</Test>
</Peach>
3. 开始运行
 

我们直接开始运行 Peach 即可:

1
.\Peach.exe E:\Fuzz\training\peach\pit-xml-samples\httpfuzz2.xml
4. 测试结果
 

因为只是说明样例,所以并没有产生实际的 crash 。我们可以在终端和 wireshark 中看到每次的 fuzz 的详细信息:

 

image-20211220194504406

 

每次的 response 大部分都是 400 ,说明是没有意义的,我们需要对 pit 文件进行更精确的定制才有可能发现漏洞。

7. 总结

Peach 的核心是 pit 文件的高度定制化,使用者需要根据自己的实际需求进行 pit 文件开发,这种开发越精确,fuzz 的成功率越高。其 fuzz 对象可以是文件、协议等,这需要使用者对文件格式、协议格式十分熟悉,才能写出高质量的 pit 文件。所以,该工具的思路比工具本身更重要。

2. Sulley

写在前面

 

由于 Sulley 在多年之前已经停止维护,且其继承者为后续将介绍的 BooFuzz,所以我们此处只对其原理等理论知识做说明,不再进行实践,详细的实践内容我们会在 BooFuzz 工具中进行展开测试。

1. Description

Sulley 是一个可开发的 fuzzer 和多个可扩展组件组成的 fuzz 框架,其相对当时其他工具的优势是简化了数据传输、表示和目标监控。其几个显著特点为:

  • 监控网络并进行记录;
  • 检测和监控目标的运行情况,可以使用多种方法恢复到“健康”状态;
  • 检测、跟踪并分类 crash;
  • 并行 fuzz;
  • 自动确定用例触发的特殊错误。

2. Installation

Sulley 的安装可以参考其官方 wiki(Windows) :https://github.com/OpenRCE/sulley/wiki/Windows-Installation。对于 *nix 平台下的安装,官方至今未发布安装流程,估计此生无缘了。

3. Usage

Sulley 的总体用法分解如下:

  1. Data Representation:分解待 fuzz 协议为单独的请求,并转换为 Sulley 中的 block;
  2. Session:将分解的请求链接成一个 session,并附加可用的 Sulley 监控代理,然后就可以开始 fuzz;
  3. Post Mortem:查看生成的数据和监控结果,重现测试用例。

这里给出 Sulley 的使用手册,感兴趣的小伙伴可自行翻阅:Sulley使用手册,其中对上面提到的概念、原理和流程均有详细的介绍。

4. 总结

Sulley 的核心是对请求的拆解,然后链接成 session,本质上与 Peach 一样,需要使用者明确 fuzz 的目标和需求,根据实际情况进行定制。

二、现代工具

1. AFLNet

source:https://github.com/aflnet/aflnet

1. Description

AFLNet是一款灰盒协议fuzz工具,采用了代码覆盖率反馈、种子变异以及状态反馈等技术。

 

与传统的基于生成的协议fuzz工具,它采用了server和client之间的通信消息数据作为种子,无需任何的协议规范。本质上是模拟一个client来发送一系列消息到server,并保留可以触发新的代码执行路径或者响应状态的变异数据。

 

AFLNet使用server端的响应码来识别消息序列触发的不同状态,根据这种反馈,AFLNet可以尽可能得向有效的状态区域靠近。

2. Installation

1. 环境

system:Ubuntu 20.04 64-bit

 

dependencies:clang, graphviz-dev

 

(对于环境要求,只要支持AFL和graphviz工具即可,对版本没有特殊要求。)

2. AFLNet

下载源码,并编译,最后设置环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# First, clone this AFLNet repository to a folder named aflnet
git clone <links to the repository> aflnet
# Then move to the source code folder
cd aflnet
make clean all
cd llvm_mode
# The following make command may not work if llvm-config cannot be found
# To fix this issue, just set the LLVM_CONFIG env. variable to the specific llvm-config version on your machine
# On Ubuntu 18.04, it could be llvm-config-6.0 if you have installed clang using apt-get
make
# Move to AFLNet's parent folder
cd ../..
export AFLNET=$(pwd)/aflnet
export WORKDIR=$(pwd)
 
export PATH=$AFLNET:$PATH
export AFL_PATH=$AFLNET

3. Usage

样例:

1
afl-fuzz -d -i in -o out -N <server info> -x <dictionary file> -P <protocol> -D 10000 -q 3 -s 3 -E -K -R <executable binary and its arguments (e.g., port number)>

选项说明:

  • -N netinfo:server信息(例如 tcp://127.0.0.1/8554)
  • -P protocol:待测试的应用协议(例如:RTSP, FTP, DTLS12, DNS, DICOM, SMTP, SSH, TLS, DAAP-HTTP, SIP)
  • -D usec:可选,server完全初始化的等待时间,微秒为单位
  • -K:可选,处理完所有请求消息后,向server发送SIGTERM信号以终止server
  • -E:可选,开启状态感知模式
  • -R:可选,开启region-level变异
  • -F:可选,启用假阴性消除模式
  • -c script:可选,server cleanup的脚本或完整路径
  • -q algo:可选,状态选择算法(1. RANDOM_SELECTION, 2. ROUND_ROBIN, 3. FAVOR)
  • -s algo:可选,种子选择算法(1. RANDOM_SELECTION, 2. ROUND_ROBIN, 3. FAVOR)

4. Example

Fuzzing Live555流媒体服务器

 

Live555是一个为流媒体提供解决方案的跨平台的C++开源项目,它实现了标准流媒体传输,是一个为流媒体提供解决方案的跨平台的C++开源项目,实现了对标准流媒体传输协议如RTP/RTCP、RTSP、SIP等的支持。

 

Live555实现了对多种音视频编码格式的音视频数据的流化、接收和处理等支持,包括MPEG、H.263+ 、DV、JPEG视频和多种音频编码。同时由于良好的设计,Live555非常容易扩展对其他格式的支持。Live555已经被用于多款播放器的流媒体播放功能的实现,如VLC(VideoLan)、MPlayer。

0. Server和client的编译和安装

为了展示fuzz成果,这里使用的Live555为2018年的一个旧版本,在这个版本中,AFLNet发现了4个漏洞,其中2个是0day。Live555的编译和安装如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
cd $WORKDIR
# Clone live555 repository
git clone https://github.com/rgaufman/live555.git
# Move to the folder
cd live555
# Checkout the buggy version of Live555
git checkout ceeb4f4
# Apply a patch. See the detailed explanation for the patch below
patch -p1 < $AFLNET/tutorials/live555/ceeb4f4.patch
# Generate Makefile
./genMakefiles linux
# Compile the source
make clean all

在上述命令中,使用了一个patch来使得目标更容易被fuzz。patch文件的主要功能是设置编译器为afl-clang-fast\fast++以实现覆盖反馈:

 

image-20211025172741697

 

禁用Live555中的随机会话id生成:

 

image-20211025172827838

 

这里的随机会话id主要是在原生的Live555版本中,会为每个连接生成一个session id,该id会用在从以连接的client发送的后续的request中,如果没有合法的id则会被server拒绝,这样就会导致fuzz过程中即使是相同的消息序列也会产生不同的执行路径,不同部分主要是session id部分的更改,所以这里就直接硬编码session id来消除这种干扰变量。

 

Live555编译成功后,在testProgs目录下会看到server端testOnDemandRTSPServer和client端testRTSPClient。可以执行以下命令进行测试:

1
2
3
4
5
6
7
8
# Move to the folder keeping the RTSP server and client
cd $WORKDIR/live555/testProgs
# Copy sample media source files to the server folder
cp $AFLNET/tutorials/live555/sample_media_sources/*.* ./
# Run the RTSP server on port 8554
./testOnDemandRTSPServer 8554
# Run the sample client on another screen/terminal
./testRTSPClient rtsp://127.0.0.1:8554/wavAudioTest

client能成功发送reqeust并接收从server发来的数据即可。

 

image-20211025173804525

1. 准备种子

AFLNet使用发送的消息序列作为种子输入,所以需要先获取消息序列。基本方法就是首先捕获一些testRTSPClient和server之间的交互数据作为种子输入,这里以请求一个wav格式的音频文件为例:

 

首先启动server:

1
2
cd $WORKDIR/live555/testProgs
./testOnDemandRTSPServer 8554

使用tcpdump捕获8554端口的所有流量并保存到pcap文件:

1
tcpdump -w rtsp.pcap -i lo port 8554

运行client发起请求:

1
./testRTSPClient rtsp://127.0.0.1:8554/wavAudioTest

交互完成后,停下tcpdump,对抓到的流量进行分析。直接跟踪TCP流查看所有发往server的数据:

 

image-20211025175412026

 

这就是在整个的交互过程中,client发出的所有的request消息序列,将它作为种子即可(需要使用的是原始数据二进制格式)。种子路径为$AFLNET/tutorials/live555/in-rtsp

 

image-20211025175621826

2. 进行fuzz
1
2
cd $WORKDIR/live555/testProgs
afl-fuzz -d -i $AFLNET/tutorials/live555/in-rtsp -o out-live555 -N tcp://127.0.0.1/8554 -x $AFLNET/tutorials/live555/rtsp.dict -P RTSP -D 10000 -q 3 -s 3 -E -K -R ./testOnDemandRTSPServer 8554

触发crash的消息序列的测试用例会放在crashesreplayable-hangs目录中。在fuzz过程中,AFLNet状态机会不断推断server的已实现状态,并相应地更新.dot文件,可以查看该文件来监控AFLNet在协议推理过程中的情况。

 

image-20211026194607837

 

image-20211026194913266

 

(备注:不做任何修改的话,这个fuzz速度慢到令人发指,具体原因暂时还未深入研究。)

3. crash重现

AFLNet自带重现工具:afl-replay

1
./afl-replay tutorials/live555/CVE_2019_7314.poc RTSP 8554

image-20211026201424376

 

(备注:官方并没有说明命令执行完成后会怎么样,反正我执行完没有任何反应,目标程序也没有发生crash)

 

获取更多的crash信息可以使用GDB调试工具调试server,或者加上Address Sanitizer-Enabled patch。

2. StateAFL

1. Description

沿用AFL的基本思路,但是提升了代码覆盖率,并且寻求最大化协议状态覆盖。StateAFl会自动推测server的当前协议状态。在编译阶段,会想目标server的内存分配和网络I/O操作插入探针;在运行阶段,会为每个协议迭代拍摄进程内存中长期驻留的数据的快照,并使用fuzzy hashing将内存状态映射到唯一的协议状态。

 

image-20211026175400142

 

(感觉本质上还是AFLNet的思路,发送请求序列,只不过在状态监控上做了另外一种方案。)

2. Installation

与AFLNet的安装方式基本相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Install clang (required by afl-clang-fast)
sudo apt-get install clang
# Install graphviz development
sudo apt-get install graphviz-dev
 
 
# First, clone this StateAFL repository to a folder named stateafl
git clone <links to the repository> stateafl
# Then move to the source code folder
cd stateafl
make clean all
cd llvm_mode
# The following make command may not work if llvm-config cannot be found
# To fix this issue, just set the LLVM_CONFIG env. variable to the specific llvm-config version on your machine
# On Ubuntu 18.04, it could be llvm-config-6.0 if you have installed clang using apt-get
make
# Move to StateAFL's parent folder
cd ../..
export STATEAFL=$(pwd)/stateafl

3. Usage

与AFLNet一毛一样。

4. Example

测试环境与AFLNet的一样,这里直接执行fuzz,看看效果如何:

 

image-20211026192011628

 

image-20211026192600485

 

速度上比AFLNet会快一丢丢,在覆盖率上也会高一点。

 

(自带的语料库没法触发漏洞,忽略这个吧,真实场景下的语料库需要精心设计和构造。)

3. BooFuzz

4.protocol-fuzzer-ce

。。。 。。。

三. ProFuzzBench

这是一个对于网络协议相关fuzz工具的测试集合,可以方便地对流行的几款协议fuzz工具进行使用测试。

 

ProFuzzBench是一个有状态的网络协议测试的基准,包含了多个用于测试流行网络协议(TLS, SSH, SMTP, FTP, SIP等)的server。

 

ProFuzzBench提供了自动化执行fuzz的脚本,截止目前包含的fuzz工具有:AFLnwe(基于网络的AFL版本,使用TCP/IP sockets替代文件作为输入)、AFLNet(一款针对有状态网络协议的fuzz工具),而StateAFL(另一款针对有状态网络协议的fuzz工具)尚未提供自动化执行脚本,可直接使用原生的StateAFL进行fuzz。

 

其项目结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protocol-fuzzing-benchmark
├── subjects: this folder contains all protocols included in this benchmark and
│   │         each protocol may have more than one target server
│   └── RTSP
│   └── FTP
│   │   └── LightFTP
│   │       └── Dockerfile: subject-specific Dockerfile
│   │       └── run.sh: (subject-specific) main script to run experiment inside a container
│   │       └── cov_script.sh: (subject-specific) script to do code coverage analysis
│   │       └── other files (e.g., patches, other subject-specific scripts)
│   └── ...
└── scripts: this folder contains all scripts to run experiments, collect & analyze results
│   └── execution
│   │   └── profuzzbench_exec_common.sh: main script to spawn containers and run experiments on them
│   │   └── ...
│   └── analysis
│       └── profuzzbench_generate_csv.sh: this script collect code coverage results from different runs
│       └── profuzzbench_plot.py: sample script for plotting
└── README.md

接下来以LightFTP为例进行fuzz。

0. Installation and Setup

首先,下载ProFuzzBench的源码并设置环境变量:

1
2
3
4
git clone https://github.com/profuzzbench/profuzzbench.git
cd profuzzbench
export PFBENCH=$(pwd)
export PATH=$PATH:$PFBENCH/scripts/execution:$PFBENCH/scripts/analysis

然后,创建lightFTP server的docker image:

1
2
3
4
5
6
7
8
9
cd $PFBENCH
cd subjects/FTP/LightFTP
docker build . -t lightftp
 
# 为了提高build效率,可以使用以下命令:
# docker build . -t lightftp --build-arg -j4
 
# 使用StateAFL时,使用的是额外定制Dockfile:Dockerfile-stateafl,所以使用的build命令需要指明使用的dockerfile
docker build . -f Dockerfile-stateafl -t lightftp-stateafl

1. Run Fuzzing

执行profuzzbench_exec_common.sh脚本开启环境,这里涉及到8个参数:

  • Docimage:指定docker image
  • Runs:runs的实例数,每个container跑一个fuzz过程,类似于并行fuzz
  • Saveto:结果的保存路径
  • Fuzzer:指定使用的fuzzer name
  • Outdir:docker container中创建的output文件夹名称
  • Options:除了目标特定的 run.sh 脚本中编写的标准选项之外,fuzz所需的所有选项
  • Timeout:fuzz时长,秒为单位
  • Skipcount:用于计算覆盖率时间,例如Skipcount=5就是说每5个test case后执行一次gcov

以下指令就是在10分钟内执行4个AFLNet实例和4个AFLnwe实例来对LightFTP进行fuzz:

1
2
3
4
5
cd $PFBENCH
mkdir results-lightftp
 
profuzzbench_exec_common.sh lightftp 4 results-lightftp aflnet out-lightftp-aflnet "-P FTP -D 10000 -q 3 -s 3 -E -K" 3600 5 &
profuzzbench_exec_common.sh lightftp 4 results-lightftp aflnwe out-lightftp-aflnwe "-D 10000 -K" 3600 5

AFLNet的fuzz结果如下:

 

image-20211026142727824

 

输出结果保存在了`results-lightftp目录中:

 

image-20211026142951989

 

一个fuzzer实例产生一个.tar.gz文件,每个.tar.gz文件包含了这次fuzz过程产生的所有数据。

 

类似的,AFLnwe的输出一样:

 

image-20211026144548361

 

这两个工具对比起来,fuzz效果都一般般,但AFLNet的速度会快一些,相对而言,比AFLnwe效果也好一些。cov_over_time数据对比如下:

 

image-20211026144930796

2. Collect the results

对于覆盖率信息(也就是上面的表格)的处理,ProFuzzBench提供了处理覆盖率的自动化工具profuzzbench_generate_cssv.sh,参数说明如下:

  • prog:subject program的名字,例如lightftp
  • runs:runs数量
  • fuzzer:fuzzer的name,例如AFLNet
  • covfile:CSV格式的输出文件
  • append:append模式

可以使用下面的命令来处理fuzzer跑出来的覆盖率信息文件:

1
2
3
4
cd $PFBENCH/results-lightftp
 
profuzzbench_generate_csv.sh lightftp 4 aflnet results.csv 0
profuzzbench_generate_csv.sh lightftp 4 aflnwe results.csv 1

输出结果为results.csv文件:

 

image-20211026164017059

 

文件中的第一列为时间戳,第二列为目标程序,第三列为fuzzer,第四列为运行的index,第五列为coverage type,第六列为type的值。文件包含了随时间变化的line coverage和branch coverage信息,每个coverage type都包含两个值:百分比 (_per) 和绝对数量 (_abs)。

3. Analysis the results

前面生成的results.csv文件可以进一步进行绘图显示,使用脚本profuzzbench_plot.py:

1
2
3
cd $PFBENCH/results-lightftp
 
profuzzbench_plot.py -i results.csv -p lightftp -r 4 -c 60 -s 1 -o cov_over_time.png

处理完成后,可以看到处理结果:

 

image-20211026165419776

 

从这里也能看出AFLNet比AFLnwe的效果要好太多。其实这个脚本的实现也不难,python中有很多成熟的库。

4. Conclusion

该工具支持添加自定义的fuzzer,按照stateafl的添加方式来进行添加即可,但是个人感觉以docker模式运行,速度上肯定要变慢。该工具值得肯定的是将常见的几个网络协议的fuzz环境能实现自动化搭建,可以节省一定的环境搭建时间成本。看个人需求吧,侧重效率的话还是要自行根据需求搭建独立环境。

 

该工具目前支持的协议环境有:

 

image-20211026170043679

 

支持自定义添加协议,官方的开发文档也算完善,还是比较值得尝试的(毕竟也没有其他更好的选择了-。-)。

未完待续。。。


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

最后于 2022-1-17 09:47 被有毒编辑 ,原因:
收藏
点赞5
打赏
分享
最新回复 (8)
雪    币: 9703
活跃值: 活跃值 (9580)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2 2021-11-3 15:54
2
1
booFuzz能算是协议Fuzz吗?有时候我感觉afl并没有网传的那么好用……
雪    币: 15100
活跃值: 活跃值 (13793)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
有毒 活跃值 10 2021-11-3 16:02
3
0
pureGavin booFuzz能算是协议Fuzz吗?有时候我感觉afl并没有网传的那么好用……
算,基于生成的工具我都还没有整合进来。不同工具有不同的适用场景,如果是单文件的fuzz,afl还可以,但大部分情况下都要做定制,原生的效果不好。
雪    币: 9703
活跃值: 活跃值 (9580)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2 2021-11-4 10:04
4
0
有毒 算,基于生成的工具我都还没有整合进来。不同工具有不同的适用场景,如果是单文件的fuzz,afl还可以,但大部分情况下都要做定制,原生的效果不好。
我实际应用下来如果是确定了数据包的字段或者是针对某一个字段做测试的话,booFuzz更快而且出crash的几率更高
雪    币: 15100
活跃值: 活跃值 (13793)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
有毒 活跃值 10 2021-11-4 10:18
5
0
pureGavin 我实际应用下来如果是确定了数据包的字段或者是针对某一个字段做测试的话,booFuzz更快而且出crash的几率更高
嗯嗯,这是基于生成的,和AFL不是一个思路。但是开源协议基本被玩的差不多了,很多情况下是没有协议详细信息的,生成的就用不上了。
雪    币: 15100
活跃值: 活跃值 (13793)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
有毒 活跃值 10 2021-12-28 14:24
6
0

新增 Peach工具初步使用

最后于 2021-12-28 14:24 被有毒编辑 ,原因:
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_qudtuude 活跃值 2022-1-14 17:14
7
0
请教下,在测试网络协议时候, 使用传统工具如peach 可以在无代码情况下即可, 但是像afl这种的需要插桩,如何做到测试网络协议? 感觉应用前景不是很好啊。在实际应用中客户不可能拿代码让你测试
雪    币: 233
活跃值: 活跃值 (801)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
hackbs 活跃值 2022-1-14 20:11
8
0
哈哈 楼主的壁纸挺好看的,能分享下吗谢谢。
雪    币: 15100
活跃值: 活跃值 (13793)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
有毒 活跃值 10 2022-1-17 09:15
9
0
hackbs 哈哈 楼主的壁纸挺好看的,能分享下吗谢谢。
没问题,我稍微晚一会就上传到附件
游客
登录 | 注册 方可回帖
返回