Peach

Peach是一款基于变异的模糊测试工具,被广泛应用于各种协议的测试。

编译

Gitlab在2020年收购Peach Fuzzer的母公司后,基于Peach Fuzzer Professional v4开发出协议测试工具GitLab Protocol Fuzzer,使用方法变化不大,所以下文都是基于GitLab Protocol Fuzze。

由于官方不提供编译好的二进制文件,需要自己编译,推荐是在Ubuntu 16.04上编译, Ubuntu 18.04实测也可以。

本文提供了两种编译方式,本地编译以及CI编译,其中本地编译要踩的坑比较多。

本地编译

安装过程主要参考
https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce/-/issues/2#note_676566894

安装编译依赖的包

apt-get install -y \
    coreutils apt-utils wget curl openssl ca-certificates bash-completion \
    joe vim nano \
    unzip p7zip \
    fping hping3 httping thc-ipv6 gdb \
    tcpdump wireshark-common \
    locales-all \
    git build-essential joe vim strace tcpdump python python-pip \
    ruby doxygen libxml2-utils less openjdk-8-jre xsltproc asciidoctor \
    nodejs node-typescript wget \
    apt-transport-https dirmngr gnupg ca-certificates apt-utils

编译过程中需要用到Paket这个包管理工具下载相关依赖,由于国内网络原因,即使挂代理,也很容易因为网络原因而下载失败,强烈建议在海外主机上编译

这里把代码里面自带的Paket去掉,下载最新版本Paket替代(截止至2021/12/10,最新版本6.2.1)

git clone https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce
cd protocol-fuzzer-ce/paket/.paket
rm -f paket.exe
rm -f paket.bootstrapper.exe
rm -f paket.targets
wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.bootstrapper.exe
wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.targets
wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.exe
wget https://github.com/fsprojects/Paket/releases/download/6.2.1/Paket.Restore.targets
cd ../../

下载最新版pintool放在3rdParty/pin/目录下,同时修改build配置

wget https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz
mv pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz 3rdParty/pin/
cd 3rdParty/pin/ && tar -xf pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz && mv pin-3.21-98484-ge7cd811fd-gcc-linux pin-3.21-98484-gcc-linux
sed -i s/pin-3.19-98425-gcc-linux/pin-3.21-98484-gcc-linux/g build/config/linux.py
cd ../../

下载Mono,官方要求是4.x版本,实测是有问题的,这里我们直接从官方源下载最新版

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list
apt-get update -y
apt-get install -y mono-devel

对部分代码打Patch,不Patch的话编译过程会报错
参见
https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce/-/issues/1
https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce/-/merge_requests/7

sed -i '/^int main.*/itemplate<bool b>\nstruct StaticAssert {};\ntemplate <>\nstruct StaticAssert<true>\n{\n    static void myassert() {}\n};\n' core/BasicBlocks/bblocks.cpp
sed -i 's/STATIC_ASSERT(sizeof(size_t) == sizeof(ADDRINT))/StaticAssert<sizeof(size_t) == sizeof(ADDRINT)>::myassert()/g' core/BasicBlocks/bblocks.cpp
sed -i 's/var config = new LicenseConfig();/\/\/var config = new LicenseConfig();/g' pro/Core/Runtime/BaseProgram.cs

一切正常的话linux_x86,linux_x86_64都应该是Available状态

./waf configure

如果遇到问题,可以尝试

./waf configure -v

可能会遇到的问题有两类

  • 报错如下的是因为Mono版本问题,按上面说的,添加官方源后下载最新版本
    linux_x86 is not available: Command ['/usr/bin/mono', '/home/xxxx/protocol-fuzzer-ce/paket/.paket/paket.exe', 'restore'] returned 1
  • 报错如下是因为Paket版本问题,按上面说的,下载最新版替换掉原来的
    linux_x86 is not available: Command ['/usr/bin/mono', '/home/xxxx/protocol-fuzzer-ce/paket/.paket/paket.bootstrapper.exe'] returned 1

开始编译

./waf build

重点,编译完成后,不要直接执行install,必须要先把mono版本降级到4.x,否则后面会失败

apt purge -y mono* libmono* doxygen
rm /etc/apt/sources.list.d/mono-official-stable.list
apt update -y
apt install -y mono-complete
./waf install

一切顺利的话,output目录下会有编译好的二进制文件

CI 编译

CI配置文件如下,Fork官方repo之后,main分支创建CI/CD流水线即可

image: ubuntu:18.04

stages:
    - build

builder:
    stage:
        build
    script:
        - export DEBIAN_FRONTEND=noninteractive
        - apt-get update -qq
        - apt-get install -y -qq gnupg2
        - apt-get install -y -qq gcc
        - apt-get install -y -qq g++
        - apt-get install -y -qq g++-multilib

        - apt-get install -y -qq python
        - apt-get install -y -qq ruby

        - apt-get install -y -qq curl
        - apt-get install -y -qq nodejs
        - apt-get install -y -qq node-typescript

        - apt-get install -y -qq default-jdk
        - apt-get install -y -qq doxygen
        - apt-get install -y -qq libxml2-utils
        - apt-get install -y -qq xsltproc
        - apt-get install -y -qq wget

        - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
        - apt install -y apt-transport-https ca-certificates
        - echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | tee /etc/apt/sources.list.d/mono-official-stable.list
        - apt update -qq -y
        - apt-get install -y mono-devel
        - cd paket/.paket
        - rm -f paket.exe
        - rm -f paket.targets
        - rm -f paket.bootstrapper.exe
        - wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.bootstrapper.exe
        - wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.targets
        - wget https://github.com/fsprojects/Paket/releases/download/6.2.1/paket.exe
        - wget https://github.com/fsprojects/Paket/releases/download/6.2.1/Paket.Restore.targets
        - cd ../../
        - wget https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz
        - mv pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz 3rdParty/pin/
        - cd 3rdParty/pin/ && tar -xf pin-3.21-98484-ge7cd811fd-gcc-linux.tar.gz && mv pin-3.21-98484-ge7cd811fd-gcc-linux pin-3.21-98484-gcc-linux
        - cd ../../
        - sed -i s/pin-3.19-98425-gcc-linux/pin-3.21-98484-gcc-linux/g build/config/linux.py
        - sed -i '/^int main.*/itemplate<bool b>\nstruct StaticAssert {};\ntemplate <>\nstruct StaticAssert<true>\n{\n  static void myassert() {}\n};\n' core/BasicBlocks/bblocks.cpp
        - sed -i 's/STATIC_ASSERT(sizeof(size_t) == sizeof(ADDRINT))/StaticAssert<sizeof(size_t) == sizeof(ADDRINT)>::myassert()/g' core/BasicBlocks/bblocks.cpp
        - sed -i 's/var config = new LicenseConfig();/\/\/var config = new LicenseConfig();/g' pro/Core/Runtime/BaseProgram.cs
        - ./waf configure
        - ./waf build
        - apt purge -y mono* libmono* doxygen
        - rm /etc/apt/sources.list.d/mono-official-stable.list
        - apt update -y
        - apt install -y mono-complete
        - apt install -y mono-devel
        - ./waf install
    artifacts:
        untracked: false
        expire_in: 30 days
        paths:
            - output/

基础

使用Peach进行模糊测试可以分为几个步骤

  • 创建数据模型
  • 创建状态模型
  • 添加Publisher
  • 添加Monitor

Pit文件

Peach pit文件是一个XML格式的配置文件,它定义了模糊测试所需要的信息,文件里面的内容包括数据模型、状态模型等等。

以下是Peach提供的一个示例

<!-- 版本信息等,一般情况下不做改动 -->
<?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>

    <!-- 定义状态模型 initialState表示初始状态 -->
    <StateModel name="State" initialState="State1" >
        <!-- 定义状态 -->
        <State name="State1"  >
            <!-- 具体动作,output表示外发数据 -->
            <Action type="output" >
                <DataModel ref="TheDataModel"/>
            </Action>
        </State>
    </StateModel>

    <!-- 配置要使用的状态模型、数据模型等等 -->
    <Test name="Default">
                <!-- 指定要使用的状态模型 -->
        <StateModel ref="State"/>
        <!-- 指定Publisher,用于将生成的数据传输出去,Console表示打印到命令行 -->
        <Publisher class="Console" />

    </Test>

</Peach>
<!-- end -->

一般pit文件保存在pits目录下,运行

Peach.exe pits/example.xml

DataModel

DataModel描述了数据包中数据的类型、格式、大小等等信息。同时,DataModel还可以被其他DataModel通过ref所引用,类似于编程语言中的继承。

Peach支持非常多类型的数据,下面介绍几种常用的数据类型

Number

Peach支持从1到64比特任意长度的数字,同时可以定制字节序、符号等信息。
常用的属性:
size:比特长度(1-64)
value:默认值
valueType:类型(string/hex)
endian:字节序
signed:有无符号
mutable:是否允许变异,默认为true

<Number name="test" size="32" endian="big" signed="false"/>

String

字符串
常用属性:
length:长度(字节)
type:编码类型,默认utf8
value:默认值
nullTerminated:末尾是否添加NULL截断

<String name="test" value="test"/>

Blob

Blob通常用于表示二进制数据
常用属性:
length:长度(字节)
valueType:格式(hex/string)

<Blob name="test" valueType="hex" value ="1F 22 03"/>

Flags与Flag

Flags是Flag元素的容器,由于旧版本Peach不支持任意比特长度的Number元素,Flag被用来表示只占用一个或几个比特的标志位

<Flags name="flags" size="16">
    <Flag name="flag1" position="0" size="1"/>
    <Flag name="flag2" position="1" size="5"/>
</Flags>

Block

Block是一个容器元素,与DataModel类型,但区别是Block是DataModel的子元素,同样的,Block也支持被DataModel引用

<Block name="hello">
    <Number value="1"/>
    <String value="test"/>
</Block>

DNS

RFC1035定义了DNS报文格式

DNS Header

我们可以先定义出大致的结构,并给与合适的初始值

<DataModel name="Header">
    <Number name="ID" size="16"/>
    <Number name="QR" size="1" />
    <Number name="Opcode" size="4" />
    <Number name="AA" size="1" />
    <Number name="TC" size="1" />
    <Number name="RD" size="1" value="1" />
    <Number name="RA" size="1" />
    <Number name="Z" size="3" />
    <Number name="RCODE" size="4" />
    <Number name="QDCOUNT" size="16"/>
    <Number name="ANCOUNT" size="16"/>
    <Number name="NSCOUNT" size="16"/>
    <Number name="ARCOUNT" size="16"/>
</DataModel>

Question

先来看看查询报文

查询报文有三个部分,QTYPE、QCLASS使用Number表示即可,但QNAME部分采用了DNS标准名称表示法,详细可参考RFC1035文档。

简单来说,每个域名(QNAME)是由一系列label构成,每个label第一个字节高两位被用来表示label的类型,一共有两种类型:00表示普通label,11表示压缩label

普通label
第一个字节高两位为00时,表示为普通label,剩下6比特被用来表示label的大小
以 www.baidu.com 为例,可以分为三个label,分别是www、baidu、com,用普通label表示为\x03www\x05baidu\x03com\x00

压缩label
第一个字节高两位为11时,表示为压缩label,剩下6比特与后面的字节共14比特构成一个指针,指针的值为对应字符串的偏移。
由于一个报文内可以同时有多个域名,而这些域名有一些部分是公共的,比如com这类后缀,通过指针可以节省空间。

下面这张图为例子,第二个域名为 www.example.com, 由于example.com在前面出现过,偏移为0xC,所以可以直接用指针

所以QNAME一共有三种情况:
1.全部由普通label表示,最后以NULL结尾
2.只有一个压缩label
3.前面由普通label表示,最后一个压缩label

普通label中,size的取值取决于后面的长度,这里用到Relation这个属性,取后面的长度赋值给size

<Block name="Label1">
    <Number name="flag" size="2" value="0" mutable="false"/>
    <Number name="size" size="6">
        <Relation type="size" of="id"/>
    </Number>
    <String name="id" value="www" nullTerminated="false"/>
</Block>

压缩label就比较简单

<Block>
    <Number name="flag" value="3" size="2" mutable="false"/>
    <Number size="14"/>
</Block>

第一种情况全部由普通label表示,最后以NULL结尾

<Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="www" nullTerminated="false"/>
    </Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="google" nullTerminated="false"/>
    </Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="com" nullTerminated="false"/>
    </Block>
    <Blob name="NULL" length="1" valueType="hex" mutable="false" value="00"/>
</Block>

第二种情况 只有一个压缩label

<Block>
    <Number name="flag" value="3" size="2" mutable="false"/>
    <Number size="14"/>
</Block>

第三种情况前面由普通label表示,最后一个压缩label

<Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="www" nullTerminated="false"/>
    </Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="google" nullTerminated="false"/>
    </Block>
    <Block occurs="1">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
            <Relation type="size" of="id"/>
        </Number>
        <String name="id" value="com" nullTerminated="false"/>
    </Block>
    <Block>
        <Number name="flag" value="3" size="2" mutable="false"/>
        <Number size="14"/>
    </Block>
</Block>

将三种情况通过Choice组合在一起,Fuzz过程中,Peach会随机在Choice中挑选一个来执行,类似于C语言中的switch

<DataModel name="Label">
    <Number name="flag" size="2" value="0" mutable="false"/>
    <Number name="size" size="6">
        <Relation type="size" of="id"/>
    </Number>
    <String name="id" nullTerminated="false"/>
</DataModel>

<DataModel name="Labels">
    <Block ref="Label" occurs="1">
        <String name="id" value="www" nullTerminated="false"/>
    </Block>
    <Block ref="Label" occurs="1">
        <String name="id" value="google" nullTerminated="false"/>
    </Block>
    <Block ref="Label" occurs="1">
        <String name="id" value="com" nullTerminated="false"/>
    </Block>
</DataModel>

<DataModel name="QNAME">
    <Choice>
        <Block ref="Labels">
            <Blob name="NULL" length="1" valueType="hex" mutable="false" value="00"/>
        </Block>
        <Block ref="Labels">
            <Number name="flag" value="3" size="2" mutable="false"/>
            <Number size="14"/>
        </Block>
        <Block>
            <Number name="flag" value="3" size="2" mutable="false"/>
            <Number size="14"/>
        </Block>
    </Choice>
</DataModel>

Header中的QDCOUNT取决于Question的数量,同样用Relation处理

<DataModel name="DNS" ref="Header">
    <Number name="QDCOUNT" size="16" mutable="true">
        <Relation type="count" of="Question"/>
    </Number>
    <Block name="Question" ref="QNAME" maxOccurs="10">
        <Number name="QTYPE" size="16" valueType="hex" mutable="false" value="00 01"/>
        <Number name="QCLASS" size="16" valueType="hex" mutable="false" value="00 01"/>
    </Block>
</DataModel>

到此数据建模部分基本完结,有些地方处理的方式比较粗糙,希望多多指教

StateModel

DNS协议通信比较简单,分别定义一个output跟input的action,这里我们不关心返回的结果,直接用Blob去匹配就行

<StateModel name="State" initialState="State1" >
    <!-- 定义状态 -->
    <State name="State1"  >
        <!-- 具体动作,output表示外发数据 -->
        <Action type="output" >
            <DataModel ref="DNS"/>
        </Action>
        <Action type="input" >
            <DataModel>
                <Blob />
            </DataModel>
        </Action>
    </State>
</StateModel>

Publisher

Publisher是Peach Fuzzer的IO接口,所有的数据都是经过Publisher来处理,Peach支持相当多种类的Publisher,如Udp、Tcp、RawSocket、CAN、File等等。DNS协议只要涉及到Tcp与Udp这两个,具体支持的参数可查阅官方文档 https://gitlab.com/gitlab-org/security-products/protocol-fuzzer-ce/-/tree/main/docs/src.pro/Common/Monitors

<Publisher class="TcpClient">
    <Param name="Host" value="8.8.8.8"/>
    <Param name="Port" value="53" />
</Publisher>

<Publisher class="Udp">
    <Param name="Host" value="8.8.8.8"/>
    <Param name="Port" value="53" />
</Publisher>

Monitor

Monitor是Peach用来观察Fuzz对象状态的模块,Peach支持许多种类的Monitor,常用的有Ping Monitor、Socket Monitor、TcpPort Monitor、Run Command等等

TCP比较好处理,在每轮循环结束的时候,检测目标端口,当为Closed的时候,生成Fault

<Monitor class="TcpPort">
    <Param name="Host" value="8.8.8.8" />
    <Param name="Port" value="53" />
    <Param name="Action" value="Fault" />
    <Param name="State" value="Closed" />
    <Param name="When" value="OnIterationEnd" />
</Monitor>

由于不好检测Udp端口是否开放,因此可以采用Run Command来检测,每次循环结束,执行自定义脚本,确定dns服务器是否正常

monitor.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-"

import dns.resolver

myResolver = dns.resolver.Resolver()
myResolver.nameservers = ['8.8.8.8']
try:
    myAnswers = myResolver.query("www.baidu.com", "A",lifetime=2)
except:
    exit(-1)

当自定义脚本返回值非0时,就认为产生错误

<Monitor class="RunCommand">
    <Param name="Command" value="python3"/>
    <Param name="Arguments" value="./pits/monitor.py" />
    <Param name="FaultOnNonZeroExit" value="true" />
    <Param name="When" value="OnIterationEnd" />
</Monitor>

优化

Peach支持许多种类的变异器(Mutator),但并不是所有的变异器都是我们想要使用的,可通过exclude去除掉不需要的变异器,相反地,也可以通过include指定变异器

<Mutators mode="exclude">
            <Mutator class="DataElementDuplicate"/>
            <Mutator class="DataElementRemove"/>
            <Mutator class="DataElementSwapNearNodes"/>
            <Mutator class="DataElementSwapNear"/>
        </Mutators>

测试

将dns.xml保存至pits目录下,开始执行Peach.exe pits/dns.xml
dns.xml

<?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">

    <!-- 默认配置 -->
    <Defaults>
        <Number endian="big" />
    </Defaults>

    <!-- 定义数据模型 -->
    <DataModel name="Header">
        <Number name="ID" size="16" value="1234"/>
        <Number name="QR" size="1"  mutable="false"/>
        <Number name="Opcode" size="4"  mutable="false"/>
        <Number name="AA" size="1"  mutable="false"/>
        <Number name="TC" size="1"  mutable="false"/>
        <Number name="RD" size="1" value="1"  mutable="false"/>
        <Number name="RA" size="1"  mutable="false"/>
        <Number name="Z" size="3"  mutable="false"/>
        <Number name="RCODE" size="4"  mutable="false"/>
        <Number name="QDCOUNT" size="16" mutable="false"/>
        <Number name="ANCOUNT" size="16"  mutable="false"/>
        <Number name="NSCOUNT" size="16"  mutable="false"/>
        <Number name="ARCOUNT" size="16" mutable="false" />
    </DataModel>

    <DataModel name="Label">
        <Number name="flag" size="2" value="0" mutable="false"/>
        <Number name="size" size="6">
        <Relation type="size" of="id"/>
        </Number>
        <String name="id" nullTerminated="false"/>
    </DataModel>

    <DataModel name="Labels">
        <Block ref="Label" occurs="1">
            <String name="id" value="www" nullTerminated="false"/>
        </Block>
        <Block ref="Label" occurs="1">
            <String name="id" value="google" nullTerminated="false"/>
        </Block>
        <Block ref="Label" occurs="1">
            <String name="id" value="com" nullTerminated="false"/>
        </Block>
    </DataModel>

    <DataModel name="QNAME">
        <Choice>
            <Block ref="Labels">
                <Blob name="NULL" length="1" valueType="hex" mutable="false" value="00"/>
            </Block>
            <Block ref="Labels">
                <Number name="flag" value="3" size="2" mutable="false"/>
                <Number size="14"/>
            </Block>
            <Block>
                <Number name="flag" value="3" size="2" mutable="false"/>
                <Number size="14"/>
            </Block>
        </Choice>
    </DataModel>

    <DataModel name="DNS" ref="Header">
        <Number name="QDCOUNT" size="16" mutable="true">
            <Relation type="count" of="Query"/>
        </Number>
        <Block name="Query" ref="QNAME" maxOccurs="10">
            <Number name="QTYPE" size="16" valueType="hex" mutable="false" value="00 01"/>
            <Number name="QCLASS" size="16" valueType="hex" mutable="false" value="00 01"/>
        </Block>
    </DataModel>

    <!-- 定义状态模型 initialState表示初始状态 -->
    <StateModel name="State" initialState="State1" >
        <!-- 定义状态 -->
        <State name="State1"  >
            <!-- 具体动作,output表示外发数据 -->
            <Action type="output" >
                <DataModel ref="DNS"/>
            </Action>
        </State>
    </StateModel>

    <!-- Monitor -->
    <Agent name="TheAgent">
        <Monitor class="RunCommand">
            <Param name="Command" value="python3"/>
            <Param name="Arguments" value="./pits/monitor.py" />
            <Param name="FaultOnNonZeroExit" value="true" />
            <Param name="When" value="OnIterationEnd" />
        </Monitor>
    </Agent>

    <!-- 设置maxOutputSize以防止产生过大数据包 -->
    <Test name="Default" maxOutputSize="100000" >
        <!-- 变异策略 -->
        <Strategy class="Random">
            <Param name="MaxFieldsToMutate" value="6" />
            <Param name="SwitchCount" value="200" />
        </Strategy>
        <Mutators mode="exclude">
            <Mutator class="DataElementDuplicate"/>
            <Mutator class="DataElementRemove"/>
            <Mutator class="DataElementSwapNearNodes"/>
            <Mutator class="DataElementSwapNear"/>
        </Mutators>
        <!-- 指定要使用的状态模型 -->
        <StateModel ref="State"/>
        <!-- 指定Publisher -->
        <Publisher class="Udp">
            <Param name="Host" value="8.8.8.8"/>
            <Param name="Port" value="53" />
        </Publisher>
        <Agent ref="TheAgent"/>
    </Test>
</Peach>


Wireshark抓包观察到畸形报文

完结

如果有不正确的地方,请各位大佬多多指点

点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖