В этой статье мы будем получать информацию напрямую из источника вне какого-либо контекста.
Автор: Juan Carlos Jiménez
В первой, второй и третьей частях мы изучали интересующую нас информацию и ресурсы, используемы процессами, в определенном контексте. С другой стороны, мы находились в определенных рамках, не имели доступа ко всей информации в целом и имели дело с ограниченным набором инструментов. Вполне бы могло случиться так, что мы не смогли найти последовательный порт на печатной плате, или порт был бы найден, но в системе не была бы предусмотрена стандартная учетная запись. В таких случаях необходима кардинально другая методика работы.
В этой статье мы будем получать информацию напрямую из источника вне какого-либо контекста. Данные будут выгружаться из внешней флеш-памяти, после чего будет проводиться распаковка, чтобы полученная информация была пригодна к дальнейшему анализу. Этот метод не требует дорогостоящего оборудования и каких-либо других первоначальных условий. Внешняя флеш-память в комплекте с общедоступным даташитом – прекрасный союзник реверс-инженера.
Нюансы при выгрузке памяти
Во время исследования информационных потоков в третьей части мы обзавелись даташитом на внешнюю флеш-память, и у нас нет необходимости в изучении функционала каждого пина.
Рисунок 1: Назначение некоторых пинов у внешней флеш-памяти
Кроме того, мы ознакомились с набором инструкций и можем взаимодействовать с микросхемой при помощи любого устройства, которое умеет «общаться» с шиной SPI.
Мы также знаем, что при включении роутера микроконтроллер Ralink начинает общаться с внешней флеш-памятью, что может спровоцировать конфликты во время чтения информации. Нам нужно остановить взаимодействие между Ralink и флеш-памятью, но конкретный способ решения этой задачи зависит от конструкции электронной цепи, с которой мы работаем.
Нужен демонтаж флеш-памяти? (теория)
Самый лучший способ остановить коммуникацию между Ralink и флеш-памятью – демонтаж и полная изоляция микросхемы от остальной цепи. Данный метод позволяет нам полностью управлять ситуацией и исключает все возможные источники конфликтов, но, к сожалению, требует дополнительное оборудование, опыт и время. Мы попробуем пойти более простым путем.
Второй способ – перевод Ralink в неактивный режим, в то время как все остальные элементы вокруг находятся в режиме ожидания. Зачастую у микроконтроллеров есть пин Reset, который, при подаче логического нуля, перезагружает микросхему без отключения питания на плате. Но у нас нет полной версии даташита (возможно, эта документация распространяется только среди покупателей на основе соглашения о неразглашении информации). Внешний вид микросхемы и сложность окружающей цепи серьезно затрудняю задачу по самостоятельному поиску нужного пина.
Третий способ – подача напряжения только на внешнюю флеш-память вместо включения всей цепи. Подача питания на плату недокументированным способом может привести к конфликтам. Мы могли бы изучить цепь питания, но поскольку роутер дешевый и распространенный, попробуем обойтись без дополнительных исследований. Согласно даташиту необходимое напряжение – 3 В. Я буду запитывать внешнюю флеш-память напрямую.
Рисунок 2: Схема прямого запитывания внешней-флеш памяти
Мы будем напрямую подавать питание и ожидать данные из UART порта микроконтроллера Ralink. После подачи напряжения на задней стороне платы загорелись светоизлучающие диоды, трафик на порте отсутствует, и, предположительно, Ralink находится в неактивном режиме. Однако даже в этом случае, соединение микроконтроллера с флеш-памятью может препятствовать передаче информации вследствие нюансов проектирования цепи питания и чипа. Важно не забывать об этих деталях, если мы в дальнейшем столкнемся с чем-нибудь странным. Если произойдет нечто подобное, нам нужно физически отпаять флеш-память (или, по крайней мере, пины, отвечающие за передачу информации).
Светоизлучающие диоды и другие статические компоненты не могут взаимодействовать с флеш-памятью и, соответственно, не могут стать причиной проблем, если мы подаем достаточный ток. Я использую ступенчатый источник питания, где предусмотрена подача различных токов на все случаи жизни. Если у вас нет подобного источника питания, можете попробовать воспользоваться системой питания внешнего (ведущего) устройства или каким-либо USB-адаптером питания в случае, если необходимы токи большего размера.
Теперь пришло время подключить внешнее устройство к шине SPI.
Соединение с флеш-памятью
После того как мы убедились в отсутствии необходимости демонтажа, то можем подсоединить устройство, которое умеет общаться с шиной SPI, и начать поблочное чтение памяти. Для решения этой задачи подойдет любой микроконтроллер, но намного удобнее воспользоваться специальным переходником SPI-USB. Я воспользуюсь моделью FT232H, которая поддерживает как протокол шины SPI, так и другие низкоуровневые протоколы.
Теперь, когда мы знаем назначения пинов флеш-памяти и переходника USB-SPI, пробуем подсоединиться.
Рисунок 3: Схема подключение переходника к флеш-памяти
После подготовки и настройки аппаратной части переходим к выгрузке данных.
Выгрузка информации
Нам потребуется программное обеспечение, которое «понимает» трафик, поступающий с переходника, и умеет считывать память в бинарный файл. Написание собственной утилиты не составит особого труда, но уже есть множество доступных приложений, поддерживающих различные микросхемы и шины. Попробуем воспользоваться программой flashrom, которая широко распространена и идет с открытым исходным кодом.
Flashrom – старое и нестабильное приложение, однако поддерживает модель FT232H (переходник) в качестве ведущего устройства, и модель FL064PIF (флеш-память) – в качестве ведомого. У меня возникли проблемы при работе в OSX и виртуальной машине с Ubuntu, но в конечном итоге все заработало в системе Raspberry Pi (ОС Raspbian):
Рисунок 4: Выгрузка данных из флеш-памяти при помощи flashrom
У нас получилось выгрузить информацию, и теперь мы можем перейти от аппаратной части к подготовке данных для анализа.
Разделение бинарного файла
Мы могли бы воспользоваться командой file для идентификации некоторых частей бинарного файла, но только в том случае, если файл имел бы знакомый формат. В условия полной неопределенности мы будем пользоваться утилитой binwalk, чтобы получить хотя бы базовое представление о бинарном файле и найти информацию для извлечения.
Примечание: binwalk – очень полезная утилита для анализа бинарных файлов, созданная командой /dev/ttyS0; Если вы занимаетесь исследованиями аппаратной части, вам определенно нужно познакомиться с ребятами из этой группы.
Рисунок 5: Базовая информация о бинарном файле, полученная при помощи утилиты bindwalk
И все же в нашем случае мы не находимся в условиях полной неопределенности. В первой статье уже были получены некоторые сведения, во второй – полная карта флеш-памяти. Адреса, упомянутые ранее в отладочном сообщении, подтверждаются сейчас, что упрощает процесс разделения бинарного файла.
Рисунок 6: Карта флеш-памяти
При наличии нужных адресов мы можем разделить бинарный файл на 4 базовых сегмента. Утилита dd принимает на входе 3 параметра в десятичном формате: размер блока (bs, в байтах), смещение (skip, количество блоков) и размер (count, количество блоков); Для преобразования из шестнадцатеричной системы в десятичную мы можем воспользоваться либо калькулятором, либо средствами шелла и командой $(()):
$ dd if=spidump.bin of=bootloader.bin bs=1 count=$((0x020000))
131072+0 records in
131072+0 records out
131072 bytes transferred in 0.215768 secs (607467 bytes/sec)
$ dd if=spidump.bin of=mainkernel.bin bs=1 count=$((0x13D000-0x020000)) skip=$((0x020000))
1167360+0 records in
1167360+0 records out
1167360 bytes transferred in 1.900925 secs (614101 bytes/sec)
$ dd if=spidump.bin of=mainrootfs.bin bs=1 count=$((0x660000-0x13D000)) skip=$((0x13D000))
5386240+0 records in
5386240+0 records out
5386240 bytes transferred in 9.163635 secs (587784 bytes/sec)
$ dd if=spidump.bin of=protect.bin bs=1 count=$((0x800000-0x660000)) skip=$((0x660000))
1703936+0 records in
1703936+0 records out
1703936 bytes transferred in 2.743594 secs (621060 bytes/sec)
Мы создали 4 бинарных файла:
Анализ отдельных частей бинарного файла
После разделения бинарного файла на 4 части рассмотрим подробнее каждый из этих сегментов.
Загрузчик
Рисунок 7: Информация о бинарном файле, имеющем отношение к загрузчику
Утилита binwalk нашла и декодировала заголовок uImage. Загрузчик U-Boot использует данные заголовки для идентификации важных областей памяти. Это та же самая информация, которая отображается командой file в случае с полным дампом памяти, поскольку вначале идет тот же самый заголовок.
Нас не особо интересует информация загрузчика, поэтому переходим к изучению других файлов.
Ядро
Рисунок 8: Информация о бинарном файле, имеющем отношение к ядру
Перед извлечением полезной информации необходима распаковка. После анализа через binwalk мы еще раз убедились (как и во второй статье), что ядро упаковано алгоритмом lzma, который является очень популярным среди встроенных систем. Быстрая проверка при помощи команды strings mainkernel.bin | less подтверждает, что информации, пригодной для анализа, в файле нет.
Существует множество утилит для распаковки алгоритма lzma, например, 7z или xz, однако ни одна из этих утилит не смогла распаковать файл mainkernel.bin:
$ xz --decompress mainkernel.bin
xz: mainkernel.bin: File format not recognized
Скорее всего, дело в заголовке uImage, который нужно вычленить из файла. Мы знаем, что информация, упакованная lzma, начинается с байта 0x40. То есть нам необходимо скопировать все, кроме первых 64 байт.
Рисунок 9: Копирование части файла при помощи утилиты dd
Пробуем распаковать еще раз:
$ xz --decompress mainkernel_noheader.lzma
xz: mainkernel_noheader.lzma: Compressed data is corrupt
Утилите xz удалось распознать алгоритм lzma, но не запакованные данные. Мы пытаемся распаковать весь файл mainkernel, имеющий отношение к флеш-памяти, однако хранимая информация навряд ли занимается 100% сегмента. Попробуем удалить неиспользуемую память в конце файла и распаковать вновь:
Рисунок 10: Удаление ненужной части файла и повторная распаковка
Как видно из рисунка выше, распаковка завершилась удачно, что можно проверить при помощи команды strings, которая ищет строки в формате ASCII в бинарных файлах. Попробуем поискать что-нибудь полезное:
Рисунок 11: Поиск полезной информации в распакованном файле при помощи команды strings
Строка Wi-Fi Easy and Secure Key Derivation выглядит многообещающе, но впоследствии выяснилось, что данная строка определена в спецификации Wi-Fi Protected Setup spec. Ничего интересного, имеющего отношения к алгоритму генерации паролей.
С другой стороны, мы смогли распаковать информацию и можем двигаться дальше.
Файловая система
Рисунок 12: Информация о бинарном файле, имеющем отношение к файловой системе
Сегмент памяти mainrootfs не имеет заголовка uImage поскольку относится к ядру, а не к загрузчику U-Boot.
Файловая система SquashFS – очень популярна среди встроенных систем. Существует множество версий и вариаций, и иногда разработчики используют нестандартные сигнатуры, чтобы затруднить обнаружение данных внутри бинарного файла. В образовательных целях мы могли бы поиграться с различными версиями unsquashfs и/или модифицировать сигнатуры.
Рисунок 13: Пример сигнатуры файловой системы
Поскольку данная файловая система популярна, и поиск нужной конфигурации – довольно скучное и утомительное занятие, кто-то уже должен был написать скрипт, упрощающий решение этой задачи. Я нашел версию Firmware Modification Kit заточенную под операционную систему OSX, которая содержит скомпилированные версии unsquashfs и включает в себя скрипт unsquashfs_all.sh.
Рисунок 14: Поиск и распаковка нужной версии файловой системы
В итоге оказалось, что скрипт поддерживает сигнатуру, используемую файловой системой SquashFS в нашем случае, и распаковка завершилась успешно. Теперь у нас есть все бинарные и конфигурационные файлы, а также символические ссылки, предусмотренные в файловой системе.
Рисунок 15: Некоторые элементы дерева файловой системы
В полной версии дерева можно найти все остальные файлы, используемые системой (а не только из папки /var/).
Теперь, используя наработки из предыдущих статей, мы можем приступить к поиску потенциально интересных бинарных файлов.
Рисунок 16: Некоторые бинарные файлы, представляющие для нас интерес
Если бы мы хотели найти уязвимости в приложениях или сетевые бреши, полный перечень бинарных и конфигурационных файлах пришелся бы весьма кстати.
Защищенная область
Рисунок 17: Информация о бинарном файле, имеющем отношение к защищенной области памяти
Как мы выяснили в третьей статье, эта область памяти не запакована и содержит информацию, используемую во время перезагрузки, но которая отличается от устройства к устройству. Для получения первоначальных сведений вполне подойдет утилита strings.
Рисунок 18: Содержимое части файла protect.bin
Содержимое файла protect.bin, скорее всего, совпадает с файлом curcfg.xml: логи и некоторые строки, показанные на рисунке выше. Эту информацию мы уже проанализировали в третьей части и не нашли ничего нового.
Что дальше
На данный момент исследование аппаратной части Ralink закончено, и мы получили все, что находится во флеш-памяти. Теперь вы можете найти, что вам необходимо. Например, мы хотим управлять роутером через отладочный UART порт, найденный в первой статье, но при попытке получить доступ к оболочке ATP CLI, мы не можем подобрать учетную запись. После выгрузки информации из внешней флеш-памяти находим XML файл в защищенной области, в котором находится учетная запись.
Если вы по какой-то причине не можете выгрузить информацию из флеш-памяти, иногда файлы, предназначенные для обновления прошивки, также могут содержать полные сегменты памяти. В этом случае во время обновления происходит перезапись соответствующих областей флеш-памяти при помощи кода, ранее загруженного в RAM. По сути, получение файлов обновления от производителя будет эквивалентно выгрузке сегментов из флеш-памяти. Вам лишь нужно выполнить распаковку. Полученной информации может быть вполне достаточно для решения ваших задач.
В следующей статье мы проведем более глубокий анализ различных бинарных файлов и попытаемся найти полезную информацию.
Спасибо за внимание.
Сбалансированная диета для серого вещества