## 9.3 獵殺 WarFTPD
在我們已經學會了如何使用 Sulley primitives 創建 protocol description(協議說明)之后。 現在可以拿個東西試試手了。這次的目標就是 WarFTPD 1.65。問題出在 USER 和 PASS 命 令身上,向他們傳遞過長的數據,就會引發棧溢出。這種漏洞很典型,出現問題的地方結構 也 很 清 晰 , 作 為 入 手 的 case 再 好 不 過 。 先 從 ftp://ftp.jgaa.com/pub/products/Windows/WarFtpDaemon/1.6_Series/ward165.exe 下載程序。在 當前目錄解壓子之后,直接運行 warftpd.exe 就能啟動 FTP 服務了。在使用 Sulley 書寫協議 說明之前,讓我們先了解下 FTP 協議的工作流程。
### 9.3.1 FTP 101
FTP 是一個簡單輕便的文件傳輸協議,被廣泛的使用于各種環境中,從 Web 服務器到 網絡打印機。FTP 服務器默認在端口 21 上監聽客戶端發送的命令。現在我們要冒充成 FTP 客戶端,向服務器發送變形過的命令數據,嘗試獲得服務器的權限。如果你順利完成 了 WarFTPD 的 fuzzer, 別忘了用它去尋找新的倒霉蛋。
一個 FTP 服務器既可以設置成不需要密碼的匿名訪問或者是需要密碼的認證訪問。因 為 WarFTPD 的漏洞出在 USER 和 PASS 命令上,所以我們就假定服務區使用認證訪問。FTP 認證命令的格式如下:
```
USER <USERNAME> PASS <PASSWORD>
```
一旦客戶端傳入了有效的用戶名和密碼后,服務器就會賦予客戶端,傳輸文件,改變目 錄,查詢文件等各種權限。當然 USER 和 PASS 命令只是 FTP 服務器提供的功能中的一個 子集,在認證成功后還有很多別的功能,如表 9-2。這些新的命令都要加入到我們程序的協 議框架(protocol skeleton)中。FTP 協議詳細的命令,請看 rfc959。
```
CWD <DIRECTORY> - change working directory to DIRECTORY
DELE <FILENAME> - delete a remote file FILENAME
MDTM <FILENAME> - return last modified time for file FILENAME
MKD <DIRECTORY> - create directory DIRECTORY
```
Listing 9-2:我們要額外 fuzz 的 FTP 命令
命令列表雖然不夠詳細,但還擴大了測試的范圍,現在讓我們動手把它們寫成 protocol description
### 9.3.2 創建 FTP 協議框架
學以致用,學以致用啊!
```
#ftp.py
from sulley import *
s_initialize("user")
s_static("USER")
s_delim(" ")
s_string("justin")
s_static("\r\n")
s_initialize("pass")
s_static("PASS")
s_delim(" ")
s_string("justin")
s_static("\r\n")
s_initialize("cwd")
s_static("CWD")
s_delim(" ")
s_string("c: ")
s_static("\r\n")
s_initialize("dele")
s_static("DELE")
s_delim(" ")
s_string("c:\\test.txt")
s_static("\r\n")
s_initialize("mdtm")
s_static("MDTM")
s_delim(" ")
s_string("C:\\boot.ini")
s_static("\r\n")
s_initialize("mkd")
s_static("MKD")
s_delim(" ")
s_string("C:\\TESTDIR")
s_static("\r\n")
```
protocol skeleton 完成之后,讓我們開始創建 Sulley 會話,把所有的請求信息連起來, 同時啟動網絡嗅探和客戶端調試。
### 9.3.3 Sulley 會話
Sulley 會話包含了請求數據整合,網絡數據包的捕捉,進程調試,崩潰報告,和虛擬機 控制。先讓我們定義一個會話文件,然后詳細的分析每個部分。
```
#ftp_session.py
from sulley import *
from requests import ftp # this is our ftp.py file
def receive_ftp_banner(sock):
sock.recv(1024) sess = sessions.session(session_filename="audits/warftpd.sess
target = sessions.target("192.168.244.133", 21)
target.netmon = pedrpc.client("192.168.244.133", 26001)
target.procmon = pedrpc.client("192.168.244.133", 26002)
target.procmon_options = { "proc_name" : "war-ftpd.exe" }
# Here we tie in the receive_ftp_banner function which receives
# a socket.socket() object from Sulley as its only parameter
sess.pre_send = receive_ftp_banner sess.add_target(target)
sess.connect(s_get("user"))
sess.connect(s_get("user"), s_get("pass"))
sess.connect(s_get("pass"), s_get("cwd"))
sess.connect(s_get("pass"), s_get("dele"))
sess.connect(s_get("pass"), s_get("mdtm"))
sess.connect(s_get("pass"), s_get("mkd"))
sess.fuzz()
```
receive_ftp_banner()是必須的,因為每個 FTP 服務器在客戶端連接上的時候,都會發送 banner(標識)。我們將它和 sess.pre_send 綁定起來,這樣 Sulley 發送 fuzzing 數據前的時候 就會先接收 FTP banner。和 receive_ftp_banner 一樣,pre_send 也只接收一個由 Sulley 傳遞的 sock 對象。第一步我們創建一個會話文件,用于記錄當前 fuzzer 的狀態,同時控制 fuzzing 的啟動和停止。第二部定義攻擊的目標,包括 IP 地址和端口號。這里設置成 192.168.244.133 端口 21(這是我們運行 WarFTPD 虛擬機的 IP)。第三步,設置網絡嗅探的端口為 26001, IP 地址和 FTP 服務器的地址一樣,這個端口用于接受 Sulley 發出的命令。第四步,設置調 試器監聽的端口 26002,這個端口用于接收 Sulley 發出的調試命令。procmon_options 選項 告訴調試器我們關注的進程是 war-ftpd.exe。第六步,在會話中加入定義好的目標對象。第 七步,將 FTP 請求指令有序的組織好。先是認證,然后將操作指令和需要的密碼成對傳入。 最后啟動 Sulley 開始 fuzzing。
現在我們定義好了會話,組織好了請求指令。只剩下網絡和監控腳本的設置了。當這一切都完成的時候,就可以去捕捉我們的獵物了。
### 9.3.4 網絡和進程監控
Sulley 的優點之一就是能非常好的跟蹤 fuzz 期間的數據交互,以及目標系統的崩潰信 息。這樣我們就能在第一時間內分析出引起目標崩潰的數據包,然后快速的開發出 exploit。
在 Sulley 的主目錄下可以找到 process_monitor.py 和 network_monitor.py 兩個腳本,他 們分別負責網絡監控和進程監控。
```
python process_monitor.py
Output:
ERR> USAGE: process_monitor.py
<-c|--crash_bin FILENAME> filename to serialize crash bin class to
[-p|--proc_name NAME] process name to search for and attach to [-i|--ignore_pid PID] ignore this PID when searching for the
target process
[-l|--log_level LEVEL] log level (default 1), increase for more
verbosity
[--port PORT] TCP port to bind this agent to
```
如下啟動進程監控。
```
python process_monitor.py -c C:\warftpd.crash -p war-ftpd.exe
```
提示:我們已經設置了默認的監聽端口 26002,所以不用-p 選項。
接下來看看 network_monitor.py。在這之前需要安裝以下的庫: WinPcap 4.0, pcapy, mpacket。
```
python network_monitor.py Output:
ERR> USAGE: network_monitor.py
<-d|--device DEVICE #> device to sniff on (see list below)
[-f|--filter PCAP FILTER] BPF filter string
[-P|--log_path PATH] log directory to store pcaps to
[-l|--log_level LEVEL] log level (default 1), increase for more verbosity
[--port PORT] TCP port to bind this agent to
Network Device List:
[0] \Device\NPF_GenericDialupAdapter
[1] {83071A13-14A7-468C-B27E-24D47CB8E9A4} 192.168.244.133
```
在這里我們需要使用第一個網絡接口。如下啟動網絡監控。 python network_monitor.py -d 1 -f "src or dst port 21" -P C:\pcaps\ 提示:在啟動之前必須先建立 C:\pcaps 目錄。
一切就緒,開始獵食。
### 9.3.5 fuzzing 和 Web 界面
現在我們啟動 Sulley,并使用內置的 Web 界面觀察整個 fuzz 過程。
```
python ftp_session.py
```
輸出如下:
```
[07:42.47] current fuzz path: -> user
[07:42.47] fuzzed 0 of 6726 total cases
[07:42.47] fuzzing 1 of 1121
[07:42.47] xmitting: [1.1]
[07:42.49] fuzzing 2 of 1121
[07:42.49] xmitting: [1.2]
[07:42.50] fuzzing 3 of 1121
[07:42.50] xmitting: [1.3]
```
如果輸出是這樣的,說明一切正常。Sulley 正在繁忙的工作著。現在讓我們看看 web 界面,它會提供更多信息。
用瀏覽器打開 http://127.0.0.1:26000 ,將看到類似圖 9-1 的結果。

Figure 9-1: Sulley 的 web 界面
不斷的刷新瀏覽器就能看到當前 fuzzing 的進程,以及正在使用的 primitive。如圖 9-1 你會看到正在 fuzzing 的 primitive 是 user,這個命令存在漏洞,在不久之后就會看到如圖 9-2 的崩潰報告。

Figure 9-2: Sulley web 界面顯示的崩潰信息
很好,應該說非常好!我們已經成功的 Crash 了 WarFTPD,Sulley 也捕捉到了所有相關 的信息。我們看到兩個測試用例的錯誤信息都是不能反匯編 0x5c5c5c5c 這個地址。0x5c 就 是 ASCII 字符\,這是由于傳入的\字符過多,覆蓋了別的內存區域,緊接這影響到 EIP。當 調試器嘗試反匯編 EIP 指向的位置的時候,就會失敗,因為 0x5c5c5c5c 不是一個有效的地 址。這意味我們已經能夠控制 EIP 了,那接下來就是開發 exploit 了!激動嗎?呵呵,可惜 這是我們之前就知道的漏洞。不過有了這次成功的測試,我們對 Sulley 的工作方式已經很 熟悉了,對于別的 fuzzing 對象也只要依葫蘆畫瓢就行了。Good Luck!
現在點擊 test case 的數字,就會看到詳細的崩潰信息。如表 9-3 PyDbg 崩潰信息格式在 60 頁的"訪問違例處理程序"中有詳細的講解。忘記的返回去看 看。
```
[INVALID]:5c5c5c5c Unable to disassemble at 5c5c5c5c from thread 252 caused access violation
when attempting to read from 0x5c5c5c5c CONTEXT DUMP
EIP: 5c5c5c5c Unable to disassemble at 5c5c5c5c
EAX: 00000001 ( 1) -> N/A
EBX: 5f4a9358 (1598722904) -> N/A
ECX: 00000001 ( 1) -> N/A
EDX: 00000000 ( 0) -> N/A
EDI: 00000111 ( 273) -> N/A
ESI: 008a64f0 ( 9069808) -> PC (heap)
EBP: 00a6fb9c ( 10943388) -> BXJ_\'CD@U=@_@N=@_@NsA_@N0GrA_@N*A_0_C@ Ct^J_@_0_C@N (stack)
ESP: 00a6fb44 ( 10943300) -> ,,,,,,,,,,,,,,,,,, cntr User from
192.168.244.128 logged out (stack)
+00: 5c5c5c5c ( 741092396) -> N/A
+04: 5c5c5c5c ( 741092396) -> N/A
+08: 5c5c5c5c ( 741092396) -> N/A
+0c: 5c5c5c5c ( 741092396) -> N/A
+10: 20205c5c ( 538979372) -> N/A
+14: 72746e63 (1920233059) -> N/A
disasm around:
0x5c5c5c5c Unable to disassemble
stack unwind:
war-ftpd.exe:0042e6fa
MFC42.DLL:5f403d0e
MFC42.DLL:5f417247
MFC42.DLL:5f412adb
MFC42.DLL:5f401bfd
MFC42.DLL:5f401b1c
MFC42.DLL:5f401a96
MFC42.DLL:5f401a20
MFC42.DLL:5f4019ca
USER32.dll:77d48709
USER32.dll:77d487eb
USER32.dll:77d489a5
USER32.dll:77d4bccc
MFC42.DLL:5f40116f
SEH unwind:
00a6fcf4 -> war-ftpd.exe:0042e38c mov eax,0x43e548
00a6fd84 -> MFC42.DLL:5f41ccfa mov eax,0x5f4be868
00a6fdcc -> MFC42.DLL:5f41cc85 mov eax,0x5f4be6c0
00a6fe5c -> MFC42.DLL:5f41cc4d mov eax,0x5f4be3d8
00a6febc -> USER32.dll:77d70494 push ebp
00a6ff74 -> USER32.dll:77d70494 push ebp
00a6ffa4 -> MFC42.DLL:5f424364 mov eax,0x5f4c23b0
00a6ffdc -> MSVCRT.dll:77c35c94 push ebp
ffffffff -> kernel32.dll:7c8399f3 push ebp
```
Listing 9-3:#437 測試用例 產生的崩潰信息
Sulley 的主要應用已經講解完成了。當然這些只是其中的一部分,還有很多很多的東西, 需要各位同學,自己去研究,比如崩潰數據的過濾,primitives 的圖形化輸出,等等。從今 以后,Sulley 不再是一頭可怕的怪物,而是我們 bug-hunging 時的利器。在我們成功的完成 了遠程服務的 fuzz 以后,接下來然我們 fuzz 本地的 Windows 下的驅動程序,這次我們用自 己的工具。
- 序
- 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