Determinazione dell'algoritmo CRC da dati + CRC - applicazione incorporata.
Domanda
Ho una serie di dati protetti da checksum a 16 bit che devo correggere. Le posizioni di checksum sono note, le aree esatte su cui sono calcolate e l'esatto algoritmo utilizzato per calcolarle non lo sono. 16 bit, prima LSB. Sospetto che sia una sorta di CRC a 16 bit, ma non sono stato in grado di trovare il codice che sta effettivamente calcolando i checksum.
Esempio:
00 4E00FFFF26EC14091E00A01830393630
10 30313131313030393030363030313030
20 30303131313030393030363030313030
30 30303131313030393030363030313030
40 3030FFFF225E363436304D313037**0CE0**
50 64000000000000008080808080800000
60 00000000**BE6E**FC01E001EB0013010500
I checksum sono memorizzati su 4E e 64. Non so se sono calcolati a partire dall'offset nella prima parola all'inizio di ogni sezione di dati o a partire da quello successivo, o sull'intero intervallo. Ho provato diversi algoritmi e polinomi comuni CRC senza fortuna. Non ci sono riferimenti o specifiche disponibili per questa applicazione.
Ecco un'altra sezione di dati con diversi CRC per il confronto.
00 4E00FFFF26C014091600A01030393132
10 30313131313030393030313230313030
20 30303131313030393030313230313030
30 30303131313030393030313230313030
40 3030FFFF225E343231324F313044**8348**
50 64000000000000008080808080800000
60 00000000**72F8**E001EB00130105000E01
La mia domanda è: qualcuno può identificare l'algoritmo? Esiste un modo per calcolare il polinomio CRC e altri fattori dai dati e dal CRC?
Grazie!
Modifica:
Una ricerca del mio disassemblaggio per il comune polinomio CRC16 0xA001 ha rivelato questa funzione:
34F86 ; =============== S U B R O U T I N E =======================================
34F86
34F86
34F86 Possible_Checksum: ; CODE XREF: MEM_EXT_4:00034FEEP
34F86 ; MEM_EXT_4:0003503AP ...
34F86 mov [-r0], r9 ; Move Word
34F88 mov r4, r12 ; Move Word
34F8A mov r5, r13 ; Move Word
34F8C shr r4, #14 ; Shift Right
34F8E shl r5, #2 ; Shift Left
34F90 or r5, r4 ; Logical OR
34F92 mov r4, r12 ; Move Word
34F94 mov DPP0, r5 ; Move Word
34F98 and r4, #3FFFh ; Logical AND
34F9C movb rl3, [r4] ; Move Byte
34F9E mov DPP0, #4 ; Move Word
34FA2 movbz r9, rl3 ; Move Byte Zero Extend
34FA4 mov r15, #0 ; Move Word
34FA6
34FA6 loc_34FA6: ; CODE XREF: MEM_EXT_4:00034FC8j
34FA6 mov r4, [r14] ; Move Word
34FA8 xor r4, r9 ; Logical Exclusive OR
34FAA and r4, #1 ; Logical AND
34FAC jmpr cc_Z, loc_34FBA ; Relative Conditional Jump
34FAE mov r4, [r14] ; Move Word
34FB0 shr r4, #1 ; Shift Right
34FB2 xor r4, #0A001h ; Logical Exclusive OR
34FB6 mov [r14], r4 ; Move Word
34FB8 jmpr cc_UC, loc_34FC0 ; Relative Conditional Jump
34FBA ; ---------------------------------------------------------------------------
34FBA
34FBA loc_34FBA: ; CODE XREF: MEM_EXT_4:00034FACj
34FBA mov r4, [r14] ; Move Word
34FBC shr r4, #1 ; Shift Right
34FBE mov [r14], r4 ; Move Word
34FC0
34FC0 loc_34FC0:
Soluzione
Il codice che hai pubblicato da loc_34FA6 in basso è sostanzialmente il seguente:
unsigned short
crc16_update(unsigned short crc, unsigned char nextByte)
{
crc ^= nextByte;
for (int i = 0; i < 8; ++i) {
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
return crc;
}
Questo è un CRC-16 con un polinomio 0xA001. Una volta scoperto l'intervallo di dati per cui si applica il CRC-16, si inizializza CRC su 0xFFFF e si chiama questa funzione per ogni byte della sequenza. Memorizza il valore restituito e passalo alla volta successiva. Il valore restituito alla fine è il tuo CRC finale.
Non sono sicuro di cosa stia facendo il prologo ...
Altri suggerimenti
Più in generale, parte del concetto di CRC è che quando si calcola il CRC di alcuni file di dati e quindi si aggiunge il CRC alla fine, si ottiene un file il cui CRC è un valore che dipende dalla lunghezza del file, ma non è contenuto. (Per alcuni algoritmi CRC, non dipende nemmeno dalla lunghezza del file.)
Quindi, se sospetti che l'app che stai cercando di decodificare stia utilizzando CRC16, e hai un programma che calcola CRC16 e hai più campioni della stessa lunghezza, calcola semplicemente il CRC16 di quei file di dati (che include il checksum). Se vengono restituiti gli stessi dati di checksum ogni volta (per file della stessa lunghezza), devono contenere un checksum CRC utilizzando la stessa larghezza e polinomio.
Ad esempio, una volta ho dovuto decodificare alcuni file in cui lo sviluppatore pensava che fosse intelligente cambiando l'algoritmo CRC32 cambiando due costanti. Non ho dovuto trovare il codice oggetto che ha verificato il checksum, smontarlo e poi capirlo nel modo più difficile. Questo semplice test ha risolto il problema.