Description
This is an utility for packing/unpacking of Cisco IP Phone firmwares based on CNU_File_Archive_3.0 format, called so after strings found in firmware files. These are 7911/7906, 7941/7961, 7970/7971 and others for 79xx series phones.
Firmwares for 3911, 7931 and other newer models have different format and can't be unpacked with this utility.
History
In far 2007 my work was bound with installation of Asterisk-based PBX systems and various intellectual (and not so intellectual) value-added services, so I had some hands-on experience with few SIP phones, including Cisco. Initially Cisco phones are expected to be used with Cisco Call Manager, therefore all provision and configuration solutions are hidden in CCM internals. Some 79xx series phones don't even have web-interfaces or menu access to configuration items and configured from TFTP or other system interfaces only.
Firmware upgrade is also done via TFTP. Internet community has re-engineered configuration file format and found settings needed to work with Asterisk. Look at http://www.voip-info.org/wiki/view/Asterisk+phone+cisco+79xx for details. Telling the truth, I'm don't exactly understand the problem of dumping full configuration from phones or sniffing it while provisioning from Call Manager, and why there still no XML schema for configuration files, but this is not the point now.
Generally everything works fine, but there was no remote management for these phones, there was no root access to remote console - only default, log, debug users with very limited access. Though these accounts allowed to view some information, there was no ability to fine-tune phone internals. You also able to set account credentials from configuration file, but it will be usual limited account with a custom shell. Also I wanted to look into phone internals and OS since there is Java-based UI in it.
There was attempts to reveal root password for devices, but naturally all failed because nobody wants you pecking in their brand new shiny phones with your dirty hands. It has become clear that we need to dive deeper - just into the firmware.
Firmware analysis
Прошивка распространяется в виде .sbn- или .zip-архива. Собственно еще до поисков информации об этих телефонах в сети первым делом я попробовал посмотреть на .sbn-файл. Беглый осмотр и поиск известных сигнатур файлов показал, что это просто tar.gz с присобаченной цифровой подписью. Цифровая подпись нам пока неинтересна, сначала надо разобрать сам файл. Безжалостно вырезав ее в vi, я распаковал получившийся .tar.gz.
Внутри некоторое количество .sbn- и .loads-файлов. Последние предназначены для того чтобы указать телефону, какие файлы прошивки грузить при загрузке с TFTP, когда прошивка выкладывается на Cisco Call Manager или TFTP-сервер в случае работы с Asterisk. Это просто текстовые файлы с именами файлов прошивки. Нам же нужно разбирать .sbn. Теперь уже понятно, что это такой же подписанный контейнер непонятного пока формата.
С чего начать анализ незнакомого файла? Я начал с открытия файла с прошивкой в vi :). Беглый осмотр показал наличие текстов, характерных для несжатого и незашифрованного файла - видны заголовки PNG-файлов, системные сообщения внутри каких-то бинарных модулей. Но самое главное - похоже есть список файлов, и он не зашифрован.
Так как в файле наверняка хранятся смещения или абсолютные адреса частей содержимого, то нужно было правильно определить начало заголовка. Примерно посмотрев где заканчивается подпись в основном архиве прошивки, я понял куда надо смотреть, и без особых колебаний ее обрезал.
Дальнейшие копания в файле показали, что после zerofill-дыры за началом файла существует набор небольших секций с повторяющейся структурой. Я решил, что это таблица размещения файлов и начал анализировать пары и четверки байт, полагая, что вряд ли в файловом архиве смещения или указатели длины файлов будут однобайтовыми. Выбрав файлы известного формата, следующие друг за другом в списке файлов в тексте прошивки, я записал смещения их заголовков, и начал сравнивать записи в таблице размещения.
В общем, впоследствии все мои догадки подтвердились, это действительно оказалась таблица смещений, а точнее абсолютных адресов в файле. Что меня затормозило, так это неправильный выбор начала файла прошивки, в результате я получал неверные данные по адресам, указанным в таблице адресов, но потом я обратил внимание, что адреса почти правильные, плюс-минус каких-то тридцать байт =) И В сответствии с этим скорректировал свои представления о действительном начале файла с прошивкой. Теперь я знал где начинается сам файл с прошивкой и имел представление о формате хранения.
После написания пары пробных версий программы для распаковки со всякими автоматическими попытками найти начало первого хранимого файла я заметил, что количество файлов и информация об адресе первого файла тоже есть в заголовке, просто в азарте разбора секции размещения файлов я их пропустил =)
Формат оказался на редкость странным - в заголовке какая-то дыра, не то для future use, не то для загрузчика или распаковщика, который возможно планировалось реализовать. Размещение некоторых элементов тоже странное для человека, и есть некоторая избыточность хранимых смещений, но возможно так сделано для скорейшей идентификации и проверки прошивки на корректность загрузчиком при обновлении.
Возможно также, что это как-то связано с потенциальной работой прошивки непосредственно с Flash, без загрузки ее в память, но я не специалист по встраиваемым системам и контроллерам. Кроме того, гадать, почему в кружке китайско-индийской дружбы имени Cisco (о чем красноречиво свидетельствуют имена в цифровых подписях и скриптах в прошивке) решили сделать так, а не иначе, бессмысленно - сказывается различие наших культур, хаха.
Ладно, дальше даю формат, смотрите сами.
Формат прошивки
Удивительно, но прошивка начинается там, где заканчивается подпись файла.
0x0D 0x0D - разделитель после цифровой подписи, это два перевода строки, дальше идет прошивка.
Я описываю смещения в файле прошивки исходя из того, что подпись из файла удалена.
Подписи на английском, кому нужно, тот разберется, а зарубежным товарищам возможно тоже будет интересно.
| Begin | End | Data Type | Item | Description |
| 0x00 | 0x13 | bytes | Signature | CNU_File_Archive_3.0 |
| 0x14 | 0x31 | bytes | Hole | Unused/Reserved (zerofill) |
| 0x30 | 0x33 | dword | FileCount | Number of files in archive |
| 0x34 | 0x37 | dword | ContentOffset | First byte of first file |
| 0x38 | 0x4B | bytes | Signature | Copy of file signature (for compatibility?) |
| 0x4C | 0x247 | bytes | Hole | Unused/Reserved (zerofill) |
| 0x248 | 0x248+SizeOf(FileRec)*FileCount - 1 | records of dwords | FileTable | File table (see File table record format) |
| 0x248+SizeOf(FileRec)*FileCount | ContentOffset | strings | FilenameList |
List of file names |
| ContentOffset | EOF | bytes | Content | Archived Files |
| Begin | End | Data Type | Item | Description |
| 0x00 | 0x03 | dword | FlagA | Can be 6 or 7. 6 is a kernel/loader file, 7 - usual file |
| 0x04 | 0x07 | dword | FlagB | 2. File type or mode? |
| 0x08 | 0x0B | dword | Size | Size of file |
| 0x0C | 0x0F | dword | Timestamp | File UNIX timestamp |
| 0x10 | 0x13 | dword | FilenameOffset | Absolute offset to file name string |
Таким образом, одна запись в таблице файлов имеет размер 20 байт, это 5 чисел в dword-ах. Таких записей в этой таблице по числу файлов в архиве.
После таблицы файлов следует список имен файлов, содержащихся в архиве. Это просто строки C, содержащие полный путь к каждому файлу, заканчиваются нулевым байтом, других разделителей нет. На начало каждой из строк указывает FilenameOffset в соответствующей файлу записи в таблице файлов.
После последнего имени файла начинается непосредственно контент - содержимое файлов архива без разделителей, подряд.
