CRC Reverse Engineer (Контрольная сумма от машины / ПК)

Я в настоящее время ищу, как определить CRC, произведенный от машины до ПК (и наоборот). Устройства обмениваются данными с помощью последовательной связи или кабеля 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 :)

1 ответ

Решение

Последовательность, используемая для вычисления CRC в вашем протоколе, представляет собой строку ASCII.

  • начиная с первого печатного символа (например, 'R' из REQ)
  • до и включая "1E" в расчете.
  • Это CRC со следующими характеристиками в соответствии с нашим калькулятором CRC

    CRC:16,1021,0000,0000, нет, нет

что значит:

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

(Если бы 'значение инициализации' было FFFF, это был бы "CRC 16 бит ширины, как обозначено CCITT").

См. Также глоссарий Docklight CRC и библиотеку Boost CRC о том, что означают термины CRC, а также образец кода.

Я написал небольшой скрипт, который опробует популярные 16-битные CRC на разных частях первой простой команды "REQ=INI", и посмотрю, получу ли я в итоге сумму 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

Надеюсь, что это поможет, и я рад предоставить дополнительную информацию или уточнить детали.

Другие вопросы по тегам