At my work, I occasionally end up with pieces of equipment that were once deployed at customer sites or in our own production datacenter that are no longer required. On this occasion, one of our clients replaced their Draytek Vigor3300 router with something else, and decided they didn’t care what happened to the deprecated device.
The first thing I did with the device was to crack it open and take a look at the chipset the device is based on. In this case, the 3300 is powered by a Cavium Networks Nitrox CN210-200 which is an SOC containing a MIPS32 4Km processor. This processor lacks a PMMU, so it’s operating system choices are relatively limited.
With that in mind, I decided to directly attack a system firmware image to determine what software the device is running and if there are any means to get custom software running on the thing.
The firmware for the device is easily available from the Draytek website, the latest version of which appears to be v2.6.3. Extracting the ZIP archive reveals the firmware image file, named V3K32263_en.all.
During my first attempt to discover the composition of this file, I opened it up in a hex editor and found a giant binary blob with a small collection of ascii strings near the beginning of the file (around offset 0x3518).
vfprintf: out of memory unzip - Unknown header at address %x, %0x, %0x unzip - Unknown compression method, should be 8, was %x ...
Also of interest, right after the block of strings was the presence of a GZIP magic number followed by the compression method id 8. The hex code for this is 0x1F 0x8B 0x08.
I then ran a binary diff against two different versions of the firmware (Version 2.6.3 and 188.8.131.52) and used the output to determine the boundaries of the real firmware payload.
It seems that first 14kb of the firmware package is identical between versions, except for a few bytes near the very beginning of the file (5 bytes from offset 0x03).
At least some of the code seems to be at least superficially similar to unzip.c and util.c. At the very least the presence of the same ASCII strings and matching CRC32 table would indicate that codebas is possibly in use. Further disassembly of this code block would be required to definitively determine it’s origin.
Beyond that 14kb is a ~6MB GZIP image.
Using the handy DD tool I extracted the GZIP image from the binary blob and extracted it. This revealed yet another binary blob file, this time named image.bin.
Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ dd if=V3K32263_en.all of=image.bin.gz bs=14144 skip=1 Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ gunzip image.bin.gz gzip: image.bin.gz: decompression OK, trailing garbage ignored Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ ls -lah image.bin -rw-r--r-- 1 matthew staff 7.6M 16 May 13:03 image.bin
A quick scan of the ASCII strings in the file found some interesting identifiers that confirm the operating system and software choices made by the firmware developers
Linux version 2.4.20-br251 ([email protected]) (gcc version 3.2 20030604 (BRECIS uClinux)) #2 Tue Aug 17 14:54:00 CST 2010
Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ file image.bin image.bin: data
Using the handy binwalk program it was possible to identify the offsets for both the uClinux kernel image as well as the presence of a ROMFS image. The ROMFS image is padded on both sides, ensuring it’s aligned on 4KB boundaries.
Extracting the ROMFS image is another simple affair.
Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ dd if=image.bin of=rootfs.img bs=1945600 skip=1 3+1 records in 3+1 records out 6000640 bytes transferred in 0.009189 secs (653015110 bytes/sec) Matthew-Costas-Mac-Pro-2:V3300V_263 matthew$ file rootfs.img rootfs.img: romfs filesystem, version 1 6000208 bytes, named rom 4c6a3206.