wireshark外掛開發 - 自定義協議
阿新 • • 發佈:2021-06-16
雖然wireshark自帶了很多知名協議的解析外掛,譬如HTTP、DHCP等等,然而在實際應用環境中,有不少軟體之間的通訊協議都是私有的,如遊戲客戶端和伺服器之間的互動協議通常都是私有的,wireshark無法具體解析出各種欄位之間的含義,只能顯示接收到的二進位制資料,給協議的分析和問題的排查帶來了一定的困難,尤其是協議內容比較複雜時。
本文一個自定義的簡單協議入手,分析如何基於wireshark開發自定義協議分析外掛。
1.1.概述
本書使用Go語言來描述協議的互動過程。Go由Google出品,號稱是網際網路上的C語言,有點類似於C語言,以其簡潔和高併發著稱。
即使不瞭解Go語言也沒有關係,本書給出的程式碼,基本可以自釋其義,瞭解過程即可,重點不在於此。
1.2.協議描述
1 package packet 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "os" 8 ) 9 10 type NPacket struct { 11 Version int16 //兩個位元組 12 ID uint32 //四個位元組 13 Buffer [1024]byte //簡單起見,固定為1024個位元組 14 } 15 16 func (packet *NPacket) String() string { 17 return fmt.Sprintf("%v, %v, %v\n", packet.Version, 18 packet.ID, string(packet.Buffer[:])) 19 } 20 21 func CheckError(err error) { 22 if err != nil { 23 fmt.Println("Error: %s", err.Error()) 24 os.Exit(1) 25 } 26 } 27 28 func ConvertToPacket(b []byte) (packet *NPacket, err error) { 29 buffer := bytes.NewBuffer(b[:]) 30 31 packet = &NPacket{} 32 #將緩衝區buffer的內容轉換到NPacket結構體中 33 err = binary.Read(buffer, binary.BigEndian, packet) 34 35 return packet, err 36 } 37 38 func ConvertToBuffer(packet *NPacket) (b []byte, err error) { 39 buf := new(bytes.Buffer) 40 41 #將結構體內容轉換到緩衝區中 42 err = binary.Write(buf, binary.BigEndian, packet) 43 44 return buf.Bytes(), err 45 }
1.3.客戶端
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 ) 7 8 import "packet" 9 10 func main() { 11 #連線服務端,UDP協議 12 conn, err := net.Dial("udp", "192.168.5.4:11110") 13 defer conn.Close() 14 packet.CheckError(err) 15 16 #定義報文內容 17 pkt_send := packet.NPacket{Version: 1, ID: 1} 18 copy(pkt_send.Buffer[:], "Ping") 19 20 send_buff, err := packet.ConvertToBuffer(&pkt_send) 21 packet.CheckError(err) 22 #傳送報文 23 conn.Write(send_buff) 24 25 var recv_msg [4096]byte 26 #讀取報文 27 n, err := conn.Read(recv_msg[0:]) 28 packet.CheckError(err) 29 30 #報文轉換到結構體中 31 pkt_recv, err := packet.ConvertToPacket(recv_msg[0:n]) 32 packet.CheckError(err) 33 34 #會呼叫NPacket結構體的String方法 35 fmt.Println(pkt_recv) 36 }
1.4.服務端
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 ) 7 8 import "packet" 9 10 func recvUDPMsg(conn *net.UDPConn) { 11 var buf [4096]byte 12 13 #讀取UDP報文 14 n, raddr, err := conn.ReadFromUDP(buf[0:]) 15 packet.CheckError(err) 16 17 #網路資料轉換到結構體中 18 pkt_recv, err := packet.ConvertToPacket(buf[0:n]) 19 packet.CheckError(err) 20 21 fmt.Println(pkt_recv) 22 23 #構造響應報文 24 pkt_send := packet.NPacket{Version: pkt_recv.Version, ID: pkt_recv.ID} 25 copy(pkt_send.Buffer[:], "Pong") 26 27 send_buff, err := packet.ConvertToBuffer(&pkt_send) 28 packet.CheckError(err) 29 #傳送報文 30 _, err = conn.WriteToUDP(send_buff, raddr) 31 packet.CheckError(err) 32 } 33 34 func main() { 35 udp_addr, err := net.ResolveUDPAddr("udp", ":11110") 36 packet.CheckError(err) 37 38 conn, err := net.ListenUDP("udp", udp_addr) 39 defer conn.Close() 40 packet.CheckError(err) 41 42 recvUDPMsg(conn) 43 }
1.5.啟動方式
1、啟動服務端
開啟CMD視窗,進入原始碼所在目錄
$env:GOPATH="原始碼所在目錄"
$env:GOPATH
go run src\main\server.go
2、啟動客戶端
開啟CMD視窗,進入原始碼所在目錄
$env:GOPATH="原始碼所在目錄"
$env:GOPATH
go run src\main\client.go
1.6.抓包