Wireshark: Удаленный захват через UART

Wireshark: Удаленный захват через UART

TL;DR:Как правильно передать вывод удаленного устройства tcpdumpна локальный компьютер через UART 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 на хосте все еще преобразует некоторые специальные символы, возможно, перевод строки или возврат каретки.

Становлюсь глупым: hexdump через 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), и запись снова останавливается.

Пожалуйста помоги! :)

Вы можете заметить, что я пробовал поиграться с -sопцией tcpdump, но она не сработала даже с небольшими объемами.

Я также пробовал подключаться через picocom, но безрезультатно.

Так что, если у вас есть какие-либо идеи, какое-либо программное обеспечение для туннелирования UART, которое могло бы работать, любые замечания по моему (некомпетентному) использованию stty или любые улучшения моих скриптов на Python, я буду очень рад!

Wireshark — 2.2.5, tcpdump — 4.5.0 с libpcap 1.5.0.

решение1

Наконец-то я заставил это работать. Это не идеальная настройка, но, по крайней мере, она работает, так что, возможно, она поможет кому-то в будущем.

Я использовал скрипт Python поверхPySerialзапустить tcpdump через UART и использовать 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))

Связанный контент