26 апреля 2018 года компания ИНФОРИОН провела конференцию для студентов МГТУ им. Баумана SMARTRHINO-2018. Специально для конференции было подготовлено небольшое устройство на базе микроконтроллера STM32F042.
Этот носорожек стал подопытным главным героем мастер-класса по реверсу прошивки. К сожалению, за время, отведенное на мастер-класс, не представлялось возможным провести полное исследование прошивки, поэтому мы решили восполнить это подробным разбором в формате статьи. Надеемся, информация будет полезна не только участникам конференции, но также всем начинающим кодокопателям.
Первая часть статьи составлена по мотивам проведённого мастер-класса и рассчитана на начинающих — уделяется внимание базовым подходам к реверсу прошивок и особенностям работы с дизассемблером IDA. Вторая часть немного сложнее, в ней уделяется внимание особенностям работы устройств на базе операционных систем реального времени.
Осторожно, под катом мигающий носорог и его прошивка!
Легенда
Участникам семинара была предложена следующая легенда.
Вам досталось устройство и небольшая инструкция к нему.
Прибор осветительный «Носорог»
Инструкция по эксплуатации
Прибор осветительный «Носорог» предназначен для освещения помещений небольшой площади. Прибор совмещает в себе стильный компактный дизайн, яркие светодиоды с низким потреблением тока и USB-интерфейс для подключения питания.
Устройство оснащено Bluetooth-модулем для удаленного управления. Предоставляются широкие возможности для контроля освещенности, позволяющие задавать оттенок и насыщенность для каждого светодиода в отдельности.
Управление устройством осуществляется через специальное программное обеспечение «Синезубик».
Приятного использования!
Упомянутого программного обеспечения для управления устройством у вас нет и необходимо написать его с нуля. Помимо этого необходимо удостовериться в безопасности использования данного устройства.
То есть всё, что есть у исследователя — устройство, которое можно включить. Если есть устройство, то можно попытаться получить его прошивку, вычитав её из flash-накопителя микроконтроллера. Этот этап был пропущен для упрощения и ускорения мастер-класса — участники получили готовый образ прошивки в виде бинарного файла rhino_fw42k6.bin (как если бы они получили прошивку, например, из обновлений).
Заинтересованный читатель также может скачать прошивку для самостоятельного исследования.
Мастер-класс проходил в интерактивном режиме – с возможностью спрашивать, предлагать свои пути решения. Для участников было доступно 4 рабочих «Носорога».
Внешний осмотр
Кратко: на этом этапе производится внешний осмотр устройства с целью поиска маркировок, доступных разъемов.
В начале семинара был сделан акцент на то, чтобы сначала внешне изучить устройство, потом уже приступать к реверсу прошивки.
В первую очередь, интересует микроконтроллер, потом периферийные устройства и разъёмы.
Внешний осмотр устройства позволил установить следующее:
- Микроконтроллер STM32F042 – тут сразу стоит обратиться к документации на микроконтроллер (если такая есть), откуда можно узнать архитектуру, разрядность микроконтроллера и много чего полезного (для нашего случая – 32 разрядный микроконтроллер на архитектуре ARM);
- На тыльной стороне имеется разъем без обозначений – те, кто работал с микроконтроллерами, могут сделать верное предположение, что это разъем для прошивки устройства (во-первых, он не промаркирован; во-вторых, он имеет 5 контактов, что соответствует необходимому количеству контактов для перешивки микроконтроллера);
- Контакты GND, TX;
- USB-разъем для питания устройства (об этом говорится и в «Инструкции»);
- Неизвестный разъем XP2 на лицевой стороне устройства;
- Непонятная желтая блямба на ноге носорога – вероятно, сенсорная кнопка.
Самые шустрые участники сразу же подключили питание устройствам и увидели следующее:
Также было обнаружено, что появились доступные Bluetooth-устройства c именами RHINOCEROS-220x, при подключении к которым в системе создаётся виртуальный COM-порт. Оказалось удобным подключаться к устройству по Bluetooth со смартфона и взаимодействовать через мобильное приложение «Serial Bluetooth Terminal» или аналогичное.
Было установлено, что при отправке в COM-порт произвольного текста устройство возвращает ответ Unknown command
.
Начальное исследование прошивки
Кратко: на этом этапе выполняется предварительный анализ прошивки. Просмотр строк. Загрузка прошивки в IDA Pro.
Перед разбором кода прошивки имеет смысл проверить, не упакован ли код. Тут могут быть разные подходы, в простом случае достаточно воспользоваться утилитой strings, чтобы получить строки бинарного файла (приводятся в сокращении):
../Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_cortex.c
../Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_dma.c
…
Hardware init done... Starting FreeRTOS
sendMsg error %s
TSC %d
SET AUTH %d
cmd[%d] %s
UART task
Bluetooth task
AT+AB ShowConnection
…
AT-AB -BypassMode-
state bypass
ERROR: Wrong header length
cmd: %s
led idx %d hue %d sat %d val %d
msg %s
addr=%x, size=%x
User auth pass %s
Congrats amigo!
Wrong won't give up!
ERROR: Unk cmd
I've got a super power and now I'm seeing invisible tactical combatant nano-ants everywhere
…
uartRxTask
watchdogTask
sensorTask
bluetoothTask
ledsTask
Строк нашлось много – можно сделать предположение, что прошивка не сжата и не зашифрована. Уже на этом этапе можно обратить внимание на некоторые примечательные строки, например, форматные строки, строки с описанием ошибок и указанием операционной системы (а вы их увидели?). Наличие осмысленных строк, по большому счёту, можно считать половиной успешного реверса.
Что ж, попробуем загрузить прошивку в самый популярный дизассемблер. Будем использовать IDA версии 6.9 для 32-битного кода (так как микроконтроллер 32-разрядный).
При открытии файла прошивки IDA не может автоматически определить архитектуру и точку входа – необходимо ей помочь.
На этом этапе необходимо снова обратиться к документации на микроконтроллер STM32F042x4 STM32F042x6 и посмотреть раздел 5 «Memory mapping»:
В качестве Processor Type выбираем ARM Little endian, ставим галку Manual load, нажимаем OK:
В окне «Do you want to change the processor type» нажимаем Yes, после этого IDA предлагает нам создать сегменты ОЗУ (RAM) и ПЗУ (ROM), ставим галку ROM.
Теперь мы должны указать адрес начала ROM. На схеме нужно смотреть секцию Flash – это адреса 0x08000000 – 0x08008000. Также укажем, что именно в этот же адрес мы хотим загрузить файл прошивки: Loading address = 0x08000000.
В окне "ARM and Thumb mode switching instructions" нажимаем OK.
Далее IDA говорит, что ничего не знает о произвольных двоичных файлах и точку входа – функцию main — вы должны определить самостоятельно. Нажимаем OK.
Загрузка произведена. Можно изучать прошивку.
Откроем окно строк (Shift + F12). Можно обратить внимание на то, что не все строки совпадают с результатами из утилиты strings – IDA распознала не всё, к сожалению. Немного погодя мы ей поможем…
Примечание для начинающих
- Любая программа/прошивка представляет собой набор двоичных данных. IDA Pro может по-разному интерпретировать эти данные исходного файла (представлять данные в виде команд или данных в том или ином формате). При этом тут нет кнопки «Назад» (Ctrl+Z), чтобы отменить выбранное отображение — нужно знать, как переключаться между разными режимами отображения. (Шпаргалка по горячим клавишам IDA Pro)
- Реверс-инженер из кажущегося хаоса двоичных данных восстанавливает логику, структуру и читаемость.
- Строки – важная информация при реверсе! Так как, по сути, среди всего набора двоичных данных являются наиболее просто и быстро воспринимаются человеком. Строки позволяют делать выводы о назначении функций, переменных и блоков кода.
- Именуй просмотренные функции! По умолчанию, IDA даёт функциям имена по их стартовым адресам. При анализе держать в голове эти адреса весьма сложно, гораздо проще пользоваться осмысленными именами. Для того, чтобы поименовать функцию достаточно хотя бы её беглого анализа – это уже будет важным подспорьем для дальнейшего анализа.
- Именуй распознанные переменные! Для того чтобы эффективнее проводить анализ блоков кода и функций, имеет смысл именовать переменные, которые распознала IDA, в соответствии с их назначением (всё, как в лучших практиках программирования).
- Оставляй комментарии, чтобы не забыть важное. По аналогии с программированием, комментарии при реверсе позволяют дополнительно пояснять логику работы программы или отдельных её участков.
- По возможности создавай структуры! IDA в своём арсенале имеет средство работы со структурами, имеет смысл освоить это средство и применять его при необходимости. При наличии структур исследуемый код станет еще проще для восприятия.
Анализ строк
Кратко: Анализ строк может помочь составить примерный план исследования двоичного файла.
Итак, строки.
Hardware init done... Starting FreeRTOS
sendMsg error %s
…
cmd[%d] %s
rsp[%d] %s
UART task
Bluetooth task
…
AT+AB SPPDisconnect
AT+AB DefaultLocalName RHINOCEROS-2205
…
Лишь только на основании строк уже можно получить много информации:
- Операционная система – FreeRTOS;
- Наличие форматных строк – скорее всего используются printf-подобные функции, можно будет установить назначение регистров/переменных;
- Названия задач (тасков) – можно предположить назначение этих самых тасков и связанных с ними функций;
- Использование AT-команд – предположительно так строится взаимодействие микроконтроллера и Bluetooth-модуля.
Далеко не всегда всё так радужно при анализе прошивок – строк и debug-информации может не быть совсем или они малоинформативны, но при создании прошивки мы намеренно не стали усложнять процесс обратной разработки.
Идентификация стандартных функций
Кратко: на данном этапе необходимо удостовериться, что строки действительно распознались, после чего предстоит идентифицировать некоторые стандартные функции языка C.
После загрузки прошивки и автоматического анализа IDA распознала тела функций (не всех, кстати), но среди имён функций нет ни одного «нормального» (только автоматические имена от IDA), что может быть небольшой сложностью в сравнении с реверсом ELF- или PE-файла.
Таким образом, в ходе исследования нужно определить назначение не только специфических функций конкретной прошивки, но и идентифицировать стандартные C-функции. Может возникнуть разумный вопрос — где гарантия, что такие функции есть в прошивке и что они стандартные? Здесь стоит сказать, что обычно при создании программного обеспечения (в том числе прошивок), в 9 случаях из 10 не заморачиваются созданием своей уникальной libc-библиотеки, а пользуются тем, что уже написано и проверено временем. Именно поэтому в 90% случаев можно выдвигать предположение о наличии стандартных С-функций.
Поскольку Hex-Rays Decompiler умеет превращать ARM-ассемблер в С-код, воспользуемся этой приятной возможностью. Стоит обратить внимание, что наличие декомпилированного листинга не отменяет необходимости понимать ассемблер, тем более, декомпил существует далеко не для всех платформ.
Откроем окно строк в IDA (Shift+F12).
Выберем строку sendMsg error %s, откроем ссылки на эту строку (клавиша X – Xrefs — Cross References) — IDA распознала ссылки на строку, это хорошо:
Однако среди строк, выделенных зелёным в дизассемблере, есть просто байты, выделенные красным. При этом некоторые строки явно распознаны не полностью. Так, например, если установить курсор на адрес 0x080074E6
и нажать клавишу A (потом согласиться с предложением «Directly convert to string?»), то получится строка «No device connected». Таким же образом можно пройтись по всем строко-подобным данным и превратить их в строки (или, например, написать Python-скрипт, который пробежится по указанному диапазону адресов и создаст строки).
Следующее препятствие, которое может возникнуть – нераспознанные ссылки на строки (даже если строка распозналась). Попробуйте пройтись по строкам, нажимая клавишу X. Так, например, в моем случае не найдена ссылка на строку «recvMsg error». Ссылка на объект может быть не найдена по двум очевидным причинам:
- нет кода, который ссылается на текущий объект;
- IDA не распознала ссылку.
Постараемся исключить первую из них, выполнив двоичный поиск по прошивке. Открываем окно двоичного поиска (Alt + B), вводим адрес строки, не забываем поставить галочку «Find all occurrences»:
Получили одно вхождение:
Перейдём к нему (адрес 0x08007433
):
Превратим DWORD-число в offset, нажатием клавиши O. Появилась ссылка на строку:
Установим курсор чуть выше — внутри функции sub_8005070 (диапазон 0x08005070-0x08005092
). Переключимся к декомпилированному листингу нажатием Tab:
Обратим внимание на функцию sub_8006690. Если вернуться к строке «sendMsg error %s», то можно увидеть, что она также передается в функцию sub_8006690. Именно строки с символами форматирования могут привести к предположению о том, что функция sub_8006690 – это стандартный printf. Пусть сейчас на уровне предположения это будет printf (даже если наше предположение окажется неверным, то оно всё равно позволит нам продвинуться в исследовании).
Поставим курсор на имя sub_8006690, нажмём клавишу N, введём новое имя x_printf. Префикс «x_» добавим для удобства (от слова «eXecutable») – так можно будет отличить переименованные нами функции от функций, имена которым дала IDA автоматически.
Можно считать выполненной подготовительную часть, теперь перейдём к анализу таска, отвечающего за обработку Bluetooth-соединения. Выйти на него можно опять же через строки. Во многих окнах IDA можно выполнять поиск по Ctrl+F. Так, можно сразу выбрать строки со словом «bluetooth»:
Bluetooth-таск
Кратко: идентифицировать и проанализировать функцию обработки команд, передающихся по Bluetooth. Необходимо будет создать дополнительный сегмент памяти в IDA.
Строка «Bluetooth taskrn» не имеет кросс-ссылок — воспользуемся снова двоичным поиском, получим адрес, где она используется – 0x080058A0
, перейдём туда и увидим список частично распознанных ссылок:
Создадим из них полноценные ссылки (проклацав клавишу O, или написав Python-скрипт для IDA).
Возможно, не везде создадутся ссылки (адреса, выделенные зелёным):
Перейдя по ссылкам, выделенным зеленым, увидим, что там не созданы строки. Исправляем — помогаем Иде.
Вернёмся к строке «Bluetooth taskrn». Теперь в коде по адресу 0x08005556
появилась ссылка на эту строку:
Здесь же видим, что эта строка передается аргументом в уже просмотренную нами функцию x_printf. Не забудем также дать говорящее название текущей функции «sub_8005554», например, «x_bluetooth_task».
Переключимся в декомпил и просмотрим функцию полностью. Обратим внимание на строку 132, где в функцию x_printf передаётся некое число. Если изменить отображение числа с десятичной системы счисления на шестнадцатеричную (клавиша H), то увидим число 0x8007651
, которое очень похоже на адрес.
Уже знакомая ситуация – IDA не распознала ссылку. Помогаем ей, правда, для этого нужно переключиться из декомпила в дизассемблер (клавиша Tab): делаем offset, переходим по нему, создаём строку. Переходим обратно в декомпил, нажимаем F5 (обновить).
Радуемся улучшению кода:
Снова обратим внимание на строку 132. Явно, помимо форматной строки в x_printf должен передаваться еще список аргументов переменной длины (va_list), IDA этого не распознала… Ну вы поняли, да? Поможем ей.
Установим курсор на имя функции x_printf, нажмём Y – откроется окно изменения прототипа объекта. Впишем правильный прототип функции printf:
int x_printf( const char *format, ... )
void x_printf( const char *format, ... )
. И чуть позже мы это исправим.
IDA отобразит аргументы для форматной строки:
Пришло время установить назначение (имена) переменных (снова строки нам помогают):
x_printf("recv %s state %drn", v0, v25);
—x_printf("recv %s state %drn", recv_data, state);
x_printf("cmd: %srn", v24);
—x_printf("cmd: %srn", cmd);
x_printf("addr=%x, size=%xrn", v14, v15);
—x_printf("addr=%x, size=%xrn", addr, size);
Другие имена уже не так очевидны, но и не супер-сложны для понимания.
Например, обратим внимание на участок кода:
Переменная v3 сравнивается с числом 3, потом фигурирует сообщение о неправильной длине заголовка. Логично переименовать:
- переменную v3 в header_len;
- функцию sub_80006C8 в x_strlen (можно зайти в эту функцию и проверить наше предположение).
Далее обращаем внимание на следующий блок кода:
Функция sub_80006B4 используется несколько раз. Внутри она выглядит так:
Теперь обратим внимание на переменные v20000624, v20000344, v20000348
. IDA выделила их красным цветом. Всё потому, что они ссылаются на адреса, которые отсутствуют в текущей базе дизассемблера. Если снова обратиться к документации на микроконтроллер, то можно увидеть, что диапазон адресов 0x20000000-0x20001800
относится к RAM.
Если переменная ссылается на несуществующую область памяти, для нее будут недоступны xref’ы – исследование будет вызывать дискомфорт… Для удобства и производительности имеет смысл создать дополнительный сегмент памяти. Открываем окно сегментов (Shift + F7), добавляем RAM-сегмент:
Обновляем декомпил. Обращаем внимание на переменную unk_20000344:
Очень похоже, что это некий auth_flag (флаг авторизации). Так и запишем, то есть назовем эту переменную. В моем случае кросс-ссылок не нашлось – используем двоичный поиск и создаём ссылки.
Проверка на устройстве
Кратко: проверим отдельные предположения на работающем устройстве
Статический анализ – классная штука, но еще лучше, если есть возможность исследовать код в динамике. Тут тоже простор для творчества, но если не усложнять, то самое простое – подключиться к устройству по Bluetooth, отправить какую-то команду и посмотреть на результат.
Так, например, при отправке строки «ZZZ» устройство ответит строкой ERROR: Wrong header lengthrn
, при отправке «MEOW» (эта строка есть в исследуемом коде, передаётся в функцию strcmp) увидим mur-mur (>._.<)rn
, а при отправке «ZZZZ» — ERROR: Unk cmd
. Таким образом, функцию sub_8005234 можно переименовать в x_bluetooth_send.
Составлю список команд, которые возможно поддерживаются устройством, и сразу проверю их. Вот что получилось:
“ECH1”
– возвращает «ОК», включает эхо-режим – команда дублируется отправителю;“ECH0”
– выключает эхо-режим;“MEOW”
– возвращает «mur-mur (>._.<)rn » — то ли пасхалка, то ли отладочная команда;“LED “
— выключает один из ярких светодиодов;“UART”
– возвращает «ОК»;“BLE “
— однократно мигает красным светодиодом;“READ”
– возвращает «ERROR: Not auth!»“WRIT”
– возвращает «ERROR: Not auth!»“AUTP”
– возвращает «ERROR: auth error!»“SETP”
– возвращает «ERROR: Not auth!»“VIP “
— возвращает «Wrong won’t give up!»
Промежуточные выводы относительно протокола:
- команда состоит минимум из 4 символов;
- есть довольно странные команды, как-то связанные с авторизацией (зачем авторизация на осветительном приборе?).
Улучшение кода. Создание структуры
Кратко: при возможности имеет смысл создавать структуры данных — большое подспорье для анализа.
Идём дальше. Задача минимум для нас – научиться управлять светодиодами.
Эксперимент показал, что с большими светодиодами связана команда «LED » — по крайней мере, она позволила выключить один из четырех больших светодиодов. Посмотрим, что находится в этой ветке:
Здесь можно было бы переименовать переменные, смущают только конструкции вроде
*(_WORD *)(v6 + 4) = sub_8005338(v4);
В большинстве случаев переменная v6 является указателем на структуру. Для удобства также создадим эту структуру. Контекстное меню для переменной v6 – выбираем пункт «Create new struct type».
IDA предлагает следующее определение для структуры:
Здесь доверимся автоматике относительно типов полей структуры, но установим читабельные имена, основываясь на данных из форматной строки:
struct struct_LED
{
_DWORD idx;
_WORD hue;
_BYTE sat;
_BYTE val;
};
После создания структуры код стал ещё приятнее:
Переменная v6 по ходу дела была переименована в led. Дополнительные переменные v7 и v8 для удобства также были переименованы. Пусть Вас не смущает появление дополнительных переменных – компилятору виднее.
По сведениям из форматной строки можно сделать вывод, что цвет задаётся в формате HSV (Hue, Saturation, Value). Для перевода цвета из RGB можно воспользоваться таблицей.
Про переменную v4 пока сложно что-то сказать наверняка, кроме того, что она является структурой и создается в функции sub_8005298:
Можно предположить, что переменная v4 представляет собой аргументы команды, пришедшие по Bluetooth. Давайте так и назовём:
- v4 — bt_args
- sub_8005298 — x_get_bt_args
Команда “LED ”
Кратко: исследование LED-команды, продолжаем переименовывать функции и переменные.
Сделаем еще несколько переименований для удобства восприятия:
- sub_8003B6E – x_create_struct
- sub_800532C – x_get_value_1
- sub_8005338 – x_get_value_2
Зайдём в функцию x_get_value_1:
Переименуем sub_800530C в x_get_value_3. А теперь сравним функции x_get_value_1 и x_get_value_2:
В них используется одна и та же функция x_get_value_3, но с отличающимся вторым аргументом (2 и 4). При этом x_get_value_1 возвращает 1-байтовое число, а x_get_value_2 – 2-байтовое.
Анализируем работу с x_get_value_3:
- работа ведётся со строкой bt_args (или структурой, содержащей строку);
- когда на вход подается число 2, на выходе – число размером 1 байт;
- когда на вход подается число 4, на выходе – число размером 2 байта.
Сопоставив эти факты, можно выдвинуть предположение, что функция x_get_value_3 формирует число из hex-строки указанного размера.
Выполним переименования:
- x_get_value_1 — x_get_byte;
- x_get_value_2 — x_get_word;
- x_get_value_3 — x_unhexlify.
Проверим, используется ли функция x_unhexlify где-то ещё.
Используется. Функция sub_8005344 выглядит так:
Можно переименовать её в x_get_dword.
Заинтересованный читатель может погрузиться в статический анализ функции x_unhexlify и структуры bt_args — наверняка это будет увлекательно.
На данный момент мы можем сформировать команду для управления светодиодами:
Остаётся вопрос – нужны ли разделители между отдельными полями?
Пользуясь преимуществом наличия устройства, я проверю 2 варианта:
- пробелы в качестве разделителей;
- без разделителей.
Для включения нулевого светодиода в красный цвет (следуя таблице преобразования) необходимо задать следующие значения:
- Индекс светодиода (idx) = 0x00;
- Оттенок (hue) = 0x00;
- Насыщенность (saturation) = 0xFF;
- Значение (value) = 0xFF.
Команда с пробелами: "LED 00 0000 FF FF"
— светодиод зажегся ярким светло-голубым цветом.
Команда без пробелов: "LED 000000FFFF"
(пробел после символов «LED» нужен по формату команды) – светодиод зажегся красным цветом.
Таким образом, можно сделать вывод, что параметры команды должны передаваться без пробелов. И здесь же можно выстроить предположение (которое могут подтвердить те товарищи, кто провёл полный статический анализ функции x_unhexlify), что функция x_unhexlify служит для потокового вычитывания информации с указанием размера из некого базового буфера.
- Включить первый светодиод зелёным:
"LED 010078FF80"
- Включить второй светодиод синим:
"LED 0200F0FFFF"
- Включить третий светодиод фиолетовым:
"LED 03012СFF80"
В LED-ветке осталась неизученной функция sub_8003B7C. Она принимает на вход некую переменную dword_20000624. Посмотрим, где используется эта переменная – на всякий случай сразу воспользуемся бинарным поиском (Alt + B):
Обратите внимание на адреса 0x08004FF0, 0x08005D40
. Хотела спрятаться! Помогаем Иде – создаём ссылки.
Посмотрим теперь, куда ведут ссылки off_8004FF0
и off_8005D40
:
- функция sub_8004D84 – явно стартовая функция прошивки, так как внутри используется строка «rnHardware init done… Starting FreeRTOSrn» — переименуем эту функцию в x_main;
- функция sub_8005A08 – в самом начале использует строку «LED taskrn» — переименуем эту функцию в x_leds_task.
Таким образом, переменная dword_20000624 используется:
- ближе к концу функции main;
- после получения данных по Bluetooth в x_bluetooth_task;
- в начале цикла функции x_leds_task.
Те, кто программировал потоки в обычной ОС или же работал с тасками RTOS, увидят в этой переменной указатель на очередь для обмена данными между тасками – и правильно сделают. Выполним еще несколько переименований:
- dword_20000624 — leds_queue;
- sub_8003BD0 — x_queue_recv;
- sub_8003B7C — x_queue_send.
Дополнительно можно убедиться в правильности названий, если посмотреть места, где используются эти функции:
Переименуем:
- sub_800501C — x_sendMsg;
- sub_8005044 — x_recvMsg.
Теперь, чтобы убедиться, что мы полностью умеем управлять светодиодами, исследуем функцию x_leds_task.
На этом мы немного прервёмся, выпьем чай с шоколадкой и продолжим во второй части статьи.
Результаты первого этапа
- Проведён внешний осмотр устройства.
- Прошивка загружена в дизассемблер.
- Найдены полезные для исследования строки.
- Было установлено, что «носорог» управляется через Bluetooth по простому текстовому протоколу.
- Частично исследован таск обработки команд протокола обмена по Bluetooth.
Во второй части вас ждёт полный разбор всех тасков мигающего носорога. Поиск неочевидной функциональности и небольшое домашнее задание.
Автор: prusanov