Wireshark:透過 UART 進行遠端捕獲

Wireshark:透過 UART 進行遠端捕獲

長話短說:如何透過 UART 將遠端輸出正確傳輸tcpdump到本地wireshark

我嘗試捕獲流經嵌入式設備的資料包,但我無法在該設備上安裝任何東西。幸運的是,串口上打開了getty,並安裝了tcpdump。可惜的是,沒有 SSH、沒有 dumpcap、沒有 tshark。

直管式

我首先嘗試配置tty並透過管道將資料傳遞給wireshark。

stty -F /dev/ttyUSB0 raw
stty -F /dev/ttyUSB0 -echo -echoe -echok
cat /dev/ttyUSB0 | wireshark -k -i -
# On another terminal:
echo "tcpdump -U -s0 -i eth0 -w - 2>/dev/null" > /dev/ttyUSB0

Wireshark 抱怨輸入不是有效的 libpcap 格式,當然是因為指令被回顯,而我沒有設法擺脫它。

使用原始 PySerial

所以我決定創建一個 python 腳本來控制管道的工作方式:

import serial
import sys
import subprocess
import fcntl

def main(args):
    with serial.Serial('/dev/ttyUSB0', 115200, timeout=0) as ser:
        length = ser.write(b"tcpdump -U -s0 -i eth0 -w - 2> /dev/null\n") + 1
        # Discard the echoed command line
        while length > 0:
            discard = ser.read(length)
            length -= len(discard)
        # Spawn wireshark
        wireshark = subprocess.Popen(
            ["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
        )
        # Pipe data from serial to wireshark's input
        while True:
            data = ser.read(256)
            wireshark.stdin.write(data)
            try:
                wireshark.stdin.flush()
            except BrokenPipeError as e:
                break
            if len(data) > 0: print(data)
        # Send "Ctrl+C" to tcpdump
        ser.write(b"\x03")
        wireshark.wait()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

撇開腳本如何正確結束的一些問題不談,這並沒有我想像的那麼好。 Wireshark 高興了一段時間,但很快輸入就損壞了,記錄也停止了。我認為這是因為主機上的tty仍然轉換一些特殊字符,可能是換行或回車。

變得愚蠢:透過 PySerial 進行十六進位轉儲

所以我知道這很蹩腳,但由於我沒有其他想法,這就是我想出來的:

import serial
import sys
import subprocess
import binascii

def main(args):
    with serial.Serial('/dev/ttyUSB0', 115200, timeout=5) as ser:
        # Spawn tcpdump on the host and convert the raw output to stupid hex format
        # We need hexdump -C because that's the only format that doesn't mess up with the endianess
        length = ser.write(b"tcpdump -U -s256 -i eth0 -w - 2> /dev/null | hexdump -C\n")
        # Discard command line that is echoed
        discard = ser.readline()
        # Spawn wireshark
        wireshark = subprocess.Popen(
            ["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
        )
        while True:
            # Process each line separately
            data = ser.readline().decode('ascii')
            elements = data.split()
            # Remove the address and ascii convertion of hexdump and spaces
            hexa = "".join(elements[1:17])
            # Convert back hex to binary
            real_data = binascii.unhexlify(hexa)
            # Feed to the shark
            wireshark.stdin.write(real_data)
            try:
                wireshark.stdin.flush()
            except BrokenPipeError as e:
                break
        # Stop tcpdump
        ser.write(b"\x03")
        wireshark.wait()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

唉,雖然它的工作時間比以前的版本長一點,但當框架有點太大時,wireshark會彈出一個問題,說框架太大,長度確實很荒謬(比如-1562980309832),然後再一次錄音停止。

請幫忙! :)

您可以注意到,我嘗試使用-stcpdump 選項,但它不起作用,即使數量很少。

我也嘗試過 picocom 的管道,但無濟於事。

所以,如果您有任何想法,任何可以工作的 UART 隧道軟體,對我(不稱職的)使用 stty 的任何評論,或者對我的 python 腳本的任何改進,我會非常高興!

Wireshark 是 2.2.5,tcpdump 是 4.5.0,libpcap 是 1.5.0。

答案1

最後,我終於讓它真正發揮作用了。這不是完美的設置,但至少它有效,所以也許它可以幫助將來的某人。

我在上面使用了一個Python腳本py串口透過 UART 啟動 tcpdump 並使用 hexdump,以便二進位資料可以遍歷鏈接,而不會被 tty 轉錄規則修改。然後,Python 腳本將資料轉換回並透過管道傳輸到wireshark。下面的腳本是結果,與問題中的腳本相比,我-v為 hexdump 新增了選項,這樣它就不會嘗試壓縮相同的行。

import serial
import sys
import subprocess
import binascii

def main(args):
    with serial.Serial('/dev/ttyUSB0', 115200, timeout=5) as ser:
        # Spawn tcpdump on the host and convert the raw output to stupid hex format
        # We need hexdump -C because that's the only format that doesn't mess up with the endianess
        length = ser.write(b"tcpdump -U -s256 -i eth0 -w - 2> /dev/null | hexdump -Cv\n")
        # Discard command line that is echoed
        discard = ser.readline()
        # Spawn wireshark
        wireshark = subprocess.Popen(
            ["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
        )
        while True:
            # Process each line separately
            data = ser.readline().decode('ascii')
            elements = data.split()
            # Remove the address and ascii convertion of hexdump and spaces
            hexa = "".join(elements[1:17])
            # Convert back hex to binary
            real_data = binascii.unhexlify(hexa)
            # Feed to the shark
            wireshark.stdin.write(real_data)
            try:
                wireshark.stdin.flush()
            except BrokenPipeError as e:
                break
        # Stop tcpdump
        ser.write(b"\x03")
        wireshark.wait()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

相關內容