Skip to main content
Tweeted twitter.com/StackReverseEng/status/844122588389556224
Figured out my checksum problem
Source Link
user19009
  • 154
  • 1
  • 7
  • Type 1: One instance. Should be EOF, last record, but it's not. It is a record of zero payload length, as it should be, but I have one more record after it, Type 6.
  • Type 2: I have three instances. Should be Extended Segment Address, according to wikipedia the address field is typically zero and the data length should be two. That is what I see for all three instances.
  • Type 3: Comes just before the Type 1 (EOF?) record. Matches what Wikipedia tells me to expect for Type 3. Looks like: 3a 04 00 00 03 00 00 08 c1 30 0a. Maybe this is the CS:IP that wikipedia says?
  • Type 6: Last record, looks like: 3a 04 00 00 06 f9 f7 b1 9f b6 0a.

UPDATE: The checksum field in my file is actually the two's compliment, the original code I wrote was broken in several ways. Dang type-less python code. What eventually worked for calculating the checksum was:

def twos_comp(val, bits):
    return val - (1 << bits)        

def calc_checksum(record_byte_string):
    return abs(twos_comp(sum(record_byte_string)%256, 8))%256

So my only real question left is: what is the Type 6 record at the very end? I'm guessing its a 4-byte CRC over something, but I don't know what. Anyone seen this before?

  • Type 1: One instance. Should be EOF, last record, but it's not. It is a record of zero payload length, as it should be, but I have one more record after it, Type 6.
  • Type 2: I have three instances. Should be Extended Segment Address, according to wikipedia the address field is typically zero and the data length should be two. That is what I see for all three instances.
  • Type 3: Comes just before the Type 1 (EOF?) record. Matches what Wikipedia tells me to expect for Type 3. Looks like: 3a 04 00 00 03 00 00 08 c1 30 0a
  • Type 6: Last record, looks like: 3a 04 00 00 06 f9 f7 b1 9f b6 0a
  • Type 1: One instance. Should be EOF, last record, but it's not. It is a record of zero payload length, as it should be, but I have one more record after it, Type 6.
  • Type 2: I have three instances. Should be Extended Segment Address, according to wikipedia the address field is typically zero and the data length should be two. That is what I see for all three instances.
  • Type 3: Comes just before the Type 1 (EOF?) record. Matches what Wikipedia tells me to expect for Type 3. Looks like: 3a 04 00 00 03 00 00 08 c1 30 0a. Maybe this is the CS:IP that wikipedia says?
  • Type 6: Last record, looks like: 3a 04 00 00 06 f9 f7 b1 9f b6 0a.

UPDATE: The checksum field in my file is actually the two's compliment, the original code I wrote was broken in several ways. Dang type-less python code. What eventually worked for calculating the checksum was:

def twos_comp(val, bits):
    return val - (1 << bits)        

def calc_checksum(record_byte_string):
    return abs(twos_comp(sum(record_byte_string)%256, 8))%256

So my only real question left is: what is the Type 6 record at the very end? I'm guessing its a 4-byte CRC over something, but I don't know what. Anyone seen this before?

Source Link
user19009
  • 154
  • 1
  • 7

Anyone recognize this variant of Intel HEX firmware format?

I've got a firmware file for an ARM Cortex-M0+ that is in a format extremely similar to Intel HEX. All data is encapsulated in a 0x3a ... 0xa wrapper. The fields seem to mostly match the 16 bit Intel HEX structure, where the second field is definitely the record length, the next two are plausibly an address to load the payload. The next under Intel HEX should be the record type, and I'll cover what I see here in a second.

I see two significant variations from the standard Intel HEX (I have no experience with it, just what I've read)

  1. The fields are all specified in raw bytes, NOT ASCII representations of the bytes. So for instance, most records are 16 bytes long and hexdump shows: 0x3a 0x10 ... 0xa
  2. The last field before the record delimiter should be the two's compliment of the LSB of the sum of all fields. That is not what I'm seeing, and I don't know how it is being calculated. This is kinda important since I want to modify this firmware. Also, my python code for two's compliment calculation could be wrong, so feel free to tell me I'm just an idiot.

Any ideas what this format might be? Here's a little sample hexdump output:

00000000  3a 10 04 00 00 ff ff ff  ff ff ff ff ff ff ff ff  |:...............|
00000010  ff 7e fb ff ff 81 0a 3a  10 08 00 00 00 60 00 20  |.~.....:.....`. |
00000020  c1 08 00 00 49 93 01 00  4d 93 01 00 e1 0a 3a 10  |....I...M.....:.|
00000030  08 10 00 51 93 01 00 55  93 01 00 59 93 01 00 5d  |...Q...U...Y...]|
00000040  93 01 00 2c 0a 3a 10 08  20 00 61 93 01 00 65 93  |...,.:.. .a...e.|
00000050  01 00 69 93 01 00 6d 93  01 00 dc 0a 3a 10 08 30  |..i...m.....:..0|
00000060  00 71 93 01 00 75 93 01  00 79 93 01 00 1f 2f 02  |.q...u...y..../.|
00000070  00 4d 0a 3a 10 08 40 00  1f 2f 02 00 1f 2f 02 00  |.M.:..@../.../..|

Back to that record type field. Out of a 200kb file, I have only 6 records that are not of type 0:

  • Type 1: One instance. Should be EOF, last record, but it's not. It is a record of zero payload length, as it should be, but I have one more record after it, Type 6.
  • Type 2: I have three instances. Should be Extended Segment Address, according to wikipedia the address field is typically zero and the data length should be two. That is what I see for all three instances.
  • Type 3: Comes just before the Type 1 (EOF?) record. Matches what Wikipedia tells me to expect for Type 3. Looks like: 3a 04 00 00 03 00 00 08 c1 30 0a
  • Type 6: Last record, looks like: 3a 04 00 00 06 f9 f7 b1 9f b6 0a