CRC反向工程师(Checksum from Machine / PC)

我目前正在寻找如何确定从机器产生的CRC到PC(反之亦然)。 设备使用串行通信或RS232电缆进行通信。

I do only have data to be able for us to create a program to be used for both devices. The data given was from my boss and the program was corrupted. So we are trying for it to work out. I hope everyone can help. Thanks :) 

在协议中用于CRC计算的序列是ASCII字符串

  • 从第一个打印字符(例如REQ中的“R”)开始,
  • 直到包括'1E'在内。
  • 根据我们的CRC计算器,它是以下规格的CRC

    CRC:16,1021,0000,0000,NO,NO

意思是:

 CRC width: 16 bit (of course) polynomial: 1021 HEX (truncated CRC polynomial) init value: 0000 final Xor applied: 0000 reflectedInput: No reflectedOutput: No` 

(如果'初始值'是FFFF,它将是一个“由CCITT指定的16位宽的CRC”)。

另请参阅Docklight CRC词汇表和Boost CRC库 ,了解CRC术语的含义以及示例代码。

我所做的是编写一个小脚本,在第一个简单的“REQ = INI”命令的不同部分上尝试使用流行的16位CRC,然后看看我是否总计4255。这个失败了,一个尝试各种各样的多项式的完全暴力,我认为这可能只是一个奇怪的/有缺陷的已知标准的实现,并且确实成功了CRC-CCITT的变体。

下面是一些缓慢和简单的C代码(不是基于表格)来计算各种CRC:

 // Generic, not table-based CRC calculation // Based on and credits to the following: // CRC tester v1.3 written on 4th of February 2003 by Sven Reifegerste (zorc/reflex) unsigned long reflect (unsigned long crc, int bitnum) { // reflects the lower 'bitnum' bits of 'crc' unsigned long i, j=1, crcout=0; for (i=(unsigned long)1<<(bitnum-1); i; i>>=1) { if (crc & i) crcout|=j; j<<= 1; } return (crcout); } calcCRC( const int width, const unsigned long polynominal, const unsigned long initialRemainder, const unsigned long finalXOR, const int reflectedInput, const int reflectedOutput, const unsigned char message[], const long startIndex, const long endIndex) { // Ensure the width is in range: 1-32 bits assert(width >= 1 && width <= 32); // some constant parameters used const bool b_refInput = (reflectedInput > 0); const bool b_refOutput = (reflectedOutput > 0); const unsigned long crcmask = ((((unsigned long)1<<(width-1))-1)<<1)|1; const unsigned long crchighbit = (unsigned long)1<<(width-1); unsigned long j, c, bit; unsigned long crc = initialRemainder; for (long msgIndex = startIndex; msgIndex <= endIndex; ++msgIndex) { c = (unsigned long)message[msgIndex]; if (b_refInput) c = reflect(c, 8); for (j=0x80; j; j>>=1) { bit = crc & crchighbit; crc<<= 1; if (c & j) bit^= crchighbit; if (bit) crc^= polynominal; } } if (b_refOutput) crc=reflect(crc, width); crc^= finalXOR; crc&= crcmask; return(crc); } 

使用上面列出的代码和CRC规范,我已经能够重新计算以下三个示例CRC:

 10.03.2014 22:20:57.109 [TX] - REQ=INI<CR><LF> <RS>CRC=4255<CR><LF> <GS> 10.03.2014 22:20:57.731 [TX] - ANS=INI<CR><LF> STATUS=0<CR><LF> <RS>CRC=57654<CR><LF> <GS> 10.03.2014 22:20:59.323 [TX] - ANS=INI<CR><LF> STATUS=0<CR><LF> MID="CTL1"<CR><LF> DEF="DTLREQ";1025<CR><LF> INFO=0<CR><LF> <RS>CRC=1683<CR><LF> <GS> 

我在DEF=部分的复杂部分上失败了 – 可能没有正确理解字符序列。

Docklight脚本我用来逆向工程:

 Sub crcReverseEngineer() Dim crctypes(7) crctypes(0) = "CRC:16,1021,FFFF,0000" ' CCITT crctypes(1) = "CRC:16,8005,0000,0000" ' CRC-16 crctypes(2) = "CRC:16,8005,FFFF,0000" ' CRC-MODBUS ' lets try also some nonstandard variations with different init and final Xor, but stick ' to the known two polynoms. crctypes(3) = "CRC:16,1021,FFFF,FFFF" crctypes(4) = "CRC:16,1021,0000,FFFF" crctypes(5) = "CRC:16,1021,0000,0000" crctypes(6) = "CRC:16,8005,FFFF,FFFF" crctypes(7) = "CRC:16,8005,FFFF,0000" crcString = "06 1C 52 45 51 3D 49 4E 49 0D 0A 1E 43 52 43 3D 30 30 30 30 0D 0A 1D" For reflectedInOrOut = 0 To 3 For cType = 0 To 7 crcSpec = crctypes(cType) & "," & IIf(reflectedInOrOut Mod 2 = 1, "Yes", "No") & "," & IIf(reflectedInOrOut > 1, "Yes", "No") For cStart = 1 To 3 For cEnd = 9 To (Len(crcString) + 1) / 3 subDataString = Mid(crcString, (cStart - 1) * 3 + 1, (cEnd - cStart + 1) * 3) result = DL.CalcChecksum(crcSpec, subDataString, "H") resultInt = CLng("&h" + Left(result, 2)) * 256 + CLng("&h" + Right(result, 2)) If resultInt = 4255 Then DL.AddComment "Found it!" DL.AddComment "sequence: " & subDataString DL.AddComment "CRC spec: " & crcSpec DL.AddComment "CRC result: " & result & " (Integer = " & resultInt & ")" Exit Sub End If Next Next Next Next End Sub Public Function IIf(blnExpression, vTrueResult, vFalseResult) If blnExpression Then IIf = vTrueResult Else IIf = vFalseResult End If End Function 

希望这可以帮助,我很乐意提供额外的信息或澄清细节。