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))

相关内容