Search code examples
encryptionchecksumcrcmpegcrc32

CRC32 Mpeg checksums don't match?


I've been trying to reverse engineer a crc32 checksum. I don't have access to the original J# code as it is compiled and decompiling it has not been helpful. I ran 10 payloads through reveng which returned:

width=32 poly=0x04c11db7 init=0xFFFFFFFF refin=false refout=false xorout=0x00000000 check=0x0376e6e7 name="CRC-32/MPEG-2"

I tried running the packages through two different python libraries and even constructed an objective-c algorithm to try to get the known checksums. The recreations all matched each other, but they did not match the original checksums. Any ideas?

Here are the original and calculated crc32 checksums:

original  -> calculated

1.  0x99c93052 -> 0x13bc2c5c
2.  0xb5cea403 -> 0x1fd00c8e
3.  0xc7e4f40c -> 0xf9698bd6
4.  0xabe5ad28 -> 0x6be300d6
5.  0x2dacbf16 -> 0x43b2c356
6.  0xf321c2E9 -> 0xacb5981a
7.  0x01430cb6 -> 0x2f9e64ee
8.  0xa1028afb -> 0x44c7182b
9.  0xe73118e6 -> 0xd6c1ffa5
10. 0x5f366305 -> 0x84961d17

Any and all suggestions are appreciated!

Edit:

As per request here are original payloads with their CRC-32/MPEG-2 checksum and their calculated checksum:

1. Payload = d3b09900005500005469746c653a090954657374207469746c652020202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000
   Orig = 0xf9297a54
   Calc = 0xebcc0d91
2. Payload = d3b09900004300005469746c653a090954657374207469746c652032202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000
   Orig = 0xb518dad0
   Calc = 0x45e4e895
3. Payload = d3b09900004300005469746c653a090954657374207469746c652033202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000
   Orig = 0xe367073b
   Calc = 0x5db5800c
4. Payload = d3b09900004300005469746c653a090954657374207469746c652034202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000
   Orig = 0x44d90b1d
   Calc = 0x14039bc3

This is one way I calculated those checksums (although pycrc and the objective-c code I implemented all gave the same results):

>>> import crcmod.predefined
>>> s = 'd3b09900004300005469746c653a090954657374207469746c652034202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000'
>>> crc32_func = crcmod.predefined.mkCrcFun('crc-32-mpeg')
>>> print hex(crc32_func(s))
0x14039bc3

The above code used payload example 4. As you can see the calculated checksum (0x14039bc3) does not match the original checksum that came with the payload (0x44d90b1d).


Solution

  • So it turns out just passing the hex as a string doesn't end up with the right checksum via the python library crcmod. It won't take a bytearray either, which seemed to be a more probable way of calculating an accurate checksum. What you need to do is pass the bytearray as a buffer, and then the correct checksum is calculated.

    Using the example in the question:

    >>> import crcmod.predefined
    >>> s = 'd3b09900004300005469746c653a090954657374207469746c652034202020202020202020202020202020202020202020202020202020200a4172746973743a09095465737420617274697374202020202020202020202020202020202020200a43443a0909095465737420434420202020202020202020202020202020202020202020200a4c6162656c3a0954657374204c626c202000'
    >>> h = s.decode("hex")
    >>> b = bytearray(h)
    >>> crc32_func = crcmod.predefined.mkCrcFun('crc-32-mpeg')
    >>> print hex(crc32_func(buffer(b)))
    0x44d90b1d
    

    So there you have it. It was mostly just a lack of understanding of how CRC checksums are calculated I guess. Hope this ends up helping someone else.