## 9.2 Sulley primitives
在我们开始开始对目标动手前,必须先定义好所有的 building blocks(构建块),这些块 负责产生协议相关的测试数据。 Sulley 提供了所需的各种的数据格式,为我们创建简单高 效的 protocol descriptions 提供了便利。这些单独的数据组件叫做 primitives(原语)。我们先 简短讲解一些 fuzz WarFTPD 时候会用到的 primitives。一旦你理解了如何使用其中一个 primitives,那剩下的就很容易了。
### 9.2.1 Strings
字符串(Strings)是使用最多的 primitives。到处都有字符串;用户名,ip 地址,目录等等。
s_string()指令表示添加进测试数据的 primitives 是一个可 fuzz 的字符串。s_string()只有一个参数,就是有效的字符串,用于协议交互中的正常输入。比如,你 fuzzing 一个 email 地址:
```
s_string("justin@immunityinc.com)
```
Sulley 会把 [justin@immunityinc.com](mailto:justin@immunityinc.com) 当作一个有效值,然后进行各种变形,最后扔给目 标程序。让我们看看 email 地址变成了什么样。
```
justin@immunityinc.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA
justin@%n%n%n%n%n%n.com
%d%d%d@immunityinc.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAA
```
9.2.2 Delimiters
Delimiters(定界符),用于将大的字符串分割成晓得容易管理的片段。还是用先前的 email 地址做例子,用 s_delim()指令能够将它分割成更多的 fuzz 字符串。
```
s_string("justin")
s_delim("@")
s_string("immunityinc")
s_delim(".",fuzzable=False)
s_string("com")
```
通过 s_delim(),我们将 email 地址分成了几个子串,并且告诉 Sulley,我们在 fuzzing 的时候不使用点(.),但是会使用@ 。
### 9.2.3 Static and Random Primitives
s_static()和 s_random(),顾名思义,第一个使传入的数据不改变,第二个使数据随机的 改变。
```
s_static("Hello,world!")
s_static("\x41\x41\x41")
```
s_random()可以随机产生变长的数据。
```
s_random("Justin",min_length=6, max_length=256, num_mutations=10)
```
min_length 和 max_length 告诉 Sully 变形后的数据的长度范围, num_mutations 为可选 参数,表示变形的次数,默认为 25 次。
在我们的例子,使用"Justin"作为源数据,经过 10 次变形,产生 6-256 个长度的字符。
### 9.2.4 Binary Data
Binary Data(二进制数据)是数据表示中的瑞士军刀。Sullyey 几乎能处理所有二进制数 据。当我们在处理一些未知协议的数据包的时候,你也许只是想看看服务器是如何回应我们 生成的这些没有意义的数据的,这时候 s_binary() 就非常有用了
```
s_binary("0x00 \\x41\\x42\\x43 0d 0a 0d 0a")
```
Sully 能识别出所有这类的数据,然后像将它们当作字符串使用。
### 9.2.5 Integers
Integers(整数)的应用无处不在,从能看的见的明文数据,到看不见的二进制协议,以及 数据长度,各种结构,等等。
表 9-1 列出了 Sulley 支持的主要几种整数类型。
```
1 byte – s_byte(), s_char()
2 bytes – s_word(), s_short()
4 bytes – s_dword(), s_long(), s_int()
8 bytes – s_qword(), s_double()
```
Listing 9-1: Sulley 支持的整数类型
所有的整数表达式都有几个重要的的选项。endian 项表示整数将以什么样的形式变现出 来,是小端- (<) 还是 大端- (>)格式 l 默认似乎小端。format 项有两个可选值,ascii 和 binary; 代表整数将被如何使用。举个例子,如果你有一个用 ASCII 格式 表示是 1,用 binary 表示 就是\x31。signed 项说明整数是有符号的还是无符号的,这个选项只有在 format 指定为 ascii 后有效,默认似乎 False。最后一个有趣的选项是 full_range,启用这个选项以后,Sulley 就 会在一个很广的范围内枚举可能的整数值。举个例子,如果我们传入的整数是一个无符号的 整数,把 full_range 设置成 True,这时候 Sulley 就会很智能的测试边界值(接近或者超过最 大值,或者接近最小值),无符号的最大值是 65535,Sulley 就会试着使用 65534, 65535, 65536 去进行测试。full_range 默认为 False,因为可枚举的时间可是很长的。看看下面的例子。
```
s_word(0x1234, endian=">", fuzzable=False)
s_dword(0xDEADBEEF, format="ascii", signed=True)
```
第一个例子,我们设置了一个 2 字节大小的值 0x1234,并且将表示方式设置成大端,同时作为一个静态值。第二个例子,我们设置了一个 4 字节(双字)大小的值 0xDEADBEEF, 并且将它作为有符号的整数,以 ASCII 形式表现。
### 9.2.6 Blocks and Groups
Blocks(块)Groups(组)是 Sulley 提供的强大的组织工具。Blocks 将独立的 primitives 组装 成一个的有序的块。Groups 中包含了一些特定的 primitives,一个 Group 和一个 Block 结合 后,每次 fuzzer 调用 Block 的时候,都会将 Group 中的数据循环的取出,组成不同的 Block。
下面就是一个使用块和组 fuzzing HTTP 的例子。
```
# import all of Sulley's functionality.
from sulley import *
# this request is for fuzzing: {GET,HEAD,POST,TRACE} /index.html HTTP/1.1
# define a new block named "HTTP BASIC".
s_initialize("HTTP BASIC")
# define a group primitive listing the various HTTP verbs we wish to fuzz.
s_group("verbs", values=["GET", "HEAD", "POST", "TRACE"])
# define a new block named "body" and associate with the above group.
if s_block_start("body", group="verbs"):
# break the remainder of the HTTP request into individual primitives.
s_delim(" ")
s_delim("/")
s_string("index.html")
s_delim(" ")
s_string("HTTP")
s_delim("/")
s_string("1")
s_delim(".")
s_string("1")
# end the request with the mandatory static sequence.
s_static("\r\n\r\n")
# close the open block, the name argument is optional here.
s_block_end("body")
```
程序一开始我们就定义了一个叫 verbs 的组,其中包含了所有 HTTP 请求类型。之后定 义了一个叫 body 的块,并且和 verbs 组绑定。这意味着,以后 Sulley 每次调用 body 内的变 形数据的时候,都会循环的获取(GET, HEAD, POST, TRACE)5 种请求方式,这样一来,一 次 body 内的变形就相当于产生 5 个不同的 body。
到目前为止,我们已经讲解完了 Sulley 的基础知识。当然 Sulley 不仅仅如此,还有数 据解码,校验和计算,长度自动处理等等。想深入学习的同学可以看 Pedram 写的 Fuzzing: Brute Force Vulnerability Discovery (Addison-Wesley, 2007),一本综合了 Sulley 和 fuzzing 相 关技术的好书。现在该开始对 WarFTPD 下手了。我们要先创建自己的 primitive 集合,然后
将它们传给负责构建测试的框架内。
- 序
- 1 搭建开发环境
- 1.1 操作系统准备
- 1.2 获取和安装 Python2.5
- 1.3 配置 Eclipse 和 PyDev
- 2 调试器设计
- 2.1 通用 CPU 寄存器
- 2.2 栈
- 2.3 调试事件
- 2.4 断点
- 3 自己动手写一个 windows 调试器
- 3.2 获得 CPU 寄存器状态
- 3.3 实现调试事件处理
- 3.4 全能的断点
- 4 PyDBG---纯 PYTHON 调试器
- 4.1 扩展断点处理
- 4.2 处理访问违例
- 4.3 进程快照
- 5 IMMUNITY----最好的调试器
- 5.1 安装 Immunity 调试器
- 5.2 Immunity Debugger 101
- 5.3 Exploit 开发
- 5.4 搞定反调试机制
- 6 HOOKING
- 6.1 用 PyDbg 实现 Soft Hooking
- 6.2 Hard Hooking
- 7 Dll 和代码注入
- 7.1 创建远线程
- 7.2 邪恶的代码
- 8 FUZZING
- 8.1 Bug 的分类
- 8.2 File Fuzzer
- 8.3 改进你的 Fuzzer
- 9 SULLEY
- 9.1 安装 Sulley
- 9.2 Sulley primitives
- 9.3 猎杀 WarFTPD
- 10 Fuzzing Windows 驱动
- 10.1 驱动通信
- 10.2 用 Immunity fuzzing 驱动
- 10.4 构建 Driver Fuzzer
- 11 IDAPYTHON --- IDA 脚本
- 11.1 安装 IDAPython
- 11.2 IDAPython 函数
- 11.3 脚本例子
- 12 PyEmu
- 12.1 安装 PyEmu
- 12.2 PyEmu 一览
- 12.3 IDAPyEmu