¿Identificar el tipo de procesador a partir del código binario en bruto?

19

No está realmente relacionado con los chips, pero espero obtener instrucciones a seguir desde aquí.

Obtuve un fragmento de código, pero no sé a qué procesador se destinó. ¿Existen herramientas disponibles que puedan ayudarme a identificar el tipo de código? ¿Qué métodos estadísticos pueden ayudar? ¿Distribución de bytes? Distribución de pares, etc? Cadenas de Markov tal vez?

    
pregunta mentalist

6 respuestas

16

Intenta ejecutarlo a través del archivo GNU. Si tiene un encabezado estándar, lo recogerá.

Por ejemplo.

jrt@lin:~/src$ file foo
foo: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
    
respondido por el Toby Jaffey
9

Esta es una pregunta muy interesante. Hay millones de instrucciones establecidas allí, pero solo un puñado de instrucciones muy usadas.

Lo primero que vería es el origen y el uso previsto. Si sospechas que fue diseñado en los EE. UU., Estarías apuntando principalmente a procesadores con hojas de datos disponibles en inglés, por ejemplo. Si fue diseñado en Asia, entonces hay una serie de procesadores que utilizan para dispositivos fabricados en masa que los ingenieros de EE. UU. Rara vez ven. Incluso Europa tiene unos pocos procesadores que son más comunes que otros.

Luego echaría un vistazo al tamaño y la funcionalidad del código (asumiendo que sabes lo que el código hace hasta cierto punto). Si son unos pocos megabytes de código, puede descontar la mayoría de los procesadores de 8 bits integrados y comenzar a buscar dispositivos más grandes con memoria externa. Si son unos pocos kilobytes o menos, entonces querrás centrarte en dispositivos más pequeños y baratos. Si la funcionalidad es simple, incluso podría ser un código para un procesador de cuatro bits.

En este punto, vale la pena mirar la estructura de la memoria. Es probable que haya una sección del programa y una sección de datos como mínimo. Si se trata de un archivo binario (en comparación con Intel hex o el registro de motorola), entonces tiene poca idea de dónde se colocan ciertos fragmentos de datos en la memoria. Un editor hexadecimal podría mostrar algunos patrones. Si viene en formato de registro hexadecimal, es posible que tenga más información sobre la estructura de memoria del procesador para el que está diseñada. Algunos procesadores se reinician en la ubicación de memoria del programa 0, algunos en la ubicación de memoria más alta. El programa puede incluir valores iniciales de EEPROM en una ubicación de memoria separada. Si está destinado a un procesador seguro (como se usa en banca), incluso podría tener claves de seguridad para una ubicación de memoria impar.

Dependiendo del idioma en el que se programó, es posible que tengas algunas pistas adicionales. Si se programó en C o en un lenguaje de procedimiento similar, entonces las funciones casi siempre comenzarán con una secuencia de instrucciones para guardar ciertos registros en la pila (muchos empujes) y luego justo antes de devolver muchos pops para devolver los valores originales de la pila. . Si puede hacer un reconocimiento de patrones, encontrará muchas de estas secuencias en todo el proceso, y podrá determinar qué instrucciones son las más probables, las de retorno, etc., que podrían reducir un poco sus opciones.

Si es un dispositivo incorporado con interrupciones, puede tener una tabla de vectores de interrupción, que se verá como un montón de saltos a diferentes ubicaciones de memoria en un bloque grande, probablemente en una ubicación conveniente (dirección de 0x ??? 0 por ejemplo). Las tablas de salto se usan en otros lugares para otras cosas también, pero si puede ubicar una secuencia de instrucciones que parezcan idénticas, excepto en cuál sería la dirección a la que saltar, es posible que pueda inferir cómo se ve una instrucción de salto y, de nuevo, restringir tus elecciones hacia abajo.

En ese momento, comenzaría con las arquitecturas de procesadores más comunes y vería si algo se correlaciona. x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502, etc, etc, etc. Hay listas de procesadores y conjuntos de instrucciones comunes, al menos en el mundo de habla inglesa, que pueden ser útiles.

No tengo conocimiento de ninguna herramienta automatizada que ayude con esto, pero MAME emula una gran cantidad de arquitecturas de procesadores, y un método posible es ejecutar el código a través de varios procesadores y ver los registros para ver si hace clic. De acuerdo con lo que sabes sobre el diseño.

    
respondido por el Adam Davis
5

Idea: ¿conoce la edad del código fuente, es decir, en qué momento / año se creó?

Si fuera lo suficientemente antiguo, podría darte una pista sobre en qué procesador se escribió. Puede tomar la edad / año en que se escribió y determinar qué procesador (es) fue popular (s) en ese período de tiempo e intentar cargar / ejecutar el archivo hex en esos.

Pensándolo bien, dada la proliferación masiva de procesadores en los últimos 20 años, esta podría ser una técnica de aguja en un pajar y no ser muy fructífera.

    
respondido por el J. Polfer
4

Hace muchas lunas, cuando no había muchos núcleos de procesador diferentes, identifiqué el código Z80 varias veces mediante el análisis de frecuencia . Para Z80 CD es el código de máquina para call subroutine y C9 es return from subroutine (nunca lo olvidaré), y estos son a menudo los códigos más frecuentes. Sin embargo, esto requiere que esté familiarizado con el conjunto de instrucciones en un nivel de código de máquina. Tener experiencia en el ensamblaje a mano ayuda (hice mucho, y todavía puedo contar hacia atrás en hexadecimal para calcular las compensaciones).

    
respondido por el stevenvh
3

Si el archivo es para un PIC de 12 bits o 14 bits, cada par de bytes será una palabra de 12 o 14 bits, normalmente se almacenará primero en LSB, con los dos o cuatro bits más significativos borrados.

    
respondido por el supercat
1

Si se compilara desde un lenguaje como C o Pascal, habría ciertas secuencias estándar de binario que podrías buscar. Con C, por ejemplo, casi todas las funciones comienzan con algo que guarda el puntero de pila en un puntero de "marco" o "enlace". Para cualquier procesador dado, usualmente hay solo un par de maneras de hacer esto. Entonces, podría responder "es este código para el procesador X" buscando el binario de X para estas secuencias.

Dicho esto, tuve un poco de suerte al diferenciar entre los binarios 8088, 6502 y 68000 simplemente usando histogramas. Cualquier procesador dado tiene ciertos códigos de operación legales, y estos tienden a ser usados un poco más a menudo que el promedio. Con una gran cantidad de binarios, puedes comenzar a ver ciertas tendencias. Sin embargo, esto se dificulta por el hecho de que todos los operandos en una determinada pieza de binario tienden a no correlacionarse con el tipo de procesador dado, y esto esencialmente hace ruido en los datos de su histograma. Además, incluso dos programas diferentes para el mismo procesador pueden tener histogramas notablemente diferentes. Aún así, puede darte un lugar para comenzar.

    
respondido por el JustJeff

Lea otras preguntas en las etiquetas