Напишем драйверы USB для брошенных устройств | ВесьТоп создание и продвижение сайтов

Поддержка сайта

Высокие позиции в поисковой системе, на прямую зависят от развития вашего сайта.

Продвижение сайтов

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

Создание сайтов

Мы делаем сайты быстро, недорого и профессионально. От работы с нами, у вас останутся только положительные эмоции.

Напишем драйверы USB для брошенных устройств

Напишем драйверы USB для брошенных устройств

Недавно я увидел на eBay партию очень интересных устройств Epiphan VGA2USB LR, которые принимают сигнал VGA на входе и выводят видео на интерфейс USB, как веб-камера. Мне так понравилась эта идея, и я был так счастлив, что больше не буду иметь дело с мониторами VGA, и когда я увидел, что есть поддержка Linux, я рискнул и купил всю партию за 20 фунтов.

Получив посылку, я включил устройство, но он даже не думал, что он появится в системе как UVC. Что не так?

Посмотрел на сайте производителя и увидел, что для этого устройства нужен специальный драйвер. Для меня это что-то новое, потому что обычно в ядре Linux моего дистрибутива есть все драйверы оборудования, которое я использую.

К сожалению, поддержка драйверов для этих устройств закончилась в Linux 4.9. Таким образом, ни одна из моих машин его не увидит (Debian 10 с Linux 4.19 и последняя версия LTS Ubuntu с Linux 5.0).

Но что-то, наверное, можно сделать, правда? Я имею в виду, что файлы находятся в пакете DKMS, который компилирует драйвер исходного кода по мере необходимости, как и многие другие драйверы дра

Очень грустно, но не здесь.

В пакете я обнаружил предварительно скомпилированный двоичный файл vga2usb.o. Я изучил его, рассматривая возможности реверс-инжиниринга, и нашел несколько интересных строк:

$ strings vga2usb.ko | grep ‘v2uco’ | сортировать | uniq v2ucom_autofirmware v2ucom_autofirmware_ezusb v2ucom_autofirmware_fpga

То есть ПЛИС на флешке оказалась? Как заставить это чудо работать?

Другое забавное, но тоже очень тревожное открытие — параметрические линии с использованием закрытого ключа DSA. Я подумал, а что такого в драйвере защищать?

$ strings vga2usb.ko | grep ‘epiphan’ | сортировать | uniq epiphan_dsa_G epiphan_dsa_P epiphan_dsa_Q

Чтобы иметь возможность изучить драйвер в его обычной среде, я использовал виртуальную машину в моем Debian 9 и сделал сквозную передачу KVM USB, чтобы получить прямой доступ к устройству. Позже я установил драйвер и убедился, что он работает.

Затем меня попросили посмотреть, какой протокол подключения используется в этом драйвере. Я надеялся, что это устройство будет отправлять необработанные или почти необработанные кадры, поскольку это упростит написание собственного драйвера пользовательского пространства.

Для этого я загрузил модуль usbmon в хост виртуальной машины и запустил Wireshark для перехвата USB-трафика устройства как во время его инициализации, так и во время перехвата им видео:

Напишем USB драйверы для заброшенных устройств

Я заметил, что когда вы включаете устройство, перед началом захвата видео происходит обмен большим количеством небольших пакетов данных. Вероятно, он действительно основан на ПЛИС без собственного хранилища данных. Я вижу, что после каждого включения драйвер передает на устройство битовый поток FPGA.

И окончательно в этом я убедился после того, как вскрыл корпус одного из устройств:

Итак, микросхема в красном корпусе оказалась ISL98002CRZ-170, которая работает как АЦП для сигналов VGA. Желтый чип — XC6SLX16 — Xilinx Spartan 6 FPGA. Голубой — это 64 МБ оперативной памяти DDR3, а USB-контроллер CY7C68013A отмечен фиолетовым цветом.

Напишем драйверы USB для брошенных устройств

Чтобы запустить это устройство, необходимо отправить ему битовый поток для прошивки, и я решил поискать его в этих предварительно скомпилированных двоичных файлах. Я запустил binwalk -x и начал поиск в сжатых объектах zlib. Для этого я написал простой скрипт для поиска последовательностей шестнадцатеричных чисел, в который я поместил три байта перехваченного пакета данных.

$ bash scan.sh "03 3f 55" пытается 0.elf пытается 30020 пытается 30020.zlib пытается 30020.zlib.decompressed … пытается 84BB0 пытается 84BB0.zlib пытается 84BB0.zlib.decompressed пытается AA240 пытается AA240.zlib пытается AA240.zlib.decompressed 000288d0 07 2f 03 3f 55 50 7d 7c 00 00 00 00 00 00 00 00 | ./.? UP} | …….. | пробую C6860 пробуя C6860.zlib

После распаковки файла AA240.zlib выяснилось, что данных для полного битового потока недостаточно. Поэтому решил попробовать перехватить прошивку из USB-пакетов.

И tshark, и tcpdump могут загружать USB-пакеты из файлов pcap, но они частично их сохраняют. И поскольку каждая из этих утилит дает разные части этой головоломки, я написал небольшую программу, которая объединяет данные из этих программ в структуру, чтобы я мог самостоятельно передавать эти пакеты устройству.

На этом этапе я заметил, что загрузка этих данных происходит в два этапа — сначала данные для контроллера USB, а затем для FPGA.

Я застрял здесь на несколько дней — казалось, что загружается весь битовый поток, но устройство не хотело запускаться, хотя пакеты из реального драйвера и из моей симуляции выглядели абсолютно одинаково.

Я наконец решил проблему после тщательного изучения pcap, внимательно изучив время отклика каждого пакета. Я заметил большую разницу во времени конкретной посылки:

Напишем драйверы USB для брошенных устройств

Оказалось, что из-за неправильного символа запись велась не в той области устройства. Это будет для меня уроком быть осторожным при вводе данных вручную …

И тут светодиод устройства начал мигать! Огромный успех!

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

Здесь все стало действительно сложно. Данные оказались закодированными. Вначале я запустил perf, чтобы получить общее представление о трассировке стека драйверов во время реальной работы:

Напишем USB драйверы для заброшенных устройств

Хотя мне удалось найти функцию с данными кадра, я не мог понять, как эти данные были закодированы.

Напишем USB драйверы для заброшенных устройств

Чтобы лучше понять, что происходит внутри реального драйвера, я даже использовал специальный инструмент Ghidra ANS:

Напишем драйверы USB для брошенных устройств

Хотя Ghidra потрясающая, что я заметил после замены ею IDA Pro, но все же недостаточно хорош, чтобы помочь мне понять драйвер. Очевидно, мне пришлось выбрать другой путь для реверс-инжиниринга.

Решил поставить виртуальную машину Windows 7 и посмотреть, что это за драйвер Windows. А потом я заметил, что для этого устройства доступен SDK. Один из инструментов в этом пакете оказался особенно интересным:

PSgt; ls
Каталог: epiphan_sdk-3.30.3.0007epiphanbin
Режим LastWriteTime Длина Имя —- ————- —— —- -a — 26.10.2019 10:57 AM 528384 frmgrab.dll — a — 27.10.2019 17:41 1449548 out.aw -a — 26.10.2019 10:57 245760 v2u.exe -a — 26.10.2019 10:57 94208 v2u_avi.exe -a — 26.10.2019 10:57 AM 102400 v2u_dec.exe -a — 26.10.2019 10:57 AM 106496 v2u_dshow.exe -a — 26.10.2019 10 : 57 AM 176128 v2u_ds_decoder.ax -a — 26.10.2019 10:57 AM 90112 v2u_edid.exe -a — 26.10.2019 10:57 AM 73728 v2u_kvm.exe -a — 10 / 26/2019 10:57 77824 v2u_libdec.dll
PSgt; .v2u_dec.exe Использование: v2u_dec lt; количество кадров gt; [формат] [уровень сжатия] lt; filenamegt; — уровень сжатия srcs [1..5], — захватывает и сохраняет сжатые кадры в файл v2u_dec x [формат] lt; filenamegt; — распаковывает кадры из файла в отдельные файлы BMP

Этот инструмент позволяет разделять отдельные кадры, и хорошо то, что вначале они не сжимаются, что позволяет исследовать их с помощью более мощного компьютера. Это практически идеально, и я скопировал последовательность USB-пакетов, чтобы получить эти коварные капли, но без сжатия неизвестным алгоритмом. Количество этих байтов соответствует примерно трем (RGB) на пиксель.

Первоначальная обработка этих изображений — просто взяв данные со входа и записав их в виде пикселей RGB, дала нечто, напоминающее реальные изображения, которые устройство получает через разъем VGA:

Напишем USB драйверы для заброшенных устройств

После просмотра этих байтов в шестнадцатеричном редакторе я понял, что каждые 1028 байтов маркер повторяется. Мне немного стыдно, что я потерял столько времени на написание фильтра изображений. С другой стороны, получившееся изображение напоминает некоторые образцы современного искусства:

Напишем драйверы USB для брошенных устройств

В общем, я быстро понял, что крутизна и искажения возникают из-за отсутствия передачи одного пикселя в каждой строке. Это раздражает, но я забыл, что x = 799 не равно x = 800. Когда я исправил это, у меня получилось правильное изображение, если я не считаю цвета:

Напишем USB драйверы для заброшенных устройств

Я подумал, что проблема с калибровкой, когда увидел столько одинаковых цветов. Чтобы исправить это, я создал новое тестовое изображение, чтобы посмотреть, что произойдет. Только сейчас я вспомнил, что могу использовать что-то готовое, например тестовую картинку Philips PM5544.

Напишем драйверы USB для брошенных устройств

Я загрузил изображение в ноутбук и увидел следующую картинку VGA:

Напишем USB драйверы для заброшенных устройств

Я сразу вспомнил, что некоторое время назад я работал над 3D-рендерингом, и это очень похоже на цветовое кодирование YUV.

Прочитал базовые материалы по YUV и вспомнил, что при использовании реверс-инжиниринга драйвера, если поставить точку останова именно на функции с именем v2ucom_convertI420toBGR24, то система вылетает без возможности исправления. Разве это не кодировка I420 входных данных pix_fmt yuv420p, а выходных — RGB?

После использования встроенного языка программирования Go YCbCrToRGB изображение внезапно стало почти таким же, как оригинал:

Напишем USB драйверы для заброшенных устройств

Удачи! Я действительно это сделал! Даже собранный мной драйвер давал 7 кадров в секунду. Честно говоря, мне этого достаточно, потому что я использую VGA на случай, если что-то сломается, и мне придется использовать резервный дисплей.

Итак, теперь мы знаем об этом устройстве достаточно, чтобы объяснить алгоритм его запуска:

  1.  Необходимо инициализировать USB-контроллер.
  2. После завершения инициализации USB-устройства устройство отключается от USB-шины и время от времени отслеживает появление новых команд.
  3. Теперь можно отправить битовый поток FPGA — один пакет размером 64 байта
  4. Когда эта передача данных завершится, индикатор устройства начнет мигать зеленым. На этом этапе можно отправить необходимые параметры — развертку и другие свойства.
  5. Затем пакет управления отправляется для получения кадра. Если на широкоэкранный ввод отправляется команда кадра с соотношением сторон 4: 3, это обычно приводит к сбою кадра.

Для максимального удобства использования я вставил в свой драйвер небольшой веб-сервер. Используя MediaRecorder API браузера, он легко сохраняет экранный поток в видеофайл.

Напишем USB драйверы для заброшенных устройств

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

Код и готовые компиляции для Linux и OSX можно скачать с GitHub.

Даже если никто никогда не запускал эту программу, для меня это была чрезвычайно полезная работа — путешествие в глубины протокола USB, работа с ядром, обратимая инженерия сложного кода и обзор форматов декодирования видео. Я многому научился.

Читайте так же:
Not found

Нам доверяют

Интернет магазин