《吐血整理》高級系列教程-喫透Fiddler抓包教程(33)-Fiddler如何抓取WebSocket數據包

1.簡介

本來打算再寫一篇這個系列的文章也要和小夥伴或者童鞋們說再見了,可是有人留言問WebSocket包和小程序的包不會抓,那就關於這兩個知識點宏哥就再水兩篇文章。

2.什麼是Socket?

在計算機通信領域,socket 被翻譯爲“套接字”(套接字=主機+端口號),它是計算機之間進行通信的一種約定或一種方式。通過 socket這種約定,一臺計算機可以接收其他計算機的數據,也可以向其他計算機發送數據

socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read關閉close”模式來操作。

我的理解就是Socket就是該模式的一個實現,它只是提供了一個針對TCP或者UDP編程的接口:即socket是一種特殊的文件,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉)。

socket抽象層在網絡中的位置圖解,如下圖所示:

3.Socket通信流程

Socket通信流程,如下圖所示:

根據socket通信基本流程圖,總結通信的基本步驟:

服務器端:

第一步:創建一個用於監聽連接的Socket對像;

第二步:用指定的端口號和服務器的ip建立一個EndPoint對像;

第三步:用socket對像的Bind()方法綁定EndPoint;

第四步:用socket對像的Listen()方法開始監聽;

第五步:接收到客戶端的連接,用socket對像的Accept()方法創建一個新的用於和客戶端進行通信的socket對像;

第六步:通信結束後一定記得關閉socket;

客戶端:

第一步:建立一個Socket對像;

第二步:用指定的端口號和服務器的ip建立一個EndPoint對像;

第三步:用socket對像的Connect()方法以上面建立的EndPoint對像做爲參數,向服務器發出連接請求;

第四步:如果連接成功,就用socket對像的Send()方法向服務器發送信息;

第五步:用socket對像的Receive()方法接受服務器發來的信息 ;

第六步:通信結束後一定記得關閉socket;

4.python實現一個客戶端與服務端的通信 

4.1函數

Socket對象方法:
服務端:

函數描述
.bind() 綁定地址關鍵字,AF_INET下以元組的形式表示地址。常用bind((host,port))
.listen() 監聽TCP,可以掛起的最大連接數,該值至少爲1,一般設爲5即可
.accept() 被動接受TCP客戶端的連接
客戶端:  
函數描述
.connect() 初始化服務器連接
.connect_ex() 是對connect()函數的擴展,當出錯時返回出錯碼,不報異常
其它函數:  
函數描述
.recv() 接收數據,數據以字符串的形式返回,bufsize指定接收的最大數據量。
.send() 發送數據,將string中的數據發送到連接的套接字,返回值是要發送的字節數量,通常使用.encode()函數對數據進行轉碼
.senddall() 發送完整的數據,在返回之前會嘗試發送所有數據,成功返回None,失敗則拋出異常。
.recvfrom() 與recv()函數類似,不同的是返回值是(data,address),其中data是包含接收數據的字符串,address是發送數據的套接字地址。
.sendto() 發送UDP數據,將數據發送到套接字,形式是(ipaddr,port)的元組。
.close() 關閉套接字

4.2服務端

使用socket函數來創建一個socket對象,並設置一個socket服務,然後通過bind(hostname,port)函數來指定一個端口,使用socket對象的accept方法,等待客戶端的連接,並返回connection對象。
具體步驟爲:

#創建服務端套接字
serversocket=socket()
#把地址綁定到套接字
serversocket.bind()
#對連接進行監聽
serversocket.listen()
#使用一個while進行循環,並接收客戶端的連接
while True:
  serverclient=serversocket.accept()
  while True:
     #接收已發送
     serverclient.recv()
     serverclient.send()
     #關閉客戶端套接字
     serverclient.close()
#關閉服務端套接字
serversocket.close()

4.3具體代碼實現

實現功能:通過while實現循環接收客戶端發送的數據,並對客戶端發送的數據進行顯示並返回給客戶端數據,返回給客戶端的數據信息後加入時間戳。新建一個文件server.py。

import socket
import sys
import time

serversocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host=socket.gethostname()#獲取本地主機名
port=9999
#綁定端口號
serversocket.bind((host,port))

#設置最大連接數
serversocket.listen(5)
while True:
    print('服務器啓動,監聽客戶端鏈接')
    clientsocket,addr=serversocket.accept()
    print('鏈接地址:%s' % str(addr))
    while True:
        try:
            data=clientsocket.recv(1024)
        except Exception:
            print('斷開的客戶端:',addr)
            break
        print('客戶端發送內容:',data.decode('utf-8'))
        reply=input('回覆:').strip()
        if not reply:
            break
        msg=time.strftime('%Y-%m-%d %X')#獲取結構化時間戳
        msg1='[%s]:%s'% (msg,reply)
        clientsocket.send(msg1.encode('utf-8'))
    clientsocket.close()
serversocket.close()

4.4客戶端

創建一個客戶端用來連接以上服務的的服務,使用socket.connect()方法打開一個TCP連接到主機,連接後可以從服務端獲取數據,在操作完成後關閉連接。

具體步驟爲:

#創建客戶端的套接字 
client=socket() 
#嘗試連接服務器 
client.connect() 
#發送並接收數據 
client.send() 
client.recv() 
#關閉客戶端套接字 
client.close()

4.5具體代碼實現

新建一個文件client.py。

import socket
import sys

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host=socket.gethostname()
port=9999
s.connect((host,port))
while True:
    data= input('>>').strip()
    if not data:
        break
    s.send(data.encode('utf-8'))
    msg=s.recv(1024)
    if not msg:
        break
    print(msg.decode('utf-8'))
s.close()

4.6測試

使用cmd命令行中打開到代碼所在文件目錄,執行python 服務端文件名.py,再另打開一個cmd命令界面執行 python 客戶端文件名.py。

1.在cmd中運行服務端代碼,運行結果,如下圖所示:

2.在cmd中運行客戶端代碼,運行結果,如下圖所示:

好了到此就實現了,但是宏哥抓不到包,不知道是不是因爲服務端和客戶端都在宏哥本地一臺電腦的原因,算了宏哥直接網上找了一個在線的演示給大家。

5.實戰抓WebSocket包

由於時間關係,宏哥沒有嘗試將客戶端和服務器分開看看是否可以抓到包,然後在網上找了一個地址:http://coolaf.com/tool/chattest   演示給大家。具體操作步驟如下:

1.Fiddler V4.5以上版本,rules>customize rules,加入如下代碼,把websocket通信日誌加入log,如下圖所示:

2.class Handler 類中添加,添加的代碼如下:

static function OnWebSocketMessage(oMsg: WebSocketMessage) {  

    // Log Message to the LOG tab    
    FiddlerApplication.Log.LogString(oMsg.ToString()); 

}

3.打開PC版的聊天室(宏哥提供的演示地址),並刷新Fiddler,會看到一個WS圖標的請求,雙擊該請求,右邊會出現websocket的tab頁,如下圖所示:

PC版在線聊天,如下圖所示:

 Fiddler抓的WebSocket包,如下圖所示:

4.切換到log tab頁可以看到通信的數據往來,如下圖所示:

5.通過F12也可以看到websocket的請求信息,進入聊天室後,F12>network>濾鬥(放大鏡左邊的這個紅色圖標)>WS,雙擊name裏邊這個,即展開相關的詳情,在詳情裏選中某條數據,底部會進一步顯示全部信息,如下圖所示:

6.小結

將那段代碼保存後就可以在Fiddler右邊欄的Log標籤裏,看到WebSocket的數據包。到了這裏,還有一個情況要說明,就算是有工具可以抓到WebSocket中的包,看到的也不一定是明文。這個要看傳輸的水是什麼,如果是普通水那誰都可以分析;但如果是水銀,那這個分析水的設備很可能就顯示亂碼了。 所以也就有同學明明使用了可以抓WebSocket包的程序,卻抓出來的是亂碼。那是因爲別人傳輸的是二進制數據流(比如AMF包),而不是JSON之類的對人類可讀的明文。而宏哥演示的網址是用於測試的因此沒有考慮安全進行加密,所以使用的是明文,大家可以看到客戶端和服務端相互發送的信息內容,關於如何加密宏哥在這裏就不做贅述了因爲它不是今天的重點內容。

6.1關於websocket

1.HTML5提供的在單個TCP上運行的全雙工通訊協議(應用層協議)

2.客戶端和服務器之間只需要進行一次握手就能夠實現雙向通訊,進行數據傳輸

3.相比較Ajax輪詢機制需要不斷地從客戶端間隔性發送請求,傳輸不必要的頭部數據,消耗大量的帶寬,websocket節省了服務資源和寬帶

4.通過send()方法發送數據給客戶端,客戶端通過onmessage接收服務器返回的數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章