Wireshark usb sniffer windows

Toggle table of contents sidebar

Warning

This method requires a lot of tinkering, and is reserved for advanced
users. If you do not feel comfortable with this guide, feel free to
refuse or abandon at any point!

Note

To bring more context, and if you feel yourself to be up to it, it is also
possible to record your screen at the same time the capture is going on.

Sometimes, when dealing with exotic calculator models or cables, if you have
access to a Microsoft Windows machine, a maintainer may ask you to capture
communications from other software for analysis.

First, ensure that you have all of the official CESG502 driver from CASIO
by installing FA-124, and rebooting your computer.

Then, you must download and install Wireshark, and ensure that it comes
with USBPCap; see Wireshark USB capture setup for Windows for
more information.

You can now run Wireshark, and will see one USBPcap interface per USB
bus. You will need to determine on which will the calculator is present, and
filter on it to avoid including communication from other devices (which would
be a privacy breach for you!).

In order to accomplish this, you must first connect your calculator and place
it in Receive or USB Key mode, so that it is detected by the computer.

Preview of the interface list, with the gear icon next to the USBPcap
interfaces.

Then, you can select the small gear icon next to every interface, until you
see one with “CESG502 USB”.

../_images/wsk2.png

Options for one of the USBPcap interfaces, with the CESG502 USB
device appearing and checked.

You must select it, click on save (on the bottom of the window), then
double click on the interface to select it. You can now disable Receive or
USB Key mode on your calculator.

Note

Wireshark unfortunately does not have an option to discard the first
packets; you can help the reader distinguish what is part of the actual
exchange by leaving a large enough interval at this point, e.g. 10 seconds.

From here, Wireshark is recording! You can run your test scenario, and
Wireshark will capture the communications between your computer and calculator.

Once your test is finished and the communication with the calculator is
terminated properly, you can select the button to stop the capture (red
square).

../_images/wsk3.png

Wireshark capture interface with the stop icon (red square) highlighted.

Once the capture has stopped, you must save the result by going to
File > Save As in the contextual menu, then choosing a file name.

../_images/wsk4.png

Wireshark capture save interface.

The resulting file will have the .pcap or .pcapng extension, which you
can transmit to the maintainer in a private manner, as the file may contain
identifying information.

Wireshark capture file preview on the Windows desktop.

Use USBPcap as Wireshark extcap

Starting with USBPcap 1.2.0.0 it is recommended to use USBPcapCMD as Wireshark extcap. In order for USBPcap to appear in Wireshark interfaces list, USBPcapCMD has to be copied to either global or personal extcap directory. The extcap directory can be found by starting Wireshark, clicking on Help->About Wireshark and navigating to Folders tab.

Once USBPcapCMD is copied to Wireshark extcap directory, USBPcap interfaces will show up in Wireshark. To configure capture session, click on the gearbox symbol next to one of available USBPcap interfaces.

Attached USB Devices in USBPcap options can be used to determine the Root Hub to which the device is connected to. It is recommended to configure USBPcap to capture from newly connected devices. Capture can be started by double clicking on USBPcap interface.

USB Packet capture for Windows Tour (obsolete)

This short tour assumes you have installed the latest version of USBPcap and Wireshark 1.10.0rc1 (or newer) and rebooted your system. Each of the steps contains short description of what should happen and in some cases gives tips for troubleshooting.

If you feel the information provided there is not complete (it doesn’t cover your case), please describe your problem on the USBPcap mailing list.

Step 1 — identify the Root Hub you want to monitor

The first step is to connect the device you want to sniff the traffic and identify the Root Hub this device is connected to. In order to do so, launch the USBPcapCMD.exe that is stored in the installation directory. You should be presented with something similiar to the picture below.

Troubleshooting step 1

If for any reason you can’t see the list of connected devices make sure you have the USBPcap driver installed and you have restarted your computer after the installation.

Step 2 — start the capture

So now you know which of the Root Hubs available in your system you want to monitor. Please disconnect the device from your computer — this will allow USBPcap to capture the USB descriptors needed for analysis in Wireshark. Now you can run the USBPcapCMD.exe again and enter your desired output file name. (A careful reader will notice that they can skip the restart part: all that required to get the descriptors in the capture file is to reconnect your device after capture has started.).

We will be capturing the Root Hub that showed the two Hubs connected to it and an composite USB device (it is actually DigiTech RP250).

Now it is time to use the device in order to get packets captured. In this example I have simply started the X-Edit software that controls the DigiTech RP250.

Step 3 — analyse the data

After you’re done collecting data, press Ctrl+C and start Wireshark. Once started, open the pcap file you have created in Step 2. You should see the packets allongside with their description. The sample capture is available at the Google code: sample_2013_04_10.pcap

Step 4 — live capture

If you didn’t like that in steps 2 and 3 you had to finish capturing before having a chance to look at the data, you can also do a live capture. In order to do so, you must have running the cmd.exe with elevated privileges (as Administrator). Then enter the following command:

USBPcapCMD.exe -d \\.\USBPcap2 -o - | "C:\Program Files\Wireshark\Wireshark.exe" -k -i -

This should result in live capture from standard input in Wireshark as shown below.

Step 5 — Contribute to the project :-)

Once you know how to use USBPcap you might want it to work better. There are numerous ways to help, for example:

  • Improving project website
  • Improving the documentation
  • Improving the filter driver
  • Improving the sample application
  • Improving installation process
  • Creating project artwork (icon, website banner, etc.)
  • Integrating the project more closely with Wireshark (dumpcap)
  • Donating money

If you can help please check the menu on the right for links for github page, donation fund and contact information.

Everyone would have well known with capturing network packets using analyzer tools. But very few have known with capturing with USB packets. We are talking about USB sniffer which is quite often used in ethical hacking courses offered by International Institute of Cyber Security . USB sniffers capture and shows the packets which are transferring.

USB Protocols :-

USB interface consists of layers of protocol. In USB interface lower level layers are single handled. USB packets contain information like :-

  • Data exchange
  • Controlling the Data exchange
  • Error correction & detection

USB contains Different packet fields :-

  • SYNC – It is important field holding at start of the packet. For low and full speed mode, this field is 8 byte long and 32 byte high.
  • PID – Indicates packet id. it shows that what type of packet is being sent. This field is 8 bit long.
  • ADDR – This field stores the destination address of USB device.
  • CRCCycle Redundancy Check is used to check for any error in the data packet.
  • EOPEnd Of Packet Signals the data lines for single-ended zero.

There are two methods to capture USB packets – GUI mode using Wireshark and the CUI mode using USBPcap installer.

  • We will test wireshark on Windows 10 with build version 1709.
  • Download Wireshark from : https://2.na.dl.wireshark.org/win64/Wireshark-win64-3.0.2.exe
  • Install the wireshark. Make sure to install USBPcap while installing wirehark. If USBPcap does not install, go to : https://github.com/desowin/usbpcap/releases/download/1.2.0.3/USBPcapSetup-1.2.0.3.exe
  • Install the USBPcap. After installing Wireshark & USBPcap. Start the Wireshark.

  • Click on USBPcap1 & then connect USB device. And then start copying data from local computer to connected USB device.
  • As you will start the copying the data. You will see the packets transferring from source to destination in wireshark.

  • Above screenshot shows packets transferring from host to destination. The data is transferring on USB Mass Storage. Then it data is being transferred using protocol USBMS.
  • The USB mass storage is an computing protocol determined by USB implement Forum. USBMS makes USB device accessible to host. USB device works as external Hard drive.

  • Now we will analyze data packet. And we will try to explain each & every information which shows.
  • Firstly it shows the frame. Frame is consisting basic info of the transferring bytes.

  • Above screenshot shows the details about Frame of 40 bytes. Then it shows the interface ID on which data is captured.
  • Then frame is having info of frame length, frame number & bytes. Then it shows complete time details from previous captured & displayed frame. All this analysis is part of ethical hacking course run by International Institute of Cyber Security.
  • Further details it shows USB URB information which consists of IRP ID and IRP info.
  • There are other light weight packets analyzer like termshark available on internet.

Cyber Security Researcher. Information security specialist, currently working as risk infrastructure specialist & investigator. He is a cyber-security researcher with over 25 years of experience. He has served with the Intelligence Agency as a Senior Intelligence Officer. He has also worked with Google and Citrix in development of cyber security solutions. He has aided the government and many federal agencies in thwarting many cyber crimes. He has been writing for us in his free time since last 5 years.

2019-07-05

I was trying to reverse engineer the protocol used to communicate with a 3D printer and was thinking about hooking up an oscilloscope when I discovered that USB traffic can be captured and analyzed by Wireshark (which I had thought was only for network traffic). These instructions are for sniffing USB data using Wireshark on Mac OS, but the process should be similar under Linux and Windows.

NB: As of MacOS 10.15.1 Catalina it is no longer possible to activate the virtual USB interface XHC20 using the method described below, although it appears it might be possible if you first disable System Integrity Protection as described here: https://forums.developer.apple.com/thread/124875 

Enable USB Port Monitoring

Mac OS has a virtual port that can be used to examine USB traffic. Find the port(s), open a terminal window and type:

tcpdump -D

and look for a port name starting with XHC like XHC0, XHC1 in the output. On my machine the interface was XHC20.

To enable the port(s), type the following in the terminal window using the port name(s) you found:

sudo ifconfig XHC20 up

NB: When you are done with your research, disable the port by typing the following in a terminal window:

sudo ifconfig XHC20 down

Identify the Target Device

Click the Apple menu in the top left corner of the screen and select “About This Mac”:

Click “System Report”, select “USB” on the left hand side and then search for the USB device you are interested in:

Note down the “Location ID” of the device – you will need that to find the traffic in Wireshark.

After installing Wireshark, fire it up and select the port to capture – XHC20 (or whatever port you found). You should immediately see USB packets being displayed in the capture window.

In the space for a display filter above the capture window, enter the following (replacing the ID with the location ID for your device):

usb.darwin.location_id == 0x14323000

You should now only see packets related to your device – if no packets are being sent to the USB device then the display window may be empty.

After you capture some packets the display will look more like:

In the above picture Wireshark is configured to display the packet list in the top pane, packet details in the middle pane and the raw packet in the bottom pane. The direction of the packets is displayed “in” (into the computer from client), “out” (from computer into the client device). The USB payload seems to start at byte 0x0020 in the raw packet data. In the above picture the packet is displaying the response by a 3D printer to a command issued by the computer, using a variation of the G-Code protocol.

Note that Wireshark has mis-identified some of the packets as “SNA” – you can tell Wireshark what protocols to expect (by default all are enabled), thereby forcing it to display all packets as USB:

Wireshark Tips

Beware – sometimes it translates the hex to text incorrectly:

This should translate to ~M105 . If you are expecting ASCII text, you can use a site like http://www.unit-conversion.info/texttools/hexadecimal/ to verify the translation.

While Wireshark is running it can be collecting huge volumes of data which can fill up your memory/drive, so remember to stop the capture when you are done. You can limit the amount of captured data (especially useful if you are planning to save the capture as a file for later analysis) by creating a capture filter instead of/or in addition to the display filter. If you intend to use the filter more than once then define it under the “Capture” menu:

You select filters to use during data capture by clicking “Options” under the “Capture” menu to get the capture options window:

Click the circled icon to use a predefined filter (eg one you just created), or type a filter in the box. Unfortunately, as of writing this, USB capture filtering is not implemented.

Почти четыре года назад я писал о реверс-инжиниринге Stream Deck с целью получения полного контроля над устройством и устранения зависимости от ПО Stream Deck. Мне по-прежнему нравится это «железо», но ПО стало только хуже — теперь оно даже требует входа в аккаунт пользователя для скачивания расширений.

Я стремлюсь максимально уважать приватность и выбор пользователей, поэтому если уж я хочу использовать устройство без аккаунта, то вам лучше предоставить мне такую возможность. К счастью, развивая идеи моей предыдущей работы над DeckSurf, я наконец-то набрался решимости вложиться по полной и сделать мой проект приемлемой альтернативой проприетарному ПО для этого крайне гибкого и универсального устройства с кнопками.

В этом посте мы рассмотрим работу Stream Deck Plus — устройства ценой $179,99, которым вы, дорогой читатель, теперь сможете пользоваться, даже если не хотите устанавливать ПО его производителя.

С чем мы будем работать

Вот рассматриваемое нами устройство:

Stream Deck Plus

Stream Deck Plus имеет особенности, которые я должен вкратце описать, прежде чем приступать к подробному процессу реверс-инжиниринга:

  1. 8 кнопок. По сути, этим он ничем не отличается от других устройств Stream Deck. Количество может меняться, но их поведение одинаково.
  2. Узкий экран. Под кнопками есть узкий цветной экран, на котором может отображаться вспомогательная контекстная информация.
  3. 4 поворотных ручки. Каждую ручку можно бесконечно крутить влево или вправо. Также их можно нажимать (кликать).

Мы подробно разберём каждую из особенностей и способ их работы. Кроме того, скажу, что для выполнения реверс-инжиниринга этого устройства я использовал следующий инструментарий:

  • Wireshark c USBPcap.
  • Виртуальная машина, к которой из USB-устройств подключён только Stream Deck Plus.
  • ПО Stream Deck для изучения передаваемого по проводам трафика.

Stream Deck — это стандартное HID-устройство, не требующее для своей работы установки ПО Stream Deck. То есть после реверс-инжиниринга протокола оборудования я смогу создать собственное клиентское ПО, которое позволит выполнять любые нужные мне действия и никак не зависеть от стека ПО Elgato.

Подготовка к процессу исследования

Для начала запустим Wireshark и выберем интерфейс перехвата USB.

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

Чтобы найти устройство Stream Deck Plus в моём случае, я могу выполнить фильтрацию по product ID (PID), то есть 0x0084 (на всякий случай: Elgato VID — это 0x0FD9). Ограничение трафика только до подключённого устройства Stream Deck Plus можно выполнить, применив следующую строку фильтра:

usb.idProduct == 0x0084

После этого Stream Deck появится в списке (вероятно, в огромном количестве другого USB-трафика):

Исходя из показанного на изображении, мне нужно найти 3.5.0. Это значение также является destination — «адресом» устройства, который можно использовать для изучения исходящего трафика, например, задающего яркость или изображения на разных поверхностях Stream Deck.

Имея эти данные, я могу задать следующую строку фильтра:

usb.dst matches "3\\.5\\..*"

Постойте-ка… Выше мы сказали, что нам нужен адрес 3.5.0, но во второй строке фильтра мы ищем всё, что соответствует паттерну 3.5.. Почему?

А вы внимательны! И в самом деле, я выполняю фильтрацию не только по 3.5.0. USB-адрес состоит из трёх компонентов — шины, устройства и конечной точки. В нашем случае Stream Deck Plus работает как шина 3, устройство 5 и конечная точка 0, но также мы должны знать и то, что одно устройство может иметь множественные конечные точки. Поэтому чтобы правильно изучать весь трафик устройства Stream Deck Plus, мы исключим идентификатор конечной точки.

Для этого можно просто воспользоваться следующей строкой фильтра:

usb.dst ~ "3.5"

Так вывод будет чуть чище и нам не придётся беспокоиться о регулярных выражениях относительного ограничения.

Разобравшись с основами, давайте начнём разбирать, как оборудование взаимодействует с моим компьютером, и наоборот.

Оборудование Stream Deck

▍ Кнопки

Кнопки ведут себя так же, как у разобранного нами ранее Stream Deck XL. Я очень благодарен разработчикам за согласованность; думаю, с точки зрения удобства поддержки это логично — если вы создали более-менее работающий API, то зачем менять его действия при смене версий оборудования? Спасибо Elgato за это.

Каждая кнопка поддерживает цветное изображение размером 120×120. Его содержимое динамически обновляется не устройством, а хостом, то есть компьютером, к которому оно подключено. Если на кнопке отображается обновлённый статус, то это потому, что компьютер постоянно передаёт на Stream Deck изображения. В Windows и macOS этой работой обычно занимается ПО Stream Deck (которое я намерен полностью заменить на DeckSurf).

▍ Работа с изображениями

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

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

+----------+----+----+----+----+----+----+----+----+
| Байт     |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |
+----------+----+----+----+----+----+----+----+----+
| Значение | 02 | 07 | 18 | 00 | F8 | 03 | 00 | 00 |
+----------+----+----+----+----+----+----+----+----+

Заголовок можно описать так:

Всё, что идёт после заголовка — это полезная нагрузка изображения. Если изображение разбито на части, то мы увидим несколько пакетов:

Эти пакеты URB_INTERRUPT out нам и нужны. Не волнуйтесь, если пока не разобрались в этой терминологии. URB расшифровывается как «USB Request Block», эти структуры используются для описания передачи USB между хостом и устройством. INTERRUPT обозначает тип передачи. Передача USB interrupt предназначена для устройств, требующих обмена данных с низкими задержками, обычно для небольших объёмов данных. Такими устройствами могут быть клавиатуры, мыши или, как в нашем случае, Stream Deck Plus. По сути, это устройства, передающие или получающие частые обновления. Наконец, out обозначает направление передачи — от (out) хоста к устройству. URB_INTERRUPT out значит, что хост (мой компьютер) отправляет данные на устройство в передаче прерыванием.

Теперь обратим внимание на то, что передаваемые пакеты однородны — все они имеют длину 1051 байт. Первый пакет содержит заголовок JPEG (начальные байты изображения), а во всех последующих содержится остальное изображение, разбитое на блоки. Заголовок всегда имеет размер 8 байтов, а содержимое (полезная нагрузка изображения) объявляется в заголовке, но обычно равна 1016 байтам, благодаря чему общая полезная нагрузка составляет 1024 байта.

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

Чтобы убедиться, что изображение задано, можно воспользоваться магией командной строки. В Wireshark выберем содержащие изображение пакеты URB_INTERRUPT out. Чтобы их было проще находить, можно применить более строгий фильтр:

usb.dst ~ "3.5" && _ws.col.info == "URB_INTERRUPT out"

Этот фильтр будет искать пакеты URB_INTERRUPT out только для конкретного destination. Как я уже говорил выше, выберем пакеты, а затем в меню File выберем Export Specified Packets….

В разделе Packet Range следующего диалогового окна нажмём на Selected packets only.

Дадим файлу осмысленное имя и сохраним куда-нибудь на диск. Затем мы используем инструмент командной строки из комплекта Wireshark под названием tshark.

В Windows tshark обычно находится в папке установки Wireshark. В моём случае он находился в C:\Program Files\Wireshark:

Для удобства пользования tshark можно добавить путь до Wireshark к системной переменной среды PATH. Если сделать это, то мы сможем вызвать выполнить в терминале следующую команду:

tshark -r .\test-image-extraction.pcapng -T fields -e usb.capdata > data.txt

Она извлекает данные HID и сохраняет их дамп в текстовый файл. Так как мы уже работаем с файлом *.pcapng, который содержит только интересующие нас пакеты изображения, нам не нужно больше заниматься фильтрацией и достаточно сохранить всё в текстовый файл.

Его содержимое будет выглядеть так:

Не особо наглядно, но мы можем заметить то, о чём я говорил выше, например, начало заголовка 02 07. В качестве быстрого «хака» для выполнения дампа данных изображения из этого текстового файла я написал скрипт PowerShell:

param (
    [string]$DataFile,
    [string]$OutputFileName
)

function Process-HIDData {
    param (
        [string]$DataFile,
        [string]$OutputFileName
    )

    $lines = Get-Content -Path $DataFile

    $imageBytes = @()

    foreach ($line in $lines) {
        $hexBytes = $line.Trim()

        if ($hexBytes.Length -gt 16) {
            $processedBytes = $hexBytes.Substring(16)
            $byteArray = for ($i = 0; $i -lt $processedBytes.Length; $i += 2) {
                [Convert]::ToByte($processedBytes.Substring($i, 2), 16)
            }
            $imageBytes += $byteArray
        }
    }

    $binaryData = [byte[]]::new($imageBytes.Length)
    [System.Array]::Copy($imageBytes, $binaryData, $imageBytes.Length)

    $scriptDirectory = $PSScriptRoot
    $outputFilePath = Join-Path -Path $scriptDirectory -ChildPath $OutputFileName

    [System.IO.File]::WriteAllBytes($outputFilePath, $binaryData)

    Write-Output "Image saved as $outputFilePath"
}

if (-not $DataFile) {
    Write-Error "Data file path is required."
    exit 1
}

if (-not $OutputFileName) {
    Write-Error "Output file name is required."
    exit 1
}

Process-HIDData -DataFile $DataFile -OutputFileName $OutputFileName

На самом деле, он просто вырезает первые 8 байтов из каждой строки (каждая строка — это блок данных HID) и сохраняет двоичное представление как файл JPEG. Запустить его можно так:

.\exportimage.ps1 -DataFile .\data.txt -OutputFile image.jpg

После выполнения скрипта мы увидим моё тестовое изображение с ёжиком:

Отлично! Теперь мы имеем представление о том, как изображения передаются по проводу. Но ещё одна особенность кнопок Stream Deck заключается в том, что, как и любые другие кнопки, их можно нажимать. Я уже говорил об этом в предыдущем посте; если вкратце, то мы должны смотреть на обратное тому, что мы делали с изображениями.

То есть, строка фильтра теперь должна выглядеть так (не забудьте изменить аргумент src):

_ws.col.info == "URB_INTERRUPT in" && usb.src == 3.5.1

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

Первые четыре байта — это заголовок, который мы можем игнорировать. Третий байт всегда обозначает количество кнопок на панели, то есть 8 в случае Stream Deck Plus. Для Stream Deck XL это значение равно 32. Также третий байт означает, какое количество байтов после заголовка содержит схему кнопок. То есть если мы нажмём на четвёртую кнопку Stream Deck Plus, то на компьютер будут переданы следующие данные:

0000  01 00 08 00 00 00 00 01 00 00 00 00 00 00 00 00  ................ 
0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0070  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0080  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0090  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
00F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0100  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0110  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0120  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0130  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0140  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0150  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0160  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0170  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0180  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
0190  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
01F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 

Это ещё одна часть инфраструктуры оборудования, которая не меняется для разных моделей устройств, за что я очень благодарен Elgato.

▍ Экран

Теперь давайте поговорим о втором компоненте Stream Deck Plus: об экране. Это узкая полоса, на которой можно отображать различную информацию. По умолчанию она используется для отображения информации находящихся под ней ручек. Из этого мы можем предположить, что на этом экране есть четыре отдельные части, связанные с каждой ручкой, но это предположение будет верным только отчасти.

На практике, вся площадь экрана — это просто одно большое изображение. Условно большое — его размер 800×100. Я обнаружил это, выбрав для экрана фон, а затем выполнив описанный выше «хак» с PowerShell (но со смещением заголовка в 16 байтов вместо 8), чтобы исследовать трафик с моего компьютера к Stream Deck Plus. Я увидел следующее:

ПО Stream Deck создаёт составное изображение всего того, что пользователь связал с ручками, а затем передаёт всё это на устройство за раз в одном блобе. Если изучить исходящий трафик от хоста к устройству, мы увидим подобные пакеты:

0000  02 0C 00 00 00 00 20 03 64 00 00 00 00 F0 03 00  ...... .d....ð.. 
0010  FF D8 FF E0 00 10 4A 46 49 46 00 01 01 00 00 01  ÿØÿà..JFIF...... 
0020  00 01 00 00 FF DB 00 43 00 03 02 02 03 02 02 03  ....ÿÛ.C........ 
0030  03 03 03 04 03 03 04 05 08 05 05 04 04 05 0A 07  ................ 
0040  07 06 08 0C 0A 0C 0C 0B 0A 0B 0B 0D 0E 12 10 0D  ................ 
0050  0E 11 0E 0B 0B 10 16 10 11 13 14 15 15 15 0C 0F  ................ 
0060  17 18 16 14 18 12 14 15 14 FF DB 00 43 01 03 04  .........ÿÛ.C... 
0070  04 05 04 05 09 05 05 09 14 0D 0B 0D 14 14 14 14  ................ 

Теперь у нас есть 16-байтный заголовок, имеющий следующую структуру (судя по начальному пакету, который использовался для отправки изображения):

+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| Байт     |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| Значение | 02 | 0C | 00 | 00 | 00 | 00 | 20 | 03 | 64 | 00 | 00 | 00 | 00 | F0 | 03 | 00 |
+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+

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

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

Такими оверлеями, как и всем остальным, управляет ПО Stream Deck. Однако любопытно в них то, что они отправляются как сегмент. ПО отправляет не полное составное изображение, а только одну часть экрана.

Может ли быть так, что каждый сегмент экрана адресуем? Я начал сравнивать заголовки наборов оверлеев. В данных ниже показаны заголовки как отдельные байты, за которыми следует краткий фрагмент полезной нагрузки изображения (поверьте, вы не захотели бы изучать всё это целиком). Чтобы упростить анализ, я разделил экран на четыре сегмента слева направо — A, B, C и D.

▍ Сегмент A

02 0c 00 00 00 00 c8 00 64 00 00 00 00 f0 03 00 ffd8ffe000104a46
02 0c 00 00 00 00 c8 00 64 00 00 01 00 f0 03 00 62719049eff74526
02 0c 00 00 00 00 c8 00 64 00 00 02 00 f0 03 00 6b8844808f976955
02 0c 00 00 00 00 c8 00 64 00 00 03 00 f0 03 00 e7d81a2c2bbb151b
02 0c 00 00 00 00 c8 00 64 00 00 04 00 f0 03 00 0f7c678f7a666ddf
02 0c 00 00 00 00 c8 00 64 00 00 05 00 f0 03 00 434b7255d6e66e9d
02 0c 00 00 00 00 c8 00 64 00 00 06 00 f0 03 00 fc54da1adeecad78
02 0c 00 00 00 00 c8 00 64 00 00 07 00 f0 03 00 7e4095f72f5c6bc2
02 0c 00 00 00 00 c8 00 64 00 00 08 00 f0 03 00 918ba9de8b9d4edf
02 0c 00 00 00 00 c8 00 64 00 00 09 00 f0 03 00 12ebd3dd2116a218
02 0c 00 00 00 00 c8 00 64 00 01 0a 00 0a 00 00 d38bb9152295be67

▍ Сегмент B

02 0c c8 00 00 00 c8 00 64 00 00 00 00 f0 03 00 ffd8ffe000104a46
02 0c c8 00 00 00 c8 00 64 00 00 01 00 f0 03 00 7662eade285d4963
02 0c c8 00 00 00 c8 00 64 00 00 02 00 f0 03 00 23241008207b8c96
02 0c c8 00 00 00 c8 00 64 00 00 03 00 f0 03 00 920734728fdaf35d
02 0c c8 00 00 00 c8 00 64 00 00 04 00 f0 03 00 f41d3afd723f98ed
02 0c c8 00 00 00 c8 00 64 00 00 05 00 f0 03 00 4b14e7701b82b291
02 0c c8 00 00 00 c8 00 64 00 00 06 00 f0 03 00 78f61540d6b165b6
02 0c c8 00 00 00 c8 00 64 00 00 07 00 f0 03 00 481bb70eb8fc7fcf
02 0c c8 00 00 00 c8 00 64 00 01 08 00 05 02 00 fce4dbc726e6ea09

▍ Сегмент C

02 0c 90 01 00 00 c8 00 64 00 00 00 00 f0 03 00 ffd8ffe000104a46
02 0c 90 01 00 00 c8 00 64 00 00 01 00 f0 03 00 1260fa52b10e4d00
02 0c 90 01 00 00 c8 00 64 00 00 02 00 f0 03 00 e52b2649911c1ce1
02 0c 90 01 00 00 c8 00 64 00 00 03 00 f0 03 00 8cadbf5d1a6bf53d
02 0c 90 01 00 00 c8 00 64 00 00 04 00 f0 03 00 51e403cc601c8127
02 0c 90 01 00 00 c8 00 64 00 00 05 00 f0 03 00 bfd26ffc7fa25e69
02 0c 90 01 00 00 c8 00 64 00 00 06 00 f0 03 00 91d352f3fe933f3d
02 0c 90 01 00 00 c8 00 64 00 00 07 00 f0 03 00 e90ffb69fc22540d
02 0c 90 01 00 00 c8 00 64 00 01 08 00 13 01 00 9f434156b8d8df76

▍ Сегмент D

02 0c 58 02 00 00 c8 00 64 00 00 00 00 f0 03 00 ffd8ffe000104a46
02 0c 58 02 00 00 c8 00 64 00 00 01 00 f0 03 00 9e49ea2ad547ccd3
02 0c 58 02 00 00 c8 00 64 00 00 02 00 f0 03 00 33d453a105caa44e
02 0c 58 02 00 00 c8 00 64 00 00 03 00 f0 03 00 2d7d0e89d08caad3
02 0c 58 02 00 00 c8 00 64 00 00 04 00 f0 03 00 d7b45dcc67503a1e
02 0c 58 02 00 00 c8 00 64 00 00 05 00 f0 03 00 9e0ed72437f7b6f6
02 0c 58 02 00 00 c8 00 64 00 00 06 00 f0 03 00 b8b9d1aea3d7a351
02 0c 58 02 00 00 c8 00 64 00 01 07 00 a4 00 00 4e735a459338a458

▍ Ищем дельту

Среди перечисленных выше пакетов в заголовке менялись только третий и четвёртый байты. Я решил, что это адреса экранных сегментов. У нас есть:

Если преобразовать значения в десятичный вид, то таблица внезапно станет гораздо понятнее:

Потрясающе. Третий и четвёртый байт в заголовке обозначает смещение в пикселях (как я говорил выше, полное изображение имеет размер 800×100). Теперь давайте сравним все эти пакеты с тем, что мы видим, когда задаём полное изображение:

02 0c 00 00 00 00 20 03 64 00 00 00 00 f0 03 00 ffd8ffe000104a46
02 0c 00 00 00 00 20 03 64 00 00 01 00 f0 03 00 89b062cee0cd8e84
02 0c 00 00 00 00 20 03 64 00 00 02 00 f0 03 00 5805c9c63771d327
02 0c 00 00 00 00 20 03 64 00 00 03 00 f0 03 00 3dab5a71737721b3
02 0c 00 00 00 00 20 03 64 00 00 04 00 f0 03 00 618246734b6342fe
02 0c 00 00 00 00 20 03 64 00 00 05 00 f0 03 00 aa159464a0cce71d
02 0c 00 00 00 00 20 03 64 00 00 06 00 f0 03 00 8996e51482344335
02 0c 00 00 00 00 20 03 64 00 00 07 00 f0 03 00 45ae683e24bbff00
02 0c 00 00 00 00 20 03 64 00 00 08 00 f0 03 00 8bc53378a7c07e1c
02 0c 00 00 00 00 20 03 64 00 00 09 00 f0 03 00 ff005ff807e3af0b
02 0c 00 00 00 00 20 03 64 00 00 0a 00 f0 03 00 b299080709c9c02a
02 0c 00 00 00 00 20 03 64 00 00 0b 00 f0 03 00 4fb45746ef817c56
02 0c 00 00 00 00 20 03 64 00 00 0c 00 f0 03 00 c62390ac84897272
02 0c 00 00 00 00 20 03 64 00 00 0d 00 f0 03 00 27030d8e36a8e001
02 0c 00 00 00 00 20 03 64 00 00 0e 00 f0 03 00 d95ab7fa562dd956
02 0c 00 00 00 00 20 03 64 00 00 0f 00 f0 03 00 ba2eaf650de69fa4
02 0c 00 00 00 00 20 03 64 00 00 10 00 f0 03 00 efe19c9f0f3c1da1
02 0c 00 00 00 00 20 03 64 00 00 11 00 f0 03 00 7e140462b850800c
02 0c 00 00 00 00 20 03 64 00 00 12 00 f0 03 00 ec37b1e8da7b416d
02 0c 00 00 00 00 20 03 64 00 00 13 00 f0 03 00 ee1636963dec088e
02 0c 00 00 00 00 20 03 64 00 00 14 00 f0 03 00 3f06e9f2c02596f4
02 0c 00 00 00 00 20 03 64 00 00 15 00 f0 03 00 49a0d8d94b7b55d3
02 0c 00 00 00 00 20 03 64 00 00 16 00 f0 03 00 8a2ea63df238c374
02 0c 00 00 00 00 20 03 64 00 00 17 00 f0 03 00 f4b8d34433bc65c4
02 0c 00 00 00 00 20 03 64 00 00 18 00 f0 03 00 2033824b02a3712a
02 0c 00 00 00 00 20 03 64 00 00 19 00 f0 03 00 1c8ee4f526bf4da7
02 0c 00 00 00 00 20 03 64 00 00 1a 00 f0 03 00 e3da788745f19f88
02 0c 00 00 00 00 20 03 64 00 00 1b 00 f0 03 00 2755734755b7dc43
02 0c 00 00 00 00 20 03 64 00 00 1c 00 f0 03 00 e0cad297dd8f5c35
02 0c 00 00 00 00 20 03 64 00 00 1d 00 f0 03 00 c00217a1cfd8f259
02 0c 00 00 00 00 20 03 64 00 00 1e 00 f0 03 00 c1cfc8ec33f91ac7
02 0c 00 00 00 00 20 03 64 00 00 1f 00 f0 03 00 b6f30aecddb72492
02 0c 00 00 00 00 20 03 64 00 00 20 00 f0 03 00 ff00b3fb552c8b08
02 0c 00 00 00 00 20 03 64 00 00 21 00 f0 03 00 baf3fc47d99f25fe
02 0c 00 00 00 00 20 03 64 00 00 22 00 f0 03 00 c6adc4510f3644f3
02 0c 00 00 00 00 20 03 64 00 00 23 00 f0 03 00 dcb5a79842477124
02 0c 00 00 00 00 20 03 64 00 00 24 00 f0 03 00 73950000a48af069
02 0c 00 00 00 00 20 03 64 00 00 25 00 f0 03 00 032c919120c6eca0
02 0c 00 00 00 00 20 03 64 00 00 26 00 f0 03 00 63f0d3e1a787127d
02 0c 00 00 00 00 20 03 64 00 00 27 00 f0 03 00 6efb25e5add3b7a9
02 0c 00 00 00 00 20 03 64 00 00 28 00 f0 03 00 7874fe1883c53e1d
02 0c 00 00 00 00 20 03 64 00 00 29 00 f0 03 00 20d4632b5ceda74e
02 0c 00 00 00 00 20 03 64 00 01 2a 00 92 02 00 bf32e9c5367927c4

Седьмой и восьмой байты внезапно оказываются 20 03, потому что мы снова должны смотреть значения в представлении Little Endian. Для каждого сегмента это значение было равно C8 00, то есть 200 в десятичном виде. 20 03 — это 800, то есть ширина изображения. 64 00 — это 100, то есть высота изображения.

Моя таблица предположений теперь становится гораздо логичнее:

Вот и всё, теперь мы знаем, как задаются данные экрана! Всё оказалось не так сложно, когда я начал изучать разницу между пакетами.

Последнее, что нам нужно рассмотреть: экран является

сенсорным, так что мы должны уметь распознавать нажатия на сегменты. Нажатие на любую часть экрана — это функциональный эквивалент нажатия на ручку — при использовании ПО Stream Deck будет отображаться тот же оверлей. Но как это отражается в Wireshark?

Чтобы проверить это, давайте снова зададим фильтр, потому что нам нужно отслеживать события, происходящие в устройстве и передаваемые на PC:

usb.src ~ "3.5" && _ws.col.info == "URB_INTERRUPT in"

Касаясь экрана слева направо, мы получаем следующие данные:

01 02 0e 00 01 01 47 00 40 00 00000000000000000
01 02 0e 00 01 01 07 01 1c 00 00000000000000000
01 02 0e 00 01 01 ee 01 32 00 00000000000000000
01 02 0e 00 01 01 b3 02 29 00 00000000000000000

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

01 02 0e 00 01 01 b2 02 33 00 00000000000000000
01 02 0e 00 01 01 13 03 20 00 00000000000000000
01 02 0e 00 01 01 a9 02 46 00 00000000000000000
01 02 0e 00 01 01 06 03 26 00 00000000000000000
01 02 0e 00 01 01 bb 02 20 00 00000000000000000
01 02 0e 00 01 01 00 03 52 00 00000000000000000
01 02 0e 00 01 01 b6 02 3e 00 00000000000000000
01 02 0e 00 01 01 f7 02 2f 00 00000000000000000
01 02 0e 00 01 01 f1 02 1c 00 00000000000000000
01 02 0e 00 01 01 8d 02 1c 00 00000000000000000

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

+----------+----+----+----+----+----+----+----+-----+----+-----+
| Байт     |  0 |  1 |  2 |  3 |  4 |  5 |   6 -  7 |   8 -  9 |
+----------+----+----+----+----+----+----+----+-----+----+-----+
| Значение | 01 | 02 | 0E | 00 | 01 | 01 | Коорд. X | Коорд. Y |
+----------+----+----+----+----+----+----+----+-----+----+-----+

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

▍ Ручки

Также нам следует поговорить о ручках. Каждую ручку можно использовать тремя способами:

  1. Поворачивать вправо.
  2. Поворачивать влево.
  3. Нажимать.

Чтобы в логах всё фиксировалось правильно, я пометил каждую ручку аналогично экранным сегментам и сделал четыре поворота вправо, потом четыре поворота влево и нажимал на ручку. Ниже представлены полученные данные.

▍ Ручка A

▍ Повороты вправо

01 03 05 00 01 01 00 00 00 0000000000
01 03 05 00 01 01 00 00 00 0000000000
01 03 05 00 01 01 00 00 00 0000000000
01 03 05 00 01 01 00 00 00 0000000000

▍ Повороты влево

01 03 05 00 01 ff 00 00 00 0000000000
01 03 05 00 01 ff 00 00 00 0000000000
01 03 05 00 01 ff 00 00 00 0000000000
01 03 05 00 01 ff 00 00 00 0000000000

▍ Нажатие

01 03 05 00 00 01 00 00 00 0000000000
01 03 05 00 00 00 00 00 00 0000000000

▍ Ручка B

▍ Повороты вправо

01 03 05 00 01 00 01 00 00 0000000000
01 03 05 00 01 00 01 00 00 0000000000
01 03 05 00 01 00 01 00 00 0000000000
01 03 05 00 01 00 01 00 00 0000000000

▍ Повороты влево

01 03 05 00 01 00 ff 00 00 0000000000
01 03 05 00 01 00 ff 00 00 0000000000
01 03 05 00 01 00 ff 00 00 0000000000
01 03 05 00 01 00 ff 00 00 0000000000

▍ Нажатие

01 03 05 00 00 00 01 00 00 0000000000
01 03 05 00 00 00 00 00 00 0000000000

▍ Ручка C

▍ Повороты вправо

01 03 05 00 01 00 00 01 00 0000000000
01 03 05 00 01 00 00 01 00 0000000000
01 03 05 00 01 00 00 01 00 0000000000
01 03 05 00 01 00 00 01 00 0000000000

▍ Повороты влево

01 03 05 00 01 00 00 ff 00 0000000000
01 03 05 00 01 00 00 ff 00 0000000000
01 03 05 00 01 00 00 ff 00 0000000000
01 03 05 00 01 00 00 ff 00 0000000000

▍ Нажатие

01 03 05 00 00 00 00 01 00 0000000000
01 03 05 00 00 00 00 00 00 0000000000

▍ Ручка D

▍ Повороты вправо

01 03 05 00 01 00 00 00 01 0000000000
01 03 05 00 01 00 00 00 01 0000000000
01 03 05 00 01 00 00 00 01 0000000000
01 03 05 00 01 00 00 00 01 0000000000

▍ Повороты влево

01 03 05 00 01 00 00 00 ff 0000000000
01 03 05 00 01 00 00 00 ff 0000000000
01 03 05 00 01 00 00 00 ff 0000000000
01 03 05 00 01 00 00 00 ff 0000000000

▍ Нажатие

01 03 05 00 00 00 00 00 01 0000000000
01 03 05 00 00 00 00 00 00 0000000000

▍ Анализируем данные

Изучая описанные выше сигналы, мы достаточно быстро можем выявить общие особенности, потому что одни и те же значения продолжают сдвигаться вправо.

По сути, это паттерн нажатия на кнопки, который мы видели при нажатии на кнопки!

+----------+----+----+----+----+---------+------------------+------------------+------------------+------------------+
| Байт     |  0 |  1 |  2 |  3 |       4 |                5 |                6 |                7 |                8 |
+----------+----+----+----+----+---------+------------------+------------------+------------------+------------------+
| Значение | 01 | 03 | 05 | 00 | Поворот | Действие ручки A | Действие ручки B | Действие ручки C | Действие ручки D |
+----------+----+----+----+----+---------+------------------+------------------+------------------+------------------+

Для каждой ручки мы получаем следующую комбинацию:

  1. Байт 4 получает значение 01 (поворот), относящиеся к кнопке байты получают значения 01 (поворот вправо) или FF (поворот влево).
  2. Байт 4 получает значение 00 (нажатие), относящиеся к кнопке байты получают значения 01 (нажатие) или 00 (отпускание).

Очень здорово: если вы прочитали всю статью, то теперь знаете, как задаются двоичные данные для каждого элемента управления Stream Deck Plus.

Пишем обёртку

Итак, разобравшись с рутиной анализа двоичных данных, можно сделать так, чтобы работать со всем этим было удобнее. Для этого я обновил DeckSurf SDK, добавив в него поддержку Stream Deck Plus.

Последний релиз DeckSurf SDK на NuGet (0.0.4) вы уже можете использовать для управления устройством Stream Deck Plus!

Вот полнофункциональный образец кода на C#, показывающий, как обрабатывать события и устанавливать изображения на Stream Deck Plus:

using DeckSurf.SDK.Core;
using DeckSurf.SDK.Models;
using DeckSurf.SDK.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace DeckSurf.SDK.StartBoard
{
    class Program
    {
        static void Main(string[] args)
        {
            var exitSignal = new ManualResetEvent(false);
            var devices = DeviceManager.GetDeviceList();

            Console.WriteLine("The following Stream Deck devices are connected:");

            foreach (var connectedDevice in devices)
            {
                Console.WriteLine(connectedDevice.Name);
            }

            var device = ((List<ConnectedDevice>)devices)[0];
            device.StartListening();
            device.OnButtonPress += Device_OnButtonPress;

            byte[] testImage = File.ReadAllBytes(args[0]);

            var image = ImageHelpers.ResizeImage(testImage, device.ScreenWidth, device.ScreenHeight, device.IsButtonImageFlipRequired);

            device.SetScreen(image, 250, device.ScreenWidth, device.ScreenHeight);

            var keyImage = ImageHelpers.ResizeImage(testImage, device.ButtonResolution, device.ButtonResolution, device.IsButtonImageFlipRequired);
            device.SetKey(1, keyImage);

            device.SetBrightness(29);

            Console.WriteLine("Done");
            exitSignal.WaitOne();
        }

        private static void Device_OnButtonPress(object source, ButtonPressEventArgs e)
        {
            Console.WriteLine($"Button with ID {e.Id} was pressed. It's identified as {e.ButtonKind}. Event is {e.EventKind}. If this is a touch screen, coordinates are {e.TapCoordinates.X} and {e.TapCoordinates.Y}. Is knob rotated: {e.IsKnobRotating}. Rotation direction: {e.KnobRotationDirection}.");
        }
    }
}

В этом примере предполагается, что устройство Stream Deck Plus подключено первым (индекс 0), поэтому, возможно, в код придётся внести изменения, если к компьютеру подключено несколько Stream Deck. Тем не менее, этот пример показывает, насколько просто выполнять взаимодействия с Stream Deck при помощи DeckSurf SDK. Это ещё очень ранняя версия, поэтому в процессе движения к стабильной версии в будущем что-то может ломаться, но пока можете экспериментировать!

Самая актуальная документация доступна на https://docs.deck.surf.

Telegram-канал со скидками, розыгрышами призов и новостями IT 💻

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Группировка значков на рабочем столе windows 10
  • Поиск дубликатов изображений windows
  • Как открыть файл jpg на компьютере windows 10
  • Как добавить сетевой маршрут в windows
  • Mhdd portable для windows