Исследование прошивки Mi Router 4A Giga Version. Получение интерфейса командной оболочки Linux
Приветствую вас, дорогие читатели! Сегодня хочу рассказать вам о том, как я получил интерфейс командной оболочки Linux у wi-fi роутера Mi Router 4A Giga Version:
Рисунок 1 — wi-fi роутер
Разбор роутера и подключение к ноутбуку
Для начала я разберу роутер, чтобы определить какие порты, чипы и т. д. расположены на его плате:
Рисунок 2 — Материнская плата с компонентами wi-fi роутера
Из интересного было обнаружено:
Порт UART:
Рисунок 3 — UART порт
Чип 25Q127CSIG (SPI):
Рисунок 4 — Чип 25Q127CSIG
После внимательного изучения платы я подключил роутер к ноутбуку, используя UART порт, чтобы определить, какая информация по нему передается. Для этого я припаял провода к UART порту:
Рисунок 5 — Припаянные провода к UART порту
а другой конец подключил к PL2303:
Рисунок 6 — Подключение проводов к PL2303
Затем установил на Windows 7 драйвер PL2303 и Putty:
Рисунок 7 — Драйвер и Putty
Далее подключился к wi-fi роутеру с помощью Putty. Для этого необходимо проделать следующие шаги:
Включить wi-fi роутер.
Подключить PL2303 к ноутбуку:
Рисунок 8 — Подключение PL2303 к ноутбуку
Выбрать параметры в Putty и нажать «Open»:
Рисунок 9 — Выбор параметров Serial line = COM3(От компьютера к компьютеру может отличаться COM* порт), Speed = 115200, Connection type = Serial в Putty и нажатие «Open»
После нажатия кнопки «Open» в Putty, можно увидеть процесс загрузки прошивки wi-fi роутера, но есть проблема — нет возможности передать информацию с помощью Putty. В следствие чего я не могу повлиять на процесс загрузки прошивки, выбрав один из пунктов меню (Рисунок 10), а также нет интерфейса командной оболочки после завершения загрузки прошивки (Рисунок 11).
Рисунок 10. Пункты меню
Рисунок 11. Конец загрузки прошивки
Дамп прошивки
Чтобы решить проблему передачи информации с помощью Putty и последующего выбора одного из пунктов меню, я сделал дамп прошивки и изучил его. Итак, для дампа прошивки я подключил прищепку-коннектор к чипу 25Q127CSIG (SPI), как изображено на рисунке, красный провод к первой ноге чипа. Первая нога чипа там, где изображен круг на чипе 25Q127CSIG (SPI):
Рисунок 12 — Подключение прищепке-коннектор
, а другой конец прищепки-коннектора подключил к программатору EZP2019+ через переходник:
Рисунок 13 — Подключение другого конца прищепки-коннектора к EZP2019+
а сам EZP2019+ к ноутбуку:
Рисунок 14 — Подключение EZP2019+ к ноутбуку
Далее установил на Windows 7 драйвер для EZP2019+ и EZP2019+.exe:
Рисунок 15 — Драйвер и EZP2019+.exe
Затем запустил EZP2019+.exe и выбрал чип 25Q127C. Но так как его нет в списке, я взял ближайший к нему по характеристикам, под номером 25Q128C:
Рисунок 16 — Выбор чипа в EZP2019+.exe
Потом нажал на кнопку «READ» в программе EZP2019+.exe, дождался, когда прошивка считается, и сохранил в файл spi.bin.
Исследование прошивки
После получения дампа прошивки, я приступил к его исследованию. Начал с поиска места проверки вводимого через консоль числа, так как есть предположение, что пункт »3: Boot system code via Flash (default)» имеет константное значение, из-за чего я не могу выбрать любой другой пункт меню (Рисунок 17).
Рисунок 17 — Пункты меню
Когда я открыл файл spi.bin с помощью binwalk, меня заинтересовала строка «U-Boot version string, «U-Boot 1.1.3 (Aug 18 2020 — 11:10:29)» (Рисунок 18) по смещению 0×17DA0 от начала файла spi.bin. Эта строка указывает на то, что секция загрузчика в этой прошивке U-Boot.
Рисунок 18 — Открытие файла spi.bin с помощью binwalk
Далее нашел начало секции загрузчика U-Boot в файле spi.bin. Эту информацию я узнал, посмотрев на процессе загрузки прошивки wi-fi роутера в Putty. В момент загрузки прошивки wi-fi роутера, я увидел, что U-Boot от компании Ralink версии 5.0.0.0 (Ralink UBoot Version: 5.0.0.0). Поискав в интернете данную версию, я нашел проект на github (https://github.com/cidermole/ralink-uboot), в котором есть описание начала секции загрузчика U-Boot. Сверив свое начало файла с проектом на github, я пришел к выводу, что они совпадают (Рисунок 19). Значит это — начало секции загрузчика U-Boot в файле spi.bin по смещению 0×00000000.
Рисунок 19 — Начало секции
Следом я открыл файл spi.bin в IDA Pro, но перед тем, как это сделать, определил архитектуру (x86, x64, ARM, MIPS) файла spi.bin. Это можно сделать, взяв любой бинарный файл из файла spi.bin. Для этого воспользовался binwalk с параметрами –Me:
-M — рекурсивное сканирование извлеченных файлов.
-e — автоматическое извлечение известных типов файлов.
Рисунок 20 — binwalk
После выполнения команды binwalk –Me создается директория _spi.bin.extracted, в которой можно найти исполняемые файлы операционной системы Linux, одним из которых является wpad:
Рисунок 21 — wpad
Этот файл я открыл с помощью IDA Pro x86 и посмотрел, какие параметры выбирает IDA Pro:
Рисунок 22 — Открытие wpad в IDA Pro
Узнав, какие параметры выбирает IDA Pro в момент открытия файла wpad, я могу открыть файл spi.bin в IDA Pro x86 с такими же параметрами (Рисунок 23).
Рисунок 23 — Открытие spi.bin в IDA Pro
После того как я открыл файл spi.bin в IDA Pro, его необходимо разметить (преобразовать из байт кода в читабельный ассемблерный (assembler) код). Во-первых, я отсчитал от начала файла 0×1000 байт, чтобы не наткнуться на служебную область. Во-вторых, выделил несколько тысяч байт, например, с 0×1000 до 0×4000. Это необходимо для того, чтобы IDA Pro могла автоматически преобразовать из байт кода в ассемблерный код (Рисунок 24):
Рисунок 24 — Начало и конец выделенного участка
И нажал на клавиатуре «C», чтобы появилось диалоговое окно, и следом нажал на кнопку «Analyze»:
Рисунок 25 — Analyze
В результате получил ассемблерный код:
Рисунок 26 — Assembler code
Дальше необходимо понять, какой Imagebase (это базовый адрес загрузки программы) для того, чтобы IDA Pro могла создать перекрёстные ссылки (это информация о том, где в коде используется функция или строка), относящиеся к строкам и функциям. Это можно сделать, посмотрев на dword (Рисунок 27) или посмотреть в hex-rays (это функциональная возможность IDA Pro, позволяющая конвертировать assembler code в псевдо-код, наподобие языка программирования С) (Рисунок 28). Чтобы перейти в hex-rays, необходимо нажать на клавиатуре «F5».
Рисунок 27 — Поиск Imagebase в dword
Рисунок 28 — Поиск Imagebase в hex-rays
Из вышесказанного (Рисунок 27, Рисунок 28), можно сделать вывод, что Imagebase начинается с 0xBFC*, а вот четвертый байт я нашел перебором от 0 до 9. Правильный байт можно определить, посмотрев на строки, они должны преобразоваться в следующий вид и иметь перекрестные ссылки (Рисунок 29).
Рисунок 29 — Корректные строки
Теперь необходимо изменить Imagebase в IDA Pro. Для этого я перешёл в Edit → Segments → Rebase program… и изменил Imagebase на 0xBFC10000:
Рисунок 30 — Rebase program
Далее приступил к решению проблемы в передаче информации с помощью Putty и последующем выборе одного из пунктов меню. Начал я с поиска строки »3: Boot system code via Flash (default)» в файле spi.bin с помощью IDA Pro:
Рисунок 31 — Найденная строка в IDA Pro
Затем я нажал на aDBootSystemCod (Рисунок 32).
Рисунок 32 — Нажатие на aDBootSystemCod
и следом нажал на клавиатуре «X», затем появляется окно, в котором можно увидеть, где используется данная строка.
Рисунок 33 — Место использования строки «Boot system code via Flash (default).»
Потом нажал на строчку sub_BFC028C0+6C (Рисунок 33) и провалился в функцию sub_BFC028C0:
Рисунок 34 — Функция sub_BFC028C0
Дальше нажал на функцию sub_BFC028C0 (Рисунок 34), затем на клавиатуре «X» и посмотрел, куда ведёт эта функция. Она привела в место проверки введённого числа (Рисунок 35). Также из документации по U-Boot следует, что bootdelay — это количество секунд, данное на ввод числа, для выбора одного из пунктов. А вот описания boot_wait в документации не обнаружено.
Рисунок 35 — Место проверки введённого числа
Вернемся к проблеме, описанной выше. Я не мог передать информацию с помощью Putty и выбрать пункт меню, так как в коде есть константное значение (Рисунок 35 — строка 259) и нет возможности передачи информации роутеру с помощью Putty, потому что переменная v33 равна «off» (Рисунок 35 — строка 239). Исходя из этого есть два варианта: изменить константное значение на необходимое мне, или удалить «off». Я выбрал второй вариант, так как он позволит более гибко выбирать пункты меню (Рисунок 10) и удалил «off» в файле spi.bin:
Рисунок 36 — Удаление «off» в файле spi.bin
Перепрошивка роутера и получение командной оболочки Linux
Следом перепрошил wi-fi роутер полученным дампом прошивки. Для этого подключил прищепку-коннектор к чипу 25Q127CSIG (SPI), как было описано выше. Затем запустил EZP2019+.exe и выбрал чип 25Q128C. Потом нажал на кнопку «OPEN», выбрал файл spi_fix.bin. Далее нажал на кнопку «WRITE» и дождался, когда прошивка загрузится:
Рисунок 37 — Перепрошивка роутера
После загрузки прошивки я подключился к wi-fi роутеру с помощью Putty.exe и выбрал пункт »4: Entr boot command line interface» (Рисунок 38). Пункт 4 позволяет зайти в интерфейс командной оболочки загрузчика и используя командную оболочку загрузчика попасть в интерфейс командной оболочки Linux.
Рисунок 38 — Выбор пункта 4
Теперь необходимо разобраться, как из комодный оболочки U-Boot, получить командную оболочку Linux. Я начал с чтения документации по U-Boot, поскольку в ней есть описание переменной bootargs. В документации сказано, что содержимое этой переменной передается ядру Linux в качестве параметра загрузки. Далее я посмотрю в IDA Pro, где используется эта переменная:
Рисунок 39 — Код заполнения bootargs
После изучения кода, отвечающего за содержимое переменной bootargs, меня заинтересовали переменные (Рисунок 40), описание которых я не обнаружил в документации.
Рисунок 40 — Неизвестные переменные
Названия этих переменных наталкнули меня на мысль, что они отвечают за включение и отключение определенного функционала у роутера. Чтобы проверить эту гипотезу, я зашёл в командную оболочку U-Boot и посмотрел, чему равняются эти переменные (Рисунок 41), и поменял содержимое этих переменных на противоположные (Рисунок 42). Затем перезагрузил роутер командой «bootm».
Рисунок 41 — Содержимое переменных
Рисунок 42 — Изменение переменных
При загрузке прошивки wi-fi роутера я выбрал пункт »3: Boot system code via Flash (default)» и после окончания загрузки прошивки получил командную оболочку Linux:
Рисунок 43 — Выбор пункта 3 и получение командной оболочки Linux
Если кому-то стала интересна данная тема, то предлагайте свои идеи в комментариях, что можно посмотреть в прошивке или сделать с ней. Например, я мог бы посмотреть какую информацию отправляет роутер на сервера производителя, поискать бинарные уязвимости или уязвимости, связанные с web частью.