💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 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 集合,然后 将它们传给负责构建测试的框架内。