Девайсы
Софт
Статьи
Контакты

 


Изучение протокола обмена данными в диагностическом ПО с помощью ILdasm

В статье описывается случай изучения протокола передачи данных по IL-коду диагностического ПО, написанного под .NET Framework. Производитель оборудования и ПО здесь указываться не будет, как и не будет раскрыто каких-либо секретов. Усложнить чтение IL-кода производитель мог, но это не было сделано. Знание протокола дает возможность создания своего ПО с нужным функционалом, а также создать приложение для смартфона, поскольку подключение к оборудованию происходит по Bluetooth.


Рисунок 1 - Связь хоста и диагностиуемой системы

Оборудование (система накопления электроэнергии из 160 ячеек типа LiFeYPO4) имеет в своем составе блок, который формирует пакеты данных с информацией о напряжении и температуре всех ячеек и отправляет их с периодом около 3 секунд на верхний уровень по RS-485 и параллельно по Bluetooth на хост с диагностическим ПО. Задача автора состоит в определении алгоритма кодирования этих пакетов. Для получения и сохранения передаваемых данных использован терминал HTerm, подключенный к оборудованию вместо диагностической программы. Подключение производится как к виртуальному COM-порту, который был присвоен диагностируемому устройству при сопряжении по Bluetooth. После подключения к системе, она по-умолчанию находится в режиме периодической трансляции пакетов данных и не требует каких-либо запросов от хоста, поэтому данные остается только принять.

Пакет данных, полученный в HTerm
Рисунок 2 - Один из пакетов данных (1280 байт), получаемый от диагностируемой системы каждые 3 секунды

В данном случае достаточно одного пакета данных, поэтому, получив пакет данных (рис. 2), не дожидаемся поступления следующего через 3 секунды, а отключаемся от порта и сохраняем полученные данные файл (в HTerm формат "RAW"). В полученных данных наблюдается повторение определенной последовательности каждые 8 байт. Поэтому для удобства, в HTerm установлен перенос строки через каждые 8 байт (Newline every...characters). После разбиения, число таких строк получилось равным числу ячеек (160), что может указывать на то, что одна строка содержит информацию об одной ячейке.

Вид данных в HTerm с переносом строк
Рисунок 3 - Вид данных с переносом строк через каждые 8 байт

Чтобы понять, как должна выглядеть отображаемая информация из сохраненного пакета данных, передадим его с помощью HTerm диагностической программе, как данные от оборудования. Для связи двух программ между собой по COM-портам, использован драйвер com0com, с помощью которого создана связка из двух виртуальных COM-портов. К одному порту (COM101) подключается HTerm, а ко второму (COM100) диагностическая программа. Из терминала отправляем ранее сохраненный файл (кнопка Send File), результат на рисунке 4.

Вид окна диагностической программы
Рисунок 4 - Информация, отображаемая в диагностическом ПО после получения пакета данных

Соответствие отображаемой информации и принимаемых данных
Рисунок 5 - Выборка из 3 строк соответствия отображаемой информации и принимаемых данных

Далее можно приступить к поиску алгоритма кодирования в коде программы. Исходный код автору недоступен, но, ПО написано на базе .NET Framework, что позволяет получить код программы уже не на ассемблере, а на более высокоуровневом языке IL (Intermediate language), что упрощает изучение алгоритма. Для дизассемблирования используется утилита ILdasm. Ниже представлено дерево объектов, полученное после загрузки сборки в ILdasm.

Дерево объектов в ILdasm
Рисунок 6 - Дерево объектов в ILdasm

Поскольку разработчики специально не занимались запутыванием, имена (объектов, методов, переменных и т.д.) сохранились в исходном виде, что значительно упрощает задачу. После непродолжительного анализа полученного кода, найдены искомые участки. Один массив байтов uint8 PacketData[] должен содержать одну строку полученных байтов с информацией о ячейках.

Поиск алгоритма кодирования
Рисунок 7 - Отдельные байты из PacketData[] по таймеру передаются в функцию send_data_from_bat()

В обработчике события таймера (судя по дефолтному названию функции) timerData_Tick() на участке с IL_0175 по IL_018c загружаются в стек байты 3, 4, 5 из PacketData[] и передаются в send_data_from_bat(). Названия аргументов последней функции также дают подсказку: NbCMM, ValUBat, ValTmpBat. Далее начат проект на C# с пробными пакетами и переменными, именованными в соответствии IL-кодом.

Поиск алгоритма кодирования
Рисунок 8 - Начало восстановления алгоритма на С# по коду IL

В функции send_data_from_bat() искомый алгоритм содежится между шаблоном строки (IL_003a) и подстановкой в него обработанных данных (IL_0097). На рисунке ниже приведен разбор кода с пояснениями. Для понимания данного кода рекомендую источники [1] и [2].

Разбор кода IL
Рисунок 9 - Разбор кода IL

На рисунке ниже представлен получившийся код на C# и результат обработки им пробного пакета в переменных r4v, i2t (окно Watch).

Результат разбора на C#
Рисунок 10 - Алгоритм на C#, восстановленный по коду на IL (в окне Watch результат декодирования пробного пакета)

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

Разбор кода IL
Рисунок 11 - Алгоритм поверки целостности

Источники информации:

  1. CLR via C#. Джеффри Рихтер
  2. ECMA-335 - Common Language Infrastructure (CLI)



Комментарии




Добавление комментария
Имя:
E-mail:
Сообщение: