-
Notifications
You must be signed in to change notification settings - Fork 9
Case Study: Unkown Firmware Container
Congrats! You have an unknown firmware container and not only one but multiple files of the same container type.
First you will try to discern common and uncommon bytes between the containers. Any magic or other useable info for a file type will be shared among all files and usually at the same offset. To identify common bytes you can either "look on the files" or use tooling to help your poor eyes find them faster. Luckily in about XX % of the cases (XX being somewhere in the 80s, according to my experience) the magic will be at the very start of the binary (think of ELF
in elf binaries). As existing tool for help I would propose binwalk with the -W flag. You can also write some short python script to identify common bytes.
Let's look at an example:
$ xxd -c 32 -l 32 TL-MR3420_5_1.2.0.bin.enc
00000000: 5344 4e00 0105 3038 2e34 362e 3433 0000 59b1 c160 0012 d1a4 0017 860d 3cf6 da46 SDN...08.46.43..Y..`........<..F
$ xxd -c 32 -l 32 TL-MR3420_5_1.3.0.bin.enc
00000000: 5344 4e00 0105 3137 2e30 392e 3432 0000 5a29 c7f0 0006 9930 0008 3f7c 4385 b248 SDN...17.09.42..Z).....0..?|C..H
$ xxd -c 32 -l 32 TL-MR3420_5_1.4.1.bin.enc
00000000: 5344 4e00 0105 3137 2e32 352e 3436 0000 5b46 7de0 0006 9942 0008 3f93 7f8e 9386 SDN...17.25.46..[F}....B..?.....
You can see there are a total of 12 bytes shared among all three container files.
5344 4e00 01-- ---- 2e-- --2e 34-- 0000 ---- ---- 00-- ---- 00-- ---- ---- ----
- The first 5 bytes look most promising, since they represent the largest shared block and at least the first three bytes are ascii letters.
- The 6th, 7th and 8th shared byte are also connected, but looking at their surroundings reveals them to be part of a larger ascii string that might represent some version and is not completely shared among all files
- Shared bytes 9 and 10 are both "Zero" bytes and might represent some padding while numbers 11 and 12 could be most significant bytes of a 32-bit integer.
While it would be possible to develop a magic signature for any or all of these bytes, a sensible way would be to either
- take the first 5 bytes (better chance to avoid false positives)
- take only the first 3 bytes (better chance to avoid false negatives) having more containers at hand could help choosing correct. We will take the former (5 bytes) approach in this case study.
The common bytes are 53 44 4E 00 01
. In file magic definition one can define a series of bytes as string:
0 string \x53\x44\x4E\x00\x01 Some unknown container
where 0
is the offset of our string in the file string
is the type definition (for more on types see the docs), \x53\x44\x4E\x00\x01
is our string and Some unknown container
is the "full" file type that will be shown if our signature is found.
To enable the file command of also showing a mime type you have to add a !:mime
definition after the signature:
0 string \x53\x44\x4E\x00\x01 Some unknown container
!:mime application/unknown-container
This signature can now be appended to a magic database of your choice. If you just want to test it, store it in a file (e.g. signature.file
) and compile this file using the file command:
$ file -C -m signature.file
The command will generate a file called signature.file.mgc
which you can now use with file:
$ file -m signature.file.mgc TL-MR3420_5_1.3.0.bin.enc
Some unknown container
$ file -m signature.file.mgc --mime TL-MR3420_5_1.3.0.bin.enc
application/unknown-container
See? Not that hard 😉 Have fun writing your first (or whichever) file signature.