Livebox Sagem Firmwares
Let's take a 260 series Livebox Sagem firmware, found for instance on the CD-ROM distributed by Orange in France, and look into it.
Let's extract the firmware 26014A for instance:
It's made of three parts
- the first part is a header : 140 bytes of binary data.
dd if=firmware of=header.raw bs=1 skip=0 count=140
0x00-0x03: 01 00 00 01 magic bytes
0x04-0x07: 00 00 0a 74 size of compressed firmware loader 0xa74=2676
0x08-0x0b: 80 80 00 00 ?
0x0c-0x0f: 80 ef 00 00 ?
0x10-0x13: 00 01 00 00 ?
0x14-0x17: 00 00 17 98 size of uncompressed firmware loader 0x1798=6040
0x18-0x1b: 80 c0 00 00 ?
0x1c-0x1f: 80 c0 00 00 ?
0x20-0x23: 80 01 40 00 ?
0x24-0x27: 80 01 40 00 ?
0x28-0x7b: name of firmware "FAST3202 \tFAST3202_26014A (OpenRG 4.0.21.3.3.1.31)\0"
0x7c-0X7f: 43 45 2c 50 checksum?
0x80-0x83: 81 4a 03 ca checksum?
0x84-0x87: ff e8 3b 5c checksum?
0x88-0x8b: 00 00 00 01 magic bytes
The checksums are probably some sort of CRC32, I don't have time to investigate more at the moment. - then comes a zlib compressed that looks like some sort of flash loader. The compressed and uncompressed sizes of this part are found in the header.
dd if=firmware of=loader.raw bs=1 skip=140 count=2676
zpipe -d loader.inflated.
The zpipe program can be found here. The inflated file (6040 bytes long) is some binary executable. - The remaining part is the actual payload.
dd if=firmware of=payload.raw bs=1 skip=2816
(2816 is 2676+140). The paload itself seams to be made of several parts:- A header: 0x500=1280 bytes, all zeros except the last four bytes: 26 10 70 96. Extract it with
dd if=payload.raw of=payload_header.raw bs=1 skip=0 count=1280 - A bootloader, 9504 bytes long. Extract it with
dd if=payload.raw of=payload_code.raw bs=1 skip=1280 count=9504. The main role of this executable code seems to be uncompressing and booting the kernel. - The payload data (see below).
dd if=pawload.raw od=payload_data.raw bs=1 skip=10784 - The linux kernel code can be extracted with
dd if=2277376 bs=1 count=2277376 of=kernel.raw - The initrd contents can be extracted with
dd if=payload_data.uncompressed of=initrd.raw bs=1 skip=2277376 count=5745 - The kernel+Initrd part is terminated by 2448 zero bytes
- The rootfs comes at the end:
dd if=payload_data.uncompressed of=rootfs.raw skip=2285568 bs=1
This payload data is compressed using LZMA, bur with a slight variation: the length is stored using 4 bytes instead of 8. So let's insert four zero bytes to fix it:
dd if=payload_data.raw bs=1 count=8 of=/tmp/file1
dd if=/dev/zero bs=1 count=4 of=/tmp/file2
dd if=payload_data.raw bs=1 skip=8 of=/tmp/file3
cat /tmp/file1 /tmp/file2 /tmp/file3 >payload_data.fixed
lzmadec < payload_data.fixed >payload_data.uncompressedThe payload_data.uncompressed contains a linux kernel with an initrd, and a rootfs filesystem:
Extracting the initrd.
It is a gzip-compressed cpio archive:
gzcat initrd.raw | cpio -i --no-absolute-filenames
Nothing fancy here, only symbolic links to the actual file in /mnt/cramfsExtracting the rootfs
It is some sort of cramfs. I did not find a way to mount it using standard linux x86 utilities, so I had to write a simple program to extract the contents. The cramfs format has some documentation in order to do so. - A header: 0x500=1280 bytes, all zeros except the last four bytes: 26 10 70 96. Extract it with
Note: The files can be found here
- gle's blog
- Login or register to post comments
