## 8.1 Bug 的分類
當 hacker 或者逆向工程師分析軟件漏洞的時候,都會設法找到能控制程序執行的 bug。 Fuzzer 就提供了一種自動化的方式幫助我們找出 bug,然后獲得系統的控制權,提升權限, 并且偷取程序訪問的信息,不論目標程序是在系統獨立運行的進程,還是只運行腳本的網絡 程序。在這里我們關注的是獨立運行的進程,以及其泄漏的信息。
### 8.1.1 緩沖區溢出
緩沖區溢出是最常見的軟件漏洞。所有的正常的內存管理函數,字符處理代碼甚至編程語言本身都可能產生緩沖區溢出漏洞,致使軟件出錯。
簡而言之,緩沖區溢出就是由于,把個過多的數據存儲在一個過小的內存空間里,所引發的軟件錯誤。對于其原理的可以用個很形象的比喻來說明。如果一個水桶,只能裝一加侖 的水,我們只導入幾滴水或者半加侖的水,甚至是一加侖,把水桶填滿了,都不會出問題, 一切都正常如初。如果我們導入兩加侖的水,那水就會溢出到地板上,到時候,你就得收拾 這堆爛攤子了。用在軟件上也是一樣的,如果太多的水(數據),倒入到一個桶(buffer)內, 水就會溢出到作為的地表(memory)上。當一個攻擊者能夠控制多余的數據對內存區域的 覆蓋,就拿那個得到代碼的執行權限,進一步獲取到系統信息或者做別的事。有兩種主要的 緩沖區溢出:基于棧的和基于堆的。兩種溢出的表現不同,但產生的結果相同:攻擊者最終 控制代碼的執行。
棧溢出的特點就是通過溢出覆蓋棧,來控制程序的執行流程:比如改變函數的指針,變量的值,異常處理程序,或者覆蓋函數的返回地址,可以得到代碼的執行權限。棧溢出的時 候,會拋出一個訪問違例;這樣我們就能夠在 fuzzing 的時候非常方便的跟蹤到它們。
應用程序在運行的時候會動態的申請一塊內存區域,這些區域就是堆。堆是一塊一塊連在一起的,負責存儲元數據。當攻擊者將數據覆蓋到自己申請的堆以外的別的堆的時候,堆 溢出就發生了。接著攻擊者能通過覆蓋數據改變任何存儲在堆上的數據:變量,函數指針, 安全令牌,以及各種重要的數據。堆溢出很難被立即的跟蹤到,因為被影響的內存快,一般 不會被程序立即的訪問,需要等到程序結束之前的某個時間內才有可能訪問到,當然也有可 能一直不訪問。在 fuzzing 的時候我們就必須一直等到一個訪問違例產生了才會知道,這個 堆溢出是否在成功了。
MICROSOFT GLOBAL FLAGS
這項技術是專門為軟件開發者(or exploit writer)專門設計的。Gflags(Global flags 全局標 志)是一系列的診斷和調試設置,能夠讓你非常精確的跟蹤,記錄,和調試軟件。在 2000, xp 和 2003 上都能夠使用這項技術。
這項技術最有趣的地方在于堆頁面的校對。當我們在一個進程上打開這個選項的時候,校對器會動態的更重內存的操作,包括內存的申請和釋放。不過真正令人高興的特點是,它 能夠在堆溢出發生的時候立刻產生一個調試中斷,這樣調試器就會停在產生錯誤的指令上。 這樣在下面的調試中遇到了堆相關的 bug 的時候我們就能方便的查找到源頭在哪。
我們能夠使用gflags.exe來編輯Gflags標志幫助我們跟蹤堆溢出。 [http://www.microsoft.com/downloads/details.aspx?FamilyId=49AE8576-9BB9-4126-9761-BA80](http://www.microsoft.com/downloads/details.aspx?FamilyId=49AE8576-9BB9-4126-9761-BA80) 這個軟件是 Microsoft "免費"提供的,請"放心"安裝。
Immunity 也提供了一個 Gflags 庫,并且將它和 PyCommand 結合在了一起。更多的信 息訪問 [http://debugger.immunityinc.com/](http://debugger.immunityinc.com/).
為了通過 fuzzing 溢出目標程序,我們會簡單的傳遞給程序大量的數據,然后跟蹤程序, 找出利用了我們傳入數據的代碼,然后祈禱它沒有合格驗證數據長度的,my god!
接下來看看另一個常見的應用程序漏洞,Integer Overflows 整數溢出。
### 8.1.2 Integer Overflows
整數溢出是一種非常有趣的漏洞,包括程序如何處理(編譯器標準的)有符號整數和 exploit 如何利用這個整數。一個有符號整數,由 2 個字節組成,表示的范圍從 -32767 到 32767。當我們從嘗試向存儲一個整數的地方寫入超過其大小的數字的時候,整數溢出就觸 發了。因為存如的數字太大,處理器會自動的將高位多出來的字節丟棄。初看起來,好像沒 什么值得利用的。下面讓我們看一個設計好的例子:
```
MOV EAX, [ESP + 0x8]
LEA EDI, [EAX + 0x24]
PUSH EDI
CALL msvcrt.malloc
```
第一條指令將棧內的數據[esp+0x8]傳給 EAX,第二條指令,將 EAX 加上 0x24 這個地 址存儲在 EDI 中。之后我們將這個唯一的參數(申請的內存的大小)傳入函數 malloc。一切看 起來都很正常,真的是這樣嗎?假設在棧中的數據是一個有符號整數,而且非常大,幾乎接 近了有符號整數的最大值( 32767),然后傳遞給 EAX,EAX 加上 0x24,整數溢出,最后我 們得到一個非常小的值。看一看表 8-1,看看這一切是如何發生的,假定在堆上的參數是我 們能夠控制的,我們給它設置成一個非常大的值 0xFFFFFFF5。
```
Stack Parameter => 0xFFFFFFF5
Arithmetic Operation => 0xFFFFFFF5 + 0x24
Arithmetic Result => 0x100000019 (larger than 32 bits)
Processor Truncates => 0x00000019
```
Listing 8-1:在控制下的整數操作
如何一切順利,malloc 將只申請 0x19 個字節大小的空間,這塊內存比程序本身要申請 的空間小很多。如果程序將一大塊的數據寫入這塊區域,緩沖區溢出就發生了。在 fuzzing 的時候,我們得從整形最大值和最小值兩個方面入手,測試執行溢出,接下來就是設法進一 步控制溢出,使溢出變得更完美。
下面讓我們快速的看一看另一種常見漏洞,格式化字符串漏洞 Format String Attacks。
### 8.1.3 Format String Attacks
格式化字符串攻擊,顧名思義,攻擊者通過將設計好的字符串傳入特定字符串格式化函 數,使其產生溢出,列如 C 語言的 printf。讓我們先看看 printf 的原型:
```
int printf( const char * format, ... );
```
第一個參數是一個完整需要被格式化的字符串,我們可以附加額外的參數,表示數據將 以什么形式被輸出。舉個例子:
```
int test = 10000;
printf("We have written %d lines of code so far.", test);
Output:
We have written 10000 lines of code so far.
```
%d 是一個模式說明符,格式指定符指定了特定的輸出格式(變量 test 以數字的形式輸 出)。如果一個程序員不小心睡著了(壓榨 嚴重的壓榨),寫出了下面的代碼:
```
char* test = "%x";
printf(test);
Output: 5a88c3188
```
這看起來和上面的很不同。我們傳遞了一個模式說明符給 printf 函數,但是沒有傳遞需 要打印的變量。printf 會分析我們傳遞給它的參數,并且假設棧中的下一個參數就是需要打 印的參數,但是其實這個是毫無效果的一個數據。在這個例子中是 0x5a88c3188,也許是存 在棧上的數據,也有可能跟是一個指向內存的指針。有兩個指示符很有趣,一個是 %s,另 一個是 %n。 %s 指示符告訴字符串函數,把內存當作字符串來掃描,直到遇到一個 NULL 字符,代表字符串結束了。這對于讀取一大塊連續的數據或者讀取特定地址的數據都十分有 用,當然你也可以用它來 crash 程序。%n 指示符(惟一一個)允許向內存寫入內存,而不 僅僅是格式化字符串。這就允許,攻擊者覆蓋函數的返回地址,或者改寫一個以存在的函數 指針,以獲得代碼的執行權限。在 fuzzing 的似乎后,我們只要在測試用例中加入這些特定 格式說明符,然后傳遞給一個被錯誤使用了的字符串處理函數。
現在我們已經對不同的 bug 類型有了個個大概的了解,是時候開始創造第一個 fuzzer 了。接下來我們會簡單的實現一個 file fuzzer,它先將正常的文件變形之后拿去給程序處理。 這次繼續使用我們久違的老朋友 PyDbg。Come on!!!
- 序
- 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