# Reverse engineering a CRC byte of a message

Hello everyone

I have a big problem reverse engineering a CRC of a byte array.

I posted this question on reverseengineering.stackexchange.com
So i tought I might try my luck here

Anyway I have a pH probe that communicates with the measuring device via RS485.

Here are some captured bytes from pooling the probe with the original controller.

00 01 01 00 00 00 13 00 c0 08 00 db 44
00 01 01 00 00 00 14 00 c0 08 00 dc a4
00 01 01 00 00 00 15 00 c0 08 00 dd 84
00 01 01 00 00 00 16 00 c0 08 00 de e4

00 01 01 00 00 00 16 00 b6 08 00 a8 57
00 01 01 00 00 00 16 00 b7 08 00 a9 5f
00 01 01 00 00 00 16 00 b8 08 00 a6 27

The first five bytes represent the message ID. The sixth is checksum for the message ID, the seventh and eighth represent mV from the probe (Seventh byte is LSB and eighth is MSB)
Nineth, tenth and (i think) eleventh bytes are the temperature. Tvelveth byte is 8-bit XOR checksum of the seventh to eleventh bytes.
The last one is a mystery to me.

Here only the mV change by 1

00 01 01 00 00 00 13 00 c0 08 00 db 44
00 01 01 00 00 00 14 00 c0 08 00 dc a4
00 01 01 00 00 00 15 00 c0 08 00 dd 84
00 01 01 00 00 00 16 00 c0 08 00 de e4

And here only the temperature changes by 1

00 01 01 00 00 00 16 00 b6 08 00 a8 57
00 01 01 00 00 00 16 00 b7 08 00 a9 5f
00 01 01 00 00 00 16 00 b8 08 00 a6 27

I think the last byte is dependent of the payload and not the message ID or its checksum. One of the messages (i have it logged at work) where the payload was 00 the checksum was also 00 and the last byte was also 00.

If anyone can shine some light on how to calculate the last byte I would very much appreciate it

Thank you!

If the last byte is a CRC check, the program RevEng works very well, but you have to be certain which part of the message is included in the CRC calculation.

However, I doubt that the last byte is the result of a CRC, because you expect several bits in the CRC check to change, even if only one bit in the message changes. It might be a parity check instead.

Considerable trial and error may be required to solve this.

I have been using RevEng for a week now. I tested several variants with no success. With maybe three messages i get crc calc parameters but they don't work with other messages. But mostly i got no module found... I was starting to think the probe uses some custom lookup table.

Could you point me to the right direction on how parity check works or how can I calculate it?
It makes no sense to me why would the make a probe with checksum for the message and for payload and then another check at the end only for payload

It makes no sense to me why would the make a probe with checksum for the message and for payload and then another check at the end only for payload

If you want very high reliability, multiple different checks are required. The message structure made sense to someone.

For an 8 bit CRC, the chance of a random nonsense message passing the check is 1/256, which is certainly not negligible.

Parity checks check the bit pattern or some subset of it for the number of "1" bits. The number of "1"s plus the parity bit must be even or odd to pass, depending on the variant.

Another possibility is an exclusive OR of some subset of the message, which is a similar concept to parity checks.

But doesn't parity check only yield true or false or 0 and 1? How would someone calculate a byte from this?

I'm sorry for stupid questions but in the past I never crossed paths with checksums,CRCs and parity checks

How would someone calculate a byte from this?

Easily. Have a bytewise parity check, where the bit significance in each message byte is retained. For example, bit7 of the parity byte is the parity bit check for all bit7s in the message.

And here only the temperature changes by 1

Data like this are not necessary useful.

It is much more useful to collect messages where the data differ by only one single bit, for example when the temperature goes from 0 to 1, or from 2 to 3 (but not from 1 to 2, because two bits change).

If you collect a bunch of messages that exhibit single bit changes in the data fields and post them, I or others may be able to help you solve this problem.

But first, please explain why it is important to do so. You don't need integrity checks to simply interpret the message content.

Do I remember correctly that a parity check exclusive-or each byte of a message and if the end resulting byte was zero, the parity was zero? If non-zero, the parity was considered 1?

Paul

Who can remember details like that? That is what the web is for!

jremington:
But first, please explain why it is important to do so. You don't need integrity checks to simply interpret the message content.

You are right. Curently I an ignoring those bytes.. The problem is with initialization. I dont hava the data with me now, but to get data from the probe I need to repeatedly send a "query" message to the probe so I get a response like I posted them.
But the thing is that before I can start pooling the probe for measurments I need to send an initialization message (only once at power up) and then I can get responses from the probe.

The Init message is different for every peobe. I can copy it with the original controller and n RS458 to usb converter. But in about a year and a half or maybe rwo years when pthe probe will need to be changed I will not remember how to get the new init code :).

That is why I need to calculate the last byte. The init message is only 2 bytes wide plus the checksum and the las bit. If I could calculate the las bit I can brute force the 2 bytes to get the init.

I am not keen on brute forcing 3 bytes @10Hz it would take 19 and a half days to ID the initialization (worst case). This is for a friends aquarium to very accuratley monitor thepH of the water and calculate the co2 with carbon hardness so we can control a co2 valve. I got this one (and a few broken ones) from a co worker. I could buy some analog hobby ones but the accuracy is not good for this kind of task

jremington:
It is much more useful to collect messages where the data differ by only one single bit, for example when the temperature goes from 0 to 1, or from 2 to 3 (but not from 1 to 2, because two bits change).

If you collect a bunch of messages that exhibit single bit changes in the data fields and post them, I or others may be able to help you solve this problem.

I can do that. But must luck I can have with temperature. Changing ph so slow to read them all will be almost impossible

I managed to capture some more data from the probe where the temperature starts to increase by 1 bit…

00 01 c0 00 12 17 82 0c fb
00 01 c0 00 12 18 82 03 ea
00 01 c0 00 12 19 82 02 fd
00 01 c0 00 12 1a 82 01 fb
00 01 c0 00 12 1b 82 00 fd
00 01 c0 00 12 1c 82 07 f8
00 01 c0 00 12 1d 82 06 f4
00 01 c0 00 12 1e 82 05 e9
00 01 c0 00 12 1f 82 04 fe
00 01 c0 00 12 20 82 3b f6
00 01 c0 00 12 21 82 3a f3
00 01 c0 00 12 22 82 39 e7
00 01 c0 00 12 23 82 38 ff
00 01 c0 00 12 24 82 3f e4
00 01 c0 00 12 25 82 3e fa
00 01 c0 00 12 26 82 3d f5
00 01 c0 00 12 27 82 3c f9
00 01 c0 00 12 28 82 33 e2
(missing)    12 29 82 xx xx
00 01 c0 00 12 2a 82 31 f3
00 01 c0 00 12 2b 82 30 fc
00 01 c0 00 12 2c 82 37 f0
00 01 c0 00 12 2d 82 36 f0
00 01 c0 00 12 2e 82 35 e1
00 01 c0 00 12 2f 82 34 fc
00 01 c0 00 12 30 82 2b ee
00 01 c0 00 12 31 82 2a ff  < repeat?
00 01 c0 00 12 32 82 29 ff < repeat?
00 01 c0 00 12 33 82 28 ff < repeat?
00 01 c0 00 12 34 82 2f fc
00 01 c0 00 12 35 82 2e f6
00 01 c0 00 12 36 82 2d ed
00 01 c0 00 12 37 82 2c ff
00 01 c0 00 12 38 82 23 fa
00 01 c0 00 12 39 82 22 f5
00 01 c0 00 12 3a 82 21 eb
00 01 c0 00 12 3b 82 20 ff
00 01 c0 00 12 3c 82 27 e8
00 01 c0 00 12 3d 82 26 fc
00 01 c0 00 12 3e 82 25 f9
00 01 c0 00 12 3f 82 24 fa
00 01 c0 00 12 40 82 5b f6
00 01 c0 00 12 41 82 5a f3
00 01 c0 00 12 42 82 59 e7
00 01 c0 00 12 43 82 58 ff
00 01 c0 00 12 44 82 5f e4
00 01 c0 00 12 45 82 5e fa
00 01 c0 00 12 46 82 5d f5

in one part the last byte is unchanged but the data changes ??

I captured also a part of the init of the probe that seems interesting

[/code]
00 01 8c 00 c6 00 00 00
[/code]

This has nothing to do with the temperature or mV it is part of an initialization of the probe.
I managed to get the probe working with an Arduino
First I sent to the probe

00 01 1a 04 00 1f 22 04 26 80

This is the message ID and is the same for every probe

00 01 1a 04 00 1f

And then I repeatedly send

00 01 01 01 00 01

then I get responses like I posted in the beginning on this post

The tricky part is figuring out the initialization code ( 0x22 0x04 0x26 0x80)
The 0x22 and 0x04 is different for every probe, the 0x26 is the Xor checksum of 0x22 and 0x04. The 0x80 is the same mistery variable.

I could brute force attack and calculate the third byte but that leaves me with 3 bytes and at 10Hz highest pooling speed it would take 19 days (worst case) to find the probe… I know the probe wil not be changed for a year or more but if/when it will need replacing I would use 19 days to register the new probe

The hex numbers 0x17 and 0x18 differ by 4 bits, not one.

The binary representations are 00010111 and 00011000

Here are two examples where the data change by only 1 bit, and as you see, two of the supposed digits of the "checksums" also change by only 1 bit, suggesting a simple additive/subtractive pattern.

00 01 c0 00 12 18 82 03 ea
00 01 c0 00 12 19 82 02 fd

00 01 c0 00 12 1e 82 05 e9
00 01 c0 00 12 1f 82 04 fe

Yeah it seems that the number of bits changed in the message equals the number of bits changed in "checksum". I've been going around this for two weeks with no clue on how to calculate the last byte