Введение в перехват USB команд с помощью Wireshark

Введение

Недавно у меня на работе возникла задача повторить работу программы настройки одного навигационного устройства и поэтому я стал изучать тему, как можно перехватить данную информацию без полного реверс инжинеринга самого ПО и прошивки устройства. В итоге выяслилось что это можно сделать по средствам перехвата USB трафика, о чем я ниже напишу.

Кратко о USB

USB является хост-ориентированной шиной с топологией многоуровневой звезды. На шине может присутствовать только один хост и до 127 устройств. Каждое устройство может иметь до 32 концевых точек (endpoint) — 16 на приём и 16 на передачу. Все передачи на шине инициирует только хост — устройство может передавать данные только тогда, когда хост запросит их.

Также у USB есть многослойная система протоколов. Самый нижний слой обычно реализован в железе, поэтому он не так важен для нас.

Далее идет транспортный слой, который работает через каналы (pipe). Каналы делятся на:

  • потоковые, которые передают разные данные
  • каналы сообщений, которые используются для управления устройствами, в каждом устройстве минимум один такой канал.

Верхний уровень - это уровень протоколов приложения (или класса в USB терминах), например USB Mass Storage (флэшки) или Human Interface Devices (HID) - устройства для взаимодействия человека с компьютером.

На уровне программного обеспечения, минимальная неделимая единица – трансфер. По типам трансферы бывают следующие:

  • прерывания (interrupt) - передают данные по чуть-чуть в реальном времени, хост не должен тормозить, и эти события не должны потеряться
  • изохронные (isochronous) - работают также как и прерывания, но могут передавать больше данных и могут допускать их потерю, если это не критично
  • пакетные (bulk) - предназначены для больших объёмов
  • управляющие (control) - используются для управления устройствами, и только у них есть жёстко заданный формат запросов и ответов.

Для отправки сообщений устройству используются управляющие трансферы, так как они (единственные из всех) являются двунаправленными и ориентированы на обмен сообщениями, они состоят из 3-х фаз:

  1. Хост предает девайсу пакет с настройками (подобно заголовку сообщения)
  2. Далее передаются данные (аналогично телу сообщения), направление передачи зависит от настроек.
  3. Посылается подтверждение о корректной обработки сообщения, направление противоположно предыдущем из п. 2.

Таким образом для формирования трансфера хост должен знать адрес устройства, которому предназначен трансфер, а также тип, направление и номер концевой точки куда отправляется сообщение.

Пример перехвата USB трафика с Wireshark

Для перехвата USB траффика можно использовать популярный снифер Wireshark. Для Windows также необходимо установит USBPcap.

Запустить прехват можно выбрав соответствующий режим в wireshark:

схема взаидодействия

Разберем подробней пример дампа:

пример дампа

Этот дамп содержит 2 части:

  1. Это подключение физического устройства в USB (пакеты 1-9);
  2. Отправка команд на переключение устройства в другой режим (пакеты 9-16).

Схематично взаимодействие будет выглядеть так:

схема взаидодействия

Как видно из примера взаимодействие с портом USB очень похоже на взаимодействие по сети. Хост всегда отправляет команду, а устройство подтверждает ее получение.

Наибольший интерес вызывают пакеты 9-16, так как видно что это контрольные трансферы (URB_CONTROL) а значит именно с их помощью происходит управление устройствам.

Итак первая команда (пакет 9) отправляет какую-то команду на устройство. Об этом свидетельствует префикс out, так как команды всегда идут от хоста, то перфикс задает напрваление относительно него.

пример дампа

Если посмотреть структуру запроса, то можно понять тип запроса, сам запрос длину тела и сами данные которые отправляются на устройство. В нашем случае не важно что означают эти параметры так как нам нужно просто воспроизвести функциональность стороннего ПО.

Следующий код запрашивает состояние устройства:

пример дампа

Затем отправляется еще одна команда с данными (пакет 13) и еще раз читает состояние (пакет 13), после чего можно заметить что девайс переподключился (пакет 17-18).

Реализация перехваченной функциональности

После анализа дампа понятно какие команды нужно отправить на устройство для воспроизведения работы анализируемого ПО.

Для простоты воспроизведем эти команды с помощью пакета PyUSB.

Скрипт будет выглядеть так:

import usb.core

# находим устройство
dev = usb.core.find()
dev.set_configuration()

# отправляем команды для переключения
dev.ctrl_transfer(0x40, 85, 0x00aa, 0, bytes.fromhex('540700000e0000000000000000'))
dev.ctrl_transfer(0xc0, 85, 0x00aa, 0, 50)
dev.ctrl_transfer(0x40, 85, 0x00aa, 0, bytes.fromhex('540400000600000000000000'))
dev.ctrl_transfer(0xc0, 85, 0x00aa, 0, 50)

Также важно отметить что команды отправляются не функцией write как описано в документации, а функцией ctrl_transfer, которая как раз отвечает за работу с контрольными трансферами.

Заключение

По сути анализ работы по USB дампам не сильно отличается от анализа сетевого трафика и если у вас есть минимальный опыт работы c wireshark то вы сможете без проблем разобраться с базовыми вещами не требующими глубокого понимания.

Ссылки

 
comments powered by Disqus