I'm working on reverse engineering the serial communication protocol of an obsolete electronic control system, but I'm having trouble figuring out the CRC algorithm and polynomial.I have reverse engineered another similar system made by the same company in the past. On that previous one I was able to dump the 8051 micro-controller program from the EPROM and disassemble it. Here is my working code in C, with the original 8051 disassembly in the comments:unsigned char CalculateChecksum(void) {    unsigned char r1 = 0;               // MOV R1,#0    unsigned char r2, r3, c, a;    for (r2=1; r2<4; r2++) {    // MOV R2,#07        a = out_buffer[r2];     // MOV A,@R0        r3 = a;                 // XCH A,R1        a = r1;        r1 = r3;        c = 0;                  // CLR C        if (a & 0x80) {            c = 1;              // FAKE CARRY        }        a = a << 1;             // RLC A        if (c == 1) {           // JNC 0x03E8            a = a ^ 0x19;       // XRL A,#19        }        a = a ^ r1;             // XRL A,R1 (0x03E8)        r1 = a;                 // MOV R1,A        printf(%d: 0x%x , r2, a);    }    return a;}The problem is that this function does not work on this newer system. I've tried all 255 possible polynomials, so it is unclear wether the algorithms are shared (perhaps with some modifications?) between the different systems, however I believe there is a relation between algorithms.Here is a capture of some of the transmitted message from one unit:7E 00 12 03 00 50 FB 01 60 7E 00 12 03 00 50 FB 01 60 7E 00 12 03 00 50 FB 01 60 7E 00 12 03 00 50 FB 01 60 7E 00 12 03 00 51 FB 01 61 7E 00 12 03 00 51 FB 01 61 7E 00 12 03 00 51 FB 01 61 7E 00 12 03 00 51 FF 01 65 7E 00 12 03 00 51 03 00 69 7E 00 12 03 00 51 09 00 6F0x7E appears to be a preamble, followed by 7 bytes of data, then the checksum byte. Can anyone figure it out?
Reverse engineering serial communication CRC algorithm
serial communication;crc;binary diagnosis
This question seems simpler than you might expect.Since as OP noted, the code is irrelevant to validation mechanism used in the discussed system, I shall ignore it. It is indeed irrelevant as will be shown below.as the first byte in each message indeed looks like a preamble, we'll ignore it. Our goal is to recover the function which, when applied to the given 1-8th bytes (i.e. all bytes except the first and last), provides the last byte.Lets take the first message provided by OP:00 12 03 00 50 FB 01 60Thus, we need to find f such thatf(00 12 03 00 50 FB 01) = 60The following 3 messages are identical. This is good, it uncovers the fact the validation byte is deterministic with regards to the message bytes, but otherwise useless. We'll skip to the fifth message and compare it to the first:f(00 12 03 00 50 FB 01) = 60f(00 12 03 00 51 FB 01) = 61This is nice, we know that a single bit incremental change in the 5th byte of the message causes the exact same change on the output. Adding one to the fifth byte increments the output by one as well.The same happens for the last two messages:f(00 12 03 00 51 03 00) = 69 f(00 12 03 00 51 09 00) = 6F9-3 = 6 = 6F-69Only this time with a different byte and a bigger increment.We might be willing to assume this relationship is preserved for all bytes and all increments, and we'll be correct.If it wasn't clear until now, the answer is quite in front of us: The last byte is the sum of all message bytes, modulo 257.In python, given m = ['00', '12', '03', '00', '51', '09', '00'], the following code will provide the correct value of 0x6F:hex(sum(map(lambda x: int(x, 16), m))%257)This behaves properly for all provided inputs.