The Router Review: From nmap to firmware
When I moved into my flat, I found that the previous tenant had left behind his Sky Broadband router. Awesome - a new toy to break! Sadly I got bogged down with silly things like moving house and going to work, so I didn’t get a chance to play with it. Until now, that is.
This isn’t the first embedded device I’ve played with. Over the years I’ve desoldered EEPROMs from routers, done unspeakable things to photocopiers, and even overvolted an industrial UPS unit via SNMP. The router I shall be discussing in this post, however, was one of the easier and more generic bits of kit I’ve played with.
Now, a little about the device. The model is DG934, and the full part number is 272-10452-01. It’s an ADSL router supplied by Sky (also known as BSkyB) as part of their old broadband package, but it’s actually manufactured by Netgear. It’s got four ethernet ports, an ADSL (phone) port, and takes a 12V power supply. Internally, it runs on the Atheros chipset. Unfortunately, this being a UK-only device, there’s no FCC ID - if there had been, I could’ve looked it up on the FCC OET database and found all sorts of internal photos and test data, which is often valuable when looking at the hardware aspects.
My first job was to power it on and get into the config panel. Since the previous tenant clearly wasn’t security conscious, he’d kindly left the device in its default configuration and I was able to log into the configuration interface using the default admin / sky credentials. I exported the config file to my machine, and took a look. In this case it’s plaintext, so there’s nothing to break here, but it’s not exactly good practice - it includes the passwords for WiFi and the configuration interface.
I ran nmap against the device and got the following results:
PORT STATE SERVICE VERSION
80/tcp open http BSkyB DG934G http config
5000/tcp open sip BSkyB/1.0 UPnP/1.0 miniupnpd/1.0 (Status: 501 Not Implemented)
8080/tcp open http BSkyB DG934G http config
32764/tcp open unknown
Interestingly, the configuration site was available on both 80 and 8080. This seems to be the norm for many routers, but I have no idea why. UPnP on port 5000 is always a fun one to spot, and we’ll take a look at this shortly. Finally, there’s an unknown protocol running on port 32764.
For messing with UPnP, I have the UPnP Developer Tools for Windows. They’re mainly written in C# and are open source, so you can always port to Mono if you want. I used Device Spy to get the following info:
It’s a BSkyB DG934 Router.
The firmware date is 2007-08-27.
You can pull out stats such as total bytes sent/received, total packets sent/received, and uptime in seconds.
Port mapping functions are available.
SetEnabledForInternet isn’t present - shame, really, since it leads to a nice DoS condition.
Sadly there’s not much you can play with here.
Next, we’ll take a look at that weird unknown protocol on port 32764. When connecting to it, the string “MMcS” is returned, along with two binary IP representations: 255.255.255.0 and 0.0.0.0. I tried playing around with this, but honestly I have no idea what it’s for. Google returned a bunch of people asking what it was, and nobody with any real answers. Potentially it’s for Multimedia Class Schedule Server, but that’s speculation at best. Again, no luck at fun stuff here.
Finally, let’s dig into the firmware. Instead of taking the device apart, desoldering the firmware EEPROM, and interfacing to it with a BusPirate to rip the data off, I decided to go the easy route and download the openly available firmware from Netgear. The file provided is a flat binary, with some interesting data inside it. It’s partitioned into various sections, with conveniently obvious data offsets (e.g. 0x10000). In order to properly dissect the file, I used binwalk. In BackTrack 5 it’s located in /pentest/reverse-engineering/binwalk/
and requires you to manually set the magic file via the -m
switch.
root@bt:~# binwalk -m /pentest/reverse-engineering/binwalk/magic.binwalk ~/dg834gt_1_02_09.img
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
:1248 0x4E0 CFE boot loader
1288 0x508 CFE boot loader
4177 0x1051 LZMA compressed data, properties: 0xA4, dictionary size: 285474816 bytes, uncompressed size: 256 bytes
7951 0x1F0F LZMA compressed data, properties: 0xC2, dictionary size: 556793856 bytes, uncompressed size: 67108881 bytes
8087 0x1F97 LZMA compressed data, properties: 0x82, dictionary size: 556793856 bytes, uncompressed size: 67108881 bytes
8227 0x2023 LZMA compressed data, properties: 0xC2, dictionary size: 556793856 bytes, uncompressed size: 67108881 bytes
8371 0x20B3 LZMA compressed data, properties: 0x82, dictionary size: 556793856 bytes, uncompressed size: 67108881 bytes
10563 0x2943 LZMA compressed data, properties: 0xDF, dictionary size: 555220992 bytes, uncompressed size: 167272448 bytes
65792 0x10100 CramFS filesystem, big endian size 2879488 version #2 sorted_dirs CRC 0x51df60ff, edition 0, 1975 blocks, 938 files
1016865 0xF8421 ARJ archive data, v193, backup, original name: \230\346+\210\365 ... [snip]
This gives us a pretty good idea of what we’re dealing with. First, there’s a Common Firmware Environment (CFE) bootloader, which is Broadcom’s alternative to U-Boot. There’s some irony here in that Broadcom and Atheros are competitors, yet CFE is being used on an Atheros chipset device. Anyway, there’s a bunch of LZMA junk after that which looks like various bits of firmware and a Linux kernel image. The bit we’re really interested in is the CramFS data. As a side note here, it looks like binwalk was a bit overzealous in identifying an ARJ archive at the end (hence the corrupted original name) so we can assume that the CramFS block takes up the remainder of the file.
In order to extract the filesystem, we can use good old dd
. The following should suffice:
dd size=256 skip=257 count=20000 if=dg834gt_1_02_09.img of=firmware.cramfs
Note that 257 * 256 = 65792, which is 0x10100, i.e. the offset of the data we want to pull out. I stuck a really big count in there because we’re reading to the end of the file. Now, you’re going to want to grab some tools to work with CramFS:
sudo apt-get install cramfsprogs fusecram
This provides you with the modules needed to mount CramFS volumes, as well as some tools to help you along the way. Now we can mount the filesystem:
root@bt:~# sudo mount -t cramfs -o loop ~/firmware.cramfs /media/firmware/
mount: wrong fs type, bad option, bad superblock on /dev/loop1,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so
Hmmm, that’s odd. Let’s see what dmesg
has to say about this…
root@bt:~# dmesg | tail -n 1
[ 4394.319907] cramfs: wrong endianess
Aha! A fun fact about CramFS is that file systems have endianness as per the architecture they were created on. Since the router is big-endian and my box is little-endian, I need to convert it. Thankfully, cramfsprogs
includes a tool called cramfsswap
that flips the endianness of a provided image. Side note: if you get “wrong magic” as an error, you didn’t extract the right blocks of data, or the file system isn’t CramFS.
root@bt:~# cramfsswap ./firmware.cramfs ./firmware-conv.cramfs
Filesystem is big endian, will be converted to little endian.
Filesystem contains 937 files.
CRC: 0xe86ad3b0
root@bt:~# sudo mount -t cramfs -o loop ~/firmware-conv.cramfs /media/firmware/
root@bt:~#
Excellent! Now to dig around inside the files.
root@bt:~# ls -l /media/firmware/
total 20
drwxr-xr-x 1 root root 452 1970-01-01 01:00 bin
drwxr-xr-x 1 root root 0 1970-01-01 01:00 dev
lrwxrwxrwx 1 root root 8 1970-01-01 01:00 etc -> /tmp/etc
drwxr-xr-x 1 root root 784 1970-01-01 01:00 lib
drwxr-xr-x 1 root root 0 1970-01-01 01:00 proc
drwxr-xr-x 1 root root 176 1970-01-01 01:00 sbin
drwxr-xr-x 1 root root 0 1970-01-01 01:00 tmp
drwxr-xr-x 1 root root 116 1970-01-01 01:00 usr
lrwxrwxrwx 1 root root 8 1970-01-01 01:00 var -> /tmp/var
lrwxrwxrwx 1 root root 8 1970-01-01 01:00 www -> /tmp/www
drwxr-xr-x 1 root root 3900 1970-01-01 01:00 www.deu
drwxr-xr-x 1 root root 3908 1970-01-01 01:00 www.eng
drwxr-xr-x 1 root root 3824 1970-01-01 01:00 www.fre
There’s a full listing on pastebin, if you’re interested. It’s worth noting that if you can mount the filesystem, can see the directories and files inside it, but can’t read the file data, then you probably didn’t copy the entire filesystem and it’s missing chunks of data. Anyway, this looks pretty typical. We can see a very basic file system that comprises all the runtime parts of the device, excluding the kernel and any ramfs stuff. Here’s what I found:
The three www prefixed directories contain the template files used for the administration panel.
/bin contains busybox binaries.
/lib contains the kinds of libraries you’d expect on a router, e.g. libcrypt, libupnp, libpppoe, etc.
/lib/modules contains various kernel modules for the router, such as the push button driver and Atheros HAL.
/sbin contains various binaries such as ifconfig, insmod, lsmod, etc.
/usr/bin contains four binaries, including one called test.
/usr/etc contains the default config files and various scripts.
/usr/sbin contains various binaries for daemons (including reaim and iptables), as well as some for performing maintenance operations, e.g. WiFi control operations.
/usr/upnp contains the definitions for the UPnP endpoint.
The most interesting directory was /usr/etc, which contains both passwd and an svn.info. The passwd file shows only root and nobody, which leads me to believe that all services run as root. The svn.info file has all sorts of interesting info in it:
Path: .
URL: file:///svn/Platform/DG834_PN/Source
Repository Root: file:///svn/Platform/DG834_PN
Repository UUID: 25bc2c04-8815-0410-823d-fa30465ac5aa
Revision: 93
Node Kind: directory
Schedule: normal
Last Changed Author: ethan
Last Changed Rev: 93
Last Changed Date: 2007-02-16 16:23:45 +0800 (Fri, 16 Feb 2007)
Boot Loader version: CFE version 1.0.37-5.11 for BCM96348
So we now know that Netgear use(d) SVN for their source control, that “Ethan” is the guy developing the firmware for the DG834, and that we’re running CFE 1.0.37-5.11 on the BCM96348 SoC IC. Hi, Ethan!
I’m going to leave this here for now, primarily because it’s almost 4am, but also because the point of this blog post was to show just how much information you can dig out of a device without even touching it with a screwdriver, or opening a manual. Keep in mind that the techniques I’ve shown here should apply to many routers and other small embedded devices. At some point in the future I’ll get around to digging into some of their custom binaries, as well as their HTTPD. If I find anything interesting, I’ll be sure to post an update. Also, let me know if you’ve got any spare routers you want me to dig into when I get a spare few hours - I’m always happy to take donations!