Реверс прошивок роутера

Реверс прошивок роутера

При разработке кастомных прошивок для роутера, часто сталкиваемся с необходимостью подделать подпись, чтобы загрузить прошивку через стандартный веб-интерфейс. Это требует понимания процесса проверки образа в стандартной прошивке. Давайте погрузимся в реверс прошивок роутера, используя роутер D-Link DIR-806A B1 в качестве примера и поймем, как работает проверка подписи.

Еще по теме: Как извлечь образ прошивки с помощью Binwalk

Реверс прошивок роутера

D-Link DIR-806A B1 имеет 8 Мбайт флеш-памяти и 64 Мб перативки. Работает на базе чипа MediaTek MT7620A, с архитектурой MIPS и поддерживаемого ядром Linux. Загрузка стандартной прошивки осуществляется через U-Boot, имеющий встроенный клиент TFTP для восстановления, если случайно загрузить неудачную прошивку. Главное — сохранить работоспособность загрузчика, иначе придется прибегнуть к пайке.

На мой взгляд, идеальное устройство для тестов. Однако, один из недостатков — в стандартной комплектации DIR-806A нет USB. Но на плате присутствуют контакты для USB, так что при достаточном уровне умений и сноровки, порт можно добавить самостоятельно.

Начнем с подключения к UART, поэтому убедитесь, что у вас есть преобразователь уровней для UART. При подключении не забудьте «перекрестить» RX и TX. То есть, RX подключаем к TX, а TX — к RX. Настройки соединения — 57600 8N1.

Реверс прошивок роутера

Подключились к UART. Давайте попробуем прошить нашу «жертву», при этом будем наблюдать за консолью. Возможно, там есть строки, которые помогут нам найти части кода, ответственные за процесс прошивки?

Успех! Роутер выводит в консоль сообщение о начале обновления и указывает раздел, куда записывается прошивка. При анализе будем искать строки, а по строкам — место в коде. Классический подход! Попробуем найти строку start… в прошивке:

Мы нашли утилиту fw_updater. Попробуем её запустить:

Кажется, именно она применяет новую прошивку в разделе Linux.

Если бы не было никакого текста, пришлось бы анализировать сам веб-интерфейс. Там обязательно есть сообщения, коды ошибок и т.д., которые затем можно искать. Оттуда же можно выйти на утилиты прошивки. Либо наугад поискать утилиты, в названиях которых есть слова fw, firmware, update и т.п. Если утилита найдена, остается только разобрать ее в IDA Pro, Ghidra, Radare2 или любом другом реверс-инжиниринговом инструменте.

Те­перь поп­робу­ем най­ти, отку­да fw_updater вызыва­ется в про­шив­ке:

Мы обна­ружи­ли, что fw_updater исполь­зует­ся в биб­лиоте­ке libdhal.so. Это очень любопыт­но. Поп­робу­ем взгля­нуть, что у нее внут­ри. Для ревер­са будем использовать Ghidra. Она поз­воля­ет пре­обра­зовать бинар­ный исполня­емый файл в код на С. Это очень удоб­но, и не при­дет­ся копать­ся в ассем­блер­ном лис­тинге.

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

В нашем слу­чае есть netcat. Переки­дыва­ем libdhal.so на компь­ютер:

Соз­даем про­ект в Ghidra и дизас­сем­бли­руем биб­лиоте­ку. Пос­ле бег­лого изу­чения нет­рудно най­ти фун­кцию с говоря­щим наз­вани­ем — check_firmware_in_buffer. Вот ее лис­тинг на С:

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

Пос­ле ана­лиза это­го кода при­ходим к выводу, что:

  • param_1 — ука­затель на буфер с фай­лом про­шив­ки;
  • param_2 — раз­мер буфера.

Взгля­нем вот на эту строч­ку:

Нет­рудно понять, что магичес­кое чис­ло рас­полага­ется в пос­ледних четырех бай­тах про­шив­ки и рав­но 0xc0ffee.

Те­перь раз­берем­ся с хешем:

Ви­дим, что хеш счи­тает­ся из мас­сива local_95 раз­мером 16 байт и фай­ла про­шив­ки (за исклю­чени­ем 20 байт в кон­це). 20 байт здесь — это раз­мер MD5 плюс 4 бай­та магичес­кого чис­ла. Мас­сив local_95 стро­ится из парамет­ра pcVar4, в котором содер­жится UUID устрой­ства.

Что про­исхо­дит в этом кус­ке кода:

Это кон­верта­ция бай­та из тек­сто­вого пред­став­ления в машин­ный код.

Са­мое вре­мя про­верить, так ли мы хороши. Напишем скрипт на Python для рас­чета MD5:

На вход скрипт при­нима­ет про­шив­ку. Резуль­тат выпол­нения ниже:

Срав­нив получен­ный хеш с исходной про­шив­кой по сме­щению 0x6c4750, понима­ем, что хеш рас­счи­тан пра­виль­но.

Реверс роутера

Те­перь мы лег­ко можем соз­дать про­шив­ку, которая будет заг­ружать­ся через сто­ковый веб‑интерфейс.

Хеш MD5, а тем более, как в нашем слу­чае, сло­жен­ный из UUID и обра­за, встре­чает­ся ред­ко. Кон­крет­ная реали­зация будет зависеть от про­изво­дите­ля, и тут кто во что горазд. Нап­ример, у оте­чес­твен­ных вен­доров вро­де SNR или Keenetic с этим про­ще. В SNR замени­ли рас­чет сум­мы CRC32 ядра на CRC32 всей про­шив­ки. А в Keenetic про­писы­вают в про­шив­ке магичес­кое чис­ло, CRC32 и ID устрой­ства.

Заключение

При­мер­но так же по слож­ности обсто­ят дела с про­шив­ками роуте­ров Xiaomi. Там тоже есть и минималь­ный раз­мер про­шив­ки, и магичес­кое чис­ло. Толь­ко вмес­то MD5 исполь­зует­ся RSA. В общем, как повезет. Но еще не встре­чалась под­пись, которую нель­зя было бы отре­вер­сить.

ПОЛЕЗНЫЕ ССЫЛКИ:

Дима (Kozhuh)

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

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