Анализ встроенного ПО маршрутизаторов: Способы извлечения прошивки из маршрутизатора, Часть 2
Способы извлечения прошивки из маршрутизатора
Извлечение прошивки, это первый реальный шаг в изучении любого роутера: имея бинарный дамп флеша, вы можете распаковать rootfs, посмотреть конфиги и поискать уязвимости. Существует несколько практик: самый простой, скачать официальную сборку с сайта вендора или перехватить образ во время обновления, но чаще приходится доставать содержимое прямо из платы. Для этого используются три основных аппаратных подхода: подключение к последовательной консоли (UART), чтение флеш-чипа через программатор (SPI/CH341A) и отладочный доступ через JTAG/OpenOCD. Все эти методы можно комбинировать например, остановить загрузку через UART и отдать команду загрузчику, чтобы тот переслал содержимое по TFTP, или прочитать образ напрямую со снятой микросхемы с помощью flashrom. Практически для каждой из этих техник есть отладочные утилиты и примеры команд, которые я приведу ниже и которые подходят для большинства бытовых роутеров.
Извлечение прошивки из маршрутизатора часто является первым шагом в обратном инжиниринге или исследовании уязвимостей. В зависимости от устройства и уровня защиты существует несколько практических методов — от простой загрузки до извлечения на аппаратном уровне.
Примечание: если у вас нет набора инструментов для извлечения прошивки из аппаратного обеспечения. Не беспокойтесь, в нашем тестовом случае мы используем прошивку, предоставленную производителем, с его сайта.
Способы извлечения прошивки:
— Загрузка прошивки непосредственно с официального сайта.
— JTAG-доступ (извлечение прошивки на аппаратном уровне.
— Дампинг чипа SPI-флеш-памяти (аппаратный уровень).
— Дамп через UART / последовательную консоль (уровень загрузчика)
Мы расмотрим только два способа:
Дампинг чипа SPI-флеш-памяти
Когда речь заходит о дампинге прошивки напрямую с флеш-чипа, чаще всего мы имеем в виду SPI-память. Практически все современные маршрутизаторы используют именно SPI-Flash: небольшой энергонезависимый чип, подключённый по последовательной шине SPI (Serial Peripheral Interface). Это крайне простой протокол: одна линия данных туда, одна обратно, линия тактирования и выбор микросхемы — тот набор, который идеально подходит для дешёвых и надёжных встраиваемых систем. Внутри такого чипа обычно хранится всё: загрузчик, ядро Linux, корневая файловая система и иногда заводские калибровочные данные Wi-Fi.
Дампим мы именно SPI-Flash потому, что это самый прямой способ получить прошивку в неизменённом виде. В отличие от UART или веб-админки, SPI не зависит ни от конфигурации роутера, ни от загрузчика, ни от паролей. Чип лежит на плате, и если добраться до его дорожек, можно вычитать из него весь содержимый образ, байт в байт.

Для работы большинство используют недорогой программатор CH341A. Это маленькая USB-плата, которая умеет общаться с разными типами памяти, а благодаря поддержке SPI подходит почти под любые флеш-чипы объёмом от 1 до 128 мегабайт. У него есть критический нюанс: по умолчанию CH341A выдаёт 5 V, но подавать их на SPI-чип роутера категорически нельзя. Почти все такие микросхемы рассчитаны строго на 3.3 V, и одно неверное подключение способно их сжечь. Поэтому перед тем как касаться роутера, нужно убедиться, что у вас есть версия CH341A с переключателем на 3.3 V или адаптер-понизитель напряжения.
На плате CH341A действительно есть отдельный стабилизатор на 3.3 V, но он по умолчанию питает только разъём для SPI-микросхемы, а сам чип CH341A продолжает висеть на 5 V. Поэтому модификация заключается в том, чтобы запитать CH341A тоже от 3.3 V.
Есть простой и безопасный способ исправить проблему с CH341A, когда он подаёт 5 V на флеш-чипы, которые рассчитаны только на 3.3 V. На плате программатора есть стабилизатор на 3.3 V, но он питает только разъём под микросхему SPI, а сам чип CH341A продолжает работать от 5 V. Из-за этого сигналы тоже остаются 5-вольтовыми, и флешки легко повредить.
Чтобы исправить это, нужно перебросить питание CH341A на 3.3 В. Вместо того чтобы поднимать ножку питания на чипе (это рискованно, её можно просто оторвать), делают более аккуратный вариант. На нижней стороне платы находится дорожка, по которой 5 V идут к микросхеме. Эту дорожку аккуратно перерезают и подают 3.3 V напрямую от стабилизатора. Провод припаивают к 28-й ножке чипа и к точке, которая соединена с 9-й ножкой. Есть фотографии и схема платы, по которым легко понять, где именно разрез и куда припаивать провод.

Задняя сторона:

После такой правки программатор полностью работает на 3.3 V. Теперь все контакты вокруг SPI-сокета тоже выдают 3.3 V, а не 5 V. Это безопаснее при работе с памятью, потому что меньше шансов по ошибке подать лишнее напряжение и сжечь чип.
Модификация делается быстро, никаких сложных навыков не требует, и после неё CH341A уже не угрожает флеш-микросхемам и работает строго в пределах их нормального питания. Этот процесс более подробно изложен здесь: https://wej.k.vu/electronics/ch341a-mini-programmer-fix/

Подключение выглядит довольно прямолинейно как на схеме: мы находим на плате сам SPI-чип (обычно это маленький восьминогий корпус SOIC8) и либо выпаиваем его, либо используем прищепку SOIC8, чтобы читать прямо на плате. В любом случае нам нужно соединить выводы питания, земли, и четыре SPI-сигнала: CLK, MOSI, MISO и CS#. Эти линии всегда подписаны в даташите на сам чип, поэтому перед перепрошивкой имеет смысл скачать PDF с распиновкой. Если всё подключено правильно и питание 3.3 V, программатор увидит микросхему без проблем.
Дальше всё можно сделать обычными консольными инструментами. Почти все используют утилиту flashrom, поскольку она поддерживает CH341A из коробки. Командная последовательность выглядит примерно так:
Подключите зажим → CH341A → USB
Запустите:
sudo flashrom -p ch341a_spi -r full_dump.bin
Проверить:
sudo flashrom -p ch341a_spi -v full_dump.bin
Если внутрисхемный доступ не удался (из-за помех по напряжению):
sudo flashrom -p ch341a_spi --noverify-all -r dump_partial.bin
Если все еще плохо: отпаяйте микросхему и читайте напрямую:
sudo flashrom -p ch341a_spi -r dump.bin
sudo flashrom -p ch341a_spi -r dump2.bin
Так мы читаем содержимое во внешний файл и получаем сырой дамп прошивки. Хорошей практикой считается прочитать его минимум дважды и сравнить контрольные суммы:
md5sum dump.bin md5sum dump2.bin
Если хэши совпадают, вы считали память корректно и без шумов на линиях. После этого можно уже разбирать образ binwalk’ом, восстанавливать файловые системы и исследовать прошивку.
Дамп через UART / последовательную консоль

UART — это стандартный последовательный интерфейс для обмена данными, встроенный во множество SoC и микроконтроллеров. В контексте роутеров и других встроенных устройств UART часто используется как отладочный / консольный порт. Он даёт доступ к логам загрузчика (чаще всего U-Boot) и иногда к командной строке самого загрузчика. Через консоль вы можете увидеть, как устройство стартует, и, если загрузчик позволяет использовать команды для копирования содержимого флеша в оперативную память и дальнейшей его передачи на ваш компьютер.
Для подключения вам понадобится:

— USB-TTL адаптер (например, FT232, CP2102, CH340 и др.) с уровнем логики 3.3 В (не RS-232 ±12 В!).
— Несколько проводков: только GND, RX, TX. Важно: не подключать питание (Vcc) адаптера к питанию роутера — это может повредить устройство.
— Терминальную программу на компьютере: screen, picocom, minicom.
Разбираем корпус роутера, ищем контакты UART (как на фото) часто это 3-4 пина, подписанные как GND, TX, RX (иногда VCC, но он не нужен). Такие пины встречаются на печатной плате почти у всех роутеров.

Подключаем GND ↔ GND, RX адаптера ↔ TX роутера, TX адаптера ↔ RX роутера. Ничего больше не подключаем — особенно не VCC.
Включаем адаптер к компьютеру, запускаем терминал, настраиваем порт. Например:
screen /dev/ttyUSB0 115200
Или:
picocom /dev/ttyUSB0 -b 115200
115200 используется по умолчанию, может быть другим, зависит от оборудования.
Есть роутеры, у которых UART пины могут быть выпаяны, запаяны, отключены, тогда логов не будет.
Скорость передачи данных зависит от аппаратного обеспечения; она может отличаться.
Нажмите Ctrl+C или любую клавишу во время загрузки, чтобы остановить автозагрузку.
Вы увидите что-то вроде:
U-Boot 1.1.4 (Jan 1 2010)
ar7240>
Дамп флэш-памяти с помощью команд U-Boot
Дамп данных с флэш-памяти в оперативную память
Пример чтения 4 МБ из флэш-памяти:
ar7240> nand read 0x81000000 0x000000 0x400000
0x81000000 = буфер ОЗУ, 0x000000 = смещение флэш-памяти, 0x400000 = размер (4 МБ).
Передача дампа на хост через TFTP
Установите TFTP-сервер на вашем компьютере, затем:
ar7240> setenv ipaddr 192.168.1.1
ar7240> setenv serverip 192.168.1.2
ar7240> tftp put 0x81000000 0x400000 flash_dump.bin
В некоторых загрузчиках нет возможности полного чтения nand, поэтому используется цикл:
ar7240> md.b 0x1f000000 0x10000
Дамп MTD-разделов через Linux Shell
Если маршрутизатор загружается полностью и предлагает оболочку:
cat /proc/mtd
Пример вывода:
mtd0: 00040000 00010000 "u-boot"
mtd1: 00200000 00010000 "kernel"
mtd2: 003c0000 00010000 "rootfs"
Дамп разделов:
dd if=/dev/mtd0 of=u-boot.bin
dd if=/dev/mtd1 of=kernel.bin
dd if=/dev/mtd2 of=rootfs.bin
Или все сразу:
dd if=/dev/mtdblock0 of=flash_complete.bin
Мы получили подходящую прошивку для анализа, в следующей части нашего блога мы будем эмулировать прошивку на QEMU.
Анализ встроенного ПО маршрутизаторов: Введение, Часть 1
Анализ встроенного ПО маршрутизаторов: Эмуляция прошивки TP-Link, Часть 3