Хабрахабр

[Перевод] Реверс-инжиниринг домашнего роутера с помощью binwalk. Доверяете софту своего роутера?

Несколько дней назад, я решил провести реверс-инжиниринг прошивки своего роутера используя binwalk.

Я купил себе TP-Link Archer C7 home router. Не самый лучший роутер, но для моих нужд вполне хватает.

Каждый раз когда я покупаю новый роутер, я устанавливаю OpenWRT. Зачем? Как правило производители не сильно заботятся о поддержке своих роутеров и со временем софт устаревает, появляются уязвимости и так далее, в общем вы поняли. Поэтому я предпочитаю хорошо поддерживаемую сообществом open-source прошивку OpenWRT.

Скачав себе OpenWRT, я так же скачал последний образ прошивки под мой новый Archer C7 с официального сайта и решил проанализировать его. Чисто ради фана и рассказать о binwalk.

Что такое binwalk?

Binwalk — это инструмент с открытым исходным кодом для анализа, реверс-инжиниринга и извлечения образов прошивок.

Созданный в 2010 году Крейгом Хеффнером, binwalk может сканировать образы прошивок и находить файлы, идентифицировать и извлекать образы файловой системы, исполняемый код, сжатые архивы, загрузчики и ядра, форматы файлов, такие как JPEG и PDF, и многое другое.

Вы можете использовать binwalk для реверс-инжиниринга прошивки для того, что бы понять как она устроена. Искать в бинарных файлах уязвимости, извлекать файлы и искать бекдоры или цифровые сертификаты. Можно так же найти opcodes для кучи разных CPU.

Вы можете распаковать образы файловой системы для поиска определенных файлов паролей (passwd, shadow и т.д.) И попытаться сломать хэши паролей. Вы можете выполнить двоичный анализ между двумя или более файлами. Вы можете выполнить анализ энтропии данных для поиска сжатых данных или закодированных ключей шифрования. Все это без необходимости доступа к исходному коду.

В общем все, что необходимо, есть 🙂

Как работает binwalk?

Основной особенностью binwalk является его сигнатурное сканирование. Binwalk может сканировать образ прошивки для поиска различных встроенных типов файлов и файловых систем.

Вы знаете утилиту командной строки file?

file /bin/bash/bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=12f73d7a8e226c663034529c8dd20efec22dde54, stripped

Команда fileсмотрит на заголовок файла и ищет подпись (магическое число), чтобы определить тип файла. Например, если файл начинается с последовательности байтов 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A, она знает, что это файл PNG. На Википедии есть список распространенных подписей файлов.

Binwalk работает так же. Но вместо того, чтобы искать подписи только в начале файла, binwalk будет сканировать весь файл. Кроме того, binwalk может извлечь файлы, найденные в образе.

Инструменты file и binwalk используют библиотеку libmagic для идентификации подписей файлов. Но binwalk дополнительно поддерживает список пользовательских магических сигнатур для поиска сжатых / заархивированных файлов, заголовков прошивок, ядер Linux, загрузчиков, файловых систем и так далее.

Давайте повеселимся?

Установка binwalk

Binwalk поддерживается на нескольких платформах, включая Linux, OSX, FreeBSD и Windows.

Чтобы установить последнюю версию binwalk, вы можете загрузить исходный код и следовать инструкции установки или краткому руководству, доступному на веб-сайте проекта.

У Binwalk много разных параметров:

$ binwalk Binwalk v2.2.0Craig Heffner, ReFirmLabshttps://github.com/ReFirmLabs/binwalk Usage: binwalk [OPTIONS] [FILE1] [FILE2] [FILE3] ... Signature Scan Options: -B, --signature Scan target file(s) for common file signatures -R, --raw=<str> Scan target file(s) for the specified sequence of bytes -A, --opcodes Scan target file(s) for common executable opcode signatures -m, --magic=<file> Specify a custom magic file to use -b, --dumb Disable smart signature keywords -I, --invalid Show results marked as invalid -x, --exclude=<str> Exclude results that match <str> -y, --include=<str> Only show results that match <str> Extraction Options: -e, --extract Automatically extract known file types -D, --dd=<type:ext:cmd> Extract <type> signatures, give the files an extension of <ext>, and execute <cmd> -M, --matryoshka Recursively scan extracted files -d, --depth=<int> Limit matryoshka recursion depth (default: 8 levels deep) -C, --directory=<str> Extract files/folders to a custom directory (default: current working directory) -j, --size=<int> Limit the size of each extracted file -n, --count=<int> Limit the number of extracted files -r, --rm Delete carved files after extraction -z, --carve Carve data from files, but don't execute extraction utilities -V, --subdirs Extract into sub-directories named by the offset Entropy Options: -E, --entropy Calculate file entropy -F, --fast Use faster, but less detailed, entropy analysis -J, --save Save plot as a PNG -Q, --nlegend Omit the legend from the entropy plot graph -N, --nplot Do not generate an entropy plot graph -H, --high=<float> Set the rising edge entropy trigger threshold (default: 0.95) -L, --low=<float> Set the falling edge entropy trigger threshold (default: 0.85) Binary Diffing Options: -W, --hexdump Perform a hexdump / diff of a file or files -G, --green Only show lines containing bytes that are the same among all files -i, --red Only show lines containing bytes that are different among all files -U, --blue Only show lines containing bytes that are different among some files -u, --similar Only display lines that are the same between all files -w, --terse Diff all files, but only display a hex dump of the first file Raw Compression Options: -X, --deflate Scan for raw deflate compression streams -Z, --lzma Scan for raw LZMA compression streams -P, --partial Perform a superficial, but faster, scan -S, --stop Stop after the first result General Options: -l, --length=<int> Number of bytes to scan -o, --offset=<int> Start scan at this file offset -O, --base=<int> Add a base address to all printed offsets -K, --block=<int> Set file block size -g, --swap=<int> Reverse every n bytes before scanning -f, --log=<file> Log results to file -c, --csv Log results to file in CSV format -t, --term Format output to fit the terminal window -q, --quiet Suppress output to stdout -v, --verbose Enable verbose output -h, --help Show help output -a, --finclude=<str> Only scan files whose names match this regex -p, --fexclude=<str> Do not scan files whose names match this regex -s, --status=<int> Enable the status server on the specified port

Сканирования образов

Начнем с поиска сигнатур файлов внутри образа (образ с сайта TP-Link).

Запуск binwalk с параметром --signature:

$ binwalk --signature --term archer-c7.bin DECIMAL HEXADECIMAL DESCRIPTION------------------------------------------------------------------------------------------21876 0x5574 U-Boot version string, "U-Boot 1.1.4-g4480d5f9-dirty (May 20 2019 - 18:45:16)"21940 0x55B4 CRC32 polynomial table, big endian23232 0x5AC0 uImage header, header size: 64 bytes, header CRC: 0x386C2BD5, created: 2019-05-20 10:45:17, image size: 41162 bytes, Data Address: 0x80010000, Entry Point: 0x80010000, data CRC: 0xC9CD1E38, OS: Linux, CPU: MIPS, image type: Firmware Image, compression type: lzma, image name: "u-boot image"23296 0x5B00 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 97476 bytes64968 0xFDC8 XML document, version: "1.0"78448 0x13270 uImage header, header size: 64 bytes, header CRC: 0x78A267FF, created: 2019-07-26 07:46:14, image size: 1088500 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0xBB9D4F94, OS: Linux, CPU: MIPS, image type: Multi-File Image, compression type: lzma, image name: "MIPS OpenWrt Linux-3.3.8"78520 0x132B8 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 3164228 bytes1167013 0x11CEA5 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 14388306 bytes, 2541 inodes, blocksize: 65536 bytes, created: 2019-07-26 07:51:3815555328 0xED5B00 gzip compressed data, from Unix, last modified: 2019-07-26 07:51:41

Теперь у нас много информации об этом образе.

Образ использует U-Boot в качестве загрузчика (заголовок образа по адресу 0x5AC0 и сжатый образ загрузчика по адресу 0x5B00). Основываясь на заголовке uImage по адресу 0x13270, мы знаем, что архитектура процессора — MIPS, а ядро Linux — версия 3.3.8. И на основании образа, найденного по адресу 0x11CEA5, мы можем видеть, что rootfs является файловой системой squashfs.

Давайте теперь распакуем загрузчик (U-Boot) с помощью команды dd:

$ dd if=archer-c7.bin of=u-boot.bin.lzma bs=1 skip=23296 count=4116241162+0 records in41162+0 records out41162 bytes (41 kB, 40 KiB) copied, 0,0939608 s, 438 kB/s

Поскольку образ сжато с помощью LZMA, нам нужно распаковать его:

$ unlzma u-boot.bin.lzma

Теперь у нас есть образ U-Boot:

$ ls -l u-boot.bin-rw-rw-r-- 1 sprado sprado 97476 Fev 5 08:48 u-boot.bin

Как насчет поиска дефолтного значения для bootargs?

$ strings u-boot.bin | grep bootargsbootargsbootargs=console=ttyS0,115200 board=AP152 rootfstype=squashfs init=/etc/preinit mtdparts=spi0.0:128k(factory-uboot),192k(u-boot),64k(ART),1536k(uImage),14464k@0x1e0000(rootfs) mem=128M

Переменная окружения U-Boot bootargs используется для передачи параметров ядру Linux. И из вышеприведенного мы лучше понимаем флэш-память устройства.

Как насчет извлечения образа ядра Linux?

$ dd if=archer-c7.bin of=uImage bs=1 skip=78448 count=10885721088572+0 records in1088572+0 records out1088572 bytes (1,1 MB, 1,0 MiB) copied, 1,68628 s, 646 kB/s

Мы можем проверить, что образ был успешно извлечен с помощью команды file:

$ file uImageuImage: u-boot legacy uImage, MIPS OpenWrt Linux-3.3.8, Linux/MIPS, Multi-File Image (lzma), 1088500 bytes, Fri Jul 26 07:46:14 2019, Load Address: 0x80060000, Entry Point: 0x80060000, Header CRC: 0x78A267FF, Data CRC: 0xBB9D4F94

Формат файла uImage — это в основном образ ядра Linux с дополнительным заголовком. Давайте удалим этот заголовок, чтобы получить окончательный образ ядра Linux:

$ dd if=uImage of=Image.lzma bs=1 skip=721088500+0 records in1088500+0 records out1088500 bytes (1,1 MB, 1,0 MiB) copied, 1,65603 s, 657 kB/s

Образ сжат, поэтому давайте распакуем его:

$ unlzma Image.lzma

Теперь у нас есть образ ядра Linux:

$ ls -la Image-rw-rw-r-- 1 sprado sprado 3164228 Fev 5 10:51 Image

Что мы можем сделать с образом ядра? Мы могли бы, например, сделать поиск по строкам в образе и найти версию ядра Linux и узнать об окружающей среде, используемой для сборки ядра:

$ strings Image | grep "Linux version"Linux version 3.3.8 (leo@leo-MS-7529) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Mon May 20 18:53:02 CST 2019

Не смотря на то, что прошивка была выпущена в прошлом году (2019 г.), когда я пишу эту статью, она использует старую версию ядра Linux (3.3.8), выпущенную в 2012 г., скомпилированную с очень старой версией GCC (4.6) также с 2012 г.!
(прим. перев. еще доверяете своим роутерам в офисе и дома?)

С опцией --opcodes мы также можем использовать binwalk для поиска машинных инструкций и определения архитектуры процессора образа:

$ binwalk --opcodes ImageDECIMAL HEXADECIMAL DESCRIPTION--------------------------------------------------------------------------------2400 0x960 MIPS instructions, function epilogue2572 0xA0C MIPS instructions, function epilogue2828 0xB0C MIPS instructions, function epilogue

Как насчет корневой файловой системы? Вместо того, чтобы извлекать образ вручную, давайте воспользуемся опцией binwalk --extract:

$ binwalk --extract --quiet archer-c7.bin

Полная корневая файловая система будет извлечена в подкаталог:

$ cd _archer-c7.bin.extracted/squashfs-root/ $ lsbin dev etc lib mnt overlay proc rom root sbin sys tmp usr var www $ cat etc/banner MM NM MMMMMMM M M $MMMMM MMMMM MMMMMMMMMMM MMM MMM MMMMMMMM MM MMMMM. MMMMM:MMMMMM: MMMM MMMMMMMMM= MMMMMM MMM MMMM MMMMM MMMM MMMMMM MMMM MMMMM'MMMM= MMMMM MMMM MM MMMMM MMMM MMMM MMMMNMMMMMMMMM= MMMM MMMMM MMMMM MMMM MMMM MMMMMMMMMMMM= MMMM MMMMMM MMMMM MMMM MMMM MMMMMMMMMMMMM= MMMM MMMMM, NMMMMMMMM MMMM MMMM MMMMMMMMMMMMMMM= MMMM MMMMMM MMMMMMMM MMMM MMMM MMMM MMMMMMMMMM= MMMM MM MMMM MMMM MMMM MMMM MMMM MMMMMMMM$ ,MMMMM MMMMM MMMM MMM MMMM MMMMM MMMM MMMM MMMMMMM: MMMMMMM M MMMMMMMMMMMM MMMMMMM MMMMMMM MMMMMM MMMMN M MMMMMMMMM MMMM MMMM MMMM M MMMMMMM M M M --------------------------------------------------------------- For those about to rock... (%C, %R) ---------------------------------------------------------------

Теперь мы можем сделать много разного.

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

С помощью qemu и chroot мы можем даже запустить (эмулировать) исполняемый файл из образа:

$ lsbin dev etc lib mnt overlay proc rom root sbin sys tmp usr var www $ cp /usr/bin/qemu-mips-static . $ sudo chroot . ./qemu-mips-static bin/busyboxBusyBox v1.19.4 (2019-05-20 18:13:49 CST) multi-call binary.Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenkoand others. Licensed under GPLv2.See source distribution for full notice. Usage: busybox [function] [arguments]... or: busybox --list[-full] or: function [arguments]... BusyBox is a multi-call binary that combines many common Unix utilities into a single executable. Most people will create a link to busybox for each function they wish to use and BusyBox will act like whatever it was invoked as. Currently defined functions: [, [[, addgroup, adduser, arping, ash, awk, basename, cat, chgrp, chmod, chown, chroot, clear, cmp, cp, crond, crontab, cut, date, dd, delgroup, deluser, dirname, dmesg, echo, egrep, env, expr, false, fgrep, find, free, fsync, grep, gunzip, gzip, halt, head, hexdump, hostid, id, ifconfig, init, insmod, kill, killall, klogd, ln, lock, logger, ls, lsmod, mac_addr, md5sum, mkdir, mkfifo, mknod, mktemp, mount, mv, nice, passwd, pgrep, pidof, ping, ping6, pivot_root, poweroff, printf, ps, pwd, readlink, reboot, reset, rm, rmdir, rmmod, route, sed, seq, sh, sleep, sort, start-stop-daemon, strings, switch_root, sync, sysctl, tail, tar, tee, telnet, test, tftp, time, top, touch, tr, traceroute, true, udhcpc, umount, uname, uniq, uptime, vconfig, vi, watchdog, wc, wget, which, xargs, yes, zcat

Здорово! Но обратите внимание, что версия BusyBox — 1.19.4. Это очень старая версия BusyBox, выпущенная в апреле 2012 года.

Таким образом, TP-Link выпускает образ прошивки в 2019 году с использованием программного обеспечения (GCC toolchain, kernel, BusyBox и т. Д.) 2012 года!

Теперь вы понимаете, почему я всегда устанавливаю OpenWRT на свои роутеры?

Это еще не все

Binwalk также может выполнять энтропийный анализ, печатать необработанные энтропийные данные и генерировать энтропийные графики. Обычно большая энтропия наблюдается, когда байты в образе случайны. Это может означать, что образ содержит зашифрованный, сжатый или обфусцированный файл. Хардкорно прописанный ключ шифрования? Почему бы и нет.

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

Пользовательские сигнатуры могут быть добавлены в binwalk либо через файл пользовательских сигнатур, указанный в командной строке с помощью параметра --magic, либо путем добавления их в каталог $ HOME / .config / binwalk / magic.

Вы можете найти больше информации о binwalk в официальной документации.

Расширение binwalk

Существует API-интерфейс binwalk, реализованный в виде модуля Python, который может использоваться любым скриптом Python для программного выполнения сканирования binwalk, а утилита командной строки binwalk может быть почти полностью продублирована всего двумя строками кода Python!

import binwalkbinwalk.scan()

С помощью Python API вы также можете создавать плагины под Python для настройки и расширения binwalk.

Также существует плагин IDA и облачная версия Binwalk Pro.

Так почему бы вам не скачать образ прошивки из Интернета и не попробовать binwalk? Обещаю, вам будет очень весело 🙂

Показать больше

Похожие публикации

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»