sulley 是一款模糊测试框架,可以使用 sulley 进行协议Fuzzing。Sulley(以作者的观点来看)所具有的能力超过了以前所发布的大多数模糊测试技术,包括商业工具和那些在公开领域中可用的工具。该框架的目标是不仅要简化数据的表示,而且还要简化数据的传输以及对目标的监视。Sulley从Monsters,Inc创建之后就被亲切的命名 ,因为它是模糊化的工具。现在sulley 已经停止更新,不在维护。
sulley 安装教程
sulley 的Windows的安装 网上教程很多, 对于linux的安装比较少. 这是linux的安装教程
安装测试环境
deepin 15.3
python2.7
安装系统环境:
$ sudo apt-get install python
$ Sudo apt-get install flex
$ Sudo apt-get install bison
Install libpcap-1.4.0
http://www.tcpdump.org/release/libpcap-1.4.0.tar.gz
$ ./configure
$ make
$ sudo make install
$ sudo apt-get install libpcap-dev
$ sudo apt-get install python-pcapy
之后下载sulley目录
git clone https://github.com/Bit9/sulley.git sulley
由于在linux 还需要相关依赖
所以下载
解压vdb在sulley 的父目录下 即跟sulley 处于同一目录
最后的目录结构
.
├── sulley
│ ├── archived_fuzzies
│ ├── AUTHORS.txt
│ ├── CONTRIBUTORS.txt
│ ├── docs
│ ├── ftp_session.py
│ ├── init.py
│ ├── installer
│ ├── INSTALL.txt
│ ├── LICENSE.txt
│ ├── network_monitor.py
│ ├── process_monitor.py
│ ├── README.md
│ ├── requests
│ ├── session_test.udg
│ ├── sulley
│ ├── unit_test.py
│ ├── unit_tests
│ ├── utils
│ ├── vmcontrol.py
│ └── wftpserver.session
└── vdb
├── cobra
├── docs
├── Elf
├── envi
├── mach
├── PE
├── README
├── scripts
├── vdb
├── vdbbin
├── visgraph
├── vqt
├── vstruct
├── vtrace
└── vwidget
安装python 环境
python 环境下需要安装 distorm 包
pip install distorm3
pip install pcapy
pip install
sulley 目录结构
在Sulley的目录结构中存在着一些技巧。对目录结构进行维护将可以确保当你使用用户定义的复杂类型、请求以及工具对模糊器进行扩展时,目录中的所有内容仍然是有组织的。下面的层次关系指出了你需要了解的有关目录结构的一些内容:
-
archived_fuzzies:这是一个自由格式的目录,由模糊测试目标应用的名字进行组织,以存储已存档的模糊器以及从模糊测试会话中所生成的数据。
-
trend_server_protect_5168:包含将在本文档后面的单步遍历中被引用的已执行完毕的模糊测试。
-
trillian_jabber:包含文档将引用的另外一个已执行完毕的模糊测试。
-
audits:针对活动的模糊测试会话所记录的PCAP、崩溃的二进制文件、代码覆盖以及分析图等应当被保存到这个目录中。一旦模糊测试执行完毕,应当将所记录的数据转移到archived_fuzzies目录中。
-
docs:该目录包含相关文档以及所生成的Epydoc API引用。
-
-
requests:该目录是Sulley请求库。每个目标应用都应当获得其自己的文件,该文件可以被用来存储多个请求。
-
_REQUESTS_html:这个文件包含针对所存储的请求分类的描述,并且列出了单个的类型。它是按照字母顺序来进行维护的。
-
http.py:表示不同的Web服务器模糊测试请求。
-
trend.py:包含与本文档后面所讨论的完整的模糊测试走查相关联的请求。
-
-
sulley:该目录是模糊器的框架。除非你想要扩展该框架,否则的话不要触及这些文件。
-
legos:包含用户所定义的复杂原始类型。
-
ber.py:包含ASN.1/BER原始类型。
-
dcerpc.py:包含微软的RPC NDR原始类型。
-
misc.py:包含多种不同的未分类的复杂原始类型,如邮件地址和主机名等。
-
xdr.py:包含XDR类型。
-
pgraph:该目录包含Python图形抽象库。在构建会话时使用。
-
utils:包含不同的帮助例程。
-
dcerpc.py:微软的RPC帮助例程,例如实现绑定到一个接口或者生成一个请求。
-
misc.py:包含不同的未分类例程,比如CRC-16以及UUID操纵例程。
-
scada.py:包含一个DNP3块编码器的特定于SCADA的帮助例程。
-
-
init_py:这里定义了在创建请求时所使用的不同的s别名。
-
blocks.py:这里定义了块以及块的帮助例程。
-
pedrpc.py:这个文件定义了Sulley所使用的在不同的代理与主模糊器之间进行通信的客户端和服务器类。
-
primitives.py:该文件定义了不同的模糊器原始类型,包括静态类型、随机类型、字符串类型以及整数类型等。
-
sessions.py:这个文件包含构建以及执行一个会话所需要的功能。
-
sex.py:包含Sulley的定制异常处理类。
-
-
unit_tests:该目录包含Sulley的单元测试套件。
-
utils:包含多种不同的单机版工具。
-
Crashbin_explorer.py:包含用于研究存储在序列化的崩溃bin文件中的结果的命令行工具。
-
pcap_cleaner.py:包含用于清除一个PCAP目录中与错误不相关的所有条目的命令行工具。
-
-
-
network_monitor.py:包含PedRPC驱动的网络监视代理。
-
process_monitor.py:包含PedRPC驱动的、基于调试器的目标监视代理。
-
unit_test.py:Sulley的单元测试套件。
-
vmcontrol.py:包含PedRPC驱动的VMWare控制代理。
参考网址
http://blog.163.com/wuzhiyong_430/blog/static/48883052201351310184631
https://github.com/Bit9/sulley/blob/master/INSTALL.txt
http://download.csdn.net/download/xiaoliyaqian/8402057
https://github.com/OpenRCE/sulley/issues/51
https://github.com/Bit9/sulley
1、sulley 用法
1.数据表示:这是使用任何模糊器所需要执行的第一个步骤。运行你的目标应用,并且当拦截包时处理某些接口。将协议分解为单独的请求,并使用Sulley将它们表示为块。
2.会话:将所开发的请求进行连接以形成一个会话,并将其关联到不同的可用的Sulley监视代理(socket,调试器等等),然后开始执行模糊测试。
3.事后工作:对生成的数据以及所监视的结果进行评审。重放单独的测试用例。
2、sulley 目录结构
在Sulley的目录结构中存在着一些技巧。对目录结构进行维护将可以确保当你使用用户定义的复杂类型、请求以及工具对模糊器进行扩展时,目录中的所有内容仍然是有组织的。下面的层次关系指出了你需要了解的有关目录结构的一些内容:
-
archived_fuzzies:这是一个自由格式的目录,由模糊测试目标应用的名字进行组织,以存储已存档的模糊器以及从模糊测试会话中所生成的数据。
-
trend_server_protect_5168:包含将在本文档后面的单步遍历中被引用的已执行完毕的模糊测试。
-
trillian_jabber:包含文档将引用的另外一个已执行完毕的模糊测试。
-
audits:针对活动的模糊测试会话所记录的PCAP、崩溃的二进制文件、代码覆盖以及分析图等应当被保存到这个目录中。一旦模糊测试执行完毕,应当将所记录的数据转移到archived_fuzzies目录中。
-
docs:该目录包含相关文档以及所生成的Epydoc API引用。
-
requests:该目录是Sulley请求库。每个目标应用都应当获得其自己的文件,该文件可以被用来存储多个请求。
-
_REQUESTS_html:这个文件包含针对所存储的请求分类的描述,并且列出了单个的类型。它是按照字母顺序来进行维护的。
-
http.py:表示不同的Web服务器模糊测试请求。
-
trend.py:包含与本文档后面所讨论的完整的模糊测试走查相关联的请求。
-
sulley:该目录是模糊器的框架。除非你想要扩展该框架,否则的话不要触及这些文件。
-
legos:包含用户所定义的复杂原始类型。
-
ber.py:包含ASN.1/BER原始类型。
-
dcerpc.py:包含微软的RPC NDR原始类型。
-
misc.py:包含多种不同的未分类的复杂原始类型,如邮件地址和主机名等。
-
xdr.py:包含XDR类型。
-
pgraph:该目录包含Python图形抽象库。在构建会话时使用。
-
utils:包含不同的帮助例程。
-
dcerpc.py:微软的RPC帮助例程,例如实现绑定到一个接口或者生成一个请求。
-
misc.py:包含不同的未分类例程,比如CRC-16以及UUID操纵例程。
-
scada.py:包含一个DNP3块编码器的特定于SCADA的帮助例程。
-
init_py:这里定义了在创建请求时所使用的不同的s别名。
-
blocks.py:这里定义了块以及块的帮助例程。
-
pedrpc.py:这个文件定义了Sulley所使用的在不同的代理与主模糊器之间进行通信的客户端和服务器类。
-
primitives.py:该文件定义了不同的模糊器原始类型,包括静态类型、随机类型、字符串类型以及整数类型等。
-
sessions.py:这个文件包含构建以及执行一个会话所需要的功能。
-
sex.py:包含Sulley的定制异常处理类。
-
unit_tests:该目录包含Sulley的单元测试套件。
-
utils:包含多种不同的单机版工具。
-
Crashbin_explorer.py:包含用于研究存储在序列化的崩溃bin文件中的结果的命令行工具。
-
pcap_cleaner.py:包含用于清除一个PCAP目录中与错误不相关的所有条目的命令行工具。
-
network_monitor.py:包含PedRPC驱动的网络监视代理。
-
process_monitor.py:包含PedRPC驱动的、基于调试器的目标监视代理。
-
unit_test.py:Sulley的单元测试套件。
-
vmcontrol.py:包含PedRPC驱动的VMWare控制代理。
3、sulley 数据表示
3.1 静态和随机的原始类型
num_mutations(整数值,默认值是25):在恢复到默认值之前要进行的变异的数量。
fuzzable(布尔值,默认值是True):将对此原始类型的模糊测试设置为使能或者不使能。
name(字符串值,默认值是None):在所有Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
num_mutations关键字参数指定了在该原始类型被认为用完之前,应当被重新显示多少次。为了用随机数据填充一个静态大小的字段,可以将'min_length'和'max_length'的值设置为相同值。
3.2整数类型
一个字节:s_byte(),s_char()
两个字节:s_word(),s_short()
四个字节:s_dword(),s_long(),s_int()
八个字节:s_qword(),s_double()
每个整数类型至少接受一个单一的参数,即默认的整数值。另外,下面的可选的关键字参数也可以被指定:
endian(字符型,默认值为'<'):位字段的存放顺序。将低位字节先存放在低地址处的顺序指定为<,将高位字节先存放在低地址处的顺序指定为>。
format(字符串型,默认值是"binary"):将输出格式指定为"binary"或者"ascii",用以控制整数原始类型的显示格式。例如,值100以ASCII格式显示为"100",而以二进制格式则显示为"\x64"。
signed(布尔型,默认值是False):将大小设置为有符号的或者无符号的,只有当输出格式设定为"ascii"时才可应用该类型。
full_range(布尔型,默认值是False):如果其值为真,那么该原始类型将变异所有可能的值(稍后将对该类型进行更加详细的介绍)。
fuzzable(布尔型,默认值是True):将对该原始类型的模糊测试设置为使能或者不使能。
name(字符串型,默认值是None):在所有的Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
full_range修饰符在上述这些类型中是特别有趣的一个。考虑你想要对一个DWORD值进行模糊测试,总共有4294967295个可能的值。以每秒钟执行10个测试用例的速度来计算,它将会耗费13年的时间完成对这个单一的原始类型的模糊测试。为了减少巨大的输入空间,Sulley在默认情况下只尝试那些"智能"值。这包括对0周围的10个边界测试用例加上或减去适当的值,最大的整数值(MAX_VAL),MAX_VAL/2,MAX_VAL/3,MAX_VAL/4,MAX_VAL/8,MAX_VAL/16,MAX_VAL/32。缩减后的输入空间只包含141个测试用例,而执行这些测试用例只需要几秒钟的时间。
3.3 字符串和分隔符
size(整数值,默认值是-1):该字符串的静态大小。为了指定动态大小,将该值设置为-1。
padding(字符型,默认值是'\x00'):如果一个显式大小被指定,并且所生成的字符串要小于该大小,那么就使用该值将字段变为等于大小值。
encoding(字符串型,默认值是"ascii"):编码以为字符串所用。有效选项包括Python str.encode()例程可以接受的任何内容。对于微软的Unicode字符串而言,将其指定为"utf_16_le"。
fuzzable(布尔值,默认值是True):将对该原始类型的模糊测试设置为使能或者不使能。
name(字符串型,默认值是None):在所有的Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
通过使用分隔符,字符串经常被解析为子字段。例如,空格字符在HTTP请求GET/index.html HTTP/1.0中就被用做一个分隔符。在这个请求当中,前面的斜线(/)和点(.)字符同样也是分隔符。当在Sulley中定义一个协议时,要确保使用s_delim()原始类型来表示分隔符。同其它的原始类型一样,第一个参数是强制使用的,并且被用来指定默认值。同样,与其它原始类型一样,s_delim()也接受可选的'fuzzable'和'name'关键字参数。针对分隔符的变异包括重复、替换和删除。作为一个完整的例子,考虑针对HTML主体标签进行模糊测试的原始类型序列。
3.4 块
group(字符串型,默认值是None):该块所关联的群组的名字(稍后将对此进行更加详细的介绍)。
encoder(函数指针,默认值是None):指向一个函数的指针,该函数在返回所显示的数据之前显示该数据。
dep(字符串型,默认值是None):可选的原始类型,该块依赖于该类型的特定值。
dep_value(混合类型,默认值是None):为了能够显示块,dep字段必须要包含的值。
dep_value(混合类型的列表,默认值是[]):为了能够显示块,dep字段可能将包含的值。
dep_compare(字符串型,默认值是"=="):应用于依赖的比较方法。有效的选项包括==,!=,>,>=,<以及<=。
分组、编码和依赖是在其它的大多数框架中所没有的功能强大的特性,因此值得对它们进行深入的研究。
3.5 群组
分组允许你将一个块关联到一个群组原始类型,以指定该块应当为群组内部的每个值来循环遍历所有可能的变异。例如,群组原始类型对于表示带有相似参数结构的有效操作码或动词的一个列表是非常有用的。原始类型s_group()定义了一个群组,并且接受两个强制使用的参数。第一个参数指定了群组的名字,第二个参数指定了将要遍历的、可能的原始值的列表。作为一个简单的例子,考这个完整的Sulley请求,该请求被设计为对一个Web服务器进行模糊测试。
在该脚本的开始,首先导入了Sulley的所有构件。接下来,初始化了一个新的请求,并且将其命名为HTTP BASIC。在后面可以通过引用这个名字来直接访问该请求。然后定义了一个群组,其名字为verbs,所包含的可能的字符串值为GET,HEAD,POST以及TRACE。接着启动了一个新块,其名字为body,并且通过可选的group关键字参数将其关联到前面所定义的群组原始类型。注意s_block_start()将一直返回True,这就允许你可以使用一个简单的if语句来识别出其所包含的原始类型。同时注意到s_block_end()的name参数也是可选的。这些框架的设计决定纯粹是出于美观的目的而做出的。接着,在body块的内部定义了一系列基本的分隔符和字符串原始类型,然后将该块关闭。当将这个被定义的请求加载到一个Sulley会话中时,模糊器将为该块生成并传递所有可能的值,每次为群组中定义的每个动词生成并传递值。
3.6 编码器
编码器是一个简单而又功能强大的块修饰符。可以指定一个函数并将其关联到一个块,以在通过网络返回和传输之前,来修改所显示的该块的内容。使用一个现实世界中的例子可以更好的对此进行解释。来自于Trend微控制管理器的DcsProcessor.exe daemon程序在TCP端口20901进行监听,并且期望接收被私有的XOR编码例程所格式化的数据。通过对解码器实施逆向工程,开发了XOR编码例程。
Sulley编码器包含一个单一的参数,即将要编码的数据,并且返回被编码的数据。现在可以将这个定义的编码器关联到包含可模糊化原始类型的一个块,并且允许模糊器的开发者继续工作就好像不存在这个小的障碍一样。
3.7 依赖
依赖允许你将一个条件应用于一个完整块的显示中。其实现过程如下,首先使用可选的dep关键字参数将一个块与它将要依赖的原始类型相连接。当Sulley准备显示依赖块时,它将会检查所连接的原始类型的值并相应的采取行为。可以使用dep_value关键字参数来指定一个依赖值。另外,可以使用dep_values关键字参数来指定依赖值的一个列表。最后,可以通过使用dep_compare关键字参数来修改实际的条件比较。例如,考虑这样一个情形,取决于一个整数的值而期望得到不同的数据。
可以采用多种方法将块依赖串接起来,以构成功能更加强大(但也更为复杂)的组合。
3.8 块帮助函数
为了有效的利用Sulley,你必须要熟悉的关于数据生成的一个重要方面就是块帮助函数。这些函数包括大小计算函数(sizers)、校验和函数(checksums)和重复函数(repeaters)等。
3.9 大小计算函数
SPIKE的用户将会对块帮助函数s_sizer()(或s_size())非常熟悉。该帮助函数使用块的名字来度量第一个参数的大小,并且接受如下的额外关键字参数:
endian(字符型,默认值为'<'):位字段的存放顺序。将低位字节先存放在低地址处的顺序指定为<,将高位字节先存放在低地址处的顺序指定为>。
format(字符串型,默认值是"binary"):将输出格式指定为"binary"或者"ascii",用以控制整数原始类型的显示格式。
inclusive(布尔型,默认值是False):大小计算函数应当计算其自己的长度吗?
signed(布尔型,默认值是False):将大小设置为有符号的或者无符号的,只有当输出格式设定为"ascii"时才可应用该类型。
fuzzable(布尔型,默认值是False):将对该原始类型的模糊测试设置为使能或者不使能。
name(字符串型,默认值是None):在所有的Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
大小计算函数是数据生成中的一个重要构件,它允许表示诸如XDR符号和ASN.1等的复杂协议。当显示大小计算函数时,Sulley将会动态的计算所关联块的长度。在默认情况下,Sulley将不会对size字段进行模糊测试。在许多情况下我们需要进行这样的处理,然而,如果不想这样处理,那么就将可模糊化标志设置为使能。
3.10 校验和
类似于大小计算函数,s_checksum()帮助函数使用块的名字来计算第一个参数的校验和。同时也可以指定下面的可选的关键字参数:
algorithm(字符串型或者是函数指针,默认值是"crc32"):应用于目标块的校验和算法(crc32,adler32,md5,sha1)。
endian(字符型,默认值为'<'):位字段的存放顺序。将低位字节先存放在低地址处的顺序指定为<,将高位字节先存放在低地址处的顺序指定为>。
length(整数值,默认值是0):校验和的长度,其值为0时表示自动计算。
name(字符串型,默认值是None):在所有的Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
该算法的参数可以是crc32,adler32,md5或者sha1中的一个。另外,你还可以为该参数指定一个函数指针,以应用一个定制的校验和算法。
3.11 重复函数
可以使用s_repeat()(或者s_repeater()函数)对一个块重复可变数量的次数。例如,当对带有多个元素的表中的溢出进行测试时,该函数是非常有用的。该帮助函数包含三个强制使用的参数:将要被重复的块的名字,重复的最小次数以及重复的最大次数。另外,也可以指定下面的可选的关键字参数:
step(整数值,默认值是1):在最小重复次数和最大重复次数之间的单步计数。
fuzzable(布尔型,默认值是False):将对该原始类型的模糊测试设置为使能或者不使能。
name(字符串型,默认值是None):在所有的Sulley对象中,指定一个名字就可以在整个请求中直接访问该原始类型。
考虑下面的例子,它将所介绍的三个帮助函数连接到了一起。我们正在对包含一个字符串表的协议的一部分进行模糊测试。该表中的每个条目包含以下内容:一个两字节字符串类型的字段,一个两字节长度字段,一个字符串字段,最后是一个对字符串字段进行计算的CRC32校验和字段。由于我们不知道这些类型字段的有效值是什么,因此我们将使用随机数据对它们进行模糊测试。
这个Sulley脚本将不仅对表条目的解析过程进行模糊测试,而且还可能会在对超长表的处理中发现一个错误。
3.12 Legos
Sulley利用legos来表示用户定义的构件,如邮件地址、主机名以及在微软的RPC ,XDR,ASN.1以及其它标准中所使用的协议原始类型。在ASN.1/BER中,字符串被表示为[0x04][0x84][双字长度][字符串]的序列。当对一个基于ASN.1的协议进行模糊测试时,在每个字符串的前面加上长度和类型前缀将是非常繁琐的。取而代之,我们可以定义一个lego,并对其进行引用。
几乎所有的lego都遵循着一个类似的格式,而其中的一个例外情形是可选的options关键字参数,它是特定于单个的lego的。作为一个简单的例子,考虑如下的对tag lego的定义,它有助于对XMLish协议进行模糊测试。
这个示例lego简单的将所需要的标签作为一个字符串来接受,并且将其封装到适当的分隔符中。它是通过下面的操作来实现这一点的,即将块类进行扩展,并且通过self.push()来手工的将标签分隔符和用户提供的字符串添加到块中。
这里还有另外一个例子,它生成一个简单的lego以在Sulley中表示ASN.1/BER 整数。采用最低层次的通用命名符将所有的整数表示为四字节整数,其格式如下:[0x02][0x04][双字],其中0x02指明了整数的类型,0x04指定了该整数的长度为四字节,双字表示我们正在解析的实际整数值。下面是摘自于sulley\legos\ber.py的示例定义。
4、会话
一旦你已经定义了许多的请求,那么就可以将它们在一个会话中连接起来。同其它的模糊测试框架相比,Sulley所具有的一个主要的优越性在于,它具备对协议进行深层次模糊测试的能力。这一功能是通过在一个图中将请求连接在一起来实现的。在下面的例子中,一系列的请求被连接到了一起,并且利用pgraph库以uDraw格式将图形加以显示,而会话和请求类都是从pgraph库扩展而来的。
当实例化一个会话时,可以指定如下所示的可选的关键字参数:
-
sessio_filename(字符串型,默认值是None):序列化持久数据的文件名。指定一个文件名将允许你停止并重新启动模糊器。
-
skip(整数值,默认值是0):将要被略过的测试用例数。
-
sleep_time(浮点数,默认值是1.0):在传输测试用例之间的休眠时间。
-
log_level(整数值,默认值是2):设置日志级别,一个更大的数字表示将包含更多的日志消息。
-
proto(字符串型,默认值是"tcp"):通信协议。
-
timeout(浮点数,默认值是5.0):在超时之前等待send()或recv()返回的秒数。
Sulley所具备的另外一个高级特性是,它可以在协议图结构中所定义的每条边上记录回调函数。这就允许我们在节点传输之间记录一个将调用的函数,以实现诸如挑战响应系统这样的功能。回调方法必须要采用的原型加以定义。
5 、实例
5.1 FTP协议测试
Fuzzing对象: FTP服务器
环境:host:windows xpsp2,虚拟机
工具:sulley framework + ollydbg
首先了解要fuzzing的对象,对fuzzing对象协议的熟悉程度对fuzzing的结果有很大影响
FTP的配置就无需多说,21端口,若干FTP命令,因为我对python不是很熟悉,就只能简单构造一些用来fuzz数据
第一步:创建一个FTP.py的文件,内容如下
# ftp.py 2008-12-17
# we use this moduie to generate fuzzing data
#
from sulley import *
#########################################################
s_initialize("War-FTP")
s_group("verbs",values=["USER","PASSWORD"])
if s_block_start("body",group = "verbs"):
#以verbs形成报文的头
s_delim(" ")
s_string("A"*1000)
s_static("\r")
s_block_end()
#上面的代码片断形成一个如 "USER AAAAAAA...\r"\"PASSWORD AAAAAAAA...."的数据报文,
s_initialize()#等函数在sulley\__init__.py模块中定义,是作者自己写的形成请求数据的函数
s_delim(" ")#加入一个空格分隔符
s_string("A"*1000)#,由1000个A组成的字符串
s_static("\r")#回车字符
将ftp.py文件放入/requests目录下,作为fuzzing的数据模块调用,读者可以自行扩展,这样就粗糙的完成了构造fuzzing数据的工作.
第二步,按照自己的要求完成一个会话,命名为example.py
#sulley module test
#example.py
from sulley import *
#from primitives import *
from requests import ftp
def bind(target):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(target)
s.send("USER anonymous\n")
s.recv(buff,100)
s.send("anonymous\n")
def do_fuzz():
sess = sessions.session(session_filename ="tmp.log")
target = sessions.target("192.168.15.22",21)
#使用procmon监控fuzzing
target.procmon = pedrpc.client("192.168.15.22",26002)
target.procmon_options = \
{
"proc_name":"War-ftpd.exe"
}
sess.add_target(target)
# 首先启动 process_monitor.py -c audits\war-ftp.crashbin -p war-ftpd.exe
#sess.pre_send = bind
sess.connect(s_get("War-FTP"))
sess.fuzz()
print "done fuzzing..."
if 1:
do_fuzz()
第三步 运行我们建立好的example.py
E:\Hack_tools\FUZZTOOL\Fuzz_FrameWork\sulley>example.py
[10:53.43] current fuzz path: -> War-FTP
[10:53.43] fuzzed 0 of 2244 total cases
[10:53.43] fuzzing 4 of 2244
[10:53.45] xmitting: [1.4]
[10:53.46] fuzzing 5 of 2244
[10:53.46] xmitting: [1.5]
[10:53.54] procmon detected access violation on test case #5
[10:53.54] primitive lacks a name, type: delim, default value:
[10:53.54] [INVALID]:41414141 Unable to disassemble at 41414141 from thread 1500
caused access violation
[10:53.54] restarting target process
监控程序窗口出现连接的信息,说明已经开始工作了
10:53.43] updating target process name to 'War-ftpd.exe'
10:53.43] debugger thread-1229655223 looking for process name: War-ftpd.exe
10:53.43] debugger thread-1229655223 found match on pid 3676
10:53.54] debugger thread-1229655223 caught access violation: '[INVALID]:414141
1 Unable to disassemble at 41414141 from thread 1500 caused access violation'
10:53.54] debugger thread-1229655223 exiting
10:53.54] starting target process
5.2 私有协议 SecuRemote 模糊测试
SecuRemote协议结构
enter description here模糊测试逻辑
#!/usr/bin/env python
from sulley import *
SLEEP_TIME=0.5TIMEOUT=3CRASH_THRESHOLD=3# The function Sulley will run prior to sending each mutation. We leverage
# it to setup the target system with the initial packets and response in the
# protocol exchange prior to our target packet.
def preconn(sock):
sock.send("\x51\x00\x00\x00") time.sleep(0.5)
sock.send("\x00\x00\x00\x21")
# Set a socket timeout on the recv so we aren't waiting indefinitely if
# the server crashed from a previous test case.
sock.settimeout(5) response = sock.recv(4)
print "Setup response: ", for i in response:
print "%02x" % ord(i),
print
s_initialize("SecuRemote-Simple-String")
# Create a size field, which is based on the content of the named block
# Sulley uses ">" to indicate big-endian values, "<" is little-endian
s_size("client-name-string", length=4, endian=">")
# This is the block of data used for filling in the s_sizeif s_block_start("client-name-string"):
# "securemote" is the default string
s_string("securemote")
# constant null terminator
s_byte("\x00")
s_block_end()
sess = sessions.session(session_filename="Securemote-Simple-string.sess", sleep_time=SLEEP_TIME, timeout=TIMEOUT, crash_threshold=CRASH_THRESHOLD)
# Call preconn() before each mutation is sent to setup the target
sess.pre_send = preconn
sess.connect(s_get("SecuRemote-Simple-String"))
target = sessions.target("127.0.0.1", 264)
sess.add_target(target)
sess.fuzz()
网友评论