Information about the binary structure of TPLink's TX6610 V4 firmware
I'm working on reverse engineering TPLink's TX6610 firmware. I have been able to successfully unpack and pack/compile the files from the firmware. I also have been working on actually parsing the header of the firmware's blob and getting information from it.
The firmware consists of several parts:
- 256 bytes header
- Kernel blob (starting at
0x100
) - RootFS blob (starting at
0x150000
) - Some sort of data appended to the end (starting at
0x350000
)
- Magic bytes (4 bytes):
HDR2
- Header size (
uint32_t
) - File size (
uint32_t
) Keep in mind this size doesn't include the "checksum ending data". Keep reading. - CRC32 (4 bytes) with a custom table (check
compress.py
). - Version (32 bytes)
- Customer version (32 bytes)
- Kernel size (
uint32_t
) The size that the LZMA blob takes (starting from0x100
) - RootFS size (
uint32_t
) The size that the SquashFS blob takes (starting from0x150000
) - ctrom size (
uint32_t
) - Model (32 bytes)
- Unknown 4 bytes
- 128 empty bytes
A CRC32 is performed on the the data starting at 0x100
and ending at 0x350000
. The CRC32 uses a custom table (check compress.py
)
Starts at 0x100
. It contains the kernel and it's compressed with LZMA.
Starts at 0x150000
. It contains the FS and configuration data. It also contains the web-admin, users/passwords, etc... You can mount it like any other squashFS file.
At 0x350000
there are 232 bytes of checksum data. After some more debugging of the firmware, I found how the firmware is validated.
Basically, the firmware blob is constructed the following way:
- write the header data
- write the kernel blob
- write
0x00
up to0x150000
- write rootfs blob
- write
0x00
up to0x350000
- write the first 212 bytes (starting from
0x350000
) of the original firmware - write the magic bytes (check
md5_magic
incompress.py
) - write 4
0x00
Now run an MD5 against that entire blob and then use the result to replace the magic md5 bytes.
You'll need squashfs
with LZMA support. On MacOS that would be brew install squashfs
.
Now download the firmware and move it to the folder where you cloned this repository.
Then extract the rootfs and unsquash it: python3 extract.py
and sudo unsquash rootfs.squashfs
.
Note that you need the sudo
because there are some special files (devices) in the /dev
folder.
Once you're done editing the files, squash everything: mksquashfs squashfs-root/ rootfs.squashfs -noappend -always-use-fragments -comp lzma
.
The last thing is to compress the firmware and you're done: python3 compress.py
.
I'm adding a simple python piece of code that extracts the different parts of the firmware and another one that joins them back together in a perfectly valid and working firmware.
I'm also adding a grammar file so you can easily analyze the firmware yourself.