Взлом прошивок USB-устройств

В этой статье я хочу продемонстрировать извлечение прошивки из защищенного USB-устройства, работающего на микроконтроллере Cortex M0.

Кто взламывает игровые приставки?

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

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

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

Защита геймпада DualShock 4

Те читатели, которые следят за моим аккаунтом в Twitter, знают, что я давно увлекаюсь игровыми приставками, их реверсом, а также всем, что связано с консолями, в том числе, неофициальными игровыми устройствами. В первые дни существования PlayStation 4 публично известная уязвимость в ядре FreeBSD, на котором основано ядро этой приставки, позволила мне (и многим другим исследователям) приобщиться к архитектуре и принципам работы консоли Sony. Я провел множество исследований, в том числе, изучил принципы аутентификации игровой периферии и то, как PS4 отличает лицензированные устройства от нелегальных. Ранее я проводил подобные исследования других приставок, и авторизация периферийных устройств у PS4 оказалась хоть и проще чем у Xbox 360, но не менее эффективна.


Схема авторизации USB-аксессуаров PlayStation 4

PS4 посылает 0x100 случайных данных, в ответ на которые DualShock 4 генерирует подпись RSASSA-PSS SHA-256 и присылает её вместе с криптографическими константами N и E (публичный ключ), которые нужны для верификации этой подписи. Эти константы уникальны для каждого выпущенного геймпада. Также геймпад посылает подпись для верификации N и E, алгоритм тот же — RSASSA-PSS SHA-256, но криптографические константы едины для всех приставок и хранятся в ядре приставки.

Таким образом, чтобы авторизовать свое устройство недостаточно взломать ядро приставки — нужно иметь приватный ключ геймпада. И если кто-то всё-таки взломает геймпад и получит его, то у Sony остается возможность заблокировать ключ с обновлением прошивки. Также, если в течении 8 минут приставка не получает авторизационное сообщение от геймпада, то она прекращает «общение» с ним, и чтобы продолжить использование устройства нужно отключить его от консоли и подключить заново. Симуляция этого процесса очень раздражала владельцев первых нелегальных геймпадов.

Слухи о суперподделке DualShock 4

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

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


Неавторизированный геймпад Gator Claw

Интересным в нем было то, что, судя по обсуждению контроллера на Reddit, сначала он работал, как и другие неавторизованные геймпады — по 8 минут, но разработчики смогли это исправить в обновлении прошивки. На сайте магазина была доступна ссылка на файл обновления и руководство по его установке, которые я и скачал.


Инструкция по обновлению геймпада Gator Claw

Основы анализа embedded прошивок

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


Прошивка, найденная в ресурсах программы обновления Gator Claw

Читатели, знакомые с программированием embedded-устройств, наверняка узнают этот формат. Это файловый формат Intel HEX который часто применяется для программирования микроконтроллеров и многие компиляторы, например, GNU Compiler, могут выводить скомпилированную программу в таком формате. Также мы можем видеть, что начало этой прошивки не имеет большой энтропии и последовательности байтов легко различимы, что означает отсутствие шифрования или сжатия. После декодирования Intel HEX стрима и загрузки в редактор (010 Editor умеет открывать файлы прямо в таком формате) мы можем взглянуть на прошивку. Что это за архитектура? ARM Cortex-M настолько распространен что я различаю его с первого взгляда.


Прошивка Gator Claw (слева) и векторная таблица ARM Cortex-M (справа)

Согласно спецификации первое двойное слово — это начальная вершина стека, после него идет таблица прерываний. Первое слово в этой таблице — Reset vector, служащий точкой входа. Также можно сразу обратить внимание на верхнюю часть адресов других обработчиков прерываний, что дает нам представление о базовом адресе прошивки.

Помимо этого, в ресурсах был найден файл конфигурации с описанием различных микроконтроллеров. Скорее всего, разработчики программы для обновления задействовали некий общедоступный код от производителя микроконтроллера и наиболее вероятно, что этот файл конфигурации шел вместе с этим публичным кодом.


Файл конфигурации с описанием различных микроконтроллеров

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


Сайт производителя микроконтроллеров Nuvoton

Благодаря этому у нас есть прошивка, мы знаем архитектуру и производителя микроконтроллера, у нас есть сведения о базовом адресе, вершине стека и точке входа. Доступной информации более чем достаточно, чтобы загрузить прошивку в IDA Pro и приступить к анализу.

В процессорах ARM поддерживаются два режима исполнения кода с различными инструкциями: ARM (32-битные инструкции) и Thumb (16-битные инструкции, дополненные Thumb-2 32-битными инструкциями). Cortex-M0 поддерживает только режим Thumb, поэтому мы установим переключатель в Processor options – Edit ARM architecture options – Set ARM instructions на NO во время загрузки прошивки.

Мы видим, что прошивка хорошо загрузилась по базовому адресу 0, автоматический анализ распознал практически все функции. И теперь встает вопрос – как правильно анализировать прошивки?


Одна из функций, присутствующих в прошивке

Если изучить эту прошивку, то мы увидим, что она совершает большое количество операций чтения и записи к памяти с базовым адресом 0x40000000. Это базовый адрес где находится память, отведенная под ввод-вывод (memory mapped input output — MMIO). Через эти адреса предоставляется доступ ко всем периферийным компонентам, которые есть у микроконтроллера. Все что делает прошивка происходит через доступ к MMIO-регистрам.


Схема адресов периферийных устройств

Найдя в документации адрес 0x40000000 мы узнаем, что этот микроконтроллер серии M451. Зная семейство микроконтроллера, можем скачать SDK и образцы кода для этой платформы. Внутри SDK мы находим заголовочный файл с объявлением всех MMIO-адресов, всех битовых полей и структур. Так же мы можем скомпилировать образцы кода и все библиотеки, а затем сравнить их с функциями в нашей IDB, или мы можем просто искать имена MMIO адресов в исходном коде и сравнивать их с нашим ассемблерным кодом. Это превращает процесс обратной разработки прошивки в простой и легкий процесс. Анализ был бы намного сложнее если бы у нас не было информации об архитектуре и модели микроконтроллера, и MMIO-регистрах. К слову, именно поэтому многие производители делятся SDK только после подписи NDA.


Процесс нахождения библиотечных функций в коде прошивки

Но что по-настоящему заинтересовало меня в этой прошивке — одна неиспользуемая строка с именем крупного производителя электроники (наиболее известного своими логическими анализаторами, но, как оказалось, имеющего и игровое подразделение). Судя по всему, она должны была быть частью USB Device Descriptor, но этот дескриптор не был использован.

В тени гиганта

Мне удалось найти магазин с огромным ассортиментом игровых аксессуаров, продаваемых под единой торговой маркой. Среди продаваемых аксессуаров числились два десятка различных адаптеров для подключения геймпадов одной приставки к другой. К примеру, отдельный продукт для подключения геймпада Xbox 360 к приставке PS4, отдельный продукт для подключения геймпада PS3 к приставке Xbox One, и многие другие, включая «все в одном». Также ассортимент продукции включает адаптеры для подключения клавиатуры и мыши к консолям PS4, Xbox One и Nintendo Switch, различные игровые геймпады и печатные платы для создания своих аркадных контроллеров для приставок. Все продукты шли с обновлениями, аналогичными тому, которое шло с Gator Claw, но с существенным отличием – все прошивки были зашифрованы.


Пример инструкции и зашифрованной прошивки из ресурсов программы обновления к одному из продуктов

Теперь попробуем найти фотографии печатных плат аркадных контроллеров, что позволит оценить схему устройства, не покупая и не разбирая его. Скорее всего их дизайн идентичен дизайну Gator Claw. На найденных фотографиях мы можем видеть два микроконтроллера: один из них должен быть Nuvoton M451, а другой – вспомогательный, для секретов: производители понимают, что конкуренты могут изучить их прошивку, и чтобы предотвратить это используют второй микроконтроллер. Забегая вперед, скажу, что в нашем случае он тоже присутствовал. Данные для аутентификации передаются в него по протоколу I2C и после получения отправляются обратно на приставку.

Поскольку все дорожки идут к микроконтроллеру под черной эпоксидной смолой, мы можем заключить, что это главный микроконтроллер. А микроконтроллер с четырьмя желтыми ножками соответствует требованиям для работы по протоколу I2C и является вспомогательным.


Примеры внутреннего дизайна выпускаемой продукции

Внутри контроллера

К этому моменту я наконец получил посылку из Шэньчжэня, и надо сказать, что контрафактный гаджет очень сложно отличить от оригинального DualShock 4: геймпад выполнен из качественных материалов, touchpad работает, динамик и гарнитура тоже.


Контрафактный DualShock 4 (вид снаружи)

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


Контрафактный DualShock 4 (вид на главную плату)

Я припаял провода к отладочным площадкам и подключил программатор. Программатор определил устройство, но security lock был установлен.


Программатор определил микроконтроллер и включенный Security Lock

Метод взлома прошивок USB-устройств

Дизайн USB-протокола определяет две сущности — хост и остальные устройства, которые подключаются к нему. Они, в свою очередь, разделяются на классы: hub, human interface, printer, imaging, mass storage device и другие.


Схема подключения USB устройств

Общение между устройствами и хостом происходит посредством односторонних и двухсторонних каналов. Под каналом мы подразумеваем передачу данных между программой на хосте и конкретным «конечной точкой» на устройстве. Таких точек может быть несколько для передачи различных данных.


Схема типов передачи данных

Существует четыре типа передачи данных:

  • Control Transfers (используется для конфигурации)
  • Bulk Data Transfers (большие количества последовательных данных)
  • Interrupt Data Transfers (используются для своевременной и точной передачи данных)
  • Isochronous Data Transfers (беспрерывный поток данных)

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

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


Пакеты, задействованные в протоколе USB

По факту, USB-протокол — это машина состояния, и в этой статье мы не будем останавливаться на каждом из этих пакетов. Ниже представлен пример осуществления Control Transfer:


Control Transfer

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

Диаграмма ниже изображает формат SETUP-пакета, который используется для выполнения Control Transfer.


Формат SETUP-пакета

SETUP-пакет занимает 8 байт и может предоставлять различные данные в зависимости от типа запроса. Некоторые из них едины для всех устройств (например, дескрипторы), другие зависят от класса устройства или желания производителя. Размер передаваемых/получаемых данных задается 16-битным словом и также передается в SETUP-пакете.


Примеры запросов

Подводя итог: Control Transfers используют простой протокол, поддерживаемый всеми USB-устройствами, которые могут иметь множество дополнительных команд, и мы контролируем размер данных. Все это делает Control Transfers идеальной целью для фаззинга и глитчинга.

Эксплуатация

Для взлома поддельного геймпада мне не пришлось прибегать к фаззингу т.к. я нашел баги еще во время просмотра кода прошивки Gator Claw.


Уязвимый код в обработчике HID реквестов

Функция HID_ClassRequest() написана для симуляции работы оригинального геймпада DualShock 4, и поддерживает минимум необходимых запросов для работы с приставкой PlayStation 4. USBD_GetSetupPacket() получает SETUP-пакет и в зависимости от типа переданного репорта либо получит, либо отправит данные функциями USBD_PrepareCntrlIn() и USBD_PrepareCntrlOut(). Как можно заметить, запрошенный размер данных не проверяется и это должно дать нам возможность читать часть внутренней памяти, где хранится прошивка, а также читать и писать в начало SRAM-памяти.


Переполнение буфера в процессе Control Transfer

Размер DATA-пакета задается в USB Device Descriptor (который также получается с помощью Control Transfer) но, похоже, что остается не учтен тот факт, что этот размер указывает на размер одного пакета, а их может быть сколько угодно в зависимости от размера, заданного в SETUP-пакете.

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


Эксплуатация переполнения буфера в SRAM памяти

SRAM (Static random access memory) — это оперативная память, в которой помимо прочего находится стек. Очень часто SRAM также является исполняемой памятью (настраивается), обычно это делается для улучшения производительности – основная прошивка может скопировать в SRAM часто вызываемый код, например, код Real-Time Operating System. Нет гарантий, что вершина стека будет находиться в достижимых пределах переполнения буфера, но вероятность этого велика.

Неожиданно, но главным препятствием на пути к эксплуатации уязвимостей в прошивках USB-устройств являются операционные системы. Нижеперечисленное характерно для Windows, но думаю, что актуально и для Linux-based систем без специальных исправлений.

Во-первых, ОС не позволяет прочесть больше 4 килобайт во время передачи данных Control Transfer. Во-вторых, по моему опыту ОС не позволяет записать больше одного пакета с данными во время Control Transfer. В-третьих, USB-устройство может использовать «скрытые» запросы, которые ОС откажется посылать.

Это легко продемонстрировать на примере устройств HID (Human Interface Device), к которым относится геймпад. У них есть дополнительные дескрипторы: HID Descriptor, Report Descriptor, Physical Descriptor. Второй из списка отличается от каких-либо других дескрипторов и состоит из программных единиц, описывающих доступные репорты. Если запрос не описан в Report Descriptor, то в таком случае ОС откажется его выполнить даже если он обрабатывается в устройстве. Все это противодействует нахождению и эксплуатации уязвимостей.

Чтобы решить эту проблему без необходимости разбираться и перекомпилировать ядро Linux, я воспользовался low end инструментами которые были у меня под рукой: плата Arduino Mega + USB Host Shield (общая стоимость — менее 30 $).


Схема подключения устройств

После подключения устройств по представленной выше схеме, я воспользовался Arduino для выполнения Control Transfer без каких-либо вмешательств со стороны операционной системы.


Arduino Mega + USB Host Shield

Поддельный геймпад содержал те же уязвимости что и Gator Claw, и первое что я сделал — «сдампил» часть прошивки.


«Сдампленная» часть прошивки

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


Структура с указателями на известные данные

Дамп прошивки позволил нам узнать адрес функции printf(), которая выводит в UART информацию, необходимую для контроля качества. Также анализ дампа позволили найти аналог функции hexdump(), что полностью освобождает нас от необходимости написания шеллкода.


Нахождение функций, облегчающих эксплуатацию

После нахождения контактов UART на плате геймпада, припаивания проводов и подключения их к TTL2USB адаптеру мы видим вывод в терминале.


Стандартный UART вывод при включении геймпада

Стандартная библиотека для микроконтроллеров Nuvoton идет с очень удобным обработчиком Hard Fault исключений, который выводит дамп регистров. Это сильно облегчает эксплуатацию и позволяет отлаживать эксплойт.


Вывод в UART при Hard Fault исключении, вызванным перезаписью стека

Финальный эксплойт для дампа прошивки:


Эксплойт и шеллкод для получения дампа прошивки по UART

Но этот способ дампа нельзя считать полноценным, поскольку серия микроконтроллеров Nuvoton M451 позволяет использовать две различные прошивки: основную (APROM) и мини-прошивку для DFU-обновлений (LDROM).


Схема Flash и системной памяти Nuvoton M451 в различных режимах исполнения

Эти прошивки транслируются на одни и те же адреса памяти, поэтому в зависимости от текущего режима можно прочесть только одну из них. Для того, чтобы получить дамп прошивки LDROM, нам нужно отключить security lock и прочитать Flash-память с помощью программатора.


Шеллкод, снимающий security lock

Криптофейл

Изучение прошивки обновлений (LDROM) показало, что это стандартный код от Nuvoton, но с добавленным шифрованием обновлений прошивок.


Схема криптографического алгоритма шифрования обновлений прошивок

Шифрование представляет собой кастомный блочный алгоритм, выполненный в режиме сцепления блоков шифротекста, длина которых составляет всего 32 бита. В этот алгоритм предоставляются ключ, который является текстовым (ASCII) идентификатором продукта, и массив инструкций, которые определяют, какое преобразование сделать с текущим блоком. После достижения конца ключа и массива, их позиция устанавливается на начальную. Список преобразований включает в себя шесть операций: xor, subtraction, subtraction (reverse), и повтор этих преобразований с переустановкой байт. Так как в прошивках присутствуют большие области, состоящие из нулевых байт, это позволяет с легкостью посчитать секретные составляющие этого алгоритма.


Раскрытие ключа шифрования обновления прошивки

Применение алгоритма, извлеченного из прошивки контрафактного геймпада, ко всем прошивкам аксессуаров, доступных на сайте OEM-производителя, показало, что они все используют этот алгоритм шифрования. Это позволяет высчитать ключи шифрования для всех устройств и расшифровать все представленные прошивки. Таким образом, алгоритм, вложенный в контрафактный продукт поставил под угрозу безопасность всех продуктов производителя.

Заключение

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

Что касается тайны со вспомогательным микроконтроллером, то оказалось, что, во-первых, он присутствует не во всех устройствах, а во-вторых, добавлен всего лишь для запутывания и не хранит никаких секретов, выполняя лишь операции SHA1 и SHA256. Контроллер Nuvoton M451, может быть объектом для дальнейших исследований т.к. во время этого исследования он продемонстрировал некоторые признаки, которые могут свидетельствовать о наличии архитектурных уязвимостей.

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

Публикации на схожие темы

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

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