使用過mysql等資料庫的話,一定會對資料庫強大的過濾以及搜索功能印象深刻。面對離線的數據包文,很多時候需要批量的提取某些信息,批量的查詢某些信息,批量的修改一些信息,批量的刪除一些信息。我是經常將單個的pcap報文和mysql中的表概念對應起來的。因為在使用wireshark進行展示的時候,每一片報文就像數據表的一行一樣,顯示著這個數據包的屬性信息。這個屬性信息要比絕大多數的數據表要豐富,因為wireshark提供了太多可以使用的信息。既然將pcap報文和數據表對應起來,那麼是否可以像操作資料庫那樣隨心所欲的操作pcap報文呢。當然可以,就是要使用wireshark提供的lua介面。

有這樣一個場景,就是批量提取HTTP報文中的host和UA欄位,通常在DPI的識別都是基於host和UA的,同理HTTPS的SNI也是一樣的。

在正式介紹lua介面之前,先介紹一個命令tshark。當然你可能會使用tcpdump,但是 tshark作為wireshark默認支持的命令,很多的特性是非常的好用的。我是這樣理解tshark和 tcpdump之間的關係的,tshark相當於wireshark親生的,而tcpdump則是其收養的。至於功能方面,由於這裡需要使用lua腳本,因此只能使用tshark。首先這個命令能夠完美的完成上述提到的場景,相應的shell腳本如下:

#!/bin/bash
find -name *.pcap > pcapFileName.txt
while read LINE
do
echo $LINE
tshark -r $LINE -T fields -e http.user_agent -E header=y -E separator=, | sort | uniq -c >> ua.txt
tshark -r $LINE -T fields -e http.host -E header=y -E separator=, | sort | uniq -c >> host.txt
done < pcapFileName.txt
cat ua.txt | sort -k 2,30 -d| awk {$1=""}{print $0} | uniq -c | awk {$1=""}{print $0} | grep -v "^$" | rev | sort -d | rev > uaSort.txt
cat host.txt | sort -k 2,30 -d| awk {$1=""}{print $0} | uniq -c | awk {$1=""}{print $0} | grep -v "^$" | rev | sort -d | rev > hostSort.txt

其中最為核心的命令為 tshark -r $LINE -T fields -e http.user_agent -E header=y -E separator=, | sort | uniq -c >> ua.txt,tshark更多參數的使用可以通過tshark -h進行查詢,這裡面用到-r讀文件參數,以及-e屬性,和-T fields配合使用表示列印輸出對應的屬性。主要提一下-e後面表示報文某個屬性項字元串的使用。這個字元串叫做過濾器,在wireshark的右上角的expression中提供了所有的過濾器,如下圖。

過濾器是wireshark強大之處之一。首先wireshark目前提供了1900+種協議的支持;其次針對每一種協議,wireshark提供了遠遠大於協議自身所提供屬性欄位的解析功能。舉個例子在TCP協議中,TCP層是沒有數據部分長度這個欄位的,數據部分只能通過IP層提供的長度以及TCP層提供的頭部長度計算得到。而對於wireshark來說,提供了tcp.hdr_len表示協議欄位中的頭部長度,提供了tcp.len表示TCP上層數據的長度,而這個屬性在協議中是沒有的。

有的時候你可能想按照某個報文的特點來進行過濾,但是並不明確如何使用對應的過濾器,這個時候可以在wireshark中選中相應的屬性欄位,右鍵,Apply as Filter,在過濾那一欄就會顯示相應的過濾條件。當然如果對於過濾條件很熟悉的話,也是可以直接輸入的。

這個時候你可能會發現tshark對於報文的操作都是在整個pcap這個粒度來進行的,應付該章開始的場景還是綽綽有餘的,但是如果我們想進行更為精細的操作,比如在操作單個報文的時候,做一些處理,那麼tshark就無能為力了,相應後面的一些場景也基本是圍繞著單片報文處理層次展開。

本次先還是以該場景為例,介紹一下lua如何實現報文中host,ua以及sni的提取,相應的代碼如下:

local getHttpHost = Field.new("http.host")
local getHttpUa = Field.new("http.user_agent")
local getSslServerName = Field.new("ssl.handshake.extensions_server_name")

local httpHostSet = {}
local httpUaSet = {}
local sslServerNameSet = {}

do
local function packet_listener()
local tap = Listener.new("frame", "tcp.port == 80")
--frame是監聽器的名稱,tcp是wireshark過濾器規則

function tap.packet(pinfo,tvb)
--回調函數,每收到一個包執行一次。
local httpHost = getHttpHost()
local httpUa = getHttpUa()
local sslServerName = getSslServerName()

if(httpHost)
then
table.insert(httpHostSet,tostring(httpHost))
--print(httpHostSet[2])
end

if(httpUa)
then
table.insert(httpUaSet,tostring(httpUa))
--print(httpUa)
end

if(sslServerName)
then
table.insert(sslServerNameSet,sslServerName)
--print(httpUa)
end

end

function tap.reset()
--print("tap reset")

end

function tap.draw()
--結束執行
--print("tap draw")
for key,value in ipairs(httpHostSet) do
print(value)
--print(key)
end
for key,value in ipairs(httpUaSet) do
print(value)
--print(key)
end

for key,value in ipairs(sslServerNameSet) do
print(value)
--print(key)
end
end
end
--監聽報文
packet_listener()

end

對上述程序做如下說明:

Field屬性域提取器類,local getHttpHost = Field.new("http.host")生成http.host 這樣一個類對象, getHttpHost() 表示得到具體的屬性域的值。 Listener 是監聽器類,local tap = Listener.new("frame", "tcp.port == 80")生成一個監聽器類對象,監聽器是每一片匹配上過濾條件的報文到來時就執行一次,本次的過濾條件為80埠的tcp報文,具體執行的函數為functiontap .packet(pinfo,tvb),參數中的內容pinfo表示Pinfo類對象,具體指的是報文相關信息類,包括報文編號,報文埠等;tvb為Tvb類對象,表示報文的原始數據內容,後續的涉及到對於數據的修改等方面操作都是基於該類的。

tap.draw如果是在wireshark圖形界面,則表示每隔數秒重行刷新圖像界面的內容,如果是在 tshark中表示程序最後執行的內容。local httpHostSet = {}是Lua中表變數的定義,類似於C語言中的數組,可以看到 httpHostSet是沒有定義具體的大小的,表示其可以動態的增長。其實對於高級語言這種特性的背後都是先初始一個具體的大小,等達到這個大小後,成倍的重新申請空間,具體的不在 過 多 表 述 。 for 循 環 也 是 Lua 中 的 遍 歷 方式table.insert(httpHostSet,tostring(httpHost))表示向表httpHostSet插入具體的字元串tostring(httpHost)。

我在centos7上面批量的處理報文時候,使用瞭如下的shell腳本來處理多個pcap報文:

#!/bin/bash
find ../pcapDir/ -name *.pcap > pcapFileName.txt
while read LINE do
tshark -X lua_script:getHostAndUa.lua -r $LINE -q
done < pcapFileName.txt

其中-q參數表示不列印報文信息,可以看到這對於處理大量的報文還是挺方便的。如果tshark -h內容不夠詳細,則使用man tshark進行查看。

那麼使用lua如何提取數據數據呢,這部分會在後面陸續提及。對於上述所提到的API可在wireshark開發者手冊中查到。

推薦閱讀:

相關文章