reverse-engineeringcrccrc16

How do I detect if there is a CRC in a sequence of bytes?


Here's the data I have, I'm not sure the last 2 bytes are the CRC but it's my best guess. I've tried CRC-RevEng with no luck. What would be the best approach to try to figure out if the last 2 bytes are a CRC for sure? and then try to crack it?

Each line is a different hex string with the las 2 bytes being the CRC (my guess).

305B80DB3D009F04D9D848000110097C
305BA9983E00A304D9D852000110F3A3
305CA40340009F04D9D83C0001108730
305D364741009F04D9D84A000110C4F1
3066380443009F04CD883A000110B6B7
3066364842000254FFFF54870100528A
30CE692D4400002AFFFF0C870300F85B
30487DA239000254FFFF2495000006FD
305B7E6A3C000254FFFFC4A4000076FA
305C7D063F000254FFFF64B400005D30
30E2570E78009A08400017000110195D
30E4558679009904400030000110846C
30E16A7575009F04400037000110031A
30E18AD27600A30440005000011074E7
30E23B0D77009704400001000110FFEE
30E4558679009904400030000110846C

Solution

  • Yes, the last two bytes are a 16-bit CRC. This will compute it (in C):

    #include <stddef.h>
    #include <stdint.h>
    
    uint16_t crc16(uint8_t const *data, size_t len) {
        uint16_t crc = 0;
        for (size_t i = 0; i < len; i++) {
            crc ^= (uint16_t)data[i] << 8;
            for (int k = 0; k < 8; k++)
                crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
        }
        return crc ^ 0xa96a;
    }
    

    The result is placed at the end of the message in little-endian order.

    Since all of the messages are of the same length, it is not possible to tell what both the initial value and the final exclusive-or are. I arbitrarily set the initial value to zero. If you have one message of a different length with the CRC, then those two can be solved for.