Monday, November 11, 2013

Unpacking Firmware Images from Cable Modems

Hacking Cable modems used to be very popular during the early 2000’s. People like DerEngel and Isabella from TCNiSO carried lots of research on the topic and talks from bitemytaco (R.I.P) and BlakeSelf during DEFCON 16 and DEFCON 18 covered lots of information on the subject.

Securing cable modems is more difficult than other embedded devices because, on most cases, you can’t choose your own device/firmware and software updates are almost entirely controlled by your ISP. Most cable modems offer a limited administrative interface and management commands are sent using SNMP.

Cable Modem Firmware

There are basically three types of firmware images for cable modems:

- Signed and compresed (PKCS#7 & binary)
- Compressed binary images
- RAM dump images (uncompressed & raw)

You can dump your own firmware image using JTAG or sniffing the connection during upgrades, for example. I’m a big fan of binwalk and I always wondered why it doesn't unpack firmwares from popular Broadcom based cable modems so I decided to research on this.

Unpacking the Firmware

For this analysis I’ll use Cisco DPC3925, which is a very common DOCSIS 3.0 modem here in Brazil. Cisco DPC3925 has a BCM3380 chipset, 16MB Flash x 64MB DRAM memory configuration.


The compressed firmware image has around 4MB. Using strings against the file didn't help much and binwalk v1.2.1 (without any additional parameters) did not recognize it.


We can gather lots of useful information from the vendor’s page: user guides, datasheets, licensing information and open source disclaimer for the product. There are no sources available on Cisco's home, but the Copyright Notices section states that the product uses LZMA SDK 4.21.


So we know that the firmware is probably packed using LZMA but we still need to figure out how to unpack it. Binwalk -i displays results marked as invalid during the scan and we might get some clue:


The LZMA header is not well documented. There are some good resources on lzma-purejs Github and you can also check binwalk's magic file signatures (devttys0 already did all the hard work for us).

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

The Bootloader in the beggining of the flash contains the necessary information to boot the firmware image. On the top of the firmware there's always an extractor which decompress the firmware into DRAM.

Offset 0x677 is a good candidate because it's located in the beginning of the file and it seems to have a valid header. 5D 00 00 00 01 indicates a LZMA compression level of -8 and the next 64 bits should be the data's uncompressed size (in little endian).


The 64 bits following the header (00 20 20 0E 3A 28 AB EF) is clearly not a valid uncompressed size (2898643604054482944 bytes). It represents the actual compressed data, making binwalk and 7zr unable to extract it.

What we need to do here is append a few extra bytes to the header so our regular 7zr binary can recognize and extract the data. We don't know the uncompressed size for the firmware yet: the good news is that we can append and specify a big value here, allowing 7zr utility to unpack it (although complaining that the EOF was reached too early). Let's specify 268435456 bytes (256MB), convert it to little endian (00 00 00 10 00 00 00 00) and append it to the original LZMA header. The new header should be something like ... 5D 00 00 00 01 00 00 00 10 00 00 00 00 00 20 20 ...

I took the opportunity to have a look on binwalk's API and wrote a simple lzma-unpacker.py:

This code will be obsolete in a couple of days because I'm pretty sure Binwalk incorporate this (a plugin maybe?)


The data was extracted successfully and contains 21982740 bytes. If we replace the uncompressed size on the LZMA header with the correct value in Little Endian (14 6E 4F 01 00 00 00 00), the 7zr tool would not complain about the file integrity.


Most Broadcom cable modems are packed this way, including the ones manufactured by different vendors. The script was fully tested and works fine for the following models:

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

Firmware Analysis

Now that you successfully unpacked the firmware, here's a couple of cool things you should do:

- Find default passwords


- Find backdoors



- Pentest the Web Application




- Fingerprint your device and submit to NMAP

- Find similar devices using scans.io dataset

- Mail HD Moore a copy of the firmware and wait for the CVE Spam

33 comments:

  1. Ótima análise do firmware, parabéns pelo texto!
    Sobre o bootloader, é possível fazer uma análise dele para habilitar o console via serial?

    ReplyDelete
    Replies
    1. Hi Luiz, OpenWRT's wiki has some useful information about DPC3825/EPC3825, which has the same chipset (BCM3380) and probably the same bootloader as the DPC3925: http://wiki.openwrt.org/toh/cisco/epc3825

      Delete
  2. What way did you dump the firmware? I have an EPC3925 and would like to see if I can retrieve the firmware off it.

    ReplyDelete
    Replies
    1. You can follow instructions from USBJTAG forums: http://www.usbjtag.com/vbforum/showthread.php?p=55977 and http://www.usbjtag.com/vbforum/showthread.php?p=55341

      Delete
    2. Cheers thanks. I actually read these threads earlier today! DO you use USB JTAG? I was thinking in investing in one of these. But this area is pretty new to me.

      Delete
    3. Hi Damien, I currently own a FlashcatUSB (http://www.embeddedcomputers.net/products/FlashcatUSB/) which is older and cheaper. USBJTAG NT has the best support and compatibility out there and their software is very good.

      If you just want to test these firmwares you can also download dumps from their forums (http://www.usbjtag.com/vbforum/downloads.php?do=cat&id=8) or google them =)

      Delete
    4. Thanks for that. I want to test the firmware specifically no my modem also as its ISP specific. Plus would learn the hardware side of things also! You hardly took a pic when you had the FlashcatUSB wired up to the SPI interface did you?

      Delete
    5. Estimado, junto con saludar, como puedo descomprimir y posteriormente comprimir el firmware del DPC3925, se como hacerlo en el SB5101, sin embargol dicha aplicación no soporta comprimir volúmenes superiores a 1mb de firmware, desde ya agradecido.

      Delete
  3. Dear Bernardo,
    very nice Post!! Thanks for sharing. Search a long time for informations about the cisco modem's.
    My Provider rent my router as a modem (because it have only one port).
    Can't bridge the device...
    Did you found any backdoor for ssh / telnet (e.g. a Web-GUI) activation ?
    I ordered already parts to read out the firmware.

    Pictures of the board and my previous informations:
    http://www.haxorware.com/forums/thread-2824.html

    Kind Regards
    MaCXyLo

    ReplyDelete
    Replies
    1. Hi MaCXyLo, I did not have much time to test it yet. Some modems like the Webstar DPC2100 have a firmware upgrade page at specific URI's (http://192.168.100.1/__swdld.asp). Try to carve and find HTML pages (using foremost or the latest binwalk-dev), analyze the strings, search for *.asp to identify hidden pages and */goform/*, which is used for dynamic actions. The modem is MIPS-based, you can also try reverse engineering it with IDA Pro.

      Delete
  4. Awesome post! Just discovered this while I was looking for CMImageTool ;) This is way better. Any chance of adding support for SBG6580? Join us on #surboard_hacker sometime. Will be nice to chat with you.

    ReplyDelete
    Replies
    1. SBG6580 disassembles just fine using the same commands. You can add it to the list of devices it works on.

      Delete
    2. Hey Mike, I didn't have a copy of the SBG6580 firmware and I couldn't test back then, thanks for letting me know. Firmwares for most broadcom based cable modems are packed this way. Anyway, newer versions of binwalk already have a plugin to unpack them, check it later on: http://binwalk.org/lzmamod-plugin/

      Delete
    3. Thanks for the reply Bernardo. Nice to see binwalk just enable it as a plugin by default, sure is coming in handy.

      Btw ever work with the backdoor that says 255.255-255.255 ? (Notice how it seems there is a dash - instead of dot . between the 2nd and 3rd 255)

      Delete
    4. Hey Mike, sorry for the late reply. Regarding the 255.255-255.255 backdoor, I didn't spend much time reversing it, as you may noticed that was a simple recursive grep, but it may reveal some interesting info.

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Will this method work for Cisco DPC3000 modems also? (it's Puma 5 based)

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I'd like to invite you to cooperate on a modem firmware project, for a generous reward. What's the best way to contact you?

    ReplyDelete
  8. I'd like to offer a $2000 reward for a modem firmware project. Email bobcat at adacity . net for details!

    ReplyDelete
  9. Great post! I was looking for *exactly* these informations. And look: it's from a brazilian fellow! Who'd have guessed? :)
    I will certainly browse through your other posts later. Thanks!!

    ReplyDelete
  10. É possível subir uma config de velocidade nesse modem?

    ReplyDelete
  11. Hi,
    I'm fighting with DI-524 rev.B4 with RDC R2600(also know as AMRISC 10100 processor)(probably 16bit x86 instruction set).
    Same CPU can be found in:
    LevelOne WBR-3406TX v2
    ZyXEL P-320W
    Gigabyte GN-BC01
    Gigabyte GN-AP05G
    ...
    binwalk was unable to find code file:
    http://labs.nccgroup.trust/djbinwalk/lookup/937e5e9531ffa156419b929a16575d7c5c8e5811df613bab91f1d32d9286008b

    Maybe you can help???

    PS.
    lzma-unpacking is not working with new binwalk:
    "from binwalk import Binwalk
    ImportError: cannot import name Binwalk"

    ReplyDelete
    Replies
    1. usage: python3 lzma-unpacker.py firmware_image.bin

      Delete
    2. "
      File "lzma-unpacker.py", line 30
      \nUsage: %s firmware_image.bin' % os.path.basename(sys.argv[0])+'\n'
      ^
      SyntaxError: invalid syntax
      "

      Delete
    3. Newer binwalk incorporated the plugin, so you can try something like:

      binwalk -e -Z -P -S D3925.bin

      DECIMAL HEXADECIMAL DESCRIPTION
      --------------------------------------------------------------------------------
      1660 0x67C Raw LZMA compression stream, properties: 0x5D [pb: 2, lp: 0, lc: 3], dictionary size: 33554432

      The -Z flag uses the same technique as lzma-unpacker:

      https://github.com/devttys0/binwalk/wiki/Usage

      Delete
  12. Hi Bernardo,
    Nice post! Thank you very much!

    ReplyDelete
  13. Hi,

    I've just bought an EPC3925 second hand off eBay. It comes with a firmware that doesn't permit bridge mode. I've Google'd around a lot today trying to find fw, and now I'm seeing it's the cable ops pushing it, and I don't find any publicly available to download fw.

    I did try the HTML injection trick, but it didn't work. I read later others whom had tried it and also failed with the same FW as me.

    Does anyone know a location I could download a FW dump that would have bridge support please? I'm in EU so it's EURODOCSIS I need.

    Any help anyone can offer would really be appreciated.

    Best wishes

    ReplyDelete
  14. Just made it for different LZMA compression levels and different possible locations... is a PHP script
    https://gist.github.com/carloslopez1990/283a4735f5fb1fb653640d8c01a7437c

    ReplyDelete
  15. Best place to find firmware files for Motorola/Arris modems?

    ReplyDelete
  16. Is there any way to enable WPA2 ENTERPRISE (FOR RADIUS authentication) I have this rogers dpc3825 which does not have wpa2 enterprise option. i want to enable the radius configuration.

    ReplyDelete

Note: Only a member of this blog may post a comment.