Pull to refresh

Vertex Wireless VW210: редкий роутер и его внутренний мир

Reading time 15 min
Views 14K
Лирическое отступление: всё описанное в данной статье производилось исключительно в образовательных целях, цели извлечения материальной выгоды не преследовалось, ни одного котика в процессе (надеюсь) не пострадало. Всё, что здесь описано вы повторяете на свой страх и риск.
КДПВ курильщика (для тех, у кого дорогой трафик)

КДПВ курильщика (для тех, у кого дорогой трафик)

Несколько лет в глухой деревне трудится, не покладая рук, этот неуловимый Джо сетевой промышленности. Выбор пал на него, благодаря поддержке единственно рабочего решения для данной местности, а именно CDMA 450 от местного оператора «Сотел» (аля SkyLink). В отличии от других роутеров/модемов для данного стандарта того времени он единственный позволил добиться устойчивой связи с помощью какой-то матери и направленной антенны. Но вот беда: сайт производителя (а возможно и он сам) исчез с горизонта этих наших интернетов в далёком 2011 году. Осталось лишь пафосное видео на YouTube и упоминания их продуктов у разномастных продавцов и операторов.

КДПВ для ни в чём не ограничивающих себя читателей, хотя какое уж тут привлечение внимания, если вы уже здесь.
КДПВ для ни в чём не ограничивающих себя читателей, хотя какое уж тут привлечение внимания, если вы уже здесь.
Все последующие изображения кликабельны (кроме сказочного персонажа)

Мотивация


Вместе с сайтом и производителем покинули этот бренный мир и любые надежды на получение файлов прошивки и уж тем более открытия её исходных кодов, несмотря на требования GPL. Идея же получить более полный доступ к системе, чем это позволяет веб-интерфейс, появилась в голове давно и не давала покоя шаловливым рукам. А, благодаря вопросу на тостере (оригинальная страница приказала долго жить, но оставила след в веб-архиве) от ув. Nomad1 и вопреки его совету выкинуть данное недоразумение сетевой промышленности, незамедлительно было приведено в исполнение. На самом деле спасибо этому хабраюзеру и за первое, и за второе, т.к. это был прям вызов, после которого я с криком «Слабоумие и отвага!» пошёл в неравный бой с корейской технологической машиной образца 2009 года.

Софт


Первым делом я начал изучать веб-интерфейс, а точнее его внутренний мир. Благодаря дыре в использованной версии встраиваемого веб-сервера GoAhead, получилось скачивать исходный код страниц, добавляя к основной ссылке "/". Например по ссылке http://192.168.200.1/html/log.asp открывался результат работы скрипта log.asp, а по http://192.168.200.1/html/log.asp/ — исходный файл скрипта log.asp. Небольшим скриптом на баше было вытащено всё, что хоть как-то упоминалось в скриптах, но после анализа добытого стало понятно, что этой информации явно не достаточно для взлома.

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

Помимо 2-х уязвимостей в веб-сервере были найдены уязвимости в реализации uPnP сервера, которые приводили к переполнению буфера и выполнению кода, но их эксплуатация тоже требовала доступа к системе роутера.

Железо


Распрощавшись с надеждами на программный взлом, я перешёл к изучению железной части.
Железная часть роутера представляет из себя бутерброд из двух плат: модем и интерфейсы (сверху на фото) и процессорный блок (снизу на фото):

image

На обратной стороне процессорной части находится разъём mini-PCI в котором мирно покоится плата Wi-Fi:

image

Первичный осмотр пациента показал, что основными узлами данного устройства являются:

  • Qualcomm MSM6801A — процессор модема
  • Micrel KSZ8692PB — система на чипе (SoC) с сетью, PCI и другой полезной нагрузкой



Так как самую большую микросхему SoC мы выявили, нужно думать с какой стороны к ней подобраться. К сожалению, по какому-то нелепому совпадению, Micrel ушёл в закат также как и Vertex Wireless. Поиски хоть какой-то документации по данному чипу заводили в тупики на форумах, где инженера возмущались закрытости спецификаций и вообще на отсутствие документации в открытом доступе, на что милые менеджеры их приглашали обсудить это тет-а-тет. Но на помощь пришла The Wayback Machine, благодаря которой всё таки удалось завладеть документацией и прочими вкусностями для данного чипа.

UART


После изучения добытой документации стало понятно, что у нашего нового друга есть UART-интерфейсы в количестве 4-х штук, а также JTAG. Один из UART'ов скорее всего используется как отладочная консоль. Запустив терминал,

$ minicom -D /dev/ttyUSB0 -b 115200

я начал тыкать иглой, подключенной к конвертеру TTL-USB, в площадки отладочных точек на плате, периодически отправляя в перезагрузку роутер. И вот на очередной точке побежали в консоли заветные буковки… а на соседней буковки ответов. Это оказался UART для общения SoC с модемом. Теоретически лог обмена с модемом тоже представляет некоторый интерес, особенно учитывая отсутствие внятной документации на творение Qualcomm'а в свободном доступе, но у нас пока несколько другая цель.

Точки же UART'а отладочной консоли оказались с обратной стороны платы и закрывались второй платой «бутерброда», поэтому на их обнаружение ушло чуть больше времени.

image

Подпаиваемся к заветным контактам:

image

Лог загрузки
U-Boot 1.1.4 (November 6, 2008)

DRAM:  64 MB
Flash:  4 MB
In:    serial
Out:   serial
Err:   serial

## Booting image at 1c040000 ...
   Image Name:   Kernel-Ramdisk-Image
   Image Type:   ARM Linux Multi-File Image (uncompressed)
   Data Size:    3338960 Bytes =  3.2 MB
   Load Address: 00008000
   Entry Point:  00008000
   Contents:
   Image 0:  1609588 Bytes =  1.5 MB
   Image 1:  1729360 Bytes =  1.6 MB
   Verifying Checksum ... OK
OK
   Relocate RAMDISK from 0x1c1c8fc0 to 0xc00000 by 0x1a6350 bytes

Starting kernel ...

Uncompressing Linux.......................................................................................................... done, booting the kernel.
Linux version 2.6.23.17-Pegasus (gcc version 4.2.1)
CPU: ARM922T [41029220] revision 0 (ARMv4T), cr=c0007177
Machine: Micrel Pegasus
Memory policy: ECC disabled, Data cache writeback
Pegasus ID=8692  SubID=00  Revision=02
Clocks: System 166 MHz, CPU 166 MHz, DDR 166 MHz, PCI 33 MHz, IPsec 50 MHz
CPU0: D VIVT write-back cache
CPU0: I cache: 8192 bytes, associativity 64, 32 byte lines, 4 sets
CPU0: D cache: 8192 bytes, associativity 64, 32 byte lines, 4 sets
Built 1 zonelists in Zone order.  Total pages: 16256
Kernel command line: console=ttyAM0,115200
PID hash table entries: 256 (order: 8, 1024 bytes)
console [ttyAM0] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 59756KB available (3028K code, 259K data, 128K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
PCI: bus0: Fast back to back transfers disabled
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
Time: pegasus clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
Freeing initrd memory: 1688K
reset button handler is loaded
NetWinder Floating Point Emulator V0.97 (double precision)
NTFS driver 2.1.28 [Flags: R/O].
JFFS2 version 2.2. (NAND) �� 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered (default)
LED device driver is installed
Serial: Micrel Pegasus UART driver version: 2.6.1.0
ttyAM0 at MMIO 0x1fffe000 (irq = 45) is a Pegasus
ttyAM1 at MMIO 0x1fffe080 (irq = 49) is a Pegasus
ttyAM2 at MMIO 0x1fffe100 (irq = 52) is a Pegasus
ttyAM3 at MMIO 0x1fffe180 (irq = 55) is a Pegasus
RAMDISK driver initialized: 16 RAM disks of 16384K size 1024 blocksize
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
IMQ starting with 2 devices...
IMQ driver loaded successfully.
        Hooking IMQ after NAT on PREROUTING.
        Hooking IMQ before NAT on POSTROUTING.
30 = ffff ffff
Micrel Pegasus 1.0.0 (Oct 7, 2008)
physmap platform flash device: 00400000 at 1c000000
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
physmap-flash.0: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
cmdlinepart partition parsing not available
RedBoot partition parsing not available
Using physmap partition information
Creating 4 MTD partitions on "physmap-flash.0":
0x00000000-0x00030000 : "Boot Loader"
0x00030000-0x00040000 : "Loader Config"
0x00040000-0x003e0000 : "Linux RootFS"
0x003e0000-0x00400000 : "System Config"
pegasus-ehci pegasus-ehci: Pegasus-EHCI
pegasus-ehci pegasus-ehci: new USB bus registered, assigned bus number 1
pegasus-ehci pegasus-ehci: irq 8, io mem 0x1fffc000
pegasus-ehci pegasus-ehci: USB 0.0 started, EHCI 1.00, driver 10 Dec 2004
usb usb1: Product: Pegasus-EHCI
usb usb1: Manufacturer: Linux 2.6.23.17-Pegasus ehci_hcd
usb usb1: SerialNumber: KS8692
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
pegasus-ohci pegasus-ohci: new USB bus registered, assigned bus number 2
pegasus-ohci pegasus-ohci: irq 9, io mem 0x1fffd000
usb usb2: Product: Pegasus-OHCI
usb usb2: Manufacturer: Linux 2.6.23.17-Pegasus ohci_hcd
usb usb2: SerialNumber: ks8692
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 2 ports detected
usbcore: registered new interface driver cdc_acm
cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters
usbcore: registered new interface driver usbserial
drivers/usb/serial/usb-serial.c: USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic
drivers/usb/serial/usb-serial.c: USB Serial Driver core
Using Pegasus for AES algorithm.
Using Pegasus for DES algorithm.
u32 classifier
    Performance counters on
nf_conntrack version 0.5.0 (1024 buckets, 4096 max)
IPv4 over IPv4 tunneling driver
GRE over IPv4 tunneling driver
ip_tables: (C) 2000-2006 Netfilter Core Team
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
NET: Registered protocol family 15
Bridge firewalling registered
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 128K
Setting hostname ...
Mounting root fs rw ...
Mounting other filesystems ...
checksum f0d68bc4, tmp_checksum f0d68bc4
flash : Read from flash memory...
sysconf read 0x40070000
Checksum is f0d68bc4
flash : Wrote to flash memory...
br0: Dropping NETIF_F_UFO since no NETIF_F_HW_CSUM feature.
device eth1 entered promiscuous mode
time: 9628 ms
usb 2-1: new full speed USB device using pegasus-ohci and address 2
usb 2-1: device descriptor read/64, error -62
usb 2-1: Product: Qualcomm CDMA Technologies MSM
usb 2-1: Manufacturer: Qualcomm, Incorporated
usb 2-1: configuration #1 chosen from 1 choice
cdc_acm 2-1:1.0: ttyACM0: USB ACM device
br0: port 1(eth1) entering learning state
udhcpd (v0.9.9) started
Unable to open /etc/config/udhcpd.leases for reading
Unable to open /etc/config/udhcpd.assigned for reading
br0: topology change detected, propagating
br0: port 1(eth1) entering forwarding state
=>ATcommand Start 3

>>>Send : AT$ROUTERBOOTDONE
>>>Read : AT$ROUTERBOOTDONE=OK
command count 0

>>>Send : AT$TIME
>>>Read : AT$TIME=19800106000024

>>>Send : AT$PINSTAT

>>>Send : AT$TIME
Sun Jan  6 00:00:24 UTC 1980
command count 0
>>>Read : AT$DRC=0
cdmainfo.r_drc Null Rate
>>>Read : AT$RF=007d,007d
cdmainfo.r_rf = Rx1 007d
cdmainfo.r_rf = Rx2 007d
>>>Read : AT$CALLSTAT=0,0
cdmainfo.r_callstat = 1x Offline
cdmainfo.r_callstat = EVDO Inactive
>>>Read : AT$PINSTAT=NOCARD
pinstat 3
command count 0
>>>Read : AT$TIME=19800106000024
command count 0
>>>Read : AT$EVDOINFO=0,0,0,0,0,-31,0,0,0
>>>Read : AT$CDMAINFO=0,0,0,0,0,0,0,-31,0,0,9,9
rmmod: nf_nat_dnsproxy: Unknown error -1074267480
create_sysconf_linux_module 

>>>Send : AT$DRC=OK

>>>Send : AT$RF=OK

>>>Send : AT$CALLSTAT=OK

>>>Send : AT$EVDOINFO=OK
Sysinit done

>>>Send : AT$CDMAINFO=OK
login: >>>Read : AT$BOOTDONE

>>>Send : AT$BOOTDONE=OK
>>>Read : AT$RUIMREADDONE=NOCARD
pinstat 3

>>>Send : AT$RUIMREADDONE=OK

И вот мы попали в консоль, но система после загрузки просит авторизоваться и всякие там стандартные явки-пароли принимать наотрез отказывается, а загрузчик u-boot оказался собранным без возможности остановить загрузку и поуправлять ей. Путь последовательной консоли был для меня закрыт и я ушёл дальше… ну это, не считая дурацких попыток подбора пароля скриптом для minicom'а, которые были обречены на получение результата чуть позже, чем тот супер-компьютер скажет своё «42».

JTAG


Моё счастье, что все контакты JTAG-интерфейса чипа оказались крайними и были доступны для «прозвона» с использованием иглы:

image

Контакты JTAG на плате:

image

Однако собранный на коленке переходник из DB25-папы для LPT-порта, сопротивлений и соплей показал, что JTAG либо отключен, либо у кого-то кривые руки. Для второго варианта на небезызвестной торговой площадке поднебесной был заказан фабричный JTAG-переходник, но это долго. А в первом случае следует попробовать ввести SoC в какой-то тестовый режим с помощью игл, провода и тестовых точек, уходящих к ножкам TESTEN и TESTEN1.

Озарение


Но в этот момент в моей памяти всплыл старый хак, применяемый для принудительной прошивки всякого железа: вогнать железку в режим «сломанной прошивки», закорачивая ножки адреса на флешке с прошивкой. На нашей плате прошивка находится в микросхеме (Samsung K8P3215UQB www.bdtic.com/DataSheet/SAMSUNG/K8P3215UQB.pdf) под экраном рядом с процом.

image

Первые ножки данной микросхемы — это линии адреса и, закорачивая их, мы сможем нарушить вычитывание прошивки:

image

Так как нам хотелось бы попасть в меню u-boot'а, то шалить мы будем сразу после его загрузки в момент вычитывания остальной прошивки. Включаем роутер и после многозначительного моргания светодиодами и вывода на консоль текста:

U-Boot 1.1.4 (November 6, 2008)

DRAM:  64 MB
Flash:  4 MB
In:    serial
Out:   serial
Err:   serial
начинаем ласково коротить 1-2-3-4 ноги флешки отвёрткой, добиваясь заветного:
Bad Header Checksum
ks8692pb >

Ну вот мы и добились расположения от несговорчивого загрузчика.

Загрузчик


Давайте посмотрим, что умеет этот ветеран:

ks8692pb > help
? — alias for 'help'
autoscr — run script from memory
base — print or set address offset
bdinfo — print Board Info structure
boot — boot default, i.e., run 'bootcmd'
bootd — boot default, i.e., run 'bootcmd'
bootm — boot application image from memory
bootp — boot image via network using BootP/TFTP protocol
cmp — memory compare
coninfo — print console devices and information
cp — memory copy
cp — memory copy
crc32 — checksum calculation
dhcp — invoke DHCP client to obtain IP/boot params
echo — echo args to console
erase — erase FLASH memory
fatinfo — print information about filesystem
fatload — load binary file from a dos filesystem
fatls — list files in a directory (default /)
flinfo — print FLASH memory information
go — start application at address 'addr'
help — print online help
icrc32 — checksum calculation
iloop — infinite loop on address range
imd — i2c memory display
iminfo — print header information for application image
imls — list all images found in flash
imm — i2c memory modify (auto-incrementing)
imw — memory write (fill)
inm — memory modify (constant address)
iprobe — probe to discover valid I2C chip addresses
isf — i2s transmit waveform data file from memory address
isr — i2s receive waveform data to the memory address
isw — i2s transmit waveform data from memory address
itest — return true/false on integer compare
loadb — load binary file over serial line (kermit mode)
loads — load S-Record file over serial line
loady — load binary file over serial line (ymodem mode)
loop — infinite loop on address range
md — memory display
mdior register — read mdio register
mdiow register data — write mdio register
mii — MII utility commands
mm — memory modify (auto-incrementing)
mmcinit — init mmc card
mnand — copy to nand boot
mr — memory read and compare
mtest — simple RAM test
mw — memory write (fill)
nettest — network port load test
nfs — boot image via network using NFS protocol
nm — memory modify (constant address)
pci — list and access PCI Configuration Space
ping — send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect — enable or disable FLASH write protection
rarpboot- boot image via network using RARP/TFTP protocol
reset — Perform RESET of the CPU
run — run commands in an environment variable
saveenv — save environment variables to persistent storage
setenv — set environment variables
sleep — delay execution for some time
sspi — SPI utility commands
tftpboot- boot image via network using TFTP protocol
usb — USB sub-system
usbboot — boot from USB device
version — print monitor version
wait — wait for memory

Выглядит многообещающе, но на поверку оказывается, что часть команд не работает, не смотря на упоминание в help'е. В первую очередь хотелось бы знать как устроена адресация флешки:

ks8692pb > flinfo
Bank # 1: CFI conformant FLASH (16 x 16)  Size: 4 MB in 78 Sectors
 Erase timeout 8192 ms, write timeout 1 ms, buffer write timeout 1 ms, buffer size 1
  Sector Start Addresses:
    1C000000 (RO) 1C002000 (RO) 1C004000 (RO) 1C006000 (RO) 1C008000 (RO)
    1C00A000 (RO) 1C00C000 (RO) 1C00E000 (RO) 1C010000 (RO) 1C020000 (RO)
    1C030000 (RO) 1C040000      1C050000      1C060000      1C070000     
    1C080000      1C090000      1C0A0000      1C0B0000      1C0C0000     
    1C0D0000      1C0E0000      1C0F0000      1C100000      1C110000     
    1C120000      1C130000      1C140000      1C150000      1C160000     
    1C170000      1C180000      1C190000      1C1A0000      1C1B0000     
    1C1C0000      1C1D0000      1C1E0000      1C1F0000      1C200000     
    1C210000      1C220000      1C230000      1C240000      1C250000     
    1C260000      1C270000      1C280000      1C290000      1C2A0000     
    1C2B0000      1C2C0000      1C2D0000      1C2E0000      1C2F0000     
    1C300000      1C310000      1C320000      1C330000      1C340000     
    1C350000      1C360000      1C370000      1C380000      1C390000     
    1C3A0000      1C3B0000      1C3C0000      1C3D0000      1C3E0000     
    1C3F0000      1C3F2000      1C3F4000      1C3F6000      1C3F8000     
    1C3FA000      1C3FC000      1C3FE000

Области помеченные "(RO)" — это сам загрузчик. Трогать его пока совсем не тянет, так что пробегаем мимо него и останавливаем свой взгляд на остальных диапазонах.

Долгие и мучительные попытки сдампить содержимое флешки в нормальном виде закончились ВНЕЗАПНО перезаписанным после рестарта проца флешем. Оказалось, что при каких-то неизвестных условиях загрузчик после закачки через tftp файла отправлял процессор в резет, после которого на флешке автоматически начиналось стирание диапазона, где лежат образа ядра и ramdisk'а, а на их место начинает записываться загруженное. В моём случае это был наспех собранный образ OpenWRT от Micrel'я для данной платформы, который к боевой прошивке имеет такое же отношение как сантехник к балетмейстеру. Пытался то я его загрузить в память, но вышеописанная особенность загрузчика привела к записи этого бреда во флеш. Спасло то, что во первых не затёрся загрузчик, а во вторых у меня рядом лежала такая же боевая железка. В последствии дамп с боевой был водружён на подбитый тестовый экземпляр, но тогда было совсем не до смеха и кирпичи валились на пол непрерывным потоком, пока я пытался взять себя в руки.

Т.к. загрузчик никуда не делся, а на месте прошивки было не пойми что, прерванное на полпути во время записи, процедура немного «облегчилась»: теперь не нужно было ласкать отвёрткой ноги флешки, чтоб выйти на «Bad Header Checksum».
На еле дышащем полутрупе был найден единственный способ сдампить флешку — это команда md (memory display), которая выводит указанный участок памяти прямо в консоль в виде шестнадцатиричного текста:

ks8692pb > md 0x1c040000
1c040000: 56190527 8e2b9359 cd32444b d0f23200    '..VY.+.KD2..2..
1c040010: 00800000 00800000 6a1878c2 00040205    .........x.j....
1c040020: 6e72654b 522d6c65 69646d61 492d6b73    Kernel-Ramdisk-I
1c040030: 6567616d 00000000 00000000 00000000    mage............
1c040040: 748f1800 50631a00 00000000 e1a00000    ...t..cP........
1c040050: e1a00000 e1a00000 e1a00000 e1a00000    ................
1c040060: e1a00000 e1a00000 e1a00000 ea000002    ................
1c040070: 016f2818 00000000 00188f74 e1a07001    .(o.....t....p..
1c040080: e1a08002 e10f2000 e3120003 1a000001    ..... ..........
1c040090: e3a00017 ef123456 e10f2000 e38220c0    ....V4... ... ..
1c0400a0: e121f002 00000000 00000000 e28f00d0    ..!.............
1c0400b0: e890307e e0500001 0a00000a e0855000    ~0....P......P..
1c0400c0: e0866000 e08cc000 e0822000 e0833000    .`....... ...0..
1c0400d0: e08dd000 e5961000 e0811000 e4861004    ................
1c0400e0: e156000c 3afffffa e3a00000 e4820004    ..V....:........
1c0400f0: e4820004 e4820004 e4820004 e1520003    ..............R.

image
«Маловато будет!»
Оказывается кроме стартового адреса нужно ещё указывать второй параметр — размер.


Дамп


Для того, чтоб всё нажитое непосильным трудом не скрылось вместе с консолью minicom'а начинаем запись вывода в файл: нажимаем «Ctrl+a l» и подтверждаем имя файла, например стандартный «minicom.cap».

Нам нужен дамп области с 0x1c040000 по 0x1c3fffff (см. вывод flinfo). Получается блок размером 0x3c0000, но размер команда md (memory display) принимает не в байтах, а в 32-битных (4-байтовых) словах, таким образом нужное нам значение получается делением 0x3c0000 на 4 и равно 0xf0000. Вот что получается в итоге:

ks8692pb > md 1c040000 f0000


Уходим пить чай/кофе/со скуки, так как процедура вывода 3932160 байт в текстовом шестнадцатиричном виде в последовательную консоль — это печаль. После завершения процедуры слива нужно закрыть minicom (Ctrl+a x).

Копируем выхлоп minidump'а в файл с более осмысленным названием

$ cp ~/minicom.cap ./dump.hex

Придётся в него заглянуть и убрать лишние строки, которые были введены/выведены в minicom'е. В моём случае это одна строка в начале:

ks8692pb > md 1c040000 f0000

и одна в конце файла:

ks8692pb >

Конвертируем из текста в бинарные данные:

$ xxd -r -s-0x1c040000 dump.hex > dump.raw.bin

Смещение в -0x1c040000 необходимо, чтоб в итоговый файл не были записаны данные из диапазона 0x00000000-0x1c03ffff, которые xxd иначе посчитает пропавшими без вести и учтиво запишет в файл.

Выяснилось, что порядок байт в получившемся бинарнике не тот и пришлось искать решение как бы развернуть каждую четвёрку байт (32-битное слово). На просторах интернета быстро было найдено решение:

cat dump.raw.bin | perl -e 'while (sysread(STDIN,$d,4)){print pack("N",unpack("V",$d));}' > dump.bin

Вскрытие


Давайте посмотрим, что же у нас внутри дампа:

$ binwalk dump.bin
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0x59932B8E, created: 2010-01-06 06:50:53, image size: 3338960 bytes, Data Address: 0x8000, Entry Point: 0x8000, data CRC: 0xC278186A, OS: Linux, CPU: ARM, image type: Multi-File Image, compression type: none, image name: "Kernel-Ramdisk-Image"
14476         0x388C          gzip compressed data, maximum compression, from Unix, last modified: 2010-01-05 04:49:24
1609664       0x188FC0        gzip compressed data, has original file name: "ramdisk.img", from Unix, last modified: 2010-01-06 06:50:44

Интересно что, не смотря на маркировку на плате «2009-10-15», заводская прошивка имеет метку январь 2010 года. Видимо что-то «пошло не так» и готовую партия допиливали на ходу. Хорошо, что софт, а не железо… навесным монтажом.

Разделим нажитое на отдельные части:
заголовок

$ dd if=dump.bin of=uImageHeader ibs=1 count=14476

ядро (размер 1595188=1609664-14476)

$ dd if=dump.bin of=zImage ibs=1 skip=14476 count=1595188

образ ramdisk'а:

$ dd if=dump.bin of=initrd.gz ibs=1 skip=1609664 & gunzip initrd.gz

В последствии после редактирования ramdisk'а можно будет собрать всё обратно в одно целое командами:

$ cat uImageHeader > out.bin
$ cat zImage >> out.bin
$ gzip initrd & cat initrd.gz >> out.bin

Теперь нужно выяснить, что за файловая система используется:

$ sudo blkid -o value -s TYPE ./initrd
ext2

И примонтировать её куда нибудь для жестоких экспериментов:

$ mkdir rootfs
$ sudo mount -o loop -t ext2 ./initrd ./rootfs/

После недолгого изучения ФС находим:

$ sudo cat rootfs/etc/inittab
::sysinit:/etc/rc
::respawn:/bin/lgc_login

Первое, что приходит в голову — это «чего же тут захардкодили?»:

$ sudo strings rootfs/bin/lgc_login
/lib/ld-uClibc.so.0
liblgc.so
_DYNAMIC
__dso_handle
_init
_fini
_GLOBAL_OFFSET_TABLE_
printf
fgets
strlen
libc.so.0
stdout
getpass
fflush
abort
stdin
signal
execlp
__uClibc_main
strcmp
exit
__data_start
_edata
__bss_start
__bss_start__
_end
__bss_end__
__end__
login: 
password: 
admin
.admin.
GCC: (GNU) 3.3.2 20031005 (Debian prerelease)
GCC: (GNU) 2.95.4 20010319 (prerelease)
GCC: (GNU) 2.95.4 20010319 (prerelease)
GCC: (GNU) 2.95.4 20010319 (prerelease)
GCC: (GNU) 3.3.2 20031005 (Debian prerelease)
.shstrtab
.interp
.note.ABI-tag
.hash
.dynsym
.dynstr
.rel.dyn
.rel.plt
.init
.text
.fini
.rodata
.data
.dynamic
.ctors
.dtors
.got
.sbss
.bss
.comment

Ну здесь то уж достаточно иметь глаза, чтоб разглядеть пару логин/пароль «admin/.admin.» намертво зашитую в коде. Не стану томить — авторизация в последовательной консоли с этими данными прошла успешно.

После более детального изучения ФС выяснилось, что можно запустить команду, вообще никак не авторизуясь, например telnetd:

$ wget --post-data "cmd_key=%24telnetd%3b" "http://192.168.200.1/goform/ping_showpopup"

Он запустится, начнёт принимать подключения… но, к сожалению, не сможет нас авторизовать. Но это уже совсем другая история.

Спасибо ув. Nomad1 за пинок под мой ленивый зад, добрым людям, предоставившим полумёртный образец для нечеловеческих экспериментов, моей жене и дочерям за терпение, а моему пятилетнему сыну за помощь в перезагрузки роутера и запуске команд на компьютере, когда у папы заканчивались конечности.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+35
Comments 17
Comments Comments 17

Articles