Анализ встроенного ПО маршрутизаторов: Эмуляция прошивки TP-Link, Часть 3
Корневая файловая система
Если вы скачали прошивку с официального сайта производителя или вы получили из способа, который показан во второй части нашего блога,и в целом, то ее легко извлечь командой binwalk -e firmware.bin, в качестве примера мы берем прошивку TP-Link WR841N V14 250328 US, чтобы наглядно показать, как она работает на самом деле.
После разархивирования и рекурсивного извлечения в файле firmware.bin.extracted мы видим несколько файлов ядра
ls
100200.squashfs 10400 10400.7z squashfs-root squashfs-root-0
Это извлеченная корневая файловая система из образа SquashFS. Инструмент unsquashfs создает этот каталог по умолчанию. Он содержит фактическое дерево корневой файловой системы Linux:/bin, /sbin, /etc, /www, /usr и т. д. Это та часть, которую вы анализируете для проверки скриптов, кода веб-интерфейса, двоичных файлов, конфигураций, паролей и т. д.
У нас есть несколько мест, которые мы должны пороверить: /usr/bin/httpd Этот двоичный файл соответствует внутренней работе с веб-сервисом, который дает администратору контроль, а также /etc/init.d/rcS начальный скрипт, который запускает скрипты и инициализирует маршрутизатор для правильной работы.
Эмуляция прошивки с помощью QEMU
Наверное, многие думают, что эмулировать не так уж и сложно, это кажется, что «просто можно эмулировать с помощью QEMU», уверяю вас, это сложнее, чем вы думаете. Давайте покажем это шаг за шагом
Что такое QEMU?
QEMU (Quick Emulator) — это эмулятор машины с открытым исходным кодом, который запускает программное обеспечение, разработанное для одной аппаратной архитектуры, на совершенно другой системе. В отличие от традиционных виртуальных машин, которые полагаются на собственные инструкции центрального процессора, QEMU может полностью эмулировать такие процессоры, как ARM, MIPS, PowerPC, x86, RISC-V и другие. Это делает его бесценным при анализе встраиваемых устройств, прошивки которых часто ориентированы на архитектуры, которые ваш ноутбук или сервер не поддерживает изначально.
Под капотом QEMU переводит инструкции гостевой архитектуры в инструкции хоста с помощью динамического двоичного транслятора, иначе говоря JIT. Он также эмулирует память, периферийные устройства, устройства хранения данных и сетевые интерфейсы, обеспечивая достаточную «поддельную аппаратную среду» для загрузки многих операционных систем (включая встроенные прошивки на базе Linux).
Поскольку QEMU имеет открытый исходный код, широко поддерживается и обладает высокой гибкостью, он стал стандартным инструментом для исследователей, реверс-инженеров и аналитиков безопасности, работающих со встроенными системами.
Как определить версию и архитектуру ядра?
strings 10400 | grep Linux
Linux version 2.6.36 (jenkins@sohoicilinux4) (gcc version 4.6.3 (Buildroot 2012.11.1) )
С помощью strings и grep мы получим точную версию Linux. Следующий шаг — определение архитектуры для точной эмуляции.
С помощью команды file мы получаем всю информацию о файле.
file bin/busybox
bin/busybox: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
file usr/bin/httpd
usr/bin/httpd: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
Вы можете загрузить все необходимые образы из этих источников:
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_wheezy_mipsel_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-2.6.32-5-4kc-malta
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta
При эмуляции прошивки маршрутизатора QEMU становится мостом между встроенным оборудованием и средой анализа. Команда, подобная приведенной ниже, может показаться сложной, но ее структура проста, как только вы поймете роль каждого компонента:
sudo qemu-system-mipsel \
-M malta \
-kernel vmlinux-2.6.32-5-4kc-malta \
-hda debian_squeeze_mipsel_standard.qcow2 \
-append "root=/dev/sda1 console=ttyS0 nokaslr" \
-net nic,model=e1000 \
-net user,hostfwd=tcp::8080-:80,hostfwd=tcp::8443-:443,hostfwd=tcp::2222-:22 \
-nographic \
-m 256M
И так, эта команда указывает QEMU на загрузку little-endian MIPS-системы с использованием платы Malta— платформы, которую ядра Linux поддерживают очень хорошо. Поставляемый файл vmlinux* — это скомпилированное ядро, которое будет работать внутри эмулятора, а образ диска QCOW2 выступает в качестве хранилища виртуальной машины. От него зависит и начальный образ RAM-диска (initrd).
Аргументы загрузки определяют, как стартует система:
root=/dev/sda1указывает ядру на корневую файловую систему,
console=ttyS0обеспечивает вывод всех данных на последовательную консоль,
nokaslrотключает рандомизацию памяти для облегчения отладки.
Работа с сетью осуществляется через виртуальную сетевую карту Intel e1000, сопряженную с сетевым стеком QEMU, работающим в пользовательском режиме. Перенаправление портов обеспечивает удобный доступ к сервисам внутри виртуальной машины с вашего хоста: HTTP на порту 8080, HTTPS на 8443 (как пример) и SSH на 2222. Запуск с параметром -nographic полностью исключает графическое окно и предоставляет чистый последовательный терминал, именно так общаются большинство встраиваемых систем. Память ограничена небольшим объемом в 256 МБ, что делает среду реалистичной для оборудования класса маршрутизаторов.
С помощью этих флагов QEMU превращается в полнофункциональный тестовый стенд MIPS, идеально подходящий для анализа прошивки, эмуляции сервисов и контролируемых экспериментов, не прикасаясь к реальному устройству.

Как показано на скриншоте, мы входим в систему с учетными данными root:root
Конечно, на файловой системе ничего нет, потому что мы не переносили никаких файлов из нашего пользовательского squashedfs в QEMU.
Прямая эмуляция отдельных частей прошивки
В редких случаях можно эмулировать командой бинарник (извлеченную прошивку), если он не имеет зависимостей, требующих уникальных библиотек или окружения:
Запуск бинарных файлов напрямую с помощью qemu-mipsel-static
qemu-mipsel-static -L squashfs-root/ squashfs-root/bin/sh
$ echo "worked" # worked
Или для конкретных программ, в редких случаях работает, в нашем случае нет
qemu-mips-static -L squashfs-root/ squashfs-root/usr/sbin/httpd
Способы перемещения файлов с хоста на VM.
К сожалению, вы не можете перетаскивать файлы, как в VirtualBox или VMware. В QEMU есть несколько безопасных способов перемещения файлов в VM.
SSH с переадресацией портов
Один из самых безопасных и простых способов перемещения файлов — это SSH.
Во-первых, убедитесь, что вы пробросили порт с VM на HOST с правильным флагом:
-net user ... hostfwd=tcp::2222-:22
И с помощью этой команды вы сможете подключиться к SSH:
ssh -p 2222 root@localhost -o HostKeyAlgorithms=+ssh-rsa
И с помощью команды перемещаем все файлы:
scp -r -P 2222 -o HostKeyAlgorithms=+ssh-rsa /home/somename/Projects/router/tplink/_firmware.bin.extracted/squashfs-root root@localhost:/root/firmware/
Использование файловой системы 9p (общая папка)
Вот конфигурация скрипта.
qemu-system-mipsel \
-M malta \
-kernel vmlinux-3.2.0-4-4kc-malta \
-append "nokaslr root=/dev/sda1" \
-hda debian_wheezy_mipsel_standard.qcow2 \
-virtfs local,path=/path/to/squashfs-root,mount_tag=host0,security_model=passthrough,id=host0 \
-net nic -net user \
-nographic
Взгляните на важную часть конфигурации файловой системы qemu 9p.
-virtfs local,path=/path/to/squashfs-root,mount_tag=host0,security_model=passthrough,id=host0 \
И заходим в QEMU:
mkdir /mnt/host
mount -t 9p -o trans=virtio,version=9p2000.L host0 /mnt/host
cp -r /mnt/host/* /tmp/firmware/
Примечание: Этот метод не поддерживается версией ядра, используемой в нашем тестовом примере; он предназначен для более современной версии ядра.
Прикрепление прошивки в качестве второго диска
Создайте образ диска с вашей прошивкой
dd if=/dev/zero of=firmware.img bs=1M count=200
mkfs.ext4 firmware.img
Смонтируйте и скопируйте прошивку
sudo mkdir -p /mnt/firmware-disk
sudo mount firmware.img /mnt/firmware-disk
sudo cp -r squashfs-root/* /mnt/firmware-disk/
sudo umount /mnt/firmware-disk
Запустите QEMU с подключенным диском с прошивкой
sudo qemu-system-mipsel \
-M malta \
-kernel vmlinux-3.2.0-4-4kc-malta \
-append "nokaslr root=/dev/sda1" \
-hda debian_wheezy_mipsel_standard.qcow2 \
-hdb firmware.img \
-net nic -net user \
-nographic
Подготовка среды для эмуляции
Перед запуском виртуальной машины мы должны подготовить сетевое окружение хоста, чтобы QEMU мог взаимодействовать с локальной машиной. QEMU взаимодействует с хостом через интерфейсы TUN/TAP, где /dev/net/tun отображается как дескриптор файла, а tap0 ведет себя как виртуальная сетевая карта, подключенная к сетевому стеку хоста. Чтобы поддержать это, мы создаем интерфейс моста (br0) на хосте, а затем подключаем к нему сетевую карту хоста и интерфейс TAP.
sudo apt-get install bridge-utils
sudo apt-get install uml-utilities
Настройте мост и подключите физический интерфейс (замените eno2 на реальную сетевую карту):
ifconfig eno2 down
brctl addbr br0
brctl addif br0 eno2
brctl stp br0 on
brctl setfd br0 2
brctl sethello br0 1
ifconfig br0 0.0.0.0 promisc up
ifconfig eno2 0.0.0.0 promisc up
dhclient br0
Вы можете проверить работу моста с помощью:
brctl show br0
brctl showstp br0
Далее создайте и настройте интерфейс TAP:
tunctl -t tap0
brctl addif br0 tap0
ifconfig tap0 0.0.0.0 promisc up
ifconfig tap0 192.168.1.1/24 up # subnet
Проверьте состояние моста:
brctl showstp br0
С этой сетевой настройкой QEMU может подключить виртуальную сетевую карту прошивки к tap0, обеспечивая реальное взаимодействие между эмулируемым маршрутизатором и вашей хост-системой, точно так же, как физический маршрутизатор вел бы себя в вашей сети.
А внутри виртуальной машины вам нужно назначить IP-адрес вручную, если DHCP его не присвоил.
brctl addbr br0
ifconfig br0 192.168.1.x/24 up # x должен принадлежать к подсети
Если мы откроем папку с прошивкой, которая была перенесена в /root/firmware в VM. Мы увидим, что все папки были полностью перенесены. Далее мы должны привязать каталоги VM /proc, /dev и /sys к файловой системе извлеченной прошивки.
mount -o bind /proc proc/
mount -o bind /sys sys/
mount -o bind /dev dev/
Как только эти системные пути будут правильно отображены, мы сможем переключиться в среду прошивки с помощью chroot
chroot squashfs-root/ /bin/sh
Вы, вероятно, думаете, что все хорошо, и мы готовы запустить скрипт из /etc/init.d/rcS и вручную запустить соответствующие сценарии запуска, чтобы вызвать службы пользовательского окружения. НО это не удастся. Так как каждая прошивка ведет себя по-разному; эти сценарии часто требуют корректировки для учета отсутствующих сетевых устройств, неработающих с вызововоми NVRAM и других причуд. Иногда на правильную эмуляцию уходят недели. И в процессе поиска решений для своих ошибок вы попадаете на GitHub Issues, где те баги, которык вы искали, они уже там обсуждались и были решены. А для себя вы открываете пару отличных инструментов, которые могут частично эмулировать вашу прошивку.
Firmadyne

Firmadyne может быть невероятно полезен. Это автоматизированный фреймворк, предназначенный для эмуляции прошивки устройств на базе Linux и поддерживающий архитектуры MIPS и ARM. Инструмент справляется с извлечением корневой файловой системы, угадывает сетевые интерфейсы, создает образ диска QEMU и даже эмулирует поведение NVRAM.
Если вы подбираете новую прошивку и хотите получить полную эмуляцию системы, стоит сначала попробовать Firmadyne. Вы сможете исправить некоторые ее причуды или ошибки, прежде чем прибегать к ручным методам эмуляции. Следует отметить, что новые версии QEMU иногда вызывают непредсказуемые проблемы. Запуск Firmadyne внутри Docker обычно позволяет обойти эти проблемы совместимости.
ARM-X

ARM-X — это еще один набор инструментов для эмуляции прошивки, но ориентированный на устройства на базе ARM. Он содержит набор ядер, скриптов и подготовленных файловых систем для загрузки ARM-прошивок в QEMU. Фреймворк также включает несколько примеров конфигураций, которые можно использовать в качестве стартовых шаблонов для различных устройств.
Эмуляция прошивки маршрутизатора TP-Link с помощью Firmadyne
Firmadyne автоматизирует эмуляцию прошивки маршрутизатора, автоматически выполняя извлечение, определение архитектуры, выбор ядра и настройку сети. Вот исправленный рабочий процесс.
Быстрая настройка
Установка зависимостей и клонирование Firmadyne
sudo apt-get update
sudo apt-get install -y busybox-static fakeroot git dmsetup kpartx netcat-openbsd \
nmap python3-psycopg2 python3-pip snmp uml-utilities util-linux vlan \
qemu-system-arm qemu-system-mips qemu-system-x86 qemu-utils postgresql
cd ~
git clone --recursive https://github.com/firmadyne/firmadyne.git
cd firmadyne
Конфигурация базы данных
Создайте пользователя PostgreSQL и базу данных (пароль: firmadyn).
sudo -u postgres createuser -P firmady
sudo -u postgres createdb -O firmadyne firmware
sudo -u postgres psql -d firmware < ./database/schema
Настройте пути к Firmadyne:
nano firmadyne.config
FIRMWARE_DIR=/home/yourusername/firmadyne/
Скачать готовые ядра
cd ~/firmadyne
./download.sh
Извлечение и эмуляция прошивки
Извлеките файловую систему прошивки:
python3 ./sources/extractor/extractor.py -b Netgear -sql 127.0.0.1 -np -nk \
"TL-WR841Nv14.bin" images
Определите архитектуру
./scripts/getArch.sh ./images/1.tar.gz
Сохранение файловой системы в базе данных
./scripts/tar2db.py -i 1 -f ./images/1.tar.gz
Создание образа диска QEMU:
sudo ./scripts/makeImage.sh 1
Определите конфигурацию сети и запустите эмуляцию
./scripts/inferNetwork.sh 1
sudo ./scratch/1/run.sh
Понимание каталога Scratch
После запуска makeImage.sh Firmadyne создает каталог scratch с идентификатором вашего образа. Структура выглядит следующим образом:
firmadyne/
├── scratch/
│ └── 1/ # ID образа
│ ├── run.sh # Скрипт для запуска эмуляции
│ ├── image.raw # Образ диска QEMU
│ └── ...
Доступ к эмулируемому маршрутизатору
После запуска sudo ./scratch/1/run.sh в выводе отображается конфигурация сети:
IP Address: 192.168.0.1
Web Interface: http://192.168.0.1
С другого терминала проверьте, доступен ли он:
ping 192.168.0.1
curl http://192.168.0.1
Альтернативный вариант в случае неудачи: Использование FirmAE
FirmAE — это улучшенная версия, которая лучше работает с современными прошивками:
git clone --recursive https://github.com/pr0v3rbs/FirmAE.git
cd FirmAE
# Установить ( устанавливает все зависимости)
./install.sh
# Запустить прошивку (одна команда выполняет все задачи)
./run.sh -r ~/TL-WR841Nv14_US_0.9.1_4.19_up_boot[250328-rel51324]_2025-03-28_14.16.58.bin
Если каталог не создан, проверьте, удалось ли выполнить makeImage.sh:
ls -la scratch/
Если извлечение не удалось, вручную извлеките с помощью binwalk:
binwalk -e TL-WR841Nv14*.bin
cd _TL-WR841Nv14*.extracted
tar -czf ../manual.tar.gz squashfs-root/
mv manual.tar.gz ~/firmadyne/images/1.tar.gz
Пример полного рабочего процесса
cd ~/firmadyne
# Извлеките ( обратите внимание на ID в выводе)
python3 sources/extractor/extractor.py -b TPLink -sql 127.0.0.1 -np -nk \
"TL-WR841Nv14.bin" images
# ID: 2
./scripts/getArch.sh ./images/2.tar.gz
./scripts/tar2db.py -i 2 -f ./images/2.tar.gz
sudo ./scripts/makeImage.sh 2
./scripts/inferNetwork.sh 2
# Запустите эмуляцию
sudo ./scratch/2/run.sh
firefox http://192.168.0.1
- extractor.py: Извлекает файловую систему с помощью binwalk и создает tarball в
images/
- getArch.sh: Определяет архитектуру процессора (mips, mipsel, armel)
- tar2db.py: Загружает метаданные файловой системы в базу данных PostgreSQL
- makeImage.sh: Создает загрузочный образ диска QEMU в
scratch/ID/
- inferNetwork.sh: Анализирует конфигурацию сети и создает сетевую настройку
- run.sh: Запускает QEMU с правильной конфигурацией ядра, сети и диска.
Ключевое отличие от ручной настройки QEMU заключается в том, что Firmadyne автоматизирует выбор ядра, создание сетевого моста и генерирует полную команду QEMU на основе обнаруженных характеристик прошивки. И вот, наконец, мы получили нашу эмуляцию:

А еще в Ghidra мы можем свободно реверсировать двоичные файлы из прошивки.

Заключение
В этой работе мы рассмотрели несколько подходов к эмуляции прошивок: от полностью ручных методов до частично автоматизированных решений. Мы прошли через настройку окружения, подготовку сетевой конфигурации, запуск системы через QEMU и разбор особенностей загрузочных скриптов. Также были показаны инструменты, такие как Firmadyne и ARM-X, которые могут упростить процесс и взять на себя часть рутинных задач.
В итоге мы получили общее понимание того, как можно эмулировать прошивку как вручную, так и с помощью специализированных фреймворков. Каждый из подходов имеет свои преимущества, и выбор зависит от конкретной цели исследования и особенностей устройства.
Анализ встроенного ПО маршрутизаторов: Введение, Часть 1
Анализ встроенного ПО маршрутизаторов: Способы извлечения прошивки из маршрутизатора, Часть 2