## 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