Reverse engineering the zyxel configuration backup file

For the Router Hacking Challenge Adrian Pastor was wondering if anyone knew how to read the configuration backup file that you can download from your ZyXEL router.

I happen to have a ZyXEL gateway as well, a P-2602HW-D1A to be precise, so I decided to take a look.

After looking at several of these files (called "rom-0" when downloaded) I came up with the following structure:
There's two blocks in my file, one for memory and one for files I guess. They start at 0x00000000 and 0x00002000 respectively and look like this:

BYTE     blocknumber
BYTE     unknown
WORD     nr of objects
DWORD    blockLength
foreach object:
  CHAR[14] objectname
  DWORD    uncompressed size
  DWORD    compressed size
  DWORD    offset to data from start of block

And there we encounter our first problem: the files can be compressed..
For me the first block mentioned a "dbgarea", and the second block "boot", "spt.dat" and "". But only the spt.dat seems to be compressed. Since the other files show little of interest this is also the file we're interested in.

Now to figure out the type of compression..
The first 32 bytes of my file look like this:

CE ED DB DB 00 03 00 09 00 00 06 84 08 00 00 ED 67 3B 5B 6D B0 00 0C 00 09 00 00 00 C8 4C 20 00

At first I had a hunch it might be LZW compression because that is often used in embedded devices, but I could not make it work on the data I had. Google also turned up nothing useful for me. So I decided to reverse engineer the firmware for my device to find the routines that read and write the spt.dat file.

I'm not going to go into the reversing itself today, but all I needed was this site and IDA Pro 5.1

From the disassembly I managed to figure out this structure for the spt.dat file:

DWORD	Unclear (Load-addres?, Magic?, Endianness?)
WORD	Major Version
WORD	Minor version
DWORD	Unclear (Chunks?)
until EOF:
  WORD		  org_size
  WORD		  raw_size
  BYTE[raw_size]  Compressed data

The decompression routines were a bit too big and complicated for me to follow since I'm no star at MIPS processors. But I did find reference to files called "lzsc.c" and "lzsd.c".
A quick google led me to the Stac LZS compression mechanism decribed at ANSI X3.241-1994

I could not quickly find an implementation or tool to now decompress the spt.dat so I went ahead and started writing my own implementation in C# (source). It still has some bugs in it so the decompression is not perfect, but it is good enough to read all settings like passwords, snmp community strings, wep keys etc.

A global ranking for hacker games and challenge site players