Determinación del algoritmo CRC a partir de datos + CRC - aplicación incorporada.

StackOverflow https://stackoverflow.com/questions/401231

  •  03-07-2019
  •  | 
  •  

Pregunta

Tengo un conjunto de datos protegidos por sumas de comprobación de 16 bits que debo corregir. Las ubicaciones de la suma de comprobación son conocidas, las áreas exactas en las que se calculan y el algoritmo exacto utilizado para calcularlas no. 16 bits, LSB primero. Sospecho que es una especie de CRC de 16 bits, pero no he podido encontrar el código que está calculando las sumas de comprobación.

Ejemplo:

00    4E00FFFF26EC14091E00A01830393630  
10    30313131313030393030363030313030  
20    30303131313030393030363030313030  
30    30303131313030393030363030313030  
40    3030FFFF225E363436304D313037**0CE0**  
50    64000000000000008080808080800000  
60    00000000**BE6E**FC01E001EB0013010500  

Las sumas de comprobación se almacenan en 4E y 64. No sé si se calculan a partir del desplazamiento en la primera palabra al comienzo de cada sección de datos o después de eso, o en todo el rango. He intentado una serie de algoritmos CRC y polinomios comunes sin suerte. No hay referencias o especificaciones disponibles para esta aplicación.

Aquí hay otra sección de datos con diferentes CRC para fines de comparación.

00    4E00FFFF26C014091600A01030393132  
10    30313131313030393030313230313030  
20    30303131313030393030313230313030  
30    30303131313030393030313230313030  
40    3030FFFF225E343231324F313044**8348**  
50    64000000000000008080808080800000  
60    00000000**72F8**E001EB00130105000E01  

Mi pregunta es, ¿puede alguien identificar el algoritmo? ¿Hay alguna forma de calcular el polinomio CRC y otros factores a partir de los datos y el CRC?

¡Gracias!

Editar:

Una búsqueda en mi desmontaje del polinomio CRC16 común 0xA001 reveló esta función:

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:                       
¿Fue útil?

Solución

El código que publicaste desde loc_34FA6 hacia abajo es básicamente el siguiente:

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;
}

Este es un CRC-16 con un polinomio 0xA001. Una vez que descubra el rango de datos para los que se aplica el CRC-16, inicialice el CRC a 0xFFFF y llame a esta función para cada byte en la secuencia. Almacene el valor de retorno y devuélvalo en la próxima vez. El valor devuelto al final es su CRC final.

No estoy seguro de qué está haciendo el prólogo ...

Otros consejos

Más generalmente, parte del concepto de CRC es que cuando se calcula el CRC de algún archivo de datos y luego se agrega el CRC al final, se obtiene un archivo cuyo CRC tiene algún valor que depende de la longitud del archivo, pero no es contenido. (Para algunos algoritmos CRC, ni siquiera depende de la longitud del archivo).

Por lo tanto, si sospecha que la aplicación que está intentando aplicar ingeniería inversa está utilizando, por ejemplo, CRC16, y tiene un programa que calcula CRC16, y tiene varias muestras de la misma longitud, simplemente calcule el CRC16 de esos archivos de datos (que incluyen la suma de comprobación). Si vuelve con los mismos datos de suma de comprobación (para archivos de la misma longitud), deben contener una suma de verificación CRC con el mismo ancho y polinomio.

Por ejemplo, una vez tuve que aplicar ingeniería inversa a algunos archivos donde el desarrollador pensó que estaba siendo inteligente al cambiar el algoritmo CRC32 al cambiar dos constantes. No tuve que encontrar el código objeto que verificaba la suma de control, desmontarlo y luego descifrarlo por el camino difícil. Esta simple prueba lo clavó.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top