Перейти к содержимому

Как декомпилировать bin прошивку

  • автор:

Как декомпилировать bin прошивку

Доброго времени суток форумчанам. Нужен совет — занимаюсь программированием блоков управления автомобилей, как говорится делаю чип-тюнинг, но мне этого мало, имею огромный интерес к самим процессам происходящим в аппаратной части. Так как для моей работы есть готовые программы — всё в наглядном виде и ни какого труда не составляет работать. Файл прошивки автомобиля является бинарным файлом размером в основном 32 килобайт — именно об этом файле и идёт речь. Открывая этот файл в НЕХ редакторе вижу только цифры и буквы, слышал такие слова как декомпилятор, раскриптовать и т.п. но что и к чему не понимаю.. Не знаю ни каких языков (т.к. знание Бейсика 20 лет назад можно считать не знанием) Подскажите с помощью каких программ или языков я смогу открыть этот файл в виде команд и строк и уже потом разобраться в самих алгоритмах. Если необходимо — могу выложить любой из файлов, что бы было более понятно с каким видом файлов (программ) мне бы хотелось бы разобраться. Заранее благодарен, Чайник-энтузиаст)))
P.S. — поисх ничего не дал, извините ежели что.

Пользователь
Регистрация: 19.12.2011
Сообщений: 11

Я понимаю что таких чайников как я ещё нужно постараться поискать, потому как многие кто есть на этом форуме люди более менее имеют хотя бы понятие. Спасибо модератору за то , что изменил название темы ( я изначально чуть не так написал) — это мне дало повод для поиска, а вернее я не знал термина декомпилятор — его назначения. Забил в поиск программы по декомпиляции и вот оно, небольшое, но продвижение! Установив программу «Ida» мне стало ясно , что для того что бы правильно декомпилировать нужно знать процессор, для которого был изначально написан бинарный файл, но в Ide не оказалось такого процессора, возможно они имеют семейства и я просто не знаю к каким относится » мой» (Siemens 80C515), тем не менее движение есть. Понимаю что для того , что бы разобраться в своём вопросе мне нужно знать работу «своего» процессора , что да как полностью не въехал, нужно время. Возможно мой вопрос будет для вас странным, но хотелось бы получить совет — есть ли возможность по декомпилированному файлу определить на каком языке был написан файл, или декомпилированный можно открыть на любом из языков (я просто не понимаю разницу в них) Мне не охота тратить время на изучение всех языков, хотел бы выбрать один , нужный. Знаю наперёд что задачу поставил перед собой очень сложную, но как говорится в японской пословице — «Всё что не убивает самурая делает его сильнее!» . Заранее благодарен если кто то остановится не пройдя мимо моей темы.

Последний раз редактировалось pobedyst; 20.12.2011 в 02:37 .
Форумчанин
Регистрация: 30.01.2011
Сообщений: 231

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

Злостный анимешнег =^.^=
Регистрация: 31.05.2010
Сообщений: 13,964

Язык, который Вам необходимо изучить называется Assembler. Для каждого микроконтроллера система команд специфична, поэтому и ассемблер жля каждого свой. Фирмы-разработчики, как правило поставляют ассеблеры для своих устройств. Многие можно найти в интернете по запросу марки микроконтроллера.
С декомпилятором (дизассемблером) несколько сложнее. Здесь нужно связаться с фирмой-разработчиком или с фирмой, делавшей прошивку для этого процессора.
Хотя исходники врядли кто Вам вышлет.Но, как говорьтся, попытка не пытка.
Можно декомпилировать и вручную. Необходимо только знать систему команд.
Ну или заказать программисту, написать дизассемблер. Правда такая разработка выльется в копеечку.

Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Последний раз редактировалось Smitt&Wesson; 20.12.2011 в 07:48 .

Smitt&Wesson
Посмотреть профиль
Найти ещё сообщения от Smitt&Wesson

Пользователь
Регистрация: 19.12.2011
Сообщений: 11

Smitt&Wesson , большое спасибо за информативный ответ, я думал что прийдётся пару страниц прочитать ответов , что бы понять что к чему а тут в двух словах со всех сторон )))Попробую найти теперь )))

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

А есть ли среди программистов некий прайс, что ли? сколько может стоить такая работа?

Реверс-инжиниринг прошивки устройства на примере мигающего «носорога». Часть 1

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-модуля.

    Идентификация стандартных функций

    Кратко: на данном этапе необходимо удостовериться, что строки действительно распознались, после чего предстоит идентифицировать некоторые стандартные функции языка 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 не распознала ссылку.

    Получили одно вхождение:

    Перейдём к нему (адрес 0x0800506С ):

    Превратим DWORD-число в offset, нажатием клавиши O. Появилась ссылка на строку:

    Почему созданы двойные ссылки на строки?

    Это связано с особенностью архитектуры ARM – длина команды фиксирована и составляет 32 бита, следовательно, нет возможности в команде передать полный адрес объекта (также 32-битный). Поэтому в коде используется короткое смещение на адрес, расположенный рядом с функцией, где уже хранится полный 32-битный адрес объекта.

    Установим курсор чуть выше — внутри функции 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»:

    Что такое таск?

    Таск (task, задача) – понятие из мира операционных систем реального времени (RTOS). Если по-простому, то таск можно представлять как отдельный процесс. Подробнее можно почитать в цикле статей о FreeRTOS

    Bluetooth-таск

    Кратко: идентифицировать и проанализировать функцию обработки команд, передающихся по Bluetooth. Необходимо будет создать дополнительный сегмент памяти в IDA.

    Строка «Bluetooth task\r\n» не имеет кросс-ссылок — воспользуемся снова двоичным поиском, получим адрес, где она используется – 0x080058A0 , перейдём туда и увидим список частично распознанных ссылок:

    Создадим из них полноценные ссылки (проклацав клавишу O, или написав Python-скрипт для IDA).

    Возможно, не везде создадутся ссылки (адреса, выделенные зелёным):

    Перейдя по ссылкам, выделенным зеленым, увидим, что там не созданы строки. Исправляем — помогаем Иде.

    Вернёмся к строке «Bluetooth task\r\n». Теперь в коде по адресу 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, . )

    Эмм, простите, у вас ошибка в прототипе printf.
    Согласен, правильно будет

    void x_printf( const char *format, . )

    И чуть позже мы это исправим.

    IDA отобразит аргументы для форматной строки:

    Пришло время установить назначение (имена) переменных (снова строки нам помогают):

    • x_printf(«recv %s state %d\r\n», v0, v25); — x_printf(«recv %s state %d\r\n», recv_data, state);
    • x_printf(«cmd: %s\r\n», v24); — x_printf(«cmd: %s\r\n», cmd);
    • x_printf(«addr=%x, size=%x\r\n», v14, v15); — x_printf(«addr=%x, size=%x\r\n», addr, size);

    Например, обратим внимание на участок кода:

    Переменная v3 сравнивается с числом 3, потом фигурирует сообщение о неправильной длине заголовка. Логично переименовать:

    • переменную v3 в header_len;
    • функцию sub_80006C8 в x_strlen (можно зайти в эту функцию и проверить наше предположение).

    Функция sub_80006B4 используется несколько раз. Внутри она выглядит так:

    Узнали её?
    strcmp. Переименовываем. Создаём из хаоса и разрозненности стройный читаемый код.

    Теперь обратим внимание на переменные v20000624, v20000344, v20000348 . IDA выделила их красным цветом. Всё потому, что они ссылаются на адреса, которые отсутствуют в текущей базе дизассемблера. Если снова обратиться к документации на микроконтроллер, то можно увидеть, что диапазон адресов 0x20000000-0x20001800 относится к RAM.

    Почему 0x20001800?
    0x1800 — это 6Kb RAM, а это указано в документации

    Если переменная ссылается на несуществующую область памяти, для нее будут недоступны xref’ы – исследование будет вызывать дискомфорт… Для удобства и производительности имеет смысл создать дополнительный сегмент памяти. Открываем окно сегментов (Shift + F7), добавляем RAM-сегмент:

    Обновляем декомпил. Обращаем внимание на переменную unk_20000344:

    Очень похоже, что это некий auth_flag (флаг авторизации). Так и запишем, то есть назовем эту переменную. В моем случае кросс-ссылок не нашлось – используем двоичный поиск и создаём ссылки.

    Проверка на устройстве

    Кратко: проверим отдельные предположения на работающем устройстве

    Статический анализ – классная штука, но еще лучше, если есть возможность исследовать код в динамике. Тут тоже простор для творчества, но если не усложнять, то самое простое – подключиться к устройству по Bluetooth, отправить какую-то команду и посмотреть на результат.

    Так, например, при отправке строки «ZZZ» устройство ответит строкой ERROR: Wrong header length\r\n , при отправке «MEOW» (эта строка есть в исследуемом коде, передаётся в функцию strcmp) увидим mur-mur (>._.<)\r\n , а при отправке «ZZZZ» — ERROR: Unk cmd . Таким образом, функцию sub_8005234 можно переименовать в x_bluetooth_send.

    Составлю список команд, которые возможно поддерживаются устройством, и сразу проверю их. Вот что получилось:

    • “ECH1” – возвращает «ОК», включает эхо-режим – команда дублируется отправителю;
    • “ECH0” – выключает эхо-режим;
    • “MEOW” – возвращает «mur-mur (>._. <)\r\n » — то ли пасхалка, то ли отладочная команда;
    • “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. Давайте так и назовём:

    В декомпиле возможна потеря ранее распознанной информации

    При манипулировании именами и типами данных в декомпиле могут пропадать или появляться аргументы функций. В этом случае нужно для таких функций явно указывать их прототип (клавиша Y на заголовке функции). Из-за того, что в ARM’е первые 4 аргумента передаются через регистры, IDA при декомпиле может эти аргументы «терять», в этом случае… спешим на помощь ИДЕ. Если по декомпилу непонятно, какие аргументы передаются в функцию, идём в дизассемблерный листинг и смотрим на регистры R0-R3 – не заносятся ли в них какие-то значения перед обращением к интересуемой функции. Если заносятся, то в 90% случаев – это аргументы функции, и нужно прописать эти аргументы в прототипе.

    Команда “LED ”

    Кратко: исследование LED-команды, продолжаем переименовывать функции и переменные.

    Сделаем еще несколько переименований для удобства восприятия:

    • sub_8003B6E – x_create_struct
    • sub_800532C – x_get_value_1
    • sub_8005338 – x_get_value_2

    Переименуем 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_1 — x_get_byte;
    • x_get_value_2 — x_get_word;
    • x_get_value_3 — x_unhexlify.

    Используется. Функция sub_8005344 выглядит так:

    Можно переименовать её в x_get_dword.

    Заинтересованный читатель может погрузиться в статический анализ функции x_unhexlify и структуры bt_args — наверняка это будет увлекательно.

    На данный момент мы можем сформировать команду для управления светодиодами:

    Остаётся вопрос – нужны ли разделители между отдельными полями?

    Пользуясь преимуществом наличия устройства, я проверю 2 варианта:

    • пробелы в качестве разделителей;
    • без разделителей.
    • Индекс светодиода (idx) = 0x00;
    • Оттенок (hue) = 0x00;
    • Насыщенность (saturation) = 0xFF;
    • Значение (value) = 0xFF.

    Команда без пробелов: «LED 000000FFFF» (пробел после символов «LED» нужен по формату команды) – светодиод зажегся красным цветом.

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

    • Включить первый светодиод зелёным: «LED 010078FF80»
    • Включить второй светодиод синим: «LED 0200F0FFFF»
    • Включить третий светодиод фиолетовым: «LED 03012СFF80»

    Обратите внимание на адреса 0x08004FF0, 0x08005D40 . Хотела спрятаться! Помогаем Иде – создаём ссылки.

    Посмотрим теперь, куда ведут ссылки off_8004FF0 и off_8005D40 :

    • функция sub_8004D84 – явно стартовая функция прошивки, так как внутри используется строка «\r\nHardware init done… Starting FreeRTOS\r\n» — переименуем эту функцию в x_main;
    • функция sub_8005A08 – в самом начале использует строку «LED task\r\n» — переименуем эту функцию в x_leds_task.
    • ближе к концу функции main;
    • после получения данных по Bluetooth в x_bluetooth_task;
    • в начале цикла функции x_leds_task.
    • dword_20000624 — leds_queue;
    • sub_8003BD0 — x_queue_recv;
    • sub_8003B7C — x_queue_send.

    • sub_800501C — x_sendMsg;
    • sub_8005044 — x_recvMsg.

    На этом мы немного прервёмся, выпьем чай с шоколадкой и продолжим во второй части статьи.

    Результаты первого этапа

    • Проведён внешний осмотр устройства.
    • Прошивка загружена в дизассемблер.
    • Найдены полезные для исследования строки.
    • Было установлено, что «носорог» управляется через Bluetooth по простому текстовому протоколу.
    • Частично исследован таск обработки команд протокола обмена по Bluetooth.

    Как отредактировать файлы прошивки

    там каракули какие то. в блокноте так же открывается. существует какой нибудь более читабельный вариант?

    dima555
    ( 29.09.18 21:38:40 MSK ) автор топика
    Ответ на: Как отредактировать файлы прошивки от dima555 29.09.18 21:38:40 MSK

    Re: Как отредактировать файлы прошивки

    Тебе каракули не видны? Сделай яркость монитора ярче, я всегда так делаю.

    anonymous
    ( 29.09.18 21:53:43 MSK )

    Полностью опиши задачу, которую ты должен сделать, пожалуйста.

    anonymous
    ( 29.09.18 21:54:48 MSK )
    Ответ на: комментарий от anonymous 29.09.18 21:54:48 MSK

    есть подозрение что прошивка на мой асик манит налево. хочу узнать куда

    dima555
    ( 29.09.18 22:11:48 MSK ) автор топика
    Ответ на: комментарий от dima555 29.09.18 22:11:48 MSK
    anonymous
    ( 29.09.18 22:41:11 MSK )
    Ответ на: Как отредактировать файлы прошивки от dima555 29.09.18 21:38:40 MSK

    Ах, каракули. А ты думал там литературный текст будет? Изучай ассемблер и инструментарий для реверс инжиниринга, если тебе «очень надо».

    slovazap ★★★★★
    ( 29.09.18 23:50:16 MSK )

    i-rinat ★★★★★
    ( 30.09.18 17:24:21 MSK )

    Для таких вопросов есть 4пда.

    time_LORd ★
    ( 30.09.18 17:26:24 MSK )
    Ответ на: Как отредактировать файлы прошивки от dima555 29.09.18 21:38:40 MSK

    Файл бинарный, открывать его надо в hex редакторе, ну а текст читать по 8-ричной таблице символов.

    torvn77 ★★★★★
    ( 30.09.18 17:28:29 MSK )

    Про то, как монтировать JFFS2, товарищ на ЛОРе даже FAQ выкладывал, пользуйся поиском.

    hobbit ★★★★★
    ( 30.09.18 17:30:57 MSK )

    О, о, я смотрю профи собрались. dtb надо декомпилировать dtc. Это Device Tree Blob. Он тебе не расскажет ничего про то, куда прошивка ходит так как это просто конфиг ядра. .jffs2 — образ файловой системы jffs2. Его можно посмотреть если включить виртуальный флеш и туда записать, ну или qemu. hex-редакторами долго будешь искать. К тому же оно сжатое и текстовых строк не будет видно.

    Reverse Engineering ESP8266 — часть 2

    Продолжаем исследование модуля ESP8266. В этот раз рассмотрим процесс загрузки прошивки для дизассемблирования.

    Первая часть статьи здесь.

    4. Загрузка прошивки для исследования

    Подготовив необходимые инструменты, мы подошли к самой интересной части – загрузке и дизассемблированию прошивки.

    ELF

    Начнем с самого простого – загрузки файла app.out – прошивки в формате ELF, созданной с помощью SDK.

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

    После компиляции и сборки в папке build у нас появится файл app.out, который представляет собой скомпилированный пользовательский код, данные, библиотеки и отладочную информацию. В таком виде прошивку загрузить в модуль нельзя, поэтому после сборки ELF-файла SDK преобразует app.out в один или два файла в папке firmware – 0x00000.bin и 0x40000.bin, которые можно непосредственно прошить.

    Открыв app.out в HIEW и посмотрев на таблицу сегментов (enter, F8, F6) мы увидем следующую картину:

    Колонка VirtAddr содержит адреса начала сегментов в адресном пространстве Xtensa. Обратите внимание, что три сегмента (.data, .rodata и .bss) будут загружены в область оперативной памяти, сегмент .text будет записан по адресу пользовательского исполняемого кода, а сегмент .irom0.text – по адресу кода библиотек SDK. Остальные сегменты, имеющие начальный адрес, равный нулю, содержат служебную информацию и в прошивку, готовую к заливке в модуль добавлены не будут.

    Забегая вперед скажу, что сегмент .irom0.text будет в исходном виде скопирован в файл 0x40000, а сегменты .data, .rodata, .bss и .text будут собраны в файл 0x00000.bin с учетом формата, который был рассмотрен выше.

    Для загрузки app.out в IDA необходимо проделать следующую последовательность действий:

    1. Открываем IDA Pro 6.6 или выше
    2. Нажимаем «Go» — никаких файлов пока открывать не будем
    3. Открываем пункт меню File – Script file и выбираем скрипт определения процессора xtensa.py
    4. Загружаем файл app.out, здесь необходимо выбрать тип процессора и нажать «Set»:

    5. В следующих окнах с предупреждением о неизвестном типе машины и предложениями загрузки отладочной информации нажать «Yes»
    6. В результате мы получим готовый к исследованию файл:

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

    Системная прошивка модуля

    Мы рассмотрели довольно простую загрузку в IDA прошивки в виде ELF-файла. Однако на практике зачастую требуется изучить уже готовые прошивки, извлеченные из flash модуля (методом подключения к flash напрямую) или распространяемые в виде файлов 0x00000.bin и 0x40000.bin. Здесь придется проделать немного ручной работы. Начнем с загрузки образа системного ROM. В первой части я давал ссылку на архив с файлом 40000000.bin – это он и есть. Последовательность действий такая:

    1. Открываем IDA Pro 6.6 или выше
    2. Нажимаем «Go»
    3. Открываем пункт меню File – Script file и выбираем скрипт определения процессора xtensa.py
    4. Открываем файл 40000000.bin
    5. Выбираем тип процессора Tensilica Xtensa [xtensa] и нажимаем «Set»
    6. Далее необходимо указать организацию памяти для правильной загрузки двоичного файла. Здесь мы создаем сегмент кода по адресу 0x40000000 и загружаем в него наш файл:

    7. Образ ROM загружен, но он плохо читаем из-за отсутствия названий функций. Теперь загрузим скрипт 40000000.idc, который произведет дополнительную работу – определит имена функций и создаст дополнительные сегменты в адресном пространстве: File – Script file – 40000000.idc. Вот результат:

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

    А вот, кстати, функция, которая копирует пользовательскую прошивку из flash в память SoC:

    Такой функции в SDK нет, поэтому название я ей дал произвольное.

    Но прошивка не полна без загрузки пользовательской части – файлов 0x00000.bin и 0x40000.bin. Поэтому подгрузим эти файлы к системному ROM.

    Пользовательская прошивка

    Мы загрузили в IDA системный ROM модуля, а скрипт подготовил нам несколько сегментов для загрузки остальных частей. Начнем с простого – загрузки кода библиотек.

    Как я говорил выше, файл прошивки 0x40000.bin представляет собой образ сегмента кода без всякой служебной информации и напрямую мапируется в адресное пространство процессора по адресу 0x40240000. Чтобы подгрузить его в IDA проделаем следующее:

    1. Убедимся, что у нас открыта база данных 40000000.bin и скрипт 40000000.idc создал дополнительные сегменты: RAM, ROM, IRAM, IROM
    2. Выбираем в меню File – Load file – Additional binary file, открываем файл прошивки 40000.bin
    3. В следующем окне выбираем параметры загрузки. Обратите внимание, что загрузка производится по смещению в параграфах, т.е. вместо адреса указываем значение в 10h раз меньше (отбрасываем последний ноль). Галку создания сегмента можно снять, он у нас уже создан:

    4. Файл загружен. После указания начала кода (в данном случае это 4024000Ch) мы получаем примерно следующую картину:

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

    Небольшое лирическое отступление

    Как исследовать голый ассемблерный код? Как понять, что выполняет та или иная функция? Для многих известных SDK IDA имеет сигнатуры FLIRT, которые определят названия стандартных функций. В нашем случае это не поможет, так как IDA не знает данный SDK. Так что эту работу придется проделать вручную. Для примера приведу несколько методов в порядке возрастания сложности:

    1. Найти сигнатуру исследуемой функции в дизассемблере ELF-файла, скомпилированного той же версией SDK. Есть вероятность, что вы ее найдете, и у нее будет имя (из отладочной информации). В том числе для этого я рассматривал загрузку прошивки в ELF.
    2. Известные константы – функция может ссылаться на текстовые строки или двоичные данные. С опытом многие такие константы запоминаешь наизусть, если константа незнакома – гуглим. Вот пример:

    Видим две примечательные константы. Гугл первой же ссылкой выдает описание алгоритма strlen, использующего эти константы:

    Сравнив реализации алгоритма, можно с уверенностью сказать, что по адресу 40100E70h расположена функция strlen.
    Или вот такой кусок кода сразу выдает функцию деления:

    3. Собственно, изучение ассемблерного кода и попытка понять, что выполняет функция. Иногда можно определить, что перед нами «местная» реализация знакомого алгоритма, а иногда нет.
    В любом случае, навык понимания ассемблерного кода приходит с опытом, так что дерзайте!

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

    Сначала идет 8 байт общего заголовка прошивки, в которой определяется количество сегментов и точка входа. Потом идут сами сегменты, также имеющие 8-ми байтовые заголовки с адресом и длиной.
    Чтобы правильно загрузить их в IDA я вырезал данные каждого сегмента (без заголовков) в отдельные файлы, назвав их по адресу загрузки:

    Теперь остается подгрузить их в IDA. Для каждого файла выполняем последовательность действий, аналогичных загрузке системного ROM:

    1. File – Load file – Additional binary file, выбираем файл данных
    2. В параметрах загрузки указываем сегмент (по имени файла без последнего нуля), сегмент не создаем.

    Все, теперь у нас есть полностью загруженная и готовая к исследованию прошивка!

    В этой части статьи мы рассмотрели процедуры загрузки различных видов прошивок ESP8266 для дизассемблирования в IDA Pro. В заключительной части мы рассмотрим особенности процессора Xtensa, отличия от архитектуры x86, набор регистров и команд.

  • Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *