Изменение прошивки вручную
Стандартная прошивка маршрутизаторов Asus SL500/1000 позволяет нам задавать через консоль arp-таблицу, однако эта таблица теряется при перезагрузке. В качестве операционной системы для SL выбран Linux, однако, в устройстве он расположен на read-only разделах, что несколько осложняет конфигурацию. Выходом из сложившейся ситуации является изменение официальной прошивки, которую можно взять на сайте производителя. Поскольку у меня для экспериментов был маршрутизатор SL500, то и изменять прошивку я буду для него, хотя для SL1000 всё аналогично. Для экспериментов была выбрана прошивка SL500_1_1_72A_410, находящаяся в одноимённом файле SL500_1_1_72A_410.bin. Посмотрим на структуру этого файла. В качестве программы для редактирования прошивки был использован WinHEX 12.85 SR-10.
big endian 000-001 - 0000 002-003 - 91CF (depends on the device and firmware version (proprietary CRC)) 004-01F - BE73 1504 0000 0003 0002 0000 0000 0000 0000 0000 0040 0000 0100 0000 020-027 - 534C 3530 3000 0000 (device name SL500) 028-29F - 0000 2A0-2AB - 16 bit 3,2,3,0,0,B 2AC-309 - 0000 30A-329 - first file header 32A-349 - second file header 34A-369 - third file header 36A-487 - 0000 0488-...filesСлева указано смещение в шестнадцатеричной системе от начала файла, а справа – содержимое прошивки. Заголовок файла представляет собой структуру, содержащую информацию о файле (смещение начала файла, длина, номер файла).
u16 file number (1..3) u32 displacement from the beginning of the file u16 flag (00 for the first file, 01 for the second one and 3E for the third (last) one) u16 0000 u32 file length or 0 for EOF u144 18 zero-bytes;Приведём заголовки трёх файлов в шестнадцатеричном виде.
0001 0000 0488 0000 0000 0000 F9A0 0000 0000 0000 0000 0000 0000 0000 0000 0000
0002 0000 FE28 0001 0000 003A 6000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0003 003B 5E28 003E 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Первый файл в данном случае малоинтересен. Третий тоже. А второй как раз и содержит образ файловой системы, которая необходима для дальнейшей обработки. Поэтому выделяю из прошивки часть со смещения FE28 и до конца файла.
Полученный файл представляет собой сжатый образ файловой системы устройства. Сначала требуется извлечь файлы из этого образа, то есть распаковать их из cramfs. Файловая система содержит жёсткие линки, поэтому извлечение образа под Windows невозможно. Было принято решение установить Linux в виртуальной машине для того, чтобы извлечь файлы, изменить их и собрать в образ обратно. В качестве программной виртуальной машины была установлена VMware Workstation (5.5.1 build 19175). В виртуальную машину была установлена операционная система Linux Fedora Core 5 (ядро 2.6.15).
Теперь требуется подготовить всё необходимое, чтобы собрать утилиту для извлечения. В качестве ПО для работы с файловой системой была взята реализация cramfs-1.1. Кроме этого в этот же каталог пришлось установить zlib-1.2.3. Сложность извлечения состояла в том, что ПК и маршрутизатор имеют различную эндианность. Для преодоления указанной трудности пришлось воспользоваться изменённым Игорем Нестеровым файлом cramfsck.c, с которым были собраны необходимые утилиты.
[root@localhost firmware]# pwd /fox/firmware [root@localhost firmware]# ls 2.bin cramfsck.c gzio.c inftrees.h projects zconf.in.h adler32.c cramfsck.c~ image0 linux qnx zlib.3 algorithm.txt crc32.c INDEX Makefile README zlib.h amiga crc32.h infback.c Makefile.in text zutil.c as400 deflate.c inffast.c make_vms.com text~ zutil.h ChangeLog deflate.h inffast.h minigzip.c trees.c compress.c example.c inffixed.h mkcramfs.c trees.h configure examples inflate.c msdos uncompr.c contrib FAQ inflate.h NOTES win32 COPYING GNUmakefile inftrees.c old zconf.h [root@localhost firmware]# ./configure Checking for gcc... Building static library libz.a version 1.2.3 with gcc. Checking for unistd.h... Yes. Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf() Checking for vsnprintf() in stdio.h... Yes. Checking for return value of vsnprintf()... Yes. Checking for errno.h... Yes. Checking for mmap support... Yes. [root@localhost firmware]# make gcc -W -Wall -O2 -g -I. mkcramfs.c -lz -o mkcramfs mkcramfs.c: In function ‘parse_directory’: mkcramfs.c:287: warning: pointer targets in assignment differ in signedness mkcramfs.c: In function ‘write_superblock’: mkcramfs.c:399: warning: pointer targets in passing argument 1 of ‘__builtin_strncpy’ differ in signedness mkcramfs.c:401: warning: pointer targets in passing argument 1 of ‘__builtin_strncpy’ differ in signedness mkcramfs.c: In function ‘write_directory_structure’: mkcramfs.c:480: warning: pointer targets in passing argument 1 of ‘strlen’ differ in signedness mkcramfs.c: In function ‘do_compress’: mkcramfs.c:598: warning: pointer targets in passing argument 1 of ‘compress2’ differ in signedness mkcramfs.c:598: warning: pointer targets in passing argument 3 of ‘compress2’ differ in signedness mkcramfs.c: In function ‘write_data’: mkcramfs.c:647: warning: pointer targets in passing argument 3 of ‘do_compress’ differ in signedness mkcramfs.c: In function ‘main’: mkcramfs.c:825: warning: pointer targets in passing argument 2 of ‘crc32’ differ in signedness gcc -W -Wall -O2 -g -I. cramfsck.c -lz -o cramfsck [root@localhost firmware]# ls 2.bin cramfsck GNUmakefile inftrees.c NOTES win32 adler32.c cramfsck.c gzio.c inftrees.h old zconf.h algorithm.txt cramfsck.c~ image0 linux projects zconf.in.h amiga crc32.c INDEX Makefile qnx zlib.3 as400 crc32.h infback.c Makefile.in README zlib.h ChangeLog deflate.c inffast.c make_vms.com text zutil.c compress.c deflate.h inffast.h minigzip.c text~ zutil.h configure example.c inffixed.h mkcramfs trees.c contrib examples inflate.c mkcramfs.c trees.h COPYING FAQ inflate.h msdos uncompr.c [root@localhost firmware]#Теперь нужно воспользоваться собранными утилитами для извлечения файлов из ободранной прошивки в каталог /fox/extraction. Лишнее перечисление извлечённых файлов здесь не приводится.
[root@localhost firmware]# ./cramfsck usage: ./cramfsck [-hv] [-x dir] file -h print this help -x dir extract into dir -v be more verbose file file to test [root@localhost firmware]# ./cramfsck -v -x /fox/extraction 2.bin SS 13 warning: old cramfs format d 0755 344 0:0 /fox/extraction d 0755 392 0:0 /fox/extraction/bin l 0777 8 0:0 /fox/extraction/bin/bash -> /bin/msh f 0755 166484 1011:104 /fox/extraction/bin/busybox l 0777 8 0:0 /fox/extraction/log -> /tmp/log l 0777 17 0:0 /fox/extraction/firewall.cfg -> /tmp/firewall.cfg f 0755 999060 0:0 /fox/extraction/cpu1 d 0755 0 0:0 /fox/extraction/ramfs f 0755 1699436 0:0 /fox/extraction/vmlinux 2.bin: OK [root@localhost firmware]# ls 2.bin cramfsck GNUmakefile inftrees.c NOTES win32 adler32.c cramfsck.c gzio.c inftrees.h old zconf.h algorithm.txt cramfsck.c~ image0 linux projects zconf.in.h amiga crc32.c INDEX Makefile qnx zlib.3 as400 crc32.h infback.c Makefile.in README zlib.h ChangeLog deflate.c inffast.c make_vms.com text zutil.c compress.c deflate.h inffast.h minigzip.c text~ zutil.h configure example.c inffixed.h mkcramfs trees.c contrib examples inflate.c mkcramfs.c trees.h COPYING FAQ inflate.h msdos uncompr.c [root@localhost firmware]# cd .. [root@localhost fox]# ls cramfs-1.1 extraction firmware zlib-1.2.3 [root@localhost fox]# cd extraction [root@localhost extraction]# ls bin dev firewall.cfg home lib mnt proc root tmp var cpu1 etc flash0 jffs2 log opt ramfs sbin usr vmlinux [root@localhost extraction]#Автоматически запускаемым скриптом оказался файл GOCstartup из каталога /etc/init.d, поэтому всё необходимое для автозагрузки было размещено именно в этом файле. В его начало были вставлены строки об авторе изменений, а в конец добавлены необходимые команды для извлечения другого скрипта, изменения его параметров и запуска извлечённого.
echo "Start my part."echo "Extracting file fox.script..." rfcutil xtract /tmp/fox.script fox.script echo "Changing script (fox.script) rights..." chmod 777 /tmp/fox.script echo "Runing script (fox.script)..." /tmp/fox.script echo "End my part."Сложность всей схемы загрузки обусловлена тем, что всё запускаемое системой расположено на разделе с доступом только для чтения. Файлы логов и параметров (пользовательских настроек) сохранены в области с доступом для чтения и записи, но загрузка оттуда не производится. В связи с тем, что реальные условия работы сети требуют достаточно частого изменения нужных параметров, было принято решение основной скрипт разместить в read-only области, а затем извлекать и запускать из него другой скрипт, который можно изменять без перепрошивки устройства. Такая схема также позволяет дополнять функциональность маршрутизатора без трудоёмкого изменения прошивки.
Теперь необходимо собрать образ файловой системы, что можно осуществить с помощью уже собранной утилиты mkcramfs.
[root@localhost firmware]# ./mkcramfs --help ./mkcramfs: invalid option -- - usage: ./mkcramfs [-h] [-e edition] [-i file] [-n name] dirname outfile -h print this help -E make all warnings errors (non-zero exit status) -e edition set edition number (part of fsid) -i file insert a file image into the filesystem (requires >= 2.4.0) -n name set name of cramfs filesystem -p pad by 512 bytes for boot code -s sort directory entries (old option, ignored) -v be more verbose -z make explicit holes (requires >= 2.3.39) dirname root of the directory tree to be compressed outfile output file [root@localhost firmware]# ./mkcramfs /fox/extraction /fox/foxware.bin Directory data: 9008 bytes Everything: 3728 kilobytes Super block: 76 bytes CRC: ffadf25 [root@localhost firmware]# ls 2.bin cramfsck GNUmakefile inftrees.c NOTES win32 adler32.c cramfsck.c gzio.c inftrees.h old zconf.h algorithm.txt cramfsck.c~ image0 linux projects zconf.in.h amiga crc32.c INDEX Makefile qnx zlib.3 as400 crc32.h infback.c Makefile.in README zlib.h ChangeLog deflate.c inffast.c make_vms.com text zutil.c compress.c deflate.h inffast.h minigzip.c text~ zutil.h configure example.c inffixed.h mkcramfs trees.c contrib examples inflate.c mkcramfs.c trees.h COPYING FAQ inflate.h msdos uncompr.c [root@localhost firmware]# cd .. [root@localhost fox]# ls cramfs-1.1 extraction firmware foxware.bin zlib-1.2.3 [root@localhost fox]#Так как модернизирована была лишь разбирающая утилита, то необходимо «перевернуть» собранный образ файловой системы. В стандартной поставке Fedora Core 5 не было обнаружено утилиты для преобразования cramfs, поэтому данная утилита была перенесена из системы Debian и носит название cramfsswap.
[root@localhost firmware]# ./cramfsswap Usage: ./cramfsswap <in> <out>> [root@localhost firmware]# ./cramfsswap /fox/foxware.bin /fox/foxware_swapped.bin Filesystem is in hostorder. Filesystem contains 392 files. CRC: 0xa95c730f [root@localhost firmware]# cd .. [root@localhost fox]# ls cramfs-1.1 extraction firmware foxware.bin foxware_swapped.bin zlib-1.2.3 [root@localhost fox]#Полученный файл foxware_swapped.bin и является готовым образом файловой системы, который необходимо вставить в прошивку вместо старого образа. Для этого необходимо к части оригинальной прошивки с выдранным оригинальным образом дописать изменённый образ файловой системы. Данную операцию можно произвести уже под Windows с использованием WinHex.
Однако простой замены блока данных с образом файловой системы недостаточно. Необходимо поправить также заголовки файлов. Как упоминалось ранее, в прошивке находятся заголовки трёх файлов, второй из которых и представляет файловую систему. Изменения в заголовках должны быть следующими: длина второго файла должна соответствовать действительности (вместо 3A6000 должно теперь быть 3A4000), смещение третьего файла должно также быть изменено со значения 3B5E28 на 3B3E28. Изменённые заголовки файлов приведены ниже.
0001 0000 0488 0000 0000 0000 F9A0 0000 0000 0000 0000 0000 0000 0000 0000 0000 0002 0000 FE28 0001 0000 003A 4000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0003 003B 3E28 003E 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Остаются два не менее важных шага по подготовке самого файла прошивки. Как отмечалось ранее 3 и 4 байты прошивки содержат контрольную сумму всего файла, правда, понять, как именно она считается, не удалось. Однако выйти из сложившейся ситуации всё-таки можно. Для этого необходимо попытаться залить прошивку с использованием протоколов FTP или TFTP, а уже существующая версия прошивки подсчитает контрольную сумму и напишет её. Для этой операции был поднят TFTP-сервер от компании 3COM (3CServer 1.1.007). Это бесплатная утилита, которая элементарна в настройке. Ниже приводится лог команд и ответов устройства.
SL500(config)# upgrade tftp 192.168.1.3 foxware.bin Shutting down Event-Manager and Syslogd [ OK ] Successfully created and tested attach to shared memory block for software package ##Package Information: CRC = 0x91cf Magic No. = 0xbe731504 Min-Max Config. Size = 0x20000 noConfigBackup Flag = 0 Minimum Flash = 0x400000 Minimum RAM = 0x1000000 Version = LX_3.2.3_Comp_0_0_0_b Components = IRB, QoS, FW ##Models Supported: SL500 ## ##Images: BOOT: Offset [Package = 1160, Flash = 0x0], Size = 63904 CRAMFS: Offset [Package = 65064, Flash = 0x10000], Size = 3817472 CONFIG: Offset [Package = 3882536, Flash = 0x3e0000], Size = 0 ## ## Invalid package CRC. Expected 91cf, computed 68bc % Package validation error Restarting system.Открываю снова файл прошивки и вижу, что 3 и 4 байты содержат 91CF, хотя в них должны содержаться 68BC. Заменяем значения указанных двух байт на 68BC (SL500_1_1_72A_410_final.bin), после чего прошивание можно производить любым доступным способом (TFTP, FTP, HTTP). Я вновь произвожу обновление через TFTP, полный лог данного обновления приведён ниже.
ASUS CLI User Access Verification (none) login: admin Password : admin logged in SL500> ena SL500# conf t SL500(config)# up t 192.168.1.3 foxware.bin Shutting down Event-Manager and Syslogd [ OK ] Successfully created and tested attach to shared memory block for software packa ge ##Package Information: CRC = 0x68bc Magic No. = 0xbe731504 Min-Max Config. Size = 0x20000 noConfigBackup Flag = 0 Minimum Flash = 0x400000 Minimum RAM = 0x1000000 Version = LX_3.2.3_Comp_0_0_0_b Components = IRB, QoS, FW ##Models Supported: SL500 ## ##Images: BOOT: Offset [Package = 1160, Flash = 0x0], Size = 63904 CRAMFS: Offset [Package = 65064, Flash = 0x10000], Size = 3817472 CONFIG: Offset [Package = 3882536, Flash = 0x3e0000], Size = 0 ## ## Successfully uploaded new software image. System will now install the new softwa re and reset automatically with the CURRENT SAVED CONFIGURATION. Shutting down PPP Interfaces [ OK ] Shutting down PPP task [ OK ] Shutting down DB service 0:0:1:4: P PP : Exceptional exit from ppp_eventTask [ OK ] ##Package Information: Magic No. = 0xbe731504 Min-Max Config. Size = 0x20000 noConfigBackup Flag = 0 Minimum Flash = 0x400000 Minimum RAM = 0x1000000 ##Models Supported: SL500 ## ##Images: BOOT: Offset [Package = 1160, Flash = 0x0], Size = 63904 CRAMFS: Offset [Package = 65064, Flash = 0x10000], Size = 3817472 CONFIG: Offset [Package = 3882536, Flash = 0x3e0000], Size = 0 ## ## nobkup is 0, and CONFIG offset + size is identical to current values, hence do nothing for CONFIG partition Upgrading bootloader ..... Bootloader successfully upgraded Upgrading CRAMfs ..... 3a0000 bytes CRAMfs successfully upgraded SDRAM self-test Pass..... Hit Return to enter diagnostics Type II memory configuration Starting boot... Power on bss_start 8099DB40 bss_end 809A2270 Detected Memory: 16 MB Calibrating delay loop... 132.71 BogoMIPS Detected CFI Flash Chip 1 @0xBFC00000 Size(4 MB) Flash self-test pass. Boot: Detected cramfs filesystem SecureLink Boot Loader Software TYP_REL_BOOTSW.4.1.0, Mar 21 2006, 23:45:55 CPU ID 4 Revision 0 Loading CPU 0 ....... Loading CPU 1 .... Booting up system,please wait... Detected LX4189 (PRID: c401), Revision: 0000001e, 16 entry TLB. Board has been soft reset:0 times 9 MB SDRAM. Enabling MMU .......done Loading Lexra 4xxx/5xxx MMU routines. Determined physical RAM map: memory: 00988000 @ 00000000 (usable) memory: 00638000 @ 00988000 (reserved) memory: 00040000 @ 00fc0000 (usable) On node 0 totalpages: 4096 zone(0): 4096 pages. zone(1): 0 pages. zone(2): 0 pages. Linux version 2.4.2_hhl20 (root@gdk) (gcc version 2.95.3 20010315 (release/Monta Vista)) #1955 ¤G 3¤ë 21 23:46:00 CST 2006 rtsched version <20010618.0943.20> New MIPS time_init() invoked. Memory: 7640k/10016k available (1500k kernel code, 2376k reserved, 103k data, 44 k init) Dentry-cache hash table entries: 2048 (order: 2, 16384 bytes) Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes) Page-cache hash table entries: 4096 (order: 2, 16384 bytes) Inode-cache hash table entries: 1024 (order: 1, 8192 bytes) Checking for 'wait' instruction... unavailable. POSIX conformance testing by UNIFIX Initializing RT netlink socket Starting kswapd v1.8 pty: 3 Unix98 ptys configured RTC to Sysclk synchronize Started. Amd/Fujitsu Extended Query Table v .166 at 0x0040ots per queue number of CFI chips: 1 Manufacturer ID: c2, Device ID: a8 IP: routing cache hash table of 512 buckets, 4Kbytes TCP: Hash tables configured (established 1024 bind 1024) IP-Config: No network devices available. Freeing unused kernel memory: 44k freedeadonly. 0:0:8:4: CPU 0 Software Reset IramStart=80000640,IramSize=39c0 Initializing Crypt..... Crypt Engine Initialized! Mode is IRB Initializing Database iBE optimized for ALL_ROUTER mode VPN Addfuncs2Iram IBE initialization done Kernel init for VPN successful ipm_RxTask: Waiting for ICCD MSG +³{6{s›{c«˜X›[dnÝعted: BusyBox v0.60.2 (2002.10.22-13:52+0000) multi-call bina ry c›sÖLض›Û· Starting pid 13, console /dev/console: '/etc/init.d/GOCstartup' Algorithmics/MIPS FPU Emulator v1.5a This firmware has been modified by Klimanov Maxim. Starting modified firmware... mounting /proc mounting /dev/pts setting system clock... Bringing up loopback interface...done Creating directories...done starting user_mgr starting fileconvertor starting firewall ...done bringing up the network starting evtmgr (syslogd also started) starting inetd starting dns starting ddns starting sntp starting l2f_server starting goahead Copyright (c) 2002 GoAhead Software Inc. All Rights Reserved starting dhcpd starting rip starting VPN starting igd starting pptp starting ppp starting monitor Start my part. Extracting file fox.script... assign_memory_buffer:0 rfc_lock:0 extract_file:0 xtract:0 rfc_unlock:0 Changing script (fox.script) rights... Runing scripStarting pid 120, console /dev/console: '/sbin/getty -L ttyS2 9600 vt100' ASUS CLI User Access Verification (none) login: admin Password : admin logged in SL500>Конец лога говорит о том, что команды из файла GOCstartup выполняются, однако, в какой-то момент происходит запуск консольной программы, которая полностью перехватывает вывод, поэтому просмотреть сообщения, выводимые скриптом через консоль не получится. Перехожу к созданию и сохранению самого файла скрипта fox.script.
В этом файле необходимо вызвать программу, которую видит пользователь на консольном порте или через telnet, а также передать ей необходимые команды для воссоздания arp-таблицы. Создаю отдельный файл для команд, которые надо передать консольной программе. Содержимое основного скрипта приведено ниже.
#!/bin/sh rfcutil xtract /tmp/fox.console fox.console /usr/bin/clcli < /tmp/fox.consoleФайл дополнительного скрипта (fox.console) также привожу.
admin admin ena conf t ip arp 192.168.1.2 00:11:22:33:44:55Первые две строки содержат логин и пароль пользователя, которому разрешён консольный вход.
Автор благодарит Нестерова Игоря и Хомутова Владимира за неоценимую помощь в подготовке материала.