從CTF中學(xué)USB流量捕獲與解析
一、簡(jiǎn)介
USB接口是目前最為通用的外設(shè)接口之一,通過監(jiān)聽該接口的流量,可以得到很多有意思的東西,例如鍵盤擊鍵,鼠標(biāo)移動(dòng)與點(diǎn)擊,存儲(chǔ)設(shè)備的明文傳輸通信、USB無線網(wǎng)卡網(wǎng)絡(luò)傳輸內(nèi)容等。本文將通過兩個(gè)CTF題,講解如何捕獲USB接口的數(shù)據(jù),以及鍵盤鼠標(biāo)USB協(xié)議的具體解析方式。相關(guān)下載鏈接:http://pan.baidu.com/s/1i57b33B
二、 USB capture
USB流量的捕獲可以使用wireshark或者usbpcap來進(jìn)行,最新版本的wireshark已經(jīng)支持USB接口的捕獲,且在安裝時(shí)會(huì)提示usbpcap的安裝,當(dāng)前網(wǎng)上已有相關(guān)中文資料對(duì)wireshark抓取usb數(shù)據(jù)包的方法進(jìn)行講解,感興趣的讀者可閱讀參考鏈接,在此我們使用一種相對(duì)簡(jiǎn)單的方式,即直接采用usbpcap捕獲USB流量。該軟件的下載地址為http://desowin.org/usbpcap/,可支持32位以及64位的winxp至win10操作系統(tǒng),安裝完成后須重啟機(jī)器或者按照提示選擇重啟所有USB設(shè)備。
安裝完成后,直接雙擊USBPcapCMD.exe,按照提示信息選擇filter,輸入文件名,便可愉快地等產(chǎn)生的信息被捕獲了,程序運(yùn)行界面如下圖:
三、鍵盤流量解析
以今年xnuca misc 專場(chǎng)的old years 題為例,該題目給出一個(gè)pcap包,使用wireshark打開,看到Protocol 為USB協(xié)議。
USB協(xié)議的數(shù)據(jù)部分在Leftover Capture Data域之中,右鍵leftover capture data –> 應(yīng)用為列,可以將該域的值在主面板上顯示,鍵盤數(shù)據(jù)包的數(shù)據(jù)長(zhǎng)度為8個(gè)字節(jié),擊鍵信息集中在第3個(gè)字節(jié),每次key stroke都會(huì)產(chǎn)生一個(gè)keyboard event usb packet ,如下圖:
網(wǎng)上查找USB協(xié)議的文檔,可以找到這個(gè)值與具體鍵位的對(duì)應(yīng)關(guān)系,http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
第53頁(yè)有一個(gè)usb keyboard/keypad映射表:
使用wireshark自帶的tshark命令行工具,可以將 leftover capture data單獨(dú)提取出來,具體命令為:
- tshark.exe -r usb1.pcap -T fields -e usb.capdata > usbdata.txt
然后我們需要編寫腳本從得出的userdata.txt文件中過濾出鍵盤擊鍵相關(guān)的流量,并根據(jù)上述映射表,將鍵盤按鍵按照對(duì)應(yīng)關(guān)系輸出出來,這里附上簡(jiǎn)要的腳本:
- mappings = { 0x04:"A", 0x05:"B", 0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G", 0x0B:"H", 0x0C:"I", 0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O", 0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5", 0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]", 0X2B:" ", 0x2C:" ", 0x2D:"-", 0x2E:"=", 0x2F:"[", 0x30:"]", 0x31:"\\", 0x32:"~", 0x33:";", 0x34:"'", 0x36:",", 0x37:"." }
- nums = []
- keys = open('usbdata.txt')
- for line in keys:
- if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
- continue
- nums.append(int(line[6:8],16))
- keys.close()
- output = ""
- for n in nums:
- if n == 0 :
- continue
- if n in mappings:
- output += mappings[n]
- else:
- output += '[unknown]'
- print 'output :\n' + output
運(yùn)行該腳本,便可得到輸出結(jié)果如下:
這里還有最后一個(gè)小彎,由提示中的“不使用拼音 ”等信息推測(cè)出上文的特殊編碼可能是某種拼音之外的古老的輸入法,例如五筆,畢竟這也是做keylogger的人需要考慮而且頭疼的一個(gè)地方。嘗試對(duì)照著輸入,可以得出如下文字:
最后得出flag . xnuca{wojiushifulagehaha}
四、鼠標(biāo)流量解析
這是xnuca第二道usb流量的題,首先可以直接使用上述的解決方案試一下,得到這樣一話:
解決本題需要把鼠標(biāo)流量還原出來,然而鼠標(biāo)與鍵盤不同,鼠標(biāo)移動(dòng)時(shí)表現(xiàn)為連續(xù)性,與鍵盤擊鍵的離散性不一樣,不過實(shí)際上鼠標(biāo)動(dòng)作所產(chǎn)生的數(shù)據(jù)包也是離散的,畢竟計(jì)算機(jī)表現(xiàn)的連續(xù)性信息都是由大量離散信息構(gòu)成的。
首先同樣使用tshark 命令將cap data提取出來:
1tshark.exe -r usb2.pcap -T fields -e usb.capdata > usbdata.txt
每一個(gè)數(shù)據(jù)包的數(shù)據(jù)區(qū)有四個(gè)字節(jié),第一個(gè)字節(jié)代表按鍵,當(dāng)取0x00時(shí),代表沒有按鍵、為0x01時(shí),代表按左鍵,為0x02時(shí),代表當(dāng)前按鍵為右鍵。第二個(gè)字節(jié)可以看成是一個(gè)signed byte類型,其最高位為符號(hào)位,當(dāng)這個(gè)值為正時(shí),代表鼠標(biāo)水平右移多少像素,為負(fù)時(shí),代表水平左移多少像素。第三個(gè)字節(jié)與第二字節(jié)類似,代表垂直上下移動(dòng)的偏移。
了解協(xié)議相關(guān)約定之后,可編寫腳本將數(shù)據(jù)包的內(nèi)容變成一系列點(diǎn)的集合,為了區(qū)分左右按鍵,可以特意對(duì)第一個(gè)字節(jié)的內(nèi)容作一下判斷。相關(guān)腳本如下:
- nums = []
- keys = open('data.txt','r')
- posx = 0
- posy = 0
- for line in keys:
- if len(line) != 12 :
- continue
- x = int(line[3:5],16)
- y = int(line[6:8],16)
- if x > 127 :
- x -= 256
- if y > 127 :
- y -= 256
- posx += x
- posy += y
- btn_flag = int(line[0:2],16) # 1 for left , 2 for right , 0 for nothing
- if btn_flag == 1 :
- print posx , posy
- keys.close()
本題的flag藏在右鍵信息中,當(dāng)btn_flag 取2時(shí),運(yùn)行腳本可以得到一系列坐標(biāo)點(diǎn):
得到這些點(diǎn)之后,需要將他們畫出來,因而需要輔以gnuplot 或者其他的繪圖工具,gnuplot的命令為"plot inputfile",運(yùn)行如下:
最后得到本題的flag: XNUCA{USBPCAPGETEVERYTHING}