Распаковка прошивок кабельных модемов

Распаковка прошивок кабельных модемов

Взлом кабельных модемов был весьма популярен в начале 2000-х годов. В частности, DerEngel и Isabella из группы TCNiSO провели множество исследований по этой теме и, выступая под именами bitemytaco (R.I.P) и BlakeSelf во время конференций DEFCON 16 и DEFCON 18, обнародовали большое количество информации.

Автор: Бернардо Родригес (Bernardo Rodrigues)

Взлом кабельных модемов был весьма популярен в начале 2000-х годов. В частности, DerEngel и Isabella из группы TCNiSO провели множество исследований по этой теме и, выступая под именами bitemytaco (R.I.P) и BlakeSelf во время конференций DEFCON 16 и DEFCON 18, обнародовали большое количество информации.

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

Виды прошивок кабельных модемов

Существует три типа прошивок у кабельных модемов:

  • Подписанные и запакованные прошивки (PKCS#7 & binary).
  • Запакованные бинарные прошивки.
  • Несжатые прошивки (или RAM dump images).

Вы можете выгрузить прошивку либо при помощи JTAG, либо при помощи анализа трафика во время обновления программного обеспечения. Я большой фанат утилиты binwalk и всегда поражался, почему она не распаковывает прошивки кабельных модемов на основе микросхем Broadcom. Так что я решил исследовать этот вопрос.

Распаковка прошивки

В своих экспериментах я буду использовать модем Cisco DPC3925, передающий данные по стандарту DOCSIS 3.0. Эта модель весьма распространена у нас в Бразилии. Модем Cisco DPC3925 работает на чипсете BCM3380 с конфигурацией памяти 16MB Flash x 64MB DRAM.

Рисунок 1: Внешний вид модема Cisco DPC3925 и микросхемы Broadcom

Упакованная прошивка размером примерно 4 МБ. Применив утилиты strings и bindwalk v1.2.1 (без дополнительных параметров), я не получил сколь-нибудь полезных результатов.

Рисунок 2: Первая попытка получить информацию о прошивке

Мы можем получить много полезной информации со страницы производителя: руководствах пользователя, даташитах, лицензионной информации и заявлении об ограничении ответственности за использование продукта. На домашней странице Cisco нет никаких упоминаний об этом, однако Copyright Notices section указывает на то, что в продукте используется LZMA SDK 4.21.

Рисунок 3: Информация о том, что в модеме используется LZMA SDK 4.21

Теперь мы знаем, что прошивка предположительно упакована LZMA, однако нам все еще нужно найти способ распаковки. Результаты работы binwalk с параметром –i (на предмет использования упаковки LZMA) отмечены как некорректные, и вы можете получить нечто следующее:

Рисунок 4: Результат работы bindwalk с ключом –i

LZMA-заголовок задокументирован не очень хорошо, однако есть хороший ресурс, где приводится информация о формате LZMA, или же вы можете обратиться к странице проекта bindwalk с перечнем сигнатур (devttys0 уже проделал для нас огромную работу).

Offset Size Description
0 1 lc, lp and pb in encoded form
1 4 dictSize (little endian)
5 8 uncompressed size (little endian)

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

Рисунок 5: Блок-схема процесса загрузки прошивки

Смещение 0x677 вполне подходит, поскольку находится в начале файла и, кажется, имеет правильный заголовок. 5D 00 00 00 01 показывает уровень компрессии LZMA (8) и следующие 64 бита, должно быть, содержат размер данных в распакованном состоянии (в формате little endian, «от младшего к старшему»).

Рисунок 6: Информация об уровне компрессии LZMA и размере данных в распакованном состоянии

64 бита, следующие за заголовком, (00 20 20 0E 3A 28 AB EF) явно не являются корректным размером распакованных данных (2898643604054482944 байт). Фактически, эта последовательность представляет собой сжатые данные, что делает невозможным их извлечение при помощи bindwalk и 7zr.

Нам нужно добавить несколько байт в заголовок, чтобы архиватор смог опознать и распаковать его. На данный момент нам не известен размер распакованной прошивки, однако хорошая новость в том, что мы можем добавить достаточно большое значение в заголовок, чтобы утилита 7zr смогла распаковать данные, хотя и с сообщениями о том, что конец файла достигнут слишком рано. Давайте выставим значение 268435456 байт (256 МБ), сконвертируем его к формату «от младшего к старшему» (00 00 00 10 00 00 00 00), а затем добавим полученное значение в LZMA-заголовок. Новый заголовок будет выглядеть так: ... 5D 00 00 00 01 00 00 00 10 00 00 00 00 00 20 20 ...

Воспользовавшись предоставленной возможностью, я написал простой скрипт lzma-unpacker.py, используя API для bindwalk.

#!/usr/bin/python

import os, sys
from binwalk import Binwalk

def lzma_callback(offset, results):
for result in results:
if result['description'].startswith('LZMA compressed data, properties: 0x5D'):
with open(sys.argv[1]) as f:
f.seek(result['offset'])
lzma_header = f.read(5)
uncompressed_size = '\x00\x00\x00\x10\x00\x00\x00\x00'
data = f.read()
output = open(sys.argv[1]+'.lzma', 'w')
output.write(lzma_header+uncompressed_size+data)
f.close()

if __name__ == '__main__':
nargs = len(sys.argv)

if nargs != 2:
print '\
\nLZMA Unpacker: Extract LZMA sections from firmware images\n\
\nTested with the following Cable Modems:\n\

- Cisco DPC3925, DPC2434\n\

- Motorola SB5100, SB5101, SVG6582, SVG1202\n\

- Thomson ACG905, DCM425, DHG534, DHG544, DWG850, DWG874\n\

- Webstar DPC2203\n\
\nBernardo Rodrigues, http://w00tsec.blogspot.com\n\
\nUsage: %s firmware_image.bin' % os.path.basename(sys.argv[0])+'\n'

else:
with Binwalk() as bw:
try:
with open(sys.argv[1], 'rb'):
bw.display.header()
bw.scan(sys.argv[1], callback=lzma_callback, show_invalid_results=True)
try:
with open(sys.argv[1]+'.lzma', 'rb'):
bw.extractor.add_rule('lzma:7z:7zr e -y %e')
bw.scan(sys.argv[1]+'.lzma', callback=bw.display.results)
except Exception:
print 'LZMA 0x5D signature not found'
exit
except IOError:
print 'File not found: '+sys.argv[1]

Через некоторое время этот код станет не нужен, поскольку я уверен, что в Bindwalk будет реализован подобный алгоритм (возможно, в виде плагина).

Рисунок 7: Процесс распаковки прошивки при помощи написанного скрипта

Файл размером 21982740 байт был успешно распакован. Если мы подставим в LZMA-заголовок это значение в формате «от младшего к старшему» (14 6E 4F 01 00 00 00 00), утилита 7zr не будет жаловаться на целостность файла.

Рисунок 8: Распаковка прошивки с обновленным заголовком

Большинство прошивок у кабельных модемов на базе микросхем Broadcom запакованы именно таким способом, включая модемы, которые выпущены разными производителями. Написанный мной скрипт полностью протестирован и работает для следующих моделей:

- Cisco DPC3925, DPC2434
- Motorola SB5100, SB5101, SVG6582, SVG1202
- Thomson ACG905, DCM425, DHG534, DHG544, DWG850, DWG874
- Webstar DPC2203

Анализ прошивки

Как только прошивка успешно распакована, можно сделать несколько интересных трюков:

1. Найти стандартные пароли

Рисунок 9: Стандартный пароль прошивки

2. Найти закладки

Рисунок 10: Поиск закладок в прошивке

3. Выполнить пентест веб-приложения

Рисунок 11: Пентест веб-приложения

4. Отправить отпечаток устройства в NMAP

5. Найти похожие устройства при помощи scans.io

6. Отправить HD Moore копию прошивки и ожидать CVE Spam

Где кванты и ИИ становятся искусством?

На перекрестке науки и фантазии — наш канал

Подписаться