我放弃了...。我已经尝试了两年,以确定在两台设备之间通过RS-232串行连接使用哪种CRC算法。该设备
可追溯到2002年。我只是假设它的CRC受保护,但我可能是错的。数据线。

我在显微镜上清楚地看到它是标准RS-232,带有一个起始位,
8个数据位和一个停止位。我可以说它是首先发送LSbit的。它的9600波特。

我可以控制消息中的部分数据,但不能控制所有来自发送设备的数据。我已经能够确定消息中每个字节的含义。通过旋转发射器上的旋钮,我可以看到特定的
字节增加1。因此,我可以肯定地说,我知道消息的每个数据字节的含义。它们都是对旋钮位置的简单二进制编码,有时甚至是开关位置的ASCII字符编码。
消息中的数据字节都取决于设备的用途。

这是串行线上的一长串消息。我已经能够通过所有256个值构成第4个字节序列。传输设备正在构造这些消息,我刚刚捕获了它们。前
6个字节是消息。

后两个字节在我看来是CRC而不是校验和。从此
列表中,可以收集到许多在第4个字节中相差一位的消息对。我知道这可能会有用。该设备被设计为可与PC配合使用,因此我认为我们正在使用小字节序
字节。

在我的PC上,我可以复制这些消息以模仿发送设备
,接收设备接受它们。我可以在邮件前加上
任意数量的0x00字节,并且接收设备接受它们。如果我更改消息中的任何位(包括可能的CRC字节),则接收设备
拒绝它们(如果接收者
接受消息,则发送一条简单的OK消息,否则接收器不响应完全没有。)

在我的PC上,我已接收其中一条消息,并将其发送到接收器
,最后每两个字节一次。除了最后两个字节与原始消息相同的消息外,接收方拒绝所有
消息。

这两个字节很重要。

我花了两年时间浏览由Greg Ewing编写的反向工程文档。 nz / greg.ewing / essays / CRC-Reverse-Engineering.html
,我可以按照他的方法取得一些进展,但最终还是得到了我的成就。想说说格雷格的方法对我有什么帮助,因为我可能做错了所有事情。如果有人认为它可能有用,我会在这里发布。

如果我关闭设备然后重新打开并让它
再次发送相同的消息,两个字节是相同的
我每次都这样做。

评论

变送器是否有任何文档?它是否具有可升级的固件或可以取出并读取的eprom芯片?反转发射机的固件可能很困难,但与您的两年时间相比并没有那么困难(尽管我认为这不是每天8小时工作的2年……)

#1 楼

我想到了!该网站上的某些评论使我回想起来更难-实际上要换个角度思考。

我认为我应该发布对这些消息所做的分析,以确定CRC算法。

我的分析是基于格雷格·尤因(Greg Ewing)撰写的一篇论文,该论文http://www.cosc.canterbury.ac.nz/greg.ewing/essays/CRC-Reverse-Engineering.html。他在那篇论文中提出了很多见解。除了使用他的方法总结和解释我的结果之外,我不会重复他写的内容。因此,在介绍我的数据时,请跟随他的论文。

他表明CRC的“遵循一种叠加原理。您可以认为CRC是由一组异或组成的”分量CRC中的每一个,每个CRC都仅取决于消息中的一位。 C2 = M1 xor M2
其中:
Cx = CRC
Mx =等长消息

他称“ M1 xor M2”为区别消息。

Greg写道:“然后,我与Patrick Maupin进行了交谈,后者提出了一项测试,该测试可能有助于阐明它是否是真正的CRC。由于叠加原理,如果通过用位模式B1对其进行异或更改消息而导致CRC由C1更改,而另一个位模式B2导致CRC由C2进行更改,则应使用(B1 xor B2)对消息进行异通过(C1 xor C2)更改CRC。如果那没有发生,那么该算法就不能成为普通的CRC算法。“

使用这4条从发送器到接收器的比特流消息: />
,然后


                                    CRC
                                  LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ----
M0 0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M1 0x00 0x09 0x69 0x31 0x01 0x03 0x01 0xC2
M2 0x00 0x09 0x69 0x31 0x02 0x03 0xCC 0xE7
M3 0x00 0x09 0x69 0x31 0x03 0x03 0x77 0xFB
   ---- ---- ---- ---- ---- ---- ---- ----


和另一个位模式B2导致CRC改变C2,


                                    CRC
                                  LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ----
M0 0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
B1 0x00 0x00 0x00 0x00 0x01 0x00
   ------------ XOR ------------
M1 0x00 0x09 0x69 0x31 0x01 0x03 0x01 0xC2   

C1 = 0xDEBA xor 0xC201 = 0x1CBB


然后用B3 =(B1 xor B2)对数据包进行异或,应将C3 =(C1 xor C2)更改CRC。算法。


                                    CRC
                                  LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ----
M0 0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
B2 0x00 0x00 0x00 0x00 0x02 0x00
   ------------ XOR ------------
M2 0x00 0x09 0x69 0x31 0x02 0x03 0xCC 0xE7

C2 = 0xDEBA xor 0xE7CC = 0x3976

C1 xor C2 = 0x1CBB xor 0x3976 = 0x25CD


在这种串行流的情况下,它发生了,因此它必须是普通的CRC算法。精确地说,如果C1对应于位置i上带有1的消息,而C2对应于位置i + 1上带有1的消息,则得到的CRC仅相差一个“异或”周期。 C1是通过向C2施加一个移位异或周期而得出的(如果这看起来是倒的,这是因为从消息末尾开始的1位越远,则将更多的移位异或周期应用于CRC)。 >
有两种可能:如果C2的前导位(即将移出的一位)为0,则C1等于C2的移位一位;如果为1,则C2等于到C1移了一位,然后与多项式异或。

                                    CRC
                                  LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ----
B1 0x00 0x00 0x00 0x00 0x01 0x00
B2 0x00 0x00 0x00 0x00 0x02 0x00
   ------------ XOR ------------

B3 0x00 0x00 0x00 0x00 0x03 0x00

M0 0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
B3 0x00 0x00 0x00 0x00 0x03 0x00
   ------------ XOR ------------
M3 0x00 0x09 0x69 0x31 0x03 0x03 0x77 0xFB

C3 = 0xDEBA xor 0xFB77 = 0x25CD

Does C3 = 0x25CD == C1 XOR C2 = 0x25CD  ? Yes


我想出了这些差错消息的CRC值,并显示了字节: 0,前一个CRC是此CRC的右移一位。如果LSB为1,则前面的CRC是当前CRC与多项式的异或,然后右移。


                                     CRC
                                  LSB  MSB
    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M1  0x00 0x09 0x69 0x31 0x01 0x03 0x01 0xC2
    ---- ---- ---- ---- ---- ---- ---- ---- 
D01    0    0    0    0 0x01    0 0xBB 0x1C 

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M2  0x00 0x09 0x69 0x31 0x02 0x03 0xCC 0xE7
    ---- ---- ---- ---- ---- ---- ---- ----  
D02    0    0    0    0 0x02    0 0x76 0x39

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M3  0x00 0x09 0x69 0x31 0x04 0x03 0x56 0xAC
    ---- ---- ---- ---- ---- ---- ---- ---- 
D04    0    0    0    0 0x04    0 0xEC 0x72 

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
m8  0x00 0x09 0x69 0x31 0x08 0x03 0x62 0x3B
    ---- ---- ---- ---- ---- ---- ---- ---- 
D08    0    0    0    0 0x08    0 0xD8 0xE5

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M10 0x00 0x09 0x69 0x31 0x10 0x03 0x1B 0x1D
    ---- ---- ---- ---- ---- ---- ---- ----
D10    0    0    0    0 0x10    0 0xA1 0xC3

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M20 0x00 0x09 0x69 0x31 0x20 0x03 0xE9 0x51
    ---- ---- ---- ---- ---- ---- ---- ----
D20    0    0    0    0 0x20    0 0x53 0x8f

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M40 0x00 0x09 0x69 0x31 0x40 0x03 0x0D 0xC8
    ---- ---- ---- ---- ---- ---- ---- ----
D40    0    0    0    0 0x40    0 0xB7 0x16

    ---- ---- ---- ---- ---- ---- ---- ----
M0  0x00 0x09 0x69 0x31 0x00 0x03 0xBA 0xDE
M80 0x00 0x09 0x69 0x31 0x80 0x03 0xD4 0xF3
    ---- ---- ---- ---- ---- ---- ---- ---- 
D80    0    0    0    0 0x80    0 0x6e 0x2d


这告诉我多项式为0x8408
多项式0x1021然后反映生成的CRC。值得注意的是0x1021是标准的16位多项式之一-称为“ CRC-16-CCITT”,也称为“ KERMIT”。 br />因此,格雷格(Greg)帮助我完成了分析工作。它肯定看起来像是CRC,最有可能是CRC-16-CCITT或Kermit(至少在init = XorOut = 0x0000的情况下)。

但是,当我尝试通过RevEng运行消息时并要求它使用KERMIT算法,消息中的实际CRC与RevEng生成的不匹配。

例如,使用D01消息:


Greg对他的问题的分析表明,CRC计算中可能包含一些不明显的字节。在格雷格的情况下,他写道:“我想出了以下想法。首先用多项式初始化寄存器-这对应于在1位差值消息中遇到1之后的状态。然后运行算法并计数达到已知的CRC值之前需要执行的步骤数。假设最终达到了该值,这将告诉我CRC中包含跟随1的0位。”

所以,我说也许这对我有用。所以我在消息D01的末尾添加了00个字节:
返回bb1c

WOW,0xbb1c是我对M0和M1的两个实际CRC进行异或时得到的CRC值。 (如果实际消息中的实际字节相同,并且在将它们异或化为差异消息后为0x00,则可以在差异消息中添加0x00字节。我需要记住,此分析仍然需要将init和XorOut零,在实际算法中可能不是这种情况。

所以我花了大约一年的时间(不,不是全职)来尝试查找额外字节的值。 />尝试了所有多余字节的组合,但我的值都跳了过来。我将不去尝试寻找多余字节的所有操作。这是一个死胡同。

**这是我在此网页上发布我的问题描述时的情况。 **

也许我仍然在正确的位置没有正确的数据字节,或者init = XorOut = 0x0000的假设不成立。

所以我决定尝试更多消息。我编写了一堆消息,可以控制第二个字节的值。这是我能够生成的消息:


Byte    CRC (with byte swap to MSB-LSB order)
-----   ----
01  1CBB            
02  3976    LSB of CRC = 0
04  72EC    LSB of CRC = 0
08  E5D8    LSB of CRC = 0
10  C3A1    LSB of CRC = 1
20  8F53    LSB of CRC = 1
40  16b7    LSB of CRC = 1
80  2d6e    Lsb of CRC = 0


这是区别消息:


Byte    CRC shift   xor Previous CRC
-----   ----    ----    ----    ----
01  1CBB            
02  3976    1CBB    0000    1CBB
04  72EC    3976    0000    3976
08  E5D8    72EC    0000    72EC
10  C3A1    61D0    8408    E5D8
20  8F53    47A9    8408    C3A1
40  16b7    0B5B    8408    8F53
80  2d6e    16B7    0000    16b7


然后,我对CRC字进行了相同的分析,并得出了与以前相同的多项式:0x8408或当移动另一个方向时为0x1021


                                                  CRC
                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D        
   0x00 0x04 0x77 0x32                0x97 0x13 0x14 0xE8
   0x00 0x08 0x77 0x32                0x97 0x13 0x78 0x22
   0x00 0x10 0x77 0x32                0x97 0x13 0xB1 0xBE
   0x00 0x20 0x77 0x32                0x97 0x13 0x32 0x8F
   0x00 0x40 0x77 0x32                0x97 0x13 0x34 0xEC
   0x00 0x06 0x77 0x32                0x97 0x13 0x06 0xCB
   0x00 0x0A 0x77 0x32                0x97 0x13 0x6A 0x01
   0x00 0x12 0x77 0x32                0x97 0x13 0xA3 0x9D
   0x00 0x22 0x77 0x32                0x97 0x13 0x20 0xAC
   0x00 0x42 0x77 0x32                0x97 0x13 0x26 0xCF


使用此poly的所有RockSoft CRC模型,我需要回想一下Kermit:


                                                  CRC
                                                LSB  MSB
     ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
M02a 0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
M03a 0x00 0x03 0x77 0x32                0x97 0x13 0xAB 0x9C
     ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
D01a 0x00 0x01 0x00 0x00                0x00 0x00 0x89 0x11

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x04 0x77 0x32                0x97 0x13 0x14 0xE8
   0x00 0x06 0x77 0x32                0x97 0x13 0x06 0xCB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x00 0x00                0x00 0x00 0x12 0x23

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
   0x00 0x06 0x77 0x32                0x97 0x13 0x06 0xCB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x04 0x00 0x00                0x00 0x00 0x24 0x46

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
   0x00 0x0A 0x77 0x32                0x97 0x13 0x6A 0x01
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x08 0x00 0x00                0x00 0x00 0x48 0x8C

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
   0x00 0x12 0x77 0x32                0x97 0x13 0xA3 0x9D
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x10 0x00 0x00                0x00 0x00 0x81 0x10

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
   0x00 0x22 0x77 0x32                0x97 0x13 0x20 0xAC
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x20 0x00 0x00                0x00 0x00 0x02 0x21

                                                LSB  MSB
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x02 0x77 0x32                0x97 0x13 0x22 0x8D
   0x00 0x42 0x77 0x32                0x97 0x13 0x26 0xCF
   ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
   0x00 0x40 0x00 0x00                0x00 0x00 0x04 0x42


我注意到了一些最新消息。如果我只是使用第一个字节并保留其他0x00字节,则不需要两个额外的字节来获取差异消息的正确CRC。对消息D01a使用RevEng:

D:> reveng -s -w 16 018911
width = 16 poly = 0x1021 init = 0x0000 refin = true refout = true xorout = 0x0000 check = 0x2189名称=“ KERMIT”

然后我意识到,如果我以相反的字节顺序将消息送入CRC生成器,我的原始D01消息
会生成正确的CRC。

D:> reveng -c -m kermit 01000000
bb1c

所以我认为这些多余的字节实际上只是消息的字节,但是该消息将以反向字节进行处理命令。

这是真的吗?

我拿了M02a和M03a,并以相反的字节顺序将它们送入RevEng:

D:> reveng -s -w 16 1397327702228d
宽度= 16 poly = 0x1021 init = 0xffff refin = true refout = true xorout = 0x0000 check = 0x6f91 name =“ CRC-16 / MCRF4XX”

D :> reveng -s -w 16 1397327703ab9c
width = 16 poly = 0x1021 init = 0xffff refin = true refout = true xorout = 0x0000 check = 0x6f91 name =“ CRC-16 / MCRF4XX”

让我惊讶的是,init都是该算法具有我先前发现的多边形。该算法来自MCRF4xx通信(我现在知道这是有道理的,因为我正在跟踪的RS-232线路替换了RF连接)。

MCRF4xx是RFID协议。

消息被当作一组长位,以便最后处理最后一个字节,最后处理第一个字节。不使用消息开头的0x00字节。在init = 0xffff的情况下,MCRF4xx算法将检测到多余或丢失的前导零。

我在数十条消息上尝试了该算法,每次都获得正确的CRC。

这是我在http://www.snip2code.com/Snippet/86260/Simple-CRC-16-MCRF4XX-C-implementation-


Byte    CRC (with byte swap to MSB-LSB order)
-----   ----
0x01    1189
0x02    2312    LSB of CRC = 0
0x04    4624    LSB of CRC = 0
0x08    8C48    LSB of CRC = 0
0x10    1081    LSB of CRC = 1
0x20    2102    LSB of CRC = 0
0x40    4204    LSB of CRC = 0


Byte    CRC shift   xor Previous CRC
-----   ----    ----    ----    ----
0x01    1189
0x02    2312    1189    0000    1189
0x04    4624    2312    0000    2312
0x08    8C48    4624    0000    4624
0x10    1081    0840    8408    8C48    
0x20    2102    1081    0000    1081
0x40    4204    2102    0000    2102


RevEng网站上的网页指向有关MCRF4xx的一些文档:http://reveng.sourceforge.net/crc-catalogue/16.htm。

感谢所有给了我正能量。

评论


做得好。我一直说毅力是任何逆向工程师最重要的特征之一。当他们比他们想像的更接近解决方案时,太多的人放弃了。

–彼得·安德森(Peter Andersson)
2014年11月25日18:07

#2 楼

我在2004年编写了自己的CRC暴力破解程序,但是它专门针对特定问题。 https://github.com/sitsec/bruteforce-crc

上有一个更好的通用开源软件。通过这个程序。对于16位CRC,速度相当快。对于更长的CRC,我还没有尝试过。

评论


我看过该程序,但是没有安装boost库,也没有C编译器来编译它们。

–恩里科·比斯科蒂(Enrico Biscotti)
2014年11月20日在22:44



我使用RevEng执行了我认为相同的功能。我发现这些消息和其他消息之间没有通用的算法。也就是说,对于一条消息,我得到的算法如下:poly = 0x440b init = 0xf14a refin = false refout = false xorout = 0x0000而对于另一条消息,我得到:poly = 0x17d3 init = 0x2aa1 refin = true refout = true xorout = 0x0000

–恩里科·比斯科蒂(Enrico Biscotti)
2014年11月20日在22:51

RevEng是否尝试不同的初始化和最终XOR值,正常结构和反射结构等?如果是这样,并且没有共同点,则表明他们的检查不是真正的CRC。

–埃里克·史密斯(Eric Smith)
2014年11月21日在22:32

是的,RevEng将在其搜索中尝试所有init和XorOut值。

–恩里科·比斯科蒂(Enrico Biscotti)
2014年11月24日22:53