Реверсинг прошивок микроконтроллеров

862a04b09182778e833ed7055c8c4d96.png

Сегодня мы поговорим о реверс-инжиниринге, но не о реверсе софта, а о реверсинге железа. Как следует из термина, реверс-инжиниринг (обратная разработка) — это процесс разборки спроектированного продукта или устройства на его элементарные инженерные компоненты. Мотивация для такого действия может быть различной: от конкурентного анализа и выявления нарушений патентных прав до восстановления дизайна проекта, исходный код которого утерян. Тем не менее, все они включают в себя необходимость или желание понять, как был создан продукт или устройство. Слово «как» здесь используется в самом широком смысле, включая вопросы о том, «что было использовано для его создания», «где находится каждый элемент», «когда происходят определенные события» и т.д.

Реверс-инжиниринг в мире электроники может принимать самые разные формы: от программного обеспечения до аппаратного обеспечения, от «черного ящика» до интрузивного использования. Реверс-инжиниринг аппаратного обеспечения может быть таким же простым, как разборка изделия для идентификации внутренних компонентов и схем платы, или таким же сложным, как извлечение полупроводниковых схем и тестирование на месте.

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

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

Знакомимся с паяльным феном

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

328e3ffa473484d9a40a2c07b4cd1a38.png

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

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

Полученной детали даем немного остыть и помещаем в программатор, например в вот такой MiniPro:

1ac399f3cfa8994b8801300f8eae2dd5.png

 Немного офтопа:

Как-то мне нужно было залить прошивку OpenWRT на дешевый роутер, но из-за неправильного выбора прошивки я что называется «окирпичил» железку. Из всех способов лечения, предлагаемых в Интернете, ничего не помогло. В частности, попытки подключения к плате по отладочному порту завершилась неудачей. Для того, чтобы все-таки попробовать оживить устройство нужно было выпаять модуль внешней энергонезависимой памяти (EEPROM) и перепрошить его. Для решения этих задач мне и пригодился паяльный фен и программатор. В итоге я перепрошил модуль памяти и устройство ожило под новой прошивкой. Так что не стоит считать процесс выпаивания микросхемы с платы сверхсложной задачей.

Итак, мы добыли трофей, что делать дальше?

Методы защиты

Конечно, существуют различные методы защиты прошивок от считывания и для рассматриваемых нами далее микроконтроллеров ATMega имеются специальные защитные (FUSE) биты.

Фьюзы в микроконтроллерах семейства AVR представляют собой специальные биты конфигурации (переключатели), изменяя которые (то есть устанавливая в них 0 или 1) мы можем изменять некоторые режимы работы микроконтроллера или использовать какие-либо его специальные возможности, которые недоступны в его конфигурации «по умолчанию».

Не будем подробно погружаться в эту тематику, так как на эту тему есть масса других публикаций. Будем считать что авторы устройства не озаботились защитой микроконтроллера от считывания прошивки. Например, использовали среду Arduino IDE с настройками по умолчанию, загрузчик bootloader, также с настройками по умолчанию.

В таком случае мы можем с помощью MiniPro или другого программатора считать прошивку с нашей выпаянной микросхемы, точнее микроконтроллера, в случае с Arduino.

Но на выходе мы получим просто HEX-файл. Преобразовать код обратно в язык высокого уровня у нас не получится. Здесь можно провести аналогию с EXE файлами, которые также в общем случае (не рассматриваем .NET и аналогичное) нельзя обратно превратить в высокоуровневый код.

Реверсим прошивку

Для того, чтобы превратить набор кода в нечто человеко-понятное (ну если Ассемблер можно считать человеко-понятным языком) нам потребуется… правильно, дизассемблер IDA Pro. Бесплатная IDA Free здесь нам не поможет, так что попробуйте где-нибудь «купить» версию Pro.

В интерфейсе IDA выбираем Binary file и далее в списке нужное семейство процессоров или микроконтроллеров.

52029c9e8c326d665bc44fc66aeabc82.png

Получаем что-то подобное:

7e08c870d011ca7df8d716be66a0870e.png

Далее для правильной организации представления кода указываем создание ROM Section, начиная с нулевого адреса:

4a0634d830bac37edacf9d63686e54be.png

На следующем шаге IDA предлагает нам выбрать точную модель нашего «камня»:

dd2fa821f1b0c03c3d679785dbc808e9.png

В итоге мы получим нечто похожее на представленное на следующем рисунке:

d6d518c984d29eb7495d1cef7d361183.png

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

Мы не будем погружаться в дебри Ассемблера Atmel, так как на эту тему тоже есть много довольно интересных публикаций. И кроме того, возможно вам придется иметь дело с PIC, STM или Миландром и у этих МК будет совсем другой набор ассемблерных инструкций.

Заключение

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

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

© Habrahabr.ru