dev builds
themes manual
device status forums
mailing lists
IRC bugs
dev guide

Wiki > Main > IfpCryptanalysis (compare)

Difference: IfpCryptanalysis (r23 vs. r22)

Notes on iFP firmware encryption


iRiver's iFP device firmware is encrypted.. which isn't a big surprise because iHP's firmware is encrypted.

Analysis has shown us that there are some popular 16-byte strings. After a careful look, we noticed these blocks fit together.. and came up with these 256 bytes:

        0x23, 0xd0, 0xef, 0x42, 0x54, 0x4d, 0xa5, 0x23 , 0xae, 0x69, 0x92, 0x47, 0x2e, 0x5a, 0x9c, 0x05,
        0xb2, 0x0e, 0x96, 0x97, 0xdb, 0x19, 0xbb, 0x84 , 0xc2, 0xe7, 0x28, 0x55, 0x23, 0xa0, 0x90, 0x55,
        0x62, 0x99, 0x18, 0x0c, 0x80, 0x21, 0x9c, 0x52 , 0x1f, 0x06, 0xe7, 0x4a, 0x54, 0x52, 0x36, 0x53,
        0xf6, 0xbf, 0x11, 0x90, 0x8b, 0xaf, 0x91, 0x81 , 0x6a, 0x3d, 0x15, 0xa5, 0xde, 0x83, 0x4a, 0x66,
        0xfe, 0x47, 0x47, 0xa6, 0x35, 0xea, 0x6b, 0x66 , 0x02, 0xaf, 0x95, 0x59, 0x54, 0xb9, 0xfa, 0x0f,
        0xb8, 0xf4, 0x2a, 0xb8, 0x7b, 0xb3, 0x2c, 0x66 , 0xe9, 0xa5, 0xfe, 0xfe, 0x33, 0x0a, 0x31, 0x90,
        0x99, 0x42, 0x33, 0x48, 0x0a, 0x8f, 0x2a, 0x23 , 0x6b, 0x42, 0x33, 0x1f, 0x3c, 0x23, 0x81, 0x6c,
        0xe0, 0x5e, 0x81, 0xf1, 0xa8, 0x25, 0xc9, 0x90 , 0x90, 0x6f, 0x55, 0xc9, 0x2a, 0x2c, 0xb4, 0xc0,
        0x82, 0x21, 0xa9, 0x33, 0x6f, 0x70, 0x10, 0xae , 0x39, 0x2a, 0x1a, 0x28, 0xac, 0x8d, 0xb0, 0x78,
        0xaa, 0x1e, 0x90, 0x2a, 0xfe, 0x97, 0x2c, 0x8f , 0xfa, 0x86, 0xd4, 0x2a, 0xbd, 0xaf, 0x20, 0xb2,
        0x69, 0x48, 0x14, 0xb5, 0xbf, 0xdc, 0xfd, 0xb1 , 0xbe, 0xed, 0x19, 0x4c, 0x16, 0x0a, 0xdd, 0x4d,
        0xa1, 0x45, 0xa4, 0x83, 0xdc, 0xf3, 0x0c, 0xfa , 0x16, 0x0a, 0xe8, 0x20, 0x30, 0x5d, 0x5b, 0x42,
        0x5d, 0x5b, 0x98, 0x01, 0x1f, 0x43, 0xb5, 0xf3 , 0x71, 0x52, 0xaa, 0x8c, 0xae, 0x84, 0x3d, 0x40,
        0xdd, 0x06, 0x03, 0xed, 0x9d, 0x92, 0x33, 0xc8 , 0x0d, 0x90, 0xfb, 0xc4, 0x59, 0xf0, 0xc1, 0xd2,
        0x5a, 0xd2, 0xbb, 0x5f, 0x68, 0xd5, 0x0d, 0x7c , 0x84, 0xf1, 0x58, 0x5a, 0x2c, 0xb5, 0x32, 0x68,
        0xc6, 0xd2, 0x48, 0x75, 0x03, 0x9d, 0x8d, 0xd8 , 0xee, 0xec, 0x0a, 0xb5, 0x10, 0xf6, 0x11, 0xbd

They always occur at the same offsets within 256-byte blocks. It's suspected that these bytes are "zero"s. (Yes, we've tried xoring the entire file with the above 256 block.. doesn't do much.)

LinusNielsenFeltzing: For what it's worth, all versions of the iFP5xx firmware .hex file start with the same 13 bytes:

0x39, 0xb0, 0x5d, 0xed, 0x12, 0x0d, 0xab, 0x5e, 0x85, 0xf2, 0x44, 0x5c, 0x2e

Also, the first 512 byte block differs a lot between the versions. This might mean that the first 512 bytes is a checksum array or something.

I compared the first 128k of the US and EU versions of the iFP5xxT factory 1.00 firmware. Very few differences up to about 0x11490, where the files go totally apart. In fact, most firmware versions differ very little in the beginning, except for the first 512 bytes.

The first 32 bytes of the firmware is very likely to be the exception vector table. If I understand it correctly, ARM exception vectors consist of an unconditional branch instruction. The ARM7 opcode of an unconditional branch is 0xEAxxxxxx, where xxxxxx is the offset. The reset vector offset is likely to be small, so we can probably assume that the second byte of the opcode is 0x00. The Reserved vector is probably 0x00000000. This gives us a nice beginning of a crib:

ea, 00, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, ea, ??, ??, ??, 00, 00, 00, 00, ea, ??, ??, ??, ea, ??, ??, ??

GeoffOakham - 10 Mar 2005: Interesting idea about the checksum. There seems to be 240 bytes of "random" data at the begining, and the firmware files each have around 10778 blocks of 256 bytes. iHP had 1byte checksums for each 256 block, so iFP firmware obviously does something different. Any guesses as to how this checksum might work?

Ideas & discussion

Taking a page out of Dave's book, I've converted various firmwares into graphics. My results are in a separate page because they're quite large: IfpCryptanalysisGraphic1.

GeoffOakham - 11 Mar 2005: I've been studying various graphics, and there appears to be something happening every 51 bytes. (In 512pixel wide bitmaps, these looks like lines.)

GeoffOakham - 12 Mar 2005: Confirmed. Each 256 byte block seems to be made of 5 groups of 51 + 1 extra byte. Also, the last byte of each sub-group, and the last byte of the whole block seem to be different from the others. They might be checksums: 50 bytes data, 1 byte checksum... and ending with a whole-block checksum. Take a look in the red channel of the attached picture. Green is the "raw data", red is 255 when the byte matches the [suspected] key, and blue is 255 when the byte one of the ones in the suspected key. That sounds more complicated than it has to: but the red highlights data that is probably zero.

RaulAguaviva - 14 Mar 2005: Added a SimpleFirmwareCrack

TomekMalesinski - 17 Jun 2005: I think I have decrypted the firmware. After looking at differences between the US and EU versions of the firmware and doing some frequency analysis (the last byte of an ARM opcode is usually 0xe5 or 0xe3) I assumed that the encrypted value of a byte depends only on its decrypted value and its position within a 256 byte block. So, in order to decrypt the firmware we need to know the function decrypt(position, byte), where position is a number between 0 and 249 and byte is between 0 and 255. Most probably there is a simple formula describing the function, but I have not tried to find one yet. Zeroes are encrypted in the way shown above on this page. Knowing which bytes are zero and which are not I was looking for lookup tables from the Tremor decoder. The tables were big enough to be found at unique positions. Those tables were stored at different positions in different versions of the firmware, so from each firmware I could recover decrypt function values for some arguments. After that I could decode 70% of the firmware. Looking at an incomplete table of the function I noticed that some rows are just some other rows xored by some number. More precisely, for some numbers a and b there was a number x such that decrypt(a, i) = decrypt(b, i) xor x for all i. I found pairs of rows for which the above condition was, as far as I could tell from the incomplete table, satisfied. Then I assumed that if the condition was true for most numbers in the row, then it must have been satisfied by the rest of the numbers. This way I completed the table.

I am not sure whether all the 250*256 values found by me are correct. The decrypted firmware looks quite right, but as every single value in the table affects only about 20 bytes in the firmware, it is difficult to spot mistakes. To make sure that the decryption was correct someone should find a simple formula for the decrypt function or find the decryption procedure in the firmware.

I have not investigated what the meaning of those extra bytes in 256 byte blocks is. Probably they are checksums.

I attach the decryption program together with values of the function. This version is slightly different than the one that was here before the Wiki was deleted. Now, the key.bin file is compiled into the executable, so it is not required after the compilation. The program can be run in two ways:

  • decrypt the input file and save it as one output file with a header:
         ifp_decode in.hex out.bin
  • decrypt the input file and save it as two files without a header
        ifp_decode -f 2files in.hex out1.bin out2.bin
    The first output file will contain what is probably stored in the internal flash ROM of PNX0101 and the second one will contain what is probably stored in the external flash ROM.

CoreyCason? - 20 Jul 2005: After looking at Dave's iHPBMP utility (and source), I wondered if the iFP f/w images would decode the same way as in the iHP-120 f/w. I wrote a crude app (based on Dave's algorithms) to process the whole file as if it were stored as bitmap data (I used v1.25, decoded). Of course, the whole file isn't encoded as bitmap data, but I figured something might jump out at me. It turns out that a large portion of the firmware image is devoted to non-english fonts, and the tail end of the firmware holds most (if not all) of the images used (see bitmap_decoded.gif). I've extracted a few random images fw_images.gif. (Update 22 Jul 2005): Reloaded bitmap_decoded.gif after processing it based on 1 bit-per-pixel encoding (previously based it on 2 bpp). I have successfully modified images and flashed my ifp-899 w/ modded firmware (updated images) with no ill effects. I have modified Dave's ihpbmp code to extract and change out images in the ifp firmwares and will share it when I get it cleaned up.

MariusSiegas - 20 Nov 2005: I've noticed that when the decoded bytes are zeroes the checksums at 51-st byte are: 17, 143, 250, 140, 17 and the checksum at the end of block (for all zeroes): 189 allways. My guess is that the checksumming takes place before the encoding so these could be simple sums but encoded in the same way as all the other bytes (thus the tables should be 256x256 not 256x250 if I'm right).

Are there any more new known things? It seems this page isn't touched for a while... Messing around with my new T20, the iFP decoder seems to be working, just that you can't encode anything with it due to the lacking checksumming. Would really like to change my f/w to non-european one due to the fact that my player eats music only from windows... No way to access it from my Linux box (happy to have win at work at least).

-- OlleBergkvist - 11 May 2007: I have tried the ifp_decode program, and it seems to success on my E10 firmware ver 1.04. I have a lot of promising text strings in the decrypted file.

-- OlleBergkvist - 18 April 2010. The "Hacking the iriver T10" project (see the References paragraph) has a program, irde, that performs both encryption and decryption of S10, IFP7xx, and others. I tried both encryption and decryption on various firmware images and it seems to work fine, and decryption and encryption was consistent with ifp_decode. The algorithm is much more figured out than in ifp_decode, and the checksums are verified in decoding, and calculated when encoding.

However I ran into problems when i tried running irde on E10's firmware. It seems on the positions in the blocks where there should be checksums (offset x*51 + 50, and offset 255), large parts of the E10 firmware has no checksums but something else entirely. Even if the contents of the blocks varies, the "checksums" stays the same, so they're not checksums. I worked around this by adding a cmd-line option to irde that makes it ignore checksum errors entirely. (Patched version is attached below.) Note that since we don't know what the "checksum" bytes do in this firmware, we don't know if encryption is correct or not. Especially not if these bytes represent FW content and are skipped during decoding. Right? This applies to both ifp_decode and irde. Encryption is not possible either since irde recreates the "checksums" and not the original bytes... encryption decryption is correct or not. Especially not if these bytes represent FW content and are skipped during decoding. Right? This applies to both ifp_decode and irde. Encryption is not possible either since irde recreates the "checksums" and not the original bytes...


DaveHooper, RaulAguaviva, and GeoffOakham are currently working on this problem. Send us email if you'd like to contribute.


  • irde.c: irde.c from the T10 project, modified to accept E10's firmware
ifp-5xx-1.16_unkeyed_rgb.pngpngifp-5xx-1.16_unkeyed_rgb.pngmanage 2176.0 K 11 Jul 2006 - 21:10GeoffOakham Green is firmware, blue/red are highlights
ifp_decode.tar.gzgzifp_decode.tar.gzmanage 60.2 K 11 Jul 2006 - 21:10TomekMalesinski Firmware decoder
irde.ccirde.cmanage 11.9 K 18 Apr 2010 - 20:20OlleBergkvist irde.c from the T10 project, modified to accept E10's firmware

r23 - 10 Jun 2010 - 01:51:50 - OlleBergkvist

Revision r23 - 10 Jun 2010 - 01:51 - OlleBergkvist
Revision r22 - 18 Apr 2010 - 20:37 - OlleBergkvist
Copyright by the contributing authors.