Pull to refresh

Исследуем обфускацию прошивки Linksys WRT120N

Reading time 5 min
Views 19K
Original author: Craig
Недавно мое внимание привлек факт, что в обновлениях прошивок для Linksys WRT120N используют какую-то обфускацию. Мне показалось, что будет интересно порыться в ней, и я решил взглянуть.

Последняя версия прошивки не выглядит как прошивка, с которой можно сразу работать
image

Как вы можете видеть, есть небольшой блок данных, сжатых LZMA — это просто HTML-файлы для веб-интерфейса роутера. Большая часть прошивки состоит из каких-то странных, случайных данных. Т.к. мне больше ничего с ней не сделать, а любопытство все сильнее пыталось одолеть меня, я купил эту модель роутера себе (как они стоимость Amazon Prime-то взвинтили!).

Анализ железа

При первом же взгляде на железо стало видно, что WRT120N работает на Atheros AR7240 SoC, имеет 2MB SPI флеша, 32MB RAM и что-то похожее на Serial и JTAG-разводку:
image

Для того, чтобы поглубже взглянуть на процесс загрузки, я решил начать с последовательного порта.
image

Я уже ранее рассказывал про последовательные порты, поэтому не буду заострять внимание на методы нахождения пинов и скорости в этой статье. Было легко найти выводы порта с использованием мультиметра и визуального осмотра платы:
    Pin 2 – RX
    Pin 3 – TX
    Pin 5 – Ground

Порт работает на скорости 115200 бод и выдает интересную загрузочную информацию:
$ sudo miniterm.py /dev/ttyUSB0 115200
--- Miniterm on /dev/ttyUSB0: 115200,8,N,1 ---
--- Quit: Ctrl+]  |  Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---



=======================================================================
Wireless Router WG7005G11-LF-88 Loader v0.03 build Feb  5 2009 15:59:08
                    Arcadyan Technology Corporation
=======================================================================
flash MX25L1605D found.

Copying boot params.....DONE

Press Space Bar 3 times to enter command mode ...
Flash Checking  Passed.

Unzipping firmware at 0x80002000 ... [ZIP 3] [ZIP 1]  done
In c_entry() function ...
install_exception 
install exception handler ...
install interrupt handler ...
ulVal: 0x484fb
Set GPIO #11 to OUTPUT
Set GPIO #1 to OUTPUT
Set GPIO #0 to OUTPUT
Set GPIO #6 to INPUT
Set GPIO #12 to INPUT
Timer 0 is requested
##### _ftext      = 0x80002000
##### _fdata      = 0x80447420
##### __bss_start = 0x804D5B04
##### end         = 0x81869518
##### Backup Data from 0x80447420 to 0x81871518~0x818FFBFC len 583396
##### Backup Data completed
##### Backup Data verified
[INIT] HardwareStartup ..
[INIT] System Log Pool startup ...
[INIT] MTinitialize ..
CPU Clock 350000000 Hz
init_US_counter : time1 = 270713 , time2 = 40272580, diff 40001867
US_counter = 70
 cnt1 41254774 cnt2 41256561, diff 1787
Runtime code version: v1.0.04
System startup...
[INIT] Memory COLOR 0, 1600000 bytes ..
[INIT] Memory COLOR 1, 1048576 bytes ..
[INIT] Memory COLOR 2, 2089200 bytes ..
[INIT] tcpip_startup ..
Data size: 1248266
e89754967e337d9f35e8290e231c9f92
Set flash memory layout to Boot Parameters found !!!
Bootcode version: v0.03
Serial number: JUT00L602233
Hardware version: 01A

...


Похоже, прошивка сделана компанией Arcadyan, особенно интересно было сообщение ‘Unzipping firmware…’, быстрый гуглёж привел меня к посту про деобфускацию прошивок от Arcadyan, но тут, похоже, применяется немного другой метод.

Через последовательный порт можно только использовать меню загрузчика. Во время загрузки можно в него залезть, если нажать три раза пробел, и выполнить некоторые действия, такие как очистка флеша и установка настроек платы:
Press Space Bar 3 times to enter command mode ...123
Yes, Enter command mode ...


[WG7005G11-LF-88 Boot]:?

======================
 [U] Upload to Flash  
 [E] Erase Flash      
 [G] Run Runtime Code 
 [A] Set MAC Address 
 [#] Set Serial Number 
 [V] Set Board Version 
 [H] Set Options 
 [P] Print Boot Params 
 [I] Load ART From TFTP 
 [1] Set SKU Number 
 [2] Set PIN Number  
======================


К сожалению, загрузчик не позволял сдампить содержимое RAM или флеша. Хоть на плате и есть JTAG-разводка, я решил сдампить флеш напрямую, т.к. процесс дампа через JTAG, как правило, не быстрый, а подключение SPI очень простое.

Наверное любое устройство, которое поддерживает протокол SPI, может читать флеш. Я использовал кабель FTDI C232HM и программку spiflash.py из состава libmpsse
$ sudo spiflash --read=flash.bin --size=$((0x200000)) --verify
FT232H Future Technology Devices International, Ltd initialized at 15000000 hertz
Reading 2097152 bytes starting at address 0x0...saved to flash.bin.
Verifying...success.

Флеш состоит из трех LZMA-блоков и небольшого количества MIPS-кода, но сама прошивка все еще нехорошая:
image

Два первых LZMA-блока — часть recovery image, а MIPS-код это сам загрузчик. Все остальное место занимает обфусцированный файл прошивки, кроме нулей и каких-то данных в конце.

Анализ загрузчика

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

Сначала, на раннем этапе загрузки, загрузчик проверяет, не нажата ли кнопка reset. Если она нажата, то он загружает образ “Tiny_ETCPIP_Kernel” — маленький recovery image, с веб-интерфейсом.
image

Это хорошая новость. Теперь мы знаем, что если что-то пойдет не так в процессе обновления прошивки, то можно будет нажать reset и оживить устройство.
А есть еще и скрытый режим администратора в меню загрузчика:
image

Нажатие "!" приведет к включению режима администратора, который разблокирует некоторые опции, включая чтение и запись в память.

[WG7005G11-LF-88 Boot]:!

Enter Administrator Mode !

======================
 [U] Upload to Flash  
 [E] Erase Flash      
 [G] Run Runtime Code 
 [M] Upload to Memory 
 [R] Read from Memory 
 [W] Write to Memory  
 [Y] Go to Memory     
 [A] Set MAC Address 
 [#] Set Serial Number 
 [V] Set Board Version 
 [H] Set Options 
 [P] Print Boot Params 
 [I] Load ART From TFTP 
 [1] Set SKU Number 
 [2] Set PIN Number  
======================

[WG7005G11-LF-88 Boot]:

Самая интересная часть загрузчика, конечно же, та, которая загружает обфусцированную прошивку в память.

Анализ обфускации


Деобфускация выполняется в функции load_os, которой передается указатель на обфусцированный образ и адрес, куда следует поместить распакованный образ:
image
Сама распаковка не особо сложная:
image

В общем, если прошивка начинается с 04 01 09 20 (а наша именно с этих байт и начинается), то выполняется алгоритм расшифровки, который:
  • Переставляет два 32-байтных блока данных по адресам 0×04 и 0×68
  • Переставляет 4 бита у первых 32 байт, начиная с адреса 0×04
  • Побайтно переставляет смежные 32 байта, начиная с 0×04

После этого всего, данные по адресу 0×04 содержат верный LZMA-заголовок, которые потом разжимаются.

Реализовать утилиту деобфускации было просто, и прошивка WRT120N теперь может быть распакована и разжата.
$ ./wrt120n ./firmware/FW_WRT120N_1.0.07.002_US.bin ./deobfuscated.bin
Doing block swap...
Doing nibble-swap...
Doing byte-swap...
Saving data to ./deobfuscated.bin...
Done!

image
Анализ распакованной, но не разжатой прошивки

Если кому-то интересно, можете скачать утилиту для распаковки.
Tags:
Hubs:
+51
Comments 13
Comments Comments 13

Articles