## 10.4 構建 Driver Fuzzer
第一步在完成 PyCommand:IOCTL-dump。
```
#ioctl_dump.py
import pickle
import driverlib
from immlib import *
def main( args ):
ioctl_list = [] device_list = []
imm = Debugger()
driver = driverlib.Driver()
# Grab the list of IOCTL codes and device names
ioctl_list = driver.getIOCTLCodes()
if not len(ioctl_list):
return "[*] ERROR! Couldn't find any IOCTL codes."
device_list = driver.getDeviceNames()
if not len(device_list):
return "[*] ERROR! Couldn't find any device names."
# Now create a keyed dictionary and pickle it to a file
master_list = {}
master_list["ioctl_list"] = ioctl_list
master_list["device_list"] = device_list
filename = "%s.fuzz" % imm.getDebuggedName()
fd = open( filename, "wb" )
pickle.dump( master_list, fd )
fd.close()
return "[*] SUCCESS! Saved IOCTL codes and device names to %s" % filename
```
這個 PyCommand 相當簡單:檢索 IOCTL 代碼列表,檢索設備名列表,將他們存到字 典中,然后保存到文件里。下次我們只要在 Immunity 的命令行中簡單的輸入 !ioctl_dump, pickle 文件就會保存到 Immunity 目錄下。
萬事俱備只欠 fuzzer。接下來就是 coding and coding,我們實現的這個 fuzzer 檢測范圍 限制在內存錯誤和緩沖區溢出,不過擴展也是很容易的。
```
#my_ioctl_fuzzer.py
import pickle
import sys
import random
from ctypes import *
kernel32 = windll.kernel32
# Defines for Win32 API Calls
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 0x3
# Open the pickle and retrieve the dictionary
fd = open(sys.argv[1], "rb")
master_list = pickle.load(fd)
ioctl_list = master_list["ioctl_list"]
device_list = master_list["device_list"]
fd.close()
# Now test that we can retrieve valid handles to all
# device names, any that don't pass we remove from our test cases
valid_devices = []
for device_name in device_list:
# Make sure the device is accessed properly
device_file = u"\\\\.\\%s" % device_name.split("\\")[::-1][0]
print "[*] Testing for device: %s" % device_file
driver_handle = kernel32.CreateFileW(device_file,GENERIC_READGENERIC_WRITE,0,None,OPEN_EXISTI NG,0,None)
if driver_handle:
print "[*] Success! %s is a valid device!"
if device_file not in valid_devices:
valid_devices.append( device_file )
kernel32.CloseHandle( driver_handle )
else:
print "[*] Failed! %s NOT a valid device."
if not len(valid_devices):
print "[*] No valid devices found. Exiting..."
sys.exit(0)
# Now let's begin feeding the driver test cases until we can't be
# it anymore! CTRL-C to exit the loop and stop fuzzing
while 1:
# Open the log file first
fd = open("my_ioctl_fuzzer.log","a")
# Pick a random device name
current_device = valid_devices[random.randint(0, len(valid_devices)-1 )]
fd.write("[*] Fuzzing: %s\n" % current_device)
# Pick a random IOCTL code
current_ioctl = ioctl_list[random.randint(0, len(ioctl_list)-1)]
fd.write("[*] With IOCTL: 0x%08x\n" % current_ioctl)
# Choose a random length current_length = random.randint(0, 10000) fd.write("[*] Buffer length: %d\n" % current_length)
# Let's test with a buffer of repeating As
# Feel free to create your own test cases here
in_buffer = "A" * current_length
# Give the IOCTL run an out_buffer
out_buf = (c_char * current_length)()
bytes_returned = c_ulong(current_length)
# Obtain a handle
driver_handle = kernel32.CreateFileW(device_file, GENERIC_READ|GENERIC_WRITE,0,None,OPEN_EXISTING,0,None)
fd.write("!!FUZZ!!\n")
# Run the test case
kernel32.DeviceIoControl( driver_handle, current_ioctl, in_buffer, current_length, byref(out_buf), current_length, byref(bytes_returned), None )
fd.write( "[*] Test case finished. %d bytes returned.\n\n" % bytes_returned.value )
# Close the handle and carry on!
kernel32.CloseHandle( driver_handle )
fd.close()
```
先從 pickle 文件中取出包含 IOCTL 代碼和設備名的字典。從列表中找出能夠獲得句柄 的設備名。如果無法獲取,就從列表中移除。接著隨機選取一個設備名和 IOCTL 代碼,創 建一個隨機長度的緩沖區。最后將 IOCTL 發送給驅動。
使用如下命令進行 fuzzing。
```
C:\>python.exe my_ioctl_fuzzer.py i2omgmt.sys.fuzz
```
如果 fuzzer crash 了機器,我們能夠很準確的獲得發送的 IOCTL 代碼。接著就是調試驅 動了。表 10-7 顯示的就是一個未知驅動的 fuzzing 過程。
```
[*] Fuzzing: \\.\unnamed
[*] With IOCTL: 0x84002019
[*] Buffer length: 3277
!!FUZZ!!
[*] Test case finished. 3277 bytes returned.
[*] Fuzzing: \\.\unnamed
[*] With IOCTL: 0x84002020
[*] Buffer length: 2137
!!FUZZ!!
[*] Test case finished. 1 bytes returned.
[*] Fuzzing: \\.\unnamed
[*] With IOCTL: 0x84002016
[*] Buffer length: 1097
!!FUZZ!!
[*] Test case finished. 1097 bytes returned.
[*] Fuzzing: \\.\unnamed
[*] With IOCTL: 0x8400201c
[*] Buffer length: 9366
!!FUZZ!!
```
Listing 10-7: 一次成功的 fuzzing 記錄
能夠很清楚的看到,上一個 IOCTL,0x8400201c 引發了系統崩潰,因為這是最后一條 記錄。目前為止我們的 fuzzer 很簡單,但是很漂亮,可以通過不斷的擴展功能,使它更強大。 其中一個可能的方法就是,將 InBufferLength 或者 OutBufferLength 參數設置成和實際傳入的數據長度不一樣。開始毀滅之路吧 ,哈哈!! destroy all drivers in your path!
- 序
- 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