Hashes


From SamyGO
Revision as of 21:35, 26 February 2014 by Hedak (talk | contribs) (Added some 0.02 feature descriptions and download links)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

WORK IN PROGRESS, NOT FINISHED YET! Ned to remake and update


getmkey utility

To calculate hashes you will need a 128-bit key which can be obtained from the TV or blu-ray player using getmkey utility. Check file getmkey/Makefile to get the idea how to build getmkey program, upload it to the TV or player and run it. If you do not wish to install a toolchain for cross-compilation, you may try prebuilt binaries: getmkey or getmkey_static.

If you have root access to the TV or player, run getmkey. You should get the output which looks like this:

opening /dev/mem ok!
No key was supplied from a command line.
Using mackey from /dev/tfsr11
Input key = 86d446c947765600a4a83098e6ee7ae2
After waiting 1 loops
mkey='2b7e151628aed2a6abf7158809cf4f3c'  	# for BD-C6900 player
#mkey='7ced26d8ca2fa0f80bc637e2ff07ec46'  	# B series
#mkey='6f6bc7e1fc7f86bf9c150a82f343e2e0'  	# for T-VALDEUC-1014.3 TV

./chkhash -k 7ced26d8ca2fa0f80bc637e2ff07ec46 -h 3665940 rootfs.img

Last line of the output contains an mkey which will be used in chkhash program:

Printing hashes

./chkhash -p offset n file              : prints <n> hashes at <offset> in <file>
                                         offset less than zero means offset from the end of the file.

Example: print hashes in dumps from /dev/tbml9 and /dev/tbml10. Here and below we assume that dumps from firmware partitions /dev/tbmlX are stored in files tbmlX.bin, and dumps from /dev/stl0/X are stored in files stl0-X.bin.

./chkhash -p 0 6 tbml9.bin
hash[ 0] = cb82e0476eecfe10b7415c099c34a53f   length = 39735296
hash[ 1] = efb116822ffe713571b988f4bd71fb14   length = 36028416
hash[ 2] = 66d50c94a62cb51cf51482e77c74e267   length =  3104328
hash[ 3] = 1b8f9aa5846d4d8624482c183cb9c147   length =  4190228
hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510
Only 5 hashes were detected

./chkhash -p 0 6 tbml10.bin
hash[ 0] = 25a3d13599932da3d255a749f1fe7581   length = 41050112
hash[ 1] = 2c23831d821407d180607890c07d4d22   length = 37797888
hash[ 2] = 60a8d999f3b6da20c58a3eb2056d43d6   length =  3104328
hash[ 3] = b0dac74b78a6814149187cf4d660f1f5   length =  4190228
hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510
Only 5 hashes were detected

Or print hash for /bin/authuld file (this hash is stored at the offset 4096 bytes from the end of RootFS image in /dev/tbml6 or /dev/tbml8):

./chkhash -p -4096 1 tbml6.bin
hash[ 0] = 7fe99ddcf4c6c67f68374dbc60879f64   length =    36308

./chkhash -p -4096 1 tbml8.bin
hash[ 0] = 941137492edd0c83b489c665d6335295   length =    36308

Calculating hashes

./chkhash -k mkey -h length file        : calculates and prints hash from the first <length> bytes of the file.
                                         if length is 0, the hash is calculated for full file length.

Example: if you have a copy of an authuld in current directory, run

./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -h 0 authuld
Hash: 941137492edd0c83b489c665d6335295, length = 36308

Or you can calculate, for example a hash for bootloader (in /dev/tbml1):

./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -h 123510 tbml1.bin
Hash: 7bca4cf5f259475adac2c57965d7d6f1, length = 123510

Calculating and comparing hashes

./chkhash -k mkey -m length file hash   : calculates hash from the first <length> bytes of the file and compares with <hash>
                                         prints no result, useful in scripts only: return 0 if hashes are equal
                                         if length is 0, the hash is calculated for full file length.

Looking for dumps whose hashes are stored in a hash block file (CMAC):

./chkhash -k mkey -L offset n hashfile file1 file2 ... fileN
                                        : checks if <n> hashes stored at <offset> in a <hashfile> match
                                        : with hashes for <file1> <file2> ... <fileN> 

Example: tbml10.bin (dump from /dev/tbml10), as shown above, contains a set of hashes for some files. Let's find these files (search will take some time because of calculation of hashes for many files):

./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -L 0 5 tbml10.bin tbml*.bin stl0-*.bin
hash[ 0] = 25a3d13599932da3d255a749f1fe7581   length = 41050112  :  stl0-16.bin
hash[ 1] = 2c23831d821407d180607890c07d4d22   length = 37797888  :  stl0-17.bin
hash[ 2] = 60a8d999f3b6da20c58a3eb2056d43d6   length =  3104328  :  tbml7.bin
hash[ 3] = b0dac74b78a6814149187cf4d660f1f5   length =  4190228  :  tbml8.bin
hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510  :  tbml1.bin

Here these files contain:

stl0-16.bin	: mtd_exe
stl0-17.bin	: mtd_appdata
tbml7.bin	: kernel
tbml8.bin	: rootfs
tbml1.bin	: bootloader

Calculation of hash block (CMAC) for firmware modification

./chkhash -k mkey -H outfile file1 file2 ... fileN
                                        : creates hash block (cmac) for given input files

Hashes are written in the same order as supplied files. This can be used for building a hash block (CMAC) if you modify some firmware partitions.

Save given key to binary file

./chkhash -S key file : saves given hex <key> (16 byte) to binary <file>
                        <file> is created if not existent and overwritten if already existent

Example:

./chkhash -S 6f6bc7e1fc7f86bf9c150a82f343e2e0 /mtd_rwcommon/test.bin

will create the file /mtd_rwcommon/test.bin with content (hex view): 00000000 6F 6B C7 E1 FC 7F 86 BF 9C 15 0A 82 F3 43 E2 E0 okÇáü.†¿œ..‚óCâà


Write calculated hash to file

./chkhash -k mkey -w offset k hashfile file : writes calculated hash for <file> (full length) at hash position <k> in a hash 
                                              block located at <offset> in <hashfile>
                                              offset less than zero means offset from the end of the hashfile

Example:

./chkhash -k 6f6bc7e1fc7f86bf9c150a82f343e2e0 -w 0 0 /mtd_rwcommon/bml10.dmp /mtd_rwcommon/mtd_exe_part.dmp

will write the calculated hash of /mtd_rwcommon/mtd_exe_part.dmp ('_part' indicates that the dump is cut to the length read in /dev/bml0/10, for example using 'dd' to dump the first xx blocks only) in /mtd_rwcommon/bml10.dmp with no offset (0) and update the hash at index 0 (i.e. the hash of /mtd_exe)

mknewfs.sh

This an example script to create a modified version of rootfs, mtd_exe or mtd_appdata. Please check it carefully before using. I did not test it for flashing my own firmware, so be careful. Read comments explaining the whole process and, anyway, you must accept any risk of possible bricking your TV or player.

Other remarks

Note that you will also need to know how to switch partitions for booting. Flashing of active (mounted) partition is dangerous, so you can only flash inactive (currently unused and unmounted) partition. So, first you will need to find which partition is active now. Run the following command in your device:

# df
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/tbml8                2880      2880         0 100% /
none                     10240        20     10220   0% /dtv
none                     60204         0     60204   0% /core
/dev/stl0/17             36928     36928         0 100% /mtd_appdata
/dev/stl0/16             40128     40128         0 100% /mtd_exe

This is for BD-C6900 player. Other devices may have other filesystem structure, so procedure described here may be different. Here we can see that active devices are /dev/tbml8 /dev/stl0/17 /dev/stl0/16 which belong to second partiton and their CMAC data (hashes) are stored in /dev/tbml10. Therefore we can flash first partition: /dev/tbml6 /dev/stl0/15 /dev/stl0/14 and write their hashes to /dev/tbml9.

If we assume that dumps from firmware /dev/tbmlX are stored in files tbmlX.bin, and dumps from /dev/stl0/X are stored in files stl0-X.bin, first of all we need to copy currently active files to prepare them for first (now inactive) partition:

cp tbml8.bin tbml6.bin      # rootfs
cp stl0-17.bin stl0-15.bin  # mtd_appdata
cp stl0-16.bin stl0-14.bin  # mtd_exe
cp tbml7.bin tbml5.bin      # kernel

Also, we need to copy hashes:

cp tbml10.bin tbml9.bin

Now we can start to modify the firmware: run

mknewfs.sh tbml6.bin tbml9.bin

for the first time to unsquash the rootfs. Then go to the tbml6.bin.rootdir and do necessary changes. Create new rootfs by running the same script again. You will get two files: tbml6.bin.new and tbml9.bin.new which contain new rootfs and new CMAC ready for flashing to /dev/tbml6 and /dev/tbml9. You may also modify mtd_exe by running

mknewfs.sh stl0-14.bin tbml9.bin

two times: first, to unsquash filesystem, and second time after your modifications to build new mtd_exe.

After flashing modified filesystems, kernel and hash block (CMAC), you will need to switch partitions to boot into your modified filesystems. That's it!

How to flash firmware partitions and switch them: this probably can be found elsewhere...

Note that I did not try that. So, consider this just as some theoretical analysis. Study it, check for possible errors, and use it on your own risk.


Download chkhash sources and precompiled getmkey chkhash-0.2.zip

Download precompiled chkhash for arm [1]

Download precompiled chkhash for win32 [2]

References

Discussion on the SamyGO forum (can`t decide which subforum it belongs to...)