Identifica o tipo de processador a partir do código binário bruto?


19

Não é realmente relacionado a chips, mas espero obter algumas instruções a seguir a partir daqui.

Eu tenho um pedaço de código, mas não sei para qual processador ele se destina. Existem ferramentas disponíveis que podem me ajudar a identificar o tipo de código? Quais métodos estatísticos podem ajudar? Distribuição de bytes? Distribuição de pares, etc? Cadeias de Markov, talvez?


7
Você poderia nos fornecer os primeiros 200 bytes em hexadecimal bruto?
pingswept

Esta é uma pergunta divertida. Que tipo de dispositivo você está hackeando?
DavidEGrayson

1
você pode tentar alimentá-lo com dois desmontadores diferentes e ver o que acontece.
JustJeff

2
Vou nomear esse código em 100 bytes! = P
JustJeff

Ótima pergunta. No entanto, pode ser um ajuste melhor para o StackOverflow.
Sharptooth

Respostas:


16

Tente executá-lo através do arquivo GNU. Se tiver algum cabeçalho padrão, ele será recolhido.

Por exemplo.

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

Tentei isso. O arquivo GNU diz que são "dados".
Mentalista

3
Você poderia postar alguns? Tentei procurar por ASCII nele com "strings"?
Toby Jaffey

9

Esta é uma questão muito interessante. Existem milhões de conjuntos de instruções por aí, mas apenas alguns deles muito usados.

A primeira coisa que eu observaria é a origem e o uso pretendido. Se você suspeita que foi projetado nos EUA, você estaria segmentando principalmente processadores com fichas técnicas disponíveis em inglês, por exemplo. Se ele foi projetado na Ásia, existem vários processadores que eles usam para dispositivos fabricados em massa que os engenheiros dos EUA raramente veem. Até a Europa possui alguns processadores que são mais comuns que outros.

Eu, então, daria uma olhada no tamanho e na funcionalidade do código (supondo que você saiba o que o código faz até certo ponto). Se tiver alguns megabytes de código, você pode descontar a maioria dos processadores de 8 bits incorporados e começar a procurar dispositivos maiores com memória externa. Se tiver alguns kilobytes ou menos, você prefere se concentrar em dispositivos menores e mais baratos. Se a funcionalidade for simples, pode até ser código para um processador de quatro bits.

Neste ponto, vale a pena olhar para a estrutura da memória. É provável que haja uma seção de programa e uma seção de dados no mínimo. Se for um arquivo binário (em comparação com o intel hex ou o registro da motorola), você terá poucas informações sobre o local em que certos blocos de dados estão sendo colocados na memória. Um editor hexadecimal pode mostrar alguns padrões. Se for fornecido em um formato de registro hexadecimal, você poderá obter mais informações sobre a estrutura de memória do processador a que se destina. Alguns processadores são redefinidos no local 0 da memória do programa, outros no local mais alto da memória. O programa pode incluir valores iniciais da EEPROM em um local de memória separado. Se for destinado a um processador seguro (como usado no setor bancário), pode até ter chaves de segurança para um local de memória estranho.

Dependendo do idioma em que foi programado, você pode ter algumas dicas adicionais. Se foi programado em C ou em uma linguagem procedural semelhante, as funções quase sempre começam com uma sequência de instruções para salvar determinados registros na pilha (muitos pushs) e logo antes de retornar muitos pops para retornar os valores originais da pilha . Se você conseguir fazer algum reconhecimento de padrões, encontrará muitas dessas seqüências por toda parte e poderá determinar quais instruções são mais prováveis ​​de instruções push / pop, return etc., que podem restringir um pouco suas escolhas.

Se for um dispositivo incorporado com interrupções, pode haver uma tabela de vetores de interrupção, que parecerá um monte de saltos para diferentes locais de memória em um bloco grande, provavelmente em um local conveniente (endereço de 0x ??? 0, por exemplo) . As tabelas de salto são usadas em outros lugares também para outras coisas, mas se você puder localizar uma sequência de instruções que pareçam idênticas, exceto para qual seria o endereço para o qual ir, você poderá inferir a aparência de uma instrução de salto e restringir novamente suas escolhas para baixo.

Nesse ponto, eu começaria com as arquiteturas de processador mais comuns e veria se algo se correlaciona. x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502, etc, etc, etc. Existem listas de processadores e conjuntos de instruções comuns - pelo menos no mundo de língua inglesa - que podem ser úteis.

Não conheço nenhuma ferramenta automatizada que possa ajudar com isso, mas o MAME emula muitas arquiteturas de processador e um método possível é executar o código por vários processadores e observar os registros para ver se algo clica de acordo com o que você conhece o design.


"Até a Europa tem alguns processadores que são mais comuns que outros". Viver na Europa, isso nunca me ocorreu. Você pode dar exemplos?
9302 stevenvh

@stevenvh Devido às empresas Acorn e Sinclair, os sistemas embarcados baseados em 6502 e Z80 eram muito populares. E, é claro, o processador ARM foi iniciado na Acorn Computers.
Adam Davis

5

Idéia: você conhece a idade do código fonte, ou seja, em que época / ano ele foi criado?

Se tiver idade suficiente, poderá fornecer uma pista sobre para qual processador foi escrito. Você pode pegar a idade / ano em que foi escrito e determinar quais processadores são populares naquele período e tentar carregar / executar o arquivo hexadecimal nesses.

Pensando bem, dada a proliferação em massa de processadores nos últimos 20 anos, essa pode ser uma técnica de agulha no palheiro e não ser muito proveitosa.


4

Muitas luas atrás, quando não havia tantos núcleos de processador diferentes por perto, identifiquei o código Z80 algumas vezes através da análise de frequência . Para o Z80 CDé o código de máquina para call subroutinee C9é return from subroutine(nunca esquecerei), e esses geralmente são os códigos que ocorrem mais. Isso requer que você esteja familiarizado com as instruções definidas no nível do código da máquina. Ter experiência em montagem manual ajuda (fiz muito isso, e ainda posso contar em hexadecimal para calcular as compensações).


3

Se o arquivo for para um PIC de 12 ou 14 bits, cada par de bytes será uma palavra de 12 ou 14 bits, normalmente armazenada primeiro em LSB, com os dois ou quatro bits mais significativos limpos.


1

Se fosse compilado a partir de uma linguagem como C ou Pascal, haveria certas sequências padrão de binárias que você poderia procurar. Com C, por exemplo, quase todas as funções começam com algo que salva o ponteiro da pilha em um ponteiro "frame" ou "link". Para qualquer processador, geralmente existem apenas algumas maneiras de fazer isso. Então você pode responder "este código para o processador X" procurando o binário de X para essas seqüências.

Dito isto, tive alguma sorte em diferenciar entre os binários 8088, 6502 e 68000 usando apenas histogramas. Qualquer processador possui certos códigos de instruções legais, e estes tendem a ser usados ​​um pouco mais frequentemente que a média. Com um pedaço grande o suficiente de binário, você pode começar a ver certas tendências. Isso é dificultado, no entanto, pelo fato de que todos os operandos em uma determinada parte do binário tendem a não se correlacionar com o tipo de processador especificado, e isso basicamente apenas produz ruído nos dados do histograma. Além disso, até dois programas diferentes para o mesmo processador podem ter histogramas visivelmente diferentes. Ainda assim, pode dar-lhe um lugar para começar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.